OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <memory> | 5 #include <memory> |
6 | 6 |
7 #include "src/assembler-inl.h" | 7 #include "src/assembler-inl.h" |
8 #include "src/base/adapters.h" | 8 #include "src/base/adapters.h" |
9 #include "src/base/atomic-utils.h" | 9 #include "src/base/atomic-utils.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 740 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 | 751 |
752 int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash); | 752 int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash); |
753 DCHECK(name_chars >= 0 && name_chars < kBufferSize); | 753 DCHECK(name_chars >= 0 && name_chars < kBufferSize); |
754 MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte( | 754 MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte( |
755 Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars), | 755 Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars), |
756 TENURED); | 756 TENURED); |
757 script->set_name(*name_str.ToHandleChecked()); | 757 script->set_name(*name_str.ToHandleChecked()); |
758 | 758 |
759 return script; | 759 return script; |
760 } | 760 } |
| 761 |
| 762 class JSToWasmWrapperCache { |
| 763 public: |
| 764 Handle<Code> CloneOrCompileJSToWasmWrapper(Isolate* isolate, |
| 765 const wasm::WasmModule* module, |
| 766 Handle<Code> wasm_code, |
| 767 uint32_t index) { |
| 768 const wasm::WasmFunction* func = &module->functions[index]; |
| 769 int cached_idx = sig_map_.Find(func->sig); |
| 770 if (cached_idx >= 0) { |
| 771 Handle<Code> code = isolate->factory()->CopyCode(code_cache_[cached_idx]); |
| 772 // Now patch the call to wasm code. |
| 773 for (RelocIterator it(*code, RelocInfo::kCodeTargetMask);; it.next()) { |
| 774 DCHECK(!it.done()); |
| 775 Code* target = |
| 776 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
| 777 if (target->kind() == Code::WASM_FUNCTION || |
| 778 target->kind() == Code::WASM_TO_JS_FUNCTION || |
| 779 target->builtin_index() == Builtins::kIllegal) { |
| 780 it.rinfo()->set_target_address(wasm_code->instruction_start()); |
| 781 break; |
| 782 } |
| 783 } |
| 784 return code; |
| 785 } |
| 786 |
| 787 Handle<Code> code = |
| 788 compiler::CompileJSToWasmWrapper(isolate, module, wasm_code, index); |
| 789 uint32_t new_cache_idx = sig_map_.FindOrInsert(func->sig); |
| 790 DCHECK_EQ(code_cache_.size(), new_cache_idx); |
| 791 USE(new_cache_idx); |
| 792 code_cache_.push_back(code); |
| 793 return code; |
| 794 } |
| 795 |
| 796 private: |
| 797 // sig_map_ maps signatures to an index in code_cache_. |
| 798 wasm::SignatureMap sig_map_; |
| 799 std::vector<Handle<Code>> code_cache_; |
| 800 }; |
| 801 |
761 } // namespace | 802 } // namespace |
762 | 803 |
763 Handle<JSArrayBuffer> SetupArrayBuffer(Isolate* isolate, void* backing_store, | 804 Handle<JSArrayBuffer> SetupArrayBuffer(Isolate* isolate, void* backing_store, |
764 size_t size, bool is_external, | 805 size_t size, bool is_external, |
765 bool enable_guard_regions) { | 806 bool enable_guard_regions) { |
766 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); | 807 Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer(); |
767 JSArrayBuffer::Setup(buffer, isolate, is_external, backing_store, | 808 JSArrayBuffer::Setup(buffer, isolate, is_external, backing_store, |
768 static_cast<int>(size)); | 809 static_cast<int>(size)); |
769 buffer->set_is_neuterable(false); | 810 buffer->set_is_neuterable(false); |
770 buffer->set_has_guard_region(enable_guard_regions); | 811 buffer->set_has_guard_region(enable_guard_regions); |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 } | 1056 } |
1016 | 1057 |
1017 // If we created a wasm script, finish it now and make it public to the | 1058 // If we created a wasm script, finish it now and make it public to the |
1018 // debugger. | 1059 // debugger. |
1019 if (asm_js_script.is_null()) { | 1060 if (asm_js_script.is_null()) { |
1020 script->set_wasm_compiled_module(*compiled_module); | 1061 script->set_wasm_compiled_module(*compiled_module); |
1021 isolate->debug()->OnAfterCompile(script); | 1062 isolate->debug()->OnAfterCompile(script); |
1022 } | 1063 } |
1023 | 1064 |
1024 // Compile JS->WASM wrappers for exported functions. | 1065 // Compile JS->WASM wrappers for exported functions. |
| 1066 JSToWasmWrapperCache js_to_wasm_cache; |
1025 int func_index = 0; | 1067 int func_index = 0; |
1026 for (auto exp : m->export_table) { | 1068 for (auto exp : m->export_table) { |
1027 if (exp.kind != kExternalFunction) continue; | 1069 if (exp.kind != kExternalFunction) continue; |
1028 Handle<Code> wasm_code = | 1070 Handle<Code> wasm_code(Code::cast(code_table->get(exp.index)), isolate); |
1029 code_table->GetValueChecked<Code>(isolate, exp.index); | 1071 Handle<Code> wrapper_code = js_to_wasm_cache.CloneOrCompileJSToWasmWrapper( |
1030 Handle<Code> wrapper_code = | 1072 isolate, m, wasm_code, exp.index); |
1031 compiler::CompileJSToWasmWrapper(isolate, m, wasm_code, exp.index); | |
1032 int export_index = static_cast<int>(m->functions.size() + func_index); | 1073 int export_index = static_cast<int>(m->functions.size() + func_index); |
1033 code_table->set(export_index, *wrapper_code); | 1074 code_table->set(export_index, *wrapper_code); |
1034 RecordStats(isolate, *wrapper_code); | 1075 RecordStats(isolate, *wrapper_code); |
1035 func_index++; | 1076 func_index++; |
1036 } | 1077 } |
1037 | 1078 |
1038 return WasmModuleObject::New(isolate, compiled_module); | 1079 return WasmModuleObject::New(isolate, compiled_module); |
1039 } | 1080 } |
1040 | 1081 |
1041 static WasmFunction* GetWasmFunctionForImportWrapper(Isolate* isolate, | 1082 static WasmFunction* GetWasmFunctionForImportWrapper(Isolate* isolate, |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1482 | 1523 |
1483 //-------------------------------------------------------------------------- | 1524 //-------------------------------------------------------------------------- |
1484 // Run the start function if one was specified. | 1525 // Run the start function if one was specified. |
1485 //-------------------------------------------------------------------------- | 1526 //-------------------------------------------------------------------------- |
1486 if (module_->start_function_index >= 0) { | 1527 if (module_->start_function_index >= 0) { |
1487 HandleScope scope(isolate_); | 1528 HandleScope scope(isolate_); |
1488 int start_index = module_->start_function_index; | 1529 int start_index = module_->start_function_index; |
1489 Handle<Code> startup_code = | 1530 Handle<Code> startup_code = |
1490 code_table->GetValueChecked<Code>(isolate_, start_index); | 1531 code_table->GetValueChecked<Code>(isolate_, start_index); |
1491 FunctionSig* sig = module_->functions[start_index].sig; | 1532 FunctionSig* sig = module_->functions[start_index].sig; |
1492 Handle<Code> wrapper_code = compiler::CompileJSToWasmWrapper( | 1533 Handle<Code> wrapper_code = |
1493 isolate_, module_, startup_code, start_index); | 1534 js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper( |
| 1535 isolate_, module_, startup_code, start_index); |
1494 Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New( | 1536 Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New( |
1495 isolate_, instance, MaybeHandle<String>(), start_index, | 1537 isolate_, instance, MaybeHandle<String>(), start_index, |
1496 static_cast<int>(sig->parameter_count()), wrapper_code); | 1538 static_cast<int>(sig->parameter_count()), wrapper_code); |
1497 RecordStats(isolate_, *startup_code); | 1539 RecordStats(isolate_, *startup_code); |
1498 // Call the JS function. | 1540 // Call the JS function. |
1499 Handle<Object> undefined = factory->undefined_value(); | 1541 Handle<Object> undefined = factory->undefined_value(); |
1500 MaybeHandle<Object> retval = | 1542 MaybeHandle<Object> retval = |
1501 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); | 1543 Execution::Call(isolate_, startup_fct, undefined, 0, nullptr); |
1502 | 1544 |
1503 if (retval.is_null()) { | 1545 if (retval.is_null()) { |
(...skipping 25 matching lines...) Expand all Loading... |
1529 Isolate* isolate_; | 1571 Isolate* isolate_; |
1530 WasmModule* const module_; | 1572 WasmModule* const module_; |
1531 ErrorThrower* thrower_; | 1573 ErrorThrower* thrower_; |
1532 Handle<WasmModuleObject> module_object_; | 1574 Handle<WasmModuleObject> module_object_; |
1533 Handle<JSReceiver> ffi_; // TODO(titzer): Use MaybeHandle | 1575 Handle<JSReceiver> ffi_; // TODO(titzer): Use MaybeHandle |
1534 Handle<JSArrayBuffer> memory_; // TODO(titzer): Use MaybeHandle | 1576 Handle<JSArrayBuffer> memory_; // TODO(titzer): Use MaybeHandle |
1535 Handle<JSArrayBuffer> globals_; | 1577 Handle<JSArrayBuffer> globals_; |
1536 Handle<WasmCompiledModule> compiled_module_; | 1578 Handle<WasmCompiledModule> compiled_module_; |
1537 std::vector<TableInstance> table_instances_; | 1579 std::vector<TableInstance> table_instances_; |
1538 std::vector<Handle<JSFunction>> js_wrappers_; | 1580 std::vector<Handle<JSFunction>> js_wrappers_; |
| 1581 JSToWasmWrapperCache js_to_wasm_cache_; |
1539 | 1582 |
1540 // Helper routines to print out errors with imports. | 1583 // Helper routines to print out errors with imports. |
1541 void ReportLinkError(const char* error, uint32_t index, | 1584 void ReportLinkError(const char* error, uint32_t index, |
1542 Handle<String> module_name, Handle<String> import_name) { | 1585 Handle<String> module_name, Handle<String> import_name) { |
1543 thrower_->LinkError( | 1586 thrower_->LinkError( |
1544 "Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", index, | 1587 "Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", index, |
1545 module_name->length(), module_name->ToCString().get(), | 1588 module_name->length(), module_name->ToCString().get(), |
1546 import_name->length(), import_name->ToCString().get(), error); | 1589 import_name->length(), import_name->ToCString().get(), error); |
1547 } | 1590 } |
1548 | 1591 |
(...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2200 // No JSFunction entry yet exists for this function. Create one. | 2243 // No JSFunction entry yet exists for this function. Create one. |
2201 // TODO(titzer): We compile JS->WASM wrappers for functions are | 2244 // TODO(titzer): We compile JS->WASM wrappers for functions are |
2202 // not exported but are in an exported table. This should be done | 2245 // not exported but are in an exported table. This should be done |
2203 // at module compile time and cached instead. | 2246 // at module compile time and cached instead. |
2204 WasmInstance temp_instance(module_); | 2247 WasmInstance temp_instance(module_); |
2205 temp_instance.context = isolate_->native_context(); | 2248 temp_instance.context = isolate_->native_context(); |
2206 temp_instance.mem_size = 0; | 2249 temp_instance.mem_size = 0; |
2207 temp_instance.mem_start = nullptr; | 2250 temp_instance.mem_start = nullptr; |
2208 temp_instance.globals_start = nullptr; | 2251 temp_instance.globals_start = nullptr; |
2209 | 2252 |
2210 Handle<Code> wrapper_code = compiler::CompileJSToWasmWrapper( | 2253 Handle<Code> wrapper_code = |
2211 isolate_, module_, wasm_code, func_index); | 2254 js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper( |
| 2255 isolate_, module_, wasm_code, func_index); |
2212 MaybeHandle<String> func_name; | 2256 MaybeHandle<String> func_name; |
2213 if (module_->origin == kAsmJsOrigin) { | 2257 if (module_->origin == kAsmJsOrigin) { |
2214 // For modules arising from asm.js, honor the names section. | 2258 // For modules arising from asm.js, honor the names section. |
2215 func_name = | 2259 func_name = |
2216 WasmCompiledModule::ExtractUtf8StringFromModuleBytes( | 2260 WasmCompiledModule::ExtractUtf8StringFromModuleBytes( |
2217 isolate_, compiled_module_, function->name_offset, | 2261 isolate_, compiled_module_, function->name_offset, |
2218 function->name_length) | 2262 function->name_length) |
2219 .ToHandleChecked(); | 2263 .ToHandleChecked(); |
2220 } | 2264 } |
2221 Handle<WasmExportedFunction> js_function = | 2265 Handle<WasmExportedFunction> js_function = |
(...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2901 Handle<String> module_property_name = | 2945 Handle<String> module_property_name = |
2902 isolate->factory()->InternalizeUtf8String("module"); | 2946 isolate->factory()->InternalizeUtf8String("module"); |
2903 Handle<String> instance_property_name = | 2947 Handle<String> instance_property_name = |
2904 isolate->factory()->InternalizeUtf8String("instance"); | 2948 isolate->factory()->InternalizeUtf8String("instance"); |
2905 JSObject::AddProperty(ret, module_property_name, module, NONE); | 2949 JSObject::AddProperty(ret, module_property_name, module, NONE); |
2906 JSObject::AddProperty(ret, instance_property_name, | 2950 JSObject::AddProperty(ret, instance_property_name, |
2907 instance_object.ToHandleChecked(), NONE); | 2951 instance_object.ToHandleChecked(), NONE); |
2908 | 2952 |
2909 ResolvePromise(isolate, promise, ret); | 2953 ResolvePromise(isolate, promise, ret); |
2910 } | 2954 } |
OLD | NEW |