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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
49 } while (false) | 49 } while (false) |
50 | 50 |
51 namespace { | 51 namespace { |
52 | 52 |
53 static const int kInvalidSigIndex = -1; | 53 static const int kInvalidSigIndex = -1; |
54 | 54 |
55 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { | 55 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { |
56 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; | 56 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; |
57 } | 57 } |
58 | 58 |
59 static void RecordStats(Isolate* isolate, Code* code, bool is_sync) { | 59 static void RecordStats(Code* code, Counters* counters) { |
60 if (is_sync) { | 60 counters->wasm_generated_code_size()->Increment(code->body_size()); |
61 // TODO(karlschimpf): Make this work when asynchronous. | 61 counters->wasm_reloc_size()->Increment(code->relocation_info()->length()); |
62 // https://bugs.chromium.org/p/v8/issues/detail?id=6361 | 62 } |
63 isolate->counters()->wasm_generated_code_size()->Increment( | 63 |
64 code->body_size()); | 64 static void RecordStats(Handle<FixedArray> functions, Counters* counters) { |
65 isolate->counters()->wasm_reloc_size()->Increment( | 65 DisallowHeapAllocation no_gc; |
66 code->relocation_info()->length()); | 66 for (int i = 0; i < functions->length(); ++i) { |
67 RecordStats(Code::cast(functions->get(i)), counters); | |
67 } | 68 } |
68 } | 69 } |
69 | 70 |
70 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions, | |
71 bool is_sync) { | |
72 DisallowHeapAllocation no_gc; | |
73 for (int i = 0; i < functions->length(); ++i) { | |
74 RecordStats(isolate, Code::cast(functions->get(i)), is_sync); | |
75 } | |
76 } | |
77 | |
78 void* TryAllocateBackingStore(Isolate* isolate, size_t size, | 71 void* TryAllocateBackingStore(Isolate* isolate, size_t size, |
79 bool enable_guard_regions, void*& allocation_base, | 72 bool enable_guard_regions, void*& allocation_base, |
80 size_t& allocation_length) { | 73 size_t& allocation_length) { |
81 // 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 |
82 // 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 |
83 // 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 |
84 // weren't any. | 77 // weren't any. |
85 if (enable_guard_regions && kGuardRegionsSupported) { | 78 if (enable_guard_regions && kGuardRegionsSupported) { |
86 // 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 |
87 // pages yet. | 80 // pages yet. |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
331 class CompilationHelper { | 324 class CompilationHelper { |
332 public: | 325 public: |
333 // The compilation helper takes ownership of the {WasmModule}. | 326 // The compilation helper takes ownership of the {WasmModule}. |
334 // In {CompileToModuleObject}, it will transfer ownership to the generated | 327 // In {CompileToModuleObject}, it will transfer ownership to the generated |
335 // {WasmModuleWrapper}. If this method is not called, ownership may be | 328 // {WasmModuleWrapper}. If this method is not called, ownership may be |
336 // reclaimed by explicitely releasing the {module_} field. | 329 // reclaimed by explicitely releasing the {module_} field. |
337 CompilationHelper(Isolate* isolate, std::unique_ptr<WasmModule> module, | 330 CompilationHelper(Isolate* isolate, std::unique_ptr<WasmModule> module, |
338 bool is_sync) | 331 bool is_sync) |
339 : isolate_(isolate), | 332 : isolate_(isolate), |
340 module_(std::move(module)), | 333 module_(std::move(module)), |
334 counters_shared_(isolate->counters_shared()), | |
341 is_sync_(is_sync), | 335 is_sync_(is_sync), |
342 executed_units_(isolate->random_number_generator()) {} | 336 executed_units_(isolate->random_number_generator()) { |
337 counters_ = counters_shared_.get(); | |
338 } | |
343 | 339 |
344 // The actual runnable task that performs compilations in the background. | 340 // The actual runnable task that performs compilations in the background. |
345 class CompilationTask : public CancelableTask { | 341 class CompilationTask : public CancelableTask { |
346 public: | 342 public: |
347 CompilationHelper* helper_; | 343 CompilationHelper* helper_; |
348 explicit CompilationTask(CompilationHelper* helper) | 344 explicit CompilationTask(CompilationHelper* helper) |
349 : CancelableTask(helper->isolate_), helper_(helper) {} | 345 : CancelableTask(helper->isolate_), helper_(helper) {} |
350 | 346 |
351 void RunInternal() override { | 347 void RunInternal() override { |
352 while (helper_->FetchAndExecuteCompilationUnit()) { | 348 while (helper_->FetchAndExecuteCompilationUnit()) { |
353 } | 349 } |
354 helper_->module_->pending_tasks.get()->Signal(); | 350 helper_->module_->pending_tasks.get()->Signal(); |
355 } | 351 } |
356 }; | 352 }; |
357 | 353 |
358 Isolate* isolate_; | 354 Isolate* isolate_; |
359 std::unique_ptr<WasmModule> module_; | 355 std::unique_ptr<WasmModule> module_; |
356 std::shared_ptr<Counters> counters_shared_; | |
357 Counters* counters_; | |
Clemens Hammacher
2017/06/02 13:08:50
Why is this field needed? {counters_shared_.get()}
kschimpf
2017/06/02 15:01:02
I was confusing the assignment operator with the g
kschimpf
2017/06/02 17:06:27
Fixed in CL https://codereview.chromium.org/291995
| |
360 bool is_sync_; | 358 bool is_sync_; |
361 std::vector<std::unique_ptr<compiler::WasmCompilationUnit>> | 359 std::vector<std::unique_ptr<compiler::WasmCompilationUnit>> |
362 compilation_units_; | 360 compilation_units_; |
363 CodeGenerationSchedule executed_units_; | 361 CodeGenerationSchedule executed_units_; |
364 base::Mutex result_mutex_; | 362 base::Mutex result_mutex_; |
365 base::AtomicNumber<size_t> next_unit_; | 363 base::AtomicNumber<size_t> next_unit_; |
366 size_t num_background_tasks_ = 0; | 364 size_t num_background_tasks_ = 0; |
367 // This flag should only be set while holding result_mutex_. | 365 // This flag should only be set while holding result_mutex_. |
368 bool finisher_is_running_ = false; | 366 bool finisher_is_running_ = false; |
369 | 367 |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
683 // (lazy) compilation time. | 681 // (lazy) compilation time. |
684 ValidateSequentially(&module_env, thrower); | 682 ValidateSequentially(&module_env, thrower); |
685 } | 683 } |
686 if (thrower->error()) return {}; | 684 if (thrower->error()) return {}; |
687 | 685 |
688 // At this point, compilation has completed. Update the code table. | 686 // At this point, compilation has completed. Update the code table. |
689 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 687 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
690 i < temp_instance->function_code.size(); ++i) { | 688 i < temp_instance->function_code.size(); ++i) { |
691 Code* code = *temp_instance->function_code[i]; | 689 Code* code = *temp_instance->function_code[i]; |
692 code_table->set(static_cast<int>(i), code); | 690 code_table->set(static_cast<int>(i), code); |
693 RecordStats(isolate_, code, is_sync_); | 691 RecordStats(code, counters_); |
694 } | 692 } |
695 | 693 |
696 // Create heap objects for script, module bytes and asm.js offset table to | 694 // Create heap objects for script, module bytes and asm.js offset table to |
697 // be stored in the shared module data. | 695 // be stored in the shared module data. |
698 Handle<Script> script; | 696 Handle<Script> script; |
699 Handle<ByteArray> asm_js_offset_table; | 697 Handle<ByteArray> asm_js_offset_table; |
700 if (asm_js_script.is_null()) { | 698 if (asm_js_script.is_null()) { |
701 script = CreateWasmScript(isolate_, wire_bytes); | 699 script = CreateWasmScript(isolate_, wire_bytes); |
702 } else { | 700 } else { |
703 script = asm_js_script; | 701 script = asm_js_script; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
751 for (auto exp : module->export_table) { | 749 for (auto exp : module->export_table) { |
752 if (exp.kind != kExternalFunction) continue; | 750 if (exp.kind != kExternalFunction) continue; |
753 Handle<Code> wasm_code = EnsureExportedLazyDeoptData( | 751 Handle<Code> wasm_code = EnsureExportedLazyDeoptData( |
754 isolate_, Handle<WasmInstanceObject>::null(), code_table, exp.index); | 752 isolate_, Handle<WasmInstanceObject>::null(), code_table, exp.index); |
755 Handle<Code> wrapper_code = | 753 Handle<Code> wrapper_code = |
756 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(isolate_, module, | 754 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(isolate_, module, |
757 wasm_code, exp.index); | 755 wasm_code, exp.index); |
758 int export_index = | 756 int export_index = |
759 static_cast<int>(module->functions.size() + func_index); | 757 static_cast<int>(module->functions.size() + func_index); |
760 code_table->set(export_index, *wrapper_code); | 758 code_table->set(export_index, *wrapper_code); |
761 RecordStats(isolate_, *wrapper_code, is_sync_); | 759 RecordStats(*wrapper_code, counters_); |
762 func_index++; | 760 func_index++; |
763 } | 761 } |
764 | 762 |
765 return WasmModuleObject::New(isolate_, compiled_module); | 763 return WasmModuleObject::New(isolate_, compiled_module); |
766 } | 764 } |
767 }; | 765 }; |
768 | 766 |
769 static void MemoryInstanceFinalizer(Isolate* isolate, | 767 static void MemoryInstanceFinalizer(Isolate* isolate, |
770 WasmInstanceObject* instance) { | 768 WasmInstanceObject* instance) { |
771 DisallowHeapAllocation no_gc; | 769 DisallowHeapAllocation no_gc; |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
905 int ExtractDirectCallIndex(wasm::Decoder& decoder, const byte* pc) { | 903 int ExtractDirectCallIndex(wasm::Decoder& decoder, const byte* pc) { |
906 DCHECK_EQ(static_cast<int>(kExprCallFunction), static_cast<int>(*pc)); | 904 DCHECK_EQ(static_cast<int>(kExprCallFunction), static_cast<int>(*pc)); |
907 // Read the leb128 encoded u32 value (up to 5 bytes starting at pc + 1). | 905 // Read the leb128 encoded u32 value (up to 5 bytes starting at pc + 1). |
908 decoder.Reset(pc + 1, pc + 6); | 906 decoder.Reset(pc + 1, pc + 6); |
909 uint32_t call_idx = decoder.consume_u32v("call index"); | 907 uint32_t call_idx = decoder.consume_u32v("call index"); |
910 DCHECK(decoder.ok()); | 908 DCHECK(decoder.ok()); |
911 DCHECK_GE(kMaxInt, call_idx); | 909 DCHECK_GE(kMaxInt, call_idx); |
912 return static_cast<int>(call_idx); | 910 return static_cast<int>(call_idx); |
913 } | 911 } |
914 | 912 |
915 void RecordLazyCodeStats(Isolate* isolate, Code* code) { | 913 void RecordLazyCodeStats(Code* code, Counters* counters) { |
916 isolate->counters()->wasm_lazily_compiled_functions()->Increment(); | 914 counters->wasm_lazily_compiled_functions()->Increment(); |
917 isolate->counters()->wasm_generated_code_size()->Increment(code->body_size()); | 915 counters->wasm_generated_code_size()->Increment(code->body_size()); |
918 isolate->counters()->wasm_reloc_size()->Increment( | 916 counters->wasm_reloc_size()->Increment(code->relocation_info()->length()); |
919 code->relocation_info()->length()); | |
920 } | 917 } |
921 | 918 |
922 } // namespace | 919 } // namespace |
923 | 920 |
924 Handle<JSArrayBuffer> wasm::SetupArrayBuffer(Isolate* isolate, | 921 Handle<JSArrayBuffer> wasm::SetupArrayBuffer(Isolate* isolate, |
925 void* allocation_base, | 922 void* allocation_base, |
926 size_t allocation_length, | 923 size_t allocation_length, |
927 void* backing_store, size_t size, | 924 void* backing_store, size_t size, |
928 bool is_external, | 925 bool is_external, |
929 bool enable_guard_regions) { | 926 bool enable_guard_regions) { |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1144 // It closes over the {Isolate}, the {ErrorThrower}, the {WasmCompiledModule}, | 1141 // It closes over the {Isolate}, the {ErrorThrower}, the {WasmCompiledModule}, |
1145 // etc. | 1142 // etc. |
1146 class InstantiationHelper { | 1143 class InstantiationHelper { |
1147 public: | 1144 public: |
1148 InstantiationHelper(Isolate* isolate, ErrorThrower* thrower, | 1145 InstantiationHelper(Isolate* isolate, ErrorThrower* thrower, |
1149 Handle<WasmModuleObject> module_object, | 1146 Handle<WasmModuleObject> module_object, |
1150 MaybeHandle<JSReceiver> ffi, | 1147 MaybeHandle<JSReceiver> ffi, |
1151 MaybeHandle<JSArrayBuffer> memory) | 1148 MaybeHandle<JSArrayBuffer> memory) |
1152 : isolate_(isolate), | 1149 : isolate_(isolate), |
1153 module_(module_object->compiled_module()->module()), | 1150 module_(module_object->compiled_module()->module()), |
1151 counters_shared_(isolate->counters_shared()), | |
1154 thrower_(thrower), | 1152 thrower_(thrower), |
1155 module_object_(module_object), | 1153 module_object_(module_object), |
1156 ffi_(ffi.is_null() ? Handle<JSReceiver>::null() | 1154 ffi_(ffi.is_null() ? Handle<JSReceiver>::null() |
1157 : ffi.ToHandleChecked()), | 1155 : ffi.ToHandleChecked()), |
1158 memory_(memory.is_null() ? Handle<JSArrayBuffer>::null() | 1156 memory_(memory.is_null() ? Handle<JSArrayBuffer>::null() |
1159 : memory.ToHandleChecked()) {} | 1157 : memory.ToHandleChecked()) { |
1158 counters_ = counters_shared_.get(); | |
1159 } | |
1160 | 1160 |
1161 // Build an instance, in all of its glory. | 1161 // Build an instance, in all of its glory. |
1162 MaybeHandle<WasmInstanceObject> Build() { | 1162 MaybeHandle<WasmInstanceObject> Build() { |
1163 // Check that an imports argument was provided, if the module requires it. | 1163 // Check that an imports argument was provided, if the module requires it. |
1164 // No point in continuing otherwise. | 1164 // No point in continuing otherwise. |
1165 if (!module_->import_table.empty() && ffi_.is_null()) { | 1165 if (!module_->import_table.empty() && ffi_.is_null()) { |
1166 thrower_->TypeError( | 1166 thrower_->TypeError( |
1167 "Imports argument must be present and must be an object"); | 1167 "Imports argument must be present and must be an object"); |
1168 return {}; | 1168 return {}; |
1169 } | 1169 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1239 case Code::JS_TO_WASM_FUNCTION: | 1239 case Code::JS_TO_WASM_FUNCTION: |
1240 case Code::WASM_FUNCTION: { | 1240 case Code::WASM_FUNCTION: { |
1241 Handle<Code> code = factory->CopyCode(orig_code); | 1241 Handle<Code> code = factory->CopyCode(orig_code); |
1242 code_table->set(i, *code); | 1242 code_table->set(i, *code); |
1243 break; | 1243 break; |
1244 } | 1244 } |
1245 default: | 1245 default: |
1246 UNREACHABLE(); | 1246 UNREACHABLE(); |
1247 } | 1247 } |
1248 } | 1248 } |
1249 RecordStats(isolate_, code_table, is_sync_); | 1249 RecordStats(code_table, counters_); |
1250 } else { | 1250 } else { |
1251 // There was no owner, so we can reuse the original. | 1251 // There was no owner, so we can reuse the original. |
1252 compiled_module_ = original; | 1252 compiled_module_ = original; |
1253 old_code_table = | 1253 old_code_table = |
1254 factory->CopyFixedArray(compiled_module_->code_table()); | 1254 factory->CopyFixedArray(compiled_module_->code_table()); |
1255 code_table = compiled_module_->code_table(); | 1255 code_table = compiled_module_->code_table(); |
1256 TRACE("Reusing existing instance %d\n", | 1256 TRACE("Reusing existing instance %d\n", |
1257 compiled_module_->instance_id()); | 1257 compiled_module_->instance_id()); |
1258 } | 1258 } |
1259 compiled_module_->set_native_context(isolate_->native_context()); | 1259 compiled_module_->set_native_context(isolate_->native_context()); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1516 int start_index = module_->start_function_index; | 1516 int start_index = module_->start_function_index; |
1517 Handle<Code> startup_code = EnsureExportedLazyDeoptData( | 1517 Handle<Code> startup_code = EnsureExportedLazyDeoptData( |
1518 isolate_, instance, code_table, start_index); | 1518 isolate_, instance, code_table, start_index); |
1519 FunctionSig* sig = module_->functions[start_index].sig; | 1519 FunctionSig* sig = module_->functions[start_index].sig; |
1520 Handle<Code> wrapper_code = | 1520 Handle<Code> wrapper_code = |
1521 js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper( | 1521 js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper( |
1522 isolate_, module_, startup_code, start_index); | 1522 isolate_, module_, startup_code, start_index); |
1523 Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New( | 1523 Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New( |
1524 isolate_, instance, MaybeHandle<String>(), start_index, | 1524 isolate_, instance, MaybeHandle<String>(), start_index, |
1525 static_cast<int>(sig->parameter_count()), wrapper_code); | 1525 static_cast<int>(sig->parameter_count()), wrapper_code); |
1526 RecordStats(isolate_, *startup_code, is_sync_); | 1526 RecordStats(*startup_code, counters_); |
1527 // Call the JS function. | 1527 // Call the JS function. |
1528 Handle<Object> undefined = factory->undefined_value(); | 1528 Handle<Object> undefined = factory->undefined_value(); |
1529 MaybeHandle<Object> retval = | 1529 MaybeHandle<Object> retval = |
1530 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); | 1530 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); |
1531 | 1531 |
1532 if (retval.is_null()) { | 1532 if (retval.is_null()) { |
1533 DCHECK(isolate_->has_pending_exception()); | 1533 DCHECK(isolate_->has_pending_exception()); |
1534 isolate_->OptionalRescheduleException(false); | 1534 isolate_->OptionalRescheduleException(false); |
1535 // It's unfortunate that the new instance is already linked in the | 1535 // It's unfortunate that the new instance is already linked in the |
1536 // chain. However, we need to set up everything before executing the | 1536 // chain. However, we need to set up everything before executing the |
(...skipping 13 matching lines...) Expand all Loading... | |
1550 // Represents the initialized state of a table. | 1550 // Represents the initialized state of a table. |
1551 struct TableInstance { | 1551 struct TableInstance { |
1552 Handle<WasmTableObject> table_object; // WebAssembly.Table instance | 1552 Handle<WasmTableObject> table_object; // WebAssembly.Table instance |
1553 Handle<FixedArray> js_wrappers; // JSFunctions exported | 1553 Handle<FixedArray> js_wrappers; // JSFunctions exported |
1554 Handle<FixedArray> function_table; // internal code array | 1554 Handle<FixedArray> function_table; // internal code array |
1555 Handle<FixedArray> signature_table; // internal sig array | 1555 Handle<FixedArray> signature_table; // internal sig array |
1556 }; | 1556 }; |
1557 | 1557 |
1558 Isolate* isolate_; | 1558 Isolate* isolate_; |
1559 WasmModule* const module_; | 1559 WasmModule* const module_; |
1560 constexpr static bool is_sync_ = true; | 1560 std::shared_ptr<Counters> counters_shared_; |
1561 Counters* counters_; | |
Clemens Hammacher
2017/06/02 13:08:50
Same here.
kschimpf
2017/06/02 17:06:28
Fixed in CL https://codereview.chromium.org/291995
| |
1561 ErrorThrower* thrower_; | 1562 ErrorThrower* thrower_; |
1562 Handle<WasmModuleObject> module_object_; | 1563 Handle<WasmModuleObject> module_object_; |
1563 Handle<JSReceiver> ffi_; // TODO(titzer): Use MaybeHandle | 1564 Handle<JSReceiver> ffi_; // TODO(titzer): Use MaybeHandle |
1564 Handle<JSArrayBuffer> memory_; // TODO(titzer): Use MaybeHandle | 1565 Handle<JSArrayBuffer> memory_; // TODO(titzer): Use MaybeHandle |
1565 Handle<JSArrayBuffer> globals_; | 1566 Handle<JSArrayBuffer> globals_; |
1566 Handle<WasmCompiledModule> compiled_module_; | 1567 Handle<WasmCompiledModule> compiled_module_; |
1567 std::vector<TableInstance> table_instances_; | 1568 std::vector<TableInstance> table_instances_; |
1568 std::vector<Handle<JSFunction>> js_wrappers_; | 1569 std::vector<Handle<JSFunction>> js_wrappers_; |
1569 JSToWasmWrapperCache js_to_wasm_cache_; | 1570 JSToWasmWrapperCache js_to_wasm_cache_; |
1570 | 1571 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1760 isolate_, index, module_->functions[import.index].sig, | 1761 isolate_, index, module_->functions[import.index].sig, |
1761 Handle<JSReceiver>::cast(value), module_name, import_name, | 1762 Handle<JSReceiver>::cast(value), module_name, import_name, |
1762 module_->get_origin()); | 1763 module_->get_origin()); |
1763 if (import_wrapper.is_null()) { | 1764 if (import_wrapper.is_null()) { |
1764 ReportLinkError( | 1765 ReportLinkError( |
1765 "imported function does not match the expected type", index, | 1766 "imported function does not match the expected type", index, |
1766 module_name, import_name); | 1767 module_name, import_name); |
1767 return -1; | 1768 return -1; |
1768 } | 1769 } |
1769 code_table->set(num_imported_functions, *import_wrapper); | 1770 code_table->set(num_imported_functions, *import_wrapper); |
1770 RecordStats(isolate_, *import_wrapper, is_sync_); | 1771 RecordStats(*import_wrapper, counters_); |
1771 num_imported_functions++; | 1772 num_imported_functions++; |
1772 break; | 1773 break; |
1773 } | 1774 } |
1774 case kExternalTable: { | 1775 case kExternalTable: { |
1775 if (!WasmJs::IsWasmTableObject(isolate_, value)) { | 1776 if (!WasmJs::IsWasmTableObject(isolate_, value)) { |
1776 ReportLinkError("table import requires a WebAssembly.Table", index, | 1777 ReportLinkError("table import requires a WebAssembly.Table", index, |
1777 module_name, import_name); | 1778 module_name, import_name); |
1778 return -1; | 1779 return -1; |
1779 } | 1780 } |
1780 WasmIndirectFunctionTable& table = | 1781 WasmIndirectFunctionTable& table = |
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2733 // e.g. when we synchronizing tasks or when we delete the AyncCompileJob. | 2734 // e.g. when we synchronizing tasks or when we delete the AyncCompileJob. |
2734 class AsyncCompileJob { | 2735 class AsyncCompileJob { |
2735 // TODO(ahaas): Fix https://bugs.chromium.org/p/v8/issues/detail?id=6263 to | 2736 // TODO(ahaas): Fix https://bugs.chromium.org/p/v8/issues/detail?id=6263 to |
2736 // make sure that d8 does not shut down before the AsyncCompileJob is | 2737 // make sure that d8 does not shut down before the AsyncCompileJob is |
2737 // finished. | 2738 // finished. |
2738 public: | 2739 public: |
2739 explicit AsyncCompileJob(Isolate* isolate, std::unique_ptr<byte[]> bytes_copy, | 2740 explicit AsyncCompileJob(Isolate* isolate, std::unique_ptr<byte[]> bytes_copy, |
2740 size_t length, Handle<Context> context, | 2741 size_t length, Handle<Context> context, |
2741 Handle<JSPromise> promise) | 2742 Handle<JSPromise> promise) |
2742 : isolate_(isolate), | 2743 : isolate_(isolate), |
2744 counters_shared_(isolate->counters_shared()), | |
2743 bytes_copy_(std::move(bytes_copy)), | 2745 bytes_copy_(std::move(bytes_copy)), |
2744 wire_bytes_(bytes_copy_.get(), bytes_copy_.get() + length) { | 2746 wire_bytes_(bytes_copy_.get(), bytes_copy_.get() + length) { |
2745 // The handles for the context and promise must be deferred. | 2747 // The handles for the context and promise must be deferred. |
2746 DeferredHandleScope deferred(isolate); | 2748 DeferredHandleScope deferred(isolate); |
2747 context_ = Handle<Context>(*context); | 2749 context_ = Handle<Context>(*context); |
2748 module_promise_ = Handle<JSPromise>(*promise); | 2750 module_promise_ = Handle<JSPromise>(*promise); |
2749 deferred_handles_.push_back(deferred.Detach()); | 2751 deferred_handles_.push_back(deferred.Detach()); |
2752 counters_ = counters_shared_.get(); | |
2750 } | 2753 } |
2751 | 2754 |
2752 void Start() { | 2755 void Start() { |
2753 DoAsync<DecodeModule>(); // -- | 2756 DoAsync<DecodeModule>(); // -- |
2754 } | 2757 } |
2755 | 2758 |
2756 ~AsyncCompileJob() { | 2759 ~AsyncCompileJob() { |
2757 for (auto d : deferred_handles_) delete d; | 2760 for (auto d : deferred_handles_) delete d; |
2758 } | 2761 } |
2759 | 2762 |
2760 private: | 2763 private: |
2761 Isolate* isolate_; | 2764 Isolate* isolate_; |
2765 std::shared_ptr<Counters> counters_shared_; | |
2766 Counters* counters_; | |
2762 std::unique_ptr<byte[]> bytes_copy_; | 2767 std::unique_ptr<byte[]> bytes_copy_; |
2763 ModuleWireBytes wire_bytes_; | 2768 ModuleWireBytes wire_bytes_; |
2764 Handle<Context> context_; | 2769 Handle<Context> context_; |
2765 Handle<JSPromise> module_promise_; | 2770 Handle<JSPromise> module_promise_; |
2766 std::unique_ptr<CompilationHelper> helper_; | 2771 std::unique_ptr<CompilationHelper> helper_; |
2767 std::unique_ptr<ModuleBytesEnv> module_bytes_env_; | 2772 std::unique_ptr<ModuleBytesEnv> module_bytes_env_; |
2768 | 2773 |
2769 bool failed_ = false; | 2774 bool failed_ = false; |
2770 std::vector<DeferredHandles*> deferred_handles_; | 2775 std::vector<DeferredHandles*> deferred_handles_; |
2771 Handle<WasmModuleObject> module_object_; | 2776 Handle<WasmModuleObject> module_object_; |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3118 }; | 3123 }; |
3119 | 3124 |
3120 //========================================================================== | 3125 //========================================================================== |
3121 // Step 5b (sync): Finish heap-allocated data structures. | 3126 // Step 5b (sync): Finish heap-allocated data structures. |
3122 //========================================================================== | 3127 //========================================================================== |
3123 class FinishCompile : public SyncCompileTask { | 3128 class FinishCompile : public SyncCompileTask { |
3124 void RunImpl() override { | 3129 void RunImpl() override { |
3125 TRACE_COMPILE("(5b) Finish compile...\n"); | 3130 TRACE_COMPILE("(5b) Finish compile...\n"); |
3126 HandleScope scope(job_->isolate_); | 3131 HandleScope scope(job_->isolate_); |
3127 // At this point, compilation has completed. Update the code table. | 3132 // At this point, compilation has completed. Update the code table. |
3128 constexpr bool is_sync = true; | |
3129 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 3133 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
3130 i < job_->temp_instance_->function_code.size(); ++i) { | 3134 i < job_->temp_instance_->function_code.size(); ++i) { |
3131 Code* code = Code::cast(job_->code_table_->get(static_cast<int>(i))); | 3135 Code* code = Code::cast(job_->code_table_->get(static_cast<int>(i))); |
3132 RecordStats(job_->isolate_, code, !is_sync); | 3136 RecordStats(code, job_->counters_); |
3133 } | 3137 } |
3134 | 3138 |
3135 // Create heap objects for script and module bytes to be stored in the | 3139 // Create heap objects for script and module bytes to be stored in the |
3136 // shared module data. Asm.js is not compiled asynchronously. | 3140 // shared module data. Asm.js is not compiled asynchronously. |
3137 Handle<Script> script = | 3141 Handle<Script> script = |
3138 CreateWasmScript(job_->isolate_, job_->wire_bytes_); | 3142 CreateWasmScript(job_->isolate_, job_->wire_bytes_); |
3139 Handle<ByteArray> asm_js_offset_table; | 3143 Handle<ByteArray> asm_js_offset_table; |
3140 // TODO(wasm): Improve efficiency of storing module wire bytes. | 3144 // TODO(wasm): Improve efficiency of storing module wire bytes. |
3141 // 1. Only store relevant sections, not function bodies | 3145 // 1. Only store relevant sections, not function bodies |
3142 // 2. Don't make a second copy of the bytes here; reuse the copy made | 3146 // 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... | |
3188 //========================================================================== | 3192 //========================================================================== |
3189 // Step 6 (sync): Compile JS->WASM wrappers. | 3193 // Step 6 (sync): Compile JS->WASM wrappers. |
3190 //========================================================================== | 3194 //========================================================================== |
3191 class CompileWrappers : public SyncCompileTask { | 3195 class CompileWrappers : public SyncCompileTask { |
3192 void RunImpl() override { | 3196 void RunImpl() override { |
3193 TRACE_COMPILE("(6) Compile wrappers...\n"); | 3197 TRACE_COMPILE("(6) Compile wrappers...\n"); |
3194 // Compile JS->WASM wrappers for exported functions. | 3198 // Compile JS->WASM wrappers for exported functions. |
3195 HandleScope scope(job_->isolate_); | 3199 HandleScope scope(job_->isolate_); |
3196 JSToWasmWrapperCache js_to_wasm_cache; | 3200 JSToWasmWrapperCache js_to_wasm_cache; |
3197 int func_index = 0; | 3201 int func_index = 0; |
3198 constexpr bool is_sync = true; | |
3199 WasmModule* module = job_->compiled_module_->module(); | 3202 WasmModule* module = job_->compiled_module_->module(); |
3200 for (auto exp : module->export_table) { | 3203 for (auto exp : module->export_table) { |
3201 if (exp.kind != kExternalFunction) continue; | 3204 if (exp.kind != kExternalFunction) continue; |
3202 Handle<Code> wasm_code(Code::cast(job_->code_table_->get(exp.index)), | 3205 Handle<Code> wasm_code(Code::cast(job_->code_table_->get(exp.index)), |
3203 job_->isolate_); | 3206 job_->isolate_); |
3204 Handle<Code> wrapper_code = | 3207 Handle<Code> wrapper_code = |
3205 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper( | 3208 js_to_wasm_cache.CloneOrCompileJSToWasmWrapper( |
3206 job_->isolate_, module, wasm_code, exp.index); | 3209 job_->isolate_, module, wasm_code, exp.index); |
3207 int export_index = | 3210 int export_index = |
3208 static_cast<int>(module->functions.size() + func_index); | 3211 static_cast<int>(module->functions.size() + func_index); |
3209 job_->code_table_->set(export_index, *wrapper_code); | 3212 job_->code_table_->set(export_index, *wrapper_code); |
3210 RecordStats(job_->isolate_, *wrapper_code, !is_sync); | 3213 RecordStats(*wrapper_code, job_->counters_); |
3211 func_index++; | 3214 func_index++; |
3212 } | 3215 } |
3213 | 3216 |
3214 job_->DoSync<FinishModule>(); | 3217 job_->DoSync<FinishModule>(); |
3215 } | 3218 } |
3216 }; | 3219 }; |
3217 | 3220 |
3218 //========================================================================== | 3221 //========================================================================== |
3219 // Step 7 (sync): Finish the module and resolve the promise. | 3222 // Step 7 (sync): Finish the module and resolve the promise. |
3220 //========================================================================== | 3223 //========================================================================== |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3324 // do the patching redundantly. | 3327 // do the patching redundantly. |
3325 Handle<FixedArray> new_deopt_data = | 3328 Handle<FixedArray> new_deopt_data = |
3326 isolate->factory()->CopyFixedArrayUpTo(exp_deopt_data, 2, TENURED); | 3329 isolate->factory()->CopyFixedArrayUpTo(exp_deopt_data, 2, TENURED); |
3327 lazy_compile_code->set_deoptimization_data(*new_deopt_data); | 3330 lazy_compile_code->set_deoptimization_data(*new_deopt_data); |
3328 } | 3331 } |
3329 | 3332 |
3330 return compiled_code; | 3333 return compiled_code; |
3331 } | 3334 } |
3332 | 3335 |
3333 void LazyCompilationOrchestrator::CompileFunction( | 3336 void LazyCompilationOrchestrator::CompileFunction( |
3334 Isolate* isolate, Handle<WasmInstanceObject> instance, int func_index) { | 3337 Isolate* isolate, Handle<WasmInstanceObject> instance, int func_index, |
3338 Counters* counters) { | |
3335 Handle<WasmCompiledModule> compiled_module(instance->compiled_module(), | 3339 Handle<WasmCompiledModule> compiled_module(instance->compiled_module(), |
3336 isolate); | 3340 isolate); |
3337 if (Code::cast(compiled_module->code_table()->get(func_index))->kind() == | 3341 if (Code::cast(compiled_module->code_table()->get(func_index))->kind() == |
3338 Code::WASM_FUNCTION) { | 3342 Code::WASM_FUNCTION) { |
3339 return; | 3343 return; |
3340 } | 3344 } |
3341 | 3345 |
3342 size_t num_function_tables = | 3346 size_t num_function_tables = |
3343 compiled_module->module()->function_tables.size(); | 3347 compiled_module->module()->function_tables.size(); |
3344 // Store a vector of handles to be embedded in the generated code. | 3348 // Store a vector of handles to be embedded in the generated code. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3412 DCHECK_IMPLIES(mem_size == 0, mem_start == nullptr); | 3416 DCHECK_IMPLIES(mem_size == 0, mem_start == nullptr); |
3413 if (mem_size > 0) { | 3417 if (mem_size > 0) { |
3414 code_specialization.RelocateMemoryReferences(nullptr, 0, mem_start, | 3418 code_specialization.RelocateMemoryReferences(nullptr, 0, mem_start, |
3415 mem_size); | 3419 mem_size); |
3416 } | 3420 } |
3417 } | 3421 } |
3418 code_specialization.RelocateDirectCalls(instance); | 3422 code_specialization.RelocateDirectCalls(instance); |
3419 code_specialization.ApplyToWasmCode(*code, SKIP_ICACHE_FLUSH); | 3423 code_specialization.ApplyToWasmCode(*code, SKIP_ICACHE_FLUSH); |
3420 Assembler::FlushICache(isolate, code->instruction_start(), | 3424 Assembler::FlushICache(isolate, code->instruction_start(), |
3421 code->instruction_size()); | 3425 code->instruction_size()); |
3422 RecordLazyCodeStats(isolate, *code); | 3426 RecordLazyCodeStats(*code, counters); |
3423 } | 3427 } |
3424 | 3428 |
3425 Handle<Code> LazyCompilationOrchestrator::CompileLazy( | 3429 Handle<Code> LazyCompilationOrchestrator::CompileLazy( |
3426 Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> caller, | 3430 Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> caller, |
3427 int call_offset, int exported_func_index, bool patch_caller) { | 3431 int call_offset, int exported_func_index, bool patch_caller) { |
3428 struct NonCompiledFunction { | 3432 struct NonCompiledFunction { |
3429 int offset; | 3433 int offset; |
3430 int func_index; | 3434 int func_index; |
3431 }; | 3435 }; |
3436 std::shared_ptr<Counters> counters_shared = isolate->counters_shared(); | |
3437 Counters* counters = counters_shared.get(); | |
3432 std::vector<NonCompiledFunction> non_compiled_functions; | 3438 std::vector<NonCompiledFunction> non_compiled_functions; |
3433 int func_to_return_idx = exported_func_index; | 3439 int func_to_return_idx = exported_func_index; |
3434 wasm::Decoder decoder(nullptr, nullptr); | 3440 wasm::Decoder decoder(nullptr, nullptr); |
3435 bool is_js_to_wasm = caller->kind() == Code::JS_TO_WASM_FUNCTION; | 3441 bool is_js_to_wasm = caller->kind() == Code::JS_TO_WASM_FUNCTION; |
3436 Handle<WasmCompiledModule> compiled_module(instance->compiled_module(), | 3442 Handle<WasmCompiledModule> compiled_module(instance->compiled_module(), |
3437 isolate); | 3443 isolate); |
3438 | 3444 |
3439 if (is_js_to_wasm) { | 3445 if (is_js_to_wasm) { |
3440 non_compiled_functions.push_back({0, exported_func_index}); | 3446 non_compiled_functions.push_back({0, exported_func_index}); |
3441 } else if (patch_caller) { | 3447 } else if (patch_caller) { |
(...skipping 24 matching lines...) Expand all Loading... | |
3466 ExtractDirectCallIndex(decoder, func_bytes + byte_pos); | 3472 ExtractDirectCallIndex(decoder, func_bytes + byte_pos); |
3467 non_compiled_functions.push_back({offset, called_func_index}); | 3473 non_compiled_functions.push_back({offset, called_func_index}); |
3468 // Call offset one instruction after the call. Remember the last called | 3474 // Call offset one instruction after the call. Remember the last called |
3469 // function before that offset. | 3475 // function before that offset. |
3470 if (offset < call_offset) func_to_return_idx = called_func_index; | 3476 if (offset < call_offset) func_to_return_idx = called_func_index; |
3471 } | 3477 } |
3472 } | 3478 } |
3473 | 3479 |
3474 // TODO(clemensh): compile all functions in non_compiled_functions in | 3480 // TODO(clemensh): compile all functions in non_compiled_functions in |
3475 // background, wait for func_to_return_idx. | 3481 // background, wait for func_to_return_idx. |
3476 CompileFunction(isolate, instance, func_to_return_idx); | 3482 CompileFunction(isolate, instance, func_to_return_idx, counters); |
3477 | 3483 |
3478 if (is_js_to_wasm || patch_caller) { | 3484 if (is_js_to_wasm || patch_caller) { |
3479 DisallowHeapAllocation no_gc; | 3485 DisallowHeapAllocation no_gc; |
3480 // Now patch the code object with all functions which are now compiled. | 3486 // Now patch the code object with all functions which are now compiled. |
3481 int idx = 0; | 3487 int idx = 0; |
3482 for (RelocIterator it(*caller, RelocInfo::kCodeTargetMask); !it.done(); | 3488 for (RelocIterator it(*caller, RelocInfo::kCodeTargetMask); !it.done(); |
3483 it.next()) { | 3489 it.next()) { |
3484 Code* callee = | 3490 Code* callee = |
3485 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | 3491 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
3486 if (callee->builtin_index() != Builtins::kWasmCompileLazy) continue; | 3492 if (callee->builtin_index() != Builtins::kWasmCompileLazy) continue; |
(...skipping 22 matching lines...) Expand all Loading... | |
3509 callee_compiled->instruction_start()); | 3515 callee_compiled->instruction_start()); |
3510 } | 3516 } |
3511 DCHECK_EQ(non_compiled_functions.size(), idx); | 3517 DCHECK_EQ(non_compiled_functions.size(), idx); |
3512 } | 3518 } |
3513 | 3519 |
3514 Code* ret = | 3520 Code* ret = |
3515 Code::cast(compiled_module->code_table()->get(func_to_return_idx)); | 3521 Code::cast(compiled_module->code_table()->get(func_to_return_idx)); |
3516 DCHECK_EQ(Code::WASM_FUNCTION, ret->kind()); | 3522 DCHECK_EQ(Code::WASM_FUNCTION, ret->kind()); |
3517 return handle(ret, isolate); | 3523 return handle(ret, isolate); |
3518 } | 3524 } |
OLD | NEW |