Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
# SOFTWARE.
import struct

from . import CPyExtTestCase, CPyExtFunction, CPyExtFunctionOutVars, unhandled_error_compare
from . import CPyExtTestCase, CPyExtFunction, CPyExtFunctionOutVars, CPyExtType, unhandled_error_compare

int_bits = struct.calcsize('i') * 8
max_int = 2 ** (int_bits - 1) - 1
Expand Down Expand Up @@ -195,6 +195,28 @@ def _int_examples():

class TestPyLong(CPyExtTestCase):

def test_native_long_subtype_has_native_layout(self):
NativeLongWithMember = CPyExtType(
"NativeLongWithMember",
"""
static void NativeLongWithMember_dealloc(NativeLongWithMemberObject *self) {
Py_XDECREF(self->member);
Py_TYPE(self)->tp_free((PyObject *)self);
}
""",
ready_code="NativeLongWithMemberType.tp_new = PyLong_Type.tp_new;",
tp_base="&PyLong_Type",
struct_base="PyLongObject base;",
cmembers="PyObject *member;",
tp_dealloc="(destructor)NativeLongWithMember_dealloc",
tp_members='{"member", T_OBJECT_EX, offsetof(NativeLongWithMemberObject, member), 0, NULL}',
)

obj = NativeLongWithMember(10)
assert obj == 10
obj.member = "foo"
assert obj.member == "foo"

test_PyLong_AsLong = CPyExtFunction(
_reference_as_long,
_int_examples,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@
import com.oracle.graal.python.builtins.objects.cext.structs.CStructs;
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
import com.oracle.graal.python.builtins.objects.complex.PComplex;
import com.oracle.graal.python.builtins.objects.dict.PDict;
import com.oracle.graal.python.builtins.objects.floats.PFloat;
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
import com.oracle.graal.python.builtins.objects.function.PKeyword;
Expand Down Expand Up @@ -271,33 +270,25 @@ static Object doGeneric(Node inliningTarget, Object object, Object arg,
}
}

