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 <functional> | 5 #include <functional> |
6 #include <memory> | 6 #include <memory> |
7 | 7 |
8 #include "src/asmjs/asm-js.h" | 8 #include "src/asmjs/asm-js.h" |
9 #include "src/assembler-inl.h" | 9 #include "src/assembler-inl.h" |
10 #include "src/base/atomic-utils.h" | 10 #include "src/base/atomic-utils.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 } while (false) | 48 } while (false) |
49 | 49 |
50 namespace { | 50 namespace { |
51 | 51 |
52 static const int kInvalidSigIndex = -1; | 52 static const int kInvalidSigIndex = -1; |
53 | 53 |
54 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { | 54 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { |
55 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; | 55 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; |
56 } | 56 } |
57 | 57 |
58 static void RecordStats(Isolate* isolate, Code* code, bool is_sync) { | 58 static void RecordStats(Isolate* isolate, Code* code, Counters* counters) { |
59 if (is_sync) { | 59 counters->wasm_generated_code_size()->Increment(code->body_size()); |
60 // TODO(karlschimpf): Make this work when asynchronous. | 60 counters->wasm_reloc_size()->Increment(code->relocation_info()->length()); |
61 // https://bugs.chromium.org/p/v8/issues/detail?id=6361 | 61 } |
62 isolate->counters()->wasm_generated_code_size()->Increment( | 62 |
63 code->body_size()); | 63 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions, |
64 isolate->counters()->wasm_reloc_size()->Increment( | 64 Counters* counters) { |
65 code->relocation_info()->length()); | 65 DisallowHeapAllocation no_gc; |
| 66 for (int i = 0; i < functions->length(); ++i) { |
| 67 RecordStats(isolate, Code::cast(functions->get(i)), counters); |
66 } | 68 } |
67 } | 69 } |
68 | 70 |
69 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions, | |
70 bool is_sync) { | |
71 DisallowHeapAllocation no_gc; | |
72 for (int i = 0; i < functions->length(); ++i) { | |
73 RecordStats(isolate, Code::cast(functions->get(i)), is_sync); | |
74 } | |
75 } | |
76 | |
77 void* TryAllocateBackingStore(Isolate* isolate, size_t size, | 71 void* TryAllocateBackingStore(Isolate* isolate, size_t size, |
78 bool enable_guard_regions, void*& allocation_base, | 72 bool enable_guard_regions, void*& allocation_base, |
79 size_t& allocation_length) { | 73 size_t& allocation_length) { |
80 // TODO(eholk): Right now enable_guard_regions has no effect on 32-bit | 74 // TODO(eholk): Right now enable_guard_regions has no effect on 32-bit |
81 // systems. It may be safer to fail instead, given that other code might do | 75 // systems. It may be safer to fail instead, given that other code might do |
82 // things that would be unsafe if they expected guard pages where there | 76 // things that would be unsafe if they expected guard pages where there |
83 // weren't any. | 77 // weren't any. |
84 if (enable_guard_regions && kGuardRegionsSupported) { | 78 if (enable_guard_regions && kGuardRegionsSupported) { |
85 // TODO(eholk): On Windows we want to make sure we don't commit the guard | 79 // TODO(eholk): On Windows we want to make sure we don't commit the guard |
86 // pages yet. | 80 // pages yet. |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 | 286 |
293 // A helper for compiling an entire module. | 287 // A helper for compiling an entire module. |
294 class CompilationHelper { | 288 class CompilationHelper { |
295 public: | 289 public: |
296 // The compilation helper takes ownership of the {WasmModule}. | 290 // The compilation helper takes ownership of the {WasmModule}. |
297 // In {CompileToModuleObject}, it will transfer ownership to the generated | 291 // In {CompileToModuleObject}, it will transfer ownership to the generated |
298 // {WasmModuleWrapper}. If this method is not called, ownership may be | 292 // {WasmModuleWrapper}. If this method is not called, ownership may be |
299 // reclaimed by explicitely releasing the {module_} field. | 293 // reclaimed by explicitely releasing the {module_} field. |
300 CompilationHelper(Isolate* isolate, std::unique_ptr<WasmModule> module, | 294 CompilationHelper(Isolate* isolate, std::unique_ptr<WasmModule> module, |
301 bool is_sync) | 295 bool is_sync) |
302 : isolate_(isolate), module_(std::move(module)), is_sync_(is_sync) {} | 296 : isolate_(isolate), |
| 297 module_(std::move(module)), |
| 298 counters_shared_(isolate->counters_shared()), |
| 299 is_sync_(is_sync) { |
| 300 counters_ = counters_shared_.get(); |
| 301 } |
303 | 302 |
304 // The actual runnable task that performs compilations in the background. | 303 // The actual runnable task that performs compilations in the background. |
305 class CompilationTask : public CancelableTask { | 304 class CompilationTask : public CancelableTask { |
306 public: | 305 public: |
307 CompilationHelper* helper_; | 306 CompilationHelper* helper_; |
308 explicit CompilationTask(CompilationHelper* helper) | 307 explicit CompilationTask(CompilationHelper* helper) |
309 : CancelableTask(helper->isolate_), helper_(helper) {} | 308 : CancelableTask(helper->isolate_), helper_(helper) {} |
310 | 309 |
311 void RunInternal() override { | 310 void RunInternal() override { |
312 while (helper_->FetchAndExecuteCompilationUnit()) { | 311 while (helper_->FetchAndExecuteCompilationUnit()) { |
313 } | 312 } |
314 helper_->module_->pending_tasks.get()->Signal(); | 313 helper_->module_->pending_tasks.get()->Signal(); |
315 } | 314 } |
316 }; | 315 }; |
317 | 316 |
318 Isolate* isolate_; | 317 Isolate* isolate_; |
319 std::unique_ptr<WasmModule> module_; | 318 std::unique_ptr<WasmModule> module_; |
| 319 std::shared_ptr<Counters> counters_shared_; |
| 320 Counters* counters_; |
320 bool is_sync_; | 321 bool is_sync_; |
321 std::vector<std::unique_ptr<compiler::WasmCompilationUnit>> | 322 std::vector<std::unique_ptr<compiler::WasmCompilationUnit>> |
322 compilation_units_; | 323 compilation_units_; |
323 std::queue<std::unique_ptr<compiler::WasmCompilationUnit>> executed_units_; | 324 std::queue<std::unique_ptr<compiler::WasmCompilationUnit>> executed_units_; |
324 base::Mutex result_mutex_; | 325 base::Mutex result_mutex_; |
325 base::AtomicNumber<size_t> next_unit_; | 326 base::AtomicNumber<size_t> next_unit_; |
326 size_t num_background_tasks_ = 0; | 327 size_t num_background_tasks_ = 0; |
327 // This flag should only be set while holding result_mutex_. | 328 // This flag should only be set while holding result_mutex_. |
328 bool finisher_is_running_ = false; | 329 bool finisher_is_running_ = false; |
329 | 330 |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 CompileSequentially(&module_env, temp_instance->function_code, thrower); | 614 CompileSequentially(&module_env, temp_instance->function_code, thrower); |
614 } | 615 } |
615 if (thrower->error()) return {}; | 616 if (thrower->error()) return {}; |
616 } | 617 } |
617 | 618 |
618 // At this point, compilation has completed. Update the code table. | 619 // At this point, compilation has completed. Update the code table. |
619 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 620 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
620 i < temp_instance->function_code.size(); ++i) { | 621 i < temp_instance->function_code.size(); ++i) { |
621 Code* code = *temp_instance->function_code[i]; | 622 Code* code = *temp_instance->function_code[i]; |
622 code_table->set(static_cast<int>(i), code); | 623 code_table->set(static_cast<int>(i), code); |
623 RecordStats(isolate_, code, is_sync_); | 624 RecordStats(isolate_, code, counters_); |
624 } | 625 } |
625 | 626 |
626 // Create heap objects for script, module bytes and asm.js offset table to | 627 // Create heap objects for script, module bytes and asm.js offset table to |
627 // be stored in the shared module data. | 628 // be stored in the shared module data. |
628 Handle<Script> script; | 629 Handle<Script> script; |
629 Handle<ByteArray> asm_js_offset_table; | 630 Handle<ByteArray> asm_js_offset_table; |
630 if (asm_js_script.is_null()) { | 631 if (asm_js_script.is_null()) { |
631 script = CreateWasmScript(isolate_, wire_bytes); | 632 script = CreateWasmScript(isolate_, wire_bytes); |
632 } else { | 633 } else { |
633 script = asm_js_script; | 634 script = asm_js_script; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 for (auto exp : module->export_table) { | 682 for (auto exp : module->export_table) { |
682 if (exp.kind != kExternalFunction) continue; | 683 if (exp.kind != kExternalFunction) continue; |
683 Handle<Code> wasm_code = EnsureExportedLazyDeoptData( | 684 Handle<Code> wasm_code = EnsureExportedLazyDeoptData( |
684 isolate_, Handle<WasmInstanceObject>::null(), code_table, exp.index); | 685 isolate_, Handle<WasmInstanceObject>::null(), code_table, exp.index); |
685 Handle<Code> wrapper_code = | 686 Handle<Code> wrapper_code = |
686 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(isolate_, module, | 687 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(isolate_, module, |
687 wasm_code, exp.index); | 688 wasm_code, exp.index); |
688 int export_index = | 689 int export_index = |
689 static_cast<int>(module->functions.size() + func_index); | 690 static_cast<int>(module->functions.size() + func_index); |
690 code_table->set(export_index, *wrapper_code); | 691 code_table->set(export_index, *wrapper_code); |
691 RecordStats(isolate_, *wrapper_code, is_sync_); | 692 RecordStats(isolate_, *wrapper_code, counters_); |
692 func_index++; | 693 func_index++; |
693 } | 694 } |
694 | 695 |
695 return WasmModuleObject::New(isolate_, compiled_module); | 696 return WasmModuleObject::New(isolate_, compiled_module); |
696 } | 697 } |
697 }; | 698 }; |
698 | 699 |
699 static void MemoryInstanceFinalizer(Isolate* isolate, | 700 static void MemoryInstanceFinalizer(Isolate* isolate, |
700 WasmInstanceObject* instance) { | 701 WasmInstanceObject* instance) { |
701 DisallowHeapAllocation no_gc; | 702 DisallowHeapAllocation no_gc; |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 int ExtractDirectCallIndex(wasm::Decoder& decoder, const byte* pc) { | 836 int ExtractDirectCallIndex(wasm::Decoder& decoder, const byte* pc) { |
836 DCHECK_EQ(static_cast<int>(kExprCallFunction), static_cast<int>(*pc)); | 837 DCHECK_EQ(static_cast<int>(kExprCallFunction), static_cast<int>(*pc)); |
837 // Read the leb128 encoded u32 value (up to 5 bytes starting at pc + 1). | 838 // Read the leb128 encoded u32 value (up to 5 bytes starting at pc + 1). |
838 decoder.Reset(pc + 1, pc + 6); | 839 decoder.Reset(pc + 1, pc + 6); |
839 uint32_t call_idx = decoder.consume_u32v("call index"); | 840 uint32_t call_idx = decoder.consume_u32v("call index"); |
840 DCHECK(decoder.ok()); | 841 DCHECK(decoder.ok()); |
841 DCHECK_GE(kMaxInt, call_idx); | 842 DCHECK_GE(kMaxInt, call_idx); |
842 return static_cast<int>(call_idx); | 843 return static_cast<int>(call_idx); |
843 } | 844 } |
844 | 845 |
845 void RecordLazyCodeStats(Isolate* isolate, Code* code) { | 846 void RecordLazyCodeStats(Isolate* isolate, Code* code, Counters* counters_) { |
846 isolate->counters()->wasm_lazily_compiled_functions()->Increment(); | 847 counters_->wasm_lazily_compiled_functions()->Increment(); |
847 isolate->counters()->wasm_generated_code_size()->Increment(code->body_size()); | 848 counters_->wasm_generated_code_size()->Increment(code->body_size()); |
848 isolate->counters()->wasm_reloc_size()->Increment( | 849 counters_->wasm_reloc_size()->Increment(code->relocation_info()->length()); |
849 code->relocation_info()->length()); | |
850 } | 850 } |
851 | 851 |
852 } // namespace | 852 } // namespace |
853 | 853 |
854 Handle<JSArrayBuffer> wasm::SetupArrayBuffer(Isolate* isolate, | 854 Handle<JSArrayBuffer> wasm::SetupArrayBuffer(Isolate* isolate, |
855 void* allocation_base, | 855 void* allocation_base, |
856 size_t allocation_length, | 856 size_t allocation_length, |
857 void* backing_store, size_t size, | 857 void* backing_store, size_t size, |
858 bool is_external, | 858 bool is_external, |
859 bool enable_guard_regions) { | 859 bool enable_guard_regions) { |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1074 // It closes over the {Isolate}, the {ErrorThrower}, the {WasmCompiledModule}, | 1074 // It closes over the {Isolate}, the {ErrorThrower}, the {WasmCompiledModule}, |
1075 // etc. | 1075 // etc. |
1076 class InstantiationHelper { | 1076 class InstantiationHelper { |
1077 public: | 1077 public: |
1078 InstantiationHelper(Isolate* isolate, ErrorThrower* thrower, | 1078 InstantiationHelper(Isolate* isolate, ErrorThrower* thrower, |
1079 Handle<WasmModuleObject> module_object, | 1079 Handle<WasmModuleObject> module_object, |
1080 MaybeHandle<JSReceiver> ffi, | 1080 MaybeHandle<JSReceiver> ffi, |
1081 MaybeHandle<JSArrayBuffer> memory) | 1081 MaybeHandle<JSArrayBuffer> memory) |
1082 : isolate_(isolate), | 1082 : isolate_(isolate), |
1083 module_(module_object->compiled_module()->module()), | 1083 module_(module_object->compiled_module()->module()), |
| 1084 counters_shared_(isolate->counters_shared()), |
1084 thrower_(thrower), | 1085 thrower_(thrower), |
1085 module_object_(module_object), | 1086 module_object_(module_object), |
1086 ffi_(ffi.is_null() ? Handle<JSReceiver>::null() | 1087 ffi_(ffi.is_null() ? Handle<JSReceiver>::null() |
1087 : ffi.ToHandleChecked()), | 1088 : ffi.ToHandleChecked()), |
1088 memory_(memory.is_null() ? Handle<JSArrayBuffer>::null() | 1089 memory_(memory.is_null() ? Handle<JSArrayBuffer>::null() |
1089 : memory.ToHandleChecked()) {} | 1090 : memory.ToHandleChecked()) { |
| 1091 counters_ = counters_shared_.get(); |
| 1092 } |
1090 | 1093 |
1091 // Build an instance, in all of its glory. | 1094 // Build an instance, in all of its glory. |
1092 MaybeHandle<WasmInstanceObject> Build() { | 1095 MaybeHandle<WasmInstanceObject> Build() { |
1093 // Check that an imports argument was provided, if the module requires it. | 1096 // Check that an imports argument was provided, if the module requires it. |
1094 // No point in continuing otherwise. | 1097 // No point in continuing otherwise. |
1095 if (!module_->import_table.empty() && ffi_.is_null()) { | 1098 if (!module_->import_table.empty() && ffi_.is_null()) { |
1096 thrower_->TypeError( | 1099 thrower_->TypeError( |
1097 "Imports argument must be present and must be an object"); | 1100 "Imports argument must be present and must be an object"); |
1098 return {}; | 1101 return {}; |
1099 } | 1102 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1169 case Code::JS_TO_WASM_FUNCTION: | 1172 case Code::JS_TO_WASM_FUNCTION: |
1170 case Code::WASM_FUNCTION: { | 1173 case Code::WASM_FUNCTION: { |
1171 Handle<Code> code = factory->CopyCode(orig_code); | 1174 Handle<Code> code = factory->CopyCode(orig_code); |
1172 code_table->set(i, *code); | 1175 code_table->set(i, *code); |
1173 break; | 1176 break; |
1174 } | 1177 } |
1175 default: | 1178 default: |
1176 UNREACHABLE(); | 1179 UNREACHABLE(); |
1177 } | 1180 } |
1178 } | 1181 } |
1179 RecordStats(isolate_, code_table, is_sync_); | 1182 RecordStats(isolate_, code_table, counters_); |
1180 } else { | 1183 } else { |
1181 // There was no owner, so we can reuse the original. | 1184 // There was no owner, so we can reuse the original. |
1182 compiled_module_ = original; | 1185 compiled_module_ = original; |
1183 old_code_table = | 1186 old_code_table = |
1184 factory->CopyFixedArray(compiled_module_->code_table()); | 1187 factory->CopyFixedArray(compiled_module_->code_table()); |
1185 code_table = compiled_module_->code_table(); | 1188 code_table = compiled_module_->code_table(); |
1186 TRACE("Reusing existing instance %d\n", | 1189 TRACE("Reusing existing instance %d\n", |
1187 compiled_module_->instance_id()); | 1190 compiled_module_->instance_id()); |
1188 } | 1191 } |
1189 compiled_module_->set_native_context(isolate_->native_context()); | 1192 compiled_module_->set_native_context(isolate_->native_context()); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1446 int start_index = module_->start_function_index; | 1449 int start_index = module_->start_function_index; |
1447 Handle<Code> startup_code = EnsureExportedLazyDeoptData( | 1450 Handle<Code> startup_code = EnsureExportedLazyDeoptData( |
1448 isolate_, instance, code_table, start_index); | 1451 isolate_, instance, code_table, start_index); |
1449 FunctionSig* sig = module_->functions[start_index].sig; | 1452 FunctionSig* sig = module_->functions[start_index].sig; |
1450 Handle<Code> wrapper_code = | 1453 Handle<Code> wrapper_code = |
1451 js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper( | 1454 js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper( |
1452 isolate_, module_, startup_code, start_index); | 1455 isolate_, module_, startup_code, start_index); |
1453 Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New( | 1456 Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New( |
1454 isolate_, instance, MaybeHandle<String>(), start_index, | 1457 isolate_, instance, MaybeHandle<String>(), start_index, |
1455 static_cast<int>(sig->parameter_count()), wrapper_code); | 1458 static_cast<int>(sig->parameter_count()), wrapper_code); |
1456 RecordStats(isolate_, *startup_code, is_sync_); | 1459 RecordStats(isolate_, *startup_code, counters_); |
1457 // Call the JS function. | 1460 // Call the JS function. |
1458 Handle<Object> undefined = factory->undefined_value(); | 1461 Handle<Object> undefined = factory->undefined_value(); |
1459 MaybeHandle<Object> retval = | 1462 MaybeHandle<Object> retval = |
1460 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); | 1463 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); |
1461 | 1464 |
1462 if (retval.is_null()) { | 1465 if (retval.is_null()) { |
1463 DCHECK(isolate_->has_pending_exception()); | 1466 DCHECK(isolate_->has_pending_exception()); |
1464 isolate_->OptionalRescheduleException(false); | 1467 isolate_->OptionalRescheduleException(false); |
1465 // It's unfortunate that the new instance is already linked in the | 1468 // It's unfortunate that the new instance is already linked in the |
1466 // chain. However, we need to set up everything before executing the | 1469 // chain. However, we need to set up everything before executing the |
(...skipping 13 matching lines...) Expand all Loading... |
1480 // Represents the initialized state of a table. | 1483 // Represents the initialized state of a table. |
1481 struct TableInstance { | 1484 struct TableInstance { |
1482 Handle<WasmTableObject> table_object; // WebAssembly.Table instance | 1485 Handle<WasmTableObject> table_object; // WebAssembly.Table instance |
1483 Handle<FixedArray> js_wrappers; // JSFunctions exported | 1486 Handle<FixedArray> js_wrappers; // JSFunctions exported |
1484 Handle<FixedArray> function_table; // internal code array | 1487 Handle<FixedArray> function_table; // internal code array |
1485 Handle<FixedArray> signature_table; // internal sig array | 1488 Handle<FixedArray> signature_table; // internal sig array |
1486 }; | 1489 }; |
1487 | 1490 |
1488 Isolate* isolate_; | 1491 Isolate* isolate_; |
1489 WasmModule* const module_; | 1492 WasmModule* const module_; |
1490 constexpr static bool is_sync_ = true; | 1493 std::shared_ptr<Counters> counters_shared_; |
| 1494 Counters* counters_; |
1491 ErrorThrower* thrower_; | 1495 ErrorThrower* thrower_; |
1492 Handle<WasmModuleObject> module_object_; | 1496 Handle<WasmModuleObject> module_object_; |
1493 Handle<JSReceiver> ffi_; // TODO(titzer): Use MaybeHandle | 1497 Handle<JSReceiver> ffi_; // TODO(titzer): Use MaybeHandle |
1494 Handle<JSArrayBuffer> memory_; // TODO(titzer): Use MaybeHandle | 1498 Handle<JSArrayBuffer> memory_; // TODO(titzer): Use MaybeHandle |
1495 Handle<JSArrayBuffer> globals_; | 1499 Handle<JSArrayBuffer> globals_; |
1496 Handle<WasmCompiledModule> compiled_module_; | 1500 Handle<WasmCompiledModule> compiled_module_; |
1497 std::vector<TableInstance> table_instances_; | 1501 std::vector<TableInstance> table_instances_; |
1498 std::vector<Handle<JSFunction>> js_wrappers_; | 1502 std::vector<Handle<JSFunction>> js_wrappers_; |
1499 JSToWasmWrapperCache js_to_wasm_cache_; | 1503 JSToWasmWrapperCache js_to_wasm_cache_; |
1500 | 1504 |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1651 isolate_, index, module_->functions[import.index].sig, | 1655 isolate_, index, module_->functions[import.index].sig, |
1652 Handle<JSReceiver>::cast(value), module_name, import_name, | 1656 Handle<JSReceiver>::cast(value), module_name, import_name, |
1653 module_->get_origin()); | 1657 module_->get_origin()); |
1654 if (import_wrapper.is_null()) { | 1658 if (import_wrapper.is_null()) { |
1655 ReportLinkError( | 1659 ReportLinkError( |
1656 "imported function does not match the expected type", index, | 1660 "imported function does not match the expected type", index, |
1657 module_name, import_name); | 1661 module_name, import_name); |
1658 return -1; | 1662 return -1; |
1659 } | 1663 } |
1660 code_table->set(num_imported_functions, *import_wrapper); | 1664 code_table->set(num_imported_functions, *import_wrapper); |
1661 RecordStats(isolate_, *import_wrapper, is_sync_); | 1665 RecordStats(isolate_, *import_wrapper, counters_); |
1662 num_imported_functions++; | 1666 num_imported_functions++; |
1663 break; | 1667 break; |
1664 } | 1668 } |
1665 case kExternalTable: { | 1669 case kExternalTable: { |
1666 if (!WasmJs::IsWasmTableObject(isolate_, value)) { | 1670 if (!WasmJs::IsWasmTableObject(isolate_, value)) { |
1667 ReportLinkError("table import requires a WebAssembly.Table", index, | 1671 ReportLinkError("table import requires a WebAssembly.Table", index, |
1668 module_name, import_name); | 1672 module_name, import_name); |
1669 return -1; | 1673 return -1; |
1670 } | 1674 } |
1671 WasmIndirectFunctionTable& table = | 1675 WasmIndirectFunctionTable& table = |
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2624 // e.g. when we synchronizing tasks or when we delete the AyncCompileJob. | 2628 // e.g. when we synchronizing tasks or when we delete the AyncCompileJob. |
2625 class AsyncCompileJob { | 2629 class AsyncCompileJob { |
2626 // TODO(ahaas): Fix https://bugs.chromium.org/p/v8/issues/detail?id=6263 to | 2630 // TODO(ahaas): Fix https://bugs.chromium.org/p/v8/issues/detail?id=6263 to |
2627 // make sure that d8 does not shut down before the AsyncCompileJob is | 2631 // make sure that d8 does not shut down before the AsyncCompileJob is |
2628 // finished. | 2632 // finished. |
2629 public: | 2633 public: |
2630 explicit AsyncCompileJob(Isolate* isolate, std::unique_ptr<byte[]> bytes_copy, | 2634 explicit AsyncCompileJob(Isolate* isolate, std::unique_ptr<byte[]> bytes_copy, |
2631 size_t length, Handle<Context> context, | 2635 size_t length, Handle<Context> context, |
2632 Handle<JSPromise> promise) | 2636 Handle<JSPromise> promise) |
2633 : isolate_(isolate), | 2637 : isolate_(isolate), |
| 2638 counters_shared_(isolate->counters_shared()), |
2634 bytes_copy_(std::move(bytes_copy)), | 2639 bytes_copy_(std::move(bytes_copy)), |
2635 wire_bytes_(bytes_copy_.get(), bytes_copy_.get() + length) { | 2640 wire_bytes_(bytes_copy_.get(), bytes_copy_.get() + length) { |
2636 // The handles for the context and promise must be deferred. | 2641 // The handles for the context and promise must be deferred. |
2637 DeferredHandleScope deferred(isolate); | 2642 DeferredHandleScope deferred(isolate); |
2638 context_ = Handle<Context>(*context); | 2643 context_ = Handle<Context>(*context); |
2639 module_promise_ = Handle<JSPromise>(*promise); | 2644 module_promise_ = Handle<JSPromise>(*promise); |
2640 deferred_handles_.push_back(deferred.Detach()); | 2645 deferred_handles_.push_back(deferred.Detach()); |
| 2646 counters_ = counters_shared_.get(); |
2641 } | 2647 } |
2642 | 2648 |
2643 void Start() { | 2649 void Start() { |
2644 DoAsync<DecodeModule>(); // -- | 2650 DoAsync<DecodeModule>(); // -- |
2645 } | 2651 } |
2646 | 2652 |
2647 ~AsyncCompileJob() { | 2653 ~AsyncCompileJob() { |
2648 for (auto d : deferred_handles_) delete d; | 2654 for (auto d : deferred_handles_) delete d; |
2649 } | 2655 } |
2650 | 2656 |
2651 private: | 2657 private: |
2652 Isolate* isolate_; | 2658 Isolate* isolate_; |
| 2659 std::shared_ptr<Counters> counters_shared_; |
| 2660 Counters* counters_; |
2653 std::unique_ptr<byte[]> bytes_copy_; | 2661 std::unique_ptr<byte[]> bytes_copy_; |
2654 ModuleWireBytes wire_bytes_; | 2662 ModuleWireBytes wire_bytes_; |
2655 Handle<Context> context_; | 2663 Handle<Context> context_; |
2656 Handle<JSPromise> module_promise_; | 2664 Handle<JSPromise> module_promise_; |
2657 std::unique_ptr<CompilationHelper> helper_; | 2665 std::unique_ptr<CompilationHelper> helper_; |
2658 std::unique_ptr<ModuleBytesEnv> module_bytes_env_; | 2666 std::unique_ptr<ModuleBytesEnv> module_bytes_env_; |
2659 | 2667 |
2660 bool failed_ = false; | 2668 bool failed_ = false; |
2661 std::vector<DeferredHandles*> deferred_handles_; | 2669 std::vector<DeferredHandles*> deferred_handles_; |
2662 Handle<WasmModuleObject> module_object_; | 2670 Handle<WasmModuleObject> module_object_; |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3009 }; | 3017 }; |
3010 | 3018 |
3011 //========================================================================== | 3019 //========================================================================== |
3012 // Step 5b (sync): Finish heap-allocated data structures. | 3020 // Step 5b (sync): Finish heap-allocated data structures. |
3013 //========================================================================== | 3021 //========================================================================== |
3014 class FinishCompile : public SyncCompileTask { | 3022 class FinishCompile : public SyncCompileTask { |
3015 void RunImpl() override { | 3023 void RunImpl() override { |
3016 TRACE_COMPILE("(5b) Finish compile...\n"); | 3024 TRACE_COMPILE("(5b) Finish compile...\n"); |
3017 HandleScope scope(job_->isolate_); | 3025 HandleScope scope(job_->isolate_); |
3018 // At this point, compilation has completed. Update the code table. | 3026 // At this point, compilation has completed. Update the code table. |
3019 constexpr bool is_sync = true; | |
3020 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 3027 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
3021 i < job_->temp_instance_->function_code.size(); ++i) { | 3028 i < job_->temp_instance_->function_code.size(); ++i) { |
3022 Code* code = Code::cast(job_->code_table_->get(static_cast<int>(i))); | 3029 Code* code = Code::cast(job_->code_table_->get(static_cast<int>(i))); |
3023 RecordStats(job_->isolate_, code, !is_sync); | 3030 RecordStats(job_->isolate_, code, job_->counters_); |
3024 } | 3031 } |
3025 | 3032 |
3026 // Create heap objects for script and module bytes to be stored in the | 3033 // Create heap objects for script and module bytes to be stored in the |
3027 // shared module data. Asm.js is not compiled asynchronously. | 3034 // shared module data. Asm.js is not compiled asynchronously. |
3028 Handle<Script> script = | 3035 Handle<Script> script = |
3029 CreateWasmScript(job_->isolate_, job_->wire_bytes_); | 3036 CreateWasmScript(job_->isolate_, job_->wire_bytes_); |
3030 Handle<ByteArray> asm_js_offset_table; | 3037 Handle<ByteArray> asm_js_offset_table; |
3031 // TODO(wasm): Improve efficiency of storing module wire bytes. | 3038 // TODO(wasm): Improve efficiency of storing module wire bytes. |
3032 // 1. Only store relevant sections, not function bodies | 3039 // 1. Only store relevant sections, not function bodies |
3033 // 2. Don't make a second copy of the bytes here; reuse the copy made | 3040 // 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... |
3079 //========================================================================== | 3086 //========================================================================== |
3080 // Step 6 (sync): Compile JS->WASM wrappers. | 3087 // Step 6 (sync): Compile JS->WASM wrappers. |
3081 //========================================================================== | 3088 //========================================================================== |
3082 class CompileWrappers : public SyncCompileTask { | 3089 class CompileWrappers : public SyncCompileTask { |
3083 void RunImpl() override { | 3090 void RunImpl() override { |
3084 TRACE_COMPILE("(6) Compile wrappers...\n"); | 3091 TRACE_COMPILE("(6) Compile wrappers...\n"); |
3085 // Compile JS->WASM wrappers for exported functions. | 3092 // Compile JS->WASM wrappers for exported functions. |
3086 HandleScope scope(job_->isolate_); | 3093 HandleScope scope(job_->isolate_); |
3087 JSToWasmWrapperCache js_to_wasm_cache; | 3094 JSToWasmWrapperCache js_to_wasm_cache; |
3088 int func_index = 0; | 3095 int func_index = 0; |
3089 constexpr bool is_sync = true; | |
3090 WasmModule* module = job_->compiled_module_->module(); | 3096 WasmModule* module = job_->compiled_module_->module(); |
3091 for (auto exp : module->export_table) { | 3097 for (auto exp : module->export_table) { |
3092 if (exp.kind != kExternalFunction) continue; | 3098 if (exp.kind != kExternalFunction) continue; |
3093 Handle<Code> wasm_code(Code::cast(job_->code_table_->get(exp.index)), | 3099 Handle<Code> wasm_code(Code::cast(job_->code_table_->get(exp.index)), |
3094 job_->isolate_); | 3100 job_->isolate_); |
3095 Handle<Code> wrapper_code = | 3101 Handle<Code> wrapper_code = |
3096 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper( | 3102 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper( |
3097 job_->isolate_, module, wasm_code, exp.index); | 3103 job_->isolate_, module, wasm_code, exp.index); |
3098 int export_index = | 3104 int export_index = |
3099 static_cast<int>(module->functions.size() + func_index); | 3105 static_cast<int>(module->functions.size() + func_index); |
3100 job_->code_table_->set(export_index, *wrapper_code); | 3106 job_->code_table_->set(export_index, *wrapper_code); |
3101 RecordStats(job_->isolate_, *wrapper_code, !is_sync); | 3107 RecordStats(job_->isolate_, *wrapper_code, job_->counters_); |
3102 func_index++; | 3108 func_index++; |
3103 } | 3109 } |
3104 | 3110 |
3105 job_->DoSync<FinishModule>(); | 3111 job_->DoSync<FinishModule>(); |
3106 } | 3112 } |
3107 }; | 3113 }; |
3108 | 3114 |
3109 //========================================================================== | 3115 //========================================================================== |
3110 // Step 7 (sync): Finish the module and resolve the promise. | 3116 // Step 7 (sync): Finish the module and resolve the promise. |
3111 //========================================================================== | 3117 //========================================================================== |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3215 // do the patching redundantly. | 3221 // do the patching redundantly. |
3216 Handle<FixedArray> new_deopt_data = | 3222 Handle<FixedArray> new_deopt_data = |
3217 isolate->factory()->CopyFixedArrayUpTo(exp_deopt_data, 2, TENURED); | 3223 isolate->factory()->CopyFixedArrayUpTo(exp_deopt_data, 2, TENURED); |
3218 lazy_compile_code->set_deoptimization_data(*new_deopt_data); | 3224 lazy_compile_code->set_deoptimization_data(*new_deopt_data); |
3219 } | 3225 } |
3220 | 3226 |
3221 return compiled_code; | 3227 return compiled_code; |
3222 } | 3228 } |
3223 | 3229 |
3224 void LazyCompilationOrchestrator::CompileFunction( | 3230 void LazyCompilationOrchestrator::CompileFunction( |
3225 Isolate* isolate, Handle<WasmInstanceObject> instance, int func_index) { | 3231 Isolate* isolate, Handle<WasmInstanceObject> instance, int func_index, |
| 3232 Counters* counters_) { |
3226 Handle<WasmCompiledModule> compiled_module(instance->compiled_module(), | 3233 Handle<WasmCompiledModule> compiled_module(instance->compiled_module(), |
3227 isolate); | 3234 isolate); |
3228 if (Code::cast(compiled_module->code_table()->get(func_index))->kind() == | 3235 if (Code::cast(compiled_module->code_table()->get(func_index))->kind() == |
3229 Code::WASM_FUNCTION) { | 3236 Code::WASM_FUNCTION) { |
3230 return; | 3237 return; |
3231 } | 3238 } |
3232 | 3239 |
3233 size_t num_function_tables = | 3240 size_t num_function_tables = |
3234 compiled_module->module()->function_tables.size(); | 3241 compiled_module->module()->function_tables.size(); |
3235 // Store a vector of handles to be embedded in the generated code. | 3242 // Store a vector of handles to be embedded in the generated code. |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3301 DCHECK_IMPLIES(mem_size == 0, mem_start == nullptr); | 3308 DCHECK_IMPLIES(mem_size == 0, mem_start == nullptr); |
3302 if (mem_size > 0) { | 3309 if (mem_size > 0) { |
3303 code_specialization.RelocateMemoryReferences(nullptr, 0, mem_start, | 3310 code_specialization.RelocateMemoryReferences(nullptr, 0, mem_start, |
3304 mem_size); | 3311 mem_size); |
3305 } | 3312 } |
3306 } | 3313 } |
3307 code_specialization.RelocateDirectCalls(instance); | 3314 code_specialization.RelocateDirectCalls(instance); |
3308 code_specialization.ApplyToWasmCode(*code, SKIP_ICACHE_FLUSH); | 3315 code_specialization.ApplyToWasmCode(*code, SKIP_ICACHE_FLUSH); |
3309 Assembler::FlushICache(isolate, code->instruction_start(), | 3316 Assembler::FlushICache(isolate, code->instruction_start(), |
3310 code->instruction_size()); | 3317 code->instruction_size()); |
3311 RecordLazyCodeStats(isolate, *code); | 3318 RecordLazyCodeStats(isolate, *code, counters_); |
3312 } | 3319 } |
3313 | 3320 |
3314 Handle<Code> LazyCompilationOrchestrator::CompileLazy( | 3321 Handle<Code> LazyCompilationOrchestrator::CompileLazy( |
3315 Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> caller, | 3322 Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> caller, |
3316 int call_offset, int exported_func_index, bool patch_caller) { | 3323 int call_offset, int exported_func_index, bool patch_caller) { |
3317 struct NonCompiledFunction { | 3324 struct NonCompiledFunction { |
3318 int offset; | 3325 int offset; |
3319 int func_index; | 3326 int func_index; |
3320 }; | 3327 }; |
| 3328 std::shared_ptr<Counters> counters_shared = isolate->counters_shared(); |
| 3329 Counters* counters = counters_shared.get(); |
3321 std::vector<NonCompiledFunction> non_compiled_functions; | 3330 std::vector<NonCompiledFunction> non_compiled_functions; |
3322 int func_to_return_idx = exported_func_index; | 3331 int func_to_return_idx = exported_func_index; |
3323 wasm::Decoder decoder(nullptr, nullptr); | 3332 wasm::Decoder decoder(nullptr, nullptr); |
3324 bool is_js_to_wasm = caller->kind() == Code::JS_TO_WASM_FUNCTION; | 3333 bool is_js_to_wasm = caller->kind() == Code::JS_TO_WASM_FUNCTION; |
3325 Handle<WasmCompiledModule> compiled_module(instance->compiled_module(), | 3334 Handle<WasmCompiledModule> compiled_module(instance->compiled_module(), |
3326 isolate); | 3335 isolate); |
3327 | 3336 |
3328 if (is_js_to_wasm) { | 3337 if (is_js_to_wasm) { |
3329 non_compiled_functions.push_back({0, exported_func_index}); | 3338 non_compiled_functions.push_back({0, exported_func_index}); |
3330 } else if (patch_caller) { | 3339 } else if (patch_caller) { |
(...skipping 24 matching lines...) Expand all Loading... |
3355 ExtractDirectCallIndex(decoder, func_bytes + byte_pos); | 3364 ExtractDirectCallIndex(decoder, func_bytes + byte_pos); |
3356 non_compiled_functions.push_back({offset, called_func_index}); | 3365 non_compiled_functions.push_back({offset, called_func_index}); |
3357 // Call offset one instruction after the call. Remember the last called | 3366 // Call offset one instruction after the call. Remember the last called |
3358 // function before that offset. | 3367 // function before that offset. |
3359 if (offset < call_offset) func_to_return_idx = called_func_index; | 3368 if (offset < call_offset) func_to_return_idx = called_func_index; |
3360 } | 3369 } |
3361 } | 3370 } |
3362 | 3371 |
3363 // TODO(clemensh): compile all functions in non_compiled_functions in | 3372 // TODO(clemensh): compile all functions in non_compiled_functions in |
3364 // background, wait for func_to_return_idx. | 3373 // background, wait for func_to_return_idx. |
3365 CompileFunction(isolate, instance, func_to_return_idx); | 3374 CompileFunction(isolate, instance, func_to_return_idx, counters); |
3366 | 3375 |
3367 if (is_js_to_wasm || patch_caller) { | 3376 if (is_js_to_wasm || patch_caller) { |
3368 DisallowHeapAllocation no_gc; | 3377 DisallowHeapAllocation no_gc; |
3369 // Now patch the code object with all functions which are now compiled. | 3378 // Now patch the code object with all functions which are now compiled. |
3370 int idx = 0; | 3379 int idx = 0; |
3371 for (RelocIterator it(*caller, RelocInfo::kCodeTargetMask); !it.done(); | 3380 for (RelocIterator it(*caller, RelocInfo::kCodeTargetMask); !it.done(); |
3372 it.next()) { | 3381 it.next()) { |
3373 Code* callee = | 3382 Code* callee = |
3374 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | 3383 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
3375 if (callee->builtin_index() != Builtins::kWasmCompileLazy) continue; | 3384 if (callee->builtin_index() != Builtins::kWasmCompileLazy) continue; |
(...skipping 22 matching lines...) Expand all Loading... |
3398 callee_compiled->instruction_start()); | 3407 callee_compiled->instruction_start()); |
3399 } | 3408 } |
3400 DCHECK_EQ(non_compiled_functions.size(), idx); | 3409 DCHECK_EQ(non_compiled_functions.size(), idx); |
3401 } | 3410 } |
3402 | 3411 |
3403 Code* ret = | 3412 Code* ret = |
3404 Code::cast(compiled_module->code_table()->get(func_to_return_idx)); | 3413 Code::cast(compiled_module->code_table()->get(func_to_return_idx)); |
3405 DCHECK_EQ(Code::WASM_FUNCTION, ret->kind()); | 3414 DCHECK_EQ(Code::WASM_FUNCTION, ret->kind()); |
3406 return handle(ret, isolate); | 3415 return handle(ret, isolate); |
3407 } | 3416 } |
OLD | NEW |