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

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

Issue 2021323003: [wasm] remove faux code objects Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 6 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
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 "src/base/atomic-utils.h" 5 #include "src/base/atomic-utils.h"
6 #include "src/macro-assembler.h" 6 #include "src/macro-assembler.h"
7 #include "src/objects.h" 7 #include "src/objects.h"
8 #include "src/property-descriptor.h" 8 #include "src/property-descriptor.h"
9 #include "src/v8.h" 9 #include "src/v8.h"
10 10
11 #include "src/simulator.h" 11 #include "src/simulator.h"
12 12
13 #include "src/wasm/ast-decoder.h" 13 #include "src/wasm/ast-decoder.h"
14 #include "src/wasm/module-decoder.h" 14 #include "src/wasm/module-decoder.h"
15 #include "src/wasm/wasm-function-name-table.h" 15 #include "src/wasm/wasm-function-name-table.h"
16 #include "src/wasm/wasm-module.h" 16 #include "src/wasm/wasm-module.h"
17 #include "src/wasm/wasm-result.h" 17 #include "src/wasm/wasm-result.h"
18 18
19 #include "src/compiler/wasm-compiler.h" 19 #include "src/compiler/wasm-compiler.h"
20 20
21 namespace v8 { 21 namespace v8 {
22 namespace internal { 22 namespace internal {
23 namespace wasm { 23 namespace wasm {
24 24
25 static const int kPlaceholderMarker = 1000000000;
26
27 static const char* wasmSections[] = { 25 static const char* wasmSections[] = {
28 #define F(enumerator, order, string) string, 26 #define F(enumerator, order, string) string,
29 FOR_EACH_WASM_SECTION_TYPE(F) 27 FOR_EACH_WASM_SECTION_TYPE(F)
30 #undef F 28 #undef F
31 "<unknown>" // entry for "Max" 29 "<unknown>" // entry for "Max"
32 }; 30 };
33 31
34 static uint8_t wasmSectionsLengths[]{ 32 static uint8_t wasmSectionsLengths[]{
35 #define F(enumerator, order, string) sizeof(string) - 1, 33 #define F(enumerator, order, string) sizeof(string) - 1,
36 FOR_EACH_WASM_SECTION_TYPE(F) 34 FOR_EACH_WASM_SECTION_TYPE(F)
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 os.write(name.start(), name.length()); 102 os.write(name.start(), name.length());
105 } else { 103 } else {
106 os << "+" << pair.function_->func_index; 104 os << "+" << pair.function_->func_index;
107 } 105 }
108 } else { 106 } else {
109 os << "?"; 107 os << "?";
110 } 108 }
111 return os; 109 return os;
112 } 110 }
113 111
114 // A helper class for compiling multiple wasm functions that offers
115 // placeholder code objects for calling functions that are not yet compiled.
116 class WasmLinker {
117 public:
118 WasmLinker(Isolate* isolate, std::vector<Handle<Code>>* functions)
119 : isolate_(isolate),
120 placeholder_code_(functions->size()),
121 function_code_(functions) {
122 for (uint32_t i = 0; i < placeholder_code_.size(); ++i) {
123 CreatePlaceholder(i);
124 }
125 }
126
127 Handle<Code> GetPlaceholderCode(uint32_t index) const {
128 return placeholder_code_[index];
129 }
130
131 void Finish(uint32_t index, Handle<Code> code) {
132 DCHECK(index < function_code().size());
133 function_code()[index] = code;
134 }
135
136 void Link(Handle<FixedArray> function_table,
137 const std::vector<uint16_t>& functions) {
138 for (size_t i = 0; i < function_code().size(); i++) {
139 LinkFunction(function_code()[i]);
140 }
141 if (!function_table.is_null()) {
142 int table_size = static_cast<int>(functions.size());
143 DCHECK_EQ(function_table->length(), table_size * 2);
144 for (int i = 0; i < table_size; i++) {
145 function_table->set(i + table_size, *function_code()[functions[i]]);
146 }
147 }
148 }
149
150 private:
151 std::vector<Handle<Code>>& function_code() { return *function_code_; }
152
153 void CreatePlaceholder(uint32_t index) {
154 DCHECK(index < function_code().size());
155 DCHECK(function_code()[index].is_null());
156 // Create a placeholder code object and encode the corresponding index in
157 // the {constant_pool_offset} field of the code object.
158 // TODO(titzer): placeholder code objects are somewhat dangerous.
159 byte buffer[] = {0, 0, 0, 0, 0, 0, 0, 0}; // fake instructions.
160 CodeDesc desc = {buffer, 8, 8, 0, 0, nullptr};
161 Handle<Code> code = isolate_->factory()->NewCode(
162 desc, Code::KindField::encode(Code::WASM_FUNCTION),
163 Handle<Object>::null());
164 code->set_constant_pool_offset(static_cast<int>(index) +
165 kPlaceholderMarker);
166 placeholder_code_[index] = code;
167 function_code()[index] = code;
168 }
169
170 Isolate* isolate_;
171 std::vector<Handle<Code>> placeholder_code_;
172 std::vector<Handle<Code>>* function_code_;
173
174 void LinkFunction(Handle<Code> code) {
175 bool modified = false;
176 int mode_mask = RelocInfo::kCodeTargetMask;
177 AllowDeferredHandleDereference embedding_raw_address;
178 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
179 RelocInfo::Mode mode = it.rinfo()->rmode();
180 if (RelocInfo::IsCodeTarget(mode)) {
181 Code* target =
182 Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
183 if (target->kind() == Code::WASM_FUNCTION &&
184 target->constant_pool_offset() >= kPlaceholderMarker) {
185 // Patch direct calls to placeholder code objects.
186 uint32_t index = target->constant_pool_offset() - kPlaceholderMarker;
187 CHECK(index < function_code().size());
188 Handle<Code> new_target = function_code()[index];
189 if (target != *new_target) {
190 CHECK_EQ(*placeholder_code_[index], target);
191 it.rinfo()->set_target_address(new_target->instruction_start(),
192 SKIP_WRITE_BARRIER,
193 SKIP_ICACHE_FLUSH);
194 modified = true;
195 }
196 }
197 }
198 }
199 if (modified) {
200 Assembler::FlushICache(isolate_, code->instruction_start(),
201 code->instruction_size());
202 }
203 }
204 };
205
206 namespace { 112 namespace {
207 // Internal constants for the layout of the module object. 113 // Internal constants for the layout of the module object.
208 const int kWasmModuleInternalFieldCount = 5; 114 const int kWasmModuleInternalFieldCount = 5;
209 const int kWasmModuleFunctionTable = 0; 115 const int kWasmModuleFunctionTable = 0;
210 const int kWasmModuleCodeTable = 1; 116 const int kWasmModuleCodeTable = 1;
211 const int kWasmMemArrayBuffer = 2; 117 const int kWasmMemArrayBuffer = 2;
212 const int kWasmGlobalsArrayBuffer = 3; 118 const int kWasmGlobalsArrayBuffer = 3;
213 const int kWasmFunctionNamesArray = 4; 119 const int kWasmFunctionNamesArray = 4;
214 120
215 void LoadDataSegments(const WasmModule* module, byte* mem_addr, 121 void LoadDataSegments(const WasmModule* module, byte* mem_addr,
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 } 634 }
729 if (!instance.globals_buffer.is_null()) { 635 if (!instance.globals_buffer.is_null()) {
730 instance.js_object->SetInternalField(kWasmGlobalsArrayBuffer, 636 instance.js_object->SetInternalField(kWasmGlobalsArrayBuffer,
731 *instance.globals_buffer); 637 *instance.globals_buffer);
732 } 638 }
733 639
734 HistogramTimerScope wasm_compile_module_time_scope( 640 HistogramTimerScope wasm_compile_module_time_scope(
735 isolate->counters()->wasm_compile_module_time()); 641 isolate->counters()->wasm_compile_module_time());
736 642
737 instance.function_table = BuildFunctionTable(isolate, this); 643 instance.function_table = BuildFunctionTable(isolate, this);
738 WasmLinker linker(isolate, &instance.function_code);
739 ModuleEnv module_env; 644 ModuleEnv module_env;
740 module_env.module = this; 645 module_env.module = this;
741 module_env.instance = &instance; 646 module_env.instance = &instance;
742 module_env.linker = &linker;
743 module_env.origin = origin; 647 module_env.origin = origin;
744 648
745 //------------------------------------------------------------------------- 649 //-------------------------------------------------------------------------
746 // Compile wrappers to imported functions. 650 // Compile wrappers to imported functions.
747 //------------------------------------------------------------------------- 651 //-------------------------------------------------------------------------
748 if (!CompileWrappersToImportedFunctions(isolate, this, ffi, &instance, 652 if (!CompileWrappersToImportedFunctions(isolate, this, ffi, &instance,
749 &thrower, factory, &module_env, 653 &thrower, factory, &module_env,
750 code_stats)) { 654 code_stats)) {
751 return MaybeHandle<JSObject>(); 655 return MaybeHandle<JSObject>();
752 } 656 }
(...skipping 18 matching lines...) Expand all
771 // At this point, compilation has completed. Update the code table 675 // At this point, compilation has completed. Update the code table
772 // and record sizes. 676 // and record sizes.
773 for (size_t i = FLAG_skip_compiling_wasm_funcs; 677 for (size_t i = FLAG_skip_compiling_wasm_funcs;
774 i < instance.function_code.size(); ++i) { 678 i < instance.function_code.size(); ++i) {
775 Code* code = *instance.function_code[i]; 679 Code* code = *instance.function_code[i];
776 code_table->set(static_cast<int>(i), code); 680 code_table->set(static_cast<int>(i), code);
777 code_stats.Record(code); 681 code_stats.Record(code);
778 } 682 }
779 683
780 // Patch all direct call sites. 684 // Patch all direct call sites.
781 linker.Link(instance.function_table, this->function_table); 685 compiler::Link(isolate, instance.function_code);
686
687 instance.PopulateExportTable(instance.function_code, function_table);
688
782 instance.js_object->SetInternalField(kWasmModuleFunctionTable, 689 instance.js_object->SetInternalField(kWasmModuleFunctionTable,
783 Smi::FromInt(0)); 690 Smi::FromInt(0));
784 691
785 SetDeoptimizationData(factory, instance.js_object, instance.function_code); 692 SetDeoptimizationData(factory, instance.js_object, instance.function_code);
786 693
787 //------------------------------------------------------------------------- 694 //-------------------------------------------------------------------------
788 // Create and populate the exports object. 695 // Create and populate the exports object.
789 //------------------------------------------------------------------------- 696 //-------------------------------------------------------------------------
790 if (export_table.size() > 0 || mem_export) { 697 if (export_table.size() > 0 || mem_export) {
791 Handle<JSObject> exports_object; 698 Handle<JSObject> exports_object;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 MaybeHandle<Object> retval = 765 MaybeHandle<Object> retval =
859 Execution::Call(isolate, jsfunc, undefined, 0, nullptr); 766 Execution::Call(isolate, jsfunc, undefined, 0, nullptr);
860 767
861 if (retval.is_null()) { 768 if (retval.is_null()) {
862 thrower.Error("WASM.instantiateModule(): start function failed"); 769 thrower.Error("WASM.instantiateModule(): start function failed");
863 } 770 }
864 } 771 }
865 return instance.js_object; 772 return instance.js_object;
866 } 773 }
867 774
868 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const { 775 void WasmModuleInstance::PopulateExportTable(
869 DCHECK(IsValidFunction(index)); 776 const std::vector<Handle<Code>>& compiled_functions,
870 if (linker != nullptr) return linker->GetPlaceholderCode(index); 777 const std::vector<uint16_t>& functions) {
871 DCHECK_NOT_NULL(instance); 778 if (!function_table.is_null()) {
872 return instance->function_code[index]; 779 int table_size = static_cast<int>(functions.size());
780 DCHECK_EQ(function_table->length(), table_size * 2);
781 for (int i = 0; i < table_size; i++) {
782 function_table->set(i + table_size, *(compiled_functions[functions[i]]));
783 }
784 }
873 } 785 }
874 786
875 Handle<Code> ModuleEnv::GetImportCode(uint32_t index) { 787 Handle<Code> ModuleEnv::GetImportCode(uint32_t index) {
876 DCHECK(IsValidImport(index)); 788 DCHECK(IsValidImport(index));
877 return instance ? instance->import_code[index] : Handle<Code>::null(); 789 return instance ? instance->import_code[index] : Handle<Code>::null();
878 } 790 }
879 791
880 compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone, 792 compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone,
881 uint32_t index) { 793 uint32_t index) {
882 DCHECK(IsValidFunction(index)); 794 DCHECK(IsValidFunction(index));
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
924 836
925 // Allocate the globals area if necessary. 837 // Allocate the globals area if necessary.
926 if (!AllocateGlobals(&thrower, isolate, &instance)) { 838 if (!AllocateGlobals(&thrower, isolate, &instance)) {
927 return -1; 839 return -1;
928 } 840 }
929 841
930 // Build the function table. 842 // Build the function table.
931 instance.function_table = BuildFunctionTable(isolate, module); 843 instance.function_table = BuildFunctionTable(isolate, module);
932 844
933 // Create module environment. 845 // Create module environment.
934 WasmLinker linker(isolate, &instance.function_code);
935 ModuleEnv module_env; 846 ModuleEnv module_env;
936 module_env.module = module; 847 module_env.module = module;
937 module_env.instance = &instance; 848 module_env.instance = &instance;
938 module_env.linker = &linker;
939 module_env.origin = module->origin; 849 module_env.origin = module->origin;
940 850
941 if (module->export_table.size() == 0) { 851 if (module->export_table.size() == 0) {
942 thrower.Error("WASM.compileRun() failed: no exported functions"); 852 thrower.Error("WASM.compileRun() failed: no exported functions");
943 return -2; 853 return -2;
944 } 854 }
945 855
946 // Compile all functions. 856 // Compile all functions.
947 for (const WasmFunction& func : module->functions) { 857 for (const WasmFunction& func : module->functions) {
948 // Compile the function and install it in the linker. 858 // Compile the function and install it in the linker.
949 Handle<Code> code = compiler::WasmCompilationUnit::CompileWasmFunction( 859 Handle<Code> code = compiler::WasmCompilationUnit::CompileWasmFunction(
950 &thrower, isolate, &module_env, &func); 860 &thrower, isolate, &module_env, &func);
951 if (!code.is_null()) linker.Finish(func.func_index, code); 861 if (!code.is_null()) instance.function_code[func.func_index] = code;
952 if (thrower.error()) return -1; 862 if (thrower.error()) return -1;
953 } 863 }
954 864
955 linker.Link(instance.function_table, instance.module->function_table); 865 compiler::Link(isolate, instance.function_code);
866 instance.PopulateExportTable(instance.function_code,
867 instance.module->function_table);
956 868
957 // Wrap the main code so it can be called as a JS function. 869 // Wrap the main code so it can be called as a JS function.
958 uint32_t main_index = module->export_table.back().func_index; 870 uint32_t main_index = module->export_table.back().func_index;
959 Handle<Code> main_code = instance.function_code[main_index]; 871 Handle<Code> main_code = instance.function_code[main_index];
960 Handle<String> name = isolate->factory()->NewStringFromStaticChars("main"); 872 Handle<String> name = isolate->factory()->NewStringFromStaticChars("main");
961 Handle<JSObject> module_object = Handle<JSObject>(0, isolate); 873 Handle<JSObject> module_object = Handle<JSObject>(0, isolate);
962 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper( 874 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper(
963 isolate, &module_env, name, main_code, module_object, main_index); 875 isolate, &module_env, name, main_code, module_object, main_index);
964 876
965 // Call the JS function. 877 // Call the JS function.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
997 return object->GetInternalFieldCount() == kWasmModuleInternalFieldCount && 909 return object->GetInternalFieldCount() == kWasmModuleInternalFieldCount &&
998 object->GetInternalField(kWasmModuleCodeTable)->IsFixedArray() && 910 object->GetInternalField(kWasmModuleCodeTable)->IsFixedArray() &&
999 object->GetInternalField(kWasmMemArrayBuffer)->IsJSArrayBuffer() && 911 object->GetInternalField(kWasmMemArrayBuffer)->IsJSArrayBuffer() &&
1000 (object->GetInternalField(kWasmFunctionNamesArray)->IsByteArray() || 912 (object->GetInternalField(kWasmFunctionNamesArray)->IsByteArray() ||
1001 object->GetInternalField(kWasmFunctionNamesArray)->IsUndefined()); 913 object->GetInternalField(kWasmFunctionNamesArray)->IsUndefined());
1002 } 914 }
1003 915
1004 } // namespace wasm 916 } // namespace wasm
1005 } // namespace internal 917 } // namespace internal
1006 } // namespace v8 918 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698