| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/api-natives.h" | 5 #include "src/api-natives.h" |
| 6 #include "src/api.h" | 6 #include "src/api.h" |
| 7 #include "src/asmjs/asm-js.h" | 7 #include "src/asmjs/asm-js.h" |
| 8 #include "src/asmjs/asm-typer.h" | 8 #include "src/asmjs/asm-typer.h" |
| 9 #include "src/asmjs/asm-wasm-builder.h" | 9 #include "src/asmjs/asm-wasm-builder.h" |
| 10 #include "src/assert-scope.h" | 10 #include "src/assert-scope.h" |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 if (start == nullptr || end == start) { | 85 if (start == nullptr || end == start) { |
| 86 thrower->TypeError("ArrayBuffer argument is empty"); | 86 thrower->TypeError("ArrayBuffer argument is empty"); |
| 87 } | 87 } |
| 88 } else { | 88 } else { |
| 89 thrower->TypeError("Argument 0 must be an ArrayBuffer or Uint8Array"); | 89 thrower->TypeError("Argument 0 must be an ArrayBuffer or Uint8Array"); |
| 90 } | 90 } |
| 91 | 91 |
| 92 return {start, end}; | 92 return {start, end}; |
| 93 } | 93 } |
| 94 | 94 |
| 95 void VerifyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 96 HandleScope scope(args.GetIsolate()); | |
| 97 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | |
| 98 ErrorThrower thrower(isolate, "Wasm.verifyModule()"); | |
| 99 | |
| 100 if (args.Length() < 1) { | |
| 101 thrower.TypeError("Argument 0 must be a buffer source"); | |
| 102 return; | |
| 103 } | |
| 104 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); | |
| 105 if (thrower.error()) return; | |
| 106 | |
| 107 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule( | |
| 108 isolate, buffer.start, buffer.end, true, internal::wasm::kWasmOrigin); | |
| 109 | |
| 110 if (result.failed()) { | |
| 111 thrower.CompileFailed("", result); | |
| 112 } | |
| 113 | |
| 114 if (result.val) delete result.val; | |
| 115 } | |
| 116 | |
| 117 void VerifyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 118 HandleScope scope(args.GetIsolate()); | |
| 119 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | |
| 120 ErrorThrower thrower(isolate, "Wasm.verifyFunction()"); | |
| 121 | |
| 122 if (args.Length() < 1) { | |
| 123 thrower.TypeError("Argument 0 must be a buffer source"); | |
| 124 return; | |
| 125 } | |
| 126 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); | |
| 127 if (thrower.error()) return; | |
| 128 | |
| 129 internal::wasm::FunctionResult result; | |
| 130 { | |
| 131 // Verification of a single function shouldn't allocate. | |
| 132 i::DisallowHeapAllocation no_allocation; | |
| 133 i::Zone zone(isolate->allocator(), ZONE_NAME); | |
| 134 result = internal::wasm::DecodeWasmFunction(isolate, &zone, nullptr, | |
| 135 buffer.start, buffer.end); | |
| 136 } | |
| 137 | |
| 138 if (result.failed()) { | |
| 139 thrower.CompileFailed("", result); | |
| 140 } | |
| 141 | |
| 142 if (result.val) delete result.val; | |
| 143 } | |
| 144 | |
| 145 i::MaybeHandle<i::JSObject> InstantiateModule( | |
| 146 const v8::FunctionCallbackInfo<v8::Value>& args, const byte* start, | |
| 147 const byte* end, ErrorThrower* thrower) { | |
| 148 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | |
| 149 | |
| 150 // Decode but avoid a redundant pass over function bodies for verification. | |
| 151 // Verification will happen during compilation. | |
| 152 i::Zone zone(isolate->allocator(), ZONE_NAME); | |
| 153 i::MaybeHandle<i::JSObject> module_object = | |
| 154 i::wasm::CreateModuleObjectFromBytes( | |
| 155 isolate, start, end, thrower, i::wasm::kWasmOrigin, | |
| 156 i::Handle<i::Script>::null(), nullptr, nullptr); | |
| 157 i::MaybeHandle<i::JSObject> object; | |
| 158 if (!module_object.is_null()) { | |
| 159 // Success. Instantiate the module and return the object. | |
| 160 i::Handle<i::JSObject> ffi = i::Handle<i::JSObject>::null(); | |
| 161 if (args.Length() > 1 && args[1]->IsObject()) { | |
| 162 Local<Object> obj = Local<Object>::Cast(args[1]); | |
| 163 ffi = i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj)); | |
| 164 } | |
| 165 | |
| 166 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); | |
| 167 if (args.Length() > 2 && args[2]->IsArrayBuffer()) { | |
| 168 Local<Object> obj = Local<Object>::Cast(args[2]); | |
| 169 i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj); | |
| 170 memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj)); | |
| 171 } | |
| 172 | |
| 173 object = i::wasm::WasmModule::Instantiate( | |
| 174 isolate, thrower, module_object.ToHandleChecked(), ffi, memory); | |
| 175 if (!object.is_null()) { | |
| 176 args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked())); | |
| 177 } | |
| 178 } | |
| 179 return object; | |
| 180 } | |
| 181 | |
| 182 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 183 HandleScope scope(args.GetIsolate()); | |
| 184 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | |
| 185 ErrorThrower thrower(isolate, "Wasm.instantiateModule()"); | |
| 186 | |
| 187 if (args.Length() < 1) { | |
| 188 thrower.TypeError("Argument 0 must be a buffer source"); | |
| 189 return; | |
| 190 } | |
| 191 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); | |
| 192 if (buffer.start == nullptr) return; | |
| 193 | |
| 194 InstantiateModule(args, buffer.start, buffer.end, &thrower); | |
| 195 } | |
| 196 | |
| 197 static i::MaybeHandle<i::JSObject> CreateModuleObject( | 95 static i::MaybeHandle<i::JSObject> CreateModuleObject( |
| 198 v8::Isolate* isolate, const v8::Local<v8::Value> source, | 96 v8::Isolate* isolate, const v8::Local<v8::Value> source, |
| 199 ErrorThrower* thrower) { | 97 ErrorThrower* thrower) { |
| 200 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 98 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 201 i::MaybeHandle<i::JSObject> nothing; | 99 i::MaybeHandle<i::JSObject> nothing; |
| 202 | 100 |
| 203 RawBuffer buffer = GetRawBufferSource(source, thrower); | 101 RawBuffer buffer = GetRawBufferSource(source, thrower); |
| 204 if (buffer.start == nullptr) return i::MaybeHandle<i::JSObject>(); | 102 if (buffer.start == nullptr) return i::MaybeHandle<i::JSObject>(); |
| 205 | 103 |
| 206 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); | 104 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); |
| (...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 isolate->native_context()->wasm_runtime_error_function()); | 768 isolate->native_context()->wasm_runtime_error_function()); |
| 871 JSObject::AddProperty(webassembly, isolate->factory()->RuntimeError_string(), | 769 JSObject::AddProperty(webassembly, isolate->factory()->RuntimeError_string(), |
| 872 runtime_error, attributes); | 770 runtime_error, attributes); |
| 873 } | 771 } |
| 874 | 772 |
| 875 void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) { | 773 void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) { |
| 876 if (!FLAG_expose_wasm && !FLAG_validate_asm) { | 774 if (!FLAG_expose_wasm && !FLAG_validate_asm) { |
| 877 return; | 775 return; |
| 878 } | 776 } |
| 879 | 777 |
| 880 Factory* factory = isolate->factory(); | |
| 881 | |
| 882 // Setup wasm function map. | 778 // Setup wasm function map. |
| 883 Handle<Context> context(global->native_context(), isolate); | 779 Handle<Context> context(global->native_context(), isolate); |
| 884 InstallWasmMapsIfNeeded(isolate, context); | 780 InstallWasmMapsIfNeeded(isolate, context); |
| 885 | 781 |
| 886 if (!FLAG_expose_wasm) { | 782 if (FLAG_expose_wasm) { |
| 887 return; | 783 InstallWasmConstructors(isolate, global, context); |
| 888 } | 784 } |
| 889 | |
| 890 // Bind the experimental "Wasm" object. | |
| 891 // TODO(rossberg, titzer): remove once it's no longer needed. | |
| 892 { | |
| 893 Handle<String> name = v8_str(isolate, "Wasm"); | |
| 894 Handle<JSFunction> cons = factory->NewFunction(name); | |
| 895 JSFunction::SetInstancePrototype( | |
| 896 cons, Handle<Object>(context->initial_object_prototype(), isolate)); | |
| 897 cons->shared()->set_instance_class_name(*name); | |
| 898 Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED); | |
| 899 PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM); | |
| 900 JSObject::AddProperty(global, name, wasm_object, attributes); | |
| 901 | |
| 902 // Install functions on the WASM object. | |
| 903 InstallFunc(isolate, wasm_object, "verifyModule", VerifyModule); | |
| 904 InstallFunc(isolate, wasm_object, "verifyFunction", VerifyFunction); | |
| 905 InstallFunc(isolate, wasm_object, "instantiateModule", InstantiateModule); | |
| 906 | |
| 907 { | |
| 908 // Add the Wasm.experimentalVersion property. | |
| 909 Handle<String> name = v8_str(isolate, "experimentalVersion"); | |
| 910 PropertyAttributes attributes = | |
| 911 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); | |
| 912 Handle<Smi> value = | |
| 913 Handle<Smi>(Smi::FromInt(wasm::kWasmVersion), isolate); | |
| 914 JSObject::AddProperty(wasm_object, name, value, attributes); | |
| 915 } | |
| 916 } | |
| 917 InstallWasmConstructors(isolate, global, context); | |
| 918 } | 785 } |
| 919 | 786 |
| 920 void WasmJs::InstallWasmMapsIfNeeded(Isolate* isolate, | 787 void WasmJs::InstallWasmMapsIfNeeded(Isolate* isolate, |
| 921 Handle<Context> context) { | 788 Handle<Context> context) { |
| 922 if (!context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) { | 789 if (!context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) { |
| 923 // TODO(titzer): Move this to bootstrapper.cc?? | 790 // TODO(titzer): Move this to bootstrapper.cc?? |
| 924 // TODO(titzer): Also make one for strict mode functions? | 791 // TODO(titzer): Also make one for strict mode functions? |
| 925 Handle<Map> prev_map = Handle<Map>(context->sloppy_function_map(), isolate); | 792 Handle<Map> prev_map = Handle<Map>(context->sloppy_function_map(), isolate); |
| 926 | 793 |
| 927 InstanceType instance_type = prev_map->instance_type(); | 794 InstanceType instance_type = prev_map->instance_type(); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 if (!memory_object->IsUndefined(isolate)) { | 854 if (!memory_object->IsUndefined(isolate)) { |
| 988 DCHECK(IsWasmMemoryObject(isolate, memory_object)); | 855 DCHECK(IsWasmMemoryObject(isolate, memory_object)); |
| 989 // TODO(gdeepti): This should be a weak list of instance objects | 856 // TODO(gdeepti): This should be a weak list of instance objects |
| 990 // for instances that share memory. | 857 // for instances that share memory. |
| 991 JSObject::cast(*memory_object) | 858 JSObject::cast(*memory_object) |
| 992 ->SetInternalField(kWasmMemoryInstanceObject, *instance); | 859 ->SetInternalField(kWasmMemoryInstanceObject, *instance); |
| 993 } | 860 } |
| 994 } | 861 } |
| 995 } // namespace internal | 862 } // namespace internal |
| 996 } // namespace v8 | 863 } // namespace v8 |
| OLD | NEW |