@@ -85,6 +85,54 @@ static bool ToWasmValue(const Number& value,
85
85
}
86
86
}
87
87
88
+ static Dart_Handle ToWasmValue (Dart_Handle value,
89
+ wasmer_value_tag type,
90
+ wasmer_value* out) {
91
+ switch (type) {
92
+ case wasmer_value_tag::WASM_I32: {
93
+ int64_t i64;
94
+ Dart_Handle result = Dart_IntegerToInt64 (value, &i64);
95
+ out->I32 = i64;
96
+ if (out->I32 != i64) {
97
+ return Dart_NewApiError (" Int doesn't fit into 32-bits" );
98
+ }
99
+ return result;
100
+ }
101
+ case wasmer_value_tag::WASM_I64:
102
+ return Dart_IntegerToInt64 (value, &out->I64 );
103
+ case wasmer_value_tag::WASM_F32: {
104
+ double f64;
105
+ Dart_Handle result = Dart_DoubleValue (value, &f64);
106
+ out->F32 = f64;
107
+ return result;
108
+ }
109
+ case wasmer_value_tag::WASM_F64:
110
+ return Dart_DoubleValue (value, &out->F64 );
111
+ default :
112
+ FATAL (" Unknown WASM type" );
113
+ return nullptr ;
114
+ }
115
+ }
116
+
117
+ static bool ToWasmValueTag (classid_t type, wasmer_value_tag* out) {
118
+ switch (type) {
119
+ case kWasmInt32Cid :
120
+ *out = wasmer_value_tag::WASM_I32;
121
+ return true ;
122
+ case kWasmInt64Cid :
123
+ *out = wasmer_value_tag::WASM_I64;
124
+ return true ;
125
+ case kWasmFloatCid :
126
+ *out = wasmer_value_tag::WASM_F32;
127
+ return true ;
128
+ case kWasmDoubleCid :
129
+ *out = wasmer_value_tag::WASM_F64;
130
+ return true ;
131
+ default :
132
+ return false ;
133
+ }
134
+ }
135
+
88
136
static RawObject* ToDartObject (wasmer_value_t ret) {
89
137
switch (ret.tag ) {
90
138
case wasmer_value_tag::WASM_I32:
@@ -101,6 +149,22 @@ static RawObject* ToDartObject(wasmer_value_t ret) {
101
149
}
102
150
}
103
151
152
+ static Dart_Handle ToDartApiObject (wasmer_value value, wasmer_value_tag type) {
153
+ switch (type) {
154
+ case wasmer_value_tag::WASM_I32:
155
+ return Dart_NewInteger (value.I32 );
156
+ case wasmer_value_tag::WASM_I64:
157
+ return Dart_NewInteger (value.I64 );
158
+ case wasmer_value_tag::WASM_F32:
159
+ return Dart_NewDouble (value.F32 );
160
+ case wasmer_value_tag::WASM_F64:
161
+ return Dart_NewDouble (value.F64 );
162
+ default :
163
+ FATAL (" Unknown WASM type" );
164
+ return nullptr ;
165
+ }
166
+ }
167
+
104
168
RawExternalTypedData* WasmMemoryToExternalTypedData (wasmer_memory_t * memory) {
105
169
uint8_t * data = wasmer_memory_data (memory);
106
170
uint32_t size = wasmer_memory_data_length (memory);
@@ -158,6 +222,41 @@ RawString* DescribeModule(const wasmer_module_t* module) {
158
222
return String::New (desc.str ().c_str ());
159
223
}
160
224
225
+ class WasmImports ;
226
+
227
+ struct WasmFunctionImport {
228
+ WasmImports* imports;
229
+ std::unique_ptr<wasmer_value_tag[]> args;
230
+ intptr_t num_args;
231
+ wasmer_value_tag ret;
232
+ intptr_t num_rets;
233
+ int64_t fn_id;
234
+ wasmer_import_func_t * wasm_fn;
235
+ wasmer_trampoline_buffer_t * buffer;
236
+ WasmFunctionImport (WasmImports* imports_,
237
+ std::unique_ptr<wasmer_value_tag[]> args_,
238
+ intptr_t num_args_,
239
+ wasmer_value_tag ret_,
240
+ intptr_t num_rets_,
241
+ int64_t fn_id_)
242
+ : imports(imports_),
243
+ args (std::move(args_)),
244
+ num_args(num_args_),
245
+ ret(ret_),
246
+ num_rets(num_rets_),
247
+ fn_id(fn_id_),
248
+ wasm_fn(nullptr ),
249
+ buffer(nullptr ) {}
250
+ ~WasmFunctionImport () {
251
+ wasmer_trampoline_buffer_destroy (buffer);
252
+ wasmer_import_func_destroy (wasm_fn);
253
+ }
254
+ };
255
+
256
+ extern " C" {
257
+ int64_t Trampoline (void * context, int64_t * args);
258
+ }
259
+
161
260
class WasmImports {
162
261
public:
163
262
explicit WasmImports (std::unique_ptr<char []> module_name)
@@ -167,11 +266,15 @@ class WasmImports {
167
266
for (wasmer_global_t * global : _globals) {
168
267
wasmer_global_destroy (global);
169
268
}
269
+ for (WasmFunctionImport* fn_imp : _functions) {
270
+ delete fn_imp;
271
+ }
170
272
for (const char * name : _import_names) {
171
273
delete[] name;
172
274
}
173
275
}
174
276
277
+ void SetHandle (FinalizablePersistentHandle* handle) { _handle = handle; }
175
278
size_t NumImports () const { return _imports.length (); }
176
279
wasmer_import_t * RawImports () { return _imports.data (); }
177
280
@@ -189,10 +292,86 @@ class WasmImports {
189
292
global;
190
293
}
191
294
295
+ void AddFunction (std::unique_ptr<char []> name,
296
+ int64_t fn_id,
297
+ std::unique_ptr<wasmer_value_tag[]> args,
298
+ intptr_t num_args,
299
+ wasmer_value_tag ret,
300
+ intptr_t num_rets) {
301
+ // Trampoline args include the context pointer.
302
+ const intptr_t num_trampoline_args = num_args + 1 ;
303
+
304
+ WasmFunctionImport* fn_imp = new WasmFunctionImport (
305
+ this , std::move (args), num_args, ret, num_rets, fn_id);
306
+ _functions.Add (fn_imp);
307
+
308
+ wasmer_trampoline_buffer_builder_t * builder =
309
+ wasmer_trampoline_buffer_builder_new ();
310
+ uintptr_t trampoline_id =
311
+ wasmer_trampoline_buffer_builder_add_callinfo_trampoline (
312
+ builder,
313
+ reinterpret_cast <wasmer_trampoline_callable_t *>(Trampoline),
314
+ reinterpret_cast <void *>(fn_imp), num_trampoline_args);
315
+ fn_imp->buffer = wasmer_trampoline_buffer_builder_build (builder);
316
+
317
+ const wasmer_trampoline_callable_t * trampoline =
318
+ wasmer_trampoline_buffer_get_trampoline (fn_imp->buffer , trampoline_id);
319
+ fn_imp->wasm_fn = wasmer_import_func_new (
320
+ reinterpret_cast <void (*)(void *)>(
321
+ const_cast <wasmer_trampoline_callable_t *>(trampoline)),
322
+ fn_imp->args .get (), num_args, &ret, num_rets);
323
+
324
+ AddImport (std::move (name), wasmer_import_export_kind::WASM_FUNCTION)->func =
325
+ fn_imp->wasm_fn ;
326
+ }
327
+
328
+ int64_t CallImportedFunction (WasmFunctionImport* fn_imp, int64_t * raw_args) {
329
+ wasmer_value* wasm_args = reinterpret_cast <wasmer_value*>(raw_args);
330
+ Dart_Handle inst = Dart_HandleFromWeakPersistent (_handle->apiHandle ());
331
+ Dart_Handle dart_args[2 ] = {
332
+ inst,
333
+ Dart_NewInteger (fn_imp->fn_id ),
334
+ };
335
+ Dart_Handle closure = Dart_Invoke (Dart_InstanceGetType (inst),
336
+ Dart_NewStringFromCString (" getFunction" ),
337
+ ARRAY_SIZE (dart_args), dart_args);
338
+ if (Dart_IsError (closure)) {
339
+ Dart_ThrowException (closure);
340
+ UNREACHABLE ();
341
+ }
342
+ Dart_Handle result;
343
+ {
344
+ auto args =
345
+ std::unique_ptr<Dart_Handle[]>(new Dart_Handle[fn_imp->num_args ]);
346
+ for (intptr_t i = 0 ; i < fn_imp->num_args ; ++i) {
347
+ args[i] = ToDartApiObject (wasm_args[i], fn_imp->args [i]);
348
+ }
349
+ result = Dart_InvokeClosure (closure, fn_imp->num_args , args.get ());
350
+ }
351
+ if (Dart_IsError (result)) {
352
+ Dart_ThrowException (result);
353
+ UNREACHABLE ();
354
+ }
355
+ if (fn_imp->num_rets == 0 ) {
356
+ // Wasmer ignores the result of this function if it expects no results,
357
+ // so skip the converters below (we get errors if we run them).
358
+ return 0 ;
359
+ }
360
+ wasmer_value wasm_result;
361
+ result = ToWasmValue (result, fn_imp->ret , &wasm_result);
362
+ if (Dart_IsError (result)) {
363
+ Dart_ThrowException (result);
364
+ UNREACHABLE ();
365
+ }
366
+ return wasm_result.I64 ;
367
+ }
368
+
192
369
private:
370
+ FinalizablePersistentHandle* _handle;
193
371
std::unique_ptr<char []> _module_name;
194
372
MallocGrowableArray<const char *> _import_names;
195
373
MallocGrowableArray<wasmer_global_t *> _globals;
374
+ MallocGrowableArray<WasmFunctionImport*> _functions;
196
375
MallocGrowableArray<wasmer_import_t > _imports;
197
376
198
377
wasmer_import_export_value* AddImport (std::unique_ptr<char []> name,
@@ -212,6 +391,14 @@ class WasmImports {
212
391
DISALLOW_COPY_AND_ASSIGN (WasmImports);
213
392
};
214
393
394
+ extern " C" {
395
+ int64_t Trampoline (void * context, int64_t * args) {
396
+ WasmFunctionImport* fn_imp = reinterpret_cast <WasmFunctionImport*>(context);
397
+ // Skip the first arg (it's another context pointer).
398
+ return fn_imp->imports ->CallImportedFunction (fn_imp, args + 1 );
399
+ }
400
+ }
401
+
215
402
class WasmFunction {
216
403
public:
217
404
WasmFunction (MallocGrowableArray<classid_t > args,
@@ -468,8 +655,9 @@ DEFINE_NATIVE_ENTRY(Wasm_initImports, 0, 2) {
468
655
WasmImports* imports = new WasmImports (ToUTF8 (module_name));
469
656
470
657
imp_wrap.SetNativeField (0 , reinterpret_cast <intptr_t >(imports));
471
- FinalizablePersistentHandle::New (thread->isolate (), imp_wrap, imports,
472
- Finalize<WasmImports>, sizeof (WasmImports));
658
+ imports->SetHandle (FinalizablePersistentHandle::New (
659
+ thread->isolate (), imp_wrap, imports, Finalize<WasmImports>,
660
+ sizeof (WasmImports)));
473
661
474
662
return Object::null ();
475
663
}
@@ -505,8 +693,9 @@ DEFINE_NATIVE_ENTRY(Wasm_addGlobalImport, 0, 5) {
505
693
reinterpret_cast <WasmImports*>(imp_wrap.GetNativeField (0 ));
506
694
wasmer_value_t wasm_value;
507
695
if (!ToWasmValue (value, type.type_class_id (), &wasm_value)) {
508
- Exceptions::ThrowArgumentError (String::Handle (String::NewFormatted (
509
- " Can't convert dart value to WASM global variable" )));
696
+ Exceptions::ThrowArgumentError (String::Handle (
697
+ zone, String::NewFormatted (
698
+ " Can't convert dart value to WASM global variable" )));
510
699
UNREACHABLE ();
511
700
}
512
701
@@ -515,6 +704,53 @@ DEFINE_NATIVE_ENTRY(Wasm_addGlobalImport, 0, 5) {
515
704
return Object::null ();
516
705
}
517
706
707
+ DEFINE_NATIVE_ENTRY (Wasm_addFunctionImport, 0 , 4 ) {
708
+ GET_NON_NULL_NATIVE_ARGUMENT (Instance, imp_wrap, arguments->NativeArgAt (0 ));
709
+ GET_NON_NULL_NATIVE_ARGUMENT (String, name, arguments->NativeArgAt (1 ));
710
+ GET_NON_NULL_NATIVE_ARGUMENT (Integer, fn_id, arguments->NativeArgAt (2 ));
711
+ GET_NON_NULL_NATIVE_ARGUMENT (Type, fn_type, arguments->NativeArgAt (3 ));
712
+
713
+ ASSERT (imp_wrap.NumNativeFields () == 1 );
714
+
715
+ Function& sig = Function::Handle (zone, fn_type.signature ());
716
+
717
+ classid_t ret = AbstractType::Handle (zone, sig.result_type ()).type_class_id ();
718
+ intptr_t num_rets = ret == kWasmVoidCid ? 0 : 1 ;
719
+ wasmer_value_tag wasm_ret = wasmer_value_tag::WASM_I64;
720
+ if (num_rets != 0 ) {
721
+ if (!ToWasmValueTag (ret, &wasm_ret)) {
722
+ Exceptions::ThrowArgumentError (String::Handle (
723
+ zone, String::NewFormatted (" Return type is not a valid WASM type" )));
724
+ UNREACHABLE ();
725
+ }
726
+ }
727
+
728
+ Array& args = Array::Handle (zone, sig.parameter_types ());
729
+ AbstractType& arg_type = AbstractType::Handle (zone);
730
+ intptr_t first_arg_index = sig.NumImplicitParameters ();
731
+ intptr_t num_args = args.Length () - first_arg_index;
732
+ auto wasm_args =
733
+ std::unique_ptr<wasmer_value_tag[]>(new wasmer_value_tag[num_args]);
734
+ for (intptr_t i = 0 ; i < num_args; ++i) {
735
+ arg_type ^= args.At (i + first_arg_index);
736
+ classid_t dart_arg = arg_type.type_class_id ();
737
+ if (!ToWasmValueTag (dart_arg, &wasm_args[i])) {
738
+ wasm_args.reset ();
739
+ Exceptions::ThrowArgumentError (String::Handle (
740
+ zone, String::NewFormatted (
741
+ " Type of arg %" Pd " is not a valid WASM type" , i)));
742
+ UNREACHABLE ();
743
+ }
744
+ }
745
+
746
+ WasmImports* imports =
747
+ reinterpret_cast <WasmImports*>(imp_wrap.GetNativeField (0 ));
748
+ imports->AddFunction (ToUTF8 (name), fn_id.AsInt64Value (), std::move (wasm_args),
749
+ num_args, wasm_ret, num_rets);
750
+
751
+ return Object::null ();
752
+ }
753
+
518
754
DEFINE_NATIVE_ENTRY (Wasm_initMemory, 0 , 3 ) {
519
755
GET_NON_NULL_NATIVE_ARGUMENT (Instance, mem_wrap, arguments->NativeArgAt (0 ));
520
756
GET_NON_NULL_NATIVE_ARGUMENT (Integer, init, arguments->NativeArgAt (1 ));
@@ -610,15 +846,16 @@ DEFINE_NATIVE_ENTRY(Wasm_initFunction, 0, 4) {
610
846
String& error = String::Handle (zone);
611
847
612
848
{
613
- Function& sig = Function::Handle (fn_type.signature ());
614
- Array& args = Array::Handle (sig.parameter_types ());
849
+ Function& sig = Function::Handle (zone, fn_type.signature ());
850
+ Array& args = Array::Handle (zone, sig.parameter_types ());
851
+ AbstractType& arg_type = AbstractType::Handle (zone);
615
852
MallocGrowableArray<classid_t > dart_args;
616
853
for (intptr_t i = sig.NumImplicitParameters (); i < args.Length (); ++i) {
617
- dart_args. Add (
618
- AbstractType::Cast ( Object::Handle (args. At (i))) .type_class_id ());
854
+ arg_type ^= args. At (i);
855
+ dart_args. Add (arg_type .type_class_id ());
619
856
}
620
857
classid_t dart_ret =
621
- AbstractType::Handle (sig.result_type ()).type_class_id ();
858
+ AbstractType::Handle (zone, sig.result_type ()).type_class_id ();
622
859
623
860
std::unique_ptr<char []> name_raw = ToUTF8 (name);
624
861
fn = inst->GetFunction (name_raw.get (), dart_args, dart_ret, &error);
@@ -643,19 +880,21 @@ DEFINE_NATIVE_ENTRY(Wasm_callFunction, 0, 2) {
643
880
WasmFunction* fn = reinterpret_cast <WasmFunction*>(fn_wrap.GetNativeField (0 ));
644
881
645
882
if (args.Length () != fn->args ().length ()) {
646
- Exceptions::ThrowArgumentError (String::Handle (String::NewFormatted (
647
- " Wrong number of args. Expected %" Pu " but found %" Pd " ." ,
648
- fn->args ().length (), args.Length ())));
883
+ Exceptions::ThrowArgumentError (String::Handle (
884
+ zone, String::NewFormatted (" Wrong number of args. Expected %" Pu
885
+ " but found %" Pd " ." ,
886
+ fn->args ().length (), args.Length ())));
649
887
UNREACHABLE ();
650
888
}
651
889
auto params = std::unique_ptr<wasmer_value_t []>(
652
890
new wasmer_value_t [fn->args ().length ()]);
891
+ Number& arg_num = Number::Handle (zone);
653
892
for (intptr_t i = 0 ; i < args.Length (); ++i) {
654
- if (! ToWasmValue ( Number::Cast ( Object::Handle ( args.At (i))), fn-> args ()[i],
655
- ¶ms[i])) {
893
+ arg_num ^= args.At (i);
894
+ if (! ToWasmValue (arg_num, fn-> args ()[i], ¶ms[i])) {
656
895
params.reset ();
657
896
Exceptions::ThrowArgumentError (String::Handle (
658
- String::NewFormatted (" Arg %" Pd " is the wrong type." , i)));
897
+ zone, String::NewFormatted (" Arg %" Pd " is the wrong type." , i)));
659
898
UNREACHABLE ();
660
899
}
661
900
}
@@ -709,6 +948,11 @@ DEFINE_NATIVE_ENTRY(Wasm_addGlobalImport, 0, 5) {
709
948
return nullptr ;
710
949
}
711
950
951
+ DEFINE_NATIVE_ENTRY (Wasm_addFunctionImport, 0 , 4 ) {
952
+ Exceptions::ThrowUnsupportedError (" WASM is disabled" );
953
+ return nullptr ;
954
+ }
955
+
712
956
DEFINE_NATIVE_ENTRY (Wasm_initMemory, 0 , 3 ) {
713
957
Exceptions::ThrowUnsupportedError (" WASM is disabled" );
714
958
return nullptr ;
0 commit comments