Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(379)

Side by Side Diff: src/wasm/wasm-module.cc

Issue 2705993002: [wasm] Add JSToWasmWrapperCache to reuse generated wrapper code (Closed)
Patch Set: Fix comment Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/signature.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/signature.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698