diff options
Diffstat (limited to 'deps/v8/src/wasm/wasm-js.cc')
-rw-r--r-- | deps/v8/src/wasm/wasm-js.cc | 475 |
1 files changed, 262 insertions, 213 deletions
diff --git a/deps/v8/src/wasm/wasm-js.cc b/deps/v8/src/wasm/wasm-js.cc index 254fd7061a..0e030a28c4 100644 --- a/deps/v8/src/wasm/wasm-js.cc +++ b/deps/v8/src/wasm/wasm-js.cc @@ -19,6 +19,7 @@ #include "src/wasm/module-decoder.h" #include "src/wasm/wasm-js.h" #include "src/wasm/wasm-module.h" +#include "src/wasm/wasm-objects.h" #include "src/wasm/wasm-result.h" typedef uint8_t byte; @@ -27,6 +28,12 @@ using v8::internal::wasm::ErrorThrower; namespace v8 { +enum WasmMemoryObjectData { + kWasmMemoryBuffer, + kWasmMemoryMaximum, + kWasmMemoryInstanceObject +}; + namespace { i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) { return isolate->factory()->NewStringFromAsciiChecked(str); @@ -55,7 +62,7 @@ RawBuffer GetRawBufferSource( end = start + contents.ByteLength(); if (start == nullptr || end == start) { - thrower->Error("ArrayBuffer argument is empty"); + thrower->CompileError("ArrayBuffer argument is empty"); } } else if (source->IsTypedArray()) { // A TypedArray was passed. @@ -69,132 +76,28 @@ RawBuffer GetRawBufferSource( end = start + array->ByteLength(); if (start == nullptr || end == start) { - thrower->Error("ArrayBuffer argument is empty"); + thrower->TypeError("ArrayBuffer argument is empty"); } } else { - thrower->Error("Argument 0 must be an ArrayBuffer or Uint8Array"); + thrower->TypeError("Argument 0 must be an ArrayBuffer or Uint8Array"); } return {start, end}; } -void VerifyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { - HandleScope scope(args.GetIsolate()); - i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); - ErrorThrower thrower(isolate, "Wasm.verifyModule()"); - - if (args.Length() < 1) { - thrower.TypeError("Argument 0 must be a buffer source"); - return; - } - RawBuffer buffer = GetRawBufferSource(args[0], &thrower); - if (thrower.error()) return; - - i::Zone zone(isolate->allocator()); - internal::wasm::ModuleResult result = - internal::wasm::DecodeWasmModule(isolate, &zone, buffer.start, buffer.end, - true, internal::wasm::kWasmOrigin); - - if (result.failed()) { - thrower.Failed("", result); - } - - if (result.val) delete result.val; -} - -void VerifyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) { - HandleScope scope(args.GetIsolate()); - i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); - ErrorThrower thrower(isolate, "Wasm.verifyFunction()"); - - if (args.Length() < 1) { - thrower.TypeError("Argument 0 must be a buffer source"); - return; - } - RawBuffer buffer = GetRawBufferSource(args[0], &thrower); - if (thrower.error()) return; - - internal::wasm::FunctionResult result; - { - // Verification of a single function shouldn't allocate. - i::DisallowHeapAllocation no_allocation; - i::Zone zone(isolate->allocator()); - result = internal::wasm::DecodeWasmFunction(isolate, &zone, nullptr, - buffer.start, buffer.end); - } - - if (result.failed()) { - thrower.Failed("", result); - } - - if (result.val) delete result.val; -} - -i::MaybeHandle<i::JSObject> InstantiateModule( - const v8::FunctionCallbackInfo<v8::Value>& args, const byte* start, - const byte* end, ErrorThrower* thrower, - internal::wasm::ModuleOrigin origin = i::wasm::kWasmOrigin) { - i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); - - // Decode but avoid a redundant pass over function bodies for verification. - // Verification will happen during compilation. - i::Zone zone(isolate->allocator()); - i::MaybeHandle<i::JSObject> module_object = - i::wasm::CreateModuleObjectFromBytes(isolate, start, end, thrower, - origin); - i::MaybeHandle<i::JSObject> object; - if (!module_object.is_null()) { - // Success. Instantiate the module and return the object. - i::Handle<i::JSObject> ffi = i::Handle<i::JSObject>::null(); - if (args.Length() > 1 && args[1]->IsObject()) { - Local<Object> obj = Local<Object>::Cast(args[1]); - ffi = i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj)); - } - - i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); - if (args.Length() > 2 && args[2]->IsArrayBuffer()) { - Local<Object> obj = Local<Object>::Cast(args[2]); - i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj); - memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj)); - } - - object = i::wasm::WasmModule::Instantiate( - isolate, thrower, module_object.ToHandleChecked(), ffi, memory); - if (!object.is_null()) { - args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked())); - } - } - return object; -} - -void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) { - HandleScope scope(args.GetIsolate()); - i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); - ErrorThrower thrower(isolate, "Wasm.instantiateModule()"); - - if (args.Length() < 1) { - thrower.TypeError("Argument 0 must be a buffer source"); - return; - } - RawBuffer buffer = GetRawBufferSource(args[0], &thrower); - if (buffer.start == nullptr) return; - - InstantiateModule(args, buffer.start, buffer.end, &thrower); -} - -static i::MaybeHandle<i::JSObject> CreateModuleObject( +static i::MaybeHandle<i::WasmModuleObject> CreateModuleObject( v8::Isolate* isolate, const v8::Local<v8::Value> source, ErrorThrower* thrower) { i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); i::MaybeHandle<i::JSObject> nothing; RawBuffer buffer = GetRawBufferSource(source, thrower); - if (buffer.start == nullptr) return i::MaybeHandle<i::JSObject>(); + if (buffer.start == nullptr) return i::MaybeHandle<i::WasmModuleObject>(); DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); return i::wasm::CreateModuleObjectFromBytes( - i_isolate, buffer.start, buffer.end, thrower, - i::wasm::ModuleOrigin::kWasmOrigin); + i_isolate, buffer.start, buffer.end, thrower, i::wasm::kWasmOrigin, + i::Handle<i::Script>::null(), nullptr, nullptr); } static bool ValidateModule(v8::Isolate* isolate, @@ -212,8 +115,8 @@ static bool ValidateModule(v8::Isolate* isolate, i::wasm::ModuleOrigin::kWasmOrigin); } -bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, - i::Handle<i::Symbol> sym, const char* msg) { +static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, + i::Handle<i::Symbol> sym, const char* msg) { if (value->IsJSObject()) { i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); @@ -308,14 +211,8 @@ void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { } Local<Object> obj = Local<Object>::Cast(args[0]); - - i::Handle<i::JSObject> module_obj = + i::Handle<i::JSObject> i_obj = i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj)); - if (module_obj->GetInternalFieldCount() < 1 || - !module_obj->GetInternalField(0)->IsFixedArray()) { - thrower.TypeError("Argument 0 is an invalid WebAssembly.Module"); - return; - } i::Handle<i::JSReceiver> ffi = i::Handle<i::JSObject>::null(); if (args.Length() > 1 && args[1]->IsObject()) { @@ -324,17 +221,24 @@ void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { } i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); - if (args.Length() > 2 && args[2]->IsArrayBuffer()) { + if (args.Length() > 2 && args[2]->IsObject()) { Local<Object> obj = Local<Object>::Cast(args[2]); i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj); - memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj)); + if (i::WasmJs::IsWasmMemoryObject(i_isolate, mem_obj)) { + memory = i::Handle<i::JSArrayBuffer>( + i::Handle<i::WasmMemoryObject>::cast(mem_obj)->get_buffer(), + i_isolate); + } else { + thrower.TypeError("Argument 2 must be a WebAssembly.Memory"); + } } - i::MaybeHandle<i::JSObject> instance = i::wasm::WasmModule::Instantiate( - i_isolate, &thrower, module_obj, ffi, memory); + i::MaybeHandle<i::JSObject> instance = + i::wasm::WasmModule::Instantiate(i_isolate, &thrower, i_obj, ffi, memory); if (instance.is_null()) { - if (!thrower.error()) thrower.Error("Could not instantiate module"); + if (!thrower.error()) thrower.RuntimeError("Could not instantiate module"); return; } + DCHECK(!i_isolate->has_pending_exception()); v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); return_value.Set(Utils::ToLocal(instance.ToHandleChecked())); } @@ -366,6 +270,8 @@ bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, return false; } +const int max_table_size = 1 << 26; + void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { v8::Isolate* isolate = args.GetIsolate(); HandleScope scope(isolate); @@ -392,7 +298,6 @@ void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { return; } } - const int max_table_size = 1 << 26; // The descriptor's 'initial'. int initial; if (!GetIntegerProperty(isolate, &thrower, context, descriptor, @@ -414,24 +319,14 @@ void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { &maximum, initial, max_table_size)) { return; } + } else { + maximum = static_cast<int>(i::wasm::WasmModule::kV8MaxTableSize); } i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); - i::Handle<i::JSFunction> table_ctor( - i_isolate->native_context()->wasm_table_constructor()); + i::Handle<i::FixedArray> fixed_array; i::Handle<i::JSObject> table_obj = - i_isolate->factory()->NewJSObject(table_ctor); - i::Handle<i::FixedArray> fixed_array = - i_isolate->factory()->NewFixedArray(initial); - i::Object* null = i_isolate->heap()->null_value(); - for (int i = 0; i < initial; ++i) fixed_array->set(i, null); - table_obj->SetInternalField(0, *fixed_array); - table_obj->SetInternalField( - 1, has_maximum.FromJust() - ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) - : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); - i::Handle<i::Symbol> table_sym(i_isolate->native_context()->wasm_table_sym()); - i::Object::SetProperty(table_obj, table_sym, table_obj, i::STRICT).Check(); + i::WasmTableObject::New(i_isolate, initial, maximum, &fixed_array); v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); return_value.Set(Utils::ToLocal(table_obj)); } @@ -442,7 +337,7 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), "WebAssembly.Module()"); if (args.Length() < 1 || !args[0]->IsObject()) { - thrower.TypeError("Argument 0 must be a table descriptor"); + thrower.TypeError("Argument 0 must be a memory descriptor"); return; } Local<Context> context = isolate->GetCurrentContext(); @@ -475,27 +370,196 @@ void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { static_cast<size_t>(initial); i::JSArrayBuffer::SetupAllocatingData(buffer, i_isolate, size); - i::Handle<i::JSObject> memory_obj = i::WasmJs::CreateWasmMemoryObject( - i_isolate, buffer, has_maximum.FromJust(), maximum); - v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); - return_value.Set(Utils::ToLocal(memory_obj)); + i::Handle<i::JSObject> memory_obj = i::WasmMemoryObject::New( + i_isolate, buffer, has_maximum.FromJust() ? maximum : -1); + args.GetReturnValue().Set(Utils::ToLocal(memory_obj)); } + void WebAssemblyTableGetLength( const v8::FunctionCallbackInfo<v8::Value>& args) { - // TODO(rossberg) + v8::Isolate* isolate = args.GetIsolate(); + Local<Context> context = isolate->GetCurrentContext(); + i::Handle<i::Context> i_context = Utils::OpenHandle(*context); + if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), + i::Handle<i::Symbol>(i_context->wasm_table_sym()), + "Receiver is not a WebAssembly.Table")) { + return; + } + auto receiver = + i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); + args.GetReturnValue().Set( + v8::Number::New(isolate, receiver->current_length())); } + void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { - // TODO(rossberg) + v8::Isolate* isolate = args.GetIsolate(); + Local<Context> context = isolate->GetCurrentContext(); + i::Handle<i::Context> i_context = Utils::OpenHandle(*context); + if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), + i::Handle<i::Symbol>(i_context->wasm_table_sym()), + "Receiver is not a WebAssembly.Table")) { + return; + } + + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + auto receiver = + i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); + i::Handle<i::FixedArray> old_array(receiver->get_functions(), i_isolate); + int old_size = old_array->length(); + int64_t new_size64 = 0; + if (args.Length() > 0 && !args[0]->IntegerValue(context).To(&new_size64)) { + return; + } + new_size64 += old_size; + + if (new_size64 < old_size || new_size64 > receiver->maximum_length()) { + v8::Local<v8::Value> e = v8::Exception::RangeError( + v8_str(isolate, new_size64 < old_size ? "trying to shrink table" + : "maximum table size exceeded")); + isolate->ThrowException(e); + return; + } + int new_size = static_cast<int>(new_size64); + + if (new_size != old_size) { + i::Handle<i::FixedArray> new_array = + i_isolate->factory()->NewFixedArray(new_size); + for (int i = 0; i < old_size; ++i) new_array->set(i, old_array->get(i)); + i::Object* null = i_isolate->heap()->null_value(); + for (int i = old_size; i < new_size; ++i) new_array->set(i, null); + receiver->set_functions(*new_array); + } + + // TODO(titzer): update relevant instances. } + void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) { - // TODO(rossberg) + v8::Isolate* isolate = args.GetIsolate(); + Local<Context> context = isolate->GetCurrentContext(); + i::Handle<i::Context> i_context = Utils::OpenHandle(*context); + if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), + i::Handle<i::Symbol>(i_context->wasm_table_sym()), + "Receiver is not a WebAssembly.Table")) { + return; + } + + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + auto receiver = + i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); + i::Handle<i::FixedArray> array(receiver->get_functions(), i_isolate); + int i = 0; + if (args.Length() > 0 && !args[0]->Int32Value(context).To(&i)) return; + v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); + if (i < 0 || i >= array->length()) { + v8::Local<v8::Value> e = + v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); + isolate->ThrowException(e); + return; + } + + i::Handle<i::Object> value(array->get(i), i_isolate); + return_value.Set(Utils::ToLocal(value)); } + void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) { - // TODO(rossberg) + v8::Isolate* isolate = args.GetIsolate(); + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + Local<Context> context = isolate->GetCurrentContext(); + i::Handle<i::Context> i_context = Utils::OpenHandle(*context); + if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), + i::Handle<i::Symbol>(i_context->wasm_table_sym()), + "Receiver is not a WebAssembly.Table")) { + return; + } + if (args.Length() < 2) { + v8::Local<v8::Value> e = v8::Exception::TypeError( + v8_str(isolate, "Argument 1 must be null or a function")); + isolate->ThrowException(e); + return; + } + i::Handle<i::Object> value = Utils::OpenHandle(*args[1]); + if (!value->IsNull(i_isolate) && + (!value->IsJSFunction() || + i::Handle<i::JSFunction>::cast(value)->code()->kind() != + i::Code::JS_TO_WASM_FUNCTION)) { + v8::Local<v8::Value> e = v8::Exception::TypeError( + v8_str(isolate, "Argument 1 must be null or a WebAssembly function")); + isolate->ThrowException(e); + return; + } + + auto receiver = + i::Handle<i::WasmTableObject>::cast(Utils::OpenHandle(*args.This())); + i::Handle<i::FixedArray> array(receiver->get_functions(), i_isolate); + int i; + if (!args[0]->Int32Value(context).To(&i)) return; + if (i < 0 || i >= array->length()) { + v8::Local<v8::Value> e = + v8::Exception::RangeError(v8_str(isolate, "index out of bounds")); + isolate->ThrowException(e); + return; + } + + i::Handle<i::FixedArray> dispatch_tables(receiver->get_dispatch_tables(), + i_isolate); + if (value->IsNull(i_isolate)) { + i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i, + i::Handle<i::JSFunction>::null()); + } else { + i::wasm::UpdateDispatchTables(i_isolate, dispatch_tables, i, + i::Handle<i::JSFunction>::cast(value)); + } + + i::Handle<i::FixedArray>::cast(array)->set(i, *value); } + void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { - // TODO(rossberg) + v8::Isolate* isolate = args.GetIsolate(); + Local<Context> context = isolate->GetCurrentContext(); + i::Handle<i::Context> i_context = Utils::OpenHandle(*context); + if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), + i::Handle<i::Symbol>(i_context->wasm_memory_sym()), + "Receiver is not a WebAssembly.Memory")) { + return; + } + if (args.Length() < 1) { + v8::Local<v8::Value> e = v8::Exception::TypeError( + v8_str(isolate, "Argument 0 required, must be numeric value of pages")); + isolate->ThrowException(e); + return; + } + + uint32_t delta = args[0]->Uint32Value(context).FromJust(); + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + i::Handle<i::JSObject> receiver = + i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This())); + i::Handle<i::Object> instance_object( + receiver->GetInternalField(kWasmMemoryInstanceObject), i_isolate); + i::Handle<i::JSObject> instance( + i::Handle<i::JSObject>::cast(instance_object)); + + // TODO(gdeepti) Implement growing memory when shared by different + // instances. + int32_t ret = internal::wasm::GrowInstanceMemory(i_isolate, instance, delta); + if (ret == -1) { + v8::Local<v8::Value> e = v8::Exception::Error( + v8_str(isolate, "Unable to grow instance memory.")); + isolate->ThrowException(e); + return; + } + i::MaybeHandle<i::JSArrayBuffer> buffer = + internal::wasm::GetInstanceMemory(i_isolate, instance); + if (buffer.is_null()) { + v8::Local<v8::Value> e = v8::Exception::Error( + v8_str(isolate, "WebAssembly.Memory buffer object not set.")); + isolate->ThrowException(e); + return; + } + receiver->SetInternalField(kWasmMemoryBuffer, *buffer.ToHandleChecked()); + v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); + return_value.Set(ret); } + void WebAssemblyMemoryGetBuffer( const v8::FunctionCallbackInfo<v8::Value>& args) { v8::Isolate* isolate = args.GetIsolate(); @@ -509,31 +573,14 @@ void WebAssemblyMemoryGetBuffer( i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); i::Handle<i::JSObject> receiver = i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This())); - i::Handle<i::Object> buffer(receiver->GetInternalField(0), i_isolate); + i::Handle<i::Object> buffer(receiver->GetInternalField(kWasmMemoryBuffer), + i_isolate); DCHECK(buffer->IsJSArrayBuffer()); v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); return_value.Set(Utils::ToLocal(buffer)); } } // namespace -i::Handle<i::JSObject> i::WasmJs::CreateWasmMemoryObject( - i::Isolate* i_isolate, i::Handle<i::JSArrayBuffer> buffer, bool has_maximum, - int maximum) { - i::Handle<i::JSFunction> memory_ctor( - i_isolate->native_context()->wasm_memory_constructor()); - i::Handle<i::JSObject> memory_obj = - i_isolate->factory()->NewJSObject(memory_ctor); - memory_obj->SetInternalField(0, *buffer); - memory_obj->SetInternalField( - 1, has_maximum - ? static_cast<i::Object*>(i::Smi::FromInt(maximum)) - : static_cast<i::Object*>(i_isolate->heap()->undefined_value())); - i::Handle<i::Symbol> memory_sym( - i_isolate->native_context()->wasm_memory_sym()); - i::Object::SetProperty(memory_obj, memory_sym, memory_obj, i::STRICT).Check(); - return memory_obj; -} - // TODO(titzer): we use the API to create the function template because the // internal guts are too ugly to replicate here. static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, @@ -605,41 +652,43 @@ void WasmJs::InstallWasmConstructors(Isolate* isolate, JSFunction::SetInstancePrototype( cons, Handle<Object>(context->initial_object_prototype(), isolate)); cons->shared()->set_instance_class_name(*name); - Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED); + Handle<JSObject> webassembly = factory->NewJSObject(cons, TENURED); PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM); - JSObject::AddProperty(global, name, wasm_object, attributes); + JSObject::AddProperty(global, name, webassembly, attributes); // Setup compile - InstallFunc(isolate, wasm_object, "compile", WebAssemblyCompile); + InstallFunc(isolate, webassembly, "compile", WebAssemblyCompile); // Setup compile - InstallFunc(isolate, wasm_object, "validate", WebAssemblyValidate); + InstallFunc(isolate, webassembly, "validate", WebAssemblyValidate); // Setup Module Handle<JSFunction> module_constructor = - InstallFunc(isolate, wasm_object, "Module", WebAssemblyModule); + InstallFunc(isolate, webassembly, "Module", WebAssemblyModule); context->set_wasm_module_constructor(*module_constructor); Handle<JSObject> module_proto = factory->NewJSObject(module_constructor, TENURED); i::Handle<i::Map> map = isolate->factory()->NewMap( - i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + i::kPointerSize); + i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + + WasmModuleObject::kFieldCount * i::kPointerSize); JSFunction::SetInitialMap(module_constructor, map, module_proto); JSObject::AddProperty(module_proto, isolate->factory()->constructor_string(), module_constructor, DONT_ENUM); // Setup Instance Handle<JSFunction> instance_constructor = - InstallFunc(isolate, wasm_object, "Instance", WebAssemblyInstance); + InstallFunc(isolate, webassembly, "Instance", WebAssemblyInstance); context->set_wasm_instance_constructor(*instance_constructor); // Setup Table Handle<JSFunction> table_constructor = - InstallFunc(isolate, wasm_object, "Table", WebAssemblyTable); + InstallFunc(isolate, webassembly, "Table", WebAssemblyTable); context->set_wasm_table_constructor(*table_constructor); Handle<JSObject> table_proto = factory->NewJSObject(table_constructor, TENURED); map = isolate->factory()->NewMap( - i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + 2 * i::kPointerSize); + i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + + WasmTableObject::kFieldCount * i::kPointerSize); JSFunction::SetInitialMap(table_constructor, map, table_proto); JSObject::AddProperty(table_proto, isolate->factory()->constructor_string(), table_constructor, DONT_ENUM); @@ -650,17 +699,29 @@ void WasmJs::InstallWasmConstructors(Isolate* isolate, // Setup Memory Handle<JSFunction> memory_constructor = - InstallFunc(isolate, wasm_object, "Memory", WebAssemblyMemory); + InstallFunc(isolate, webassembly, "Memory", WebAssemblyMemory); context->set_wasm_memory_constructor(*memory_constructor); Handle<JSObject> memory_proto = factory->NewJSObject(memory_constructor, TENURED); map = isolate->factory()->NewMap( - i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + 2 * i::kPointerSize); + i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + + WasmMemoryObject::kFieldCount * i::kPointerSize); JSFunction::SetInitialMap(memory_constructor, map, memory_proto); JSObject::AddProperty(memory_proto, isolate->factory()->constructor_string(), memory_constructor, DONT_ENUM); InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow); InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer); + + // Setup errors + attributes = static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); + Handle<JSFunction> compile_error( + isolate->native_context()->wasm_compile_error_function()); + JSObject::AddProperty(webassembly, isolate->factory()->CompileError_string(), + compile_error, attributes); + Handle<JSFunction> runtime_error( + isolate->native_context()->wasm_runtime_error_function()); + JSObject::AddProperty(webassembly, isolate->factory()->RuntimeError_string(), + runtime_error, attributes); } void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) { @@ -668,44 +729,13 @@ void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) { return; } - Factory* factory = isolate->factory(); - // Setup wasm function map. Handle<Context> context(global->native_context(), isolate); InstallWasmMapsIfNeeded(isolate, context); - if (!FLAG_expose_wasm) { - return; - } - - // Bind the experimental WASM object. - // TODO(rossberg, titzer): remove once it's no longer needed. - { - Handle<String> name = v8_str(isolate, "Wasm"); - Handle<JSFunction> cons = factory->NewFunction(name); - JSFunction::SetInstancePrototype( - cons, Handle<Object>(context->initial_object_prototype(), isolate)); - cons->shared()->set_instance_class_name(*name); - Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED); - PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM); - JSObject::AddProperty(global, name, wasm_object, attributes); - - // Install functions on the WASM object. - InstallFunc(isolate, wasm_object, "verifyModule", VerifyModule); - InstallFunc(isolate, wasm_object, "verifyFunction", VerifyFunction); - InstallFunc(isolate, wasm_object, "instantiateModule", InstantiateModule); - - { - // Add the Wasm.experimentalVersion property. - Handle<String> name = v8_str(isolate, "experimentalVersion"); - PropertyAttributes attributes = - static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); - Handle<Smi> value = - Handle<Smi>(Smi::FromInt(wasm::kWasmVersion), isolate); - JSObject::AddProperty(wasm_object, name, value, attributes); - } + if (FLAG_expose_wasm) { + InstallWasmConstructors(isolate, global, context); } - InstallWasmConstructors(isolate, global, context); } void WasmJs::InstallWasmMapsIfNeeded(Isolate* isolate, @@ -737,5 +767,24 @@ void WasmJs::InstallWasmMapsIfNeeded(Isolate* isolate, } } +static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> symbol) { + if (value->IsJSObject()) { + i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); + Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, symbol); + if (has_brand.IsNothing()) return false; + if (has_brand.ToChecked()) return true; + } + return false; +} + +bool WasmJs::IsWasmMemoryObject(Isolate* isolate, Handle<Object> value) { + i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); + return HasBrand(value, symbol); +} + +bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { + i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); + return HasBrand(value, symbol); +} } // namespace internal } // namespace v8 |