@GenerateInline(true)
@GenerateCached(false)
@GenerateUncached(false)
public abstract static class DictSubtypeNew extends Node {
public abstract PDict execute(Node node, Object cls, PDict managedSide);

@Specialization
static PDict allocateNativePart(Object cls, PDict managedSide,
@Bind Node inliningTarget,
@Cached PythonToNativeNode toNative) {
assert !managedSide.isNative();
assert EnsurePythonObjectNode.doesNotNeedPromotion(cls);
long clsPointer = toNative.executeLong(cls);
long nativeObject;
try {
nativeObject = ExternalFunctionInvoker.invokePY_TYPE_GENERIC_NEW_RAW(CApiContext.getNativeSymbol(inliningTarget, NativeCAPISymbol.FUN_PY_TYPE_GENERIC_NEW_RAW).getAddress(),
clsPointer, 0L, 0L);
} catch (Throwable t) {
throw CompilerDirectives.shouldNotReachHere(t);
} finally {
Reference.reachabilityFence(cls);
}
CApiTransitions.writeNativeRefCount(nativeObject, MANAGED_REFCNT);
CApiTransitions.createReference(managedSide, nativeObject);
assert managedSide.isNative();
return managedSide;
}
public static <T extends PythonObject> T allocateNativePart(Node inliningTarget, Object cls, T managedSide) {
assert !managedSide.isNative();
assert EnsurePythonObjectNode.doesNotNeedPromotion(cls);
long nativeObject;
try {
nativeObject = ExternalFunctionInvoker.invokePY_TYPE_GENERIC_NEW_RAW(CApiContext.getNativeSymbol(inliningTarget, NativeCAPISymbol.FUN_PY_TYPE_GENERIC_NEW_RAW).getAddress(),
PythonToNativeNode.executeLongUncached(cls), 0L, 0L);
} catch (Throwable t) {
throw CompilerDirectives.shouldNotReachHere(t);
} finally {
Reference.reachabilityFence(cls);
}
PythonContext context = PythonContext.get(inliningTarget);
TransformExceptionFromNativeNode.executeUncached(context.getThreadState(context.getLanguage()), NativeCAPISymbol.FUN_PY_TYPE_GENERIC_NEW_RAW.getTsName(), nativeObject == NULLPTR,
true);
CApiTransitions.writeNativeRefCount(nativeObject, MANAGED_REFCNT);
CApiTransitions.createReference(managedSide, nativeObject);
assert managedSide.isNative();
return managedSide;
}

// -----------------------------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2025, Oracle and/or its affiliates.
* Copyright (c) 2017, 2026, Oracle and/or its affiliates.
* Copyright (c) 2013, Regents of the University of California
*
* All rights reserved.
Expand Down Expand Up @@ -157,7 +157,6 @@ static Object dict(Object cls, Object[] args, PKeyword[] keywordArgs,
@Bind Node inliningTarget,
@Cached InlinedConditionProfile orderedProfile,
@Cached TypeNodes.NeedsNativeAllocationNode needsNativeAllocationNode,
@Cached CExtNodes.DictSubtypeNew subtypeNew,
@Cached IsSubtypeNode isSubtypeNode,
@Cached TypeNodes.GetInstanceShape getInstanceShape) {
Shape shape = getInstanceShape.execute(cls);
Expand All @@ -166,7 +165,7 @@ static Object dict(Object cls, Object[] args, PKeyword[] keywordArgs,
}
PDict newDict = PFactory.createDict(cls, shape, EmptyStorage.INSTANCE);
if (needsNativeAllocationNode.execute(inliningTarget, cls)) {
return subtypeNew.execute(inliningTarget, cls, newDict);
return CExtNodes.allocateNativePart(inliningTarget, cls, newDict);
} else {
return newDict;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
import com.oracle.graal.python.builtins.objects.bytes.BytesNodes.BytesFromObject;
import com.oracle.graal.python.builtins.objects.bytes.PBytes;
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes;
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.FromNativeSubclassNode;
import com.oracle.graal.python.builtins.objects.common.FormatNodeBase;
import com.oracle.graal.python.builtins.objects.floats.PFloat;
Expand Down Expand Up @@ -167,6 +168,7 @@
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.profiles.InlinedBranchProfile;
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
import com.oracle.truffle.api.profiles.InlinedIntValueProfile;
Expand Down Expand Up @@ -207,42 +209,47 @@ static Object doGeneric(VirtualFrame frame, Object cls, Object x, Object baseObj
@Bind Node inliningTarget,
@Cached IntNodeInnerNode innerNode,
@Cached IsBuiltinClassExactProfile isPrimitiveIntProfile,
@Cached TypeNodes.NeedsNativeAllocationNode needsNativeAllocationNode,
@Cached TypeNodes.GetInstanceShape getInstanceShape,
@Cached CreateIntSubclassNode createIntSubclassNode) {
Object result = innerNode.execute(frame, inliningTarget, x, baseObj);
if (isPrimitiveIntProfile.profileClass(inliningTarget, cls, PythonBuiltinClassType.PInt)) {
return result;
} else {
return createIntSubclassNode.execute(inliningTarget, cls, result);
assert IsSubtypeNode.getUncached().execute(cls, PythonBuiltinClassType.PInt);
PInt managedInt = createIntSubclassNode.execute(inliningTarget, cls, result, getInstanceShape.execute(cls));
if (needsNativeAllocationNode.execute(inliningTarget, cls)) {
// needsNativeAllocationNode acts as branch profile
return CExtNodes.allocateNativePart(inliningTarget, cls, managedInt);
} else {
return managedInt;
}
}
}

@GenerateInline
@GenerateCached(false)
abstract static class CreateIntSubclassNode extends Node {
public abstract Object execute(Node inliningTarget, Object cls, Object intObj);
public abstract PInt execute(Node inliningTarget, Object cls, Object intObj, Shape shape);

@Specialization
static Object doSubclass(Object cls, int value,
@Shared @Cached TypeNodes.GetInstanceShape getInstanceShape) {
return PFactory.createInt(cls, getInstanceShape.execute(cls), value);
static PInt doManagedSubclass(Object cls, int value, Shape shape) {
return PFactory.createInt(cls, shape, value);
}

@Specialization
static Object doSubclass(Object cls, long value,
@Shared @Cached TypeNodes.GetInstanceShape getInstanceShape) {
return PFactory.createInt(cls, getInstanceShape.execute(cls), value);
static PInt doManagedSubclass(Object cls, long value, Shape shape) {
return PFactory.createInt(cls, shape, value);
}

@Specialization
static Object doSubclass(Object cls, boolean value,
@Shared @Cached TypeNodes.GetInstanceShape getInstanceShape) {
return PFactory.createInt(cls, getInstanceShape.execute(cls), PInt.intValue(value));
static PInt doManagedSubclass(Object cls, boolean value, Shape shape) {
return PFactory.createInt(cls, shape, PInt.intValue(value));
}

@Specialization
static Object doSubclass(Object cls, PInt value,
@Shared @Cached TypeNodes.GetInstanceShape getInstanceShape) {
return PFactory.createInt(cls, getInstanceShape.execute(cls), value.getValue());
static PInt doManagedSubclass(Object cls, PInt value, Shape shape) {
return PFactory.createInt(cls, shape, value.getValue());
}
}

Expand Down
Loading