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

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
« no previous file with comments | « src/wasm/wasm-module.h ('k') | src/x64/assembler-x64.h » ('j') | 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 "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.
747 //-------------------------------------------------------------------------
748 if (!CompileWrappersToImportedFunctions(isolate, this, ffi, &instance,
749 &thrower, factory, &module_env,
750 code_stats)) {
751 return MaybeHandle<JSObject>();
752 }
753 //-------------------------------------------------------------------------
754 // Compile all functions in the module. 650 // Compile all functions in the module.
755 //------------------------------------------------------------------------- 651 //-------------------------------------------------------------------------
756 { 652 {
757 isolate->counters()->wasm_functions_per_module()->AddSample( 653 isolate->counters()->wasm_functions_per_module()->AddSample(
758 static_cast<int>(functions.size())); 654 static_cast<int>(functions.size()));
759 if (FLAG_wasm_num_compilation_tasks != 0) { 655 if (FLAG_wasm_num_compilation_tasks != 0) {
760 CompileInParallel(isolate, this, instance.function_code, &thrower, 656 CompileInParallel(isolate, this, instance.function_code, &thrower,
761 &module_env); 657 &module_env);
762 } else { 658 } else {
763 // 5) The main thread finishes the compilation. 659 // 5) The main thread finishes the compilation.
764 CompileSequentially(isolate, this, instance.function_code, &thrower, 660 CompileSequentially(isolate, this, instance.function_code, &thrower,
765 &module_env); 661 &module_env);
766 } 662 }
767 if (thrower.error()) { 663 if (thrower.error()) {
768 return Handle<JSObject>::null(); 664 return Handle<JSObject>::null();
769 } 665 }
770 666
771 // At this point, compilation has completed. Update the code table 667 // At this point, compilation has completed. Update the code table
772 // and record sizes. 668 // and record sizes.
773 for (size_t i = FLAG_skip_compiling_wasm_funcs; 669 for (size_t i = FLAG_skip_compiling_wasm_funcs;
774 i < instance.function_code.size(); ++i) { 670 i < instance.function_code.size(); ++i) {
775 Code* code = *instance.function_code[i]; 671 Code* code = *instance.function_code[i];
776 code_table->set(static_cast<int>(i), code); 672 code_table->set(static_cast<int>(i), code);
777 code_stats.Record(code); 673 code_stats.Record(code);
778 } 674 }
779 675
780 // Patch all direct call sites. 676 // Patch all direct call sites.
781 linker.Link(instance.function_table, this->function_table); 677 compiler::Link(isolate, instance.function_code, instance.function_code,
678 RelocInfo::kWasmDirectCallMask);
679 //-------------------------------------------------------------------------
680 // Compile wrappers to imported functions.
681 //-------------------------------------------------------------------------
682 if (!CompileWrappersToImportedFunctions(isolate, this, ffi, &instance,
683 &thrower, factory, &module_env,
684 code_stats)) {
685 return MaybeHandle<JSObject>();
686 }
687
688 compiler::Link(isolate, instance.function_code, instance.import_code,
689 RelocInfo::kWasmImportCallMask);
690
691 instance.PopulateExportTable(instance.function_code, function_table);
692
782 instance.js_object->SetInternalField(kWasmModuleFunctionTable, 693 instance.js_object->SetInternalField(kWasmModuleFunctionTable,
783 Smi::FromInt(0)); 694 Smi::FromInt(0));
784 695
785 SetDeoptimizationData(factory, instance.js_object, instance.function_code); 696 SetDeoptimizationData(factory, instance.js_object, instance.function_code);
786 697
787 //------------------------------------------------------------------------- 698 //-------------------------------------------------------------------------
788 // Create and populate the exports object. 699 // Create and populate the exports object.
789 //------------------------------------------------------------------------- 700 //-------------------------------------------------------------------------
790 if (export_table.size() > 0 || mem_export) { 701 if (export_table.size() > 0 || mem_export) {
791 Handle<JSObject> exports_object; 702 Handle<JSObject> exports_object;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 MaybeHandle<Object> retval = 769 MaybeHandle<Object> retval =
859 Execution::Call(isolate, jsfunc, undefined, 0, nullptr); 770 Execution::Call(isolate, jsfunc, undefined, 0, nullptr);
860 771
861 if (retval.is_null()) { 772 if (retval.is_null()) {
862 thrower.Error("WASM.instantiateModule(): start function failed"); 773 thrower.Error("WASM.instantiateModule(): start function failed");
863 } 774 }
864 } 775 }
865 return instance.js_object; 776 return instance.js_object;
866 } 777 }
867 778
868 Handle<Code> ModuleEnv::GetCodeOrPlaceholder(uint32_t index) const { 779 void WasmModuleInstance::PopulateExportTable(
869 DCHECK(IsValidFunction(index)); 780 const std::vector<Handle<Code>>& compiled_functions,
870 if (linker != nullptr) return linker->GetPlaceholderCode(index); 781 const std::vector<uint16_t>& functions) {
871 DCHECK_NOT_NULL(instance); 782 if (!function_table.is_null()) {
872 return instance->function_code[index]; 783 int table_size = static_cast<int>(functions.size());
873 } 784 DCHECK_EQ(function_table->length(), table_size * 2);
874 785 for (int i = 0; i < table_size; i++) {
875 Handle<Code> ModuleEnv::GetImportCode(uint32_t index) { 786 function_table->set(i + table_size, *(compiled_functions[functions[i]]));
876 DCHECK(IsValidImport(index)); 787 }
877 return instance ? instance->import_code[index] : Handle<Code>::null(); 788 }
878 }
879
880 compiler::CallDescriptor* ModuleEnv::GetCallDescriptor(Zone* zone,
881 uint32_t index) {
882 DCHECK(IsValidFunction(index));
883 // Always make a direct call to whatever is in the table at that location.
884 // A wrapper will be generated for FFI calls.
885 const WasmFunction* function = &module->functions[index];
886 return GetWasmCallDescriptor(zone, function->sig);
887 } 789 }
888 790
889 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start, 791 int32_t CompileAndRunWasmModule(Isolate* isolate, const byte* module_start,
890 const byte* module_end, bool asm_js) { 792 const byte* module_end, bool asm_js) {
891 HandleScope scope(isolate); 793 HandleScope scope(isolate);
892 Zone zone(isolate->allocator()); 794 Zone zone(isolate->allocator());
893 // Decode the module, but don't verify function bodies, since we'll 795 // Decode the module, but don't verify function bodies, since we'll
894 // be compiling them anyway. 796 // be compiling them anyway.
895 ModuleResult result = 797 ModuleResult result =
896 DecodeWasmModule(isolate, &zone, module_start, module_end, false, 798 DecodeWasmModule(isolate, &zone, module_start, module_end, false,
(...skipping 27 matching lines...) Expand all
924 826
925 // Allocate the globals area if necessary. 827 // Allocate the globals area if necessary.
926 if (!AllocateGlobals(&thrower, isolate, &instance)) { 828 if (!AllocateGlobals(&thrower, isolate, &instance)) {
927 return -1; 829 return -1;
928 } 830 }
929 831
930 // Build the function table. 832 // Build the function table.
931 instance.function_table = BuildFunctionTable(isolate, module); 833 instance.function_table = BuildFunctionTable(isolate, module);
932 834
933 // Create module environment. 835 // Create module environment.
934 WasmLinker linker(isolate, &instance.function_code);
935 ModuleEnv module_env; 836 ModuleEnv module_env;
936 module_env.module = module; 837 module_env.module = module;
937 module_env.instance = &instance; 838 module_env.instance = &instance;
938 module_env.linker = &linker;
939 module_env.origin = module->origin; 839 module_env.origin = module->origin;
940 840
941 if (module->export_table.size() == 0) { 841 if (module->export_table.size() == 0) {
942 thrower.Error("WASM.compileRun() failed: no exported functions"); 842 thrower.Error("WASM.compileRun() failed: no exported functions");
943 return -2; 843 return -2;
944 } 844 }
945 845
946 // Compile all functions. 846 // Compile all functions.
947 for (const WasmFunction& func : module->functions) { 847 for (const WasmFunction& func : module->functions) {
948 // Compile the function and install it in the linker. 848 // Compile the function and install it in the linker.
949 Handle<Code> code = compiler::WasmCompilationUnit::CompileWasmFunction( 849 Handle<Code> code = compiler::WasmCompilationUnit::CompileWasmFunction(
950 &thrower, isolate, &module_env, &func); 850 &thrower, isolate, &module_env, &func);
951 if (!code.is_null()) linker.Finish(func.func_index, code); 851 if (!code.is_null()) instance.function_code[func.func_index] = code;
952 if (thrower.error()) return -1; 852 if (thrower.error()) return -1;
953 } 853 }
954 854
955 linker.Link(instance.function_table, instance.module->function_table); 855 compiler::Link(isolate, instance.function_code, instance.function_code,
856 RelocInfo::kWasmDirectCallMask);
857 instance.PopulateExportTable(instance.function_code,
858 instance.module->function_table);
956 859
957 // Wrap the main code so it can be called as a JS function. 860 // Wrap the main code so it can be called as a JS function.
958 uint32_t main_index = module->export_table.back().func_index; 861 uint32_t main_index = module->export_table.back().func_index;
959 Handle<Code> main_code = instance.function_code[main_index]; 862 Handle<Code> main_code = instance.function_code[main_index];
960 Handle<String> name = isolate->factory()->NewStringFromStaticChars("main"); 863 Handle<String> name = isolate->factory()->NewStringFromStaticChars("main");
961 Handle<JSObject> module_object = Handle<JSObject>(0, isolate); 864 Handle<JSObject> module_object = Handle<JSObject>(0, isolate);
962 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper( 865 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper(
963 isolate, &module_env, name, main_code, module_object, main_index); 866 isolate, &module_env, name, main_code, module_object, main_index);
964 867
965 // Call the JS function. 868 // Call the JS function.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
997 return object->GetInternalFieldCount() == kWasmModuleInternalFieldCount && 900 return object->GetInternalFieldCount() == kWasmModuleInternalFieldCount &&
998 object->GetInternalField(kWasmModuleCodeTable)->IsFixedArray() && 901 object->GetInternalField(kWasmModuleCodeTable)->IsFixedArray() &&
999 object->GetInternalField(kWasmMemArrayBuffer)->IsJSArrayBuffer() && 902 object->GetInternalField(kWasmMemArrayBuffer)->IsJSArrayBuffer() &&
1000 (object->GetInternalField(kWasmFunctionNamesArray)->IsByteArray() || 903 (object->GetInternalField(kWasmFunctionNamesArray)->IsByteArray() ||
1001 object->GetInternalField(kWasmFunctionNamesArray)->IsUndefined()); 904 object->GetInternalField(kWasmFunctionNamesArray)->IsUndefined());
1002 } 905 }
1003 906
1004 } // namespace wasm 907 } // namespace wasm
1005 } // namespace internal 908 } // namespace internal
1006 } // namespace v8 909 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/wasm-module.h ('k') | src/x64/assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698