d00f48e198d7b60b6134263d55922c092091749e
[platform/framework/web/lwnode.git] /
1 #include "wasm-v8-lowlevel.hh"
2
3 // TODO(v8): if we don't include these, api.h does not compile
4 #include "objects/objects.h"
5 #include "objects/bigint.h"
6 #include "objects/managed.h"
7 #include "objects/module.h"
8 #include "objects/shared-function-info.h"
9 #include "objects/templates.h"
10 #include "objects/fixed-array.h"
11 #include "objects/ordered-hash-table.h"
12 #include "objects/js-promise.h"
13 #include "objects/js-collection.h"
14
15 #include "api/api.h"
16 #include "api/api-inl.h"
17 #include "wasm/wasm-objects.h"
18 #include "wasm/wasm-objects-inl.h"
19 #include "wasm/wasm-serialization.h"
20
21
22 namespace v8 {
23 namespace wasm {
24
25
26 // Objects
27
28 auto object_isolate(v8::Local<v8::Object> obj) -> v8::Isolate* {
29   auto v8_obj = v8::Utils::OpenHandle(*obj);
30   return reinterpret_cast<v8::Isolate*>(v8_obj->GetIsolate());
31 }
32
33 auto object_isolate(const v8::Persistent<v8::Object>& obj) -> v8::Isolate* {
34   struct FakePersistent { v8::Object* val; };
35   auto v8_obj = reinterpret_cast<const FakePersistent*>(&obj)->val;
36   return v8_obj->GetIsolate();
37 }
38
39 template<class T>
40 auto object_handle(T v8_obj) -> v8::internal::Handle<T> {
41   return handle(v8_obj, v8_obj.GetIsolate());
42 }
43
44
45 auto object_is_module(v8::Local<v8::Object> obj) -> bool {
46   auto v8_obj = v8::Utils::OpenHandle(*obj);
47   return v8_obj->IsWasmModuleObject();
48 }
49
50 auto object_is_instance(v8::Local<v8::Object> obj) -> bool {
51   auto v8_obj = v8::Utils::OpenHandle(*obj);
52   return v8_obj->IsWasmInstanceObject();
53 }
54
55 auto object_is_func(v8::Local<v8::Object> obj) -> bool {
56   auto v8_obj = v8::Utils::OpenHandle(*obj);
57   return v8::internal::WasmExportedFunction::IsWasmExportedFunction(*v8_obj);
58 }
59
60 auto object_is_global(v8::Local<v8::Object> obj) -> bool {
61   auto v8_obj = v8::Utils::OpenHandle(*obj);
62   return v8_obj->IsWasmGlobalObject();
63 }
64
65 auto object_is_table(v8::Local<v8::Object> obj) -> bool {
66   auto v8_obj = v8::Utils::OpenHandle(*obj);
67   return v8_obj->IsWasmTableObject();
68 }
69
70 auto object_is_memory(v8::Local<v8::Object> obj) -> bool {
71   auto v8_obj = v8::Utils::OpenHandle(*obj);
72   return v8_obj->IsWasmMemoryObject();
73 }
74
75 auto object_is_error(v8::Local<v8::Object> obj) -> bool {
76   auto v8_obj = v8::Utils::OpenHandle(*obj);
77   return v8_obj->IsJSError();
78 }
79
80
81
82 // Foreign pointers
83
84 auto foreign_new(v8::Isolate* isolate, void* ptr) -> v8::Local<v8::Value> {
85   auto foreign = v8::FromCData(
86     reinterpret_cast<v8::internal::Isolate*>(isolate),
87     reinterpret_cast<v8::internal::Address>(ptr)
88   );
89   return v8::Utils::ToLocal(foreign);
90 }
91
92 auto foreign_get(v8::Local<v8::Value> val) -> void* {
93   auto foreign = v8::Utils::OpenHandle(*val);
94   if (!foreign->IsForeign()) return nullptr;
95   auto addr = v8::ToCData<v8::internal::Address>(*foreign);
96   return reinterpret_cast<void*>(addr);
97 }
98
99
100 struct ManagedData {
101   ManagedData(void* info, void (*finalizer)(void*)) :
102     info(info), finalizer(finalizer) {}
103
104   ~ManagedData() {
105     if (finalizer) (*finalizer)(info);
106   }
107
108   void* info;
109   void (*finalizer)(void*);
110 };
111
112 auto managed_new(v8::Isolate* isolate, void* ptr, void (*finalizer)(void*)) -> v8::Local<v8::Value> {
113   assert(ptr);
114   auto managed = v8::internal::Managed<ManagedData>::FromUniquePtr(
115     reinterpret_cast<v8::internal::Isolate*>(isolate), sizeof(ManagedData),
116     std::unique_ptr<ManagedData>(new ManagedData(ptr, finalizer))
117   );
118   return v8::Utils::ToLocal(managed);
119 }
120
121 auto managed_get(v8::Local<v8::Value> val) -> void* {
122   auto v8_val = v8::Utils::OpenHandle(*val);
123   if (!v8_val->IsForeign()) return nullptr;
124   auto managed =
125     v8::internal::Handle<v8::internal::Managed<ManagedData>>::cast(v8_val);
126   return managed->raw()->info;
127 }
128
129
130 // Types
131
132 auto v8_valtype_to_wasm(v8::internal::wasm::ValueType v8_valtype) -> val_kind_t {
133   switch (v8_valtype) {
134     case v8::internal::wasm::kWasmI32: return I32;
135     case v8::internal::wasm::kWasmI64: return I64;
136     case v8::internal::wasm::kWasmF32: return F32;
137     case v8::internal::wasm::kWasmF64: return F64;
138     case v8::internal::wasm::kWasmAnyRef: return ANYREF;
139     case v8::internal::wasm::kWasmAnyFunc: return FUNCREF;
140     default:
141       UNREACHABLE();
142   }
143 }
144
145 auto func_type_param_arity(v8::Local<v8::Object> function) -> uint32_t {
146   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(function);
147   auto v8_function = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_object);
148   v8::internal::wasm::FunctionSig* sig =
149     v8_function->instance().module()->functions[v8_function->function_index()].sig;
150   return static_cast<uint32_t>(sig->parameter_count());
151 }
152
153 auto func_type_result_arity(v8::Local<v8::Object> function) -> uint32_t {
154   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(function);
155   auto v8_function = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_object);
156   v8::internal::wasm::FunctionSig* sig =
157     v8_function->instance().module()->functions[v8_function->function_index()].sig;
158   return static_cast<uint32_t>(sig->return_count());
159 }
160
161 auto func_type_param(v8::Local<v8::Object> function, size_t i) -> val_kind_t {
162   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(function);
163   auto v8_function = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_object);
164   v8::internal::wasm::FunctionSig* sig =
165     v8_function->instance().module()->functions[v8_function->function_index()].sig;
166   return v8_valtype_to_wasm(sig->GetParam(i));
167 }
168
169 auto func_type_result(v8::Local<v8::Object> function, size_t i) -> val_kind_t {
170   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(function);
171   auto v8_function = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_object);
172   v8::internal::wasm::FunctionSig* sig =
173     v8_function->instance().module()->functions[v8_function->function_index()].sig;
174   return v8_valtype_to_wasm(sig->GetReturn(i));
175 }
176
177 auto global_type_content(v8::Local<v8::Object> global) -> val_kind_t {
178   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
179   auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
180   return v8_valtype_to_wasm(v8_global->type());
181 }
182
183 auto global_type_mutable(v8::Local<v8::Object> global) -> bool {
184   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
185   auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
186   return v8_global->is_mutable();
187 }
188
189 auto table_type_min(v8::Local<v8::Object> table) -> uint32_t {
190   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
191   auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
192   return v8_table->current_length();
193 }
194
195 auto table_type_max(v8::Local<v8::Object> table) -> uint32_t {
196   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
197   auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
198   auto v8_max_obj = v8_table->maximum_length();
199   uint32_t max;
200   return v8_max_obj.ToUint32(&max) ? max : 0xffffffffu;
201 }
202
203 auto memory_type_min(v8::Local<v8::Object> memory) -> uint32_t {
204   return memory_size(memory);
205 }
206
207 auto memory_type_max(v8::Local<v8::Object> memory) -> uint32_t {
208   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
209   auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
210   return v8_memory->has_maximum_pages() ? v8_memory->maximum_pages() : 0xffffffffu;
211 }
212
213
214 // Modules
215
216 auto module_binary_size(v8::Local<v8::Object> module) -> size_t {
217   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(module);
218   auto v8_module = v8::internal::Handle<v8::internal::WasmModuleObject>::cast(v8_object);
219   return v8_module->native_module()->wire_bytes().size();
220 }
221
222 auto module_binary(v8::Local<v8::Object> module) -> const char* {
223   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(module);
224   auto v8_module = v8::internal::Handle<v8::internal::WasmModuleObject>::cast(v8_object);
225   return reinterpret_cast<const char*>(v8_module->native_module()->wire_bytes().begin());
226 }
227
228 auto module_serialize_size(v8::Local<v8::Object> module) -> size_t {
229   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(module);
230   auto v8_module = v8::internal::Handle<v8::internal::WasmModuleObject>::cast(v8_object);
231   v8::internal::wasm::WasmSerializer serializer(v8_module->native_module());
232   return serializer.GetSerializedNativeModuleSize();
233 }
234
235 auto module_serialize(v8::Local<v8::Object> module, char* buffer, size_t size) -> bool {
236   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(module);
237   auto v8_module = v8::internal::Handle<v8::internal::WasmModuleObject>::cast(v8_object);
238   v8::internal::wasm::WasmSerializer serializer(v8_module->native_module());
239   return serializer.SerializeNativeModule({reinterpret_cast<uint8_t*>(buffer), size});
240 }
241
242 auto module_deserialize(
243   v8::Isolate* isolate,
244   const char* binary, size_t binary_size,
245   const char* buffer, size_t buffer_size
246 ) -> v8::MaybeLocal<v8::Object> {
247   auto v8_isolate = reinterpret_cast<v8::internal::Isolate*>(isolate);
248   auto maybe_v8_module =
249     v8::internal::wasm::DeserializeNativeModule(v8_isolate,
250       {reinterpret_cast<const uint8_t*>(buffer), buffer_size},
251       {reinterpret_cast<const uint8_t*>(binary), binary_size});
252   if (maybe_v8_module.is_null()) return v8::MaybeLocal<v8::Object>();
253   auto v8_module = v8::internal::Handle<v8::internal::JSObject>::cast(maybe_v8_module.ToHandleChecked());
254   return v8::MaybeLocal<v8::Object>(v8::Utils::ToLocal(v8_module));
255 }
256
257
258 // Instances
259
260 auto instance_module(v8::Local<v8::Object> instance) -> v8::Local<v8::Object> {
261   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(instance);
262   auto v8_instance = v8::internal::Handle<v8::internal::WasmInstanceObject>::cast(v8_object);
263   auto v8_module = object_handle(v8::internal::JSObject::cast(v8_instance->module_object()));
264   return v8::Utils::ToLocal(v8_module);
265 }
266
267 auto instance_exports(v8::Local<v8::Object> instance) -> v8::Local<v8::Object> {
268   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(instance);
269   auto v8_instance = v8::internal::Handle<v8::internal::WasmInstanceObject>::cast(v8_object);
270   auto v8_exports = object_handle(v8_instance->exports_object());
271   return v8::Utils::ToLocal(v8_exports);
272 }
273
274
275 // Externals
276
277 auto extern_kind(v8::Local<v8::Object> external) -> extern_kind_t {
278   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(external);
279
280   if (v8::internal::WasmExportedFunction::IsWasmExportedFunction(*v8_object)) return EXTERN_FUNC;
281   if (v8_object->IsWasmGlobalObject()) return EXTERN_GLOBAL;
282   if (v8_object->IsWasmTableObject()) return EXTERN_TABLE;
283   if (v8_object->IsWasmMemoryObject()) return EXTERN_MEMORY;
284   UNREACHABLE();
285 }
286
287
288 // Functions
289
290 auto func_instance(v8::Local<v8::Function> function) -> v8::Local<v8::Object> {
291   auto v8_function = v8::Utils::OpenHandle(*function);
292   auto v8_func = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_function);
293   auto v8_instance = object_handle(v8::internal::JSObject::cast(v8_func->instance()));
294   return v8::Utils::ToLocal(v8_instance);
295 }
296
297
298 // Globals
299
300 auto global_get_i32(v8::Local<v8::Object> global) -> int32_t {
301   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
302   auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
303   return v8_global->GetI32();
304 }
305 auto global_get_i64(v8::Local<v8::Object> global) -> int64_t {
306   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
307   auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
308   return v8_global->GetI64();
309 }
310 auto global_get_f32(v8::Local<v8::Object> global) -> float {
311   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
312   auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
313   return v8_global->GetF32();
314 }
315 auto global_get_f64(v8::Local<v8::Object> global) -> double {
316   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
317   auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
318   return v8_global->GetF64();
319 }
320 auto global_get_ref(v8::Local<v8::Object> global) -> v8::Local<v8::Value> {
321   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
322   auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
323   return v8::Utils::ToLocal(v8_global->GetRef());
324 }
325
326 void global_set_i32(v8::Local<v8::Object> global, int32_t val) {
327   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
328   auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
329   v8_global->SetI32(val);
330 }
331 void global_set_i64(v8::Local<v8::Object> global, int64_t val) {
332   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
333   auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
334   v8_global->SetI64(val);
335 }
336 void global_set_f32(v8::Local<v8::Object> global, float val) {
337   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
338   auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
339   v8_global->SetF32(val);
340 }
341 void global_set_f64(v8::Local<v8::Object> global, double val) {
342   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
343   auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
344   v8_global->SetF64(val);
345 }
346 void global_set_ref(v8::Local<v8::Object> global, v8::Local<v8::Value> val) {
347   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
348   auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
349   v8_global->SetAnyRef(v8::Utils::OpenHandle<v8::Value, v8::internal::Object>(val));
350 }
351
352
353 // Tables
354
355 auto table_get(v8::Local<v8::Object> table, size_t index) -> v8::MaybeLocal<v8::Value> {
356   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
357   auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
358   // TODO(v8): This should happen in WasmTableObject::Get.
359   if (index > v8_table->current_length()) return v8::MaybeLocal<v8::Value>();
360
361   v8::internal::Handle<v8::internal::Object> v8_value =
362     v8::internal::WasmTableObject::Get(
363       v8_table->GetIsolate(), v8_table, static_cast<uint32_t>(index));
364   return v8::Utils::ToLocal(v8::internal::Handle<v8::internal::Object>::cast(v8_value));
365 }
366
367 auto table_set(
368   v8::Local<v8::Object> table, size_t index, v8::Local<v8::Value> value
369 ) -> bool {
370   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
371   auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
372   auto v8_value = v8::Utils::OpenHandle<v8::Value, v8::internal::Object>(value);
373   // TODO(v8): This should happen in WasmTableObject::Set.
374   if (index >= v8_table->current_length()) return false;
375
376   { v8::TryCatch handler(table->GetIsolate());
377     v8::internal::WasmTableObject::Set(v8_table->GetIsolate(), v8_table,
378       static_cast<uint32_t>(index), v8_value);
379     if (handler.HasCaught()) return false;
380   }
381
382   return true;
383 }
384
385 auto table_size(v8::Local<v8::Object> table) -> size_t {
386   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
387   auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
388   return v8_table->current_length();
389 }
390
391 auto table_grow(
392   v8::Local<v8::Object> table, size_t delta, v8::Local<v8::Value> init
393 ) -> bool {
394   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
395   auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
396   if (delta > 0xfffffffflu) return false;
397   auto old_size = v8_table->current_length();
398   auto new_size = old_size + static_cast<uint32_t>(delta);
399   // TODO(v8): This should happen in WasmTableObject::Grow.
400   if (new_size > table_type_max(table)) return false;
401
402   { v8::TryCatch handler(table->GetIsolate());
403     v8::internal::WasmTableObject::Grow(
404       v8_table->GetIsolate(), v8_table, static_cast<uint32_t>(delta),
405       v8::Utils::OpenHandle<v8::Value, v8::internal::Object>(init));
406     if (handler.HasCaught()) return false;
407   }
408
409   return true;
410 }
411
412
413 // Memory
414
415 auto memory_data(v8::Local<v8::Object> memory) -> char* {
416   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
417   auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
418   return reinterpret_cast<char*>(v8_memory->array_buffer().backing_store());
419 }
420
421 auto memory_data_size(v8::Local<v8::Object> memory)-> size_t {
422   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
423   auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
424   return v8_memory->array_buffer().byte_length();
425 }
426
427 auto memory_size(v8::Local<v8::Object> memory) -> uint32_t {
428   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
429   auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
430   return static_cast<uint32_t>(
431     v8_memory->array_buffer().byte_length() / v8::internal::wasm::kWasmPageSize);
432 }
433
434 auto memory_grow(v8::Local<v8::Object> memory, uint32_t delta) -> bool {
435   auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
436   auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
437   auto old = v8::internal::WasmMemoryObject::Grow(
438     v8_memory->GetIsolate(), v8_memory, delta);
439   return old != -1;
440 }
441
442 }  // namespace wasm
443 }  // namespace v8