wasmer-c-api 7.2.0

Wasmer C API library
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
#include "wasm-v8-lowlevel.hh"

// TODO(v8): if we don't include these, api.h does not compile
#include "objects/objects.h"
#include "objects/bigint.h"
#include "objects/managed.h"
#include "objects/module.h"
#include "objects/shared-function-info.h"
#include "objects/templates.h"
#include "objects/fixed-array.h"
#include "objects/ordered-hash-table.h"
#include "objects/js-promise.h"
#include "objects/js-collection.h"

#include "api/api.h"
#include "api/api-inl.h"
#include "wasm/wasm-objects.h"
#include "wasm/wasm-objects-inl.h"
#include "wasm/wasm-serialization.h"


namespace v8 {
namespace wasm {


// Objects

auto object_isolate(v8::Local<v8::Object> obj) -> v8::Isolate* {
  auto v8_obj = v8::Utils::OpenHandle(*obj);
  return reinterpret_cast<v8::Isolate*>(v8_obj->GetIsolate());
}

auto object_isolate(const v8::Persistent<v8::Object>& obj) -> v8::Isolate* {
  struct FakePersistent { v8::Object* val; };
  auto v8_obj = reinterpret_cast<const FakePersistent*>(&obj)->val;
  return v8_obj->GetIsolate();
}

template<class T>
auto object_handle(T v8_obj) -> v8::internal::Handle<T> {
  return handle(v8_obj, v8_obj.GetIsolate());
}


auto object_is_module(v8::Local<v8::Object> obj) -> bool {
  auto v8_obj = v8::Utils::OpenHandle(*obj);
  return v8_obj->IsWasmModuleObject();
}

auto object_is_instance(v8::Local<v8::Object> obj) -> bool {
  auto v8_obj = v8::Utils::OpenHandle(*obj);
  return v8_obj->IsWasmInstanceObject();
}

auto object_is_func(v8::Local<v8::Object> obj) -> bool {
  auto v8_obj = v8::Utils::OpenHandle(*obj);
  return v8::internal::WasmExportedFunction::IsWasmExportedFunction(*v8_obj);
}

auto object_is_global(v8::Local<v8::Object> obj) -> bool {
  auto v8_obj = v8::Utils::OpenHandle(*obj);
  return v8_obj->IsWasmGlobalObject();
}

auto object_is_table(v8::Local<v8::Object> obj) -> bool {
  auto v8_obj = v8::Utils::OpenHandle(*obj);
  return v8_obj->IsWasmTableObject();
}

auto object_is_memory(v8::Local<v8::Object> obj) -> bool {
  auto v8_obj = v8::Utils::OpenHandle(*obj);
  return v8_obj->IsWasmMemoryObject();
}

auto object_is_error(v8::Local<v8::Object> obj) -> bool {
  auto v8_obj = v8::Utils::OpenHandle(*obj);
  return v8_obj->IsJSError();
}



// Foreign pointers

auto foreign_new(v8::Isolate* isolate, void* ptr) -> v8::Local<v8::Value> {
  auto foreign = v8::FromCData(
    reinterpret_cast<v8::internal::Isolate*>(isolate),
    reinterpret_cast<v8::internal::Address>(ptr)
  );
  return v8::Utils::ToLocal(foreign);
}

auto foreign_get(v8::Local<v8::Value> val) -> void* {
  auto foreign = v8::Utils::OpenHandle(*val);
  if (!foreign->IsForeign()) return nullptr;
  auto addr = v8::ToCData<v8::internal::Address>(*foreign);
  return reinterpret_cast<void*>(addr);
}


struct ManagedData {
  ManagedData(void* info, void (*finalizer)(void*)) :
    info(info), finalizer(finalizer) {}

  ~ManagedData() {
    if (finalizer) (*finalizer)(info);
  }

