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 ;
@@ -830,61 +832,46 @@ public static MethDirectRoot create(PythonLanguage lang, TruffleString name, PEx
830
832
* Like {@link com.oracle.graal.python.nodes.call.FunctionInvokeNode} but invokes a C function.
831
833
*/
832
834
@ GenerateUncached
833
- @ GenerateInline (false )
835
+ @ GenerateCached (false )
836
+ @ GenerateInline
834
837
public abstract static class ExternalFunctionInvokeNode extends PNodeWithContext {
835
- public abstract Object execute (VirtualFrame frame , PExternalFunctionWrapper provider , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments );
836
-
837
- static CheckFunctionResultNode createCheckResultNode (PExternalFunctionWrapper provider ) {
838
- CheckFunctionResultNode node = provider .createCheckFunctionResultNode ();
839
- return node != null ? node : DefaultCheckFunctionResultNodeGen .create ();
840
- }
838
+ abstract Object execute (VirtualFrame frame , Node inliningTarget , PythonContext ctx , PythonThreadState threadState , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments );
841
839
842
- static CheckFunctionResultNode getUncachedCheckResultNode ( PExternalFunctionWrapper provider ) {
843
- CheckFunctionResultNode node = provider . getUncachedCheckFunctionResultNode ();
844
- return node != null ? node : DefaultCheckFunctionResultNodeGen . getUncached ( );
840
+ public final Object call ( VirtualFrame frame , Node inliningTarget , PythonContext ctx , PythonThreadState threadState , CApiTiming timing , TruffleString name , Object callable ,
841
+ Object ... cArguments ) {
842
+ return execute ( frame , inliningTarget , ctx , threadState , timing , name , callable , cArguments );
845
843
}
846
844
847
- @ Specialization (guards = {"provider == cachedProvider" }, limit = "1" )
848
- static Object invoke (VirtualFrame frame , PExternalFunctionWrapper provider , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments ,
849
- @ Bind ("this" ) Node inliningTarget ,
850
- @ Cached ("provider" ) PExternalFunctionWrapper cachedProvider ,
851
- @ Cached (value = "createCheckResultNode(provider)" , uncached = "getUncachedCheckResultNode(provider)" ) CheckFunctionResultNode checkResultNode ,
852
- @ Cached (value = "provider.createConvertRetNode()" , uncached = "provider.getUncachedConvertRetNode()" ) CExtToJavaNode convertReturnValue ,
853
- @ Cached PForeignToPTypeNode fromForeign ,
854
- @ Cached GetThreadStateNode getThreadStateNode ,
855
- @ Cached GilNode gilNode ,
845
+ @ Specialization
846
+ static Object invoke (VirtualFrame frame , Node inliningTarget , PythonContext ctx , PythonThreadState threadState , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments ,
847
+ @ Cached (inline = false ) GilNode gilNode ,
856
848
@ Cached (value = "createFor(this)" , uncached = "getUncached()" ) IndirectCallData indirectCallData ,
857
849
@ CachedLibrary (limit = "2" ) InteropLibrary lib ) {
858
- PythonContext ctx = PythonContext .get (inliningTarget );
859
- PythonThreadState threadState = getThreadStateNode .execute (inliningTarget , ctx );
860
850
861
851
// If any code requested the caught exception (i.e. used 'sys.exc_info()'), we store
862
852
// it to the context since we cannot propagate it through the native frames.
863
853
Object state = IndirectCallContext .enter (frame , threadState , indirectCallData );
864
854
865
855
CApiTiming .enter ();
866
856
try {
867
- Object result = lib .execute (callable , cArguments );
868
- result = checkResultNode .execute (threadState , name , result );
869
- if (convertReturnValue != null ) {
870
- result = convertReturnValue .execute (result );
871
- }
872
- return fromForeign .executeConvert (result );
857
+ return lib .execute (callable , cArguments );
873
858
} catch (UnsupportedTypeException | UnsupportedMessageException e ) {
874
859
CompilerDirectives .transferToInterpreterAndInvalidate ();
875
860
throw PRaiseNode .raiseUncached (inliningTarget , TypeError , ErrorMessages .CALLING_NATIVE_FUNC_FAILED , name , e );
876
861
} catch (ArityException e ) {
877
862
CompilerDirectives .transferToInterpreterAndInvalidate ();
878
863
throw PRaiseNode .raiseUncached (inliningTarget , TypeError , ErrorMessages .CALLING_NATIVE_FUNC_EXPECTED_ARGS , name , e .getExpectedMinArity (), e .getActualArity ());
879
- } finally {
880
- CApiTiming .exit (timing );
864
+ } catch (Throwable exception ) {
881
865
/*
882
866
* Always re-acquire the GIL here. This is necessary because it could happen that C
883
867
* extensions are releasing the GIL and if then an LLVM exception occurs, C code
884
868
* wouldn't re-acquire it (unexpectedly).
885
869
*/
886
- gilNode .acquire ();
887
-
870
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
871
+ GilNode .uncachedAcquire ();
872
+ throw exception ;
873
+ } finally {
874
+ CApiTiming .exit (timing );
888
875
/*
889
876
* Special case after calling a C function: transfer caught exception back to frame
890
877
* to simulate the global state semantics.
@@ -895,14 +882,73 @@ static Object invoke(VirtualFrame frame, PExternalFunctionWrapper provider, CApi
895
882
IndirectCallContext .exit (frame , threadState , state );
896
883
}
897
884
}
885
+ }
886
+
887
+ /**
888
+ * Wraps {@link ExternalFunctionInvokeNode} with result checking and conversion according to the
889
+ * passed {@link PExternalFunctionWrapper}. This node assumes that the provider argument is in
890
+ * the cached case a PE constant.
891
+ */
892
+ @ GenerateInline (false )
893
+ public abstract static class ExternalFunctionWrapperInvokeNode extends PNodeWithContext {
894
+ public abstract Object execute (VirtualFrame frame , PExternalFunctionWrapper provider , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments );
895
+
896
+ @ NeverDefault
897
+ static CheckFunctionResultNode createCheckResultNode (PExternalFunctionWrapper provider ) {
898
+ CheckFunctionResultNode node = provider .createCheckFunctionResultNode ();
899
+ return node != null ? node : DefaultCheckFunctionResultNodeGen .create ();
900
+ }
901
+
902
+ static CheckFunctionResultNode getUncachedCheckResultNode (PExternalFunctionWrapper provider ) {
903
+ CheckFunctionResultNode node = provider .getUncachedCheckFunctionResultNode ();
904
+ return node != null ? node : DefaultCheckFunctionResultNodeGen .getUncached ();
905
+ }
906
+
907
+ @ Specialization
908
+ static Object invokeCached (VirtualFrame frame , PExternalFunctionWrapper provider , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments ,
909
+ @ Bind ("this" ) Node inliningTarget ,
910
+ @ Cached ("createCheckResultNode(provider)" ) CheckFunctionResultNode checkResultNode ,
911
+ @ SuppressWarnings ("truffle-neverdefault" ) @ Cached ("provider.createConvertRetNode()" ) CExtToJavaNode convertReturnValue ,
912
+ @ Cached PForeignToPTypeNode fromForeign ,
913
+ @ Cached GetThreadStateNode getThreadStateNode ,
914
+ @ Cached ExternalFunctionInvokeNode invokeNode ) {
915
+ CompilerAsserts .partialEvaluationConstant (provider );
916
+ PythonContext ctx = PythonContext .get (inliningTarget );
917
+ return invoke (frame , ctx , timing , name , callable , cArguments , inliningTarget , checkResultNode , convertReturnValue , fromForeign , getThreadStateNode , invokeNode );
918
+ }
919
+
920
+ private static Object invoke (VirtualFrame frame , PythonContext ctx , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments , Node inliningTarget ,
921
+ CheckFunctionResultNode checkResultNode , CExtToJavaNode convertReturnValue , PForeignToPTypeNode fromForeign , GetThreadStateNode getThreadStateNode ,
922
+ ExternalFunctionInvokeNode invokeNode ) {
923
+ PythonThreadState threadState = getThreadStateNode .execute (inliningTarget , ctx );
924
+ Object result = invokeNode .execute (frame , inliningTarget , ctx , threadState , timing , name , callable , cArguments );
925
+ result = checkResultNode .execute (threadState , name , result );
926
+ if (convertReturnValue != null ) {
927
+ result = convertReturnValue .execute (result );
928
+ }
929
+ return fromForeign .executeConvert (result );
930
+ }
931
+
932
+ @ GenerateCached (false )
933
+ private static final class ExternalFunctionWrapperInvokeNodeUncached extends ExternalFunctionWrapperInvokeNode {
934
+ private static final ExternalFunctionWrapperInvokeNodeUncached INSTANCE = new ExternalFunctionWrapperInvokeNodeUncached ();
935
+
936
+ @ Override
937
+ public Object execute (VirtualFrame frame , PExternalFunctionWrapper provider , CApiTiming timing , TruffleString name , Object callable , Object [] cArguments ) {
938
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
939
+ PythonContext ctx = PythonContext .get (null );
940
+ return invoke (frame , ctx , timing , name , callable , cArguments , null , getUncachedCheckResultNode (provider ), provider .getUncachedConvertRetNode (), PForeignToPTypeNode .getUncached (),
941
+ GetThreadStateNode .getUncached (), ExternalFunctionInvokeNodeGen .getUncached ());
942
+ }
943
+ }
898
944
899
945
@ NeverDefault
900
- public static ExternalFunctionInvokeNode create () {
901
- return ExternalFunctionNodesFactory .ExternalFunctionInvokeNodeGen .create ();
946
+ public static ExternalFunctionWrapperInvokeNode create () {
947
+ return ExternalFunctionNodesFactory .ExternalFunctionWrapperInvokeNodeGen .create ();
902
948
}
903
949
904
- public static ExternalFunctionInvokeNode getUncached () {
905
- return ExternalFunctionNodesFactory . ExternalFunctionInvokeNodeGen . getUncached () ;
950
+ public static ExternalFunctionWrapperInvokeNode getUncached () {
951
+ return ExternalFunctionWrapperInvokeNodeUncached . INSTANCE ;
906
952
}
907
953
}
908
954
@@ -911,7 +957,7 @@ abstract static class MethodDescriptorRoot extends PRootNode {
911
957
private final CApiTiming timing ;
912
958
@ Child private CalleeContext calleeContext = CalleeContext .create ();
913
959
@ Child private CallVarargsMethodNode invokeNode ;
914
- @ Child private ExternalFunctionInvokeNode externalInvokeNode ;
960
+ @ Child private ExternalFunctionWrapperInvokeNode externalInvokeNode ;
915
961
@ Child private ReadIndexedArgumentNode readSelfNode ;
916
962
@ Child private ReadIndexedArgumentNode readCallableNode ;
917
963
@ Child private ReleaseNativeWrapperNode releaseNativeWrapperNode ;
@@ -930,7 +976,7 @@ abstract static class MethodDescriptorRoot extends PRootNode {
930
976
this .timing = CApiTiming .create (true , name );
931
977
this .provider = provider ;
932
978
if (provider != null ) {
933
- this .externalInvokeNode = ExternalFunctionInvokeNode .create ();
979
+ this .externalInvokeNode = ExternalFunctionWrapperInvokeNode .create ();
934
980
this .convertArgs = provider .createConvertArgNodes ();
935
981
} else {
936
982
this .invokeNode = CallVarargsMethodNode .create ();
0 commit comments