42
42
43
43
import java .util .Objects ;
44
44
45
- import org .graalvm .wasm .api .InteropArray ;
46
- import org .graalvm .wasm .api .Vector128 ;
47
- import org .graalvm .wasm .exception .Failure ;
48
- import org .graalvm .wasm .exception .WasmException ;
49
- import org .graalvm .wasm .nodes .WasmIndirectCallNode ;
50
-
51
45
import com .oracle .truffle .api .CallTarget ;
46
+ import com .oracle .truffle .api .CompilerDirectives ;
52
47
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
53
48
import com .oracle .truffle .api .RootCallTarget ;
54
49
import com .oracle .truffle .api .TruffleContext ;
50
+ import com .oracle .truffle .api .dsl .Bind ;
55
51
import com .oracle .truffle .api .dsl .Cached ;
56
- import com .oracle .truffle .api .interop . ArityException ;
52
+ import com .oracle .truffle .api .dsl . Specialization ;
57
53
import com .oracle .truffle .api .interop .InteropLibrary ;
58
54
import com .oracle .truffle .api .interop .TruffleObject ;
59
- import com .oracle .truffle .api .interop .UnsupportedTypeException ;
60
- import com .oracle .truffle .api .library .CachedLibrary ;
61
55
import com .oracle .truffle .api .library .ExportLibrary ;
62
56
import com .oracle .truffle .api .library .ExportMessage ;
57
+ import com .oracle .truffle .api .nodes .EncapsulatingNodeReference ;
58
+ import com .oracle .truffle .api .nodes .Node ;
63
59
64
60
@ ExportLibrary (InteropLibrary .class )
65
61
public final class WasmFunctionInstance extends EmbedderDataHolder implements TruffleObject {
@@ -69,6 +65,10 @@ public final class WasmFunctionInstance extends EmbedderDataHolder implements Tr
69
65
private final WasmFunction function ;
70
66
private final CallTarget target ;
71
67
private final TruffleContext truffleContext ;
68
+ /**
69
+ * Stores the imported function object for {@link org.graalvm.wasm.api.ExecuteHostFunctionNode}.
70
+ * Initialized during linking.
71
+ */
72
72
private Object importedFunction ;
73
73
74
74
/**
@@ -135,104 +135,52 @@ boolean isExecutable() {
135
135
}
136
136
137
137
@ ExportMessage
138
- Object execute (Object [] arguments ,
139
- @ CachedLibrary ("this" ) InteropLibrary self ,
140
- @ Cached WasmIndirectCallNode callNode ) throws ArityException , UnsupportedTypeException {
141
- TruffleContext c = getTruffleContext ();
142
- Object prev = c .enter (self );
143
- try {
144
- Object result = callNode .execute (target , WasmArguments .create (moduleInstance , validateArguments (arguments )));
145
-
146
- // For external calls of a WebAssembly function we have to materialize the multi-value
147
- // stack.
148
- // At this point the multi-value stack has already been populated, therefore, we don't
149
- // have to check the size of the multi-value stack.
150
- if (result == WasmConstant .MULTI_VALUE ) {
151
- WasmLanguage language = context .language ();
152
- assert language == WasmLanguage .get (null );
153
- return multiValueStackAsArray (language );
138
+ static class Execute {
139
+ private static Object execute (WasmFunctionInstance functionInstance , Object [] arguments , CallTarget callAdapter , Node node , Node callNode ) {
140
+ TruffleContext c = functionInstance .getTruffleContext ();
141
+ Object prev = c .enter (node );
142
+ try {
143
+ return callAdapter .call (callNode , WasmArguments .create (functionInstance , arguments ));
144
+ // throws ArityException, UnsupportedTypeException
145
+ } finally {
146
+ c .leave (node , prev );
154
147
}
155
- return result ;
156
- } finally {
157
- c .leave (self , prev );
158
148
}
159
- }
160
149
161
- private Object [] validateArguments (Object [] arguments ) throws ArityException , UnsupportedTypeException {
162
- if (function == null ) {
163
- return arguments ;
150
+ @ SuppressWarnings ("unused" )
151
+ @ Specialization (guards = {"actualFunction == cachedFunction" }, limit = "2" )
152
+ static Object direct (WasmFunctionInstance functionInstance , Object [] arguments ,
153
+ @ Bind ("functionInstance.function()" ) WasmFunction actualFunction ,
154
+ @ Cached ("actualFunction" ) WasmFunction cachedFunction ,
155
+ @ Cached ("getOrCreateInteropCallAdapter(functionInstance)" ) CallTarget cachedCallAdapter ,
156
+ @ Bind Node node ) {
157
+ return execute (functionInstance , arguments , cachedCallAdapter , node , node );
164
158
}
165
- final int paramCount = function .paramCount ();
166
- if (arguments .length != paramCount ) {
167
- throw ArityException .create (paramCount , paramCount , arguments .length );
159
+
160
+ @ SuppressWarnings ("unused" )
161
+ @ Specialization (guards = {"actualCallAdapter == cachedCallAdapter" }, limit = "3" , replaces = "direct" )
162
+ static Object directAdapter (WasmFunctionInstance functionInstance , Object [] arguments ,
163
+ @ Bind ("getOrCreateInteropCallAdapter(functionInstance)" ) CallTarget actualCallAdapter ,
164
+ @ Cached ("actualCallAdapter" ) CallTarget cachedCallAdapter ,
165
+ @ Bind Node node ) {
166
+ return execute (functionInstance , arguments , cachedCallAdapter , node , node );
168
167
}
169
- for (int i = 0 ; i < paramCount ; i ++) {
170
- byte paramType = function .paramTypeAt (i );
171
- Object value = arguments [i ];
172
- switch (paramType ) {
173
- case WasmType .I32_TYPE -> {
174
- if (value instanceof Integer ) {
175
- continue ;
176
- }
177
- }
178
- case WasmType .I64_TYPE -> {
179
- if (value instanceof Long ) {
180
- continue ;
181
- }
182
- }
183
- case WasmType .F32_TYPE -> {
184
- if (value instanceof Float ) {
185
- continue ;
186
- }
187
- }
188
- case WasmType .F64_TYPE -> {
189
- if (value instanceof Double ) {
190
- continue ;
191
- }
192
- }
193
- case WasmType .V128_TYPE -> {
194
- if (value instanceof Vector128 ) {
195
- continue ;
196
- }
197
- }
198
- case WasmType .FUNCREF_TYPE -> {
199
- if (value instanceof WasmFunctionInstance || value == WasmConstant .NULL ) {
200
- continue ;
201
- }
202
- }
203
- case WasmType .EXTERNREF_TYPE -> {
204
- continue ;
205
- }
206
- default -> throw WasmException .create (Failure .UNKNOWN_TYPE );
207
- }
208
- throw UnsupportedTypeException .create (arguments );
168
+
169
+ @ Specialization (replaces = "directAdapter" )
170
+ static Object indirect (WasmFunctionInstance functionInstance , Object [] arguments ,
171
+ @ Bind Node node ) {
172
+ CallTarget callAdapter = getOrCreateInteropCallAdapter (functionInstance );
173
+ Node callNode = node .isAdoptable () ? node : EncapsulatingNodeReference .getCurrent ().get ();
174
+ return execute (functionInstance , arguments , callAdapter , node , callNode );
209
175
}
210
- return arguments ;
211
- }
212
176
213
- private Object multiValueStackAsArray (WasmLanguage language ) {
214
- final var multiValueStack = language .multiValueStack ();
215
- final long [] primitiveMultiValueStack = multiValueStack .primitiveStack ();
216
- final Object [] objectMultiValueStack = multiValueStack .objectStack ();
217
- final int resultCount = function .resultCount ();
218
- assert primitiveMultiValueStack .length >= resultCount ;
219
- assert objectMultiValueStack .length >= resultCount ;
220
- final Object [] values = new Object [resultCount ];
221
- for (int i = 0 ; i < resultCount ; i ++) {
222
- byte resultType = function .resultTypeAt (i );
223
- values [i ] = switch (resultType ) {
224
- case WasmType .I32_TYPE -> (int ) primitiveMultiValueStack [i ];
225
- case WasmType .I64_TYPE -> primitiveMultiValueStack [i ];
226
- case WasmType .F32_TYPE -> Float .intBitsToFloat ((int ) primitiveMultiValueStack [i ]);
227
- case WasmType .F64_TYPE -> Double .longBitsToDouble (primitiveMultiValueStack [i ]);
228
- case WasmType .V128_TYPE , WasmType .FUNCREF_TYPE , WasmType .EXTERNREF_TYPE -> {
229
- Object obj = objectMultiValueStack [i ];
230
- objectMultiValueStack [i ] = null ;
231
- yield obj ;
232
- }
233
- default -> throw WasmException .create (Failure .UNSPECIFIED_INTERNAL );
234
- };
177
+ static CallTarget getOrCreateInteropCallAdapter (WasmFunctionInstance functionInstance ) {
178
+ WasmFunction function = functionInstance .function ();
179
+ CallTarget callAdapter = function .getInteropCallAdapter ();
180
+ if (CompilerDirectives .injectBranchProbability (CompilerDirectives .SLOWPATH_PROBABILITY , callAdapter == null )) {
181
+ return function .getOrCreateInteropCallAdapter (functionInstance .context ().language ());
182
+ }
183
+ return callAdapter ;
235
184
}
236
- return InteropArray .create (values );
237
185
}
238
186
}
0 commit comments