| 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 |