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 |