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 23 matching lines...) Expand all Loading... |
34 } while (false) | 34 } while (false) |
35 | 35 |
36 #define TRACE_CHAIN(instance) \ | 36 #define TRACE_CHAIN(instance) \ |
37 do { \ | 37 do { \ |
38 instance->PrintInstancesChain(); \ | 38 instance->PrintInstancesChain(); \ |
39 } while (false) | 39 } while (false) |
40 | 40 |
41 namespace { | 41 namespace { |
42 | 42 |
43 static const int kInvalidSigIndex = -1; | 43 static const int kInvalidSigIndex = -1; |
44 static const int kPlaceholderMarker = 1000000000; | |
45 | 44 |
46 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { | 45 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) { |
47 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; | 46 return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset; |
48 } | 47 } |
49 | 48 |
50 void ReplaceReferenceInCode(Handle<Code> code, Handle<Object> old_ref, | 49 void ReplaceReferenceInCode(Handle<Code> code, Handle<Object> old_ref, |
51 Handle<Object> new_ref) { | 50 Handle<Object> new_ref) { |
52 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); | 51 for (RelocIterator it(*code, 1 << RelocInfo::EMBEDDED_OBJECT); !it.done(); |
53 it.next()) { | 52 it.next()) { |
54 if (it.rinfo()->target_object() == *old_ref) { | 53 if (it.rinfo()->target_object() == *old_ref) { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 DCHECK(code_table->get(i)->IsCode()); | 140 DCHECK(code_table->get(i)->IsCode()); |
142 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); | 141 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); |
143 AllowDeferredHandleDereference embedding_raw_address; | 142 AllowDeferredHandleDereference embedding_raw_address; |
144 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; | 143 int mask = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; |
145 for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 144 for (RelocIterator it(*code, mask); !it.done(); it.next()) { |
146 it.rinfo()->update_wasm_global_reference(old_start, globals_start); | 145 it.rinfo()->update_wasm_global_reference(old_start, globals_start); |
147 } | 146 } |
148 } | 147 } |
149 } | 148 } |
150 | 149 |
151 Handle<Code> CreatePlaceholder(Factory* factory, uint32_t index, | 150 Handle<Code> CreatePlaceholder(Factory* factory, Code::Kind kind) { |
152 Code::Kind kind) { | 151 byte buffer[] = {0, 0, 0, 0}; // fake instructions. |
153 // Create a placeholder code object and encode the corresponding index in | 152 CodeDesc desc = { |
154 // the {constant_pool_offset} field of the code object. | |
155 // TODO(titzer): instead of placeholders, use a reloc_info mode. | |
156 static byte buffer[] = {0, 0, 0, 0}; // fake instructions. | |
157 static CodeDesc desc = { | |
158 buffer, arraysize(buffer), arraysize(buffer), 0, 0, nullptr, 0, nullptr}; | 153 buffer, arraysize(buffer), arraysize(buffer), 0, 0, nullptr, 0, nullptr}; |
159 Handle<Code> code = factory->NewCode(desc, Code::KindField::encode(kind), | 154 return factory->NewCode(desc, Code::KindField::encode(kind), |
160 Handle<Object>::null()); | 155 Handle<Object>::null()); |
161 code->set_constant_pool_offset(static_cast<int>(index) + kPlaceholderMarker); | |
162 return code; | |
163 } | |
164 | |
165 bool LinkFunction(Handle<Code> unlinked, | |
166 std::vector<Handle<Code>>& code_table) { | |
167 bool modified = false; | |
168 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); | |
169 AllowDeferredHandleDereference embedding_raw_address; | |
170 for (RelocIterator it(*unlinked, mode_mask); !it.done(); it.next()) { | |
171 RelocInfo::Mode mode = it.rinfo()->rmode(); | |
172 if (RelocInfo::IsCodeTarget(mode)) { | |
173 Code* target = | |
174 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | |
175 if (target->constant_pool_offset() < kPlaceholderMarker) continue; | |
176 switch (target->kind()) { | |
177 case Code::WASM_FUNCTION: // fall through | |
178 case Code::WASM_TO_JS_FUNCTION: // fall through | |
179 case Code::JS_TO_WASM_FUNCTION: { | |
180 // Patch direct calls to placeholder code objects. | |
181 uint32_t index = target->constant_pool_offset() - kPlaceholderMarker; | |
182 Handle<Code> new_target = code_table[index]; | |
183 if (target != *new_target) { | |
184 it.rinfo()->set_target_address(new_target->instruction_start(), | |
185 UPDATE_WRITE_BARRIER, | |
186 SKIP_ICACHE_FLUSH); | |
187 modified = true; | |
188 } | |
189 break; | |
190 } | |
191 default: | |
192 break; | |
193 } | |
194 } | |
195 } | |
196 return modified; | |
197 } | 156 } |
198 | 157 |
199 void FlushICache(Isolate* isolate, Handle<FixedArray> code_table) { | 158 void FlushICache(Isolate* isolate, Handle<FixedArray> code_table) { |
200 for (int i = 0; i < code_table->length(); ++i) { | 159 for (int i = 0; i < code_table->length(); ++i) { |
201 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i); | 160 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i); |
202 Assembler::FlushICache(isolate, code->instruction_start(), | 161 Assembler::FlushICache(isolate, code->instruction_start(), |
203 code->instruction_size()); | 162 code->instruction_size()); |
204 } | 163 } |
205 } | 164 } |
206 | 165 |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 PatchContext(it, context); | 502 PatchContext(it, context); |
544 continue; | 503 continue; |
545 } | 504 } |
546 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode())); | 505 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode())); |
547 Code::Kind kind = | 506 Code::Kind kind = |
548 Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind(); | 507 Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind(); |
549 if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION) | 508 if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION) |
550 continue; | 509 continue; |
551 ++num_wasm_calls; | 510 ++num_wasm_calls; |
552 Code* new_code = Code::cast(new_functions->get(exp.index)); | 511 Code* new_code = Code::cast(new_functions->get(exp.index)); |
553 DCHECK_EQ(kind, new_code->kind()); | 512 DCHECK(new_code->kind() == Code::WASM_FUNCTION || |
| 513 new_code->kind() == Code::WASM_TO_JS_FUNCTION); |
554 it.rinfo()->set_target_address(new_code->instruction_start(), | 514 it.rinfo()->set_target_address(new_code->instruction_start(), |
555 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | 515 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
556 } | 516 } |
557 DCHECK_EQ(1, num_wasm_calls); | 517 DCHECK_EQ(1, num_wasm_calls); |
558 func_index++; | 518 func_index++; |
559 } | 519 } |
560 DCHECK_EQ(new_functions->length(), func_index); | 520 DCHECK_EQ(new_functions->length(), func_index); |
561 } | 521 } |
562 | 522 |
563 static void ResetCompiledModule(Isolate* isolate, WasmInstanceObject* owner, | 523 static void ResetCompiledModule(Isolate* isolate, WasmInstanceObject* owner, |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
947 ModuleBytesEnv module_env(this, &temp_instance, wire_bytes); | 907 ModuleBytesEnv module_env(this, &temp_instance, wire_bytes); |
948 | 908 |
949 // The {code_table} array contains import wrappers and functions (which | 909 // The {code_table} array contains import wrappers and functions (which |
950 // are both included in {functions.size()}, and export wrappers. | 910 // are both included in {functions.size()}, and export wrappers. |
951 int code_table_size = | 911 int code_table_size = |
952 static_cast<int>(functions.size() + num_exported_functions); | 912 static_cast<int>(functions.size() + num_exported_functions); |
953 Handle<FixedArray> code_table = | 913 Handle<FixedArray> code_table = |
954 factory->NewFixedArray(static_cast<int>(code_table_size), TENURED); | 914 factory->NewFixedArray(static_cast<int>(code_table_size), TENURED); |
955 | 915 |
956 // Initialize the code table with placeholders. | 916 // Initialize the code table with placeholders. |
| 917 Handle<Code> code_placeholder = |
| 918 CreatePlaceholder(factory, Code::WASM_FUNCTION); |
957 for (uint32_t i = 0; i < functions.size(); ++i) { | 919 for (uint32_t i = 0; i < functions.size(); ++i) { |
958 Code::Kind kind = Code::WASM_FUNCTION; | 920 code_table->set(static_cast<int>(i), *code_placeholder); |
959 if (i < num_imported_functions) kind = Code::WASM_TO_JS_FUNCTION; | 921 temp_instance.function_code[i] = code_placeholder; |
960 Handle<Code> placeholder = CreatePlaceholder(factory, i, kind); | |
961 code_table->set(static_cast<int>(i), *placeholder); | |
962 temp_instance.function_code[i] = placeholder; | |
963 } | 922 } |
964 | 923 |
965 isolate->counters()->wasm_functions_per_module()->AddSample( | 924 isolate->counters()->wasm_functions_per_module()->AddSample( |
966 static_cast<int>(functions.size())); | 925 static_cast<int>(functions.size())); |
967 if (!FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks != 0) { | 926 if (!FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks != 0) { |
968 // Avoid a race condition by collecting results into a second vector. | 927 // Avoid a race condition by collecting results into a second vector. |
969 std::vector<Handle<Code>> results; | 928 std::vector<Handle<Code>> results; |
970 results.reserve(temp_instance.function_code.size()); | 929 results.reserve(temp_instance.function_code.size()); |
971 for (size_t i = 0; i < temp_instance.function_code.size(); ++i) { | 930 for (size_t i = 0; i < temp_instance.function_code.size(); ++i) { |
972 results.push_back(temp_instance.function_code[i]); | 931 results.push_back(temp_instance.function_code[i]); |
(...skipping 10 matching lines...) Expand all Loading... |
983 if (thrower->error()) return nothing; | 942 if (thrower->error()) return nothing; |
984 | 943 |
985 // At this point, compilation has completed. Update the code table. | 944 // At this point, compilation has completed. Update the code table. |
986 for (size_t i = FLAG_skip_compiling_wasm_funcs; | 945 for (size_t i = FLAG_skip_compiling_wasm_funcs; |
987 i < temp_instance.function_code.size(); ++i) { | 946 i < temp_instance.function_code.size(); ++i) { |
988 Code* code = *temp_instance.function_code[i]; | 947 Code* code = *temp_instance.function_code[i]; |
989 code_table->set(static_cast<int>(i), code); | 948 code_table->set(static_cast<int>(i), code); |
990 RecordStats(isolate, code); | 949 RecordStats(isolate, code); |
991 } | 950 } |
992 | 951 |
993 // Link the functions in the module. | |
994 for (size_t i = FLAG_skip_compiling_wasm_funcs; | |
995 i < temp_instance.function_code.size(); ++i) { | |
996 Handle<Code> code = temp_instance.function_code[i]; | |
997 bool modified = LinkFunction(code, temp_instance.function_code); | |
998 if (modified) { | |
999 // TODO(mtrofin): do we need to flush the cache here? | |
1000 Assembler::FlushICache(isolate, code->instruction_start(), | |
1001 code->instruction_size()); | |
1002 } | |
1003 } | |
1004 | |
1005 // Create heap objects for script, module bytes and asm.js offset table to be | 952 // Create heap objects for script, module bytes and asm.js offset table to be |
1006 // stored in the shared module data. | 953 // stored in the shared module data. |
1007 Handle<Script> script; | 954 Handle<Script> script; |
1008 Handle<ByteArray> asm_js_offset_table; | 955 Handle<ByteArray> asm_js_offset_table; |
1009 if (asm_js_script.is_null()) { | 956 if (asm_js_script.is_null()) { |
1010 script = CreateWasmScript(isolate, wire_bytes); | 957 script = CreateWasmScript(isolate, wire_bytes); |
1011 } else { | 958 } else { |
1012 script = asm_js_script; | 959 script = asm_js_script; |
1013 asm_js_offset_table = | 960 asm_js_offset_table = |
1014 isolate->factory()->NewByteArray(asm_js_offset_table_bytes.length()); | 961 isolate->factory()->NewByteArray(asm_js_offset_table_bytes.length()); |
(...skipping 1525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2540 | 2487 |
2541 JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(), | 2488 JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(), |
2542 NONE); | 2489 NONE); |
2543 JSObject::AddProperty(entry, kind_string, export_kind, NONE); | 2490 JSObject::AddProperty(entry, kind_string, export_kind, NONE); |
2544 | 2491 |
2545 storage->set(index, *entry); | 2492 storage->set(index, *entry); |
2546 } | 2493 } |
2547 | 2494 |
2548 return array_object; | 2495 return array_object; |
2549 } | 2496 } |
OLD | NEW |