4141package com .oracle .graal .python .builtins .objects .cext .capi .transitions ;
4242
4343import static com .oracle .graal .python .builtins .objects .cext .capi .PythonNativeWrapper .PythonAbstractObjectNativeWrapper .IMMORTAL_REFCNT ;
44+ import static com .oracle .graal .python .builtins .objects .cext .capi .PythonNativeWrapper .PythonAbstractObjectNativeWrapper .MANAGED_REFCNT ;
4445
4546import java .lang .ref .ReferenceQueue ;
4647import java .lang .ref .WeakReference ;
8283import com .oracle .graal .python .builtins .objects .cext .structs .CStructAccess .AllocateNode ;
8384import com .oracle .graal .python .builtins .objects .cext .structs .CStructAccess .FreeNode ;
8485import com .oracle .graal .python .builtins .objects .cext .structs .CStructs ;
86+ import com .oracle .graal .python .builtins .objects .floats .PFloat ;
8587import com .oracle .graal .python .builtins .objects .getsetdescriptor .DescriptorDeleteMarker ;
8688import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
8789import com .oracle .graal .python .nodes .PGuards ;
102104import com .oracle .truffle .api .dsl .Bind ;
103105import com .oracle .truffle .api .dsl .Cached ;
104106import com .oracle .truffle .api .dsl .Cached .Exclusive ;
107+ import com .oracle .truffle .api .dsl .Cached .Shared ;
105108import com .oracle .truffle .api .dsl .GenerateCached ;
106109import com .oracle .truffle .api .dsl .GenerateInline ;
107110import com .oracle .truffle .api .dsl .GenerateUncached ;
@@ -390,7 +393,7 @@ public static void pollReferenceQueue() {
390393 * free'd at context finalization.
391394 */
392395 long stubPointer = HandlePointerConverter .pointerToStub (reference .pointer );
393- if (subNativeRefCount (stubPointer , PythonAbstractObjectNativeWrapper . MANAGED_REFCNT ) == 0 ) {
396+ if (subNativeRefCount (stubPointer , MANAGED_REFCNT ) == 0 ) {
394397 freeNativeStub (stubPointer );
395398 } else {
396399 /*
@@ -429,7 +432,7 @@ public static void pollReferenceQueue() {
429432 */
430433 private static void processNativeObjectReference (NativeObjectReference reference , NativeObjectReferenceArrayWrapper referencesToBeFreed ) {
431434 LOGGER .fine (() -> PythonUtils .formatJString ("releasing %s" , reference .toString ()));
432- if (subNativeRefCount (reference .pointer , PythonAbstractObjectNativeWrapper . MANAGED_REFCNT ) == 0 ) {
435+ if (subNativeRefCount (reference .pointer , MANAGED_REFCNT ) == 0 ) {
433436 referencesToBeFreed .add (reference .pointer );
434437 }
435438 }
@@ -752,6 +755,7 @@ public static boolean pointsToPyHandleSpace(long pointer) {
752755 @ GenerateUncached
753756 @ GenerateInline
754757 @ GenerateCached (false )
758+ @ ImportStatic (CApiGuards .class )
755759 public abstract static class FirstToNativeNode extends Node {
756760
757761 public static long executeUncached (PythonAbstractObjectNativeWrapper wrapper , boolean immortal ) {
@@ -765,55 +769,127 @@ public final long execute(Node inliningTarget, PythonAbstractObjectNativeWrapper
765769 public abstract long execute (Node inliningTarget , PythonAbstractObjectNativeWrapper wrapper , boolean immortal );
766770
767771 @ Specialization
768- static long doGeneric (Node inliningTarget , PythonAbstractObjectNativeWrapper wrapper , boolean immortal ,
772+ static long doPrimitiveNativeWrapper (Node inliningTarget , PrimitiveNativeWrapper wrapper , boolean immortal ,
773+ @ Shared @ Cached (inline = false ) CStructAccess .WriteDoubleNode writeDoubleNode ,
774+ @ Shared @ Cached InlinedConditionProfile isFloatObjectProfile ,
775+ @ Shared @ Cached AllocateNativeObjectStubNode allocateNativeObjectStubNode ) {
776+ boolean isFloat = isFloatObjectProfile .profile (inliningTarget , wrapper .isDouble ());
777+ CStructs ctype = isFloat ? CStructs .GraalPyFloatObject : CStructs .GraalPyObject ;
778+ Object type ;
779+ if (wrapper .isBool ()) {
780+ type = PythonBuiltinClassType .Boolean ;
781+ } else if (wrapper .isIntLike ()) {
782+ type = PythonBuiltinClassType .PInt ;
783+ } else if (isFloat ) {
784+ type = PythonBuiltinClassType .PFloat ;
785+ } else {
786+ throw CompilerDirectives .shouldNotReachHere ();
787+ }
788+ long taggedPointer = allocateNativeObjectStubNode .execute (inliningTarget , wrapper , type , ctype , immortal );
789+
790+ // allocate a native stub object (C type: GraalPy*Object)
791+ if (isFloat ) {
792+ long realPointer = HandlePointerConverter .pointerToStub (taggedPointer );
793+ writeDoubleNode .write (realPointer , CFields .GraalPyFloatObject__ob_fval , wrapper .getDouble ());
794+ }
795+ return taggedPointer ;
796+ }
797+
798+ @ Specialization (guards = "!isPrimitiveNativeWrapper(wrapper)" )
799+ static long doOther (Node inliningTarget , PythonAbstractObjectNativeWrapper wrapper , boolean immortal ,
800+ @ Cached (inline = false ) CStructAccess .WriteLongNode writeLongNode ,
801+ @ Cached (inline = false ) CStructAccess .WritePointerNode writePointerNode ,
802+ @ Shared @ Cached (inline = false ) CStructAccess .WriteDoubleNode writeDoubleNode ,
803+ @ Exclusive @ Cached InlinedConditionProfile isVarObjectProfile ,
804+ @ Shared @ Cached InlinedConditionProfile isFloatObjectProfile ,
805+ @ Cached GetClassNode getClassNode ,
806+ @ Shared @ Cached AllocateNativeObjectStubNode allocateNativeObjectStubNode ) {
807+
808+ assert !(wrapper instanceof TruffleObjectNativeWrapper );
809+ assert !(wrapper instanceof PrimitiveNativeWrapper );
810+
811+ Object delegate = wrapper .getDelegate ();
812+ Object type = getClassNode .execute (inliningTarget , delegate );
813+
814+ CStructs ctype ;
815+ if (isVarObjectProfile .profile (inliningTarget , delegate instanceof PTuple )) {
816+ ctype = CStructs .GraalPyVarObject ;
817+ } else if (isFloatObjectProfile .profile (inliningTarget , delegate instanceof Double || delegate instanceof PFloat )) {
818+ ctype = CStructs .GraalPyFloatObject ;
819+ } else {
820+ ctype = CStructs .GraalPyObject ;
821+ }
822+
823+ long taggedPointer = allocateNativeObjectStubNode .execute (inliningTarget , wrapper , type , ctype , immortal );
824+
825+ // allocate a native stub object (C type: GraalPy*Object)
826+ if (ctype == CStructs .GraalPyVarObject ) {
827+ assert delegate instanceof PTuple ;
828+ SequenceStorage sequenceStorage = ((PTuple ) delegate ).getSequenceStorage ();
829+ long realPointer = HandlePointerConverter .pointerToStub (taggedPointer );
830+ writeLongNode .write (realPointer , CFields .GraalPyVarObject__ob_size , sequenceStorage .length ());
831+ Object obItemPtr = 0L ;
832+ if (sequenceStorage instanceof NativeSequenceStorage nativeSequenceStorage ) {
833+ obItemPtr = nativeSequenceStorage .getPtr ();
834+ }
835+ writePointerNode .write (realPointer , CFields .GraalPyVarObject__ob_item , obItemPtr );
836+ } else if (ctype == CStructs .GraalPyFloatObject ) {
837+ assert delegate instanceof Double || delegate instanceof PFloat ;
838+ long realPointer = HandlePointerConverter .pointerToStub (taggedPointer );
839+ double fval ;
840+ if (delegate instanceof Double d ) {
841+ fval = d ;
842+ } else {
843+ fval = ((PFloat ) delegate ).getValue ();
844+ }
845+ writeDoubleNode .write (realPointer , CFields .GraalPyFloatObject__ob_fval , fval );
846+ }
847+
848+ return taggedPointer ;
849+ }
850+ }
851+
852+ @ GenerateUncached
853+ @ GenerateInline
854+ @ GenerateCached (false )
855+ abstract static class AllocateNativeObjectStubNode extends Node {
856+
857+ abstract long execute (Node inliningTarget , PythonAbstractObjectNativeWrapper wrapper , Object type , CStructs ctype , boolean immortal );
858+
859+ @ Specialization
860+ static long doGeneric (Node inliningTarget , PythonAbstractObjectNativeWrapper wrapper , Object type , CStructs ctype , boolean immortal ,
769861 @ Cached (inline = false ) GilNode gil ,
770862 @ Cached (inline = false ) CStructAccess .AllocateNode allocateNode ,
771863 @ Cached (inline = false ) CStructAccess .WriteLongNode writeLongNode ,
772- @ Cached (inline = false ) CStructAccess .WritePointerNode writePointerNode ,
773864 @ Cached (inline = false ) CStructAccess .WriteObjectNewRefNode writeObjectNode ,
774865 @ Cached (inline = false ) CStructAccess .WriteIntNode writeIntNode ,
775- @ Cached InlinedConditionProfile isVarObjectProfile ,
776- @ Cached InlinedExactClassProfile wrapperProfile ,
777- @ Cached GetClassNode getClassNode ,
778866 @ Cached CoerceNativePointerToLongNode coerceToLongNode ) {
779867
868+ log (wrapper );
869+ pollReferenceQueue ();
870+
871+ long initialRefCount = immortal ? IMMORTAL_REFCNT : MANAGED_REFCNT ;
872+
873+ // allocate a native stub object (C type: GraalPy*Object)
874+ Object nativeObjectStub = allocateNode .alloc (ctype );
875+
876+ HandleContext handleContext = PythonContext .get (inliningTarget ).nativeContext ;
877+ long stubPointer = coerceToLongNode .execute (inliningTarget , nativeObjectStub );
878+ long taggedPointer = HandlePointerConverter .stubToPointer (stubPointer );
879+
880+ writeLongNode .write (stubPointer , CFields .PyObject__ob_refcnt , initialRefCount );
881+ writeObjectNode .write (stubPointer , CFields .PyObject__ob_type , type );
882+
883+ // TODO(fa): this should not require the GIL (GR-51314)
780884 boolean acquired = gil .acquire ();
781885 try {
782- log (wrapper );
783- assert !(wrapper instanceof TruffleObjectNativeWrapper );
784- pollReferenceQueue ();
785-
786- long initialRefCount = immortal ? IMMORTAL_REFCNT : PythonAbstractObjectNativeWrapper .MANAGED_REFCNT ;
787-
788- Object delegate = NativeToPythonNode .handleWrapper (inliningTarget , wrapperProfile , false , wrapper );
789- Object type = getClassNode .execute (inliningTarget , delegate );
790-
791- // allocate a native stub object (C type: PyObject)
792- boolean isTuple = isVarObjectProfile .profile (inliningTarget , delegate instanceof PTuple );
793- Object nativeObjectStub = allocateNode .alloc (isTuple ? CStructs .GraalPyVarObject : CStructs .GraalPyObject );
794- writeLongNode .write (nativeObjectStub , CFields .PyObject__ob_refcnt , initialRefCount );
795- writeObjectNode .write (nativeObjectStub , CFields .PyObject__ob_type , type );
796- if (isTuple ) {
797- SequenceStorage sequenceStorage = ((PTuple ) delegate ).getSequenceStorage ();
798- writeLongNode .write (nativeObjectStub , CFields .PyVarObject__ob_size , sequenceStorage .length ());
799- Object obItemPtr = 0L ;
800- if (sequenceStorage instanceof NativeSequenceStorage nativeSequenceStorage ) {
801- obItemPtr = nativeSequenceStorage .getPtr ();
802- }
803- writePointerNode .write (nativeObjectStub , CFields .GraalPyVarObject__ob_item , obItemPtr );
804- }
805- HandleContext handleContext = PythonContext .get (inliningTarget ).nativeContext ;
806- long stubPointer = coerceToLongNode .execute (inliningTarget , nativeObjectStub );
807- long taggedPointer = HandlePointerConverter .stubToPointer (stubPointer );
808886 int idx = nativeStubLookupReserve (handleContext );
809887 // We don't allow 'handleTableIndex == 0' to avoid that zeroed memory
810888 // accidentally maps to some valid object.
811889 assert idx > 0 ;
812890 writeIntNode .write (stubPointer , CFields .GraalPyObject__handle_table_index , idx );
813891 PythonObjectReference ref = PythonObjectReference .create (handleContext , wrapper , immortal , taggedPointer , idx );
814892 nativeStubLookupPut (handleContext , ref );
815-
816- return logResult (taggedPointer );
817893 } catch (OverflowException e ) {
818894 /*
819895 * The OverflowException may be thrown by 'nativeStubLookupReserve' and indicates
@@ -825,6 +901,7 @@ static long doGeneric(Node inliningTarget, PythonAbstractObjectNativeWrapper wra
825901 } finally {
826902 gil .release (acquired );
827903 }
904+ return logResult (taggedPointer );
828905 }
829906 }
830907
@@ -1283,7 +1360,7 @@ static Object handleWrapper(Node node, InlinedExactClassProfile wrapperProfile,
12831360 * *MUST* have done an incref and so the refcount must be greater than
12841361 * MANAGED_REFCNT.
12851362 */
1286- assert objectNativeWrapper .getRefCount () > PythonAbstractObjectNativeWrapper . MANAGED_REFCNT ;
1363+ assert objectNativeWrapper .getRefCount () > MANAGED_REFCNT ;
12871364 objectNativeWrapper .decRef ();
12881365 }
12891366 if (profiledWrapper instanceof PrimitiveNativeWrapper primitive ) {
@@ -1480,7 +1557,7 @@ private static Object createAbstractNativeObject(HandleContext handleContext, Ob
14801557 NativeObjectReference ref = new NativeObjectReference (handleContext , result , pointer );
14811558 nativeLookupPut (getContext (), pointer , ref );
14821559
1483- long refCntDelta = PythonAbstractObjectNativeWrapper . MANAGED_REFCNT - (transfer ? 1 : 0 );
1560+ long refCntDelta = MANAGED_REFCNT - (transfer ? 1 : 0 );
14841561 addNativeRefCount (pointer , refCntDelta );
14851562 return result ;
14861563 }
0 commit comments