Chromium Code Reviews| 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/assert-scope.h" | 7 #include "src/assert-scope.h" |
| 8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
| 9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
| 10 #include "src/execution.h" | 10 #include "src/execution.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 | 28 |
| 29 namespace v8 { | 29 namespace v8 { |
| 30 | 30 |
| 31 namespace { | 31 namespace { |
| 32 struct RawBuffer { | 32 struct RawBuffer { |
| 33 const byte* start; | 33 const byte* start; |
| 34 const byte* end; | 34 const byte* end; |
| 35 size_t size() { return static_cast<size_t>(end - start); } | 35 size_t size() { return static_cast<size_t>(end - start); } |
| 36 }; | 36 }; |
| 37 | 37 |
| 38 RawBuffer GetRawBufferArgument( | 38 RawBuffer GetRawBufferSource( |
| 39 ErrorThrower& thrower, const v8::FunctionCallbackInfo<v8::Value>& args) { | 39 v8::Local<v8::Value> source, ErrorThrower* thrower) { |
| 40 if (args.Length() < 1) { | |
| 41 thrower.Error("Argument 0 must be an array buffer"); | |
| 42 return {nullptr, nullptr}; | |
| 43 } | |
| 44 | |
| 45 const byte* start = nullptr; | 40 const byte* start = nullptr; |
| 46 const byte* end = nullptr; | 41 const byte* end = nullptr; |
| 47 | 42 |
| 48 if (args[0]->IsArrayBuffer()) { | 43 if (source->IsArrayBuffer()) { |
| 49 // A raw array buffer was passed. | 44 // A raw array buffer was passed. |
| 50 Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]); | 45 Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(source); |
| 51 ArrayBuffer::Contents contents = buffer->GetContents(); | 46 ArrayBuffer::Contents contents = buffer->GetContents(); |
| 52 | 47 |
| 53 start = reinterpret_cast<const byte*>(contents.Data()); | 48 start = reinterpret_cast<const byte*>(contents.Data()); |
| 54 end = start + contents.ByteLength(); | 49 end = start + contents.ByteLength(); |
| 55 | 50 |
| 56 if (start == nullptr || end == start) { | 51 if (start == nullptr || end == start) { |
| 57 thrower.Error("ArrayBuffer argument is empty"); | 52 thrower->Error("ArrayBuffer argument is empty"); |
| 58 } | 53 } |
| 59 } else if (args[0]->IsTypedArray()) { | 54 } else if (source->IsTypedArray()) { |
| 60 // A TypedArray was passed. | 55 // A TypedArray was passed. |
| 61 Local<TypedArray> array = Local<TypedArray>::Cast(args[0]); | 56 Local<TypedArray> array = Local<TypedArray>::Cast(source); |
| 62 Local<ArrayBuffer> buffer = array->Buffer(); | 57 Local<ArrayBuffer> buffer = array->Buffer(); |
| 63 | 58 |
| 64 ArrayBuffer::Contents contents = buffer->GetContents(); | 59 ArrayBuffer::Contents contents = buffer->GetContents(); |
| 65 | 60 |
| 66 start = | 61 start = |
| 67 reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset(); | 62 reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset(); |
| 68 end = start + array->ByteLength(); | 63 end = start + array->ByteLength(); |
| 69 | 64 |
| 70 if (start == nullptr || end == start) { | 65 if (start == nullptr || end == start) { |
| 71 thrower.Error("ArrayBuffer argument is empty"); | 66 thrower->Error("ArrayBuffer argument is empty"); |
| 72 } | 67 } |
| 73 } else { | 68 } else { |
| 74 thrower.Error("Argument 0 must be an ArrayBuffer or Uint8Array"); | 69 thrower->Error("Argument 0 must be an ArrayBuffer or Uint8Array"); |
| 75 } | 70 } |
| 76 | 71 |
| 77 return {start, end}; | 72 return {start, end}; |
| 78 } | 73 } |
| 79 | 74 |
| 80 void VerifyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | 75 void VerifyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 81 HandleScope scope(args.GetIsolate()); | 76 HandleScope scope(args.GetIsolate()); |
| 82 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 77 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
| 83 ErrorThrower thrower(isolate, "WASM.verifyModule()"); | 78 ErrorThrower thrower(isolate, "Wasm.verifyModule()"); |
| 84 | 79 |
| 85 RawBuffer buffer = GetRawBufferArgument(thrower, args); | 80 if (args.Length() < 1) { |
| 81 thrower.Error("Argument 0 must be a buffer source"); | |
| 82 return; | |
| 83 } | |
| 84 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); | |
| 86 if (thrower.error()) return; | 85 if (thrower.error()) return; |
| 87 | 86 |
| 88 i::Zone zone(isolate->allocator()); | 87 i::Zone zone(isolate->allocator()); |
| 89 internal::wasm::ModuleResult result = | 88 internal::wasm::ModuleResult result = |
| 90 internal::wasm::DecodeWasmModule(isolate, &zone, buffer.start, buffer.end, | 89 internal::wasm::DecodeWasmModule(isolate, &zone, buffer.start, buffer.end, |
| 91 true, internal::wasm::kWasmOrigin); | 90 true, internal::wasm::kWasmOrigin); |
| 92 | 91 |
| 93 if (result.failed()) { | 92 if (result.failed()) { |
| 94 thrower.Failed("", result); | 93 thrower.Failed("", result); |
| 95 } | 94 } |
| 96 | 95 |
| 97 if (result.val) delete result.val; | 96 if (result.val) delete result.val; |
| 98 } | 97 } |
| 99 | 98 |
| 100 void VerifyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) { | 99 void VerifyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 101 HandleScope scope(args.GetIsolate()); | 100 HandleScope scope(args.GetIsolate()); |
| 102 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 101 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
| 103 ErrorThrower thrower(isolate, "WASM.verifyFunction()"); | 102 ErrorThrower thrower(isolate, "Wasm.verifyFunction()"); |
| 104 | 103 |
| 105 RawBuffer buffer = GetRawBufferArgument(thrower, args); | 104 if (args.Length() < 1) { |
| 105 thrower.Error("Argument 0 must be a buffer source"); | |
| 106 return; | |
| 107 } | |
| 108 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); | |
| 106 if (thrower.error()) return; | 109 if (thrower.error()) return; |
| 107 | 110 |
| 108 internal::wasm::FunctionResult result; | 111 internal::wasm::FunctionResult result; |
| 109 { | 112 { |
| 110 // Verification of a single function shouldn't allocate. | 113 // Verification of a single function shouldn't allocate. |
| 111 i::DisallowHeapAllocation no_allocation; | 114 i::DisallowHeapAllocation no_allocation; |
| 112 i::Zone zone(isolate->allocator()); | 115 i::Zone zone(isolate->allocator()); |
| 113 result = internal::wasm::DecodeWasmFunction(isolate, &zone, nullptr, | 116 result = internal::wasm::DecodeWasmFunction(isolate, &zone, nullptr, |
| 114 buffer.start, buffer.end); | 117 buffer.start, buffer.end); |
| 115 } | 118 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 153 | 156 |
| 154 v8::internal::wasm::AsmWasmBuilder builder(info->isolate(), info->zone(), | 157 v8::internal::wasm::AsmWasmBuilder builder(info->isolate(), info->zone(), |
| 155 info->literal(), &typer); | 158 info->literal(), &typer); |
| 156 | 159 |
| 157 return builder.Run(foreign_args); | 160 return builder.Run(foreign_args); |
| 158 } | 161 } |
| 159 | 162 |
| 160 i::MaybeHandle<i::JSObject> InstantiateModuleCommon( | 163 i::MaybeHandle<i::JSObject> InstantiateModuleCommon( |
| 161 const v8::FunctionCallbackInfo<v8::Value>& args, const byte* start, | 164 const v8::FunctionCallbackInfo<v8::Value>& args, const byte* start, |
| 162 const byte* end, ErrorThrower* thrower, | 165 const byte* end, ErrorThrower* thrower, |
| 163 internal::wasm::ModuleOrigin origin) { | 166 internal::wasm::ModuleOrigin origin = i::wasm::kWasmOrigin) { |
| 164 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 167 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
| 165 | 168 |
| 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 // Decode but avoid a redundant pass over function bodies for verification. | 169 // Decode but avoid a redundant pass over function bodies for verification. |
| 174 // Verification will happen during compilation. | 170 // Verification will happen during compilation. |
| 175 i::Zone zone(isolate->allocator()); | 171 i::Zone zone(isolate->allocator()); |
| 176 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule( | 172 internal::wasm::ModuleResult result = internal::wasm::DecodeWasmModule( |
| 177 isolate, &zone, start, end, false, origin); | 173 isolate, &zone, start, end, false, origin); |
| 178 | 174 |
| 179 i::MaybeHandle<i::JSObject> object; | 175 i::MaybeHandle<i::JSObject> object; |
| 180 if (result.failed() && origin == internal::wasm::kAsmJsOrigin) { | 176 if (result.failed() && origin == internal::wasm::kAsmJsOrigin) { |
| 181 thrower->Error("Asm.js converted module failed to decode"); | 177 thrower->Error("Asm.js converted module failed to decode"); |
| 182 } else if (result.failed()) { | 178 } else if (result.failed()) { |
| 183 thrower->Failed("", result); | 179 thrower->Failed("", result); |
| 184 } else { | 180 } else { |
| 185 // Success. Instantiate the module and return the object. | 181 // Success. Instantiate the module and return the object. |
| 186 i::Handle<i::JSReceiver> ffi = i::Handle<i::JSObject>::null(); | 182 i::Handle<i::JSReceiver> ffi = i::Handle<i::JSObject>::null(); |
| 187 if (args.Length() > 1 && args[1]->IsObject()) { | 183 if (args.Length() > 1 && args[1]->IsObject()) { |
| 188 Local<Object> obj = Local<Object>::Cast(args[1]); | 184 Local<Object> obj = Local<Object>::Cast(args[1]); |
| 189 ffi = i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj)); | 185 ffi = i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj)); |
| 190 } | 186 } |
| 191 | 187 |
| 188 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); | |
| 189 if (args.Length() > 2 && args[2]->IsArrayBuffer()) { | |
| 190 Local<Object> obj = Local<Object>::Cast(args[2]); | |
| 191 i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj); | |
| 192 memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj)); | |
| 193 } | |
| 194 | |
| 192 object = result.val->Instantiate(isolate, ffi, memory); | 195 object = result.val->Instantiate(isolate, ffi, memory); |
| 193 | |
| 194 if (!object.is_null()) { | 196 if (!object.is_null()) { |
| 195 args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked())); | 197 args.GetReturnValue().Set(v8::Utils::ToLocal(object.ToHandleChecked())); |
| 196 } | 198 } |
| 197 } | 199 } |
| 198 | 200 |
| 199 if (result.val) delete result.val; | 201 if (result.val) delete result.val; |
| 200 return object; | 202 return object; |
| 201 } | 203 } |
| 202 | 204 |
| 203 void InstantiateModuleFromAsm(const v8::FunctionCallbackInfo<v8::Value>& args) { | 205 void InstantiateModuleFromAsm(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 204 HandleScope scope(args.GetIsolate()); | 206 HandleScope scope(args.GetIsolate()); |
| 205 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 207 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
| 206 ErrorThrower thrower(isolate, "WASM.instantiateModuleFromAsm()"); | 208 ErrorThrower thrower(isolate, "Wasm.instantiateModuleFromAsm()"); |
| 207 | 209 |
| 208 if (!args[0]->IsString()) { | 210 if (!args[0]->IsString()) { |
| 209 thrower.Error("Asm module text should be a string"); | 211 thrower.Error("Asm module text should be a string"); |
| 210 return; | 212 return; |
| 211 } | 213 } |
| 212 | 214 |
| 213 i::Factory* factory = isolate->factory(); | 215 i::Factory* factory = isolate->factory(); |
| 214 i::Zone zone(isolate->allocator()); | 216 i::Zone zone(isolate->allocator()); |
| 215 Local<String> source = Local<String>::Cast(args[0]); | 217 Local<String> source = Local<String>::Cast(args[0]); |
| 216 i::Handle<i::Script> script = factory->NewScript(Utils::OpenHandle(*source)); | 218 i::Handle<i::Script> script = factory->NewScript(Utils::OpenHandle(*source)); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 | 270 |
| 269 if (retval.is_null()) { | 271 if (retval.is_null()) { |
| 270 thrower.Error( | 272 thrower.Error( |
| 271 "WASM.instantiateModuleFromAsm(): foreign init function failed"); | 273 "WASM.instantiateModuleFromAsm(): foreign init function failed"); |
| 272 } | 274 } |
| 273 } | 275 } |
| 274 | 276 |
| 275 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | 277 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 276 HandleScope scope(args.GetIsolate()); | 278 HandleScope scope(args.GetIsolate()); |
| 277 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 279 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
| 278 ErrorThrower thrower(isolate, "WASM.instantiateModule()"); | 280 ErrorThrower thrower(isolate, "Wasm.instantiateModule()"); |
| 279 | 281 |
| 280 RawBuffer buffer = GetRawBufferArgument(thrower, args); | 282 if (args.Length() < 1) { |
| 283 thrower.Error("Argument 0 must be a buffer source"); | |
| 284 return; | |
| 285 } | |
| 286 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); | |
| 281 if (buffer.start == nullptr) return; | 287 if (buffer.start == nullptr) return; |
| 282 | 288 |
| 283 InstantiateModuleCommon(args, buffer.start, buffer.end, &thrower, | 289 InstantiateModuleCommon(args, buffer.start, buffer.end, &thrower); |
| 284 internal::wasm::kWasmOrigin); | 290 } |
| 291 | |
| 292 | |
| 293 static i::MaybeHandle<i::JSObject> CreateModuleObject( | |
| 294 v8::Isolate* isolate, const v8::Local<v8::Value> source, | |
| 295 ErrorThrower* thrower) { | |
| 296 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
| 297 | |
| 298 RawBuffer buffer = GetRawBufferSource(source, thrower); | |
| 299 if (buffer.start == nullptr) return i::MaybeHandle<i::JSObject>(); | |
| 300 | |
| 301 // TODO(rossberg): Once we can, do compilation here. | |
| 302 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); | |
| 303 Local<Context> context = isolate->GetCurrentContext(); | |
| 304 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | |
| 305 i::Handle<i::JSFunction> module_cons(i_context->wasm_module_constructor()); | |
| 306 i::Handle<i::JSObject> module_obj = | |
| 307 i_isolate->factory()->NewJSObject(module_cons); | |
| 308 i::Handle<i::Object> module_ref = Utils::OpenHandle(*source); | |
| 309 i::Handle<i::Symbol> module_sym(i_context->wasm_module_sym()); | |
| 310 i::Object::SetProperty(module_obj, module_sym, module_ref, i::STRICT).Check(); | |
| 311 | |
| 312 return module_obj; | |
| 313 } | |
| 314 | |
| 315 void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 316 v8::Isolate* isolate = args.GetIsolate(); | |
| 317 HandleScope scope(isolate); | |
| 318 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | |
| 319 "WebAssembly.compile()"); | |
| 320 | |
| 321 if (args.Length() < 1) { | |
| 322 thrower.Error("Argument 0 must be a buffer source"); | |
| 323 return; | |
| 324 } | |
| 325 i::MaybeHandle<i::JSObject> module_obj = | |
| 326 CreateModuleObject(isolate, args[0], &thrower); | |
| 327 if (module_obj.is_null()) return; | |
| 328 | |
| 329 Local<Context> context = isolate->GetCurrentContext(); | |
| 330 v8::Local<v8::Promise::Resolver> resolver; | |
| 331 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; | |
| 332 resolver->Resolve(context, Utils::ToLocal(module_obj.ToHandleChecked())); | |
| 333 | |
| 334 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | |
| 335 return_value.Set(resolver->GetPromise()); | |
| 336 } | |
| 337 | |
| 338 void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 339 v8::Isolate* isolate = args.GetIsolate(); | |
| 340 HandleScope scope(isolate); | |
| 341 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | |
| 342 "WebAssembly.Module()"); | |
| 343 | |
| 344 if (args.Length() < 1) { | |
| 345 thrower.Error("Argument 0 must be a buffer source"); | |
| 346 return; | |
| 347 } | |
| 348 i::MaybeHandle<i::JSObject> module_obj = | |
| 349 CreateModuleObject(isolate, args[0], &thrower); | |
| 350 if (module_obj.is_null()) return; | |
| 351 | |
| 352 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | |
| 353 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); | |
| 354 } | |
| 355 | |
| 356 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 357 HandleScope scope(args.GetIsolate()); | |
| 358 v8::Isolate* isolate = args.GetIsolate(); | |
| 359 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | |
| 360 "WebAssembly.Instance()"); | |
| 361 | |
| 362 if (args.Length() < 1) { | |
| 363 thrower.Error("Argument 0 must be a WebAssembly.Module"); | |
| 364 return; | |
| 365 } | |
| 366 Local<Context> context = isolate->GetCurrentContext(); | |
| 367 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | |
| 368 i::Handle<i::Symbol> module_sym(i_context->wasm_module_sym()); | |
| 369 i::MaybeHandle<i::Object> source = | |
| 370 i::Object::GetProperty(Utils::OpenHandle(*args[0]), module_sym); | |
| 371 if (source.is_null()) return; | |
| 372 | |
| 373 RawBuffer buffer = | |
| 374 GetRawBufferSource(Utils::ToLocal(source.ToHandleChecked()), &thrower); | |
| 375 if (buffer.start == nullptr) return; | |
| 376 | |
| 377 InstantiateModuleCommon(args, buffer.start, buffer.end, &thrower); | |
| 285 } | 378 } |
| 286 } // namespace | 379 } // namespace |
| 287 | 380 |
| 288 // TODO(titzer): we use the API to create the function template because the | 381 // TODO(titzer): we use the API to create the function template because the |
| 289 // internal guts are too ugly to replicate here. | 382 // internal guts are too ugly to replicate here. |
| 290 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, | 383 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, |
| 291 FunctionCallback func) { | 384 FunctionCallback func) { |
| 292 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); | 385 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); |
| 293 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); | 386 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); |
| 294 return v8::Utils::OpenHandle(*local); | 387 return v8::Utils::OpenHandle(*local); |
| 295 } | 388 } |
| 296 | 389 |
| 297 namespace internal { | 390 namespace internal { |
| 298 static Handle<String> v8_str(Isolate* isolate, const char* str) { | 391 static Handle<String> v8_str(Isolate* isolate, const char* str) { |
| 299 return isolate->factory()->NewStringFromAsciiChecked(str); | 392 return isolate->factory()->NewStringFromAsciiChecked(str); |
| 300 } | 393 } |
| 301 | 394 |
| 302 static void InstallFunc(Isolate* isolate, Handle<JSObject> object, | 395 static Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object, |
| 303 const char* str, FunctionCallback func) { | 396 const char* str, FunctionCallback func) { |
| 304 Handle<String> name = v8_str(isolate, str); | 397 Handle<String> name = v8_str(isolate, str); |
| 305 Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func); | 398 Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func); |
| 306 Handle<JSFunction> function = | 399 Handle<JSFunction> function = |
| 307 ApiNatives::InstantiateFunction(temp).ToHandleChecked(); | 400 ApiNatives::InstantiateFunction(temp).ToHandleChecked(); |
| 308 PropertyAttributes attributes = | 401 PropertyAttributes attributes = |
| 309 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); | 402 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); |
| 310 JSObject::AddProperty(object, name, function, attributes); | 403 JSObject::AddProperty(object, name, function, attributes); |
| 404 return function; | |
| 311 } | 405 } |
| 312 | 406 |
| 313 void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) { | 407 void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) { |
| 408 Factory* factory = isolate->factory(); | |
| 409 | |
| 314 // Setup wasm function map. | 410 // Setup wasm function map. |
| 315 Handle<Context> context(global->native_context(), isolate); | 411 Handle<Context> context(global->native_context(), isolate); |
| 316 InstallWasmFunctionMap(isolate, context); | 412 InstallWasmFunctionMap(isolate, context); |
| 317 | 413 |
| 318 // Bind the WASM object. | 414 // Bind the experimental WASM object. |
| 319 Factory* factory = isolate->factory(); | 415 // TODO(rossberg, titzer): remove once it's no longer needed. |
| 320 Handle<String> name = v8_str(isolate, "Wasm"); | 416 { |
| 417 Handle<String> name = v8_str(isolate, "Wasm"); | |
| 418 Handle<JSFunction> cons = factory->NewFunction(name); | |
| 419 JSFunction::SetInstancePrototype( | |
| 420 cons, Handle<Object>(context->initial_object_prototype(), isolate)); | |
| 421 cons->shared()->set_instance_class_name(*name); | |
| 422 Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED); | |
| 423 PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM); | |
| 424 JSObject::AddProperty(global, name, wasm_object, attributes); | |
| 425 | |
| 426 // Install functions on the WASM object. | |
| 427 InstallFunc(isolate, wasm_object, "verifyModule", VerifyModule); | |
| 428 InstallFunc(isolate, wasm_object, "verifyFunction", VerifyFunction); | |
| 429 InstallFunc(isolate, wasm_object, "instantiateModule", InstantiateModule); | |
| 430 InstallFunc(isolate, wasm_object, "instantiateModuleFromAsm", | |
| 431 InstantiateModuleFromAsm); | |
| 432 | |
| 433 { | |
| 434 // Add the Wasm.experimentalVersion property. | |
| 435 Handle<String> name = v8_str(isolate, "experimentalVersion"); | |
| 436 PropertyAttributes attributes = | |
| 437 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); | |
| 438 Handle<Smi> value = | |
| 439 Handle<Smi>(Smi::FromInt(wasm::kWasmVersion), isolate); | |
| 440 JSObject::AddProperty(wasm_object, name, value, attributes); | |
| 441 } | |
| 442 } | |
| 443 | |
| 444 // Create private symbols. | |
| 445 Handle<Symbol> module_sym = isolate->factory()->NewPrivateSymbol(); | |
| 446 Handle<Symbol> instance_sym = isolate->factory()->NewPrivateSymbol(); | |
| 447 context->set_wasm_module_sym(*module_sym); | |
| 448 context->set_wasm_instance_sym(*instance_sym); | |
| 449 | |
| 450 // Bind the WebAssembly object. | |
| 451 Handle<String> name = v8_str(isolate, "WebAssembly"); | |
| 321 Handle<JSFunction> cons = factory->NewFunction(name); | 452 Handle<JSFunction> cons = factory->NewFunction(name); |
| 322 JSFunction::SetInstancePrototype( | 453 JSFunction::SetInstancePrototype( |
| 323 cons, Handle<Object>(context->initial_object_prototype(), isolate)); | 454 cons, Handle<Object>(context->initial_object_prototype(), isolate)); |
| 324 cons->shared()->set_instance_class_name(*name); | 455 cons->shared()->set_instance_class_name(*name); |
| 325 Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED); | 456 Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED); |
| 326 PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM); | 457 PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM); |
| 327 JSObject::AddProperty(global, name, wasm_object, attributes); | 458 JSObject::AddProperty(global, name, wasm_object, attributes); |
| 328 | 459 |
| 329 // Install functions on the WASM object. | 460 // Install static methods on WebAssembly object. |
| 330 InstallFunc(isolate, wasm_object, "verifyModule", VerifyModule); | 461 InstallFunc(isolate, wasm_object, "compile", WebAssemblyCompile); |
| 331 InstallFunc(isolate, wasm_object, "verifyFunction", VerifyFunction); | 462 Handle<JSFunction> module_constructor = |
| 332 InstallFunc(isolate, wasm_object, "instantiateModule", InstantiateModule); | 463 InstallFunc(isolate, wasm_object, "Module", WebAssemblyModule); |
| 333 InstallFunc(isolate, wasm_object, "instantiateModuleFromAsm", | 464 Handle<JSFunction> instance_constructor = |
| 334 InstantiateModuleFromAsm); | 465 InstallFunc(isolate, wasm_object, "Instance", WebAssemblyInstance); |
|
Mircea Trofin
2016/06/21 13:20:49
Don't we want to name this "Instantiate", rather t
rossberg
2016/06/21 13:35:16
No, it's a constructor, i.e., represents a class.
| |
| 335 | 466 context->set_wasm_module_constructor(*module_constructor); |
| 336 { | 467 context->set_wasm_instance_constructor(*instance_constructor); |
| 337 // Add the Wasm.experimentalVersion property. | |
| 338 Handle<String> name = v8_str(isolate, "experimentalVersion"); | |
| 339 PropertyAttributes attributes = | |
| 340 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); | |
| 341 Handle<Smi> value = Handle<Smi>(Smi::FromInt(wasm::kWasmVersion), isolate); | |
| 342 JSObject::AddProperty(wasm_object, name, value, attributes); | |
| 343 } | |
| 344 } | 468 } |
| 345 | 469 |
| 346 void WasmJs::InstallWasmFunctionMap(Isolate* isolate, Handle<Context> context) { | 470 void WasmJs::InstallWasmFunctionMap(Isolate* isolate, Handle<Context> context) { |
| 347 if (!context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) { | 471 if (!context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) { |
| 348 // TODO(titzer): Move this to bootstrapper.cc?? | 472 // TODO(titzer): Move this to bootstrapper.cc?? |
| 349 // TODO(titzer): Also make one for strict mode functions? | 473 // TODO(titzer): Also make one for strict mode functions? |
| 350 Handle<Map> prev_map = Handle<Map>(context->sloppy_function_map(), isolate); | 474 Handle<Map> prev_map = Handle<Map>(context->sloppy_function_map(), isolate); |
| 351 | 475 |
| 352 InstanceType instance_type = prev_map->instance_type(); | 476 InstanceType instance_type = prev_map->instance_type(); |
| 353 int internal_fields = JSObject::GetInternalFieldCount(*prev_map); | 477 int internal_fields = JSObject::GetInternalFieldCount(*prev_map); |
| 354 CHECK_EQ(0, internal_fields); | 478 CHECK_EQ(0, internal_fields); |
| 355 int pre_allocated = | 479 int pre_allocated = |
| 356 prev_map->GetInObjectProperties() - prev_map->unused_property_fields(); | 480 prev_map->GetInObjectProperties() - prev_map->unused_property_fields(); |
| 357 int instance_size; | 481 int instance_size; |
| 358 int in_object_properties; | 482 int in_object_properties; |
| 359 JSFunction::CalculateInstanceSizeHelper(instance_type, internal_fields + 1, | 483 JSFunction::CalculateInstanceSizeHelper(instance_type, internal_fields + 1, |
| 360 0, &instance_size, | 484 0, &instance_size, |
| 361 &in_object_properties); | 485 &in_object_properties); |
| 362 | 486 |
| 363 int unused_property_fields = in_object_properties - pre_allocated; | 487 int unused_property_fields = in_object_properties - pre_allocated; |
| 364 Handle<Map> map = Map::CopyInitialMap( | 488 Handle<Map> map = Map::CopyInitialMap( |
| 365 prev_map, instance_size, in_object_properties, unused_property_fields); | 489 prev_map, instance_size, in_object_properties, unused_property_fields); |
| 366 | 490 |
| 367 context->set_wasm_function_map(*map); | 491 context->set_wasm_function_map(*map); |
| 368 } | 492 } |
| 369 } | 493 } |
| 370 | 494 |
| 371 } // namespace internal | 495 } // namespace internal |
| 372 } // namespace v8 | 496 } // namespace v8 |
| OLD | NEW |