72
72
import com .oracle .graal .python .builtins .objects .cext .capi .CExtNodesFactory .ReleaseNativeWrapperNodeGen ;
73
73
import com .oracle .graal .python .builtins .objects .cext .capi .ExternalFunctionNodesFactory .CreateArgsTupleNodeGen ;
74
74
import com .oracle .graal .python .builtins .objects .cext .capi .ExternalFunctionNodesFactory .DefaultCheckFunctionResultNodeGen ;
75
+ import com .oracle .graal .python .builtins .objects .cext .capi .ExternalFunctionNodesFactory .ExternalFunctionInvokeNodeGen ;
75
76
import com .oracle .graal .python .builtins .objects .cext .capi .ExternalFunctionNodesFactory .MaterializePrimitiveNodeGen ;
76
77
import com .oracle .graal .python .builtins .objects .cext .capi .ExternalFunctionNodesFactory .ReleaseNativeSequenceStorageNodeGen ;
77
78
import com .oracle .graal .python .builtins .objects .cext .capi .PythonNativeWrapper .PythonAbstractObjectNativeWrapper ;
143
144
import com .oracle .truffle .api .dsl .Cached .Exclusive ;
144
145
import com .oracle .truffle .api .dsl .Cached .Shared ;
145
146
import com .oracle .truffle .api .dsl .Fallback ;
147
+ import com .oracle .truffle .api .dsl .GenerateCached ;
146
148
import com .oracle .truffle .api .dsl .GenerateInline ;
147
149
import com .oracle .truffle .api .dsl .GenerateUncached ;
148
150
import com .oracle .truffle .api .dsl .ImportStatic ;
@@ -820,46 +822,29 @@ public static MethDirectRoot create(PythonLanguage lang, TruffleString name, PEx
820
822
* Like {@link com.oracle.graal.python.nodes.call.FunctionInvokeNode} but invokes a C function.
821
823
*/
822
824
@ GenerateUncached
823
- @ GenerateInline (false )
825
+ @ GenerateCached (false )
826
+ @ GenerateInline
824
827
public abstract static class ExternalFunctionInvokeNode extends PNodeWithContext {
825
- public abstract Object execute (VirtualFrame frame , PExternalFunctionWrapper provider , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments );
828
+ abstract Object execute (VirtualFrame frame , Node inliningTarget , PythonContext ctx , PythonThreadState threadState , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments );
826
829
827
- static CheckFunctionResultNode createCheckResultNode ( PExternalFunctionWrapper provider ) {
828
- CheckFunctionResultNode node = provider . createCheckFunctionResultNode ();
829
- return node != null ? node : DefaultCheckFunctionResultNodeGen . create ( );
830
+ public final Object call ( VirtualFrame frame , Node inliningTarget , PythonContext ctx , PythonThreadState threadState , CApiTiming timing , TruffleString name , Object callable ,
831
+ Object ... cArguments ) {
832
+ return execute ( frame , inliningTarget , ctx , threadState , timing , name , callable , cArguments );
830
833
}
831
834
832
- static CheckFunctionResultNode getUncachedCheckResultNode (PExternalFunctionWrapper provider ) {
833
- CheckFunctionResultNode node = provider .getUncachedCheckFunctionResultNode ();
834
- return node != null ? node : DefaultCheckFunctionResultNodeGen .getUncached ();
835
- }
836
-
837
- @ Specialization (guards = {"provider == cachedProvider" }, limit = "1" )
838
- static Object invoke (VirtualFrame frame , PExternalFunctionWrapper provider , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments ,
839
- @ Bind ("this" ) Node inliningTarget ,
840
- @ Cached ("provider" ) PExternalFunctionWrapper cachedProvider ,
841
- @ Cached (value = "createCheckResultNode(provider)" , uncached = "getUncachedCheckResultNode(provider)" ) CheckFunctionResultNode checkResultNode ,
842
- @ Cached (value = "provider.createConvertRetNode()" , uncached = "provider.getUncachedConvertRetNode()" ) CExtToJavaNode convertReturnValue ,
843
- @ Cached PForeignToPTypeNode fromForeign ,
844
- @ Cached GetThreadStateNode getThreadStateNode ,
845
- @ Cached GilNode gilNode ,
835
+ @ Specialization
836
+ static Object invoke (VirtualFrame frame , Node inliningTarget , PythonContext ctx , PythonThreadState threadState , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments ,
837
+ @ Cached (inline = false ) GilNode gilNode ,
846
838
@ Cached (value = "createFor(this)" , uncached = "getUncached()" ) IndirectCallData indirectCallData ,
847
839
@ CachedLibrary (limit = "2" ) InteropLibrary lib ) {
848
- PythonContext ctx = PythonContext .get (inliningTarget );
849
- PythonThreadState threadState = getThreadStateNode .execute (inliningTarget , ctx );
850
840
851
841
// If any code requested the caught exception (i.e. used 'sys.exc_info()'), we store
852
842
// it to the context since we cannot propagate it through the native frames.
853
843
Object state = IndirectCallContext .enter (frame , threadState , indirectCallData );
854
844
855
845
CApiTiming .enter ();
856
846
try {
857
- Object result = lib .execute (callable , cArguments );
858
- result = checkResultNode .execute (threadState , name , result );
859
- if (convertReturnValue != null ) {
860
- result = convertReturnValue .execute (result );
861
- }
862
- return fromForeign .executeConvert (result );
847
+ return lib .execute (callable , cArguments );
863
848
} catch (UnsupportedTypeException | UnsupportedMessageException e ) {
864
849
CompilerDirectives .transferToInterpreterAndInvalidate ();
865
850
throw PRaiseNode .raiseUncached (inliningTarget , TypeError , ErrorMessages .CALLING_NATIVE_FUNC_FAILED , name , e );
@@ -873,7 +858,7 @@ static Object invoke(VirtualFrame frame, PExternalFunctionWrapper provider, CApi
873
858
* extensions are releasing the GIL and if then an LLVM exception occurs, C code
874
859
* wouldn't re-acquire it (unexpectedly).
875
860
*/
876
- gilNode .acquire ();
861
+ gilNode .acquire (ctx );
877
862
878
863
/*
879
864
* Special case after calling a C function: transfer caught exception back to frame
@@ -885,14 +870,73 @@ static Object invoke(VirtualFrame frame, PExternalFunctionWrapper provider, CApi
885
870
IndirectCallContext .exit (frame , threadState , state );
886
871
}
887
872
}
873
+ }
874
+
875
+ /**
876
+ * Wraps {@link ExternalFunctionInvokeNode} with result checking and conversion according to the
877
+ * passed {@link PExternalFunctionWrapper}. This node assumes that the provider argument is in
878
+ * the cached case a PE constant.
879
+ */
880
+ @ GenerateInline (false )
881
+ public abstract static class ExternalFunctionWrapperInvokeNode extends PNodeWithContext {
882
+ public abstract Object execute (VirtualFrame frame , PExternalFunctionWrapper provider , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments );
883
+
884
+ @ NeverDefault
885
+ static CheckFunctionResultNode createCheckResultNode (PExternalFunctionWrapper provider ) {
886
+ CheckFunctionResultNode node = provider .createCheckFunctionResultNode ();
887
+ return node != null ? node : DefaultCheckFunctionResultNodeGen .create ();
888
+ }
889
+
890
+ static CheckFunctionResultNode getUncachedCheckResultNode (PExternalFunctionWrapper provider ) {
891
+ CheckFunctionResultNode node = provider .getUncachedCheckFunctionResultNode ();
892
+ return node != null ? node : DefaultCheckFunctionResultNodeGen .getUncached ();
893
+ }
894
+
895
+ @ Specialization
896
+ static Object invokeCached (VirtualFrame frame , PExternalFunctionWrapper provider , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments ,
897
+ @ Bind ("this" ) Node inliningTarget ,
898
+ @ Cached ("createCheckResultNode(provider)" ) CheckFunctionResultNode checkResultNode ,
899
+ @ SuppressWarnings ("truffle-neverdefault" ) @ Cached ("provider.createConvertRetNode()" ) CExtToJavaNode convertReturnValue ,
900
+ @ Cached PForeignToPTypeNode fromForeign ,
901
+ @ Cached GetThreadStateNode getThreadStateNode ,
902
+ @ Cached ExternalFunctionInvokeNode invokeNode ) {
903
+ CompilerAsserts .partialEvaluationConstant (provider );
904
+ PythonContext ctx = PythonContext .get (inliningTarget );
905
+ return invoke (frame , ctx , timing , name , callable , cArguments , inliningTarget , checkResultNode , convertReturnValue , fromForeign , getThreadStateNode , invokeNode );
906
+ }
907
+
908
+ private static Object invoke (VirtualFrame frame , PythonContext ctx , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments , Node inliningTarget ,
909
+ CheckFunctionResultNode checkResultNode , CExtToJavaNode convertReturnValue , PForeignToPTypeNode fromForeign , GetThreadStateNode getThreadStateNode ,
910
+ ExternalFunctionInvokeNode invokeNode ) {
911
+ PythonThreadState threadState = getThreadStateNode .execute (inliningTarget , ctx );
912
+ Object result = invokeNode .execute (frame , inliningTarget , ctx , threadState , timing , name , callable , cArguments );
913
+ result = checkResultNode .execute (threadState , name , result );
914
+ if (convertReturnValue != null ) {
915
+ result = convertReturnValue .execute (result );
916
+ }
917
+ return fromForeign .executeConvert (result );
918
+ }
919
+
920
+ @ GenerateCached (false )
921
+ private static final class ExternalFunctionWrapperInvokeNodeUncached extends ExternalFunctionWrapperInvokeNode {
922
+ private static final ExternalFunctionWrapperInvokeNodeUncached INSTANCE = new ExternalFunctionWrapperInvokeNodeUncached ();
923
+
924
+ @ Override
925
+ public Object execute (VirtualFrame frame , PExternalFunctionWrapper provider , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments ) {
926
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
927
+ PythonContext ctx = PythonContext .get (null );
928
+ return invoke (frame , ctx , timing , name , callable , cArguments , null , getUncachedCheckResultNode (provider ), provider .getUncachedConvertRetNode (), PForeignToPTypeNode .getUncached (),
929
+ GetThreadStateNode .getUncached (), ExternalFunctionInvokeNodeGen .getUncached ());
930
+ }
931
+ }
888
932
889
933
@ NeverDefault
890
- public static ExternalFunctionInvokeNode create () {
891
- return ExternalFunctionNodesFactory .ExternalFunctionInvokeNodeGen .create ();
934
+ public static ExternalFunctionWrapperInvokeNode create () {
935
+ return ExternalFunctionNodesFactory .ExternalFunctionWrapperInvokeNodeGen .create ();
892
936
}
893
937
894
- public static ExternalFunctionInvokeNode getUncached () {
895
- return ExternalFunctionNodesFactory . ExternalFunctionInvokeNodeGen . getUncached () ;
938
+ public static ExternalFunctionWrapperInvokeNode getUncached () {
939
+ return ExternalFunctionWrapperInvokeNodeUncached . INSTANCE ;
896
940
}
897
941
}
898
942
@@ -901,7 +945,7 @@ abstract static class MethodDescriptorRoot extends PRootNode {
901
945
private final CApiTiming timing ;
902
946
@ Child private CalleeContext calleeContext = CalleeContext .create ();
903
947
@ Child private CallVarargsMethodNode invokeNode ;
904
- @ Child private ExternalFunctionInvokeNode externalInvokeNode ;
948
+ @ Child private ExternalFunctionWrapperInvokeNode externalInvokeNode ;
905
949
@ Child private ReadIndexedArgumentNode readSelfNode ;
906
950
@ Child private ReadIndexedArgumentNode readCallableNode ;
907
951
@ Child private ReleaseNativeWrapperNode releaseNativeWrapperNode ;
@@ -920,7 +964,7 @@ abstract static class MethodDescriptorRoot extends PRootNode {
920
964
this .timing = CApiTiming .create (true , name );
921
965
this .provider = provider ;
922
966
if (provider != null ) {
923
- this .externalInvokeNode = ExternalFunctionInvokeNode .create ();
967
+ this .externalInvokeNode = ExternalFunctionWrapperInvokeNode .create ();
924
968
this .convertArgs = provider .createConvertArgNodes ();
925
969
} else {
926
970
this .invokeNode = CallVarargsMethodNode .create ();
0 commit comments