  void* info;
  void (*finalizer)(void*);
};

auto managed_new(v8::Isolate* isolate, void* ptr, void (*finalizer)(void*)) -> v8::Local<v8::Value> {
  assert(ptr);
  auto managed = v8::internal::Managed<ManagedData>::FromUniquePtr(
    reinterpret_cast<v8::internal::Isolate*>(isolate), sizeof(ManagedData),
    std::unique_ptr<ManagedData>(new ManagedData(ptr, finalizer))
  );
  return v8::Utils::ToLocal(managed);
}

auto managed_get(v8::Local<v8::Value> val) -> void* {
  auto v8_val = v8::Utils::OpenHandle(*val);
  if (!v8_val->IsForeign()) return nullptr;
  auto managed =
    v8::internal::Handle<v8::internal::Managed<ManagedData>>::cast(v8_val);
  return managed->raw()->info;
}


// Types

auto v8_valtype_to_wasm(v8::internal::wasm::ValueType v8_valtype) -> val_kind_t {
  switch (v8_valtype) {
    case v8::internal::wasm::kWasmI32: return I32;
    case v8::internal::wasm::kWasmI64: return I64;
    case v8::internal::wasm::kWasmF32: return F32;
    case v8::internal::wasm::kWasmF64: return F64;
    case v8::internal::wasm::kWasmAnyRef: return ANYREF;
    case v8::internal::wasm::kWasmAnyFunc: return FUNCREF;
    default:
      UNREACHABLE();
  }
}

auto func_type_param_arity(v8::Local<v8::Object> function) -> uint32_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(function);
  auto v8_function = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_object);
  v8::internal::wasm::FunctionSig* sig =
    v8_function->instance().module()->functions[v8_function->function_index()].sig;
  return static_cast<uint32_t>(sig->parameter_count());
}

auto func_type_result_arity(v8::Local<v8::Object> function) -> uint32_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(function);
  auto v8_function = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_object);
  v8::internal::wasm::FunctionSig* sig =
    v8_function->instance().module()->functions[v8_function->function_index()].sig;
  return static_cast<uint32_t>(sig->return_count());
}

auto func_type_param(v8::Local<v8::Object> function, size_t i) -> val_kind_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(function);
  auto v8_function = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_object);
  v8::internal::wasm::FunctionSig* sig =
    v8_function->instance().module()->functions[v8_function->function_index()].sig;
  return v8_valtype_to_wasm(sig->GetParam(i));
}

auto func_type_result(v8::Local<v8::Object> function, size_t i) -> val_kind_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(function);
  auto v8_function = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_object);
  v8::internal::wasm::FunctionSig* sig =
    v8_function->instance().module()->functions[v8_function->function_index()].sig;
  return v8_valtype_to_wasm(sig->GetReturn(i));
}

auto global_type_content(v8::Local<v8::Object> global) -> val_kind_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
  auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
  return v8_valtype_to_wasm(v8_global->type());
}

auto global_type_mutable(v8::Local<v8::Object> global) -> bool {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
  auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
  return v8_global->is_mutable();
}

auto table_type_min(v8::Local<v8::Object> table) -> uint32_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
  auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
  return v8_table->current_length();
}

auto table_type_max(v8::Local<v8::Object> table) -> uint32_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
  auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
  auto v8_max_obj = v8_table->maximum_length();
  uint32_t max;
  return v8_max_obj.ToUint32(&max) ? max : 0xffffffffu;
}

auto memory_type_min(v8::Local<v8::Object> memory) -> uint32_t {
  return memory_size(memory);
}

auto memory_type_max(v8::Local<v8::Object> memory) -> uint32_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
  auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
  return v8_memory->has_maximum_pages() ? v8_memory->maximum_pages() : 0xffffffffu;
}


// Modules

auto module_binary_size(v8::Local<v8::Object> module) -> size_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(module);
  auto v8_module = v8::internal::Handle<v8::internal::WasmModuleObject>::cast(v8_object);
  return v8_module->native_module()->wire_bytes().size();
}

