53
53
54
54
import com .oracle .truffle .api .CallTarget ;
55
55
import com .oracle .truffle .api .CompilerAsserts ;
56
+ import com .oracle .truffle .api .CompilerDirectives ;
56
57
import com .oracle .truffle .api .frame .VirtualFrame ;
57
58
import com .oracle .truffle .api .interop .ArityException ;
58
59
import com .oracle .truffle .api .interop .UnsupportedTypeException ;
71
72
* the call target to be reused by different functions of the same type (equivalence class).
72
73
*/
73
74
public final class InteropCallAdapterNode extends RootNode {
75
+
76
+ private static final int MAX_UNROLL = 32 ;
77
+
74
78
private final SymbolTable .FunctionType functionType ;
75
79
private final BranchProfile errorBranch = BranchProfile .create ();
76
80
@ Child private WasmIndirectCallNode callNode ;
@@ -105,59 +109,72 @@ public Object execute(VirtualFrame frame) {
105
109
}
106
110
}
107
111
108
- @ ExplodeLoop
109
112
private Object [] validateArguments (Object [] arguments , int offset ) throws ArityException , UnsupportedTypeException {
110
113
final byte [] paramTypes = functionType .paramTypes ();
111
114
final int paramCount = paramTypes .length ;
112
115
CompilerAsserts .partialEvaluationConstant (paramCount );
113
116
if (arguments .length - offset != paramCount ) {
114
117
throw ArityException .create (paramCount , paramCount , arguments .length - offset );
115
118
}
119
+ if (CompilerDirectives .inCompiledCode () && paramCount <= MAX_UNROLL ) {
120
+ validateArgumentsUnroll (arguments , offset , paramTypes , paramCount );
121
+ } else {
122
+ for (int i = 0 ; i < paramCount ; i ++) {
123
+ validateArgument (arguments , offset , paramTypes , i );
124
+ }
125
+ }
126
+ return arguments ;
127
+ }
128
+
129
+ @ ExplodeLoop
130
+ private static void validateArgumentsUnroll (Object [] arguments , int offset , byte [] paramTypes , int paramCount ) throws UnsupportedTypeException {
116
131
for (int i = 0 ; i < paramCount ; i ++) {
117
- byte paramType = paramTypes [i ];
118
- Object value = arguments [i + offset ];
119
- switch (paramType ) {
120
- case WasmType .I32_TYPE -> {
121
- if (value instanceof Integer ) {
122
- continue ;
123
- }
124
- }
125
- case WasmType .I64_TYPE -> {
126
- if (value instanceof Long ) {
127
- continue ;
128
- }
132
+ validateArgument (arguments , offset , paramTypes , i );
133
+ }
134
+ }
135
+
136
+ private static void validateArgument (Object [] arguments , int offset , byte [] paramTypes , int i ) throws UnsupportedTypeException {
137
+ byte paramType = paramTypes [i ];
138
+ Object value = arguments [i + offset ];
139
+ switch (paramType ) {
140
+ case WasmType .I32_TYPE -> {
141
+ if (value instanceof Integer ) {
142
+ return ;
129
143
}
130
- case WasmType . F32_TYPE -> {
131
- if ( value instanceof Float ) {
132
- continue ;
133
- }
144
+ }
145
+ case WasmType . I64_TYPE -> {
146
+ if ( value instanceof Long ) {
147
+ return ;
134
148
}
135
- case WasmType . F64_TYPE -> {
136
- if ( value instanceof Double ) {
137
- continue ;
138
- }
149
+ }
150
+ case WasmType . F32_TYPE -> {
151
+ if ( value instanceof Float ) {
152
+ return ;
139
153
}
140
- case WasmType . V128_TYPE -> {
141
- if ( value instanceof Vector128 ) {
142
- continue ;
143
- }
154
+ }
155
+ case WasmType . F64_TYPE -> {
156
+ if ( value instanceof Double ) {
157
+ return ;
144
158
}
145
- case WasmType . FUNCREF_TYPE -> {
146
- if ( value instanceof WasmFunctionInstance || value == WasmConstant . NULL ) {
147
- continue ;
148
- }
159
+ }
160
+ case WasmType . V128_TYPE -> {
161
+ if ( value instanceof Vector128 ) {
162
+ return ;
149
163
}
150
- case WasmType .EXTERNREF_TYPE -> {
151
- continue ;
164
+ }
165
+ case WasmType .FUNCREF_TYPE -> {
166
+ if (value instanceof WasmFunctionInstance || value == WasmConstant .NULL ) {
167
+ return ;
152
168
}
153
- default -> throw WasmException .create (Failure .UNKNOWN_TYPE );
154
169
}
155
- throw UnsupportedTypeException .create (arguments );
170
+ case WasmType .EXTERNREF_TYPE -> {
171
+ return ;
172
+ }
173
+ default -> throw WasmException .create (Failure .UNKNOWN_TYPE );
156
174
}
157
- return arguments ;
175
+ throw UnsupportedTypeException . create ( arguments ) ;
158
176
}
159
177
160
- @ ExplodeLoop
161
178
private Object multiValueStackAsArray (WasmLanguage language ) {
162
179
final var multiValueStack = language .multiValueStack ();
163
180
final long [] primitiveMultiValueStack = multiValueStack .primitiveStack ();
@@ -168,24 +185,39 @@ private Object multiValueStackAsArray(WasmLanguage language) {
168
185
assert objectMultiValueStack .length >= resultCount ;
169
186
final Object [] values = new Object [resultCount ];
170
187
CompilerAsserts .partialEvaluationConstant (resultCount );
171
- for (int i = 0 ; i < resultCount ; i ++) {
172
- byte resultType = resultTypes [i ];
173
- values [i ] = switch (resultType ) {
174
- case WasmType .I32_TYPE -> (int ) primitiveMultiValueStack [i ];
175
- case WasmType .I64_TYPE -> primitiveMultiValueStack [i ];
176
- case WasmType .F32_TYPE -> Float .intBitsToFloat ((int ) primitiveMultiValueStack [i ]);
177
- case WasmType .F64_TYPE -> Double .longBitsToDouble (primitiveMultiValueStack [i ]);
178
- case WasmType .V128_TYPE , WasmType .FUNCREF_TYPE , WasmType .EXTERNREF_TYPE -> {
179
- Object obj = objectMultiValueStack [i ];
180
- objectMultiValueStack [i ] = null ;
181
- yield obj ;
182
- }
183
- default -> throw WasmException .create (Failure .UNSPECIFIED_INTERNAL );
184
- };
188
+ if (CompilerDirectives .inCompiledCode () && resultCount <= MAX_UNROLL ) {
189
+ popMultiValueResultUnroll (values , primitiveMultiValueStack , objectMultiValueStack , resultTypes , resultCount );
190
+ } else {
191
+ for (int i = 0 ; i < resultCount ; i ++) {
192
+ values [i ] = popMultiValueResult (primitiveMultiValueStack , objectMultiValueStack , resultTypes , i );
193
+ }
185
194
}
186
195
return InteropArray .create (values );
187
196
}
188
197
198
+ @ ExplodeLoop
199
+ private static void popMultiValueResultUnroll (Object [] values , long [] primitiveMultiValueStack , Object [] objectMultiValueStack , byte [] resultTypes , int resultCount ) {
200
+ for (int i = 0 ; i < resultCount ; i ++) {
201
+ values [i ] = popMultiValueResult (primitiveMultiValueStack , objectMultiValueStack , resultTypes , i );
202
+ }
203
+ }
204
+
205
+ private static Object popMultiValueResult (long [] primitiveMultiValueStack , Object [] objectMultiValueStack , byte [] resultTypes , int i ) {
206
+ final byte resultType = resultTypes [i ];
207
+ return switch (resultType ) {
208
+ case WasmType .I32_TYPE -> (int ) primitiveMultiValueStack [i ];
209
+ case WasmType .I64_TYPE -> primitiveMultiValueStack [i ];
210
+ case WasmType .F32_TYPE -> Float .intBitsToFloat ((int ) primitiveMultiValueStack [i ]);
211
+ case WasmType .F64_TYPE -> Double .longBitsToDouble (primitiveMultiValueStack [i ]);
212
+ case WasmType .V128_TYPE , WasmType .FUNCREF_TYPE , WasmType .EXTERNREF_TYPE -> {
213
+ Object obj = objectMultiValueStack [i ];
214
+ objectMultiValueStack [i ] = null ;
215
+ yield obj ;
216
+ }
217
+ default -> throw WasmException .create (Failure .UNSPECIFIED_INTERNAL );
218
+ };
219
+ }
220
+
189
221
// TODO: Do we need the 3 overrides below?
190
222
@ Override
191
223
public String getName () {
0 commit comments