4545import com .oracle .graal .python .builtins .modules .ExternalFunctionNodesFactory .CreateArgsTupleNodeGen ;
4646import com .oracle .graal .python .builtins .modules .ExternalFunctionNodesFactory .MaterializePrimitiveNodeGen ;
4747import com .oracle .graal .python .builtins .modules .ExternalFunctionNodesFactory .ReleaseNativeWrapperNodeGen ;
48- import com .oracle .graal .python .builtins .modules .ExternalFunctionNodesFactory .TraverseNativeWrapperNodeGen ;
4948import com .oracle .graal .python .builtins .modules .PythonCextBuiltins .CheckFunctionResultNode ;
5049import com .oracle .graal .python .builtins .objects .PNone ;
51- import com .oracle .graal .python .builtins .objects .PythonAbstractObject ;
5250import com .oracle .graal .python .builtins .objects .cext .CApiGuards ;
5351import com .oracle .graal .python .builtins .objects .cext .CExtNodes ;
5452import com .oracle .graal .python .builtins .objects .cext .CExtNodes .ConvertArgsToSulongNode ;
5553import com .oracle .graal .python .builtins .objects .cext .CExtNodes .SubRefCntNode ;
5654import com .oracle .graal .python .builtins .objects .cext .CExtNodes .ToJavaStealingNode ;
5755import com .oracle .graal .python .builtins .objects .cext .CExtNodes .ToNewRefNode ;
5856import com .oracle .graal .python .builtins .objects .cext .CExtNodesFactory .ToJavaStealingNodeGen ;
59- import com .oracle .graal .python .builtins .objects .cext .common .CExtCommonNodes .ConvertPIntToPrimitiveNode ;
60- import com .oracle .graal .python .builtins .objects .cext .common .CExtCommonNodesFactory .ConvertPIntToPrimitiveNodeGen ;
6157import com .oracle .graal .python .builtins .objects .cext .CExtNodesFactory .ToNewRefNodeGen ;
6258import com .oracle .graal .python .builtins .objects .cext .DynamicObjectNativeWrapper ;
6359import com .oracle .graal .python .builtins .objects .cext .PythonNativeWrapper ;
64- import com .oracle .graal .python .builtins .objects .cext .PythonNativeWrapperLibrary ;
65- import com .oracle .graal .python .builtins .objects .common .SequenceStorageNodes . GetElementType ;
60+ import com .oracle .graal .python .builtins .objects .cext .common . CExtCommonNodes . ConvertPIntToPrimitiveNode ;
61+ import com .oracle .graal .python .builtins .objects .cext . common .CExtCommonNodesFactory . ConvertPIntToPrimitiveNodeGen ;
6662import com .oracle .graal .python .builtins .objects .common .SequenceStorageNodes .ToArrayNode ;
6763import com .oracle .graal .python .builtins .objects .floats .PFloat ;
6864import com .oracle .graal .python .builtins .objects .function .PArguments ;
6965import com .oracle .graal .python .builtins .objects .function .PKeyword ;
7066import com .oracle .graal .python .builtins .objects .function .Signature ;
7167import com .oracle .graal .python .builtins .objects .ints .PInt ;
68+ import com .oracle .graal .python .builtins .objects .object .PythonObject ;
7269import com .oracle .graal .python .builtins .objects .str .PString ;
7370import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
7471import com .oracle .graal .python .nodes .ErrorMessages ;
8885import com .oracle .graal .python .runtime .ExecutionContext .ForeignCallContext ;
8986import com .oracle .graal .python .runtime .PythonContext ;
9087import com .oracle .graal .python .runtime .object .PythonObjectFactory ;
91- import com .oracle .graal .python .runtime .sequence .storage .SequenceStorage ;
92- import com .oracle .graal .python .runtime .sequence .storage .SequenceStorage .ListStorageType ;
9388import com .oracle .graal .python .util .PythonUtils ;
9489import com .oracle .truffle .api .Assumption ;
9590import com .oracle .truffle .api .CompilerDirectives ;
107102import com .oracle .truffle .api .interop .InteropLibrary ;
108103import com .oracle .truffle .api .interop .UnsupportedMessageException ;
109104import com .oracle .truffle .api .interop .UnsupportedTypeException ;
110- import com .oracle .truffle .api .library .CachedLibrary ;
111105import com .oracle .truffle .api .nodes .ExplodeLoop ;
112106import com .oracle .truffle .api .nodes .ExplodeLoop .LoopExplosionKind ;
113107import com .oracle .truffle .api .nodes .Node ;
114108import com .oracle .truffle .api .nodes .NodeCost ;
115109import com .oracle .truffle .api .nodes .UnexpectedResultException ;
116110import com .oracle .truffle .api .profiles .ConditionProfile ;
117- import com .oracle .truffle .api .profiles .ValueProfile ;
118111
119112public abstract class ExternalFunctionNodes {
120113
@@ -204,7 +197,6 @@ static final class ExternalFunctionInvokeNode extends PNodeWithContext implement
204197 @ Child private ToJavaStealingNode asPythonObjectNode = ToJavaStealingNodeGen .create ();
205198 @ Child private InteropLibrary lib ;
206199 @ Child private PRaiseNode raiseNode ;
207- @ Child private ReleaseNativeWrapperNode releaseNativeWrapperNode ;
208200
209201 @ CompilationFinal private Assumption nativeCodeDoesntNeedExceptionState = Truffle .getRuntime ().createAssumption ();
210202 @ CompilationFinal private Assumption nativeCodeDoesntNeedMyFrame = Truffle .getRuntime ().createAssumption ();
@@ -264,8 +256,6 @@ public Object execute(VirtualFrame frame, String name, Object callable, Object[]
264256 // to simulate the global state semantics
265257 PArguments .setException (frame , ctx .getCaughtException ());
266258 ForeignCallContext .exit (frame , ctx , state );
267-
268- ensureReleaseNativeWrapperNode ().execute (cArguments );
269259 }
270260 }
271261
@@ -281,14 +271,6 @@ private PRaiseNode ensureRaiseNode() {
281271 return raiseNode ;
282272 }
283273
284- private ReleaseNativeWrapperNode ensureReleaseNativeWrapperNode () {
285- if (releaseNativeWrapperNode == null ) {
286- CompilerDirectives .transferToInterpreterAndInvalidate ();
287- releaseNativeWrapperNode = insert (ReleaseNativeWrapperNodeGen .create ());
288- }
289- return releaseNativeWrapperNode ;
290- }
291-
292274 private PythonContext getContext () {
293275 if (contextRef == null ) {
294276 CompilerDirectives .transferToInterpreterAndInvalidate ();
@@ -321,57 +303,21 @@ public static ExternalFunctionInvokeNode create(ConvertArgsToSulongNode convertA
321303 */
322304 abstract static class ReleaseNativeWrapperNode extends Node {
323305
324- public abstract void execute (Object [] nativeArguments );
306+ public abstract void execute (Object pythonObject , PythonNativeWrapper nativeWrapper );
325307
326- @ Specialization (guards = {"nativeArguments.length == cachedLength" , "nativeArguments.length < 8" }, limit = "1" )
327- @ ExplodeLoop
328- static void doCachedLength (Object [] nativeArguments ,
329- @ Cached ("nativeArguments.length" ) int cachedLength ,
330- @ Cached (value = "createClassProfiles(cachedLength)" , dimensions = 1 ) ValueProfile [] classProfiles ,
331- @ CachedLibrary (limit = "nativeArguments.length" ) PythonNativeWrapperLibrary lib ,
332- @ Cached ("createTraverseNodes(cachedLength)" ) TraverseNativeWrapperNode [] traverseNativeWrapperNodes ,
333- @ Cached SubRefCntNode subRefCntNode ) {
334-
335- for (int i = 0 ; i < cachedLength ; i ++) {
336- doCheck (classProfiles [i ].profile (nativeArguments [i ]), subRefCntNode , lib , traverseNativeWrapperNodes [i ]);
337- }
338- }
339-
340- @ Specialization (replaces = "doCachedLength" )
341- static void doGeneric (Object [] nativeArguments ,
342- @ Cached ("createClassProfile()" ) ValueProfile classProfile ,
343- @ CachedLibrary (limit = "3" ) PythonNativeWrapperLibrary lib ,
308+ @ Specialization
309+ static void doPythonObjectWithWrapper (PythonObject pythonObject , PythonNativeWrapper nativeWrapper ,
344310 @ Cached TraverseNativeWrapperNode traverseNativeWrapperNode ,
345- @ Cached SubRefCntNode freeNode ) {
346-
347- for (int i = 0 ; i < nativeArguments .length ; i ++) {
348- doCheck (classProfile .profile (nativeArguments [i ]), freeNode , lib , traverseNativeWrapperNode );
349- }
350- }
351-
352- private static void doCheck (Object argument , SubRefCntNode refCntNode , PythonNativeWrapperLibrary lib , TraverseNativeWrapperNode traverseNativeWrapperNode ) {
353- if (CApiGuards .isNativeWrapper (argument )) {
354- // in the cached case, refCntNode acts as a branch profile
355- if (refCntNode .dec (argument ) == 0 ) {
356- traverseNativeWrapperNode .execute (lib .getDelegate ((PythonNativeWrapper ) argument ));
357- }
358- }
359- }
311+ @ Cached SubRefCntNode subRefCntNode ) {
360312
361- static ValueProfile [] createClassProfiles (int length ) {
362- ValueProfile [] classProfiles = new ValueProfile [length ];
363- for (int i = 0 ; i < classProfiles .length ; i ++) {
364- classProfiles [i ] = ValueProfile .createClassProfile ();
313+ // in the cached case, refCntNode acts as a branch profile
314+ if (subRefCntNode .dec (nativeWrapper ) == 0 ) {
315+ traverseNativeWrapperNode .execute (pythonObject );
365316 }
366- return classProfiles ;
367317 }
368318
369- static TraverseNativeWrapperNode [] createTraverseNodes (int length ) {
370- TraverseNativeWrapperNode [] nodes = new TraverseNativeWrapperNode [length ];
371- for (int i = 0 ; i < nodes .length ; i ++) {
372- nodes [i ] = TraverseNativeWrapperNodeGen .create ();
373- }
374- return nodes ;
319+ static boolean hasNativeWrapper (PythonObject object ) {
320+ return CApiGuards .isNativeWrapper (object .getNativeWrapper ());
375321 }
376322 }
377323
@@ -385,34 +331,26 @@ abstract static class TraverseNativeWrapperNode extends Node {
385331
386332 @ Specialization
387333 static void doTuple (PTuple tuple ,
388- @ Cached GetElementType getElementTypeNode ,
389334 @ Cached ToArrayNode toArrayNode ,
390- @ Cached ReleaseNativeWrapperNode releaseNativeWrapperNode ) {
391-
392- SequenceStorage sequenceStorage = tuple .getSequenceStorage ();
393- ListStorageType storageType = getElementTypeNode .execute (sequenceStorage );
394- if (storageType == ListStorageType .Generic || storageType == ListStorageType .List || storageType == ListStorageType .Tuple ) {
395- Object [] values = toArrayNode .execute (sequenceStorage );
396- Object [] wrappers = new Object [values .length ];
397- for (int i = 0 ; i < values .length ; i ++) {
398- Object value = values [i ];
399- if (value instanceof PythonAbstractObject ) {
400- DynamicObjectNativeWrapper nativeWrapper = ((PythonAbstractObject ) value ).getNativeWrapper ();
401- // only traverse if refCnt != 0; this will break the cycle
402- if (nativeWrapper != null ) {
403- wrappers [i ] = nativeWrapper .getRefCount () != 0 ? nativeWrapper : null ;
404- }
335+ @ Cached SubRefCntNode subRefCntNode ) {
336+
337+ Object [] values = toArrayNode .execute (tuple .getSequenceStorage ());
338+ for (int i = 0 ; i < values .length ; i ++) {
339+ Object value = values [i ];
340+ if (value instanceof PythonObject ) {
341+ DynamicObjectNativeWrapper nativeWrapper = ((PythonObject ) value ).getNativeWrapper ();
342+ // only traverse if refCnt != 0; this will break the cycle
343+ if (nativeWrapper != null ) {
344+ subRefCntNode .dec (nativeWrapper );
405345 }
406346 }
407- releaseNativeWrapperNode .execute (wrappers );
408347 }
409348 }
410349
411350 @ Fallback
412351 static void doOther (@ SuppressWarnings ("unused" ) Object other ) {
413352 // do nothing
414353 }
415-
416354 }
417355
418356 abstract static class MethodDescriptorRoot extends PRootNode {
@@ -447,7 +385,12 @@ public Object execute(VirtualFrame frame) {
447385 CalleeContext .enter (frame , customLocalsProfile );
448386 try {
449387 if (externalInvokeNode != null ) {
450- return externalInvokeNode .execute (frame , name , callable , prepareCArguments (frame ), 0 );
388+ Object [] cArguments = prepareCArguments (frame );
389+ try {
390+ return externalInvokeNode .execute (frame , name , callable , cArguments , 0 );
391+ } finally {
392+ postprocessCArguments (frame , cArguments );
393+ }
451394 } else {
452395 assert externalInvokeNode == null ;
453396 return invokeNode .execute (frame , callable , preparePArguments (frame ), PArguments .getKeywordArguments (frame ));
@@ -459,6 +402,10 @@ public Object execute(VirtualFrame frame) {
459402
460403 protected abstract Object [] prepareCArguments (VirtualFrame frame );
461404
405+ protected void postprocessCArguments (VirtualFrame frame , Object [] cArguments ) {
406+ // default: do nothing
407+ }
408+
462409 protected Object [] preparePArguments (VirtualFrame frame ) {
463410 Object [] variableArguments = PArguments .getVariableArguments (frame );
464411
@@ -522,6 +469,7 @@ public static final class MethKeywordsRoot extends MethodDescriptorRoot {
522469 @ Child private ReadVarArgsNode readVarargsNode ;
523470 @ Child private ReadVarKeywordsNode readKwargsNode ;
524471 @ Child private CreateArgsTupleNode createArgsTupleNode ;
472+ @ Child private ReleaseNativeWrapperNode releaseNativeWrapperNode ;
525473
526474 public MethKeywordsRoot (PythonLanguage language , String name , Object callable ) {
527475 super (language , name , callable );
@@ -543,17 +491,31 @@ protected Object[] prepareCArguments(VirtualFrame frame) {
543491 return new Object []{self , createArgsTupleNode .execute (factory , args ), factory .createDict (kwargs )};
544492 }
545493
494+ protected void postprocessCArguments (VirtualFrame frame , Object [] cArguments ) {
495+ PTuple varargsTuple = (PTuple ) cArguments [1 ];
496+ ensureReleaseNativeWrapperNode ().execute (varargsTuple , varargsTuple .getNativeWrapper ());
497+ }
498+
546499 @ Override
547500 public Signature getSignature () {
548501 return SIGNATURE ;
549502 }
503+
504+ private ReleaseNativeWrapperNode ensureReleaseNativeWrapperNode () {
505+ if (releaseNativeWrapperNode == null ) {
506+ CompilerDirectives .transferToInterpreterAndInvalidate ();
507+ releaseNativeWrapperNode = insert (ReleaseNativeWrapperNodeGen .create ());
508+ }
509+ return releaseNativeWrapperNode ;
510+ }
550511 }
551512
552513 public static final class MethVarargsRoot extends MethodDescriptorRoot {
553514 private static final Signature SIGNATURE = new Signature (-1 , false , 1 , false , new String []{"self" }, new String [0 ]);
554515 @ Child private PythonObjectFactory factory ;
555516 @ Child private ReadVarArgsNode readVarargsNode ;
556517 @ Child private CreateArgsTupleNode createArgsTupleNode ;
518+ @ Child private ReleaseNativeWrapperNode releaseNativeWrapperNode ;
557519
558520 public MethVarargsRoot (PythonLanguage language , String name , Object callable ) {
559521 super (language , name , callable );
@@ -573,10 +535,23 @@ protected Object[] prepareCArguments(VirtualFrame frame) {
573535 return new Object []{self , createArgsTupleNode .execute (factory , args )};
574536 }
575537
538+ protected void postprocessCArguments (VirtualFrame frame , Object [] cArguments ) {
539+ PTuple varargsTuple = (PTuple ) cArguments [1 ];
540+ ensureReleaseNativeWrapperNode ().execute (varargsTuple , varargsTuple .getNativeWrapper ());
541+ }
542+
576543 @ Override
577544 public Signature getSignature () {
578545 return SIGNATURE ;
579546 }
547+
548+ private ReleaseNativeWrapperNode ensureReleaseNativeWrapperNode () {
549+ if (releaseNativeWrapperNode == null ) {
550+ CompilerDirectives .transferToInterpreterAndInvalidate ();
551+ releaseNativeWrapperNode = insert (ReleaseNativeWrapperNodeGen .create ());
552+ }
553+ return releaseNativeWrapperNode ;
554+ }
580555 }
581556
582557 public static final class MethNoargsRoot extends MethodDescriptorRoot {
0 commit comments