| 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/macro-assembler.h" | 5 #include "src/macro-assembler.h" |
| 6 #include "src/objects.h" | 6 #include "src/objects.h" |
| 7 #include "src/v8.h" | 7 #include "src/v8.h" |
| 8 | 8 |
| 9 #include "src/simulator.h" | 9 #include "src/simulator.h" |
| 10 | 10 |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 } | 375 } |
| 376 | 376 |
| 377 // Instantiates a wasm module as a JSObject. | 377 // Instantiates a wasm module as a JSObject. |
| 378 // * allocates a backing store of {mem_size} bytes. | 378 // * allocates a backing store of {mem_size} bytes. |
| 379 // * installs a named property "memory" for that buffer if exported | 379 // * installs a named property "memory" for that buffer if exported |
| 380 // * installs named properties on the object for exported functions | 380 // * installs named properties on the object for exported functions |
| 381 // * compiles wasm code to machine code | 381 // * compiles wasm code to machine code |
| 382 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, | 382 MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, |
| 383 Handle<JSObject> ffi, | 383 Handle<JSObject> ffi, |
| 384 Handle<JSArrayBuffer> memory) { | 384 Handle<JSArrayBuffer> memory) { |
| 385 HistogramTimerScope wasm_instantiate_time_scope( |
| 386 isolate->counters()->wasm_instantiate_time()); |
| 385 this->shared_isolate = isolate; // TODO(titzer): have a real shared isolate. | 387 this->shared_isolate = isolate; // TODO(titzer): have a real shared isolate. |
| 386 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 388 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
| 387 Factory* factory = isolate->factory(); | 389 Factory* factory = isolate->factory(); |
| 388 | 390 |
| 389 //------------------------------------------------------------------------- | 391 //------------------------------------------------------------------------- |
| 390 // Allocate the instance and its JS counterpart. | 392 // Allocate the instance and its JS counterpart. |
| 391 //------------------------------------------------------------------------- | 393 //------------------------------------------------------------------------- |
| 392 Handle<Map> map = factory->NewMap( | 394 Handle<Map> map = factory->NewMap( |
| 393 JS_OBJECT_TYPE, | 395 JS_OBJECT_TYPE, |
| 394 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 396 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
| 395 WasmModuleInstance instance(this); | 397 WasmModuleInstance instance(this); |
| 396 instance.context = isolate->native_context(); | 398 instance.context = isolate->native_context(); |
| 397 instance.js_object = factory->NewJSObjectFromMap(map, TENURED); | 399 instance.js_object = factory->NewJSObjectFromMap(map, TENURED); |
| 398 Handle<FixedArray> code_table = | 400 Handle<FixedArray> code_table = |
| 399 factory->NewFixedArray(static_cast<int>(functions.size()), TENURED); | 401 factory->NewFixedArray(static_cast<int>(functions.size()), TENURED); |
| 400 instance.js_object->SetInternalField(kWasmModuleCodeTable, *code_table); | 402 instance.js_object->SetInternalField(kWasmModuleCodeTable, *code_table); |
| 401 | 403 |
| 402 //------------------------------------------------------------------------- | 404 //------------------------------------------------------------------------- |
| 403 // Allocate and initialize the linear memory. | 405 // Allocate and initialize the linear memory. |
| 404 //------------------------------------------------------------------------- | 406 //------------------------------------------------------------------------- |
| 407 isolate->counters()->wasm_min_mem_pages_memory()->AddSample( |
| 408 instance.module->min_mem_pages); |
| 409 isolate->counters()->wasm_max_mem_pages_memory()->AddSample( |
| 410 instance.module->max_mem_pages); |
| 405 if (memory.is_null()) { | 411 if (memory.is_null()) { |
| 406 if (!AllocateMemory(&thrower, isolate, &instance)) { | 412 if (!AllocateMemory(&thrower, isolate, &instance)) { |
| 407 return MaybeHandle<JSObject>(); | 413 return MaybeHandle<JSObject>(); |
| 408 } | 414 } |
| 409 } else { | 415 } else { |
| 410 SetMemory(&instance, memory); | 416 SetMemory(&instance, memory); |
| 411 } | 417 } |
| 412 instance.js_object->SetInternalField(kWasmMemArrayBuffer, | 418 instance.js_object->SetInternalField(kWasmMemArrayBuffer, |
| 413 *instance.mem_buffer); | 419 *instance.mem_buffer); |
| 414 LoadDataSegments(this, instance.mem_start, instance.mem_size); | 420 LoadDataSegments(this, instance.mem_start, instance.mem_size); |
| 415 | 421 |
| 416 //------------------------------------------------------------------------- | 422 //------------------------------------------------------------------------- |
| 417 // Allocate the globals area if necessary. | 423 // Allocate the globals area if necessary. |
| 418 //------------------------------------------------------------------------- | 424 //------------------------------------------------------------------------- |
| 419 if (!AllocateGlobals(&thrower, isolate, &instance)) { | 425 if (!AllocateGlobals(&thrower, isolate, &instance)) { |
| 420 return MaybeHandle<JSObject>(); | 426 return MaybeHandle<JSObject>(); |
| 421 } | 427 } |
| 422 if (!instance.globals_buffer.is_null()) { | 428 if (!instance.globals_buffer.is_null()) { |
| 423 instance.js_object->SetInternalField(kWasmGlobalsArrayBuffer, | 429 instance.js_object->SetInternalField(kWasmGlobalsArrayBuffer, |
| 424 *instance.globals_buffer); | 430 *instance.globals_buffer); |
| 425 } | 431 } |
| 426 | 432 |
| 433 HistogramTimerScope wasm_compile_time_scope( |
| 434 isolate->counters()->wasm_compile_time()); |
| 435 |
| 427 //------------------------------------------------------------------------- | 436 //------------------------------------------------------------------------- |
| 428 // Compile wrappers to imported functions. | 437 // Compile wrappers to imported functions. |
| 429 //------------------------------------------------------------------------- | 438 //------------------------------------------------------------------------- |
| 430 uint32_t index = 0; | 439 uint32_t index = 0; |
| 431 instance.function_table = BuildFunctionTable(isolate, this); | 440 instance.function_table = BuildFunctionTable(isolate, this); |
| 432 WasmLinker linker(isolate, functions.size()); | 441 WasmLinker linker(isolate, functions.size()); |
| 433 ModuleEnv module_env; | 442 ModuleEnv module_env; |
| 434 module_env.module = this; | 443 module_env.module = this; |
| 435 module_env.instance = &instance; | 444 module_env.instance = &instance; |
| 436 module_env.linker = &linker; | 445 module_env.linker = &linker; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 450 isolate, &module_env, function.ToHandleChecked(), import.sig, | 459 isolate, &module_env, function.ToHandleChecked(), import.sig, |
| 451 module_name, function_name); | 460 module_name, function_name); |
| 452 instance.import_code.push_back(code); | 461 instance.import_code.push_back(code); |
| 453 index++; | 462 index++; |
| 454 } | 463 } |
| 455 } | 464 } |
| 456 | 465 |
| 457 //------------------------------------------------------------------------- | 466 //------------------------------------------------------------------------- |
| 458 // Compile all functions in the module. | 467 // Compile all functions in the module. |
| 459 //------------------------------------------------------------------------- | 468 //------------------------------------------------------------------------- |
| 469 { |
| 470 isolate->counters()->wasm_functions_per_module()->AddSample( |
| 471 static_cast<int>(functions.size())); |
| 460 | 472 |
| 461 // First pass: compile each function and initialize the code table. | 473 // First pass: compile each function and initialize the code table. |
| 462 index = FLAG_skip_compiling_wasm_funcs; | 474 index = FLAG_skip_compiling_wasm_funcs; |
| 463 while (index < functions.size()) { | 475 while (index < functions.size()) { |
| 464 const WasmFunction& func = functions[index]; | 476 const WasmFunction& func = functions[index]; |
| 465 if (thrower.error()) break; | 477 if (thrower.error()) break; |
| 466 DCHECK_EQ(index, func.func_index); | 478 DCHECK_EQ(index, func.func_index); |
| 467 | 479 |
| 468 WasmName str = GetName(func.name_offset, func.name_length); | 480 WasmName str = GetName(func.name_offset, func.name_length); |
| 469 WasmName str_null = {nullptr, 0}; | 481 WasmName str_null = {nullptr, 0}; |
| 470 Handle<String> name = factory->InternalizeUtf8String( | 482 Handle<String> name = factory->InternalizeUtf8String( |
| 471 Vector<const char>(str.name, str.length)); | 483 Vector<const char>(str.name, str.length)); |
| 472 Handle<Code> code = Handle<Code>::null(); | 484 Handle<Code> code = Handle<Code>::null(); |
| 473 Handle<JSFunction> function = Handle<JSFunction>::null(); | 485 Handle<JSFunction> function = Handle<JSFunction>::null(); |
| 474 if (func.external) { | 486 if (func.external) { |
| 475 // Lookup external function in FFI object. | 487 // Lookup external function in FFI object. |
| 476 MaybeHandle<JSFunction> function = | 488 MaybeHandle<JSFunction> function = |
| 477 LookupFunction(thrower, factory, ffi, index, str, str_null); | 489 LookupFunction(thrower, factory, ffi, index, str, str_null); |
| 478 if (function.is_null()) return MaybeHandle<JSObject>(); | 490 if (function.is_null()) return MaybeHandle<JSObject>(); |
| 479 code = compiler::CompileWasmToJSWrapper(isolate, &module_env, | 491 code = compiler::CompileWasmToJSWrapper(isolate, &module_env, |
| 480 function.ToHandleChecked(), | 492 function.ToHandleChecked(), |
| 481 func.sig, str, str_null); | 493 func.sig, str, str_null); |
| 482 } else { | 494 } else { |
| 483 // Compile the function. | 495 // Compile the function. |
| 484 code = compiler::CompileWasmFunction(thrower, isolate, &module_env, func); | 496 code = |
| 485 if (code.is_null()) { | 497 compiler::CompileWasmFunction(thrower, isolate, &module_env, func); |
| 486 thrower.Error("Compilation of #%d:%.*s failed.", index, str.length, | 498 if (code.is_null()) { |
| 487 str.name); | 499 thrower.Error("Compilation of #%d:%.*s failed.", index, str.length, |
| 488 return MaybeHandle<JSObject>(); | 500 str.name); |
| 501 return MaybeHandle<JSObject>(); |
| 502 } |
| 503 if (func.exported) { |
| 504 function = compiler::CompileJSToWasmWrapper( |
| 505 isolate, &module_env, name, code, instance.js_object, index); |
| 506 } |
| 507 } |
| 508 if (!code.is_null()) { |
| 509 // Install the code into the linker table. |
| 510 linker.Finish(index, code); |
| 511 code_table->set(index, *code); |
| 489 } | 512 } |
| 490 if (func.exported) { | 513 if (func.exported) { |
| 491 function = compiler::CompileJSToWasmWrapper( | 514 // Exported functions are installed as read-only properties on the |
| 492 isolate, &module_env, name, code, instance.js_object, index); | 515 // module. |
| 516 JSObject::AddProperty(instance.js_object, name, function, READ_ONLY); |
| 493 } | 517 } |
| 494 } | 518 index++; |
| 495 if (!code.is_null()) { | |
| 496 // Install the code into the linker table. | |
| 497 linker.Finish(index, code); | |
| 498 code_table->set(index, *code); | |
| 499 } | |
| 500 if (func.exported) { | |
| 501 // Exported functions are installed as read-only properties on the module. | |
| 502 JSObject::AddProperty(instance.js_object, name, function, READ_ONLY); | |
| 503 } | |
| 504 index++; | |
| 505 } | |
| 506 | |
| 507 // Second pass: patch all direct call sites. | |
| 508 linker.Link(instance.function_table, this->function_table); | |
| 509 instance.js_object->SetInternalField(kWasmModuleFunctionTable, | |
| 510 Smi::FromInt(0)); | |
| 511 | |
| 512 //------------------------------------------------------------------------- | |
| 513 // Create and populate the exports object. | |
| 514 //------------------------------------------------------------------------- | |
| 515 if (export_table.size() > 0 || mem_export) { | |
| 516 index = 0; | |
| 517 // Create the "exports" object. | |
| 518 Handle<JSFunction> object_function = Handle<JSFunction>( | |
| 519 isolate->native_context()->object_function(), isolate); | |
| 520 Handle<JSObject> exports_object = | |
| 521 factory->NewJSObject(object_function, TENURED); | |
| 522 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); | |
| 523 JSObject::AddProperty(instance.js_object, exports_name, exports_object, | |
| 524 READ_ONLY); | |
| 525 | |
| 526 // Compile wrappers and add them to the exports object. | |
| 527 for (const WasmExport& exp : export_table) { | |
| 528 if (thrower.error()) break; | |
| 529 WasmName str = GetName(exp.name_offset, exp.name_length); | |
| 530 Handle<String> name = factory->InternalizeUtf8String( | |
| 531 Vector<const char>(str.name, str.length)); | |
| 532 Handle<Code> code = linker.GetFunctionCode(exp.func_index); | |
| 533 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( | |
| 534 isolate, &module_env, name, code, instance.js_object, exp.func_index); | |
| 535 JSObject::AddProperty(exports_object, name, function, READ_ONLY); | |
| 536 } | 519 } |
| 537 | 520 |
| 538 if (mem_export) { | 521 // Second pass: patch all direct call sites. |
| 539 // Export the memory as a named property. | 522 linker.Link(instance.function_table, this->function_table); |
| 540 Handle<String> name = factory->InternalizeUtf8String("memory"); | 523 instance.js_object->SetInternalField(kWasmModuleFunctionTable, |
| 541 JSObject::AddProperty(exports_object, name, instance.mem_buffer, | 524 Smi::FromInt(0)); |
| 525 |
| 526 //------------------------------------------------------------------------- |
| 527 // Create and populate the exports object. |
| 528 //------------------------------------------------------------------------- |
| 529 if (export_table.size() > 0 || mem_export) { |
| 530 index = 0; |
| 531 // Create the "exports" object. |
| 532 Handle<JSFunction> object_function = Handle<JSFunction>( |
| 533 isolate->native_context()->object_function(), isolate); |
| 534 Handle<JSObject> exports_object = |
| 535 factory->NewJSObject(object_function, TENURED); |
| 536 Handle<String> exports_name = factory->InternalizeUtf8String("exports"); |
| 537 JSObject::AddProperty(instance.js_object, exports_name, exports_object, |
| 542 READ_ONLY); | 538 READ_ONLY); |
| 539 |
| 540 // Compile wrappers and add them to the exports object. |
| 541 for (const WasmExport& exp : export_table) { |
| 542 if (thrower.error()) break; |
| 543 WasmName str = GetName(exp.name_offset, exp.name_length); |
| 544 Handle<String> name = factory->InternalizeUtf8String( |
| 545 Vector<const char>(str.name, str.length)); |
| 546 Handle<Code> code = linker.GetFunctionCode(exp.func_index); |
| 547 Handle<JSFunction> function = compiler::CompileJSToWasmWrapper( |
| 548 isolate, &module_env, name, code, instance.js_object, |
| 549 exp.func_index); |
| 550 JSObject::AddProperty(exports_object, name, function, READ_ONLY); |
| 551 } |
| 552 |
| 553 if (mem_export) { |
| 554 // Export the memory as a named property. |
| 555 Handle<String> name = factory->InternalizeUtf8String("memory"); |
| 556 JSObject::AddProperty(exports_object, name, instance.mem_buffer, |
| 557 READ_ONLY); |
| 558 } |
| 543 } | 559 } |
| 544 } | 560 } |
| 545 | 561 |
| 546 // Run the start function if one was specified. | 562 // Run the start function if one was specified. |
| 547 if (this->start_function_index >= 0) { | 563 if (this->start_function_index >= 0) { |
| 548 HandleScope scope(isolate); | 564 HandleScope scope(isolate); |
| 549 uint32_t index = static_cast<uint32_t>(this->start_function_index); | 565 uint32_t index = static_cast<uint32_t>(this->start_function_index); |
| 550 Handle<String> name = isolate->factory()->NewStringFromStaticChars("start"); | 566 Handle<String> name = isolate->factory()->NewStringFromStaticChars("start"); |
| 551 Handle<Code> code = linker.GetFunctionCode(index); | 567 Handle<Code> code = linker.GetFunctionCode(index); |
| 552 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper( | 568 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper( |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 } | 705 } |
| 690 if (result->IsHeapNumber()) { | 706 if (result->IsHeapNumber()) { |
| 691 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 707 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
| 692 } | 708 } |
| 693 thrower.Error("WASM.compileRun() failed: Return value should be number"); | 709 thrower.Error("WASM.compileRun() failed: Return value should be number"); |
| 694 return -1; | 710 return -1; |
| 695 } | 711 } |
| 696 } // namespace wasm | 712 } // namespace wasm |
| 697 } // namespace internal | 713 } // namespace internal |
| 698 } // namespace v8 | 714 } // namespace v8 |
| OLD | NEW |