auto module_binary(v8::Local<v8::Object> module) -> const char* {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(module);
  auto v8_module = v8::internal::Handle<v8::internal::WasmModuleObject>::cast(v8_object);
  return reinterpret_cast<const char*>(v8_module->native_module()->wire_bytes().begin());
}

auto module_serialize_size(v8::Local<v8::Object> module) -> size_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(module);
  auto v8_module = v8::internal::Handle<v8::internal::WasmModuleObject>::cast(v8_object);
  v8::internal::wasm::WasmSerializer serializer(v8_module->native_module());
  return serializer.GetSerializedNativeModuleSize();
}

auto module_serialize(v8::Local<v8::Object> module, char* buffer, size_t size) -> bool {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(module);
  auto v8_module = v8::internal::Handle<v8::internal::WasmModuleObject>::cast(v8_object);
  v8::internal::wasm::WasmSerializer serializer(v8_module->native_module());
  return serializer.SerializeNativeModule({reinterpret_cast<uint8_t*>(buffer), size});
}

auto module_deserialize(
  v8::Isolate* isolate,
  const char* binary, size_t binary_size,
  const char* buffer, size_t buffer_size
) -> v8::MaybeLocal<v8::Object> {
  auto v8_isolate = reinterpret_cast<v8::internal::Isolate*>(isolate);
  auto maybe_v8_module =
    v8::internal::wasm::DeserializeNativeModule(v8_isolate,
      {reinterpret_cast<const uint8_t*>(buffer), buffer_size},
      {reinterpret_cast<const uint8_t*>(binary), binary_size});
  if (maybe_v8_module.is_null()) return v8::MaybeLocal<v8::Object>();
  auto v8_module = v8::internal::Handle<v8::internal::JSObject>::cast(maybe_v8_module.ToHandleChecked());
  return v8::MaybeLocal<v8::Object>(v8::Utils::ToLocal(v8_module));
}


// Instances

auto instance_module(v8::Local<v8::Object> instance) -> v8::Local<v8::Object> {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(instance);
  auto v8_instance = v8::internal::Handle<v8::internal::WasmInstanceObject>::cast(v8_object);
  auto v8_module = object_handle(v8::internal::JSObject::cast(v8_instance->module_object()));
  return v8::Utils::ToLocal(v8_module);
}

auto instance_exports(v8::Local<v8::Object> instance) -> v8::Local<v8::Object> {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(instance);
  auto v8_instance = v8::internal::Handle<v8::internal::WasmInstanceObject>::cast(v8_object);
  auto v8_exports = object_handle(v8_instance->exports_object());
  return v8::Utils::ToLocal(v8_exports);
}


// Externals

auto extern_kind(v8::Local<v8::Object> external) -> extern_kind_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(external);

  if (v8::internal::WasmExportedFunction::IsWasmExportedFunction(*v8_object)) return EXTERN_FUNC;
  if (v8_object->IsWasmGlobalObject()) return EXTERN_GLOBAL;
  if (v8_object->IsWasmTableObject()) return EXTERN_TABLE;
  if (v8_object->IsWasmMemoryObject()) return EXTERN_MEMORY;
  UNREACHABLE();
}


// Functions

auto func_instance(v8::Local<v8::Function> function) -> v8::Local<v8::Object> {
  auto v8_function = v8::Utils::OpenHandle(*function);
  auto v8_func = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_function);
  auto v8_instance = object_handle(v8::internal::JSObject::cast(v8_func->instance()));
  return v8::Utils::ToLocal(v8_instance);
}


// Globals

auto global_get_i32(v8::Local<v8::Object> global) -> int32_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
  auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
  return v8_global->GetI32();
}
auto global_get_i64(v8::Local<v8::Object> global) -> int64_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
  auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
  return v8_global->GetI64();
}
auto global_get_f32(v8::Local<v8::Object> global) -> float {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
  auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
  return v8_global->GetF32();
}
auto global_get_f64(v8::Local<v8::Object> global) -> double {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
  auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
  return v8_global->GetF64();
}
auto global_get_ref(v8::Local<v8::Object> global) -> v8::Local<v8::Value> {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
  auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
  return v8::Utils::ToLocal(v8_global->GetRef());
}

