| 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 <memory> | 5 #include <memory> |
| 6 | 6 |
| 7 #include "src/asmjs/asm-js.h" | 7 #include "src/asmjs/asm-js.h" |
| 8 #include "src/assembler-inl.h" | 8 #include "src/assembler-inl.h" |
| 9 #include "src/base/atomic-utils.h" | 9 #include "src/base/atomic-utils.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 base::OS::Free(memory, | 65 base::OS::Free(memory, |
| 66 RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize())); | 66 RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize())); |
| 67 | 67 |
| 68 data.GetIsolate()->AdjustAmountOfExternalAllocatedMemory( | 68 data.GetIsolate()->AdjustAmountOfExternalAllocatedMemory( |
| 69 -buffer->byte_length()->Number()); | 69 -buffer->byte_length()->Number()); |
| 70 } | 70 } |
| 71 | 71 |
| 72 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); | 72 GlobalHandles::Destroy(reinterpret_cast<Object**>(p)); |
| 73 } | 73 } |
| 74 | 74 |
| 75 static void RecordStats(Isolate* isolate, Code* code) { | 75 static void RecordStats(Isolate* isolate, Code* code, bool is_sync) { |
| 76 isolate->counters()->wasm_generated_code_size()->Increment(code->body_size()); | 76 if (is_sync) { |
| 77 isolate->counters()->wasm_reloc_size()->Increment( | 77 // TODO(karlschimpf): Make this work when asynchronous. |
| 78 code->relocation_info()->length()); | 78 // https://bugs.chromium.org/p/v8/issues/detail?id=6361 |
| 79 } | 79 isolate->counters()->wasm_generated_code_size()->Increment( |
| 80 | 80 code->body_size()); |
| 81 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) { | 81 isolate->counters()->wasm_reloc_size()->Increment( |
| 82 DisallowHeapAllocation no_gc; | 82 code->relocation_info()->length()); |
| 83 for (int i = 0; i < functions->length(); ++i) { | |
| 84 RecordStats(isolate, Code::cast(functions->get(i))); | |
| 85 } | 83 } |
| 86 } | 84 } |
| 87 | 85 |
| 86 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions, |
| 87 bool is_sync) { |
| 88 DisallowHeapAllocation no_gc; |
| 89 for (int i = 0; i < functions->length(); ++i) { |
| 90 RecordStats(isolate, Code::cast(functions->get(i)), is_sync); |
| 91 } |
| 92 } |
| 93 |
| 88 void* TryAllocateBackingStore(Isolate* isolate, size_t size, | 94 void* TryAllocateBackingStore(Isolate* isolate, size_t size, |
| 89 bool enable_guard_regions, bool& is_external) { | 95 bool enable_guard_regions, bool& is_external) { |
| 90 is_external = false; | 96 is_external = false; |
| 91 // TODO(eholk): Right now enable_guard_regions has no effect on 32-bit | 97 // TODO(eholk): Right now enable_guard_regions has no effect on 32-bit |
| 92 // systems. It may be safer to fail instead, given that other code might do | 98 // systems. It may be safer to fail instead, given that other code might do |
| 93 // things that would be unsafe if they expected guard pages where there | 99 // things that would be unsafe if they expected guard pages where there |
| 94 // weren't any. | 100 // weren't any. |
| 95 if (enable_guard_regions && kGuardRegionsSupported) { | 101 if (enable_guard_regions && kGuardRegionsSupported) { |
| 96 // TODO(eholk): On Windows we want to make sure we don't commit the guard | 102 // TODO(eholk): On Windows we want to make sure we don't commit the guard |
| 97 // pages yet. | 103 // pages yet. |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 (FLAG_asm_wasm_lazy_compilation && module->is_asm_js()); | 303 (FLAG_asm_wasm_lazy_compilation && module->is_asm_js()); |
| 298 } | 304 } |
| 299 | 305 |
| 300 // A helper for compiling an entire module. | 306 // A helper for compiling an entire module. |
| 301 class CompilationHelper { | 307 class CompilationHelper { |
| 302 public: | 308 public: |
| 303 // The compilation helper takes ownership of the {WasmModule}. | 309 // The compilation helper takes ownership of the {WasmModule}. |
| 304 // In {CompileToModuleObject}, it will transfer ownership to the generated | 310 // In {CompileToModuleObject}, it will transfer ownership to the generated |
| 305 // {WasmModuleWrapper}. If this method is not called, ownership may be | 311 // {WasmModuleWrapper}. If this method is not called, ownership may be |
| 306 // reclaimed by explicitely releasing the {module_} field. | 312 // reclaimed by explicitely releasing the {module_} field. |
| 307 CompilationHelper(Isolate* isolate, std::unique_ptr<WasmModule> module) | 313 CompilationHelper(Isolate* isolate, std::unique_ptr<WasmModule> module, |
| 308 : isolate_(isolate), module_(std::move(module)) {} | 314 bool is_sync) |
| 315 : isolate_(isolate), module_(std::move(module)), is_sync_(is_sync) {} |
| 309 | 316 |
| 310 // The actual runnable task that performs compilations in the background. | 317 // The actual runnable task that performs compilations in the background. |
| 311 class CompilationTask : public CancelableTask { | 318 class CompilationTask : public CancelableTask { |
| 312 public: | 319 public: |
| 313 CompilationHelper* helper_; | 320 CompilationHelper* helper_; |
| 314 explicit CompilationTask(CompilationHelper* helper) | 321 explicit CompilationTask(CompilationHelper* helper) |
| 315 : CancelableTask(helper->isolate_), helper_(helper) {} | 322 : CancelableTask(helper->isolate_), helper_(helper) {} |
| 316 | 323 |
| 317 void RunInternal() override { | 324 void RunInternal() override { |
| 318 while (helper_->FetchAndExecuteCompilationUnit()) { | 325 while (helper_->FetchAndExecuteCompilationUnit()) { |
| 319 } | 326 } |
| 320 helper_->module_->pending_tasks.get()->Signal(); | 327 helper_->module_->pending_tasks.get()->Signal(); |
| 321 } | 328 } |
| 322 }; | 329 }; |
| 323 | 330 |
| 324 Isolate* isolate_; | 331 Isolate* isolate_; |
| 325 std::unique_ptr<WasmModule> module_; | 332 std::unique_ptr<WasmModule> module_; |
| 333 bool is_sync_; |
| 326 std::vector<std::unique_ptr<compiler::WasmCompilationUnit>> | 334 std::vector<std::unique_ptr<compiler::WasmCompilationUnit>> |
| 327 compilation_units_; | 335 compilation_units_; |
| 328 std::queue<std::unique_ptr<compiler::WasmCompilationUnit>> executed_units_; | 336 std::queue<std::unique_ptr<compiler::WasmCompilationUnit>> executed_units_; |
| 329 base::Mutex result_mutex_; | 337 base::Mutex result_mutex_; |
| 330 base::AtomicNumber<size_t> next_unit_; | 338 base::AtomicNumber<size_t> next_unit_; |
| 331 size_t num_background_tasks_ = 0; | 339 size_t num_background_tasks_ = 0; |
| 332 | 340 |
| 333 // Run by each compilation task and by the main thread. | 341 // Run by each compilation task and by the main thread. |
| 334 bool FetchAndExecuteCompilationUnit() { | 342 bool FetchAndExecuteCompilationUnit() { |
| 335 DisallowHeapAllocation no_allocation; | 343 DisallowHeapAllocation no_allocation; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 353 | 361 |
| 354 size_t InitializeParallelCompilation( | 362 size_t InitializeParallelCompilation( |
| 355 const std::vector<WasmFunction>& functions, ModuleBytesEnv& module_env) { | 363 const std::vector<WasmFunction>& functions, ModuleBytesEnv& module_env) { |
| 356 uint32_t start = module_env.module_env.module->num_imported_functions + | 364 uint32_t start = module_env.module_env.module->num_imported_functions + |
| 357 FLAG_skip_compiling_wasm_funcs; | 365 FLAG_skip_compiling_wasm_funcs; |
| 358 uint32_t num_funcs = static_cast<uint32_t>(functions.size()); | 366 uint32_t num_funcs = static_cast<uint32_t>(functions.size()); |
| 359 uint32_t funcs_to_compile = start > num_funcs ? 0 : num_funcs - start; | 367 uint32_t funcs_to_compile = start > num_funcs ? 0 : num_funcs - start; |
| 360 compilation_units_.reserve(funcs_to_compile); | 368 compilation_units_.reserve(funcs_to_compile); |
| 361 for (uint32_t i = start; i < num_funcs; ++i) { | 369 for (uint32_t i = start; i < num_funcs; ++i) { |
| 362 const WasmFunction* func = &functions[i]; | 370 const WasmFunction* func = &functions[i]; |
| 371 constexpr bool is_sync = true; |
| 363 compilation_units_.push_back( | 372 compilation_units_.push_back( |
| 364 std::unique_ptr<compiler::WasmCompilationUnit>( | 373 std::unique_ptr<compiler::WasmCompilationUnit>( |
| 365 new compiler::WasmCompilationUnit(isolate_, &module_env, func))); | 374 new compiler::WasmCompilationUnit(isolate_, &module_env, func, |
| 375 !is_sync))); |
| 366 } | 376 } |
| 367 return funcs_to_compile; | 377 return funcs_to_compile; |
| 368 } | 378 } |
| 369 | 379 |
| 370 void InitializeHandles() { | 380 void InitializeHandles() { |
| 371 for (auto& unit : compilation_units_) { | 381 for (auto& unit : compilation_units_) { |
| 372 unit->InitializeHandles(); | 382 unit->InitializeHandles(); |
| 373 } | 383 } |
| 374 } | 384 } |
| 375 | 385 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 factory->NewFixedArray(function_table_count, TENURED); | 531 factory->NewFixedArray(function_table_count, TENURED); |
| 522 Handle<FixedArray> signature_tables = | 532 Handle<FixedArray> signature_tables = |
| 523 factory->NewFixedArray(function_table_count, TENURED); | 533 factory->NewFixedArray(function_table_count, TENURED); |
| 524 for (int i = 0; i < function_table_count; ++i) { | 534 for (int i = 0; i < function_table_count; ++i) { |
| 525 temp_instance.function_tables[i] = factory->NewFixedArray(1, TENURED); | 535 temp_instance.function_tables[i] = factory->NewFixedArray(1, TENURED); |
| 526 temp_instance.signature_tables[i] = factory->NewFixedArray(1, TENURED); | 536 temp_instance.signature_tables[i] = factory->NewFixedArray(1, TENURED); |
| 527 function_tables->set(i, *temp_instance.function_tables[i]); | 537 function_tables->set(i, *temp_instance.function_tables[i]); |
| 528 signature_tables->set(i, *temp_instance.signature_tables[i]); | 538 signature_tables->set(i, *temp_instance.signature_tables[i]); |
| 529 } | 539 } |
| 530 | 540 |
| 531 HistogramTimerScope wasm_compile_module_time_scope( | 541 if (is_sync_) { |
| 532 module_->is_wasm() | 542 // TODO(karlschimpf): Make this work when asynchronous. |
| 533 ? isolate_->counters()->wasm_compile_wasm_module_time() | 543 // https://bugs.chromium.org/p/v8/issues/detail?id=6361 |
| 534 : isolate_->counters()->wasm_compile_asm_module_time()); | 544 HistogramTimerScope wasm_compile_module_time_scope( |
| 545 module_->is_wasm() |
| 546 ? isolate_->counters()->wasm_compile_wasm_module_time() |
| 547 : isolate_->counters()->wasm_compile_asm_module_time()); |
| 548 return CompileToModuleObjectInternal( |
| 549 thrower, wire_bytes, asm_js_script, asm_js_offset_table_bytes, |
| 550 factory, &temp_instance, &function_tables, &signature_tables); |
| 551 } |
| 552 return CompileToModuleObjectInternal( |
| 553 thrower, wire_bytes, asm_js_script, asm_js_offset_table_bytes, factory, |
| 554 &temp_instance, &function_tables, &signature_tables); |
| 555 } |
| 535 | 556 |
| 536 ModuleBytesEnv module_env(module_.get(), &temp_instance, wire_bytes); | 557 private: |
| 558 MaybeHandle<WasmModuleObject> CompileToModuleObjectInternal( |
| 559 ErrorThrower* thrower, const ModuleWireBytes& wire_bytes, |
| 560 Handle<Script> asm_js_script, |
| 561 Vector<const byte> asm_js_offset_table_bytes, Factory* factory, |
| 562 WasmInstance* temp_instance, Handle<FixedArray>* function_tables, |
| 563 Handle<FixedArray>* signature_tables) { |
| 564 ModuleBytesEnv module_env(module_.get(), temp_instance, wire_bytes); |
| 537 | 565 |
| 538 // The {code_table} array contains import wrappers and functions (which | 566 // The {code_table} array contains import wrappers and functions (which |
| 539 // are both included in {functions.size()}, and export wrappers. | 567 // are both included in {functions.size()}, and export wrappers. |
| 540 int code_table_size = static_cast<int>(module_->functions.size() + | 568 int code_table_size = static_cast<int>(module_->functions.size() + |
| 541 module_->num_exported_functions); | 569 module_->num_exported_functions); |
| 542 Handle<FixedArray> code_table = | 570 Handle<FixedArray> code_table = |
| 543 factory->NewFixedArray(static_cast<int>(code_table_size), TENURED); | 571 factory->NewFixedArray(static_cast<int>(code_table_size), TENURED); |
| 544 | 572 |
| 545 // Check whether lazy compilation is enabled for this module. | 573 // Check whether lazy compilation is enabled for this module. |
| 546 bool lazy_compile = compile_lazy(module_.get()); | 574 bool lazy_compile = compile_lazy(module_.get()); |
| 547 | 575 |
| 548 // If lazy compile: Initialize the code table with the lazy compile builtin. | 576 // If lazy compile: Initialize the code table with the lazy compile builtin. |
| 549 // Otherwise: Initialize with the illegal builtin. All call sites will be | 577 // Otherwise: Initialize with the illegal builtin. All call sites will be |
| 550 // patched at instantiation. | 578 // patched at instantiation. |
| 551 Handle<Code> init_builtin = lazy_compile | 579 Handle<Code> init_builtin = lazy_compile |
| 552 ? isolate_->builtins()->WasmCompileLazy() | 580 ? isolate_->builtins()->WasmCompileLazy() |
| 553 : isolate_->builtins()->Illegal(); | 581 : isolate_->builtins()->Illegal(); |
| 554 for (int i = 0, e = static_cast<int>(module_->functions.size()); i < e; | 582 for (int i = 0, e = static_cast<int>(module_->functions.size()); i < e; |
| 555 ++i) { | 583 ++i) { |
| 556 code_table->set(i, *init_builtin); | 584 code_table->set(i, *init_builtin); |
| 557 temp_instance.function_code[i] = init_builtin; | 585 temp_instance->function_code[i] = init_builtin; |
| 558 } | 586 } |
| 559 | 587 |
| 560 (module_->is_wasm() ? isolate_->counters()->wasm_functions_per_wasm_module() | 588 if (is_sync_) |
| 561 : isolate_->counters()->wasm_functions_per_asm_module()) | 589 // TODO(karlschimpf): Make this work when asynchronous. |
| 562 ->AddSample(static_cast<int>(module_->functions.size())); | 590 // https://bugs.chromium.org/p/v8/issues/detail?id=6361 |
| 591 (module_->is_wasm() |
| 592 ? isolate_->counters()->wasm_functions_per_wasm_module() |
| 593 : isolate_->counters()->wasm_functions_per_asm_module()) |
| 594 ->AddSample(static_cast<int>(module_->functions.size())); |
| 563 | 595 |
| 564 if (!lazy_compile) { | 596 if (!lazy_compile) { |
| 565 size_t funcs_to_compile = | 597 size_t funcs_to_compile = |
| 566 module_->functions.size() - module_->num_imported_functions; | 598 module_->functions.size() - module_->num_imported_functions; |
| 567 if (!FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks != 0 && | 599 if (!FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks != 0 && |
| 568 funcs_to_compile > 1) { | 600 funcs_to_compile > 1) { |
| 569 // Avoid a race condition by collecting results into a second vector. | 601 // Avoid a race condition by collecting results into a second vector. |
| 570 std::vector<Handle<Code>> results(temp_instance.function_code); | 602 std::vector<Handle<Code>> results(temp_instance->function_code); |
| 571 CompileInParallel(&module_env, results, thrower); | 603 CompileInParallel(&module_env, results, thrower); |
| 572 temp_instance.function_code.swap(results); | 604 temp_instance->function_code.swap(results); |
| 573 } else { | 605 } else { |
| 574 CompileSequentially(&module_env, temp_instance.function_code, thrower); | 606 CompileSequentially(&module_env, temp_instance->function_code, thrower); |
| 575 } | 607 } |
| 576 if (thrower->error()) return {}; | 608 if (thrower->error()) return {}; |
| 577 } | 609 } |
| 578 | 610 |
| 579 // At this point, compilation has completed. Update the code table. | 611 // At this point, compilation has completed. Update the code table. |
| 580 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 612 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
| 581 i < temp_instance.function_code.size(); ++i) { | 613 i < temp_instance->function_code.size(); ++i) { |
| 582 Code* code = *temp_instance.function_code[i]; | 614 Code* code = *temp_instance->function_code[i]; |
| 583 code_table->set(static_cast<int>(i), code); | 615 code_table->set(static_cast<int>(i), code); |
| 584 RecordStats(isolate_, code); | 616 RecordStats(isolate_, code, is_sync_); |
| 585 } | 617 } |
| 586 | 618 |
| 587 // Create heap objects for script, module bytes and asm.js offset table to | 619 // Create heap objects for script, module bytes and asm.js offset table to |
| 588 // be stored in the shared module data. | 620 // be stored in the shared module data. |
| 589 Handle<Script> script; | 621 Handle<Script> script; |
| 590 Handle<ByteArray> asm_js_offset_table; | 622 Handle<ByteArray> asm_js_offset_table; |
| 591 if (asm_js_script.is_null()) { | 623 if (asm_js_script.is_null()) { |
| 592 script = CreateWasmScript(isolate_, wire_bytes); | 624 script = CreateWasmScript(isolate_, wire_bytes); |
| 593 } else { | 625 } else { |
| 594 script = asm_js_script; | 626 script = asm_js_script; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 620 Handle<WasmSharedModuleData> shared = WasmSharedModuleData::New( | 652 Handle<WasmSharedModuleData> shared = WasmSharedModuleData::New( |
| 621 isolate_, module_wrapper, Handle<SeqOneByteString>::cast(module_bytes), | 653 isolate_, module_wrapper, Handle<SeqOneByteString>::cast(module_bytes), |
| 622 script, asm_js_offset_table); | 654 script, asm_js_offset_table); |
| 623 if (lazy_compile) WasmSharedModuleData::PrepareForLazyCompilation(shared); | 655 if (lazy_compile) WasmSharedModuleData::PrepareForLazyCompilation(shared); |
| 624 | 656 |
| 625 // Create the compiled module object, and populate with compiled functions | 657 // Create the compiled module object, and populate with compiled functions |
| 626 // and information needed at instantiation time. This object needs to be | 658 // and information needed at instantiation time. This object needs to be |
| 627 // serializable. Instantiation may occur off a deserialized version of this | 659 // serializable. Instantiation may occur off a deserialized version of this |
| 628 // object. | 660 // object. |
| 629 Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New( | 661 Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New( |
| 630 isolate_, shared, code_table, function_tables, signature_tables); | 662 isolate_, shared, code_table, *function_tables, *signature_tables); |
| 631 | 663 |
| 632 // If we created a wasm script, finish it now and make it public to the | 664 // If we created a wasm script, finish it now and make it public to the |
| 633 // debugger. | 665 // debugger. |
| 634 if (asm_js_script.is_null()) { | 666 if (asm_js_script.is_null()) { |
| 635 script->set_wasm_compiled_module(*compiled_module); | 667 script->set_wasm_compiled_module(*compiled_module); |
| 636 isolate_->debug()->OnAfterCompile(script); | 668 isolate_->debug()->OnAfterCompile(script); |
| 637 } | 669 } |
| 638 | 670 |
| 639 // Compile JS->WASM wrappers for exported functions. | 671 // Compile JS->WASM wrappers for exported functions. |
| 640 JSToWasmWrapperCache js_to_wasm_cache; | 672 JSToWasmWrapperCache js_to_wasm_cache; |
| 641 int func_index = 0; | 673 int func_index = 0; |
| 642 for (auto exp : module->export_table) { | 674 for (auto exp : module->export_table) { |
| 643 if (exp.kind != kExternalFunction) continue; | 675 if (exp.kind != kExternalFunction) continue; |
| 644 Handle<Code> wasm_code = EnsureExportedLazyDeoptData( | 676 Handle<Code> wasm_code = EnsureExportedLazyDeoptData( |
| 645 isolate_, Handle<WasmInstanceObject>::null(), code_table, exp.index); | 677 isolate_, Handle<WasmInstanceObject>::null(), code_table, exp.index); |
| 646 Handle<Code> wrapper_code = | 678 Handle<Code> wrapper_code = |
| 647 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(isolate_, module, | 679 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(isolate_, module, |
| 648 wasm_code, exp.index); | 680 wasm_code, exp.index); |
| 649 int export_index = | 681 int export_index = |
| 650 static_cast<int>(module->functions.size() + func_index); | 682 static_cast<int>(module->functions.size() + func_index); |
| 651 code_table->set(export_index, *wrapper_code); | 683 code_table->set(export_index, *wrapper_code); |
| 652 RecordStats(isolate_, *wrapper_code); | 684 RecordStats(isolate_, *wrapper_code, is_sync_); |
| 653 func_index++; | 685 func_index++; |
| 654 } | 686 } |
| 655 | 687 |
| 656 return WasmModuleObject::New(isolate_, compiled_module); | 688 return WasmModuleObject::New(isolate_, compiled_module); |
| 657 } | 689 } |
| 658 }; | 690 }; |
| 659 | 691 |
| 660 static void MemoryInstanceFinalizer(Isolate* isolate, | 692 static void MemoryInstanceFinalizer(Isolate* isolate, |
| 661 WasmInstanceObject* instance) { | 693 WasmInstanceObject* instance) { |
| 662 DisallowHeapAllocation no_gc; | 694 DisallowHeapAllocation no_gc; |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1132 case Code::JS_TO_WASM_FUNCTION: | 1164 case Code::JS_TO_WASM_FUNCTION: |
| 1133 case Code::WASM_FUNCTION: { | 1165 case Code::WASM_FUNCTION: { |
| 1134 Handle<Code> code = factory->CopyCode(orig_code); | 1166 Handle<Code> code = factory->CopyCode(orig_code); |
| 1135 code_table->set(i, *code); | 1167 code_table->set(i, *code); |
| 1136 break; | 1168 break; |
| 1137 } | 1169 } |
| 1138 default: | 1170 default: |
| 1139 UNREACHABLE(); | 1171 UNREACHABLE(); |
| 1140 } | 1172 } |
| 1141 } | 1173 } |
| 1142 RecordStats(isolate_, code_table); | 1174 RecordStats(isolate_, code_table, is_sync_); |
| 1143 } else { | 1175 } else { |
| 1144 // There was no owner, so we can reuse the original. | 1176 // There was no owner, so we can reuse the original. |
| 1145 compiled_module_ = original; | 1177 compiled_module_ = original; |
| 1146 old_code_table = | 1178 old_code_table = |
| 1147 factory->CopyFixedArray(compiled_module_->code_table()); | 1179 factory->CopyFixedArray(compiled_module_->code_table()); |
| 1148 code_table = compiled_module_->code_table(); | 1180 code_table = compiled_module_->code_table(); |
| 1149 TRACE("Reusing existing instance %d\n", | 1181 TRACE("Reusing existing instance %d\n", |
| 1150 compiled_module_->instance_id()); | 1182 compiled_module_->instance_id()); |
| 1151 } | 1183 } |
| 1152 compiled_module_->set_native_context(isolate_->native_context()); | 1184 compiled_module_->set_native_context(isolate_->native_context()); |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1409 int start_index = module_->start_function_index; | 1441 int start_index = module_->start_function_index; |
| 1410 Handle<Code> startup_code = EnsureExportedLazyDeoptData( | 1442 Handle<Code> startup_code = EnsureExportedLazyDeoptData( |
| 1411 isolate_, instance, code_table, start_index); | 1443 isolate_, instance, code_table, start_index); |
| 1412 FunctionSig* sig = module_->functions[start_index].sig; | 1444 FunctionSig* sig = module_->functions[start_index].sig; |
| 1413 Handle<Code> wrapper_code = | 1445 Handle<Code> wrapper_code = |
| 1414 js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper( | 1446 js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper( |
| 1415 isolate_, module_, startup_code, start_index); | 1447 isolate_, module_, startup_code, start_index); |
| 1416 Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New( | 1448 Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New( |
| 1417 isolate_, instance, MaybeHandle<String>(), start_index, | 1449 isolate_, instance, MaybeHandle<String>(), start_index, |
| 1418 static_cast<int>(sig->parameter_count()), wrapper_code); | 1450 static_cast<int>(sig->parameter_count()), wrapper_code); |
| 1419 RecordStats(isolate_, *startup_code); | 1451 RecordStats(isolate_, *startup_code, is_sync_); |
| 1420 // Call the JS function. | 1452 // Call the JS function. |
| 1421 Handle<Object> undefined = factory->undefined_value(); | 1453 Handle<Object> undefined = factory->undefined_value(); |
| 1422 MaybeHandle<Object> retval = | 1454 MaybeHandle<Object> retval = |
| 1423 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); | 1455 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); |
| 1424 | 1456 |
| 1425 if (retval.is_null()) { | 1457 if (retval.is_null()) { |
| 1426 DCHECK(isolate_->has_pending_exception()); | 1458 DCHECK(isolate_->has_pending_exception()); |
| 1427 isolate_->OptionalRescheduleException(false); | 1459 isolate_->OptionalRescheduleException(false); |
| 1428 // It's unfortunate that the new instance is already linked in the | 1460 // It's unfortunate that the new instance is already linked in the |
| 1429 // chain. However, we need to set up everything before executing the | 1461 // chain. However, we need to set up everything before executing the |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1443 // Represents the initialized state of a table. | 1475 // Represents the initialized state of a table. |
| 1444 struct TableInstance { | 1476 struct TableInstance { |
| 1445 Handle<WasmTableObject> table_object; // WebAssembly.Table instance | 1477 Handle<WasmTableObject> table_object; // WebAssembly.Table instance |
| 1446 Handle<FixedArray> js_wrappers; // JSFunctions exported | 1478 Handle<FixedArray> js_wrappers; // JSFunctions exported |
| 1447 Handle<FixedArray> function_table; // internal code array | 1479 Handle<FixedArray> function_table; // internal code array |
| 1448 Handle<FixedArray> signature_table; // internal sig array | 1480 Handle<FixedArray> signature_table; // internal sig array |
| 1449 }; | 1481 }; |
| 1450 | 1482 |
| 1451 Isolate* isolate_; | 1483 Isolate* isolate_; |
| 1452 WasmModule* const module_; | 1484 WasmModule* const module_; |
| 1485 constexpr static bool is_sync_ = true; |
| 1453 ErrorThrower* thrower_; | 1486 ErrorThrower* thrower_; |
| 1454 Handle<WasmModuleObject> module_object_; | 1487 Handle<WasmModuleObject> module_object_; |
| 1455 Handle<JSReceiver> ffi_; // TODO(titzer): Use MaybeHandle | 1488 Handle<JSReceiver> ffi_; // TODO(titzer): Use MaybeHandle |
| 1456 Handle<JSArrayBuffer> memory_; // TODO(titzer): Use MaybeHandle | 1489 Handle<JSArrayBuffer> memory_; // TODO(titzer): Use MaybeHandle |
| 1457 Handle<JSArrayBuffer> globals_; | 1490 Handle<JSArrayBuffer> globals_; |
| 1458 Handle<WasmCompiledModule> compiled_module_; | 1491 Handle<WasmCompiledModule> compiled_module_; |
| 1459 std::vector<TableInstance> table_instances_; | 1492 std::vector<TableInstance> table_instances_; |
| 1460 std::vector<Handle<JSFunction>> js_wrappers_; | 1493 std::vector<Handle<JSFunction>> js_wrappers_; |
| 1461 JSToWasmWrapperCache js_to_wasm_cache_; | 1494 JSToWasmWrapperCache js_to_wasm_cache_; |
| 1462 | 1495 |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1614 isolate_, index, module_->functions[import.index].sig, | 1647 isolate_, index, module_->functions[import.index].sig, |
| 1615 Handle<JSReceiver>::cast(value), module_name, import_name, | 1648 Handle<JSReceiver>::cast(value), module_name, import_name, |
| 1616 module_->get_origin()); | 1649 module_->get_origin()); |
| 1617 if (import_wrapper.is_null()) { | 1650 if (import_wrapper.is_null()) { |
| 1618 ReportLinkError( | 1651 ReportLinkError( |
| 1619 "imported function does not match the expected type", index, | 1652 "imported function does not match the expected type", index, |
| 1620 module_name, import_name); | 1653 module_name, import_name); |
| 1621 return -1; | 1654 return -1; |
| 1622 } | 1655 } |
| 1623 code_table->set(num_imported_functions, *import_wrapper); | 1656 code_table->set(num_imported_functions, *import_wrapper); |
| 1624 RecordStats(isolate_, *import_wrapper); | 1657 RecordStats(isolate_, *import_wrapper, is_sync_); |
| 1625 num_imported_functions++; | 1658 num_imported_functions++; |
| 1626 break; | 1659 break; |
| 1627 } | 1660 } |
| 1628 case kExternalTable: { | 1661 case kExternalTable: { |
| 1629 if (!WasmJs::IsWasmTableObject(isolate_, value)) { | 1662 if (!WasmJs::IsWasmTableObject(isolate_, value)) { |
| 1630 ReportLinkError("table import requires a WebAssembly.Table", index, | 1663 ReportLinkError("table import requires a WebAssembly.Table", index, |
| 1631 module_name, import_name); | 1664 module_name, import_name); |
| 1632 return -1; | 1665 return -1; |
| 1633 } | 1666 } |
| 1634 WasmIndirectFunctionTable& table = | 1667 WasmIndirectFunctionTable& table = |
| (...skipping 850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2485 | 2518 |
| 2486 ModuleResult result = DecodeWasmModule(isolate, bytes.start(), bytes.end(), | 2519 ModuleResult result = DecodeWasmModule(isolate, bytes.start(), bytes.end(), |
| 2487 false, kAsmJsOrigin); | 2520 false, kAsmJsOrigin); |
| 2488 if (result.failed()) { | 2521 if (result.failed()) { |
| 2489 thrower->CompileFailed("Wasm decoding failed", result); | 2522 thrower->CompileFailed("Wasm decoding failed", result); |
| 2490 return {}; | 2523 return {}; |
| 2491 } | 2524 } |
| 2492 | 2525 |
| 2493 // Transfer ownership to the {WasmModuleWrapper} generated in | 2526 // Transfer ownership to the {WasmModuleWrapper} generated in |
| 2494 // {CompileToModuleObject}. | 2527 // {CompileToModuleObject}. |
| 2495 CompilationHelper helper(isolate, std::move(result.val)); | 2528 constexpr bool is_sync = true; |
| 2529 CompilationHelper helper(isolate, std::move(result.val), is_sync); |
| 2496 return helper.CompileToModuleObject(thrower, bytes, asm_js_script, | 2530 return helper.CompileToModuleObject(thrower, bytes, asm_js_script, |
| 2497 asm_js_offset_table_bytes); | 2531 asm_js_offset_table_bytes); |
| 2498 } | 2532 } |
| 2499 | 2533 |
| 2500 MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate, | 2534 MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate, |
| 2501 ErrorThrower* thrower, | 2535 ErrorThrower* thrower, |
| 2502 const ModuleWireBytes& bytes) { | 2536 const ModuleWireBytes& bytes) { |
| 2503 if (!IsWasmCodegenAllowed(isolate, isolate->native_context())) { | 2537 if (!IsWasmCodegenAllowed(isolate, isolate->native_context())) { |
| 2504 thrower->CompileError("Wasm code generation disallowed in this context"); | 2538 thrower->CompileError("Wasm code generation disallowed in this context"); |
| 2505 return {}; | 2539 return {}; |
| 2506 } | 2540 } |
| 2507 | 2541 |
| 2508 ModuleResult result = | 2542 ModuleResult result = |
| 2509 DecodeWasmModule(isolate, bytes.start(), bytes.end(), false, kWasmOrigin); | 2543 DecodeWasmModule(isolate, bytes.start(), bytes.end(), false, kWasmOrigin); |
| 2510 if (result.failed()) { | 2544 if (result.failed()) { |
| 2511 thrower->CompileFailed("Wasm decoding failed", result); | 2545 thrower->CompileFailed("Wasm decoding failed", result); |
| 2512 return {}; | 2546 return {}; |
| 2513 } | 2547 } |
| 2514 | 2548 |
| 2515 // Transfer ownership to the {WasmModuleWrapper} generated in | 2549 // Transfer ownership to the {WasmModuleWrapper} generated in |
| 2516 // {CompileToModuleObject}. | 2550 // {CompileToModuleObject}. |
| 2517 CompilationHelper helper(isolate, std::move(result.val)); | 2551 constexpr bool is_sync = true; |
| 2552 CompilationHelper helper(isolate, std::move(result.val), is_sync); |
| 2518 return helper.CompileToModuleObject(thrower, bytes, Handle<Script>(), | 2553 return helper.CompileToModuleObject(thrower, bytes, Handle<Script>(), |
| 2519 Vector<const byte>()); | 2554 Vector<const byte>()); |
| 2520 } | 2555 } |
| 2521 | 2556 |
| 2522 MaybeHandle<WasmInstanceObject> wasm::SyncInstantiate( | 2557 MaybeHandle<WasmInstanceObject> wasm::SyncInstantiate( |
| 2523 Isolate* isolate, ErrorThrower* thrower, | 2558 Isolate* isolate, ErrorThrower* thrower, |
| 2524 Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports, | 2559 Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports, |
| 2525 MaybeHandle<JSArrayBuffer> memory) { | 2560 MaybeHandle<JSArrayBuffer> memory) { |
| 2526 InstantiationHelper helper(isolate, thrower, module_object, imports, memory); | 2561 InstantiationHelper helper(isolate, thrower, module_object, imports, memory); |
| 2527 return helper.Build(); | 2562 return helper.Build(); |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2691 // Step 1: (async) Decode the module. | 2726 // Step 1: (async) Decode the module. |
| 2692 //========================================================================== | 2727 //========================================================================== |
| 2693 class DecodeModule : public CompileTask<ASYNC> { | 2728 class DecodeModule : public CompileTask<ASYNC> { |
| 2694 void Run() override { | 2729 void Run() override { |
| 2695 ModuleResult result; | 2730 ModuleResult result; |
| 2696 { | 2731 { |
| 2697 DisallowHandleAllocation no_handle; | 2732 DisallowHandleAllocation no_handle; |
| 2698 DisallowHeapAllocation no_allocation; | 2733 DisallowHeapAllocation no_allocation; |
| 2699 // Decode the module bytes. | 2734 // Decode the module bytes. |
| 2700 TRACE_COMPILE("(1) Decoding module...\n"); | 2735 TRACE_COMPILE("(1) Decoding module...\n"); |
| 2736 constexpr bool is_sync = true; |
| 2701 result = DecodeWasmModule(job_->isolate_, job_->wire_bytes_.start(), | 2737 result = DecodeWasmModule(job_->isolate_, job_->wire_bytes_.start(), |
| 2702 job_->wire_bytes_.end(), false, kWasmOrigin); | 2738 job_->wire_bytes_.end(), false, kWasmOrigin, |
| 2739 !is_sync); |
| 2703 } | 2740 } |
| 2704 if (result.failed()) { | 2741 if (result.failed()) { |
| 2705 // Decoding failure; reject the promise and clean up. | 2742 // Decoding failure; reject the promise and clean up. |
| 2706 job_->DoSync<DecodeFail>(std::move(result)); | 2743 job_->DoSync<DecodeFail>(std::move(result)); |
| 2707 } else { | 2744 } else { |
| 2708 // Decode passed. | 2745 // Decode passed. |
| 2709 job_->DoSync<PrepareAndStartCompile>(std::move(result.val)); | 2746 job_->DoSync<PrepareAndStartCompile>(std::move(result.val)); |
| 2710 } | 2747 } |
| 2711 } | 2748 } |
| 2712 }; | 2749 }; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2785 job_->code_table_->set(static_cast<int>(i), *illegal_builtin); | 2822 job_->code_table_->set(static_cast<int>(i), *illegal_builtin); |
| 2786 job_->temp_instance_->function_code[i] = illegal_builtin; | 2823 job_->temp_instance_->function_code[i] = illegal_builtin; |
| 2787 } | 2824 } |
| 2788 | 2825 |
| 2789 job_->isolate_->counters()->wasm_functions_per_wasm_module()->AddSample( | 2826 job_->isolate_->counters()->wasm_functions_per_wasm_module()->AddSample( |
| 2790 static_cast<int>(module_->functions.size())); | 2827 static_cast<int>(module_->functions.size())); |
| 2791 | 2828 |
| 2792 // Transfer ownership of the {WasmModule} to the {CompilationHelper}, but | 2829 // Transfer ownership of the {WasmModule} to the {CompilationHelper}, but |
| 2793 // keep a pointer. | 2830 // keep a pointer. |
| 2794 WasmModule* module = module_.get(); | 2831 WasmModule* module = module_.get(); |
| 2832 constexpr bool is_sync = true; |
| 2795 job_->helper_.reset( | 2833 job_->helper_.reset( |
| 2796 new CompilationHelper(job_->isolate_, std::move(module_))); | 2834 new CompilationHelper(job_->isolate_, std::move(module_), !is_sync)); |
| 2797 | 2835 |
| 2798 DCHECK_LE(module->num_imported_functions, module->functions.size()); | 2836 DCHECK_LE(module->num_imported_functions, module->functions.size()); |
| 2799 size_t num_functions = | 2837 size_t num_functions = |
| 2800 module->functions.size() - module->num_imported_functions; | 2838 module->functions.size() - module->num_imported_functions; |
| 2801 if (num_functions == 0) { | 2839 if (num_functions == 0) { |
| 2802 job_->ReopenHandlesInDeferredScope(); | 2840 job_->ReopenHandlesInDeferredScope(); |
| 2803 // Degenerate case of an empty module. | 2841 // Degenerate case of an empty module. |
| 2804 job_->DoSync<FinishCompile>(); | 2842 job_->DoSync<FinishCompile>(); |
| 2805 return; | 2843 return; |
| 2806 } | 2844 } |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2927 }; | 2965 }; |
| 2928 | 2966 |
| 2929 //========================================================================== | 2967 //========================================================================== |
| 2930 // Step 5b (sync): Finish heap-allocated data structures. | 2968 // Step 5b (sync): Finish heap-allocated data structures. |
| 2931 //========================================================================== | 2969 //========================================================================== |
| 2932 class FinishCompile : public SyncCompileTask { | 2970 class FinishCompile : public SyncCompileTask { |
| 2933 void RunImpl() override { | 2971 void RunImpl() override { |
| 2934 TRACE_COMPILE("(5b) Finish compile...\n"); | 2972 TRACE_COMPILE("(5b) Finish compile...\n"); |
| 2935 HandleScope scope(job_->isolate_); | 2973 HandleScope scope(job_->isolate_); |
| 2936 // At this point, compilation has completed. Update the code table. | 2974 // At this point, compilation has completed. Update the code table. |
| 2975 constexpr bool is_sync = true; |
| 2937 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 2976 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
| 2938 i < job_->temp_instance_->function_code.size(); ++i) { | 2977 i < job_->temp_instance_->function_code.size(); ++i) { |
| 2939 Code* code = Code::cast(job_->code_table_->get(static_cast<int>(i))); | 2978 Code* code = Code::cast(job_->code_table_->get(static_cast<int>(i))); |
| 2940 RecordStats(job_->isolate_, code); | 2979 RecordStats(job_->isolate_, code, !is_sync); |
| 2941 } | 2980 } |
| 2942 | 2981 |
| 2943 // Create heap objects for script and module bytes to be stored in the | 2982 // Create heap objects for script and module bytes to be stored in the |
| 2944 // shared module data. Asm.js is not compiled asynchronously. | 2983 // shared module data. Asm.js is not compiled asynchronously. |
| 2945 Handle<Script> script = | 2984 Handle<Script> script = |
| 2946 CreateWasmScript(job_->isolate_, job_->wire_bytes_); | 2985 CreateWasmScript(job_->isolate_, job_->wire_bytes_); |
| 2947 Handle<ByteArray> asm_js_offset_table; | 2986 Handle<ByteArray> asm_js_offset_table; |
| 2948 // TODO(wasm): Improve efficiency of storing module wire bytes. | 2987 // TODO(wasm): Improve efficiency of storing module wire bytes. |
| 2949 // 1. Only store relevant sections, not function bodies | 2988 // 1. Only store relevant sections, not function bodies |
| 2950 // 2. Don't make a second copy of the bytes here; reuse the copy made | 2989 // 2. Don't make a second copy of the bytes here; reuse the copy made |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2996 //========================================================================== | 3035 //========================================================================== |
| 2997 // Step 6 (sync): Compile JS->WASM wrappers. | 3036 // Step 6 (sync): Compile JS->WASM wrappers. |
| 2998 //========================================================================== | 3037 //========================================================================== |
| 2999 class CompileWrappers : public SyncCompileTask { | 3038 class CompileWrappers : public SyncCompileTask { |
| 3000 void RunImpl() override { | 3039 void RunImpl() override { |
| 3001 TRACE_COMPILE("(6) Compile wrappers...\n"); | 3040 TRACE_COMPILE("(6) Compile wrappers...\n"); |
| 3002 // Compile JS->WASM wrappers for exported functions. | 3041 // Compile JS->WASM wrappers for exported functions. |
| 3003 HandleScope scope(job_->isolate_); | 3042 HandleScope scope(job_->isolate_); |
| 3004 JSToWasmWrapperCache js_to_wasm_cache; | 3043 JSToWasmWrapperCache js_to_wasm_cache; |
| 3005 int func_index = 0; | 3044 int func_index = 0; |
| 3045 constexpr bool is_sync = true; |
| 3006 WasmModule* module = job_->compiled_module_->module(); | 3046 WasmModule* module = job_->compiled_module_->module(); |
| 3007 for (auto exp : module->export_table) { | 3047 for (auto exp : module->export_table) { |
| 3008 if (exp.kind != kExternalFunction) continue; | 3048 if (exp.kind != kExternalFunction) continue; |
| 3009 Handle<Code> wasm_code(Code::cast(job_->code_table_->get(exp.index)), | 3049 Handle<Code> wasm_code(Code::cast(job_->code_table_->get(exp.index)), |
| 3010 job_->isolate_); | 3050 job_->isolate_); |
| 3011 Handle<Code> wrapper_code = | 3051 Handle<Code> wrapper_code = |
| 3012 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper( | 3052 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper( |
| 3013 job_->isolate_, module, wasm_code, exp.index); | 3053 job_->isolate_, module, wasm_code, exp.index); |
| 3014 int export_index = | 3054 int export_index = |
| 3015 static_cast<int>(module->functions.size() + func_index); | 3055 static_cast<int>(module->functions.size() + func_index); |
| 3016 job_->code_table_->set(export_index, *wrapper_code); | 3056 job_->code_table_->set(export_index, *wrapper_code); |
| 3017 RecordStats(job_->isolate_, *wrapper_code); | 3057 RecordStats(job_->isolate_, *wrapper_code, !is_sync); |
| 3018 func_index++; | 3058 func_index++; |
| 3019 } | 3059 } |
| 3020 | 3060 |
| 3021 job_->DoSync<FinishModule>(); | 3061 job_->DoSync<FinishModule>(); |
| 3022 } | 3062 } |
| 3023 }; | 3063 }; |
| 3024 | 3064 |
| 3025 //========================================================================== | 3065 //========================================================================== |
| 3026 // Step 7 (sync): Finish the module and resolve the promise. | 3066 // Step 7 (sync): Finish the module and resolve the promise. |
| 3027 //========================================================================== | 3067 //========================================================================== |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3314 callee_compiled->instruction_start()); | 3354 callee_compiled->instruction_start()); |
| 3315 } | 3355 } |
| 3316 DCHECK_EQ(non_compiled_functions.size(), idx); | 3356 DCHECK_EQ(non_compiled_functions.size(), idx); |
| 3317 } | 3357 } |
| 3318 | 3358 |
| 3319 Code* ret = | 3359 Code* ret = |
| 3320 Code::cast(compiled_module->code_table()->get(func_to_return_idx)); | 3360 Code::cast(compiled_module->code_table()->get(func_to_return_idx)); |
| 3321 DCHECK_EQ(Code::WASM_FUNCTION, ret->kind()); | 3361 DCHECK_EQ(Code::WASM_FUNCTION, ret->kind()); |
| 3322 return handle(ret, isolate); | 3362 return handle(ret, isolate); |
| 3323 } | 3363 } |
| OLD | NEW |