void global_set_i32(v8::Local<v8::Object> global, int32_t val) {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
  auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
  v8_global->SetI32(val);
}
void global_set_i64(v8::Local<v8::Object> global, int64_t val) {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
  auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
  v8_global->SetI64(val);
}
void global_set_f32(v8::Local<v8::Object> global, float val) {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
  auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
  v8_global->SetF32(val);
}
void global_set_f64(v8::Local<v8::Object> global, double val) {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
  auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
  v8_global->SetF64(val);
}
void global_set_ref(v8::Local<v8::Object> global, v8::Local<v8::Value> val) {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
  auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
  v8_global->SetAnyRef(v8::Utils::OpenHandle<v8::Value, v8::internal::Object>(val));
}


// Tables

auto table_get(v8::Local<v8::Object> table, size_t index) -> v8::MaybeLocal<v8::Value> {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
  auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
  // TODO(v8): This should happen in WasmTableObject::Get.
  if (index > v8_table->current_length()) return v8::MaybeLocal<v8::Value>();

  v8::internal::Handle<v8::internal::Object> v8_value =
    v8::internal::WasmTableObject::Get(
      v8_table->GetIsolate(), v8_table, static_cast<uint32_t>(index));
  return v8::Utils::ToLocal(v8::internal::Handle<v8::internal::Object>::cast(v8_value));
}

auto table_set(
  v8::Local<v8::Object> table, size_t index, v8::Local<v8::Value> value
) -> bool {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
  auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
  auto v8_value = v8::Utils::OpenHandle<v8::Value, v8::internal::Object>(value);
  // TODO(v8): This should happen in WasmTableObject::Set.
  if (index >= v8_table->current_length()) return false;

  { v8::TryCatch handler(table->GetIsolate());
    v8::internal::WasmTableObject::Set(v8_table->GetIsolate(), v8_table,
      static_cast<uint32_t>(index), v8_value);
    if (handler.HasCaught()) return false;
  }

  return true;
}

auto table_size(v8::Local<v8::Object> table) -> size_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
  auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
  return v8_table->current_length();
}

auto table_grow(
  v8::Local<v8::Object> table, size_t delta, v8::Local<v8::Value> init
) -> bool {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
  auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
  if (delta > 0xfffffffflu) return false;
  auto old_size = v8_table->current_length();
  auto new_size = old_size + static_cast<uint32_t>(delta);
  // TODO(v8): This should happen in WasmTableObject::Grow.
  if (new_size > table_type_max(table)) return false;

  { v8::TryCatch handler(table->GetIsolate());
    v8::internal::WasmTableObject::Grow(
      v8_table->GetIsolate(), v8_table, static_cast<uint32_t>(delta),
      v8::Utils::OpenHandle<v8::Value, v8::internal::Object>(init));
    if (handler.HasCaught()) return false;
  }

  return true;
}


// Memory

auto memory_data(v8::Local<v8::Object> memory) -> char* {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
  auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
  return reinterpret_cast<char*>(v8_memory->array_buffer().backing_store());
}

auto memory_data_size(v8::Local<v8::Object> memory)-> size_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
  auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
  return v8_memory->array_buffer().byte_length();
}

auto memory_size(v8::Local<v8::Object> memory) -> uint32_t {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
  auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
  return static_cast<uint32_t>(
    v8_memory->array_buffer().byte_length() / v8::internal::wasm::kWasmPageSize);
}

auto memory_grow(v8::Local<v8::Object> memory, uint32_t delta) -> bool {
  auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
  auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
  auto old = v8::internal::WasmMemoryObject::Grow(
    v8_memory->GetIsolate(), v8_memory, delta);
  return old != -1;
}

}  // namespace wasm
}  // namespace v8