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

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

Issue 2624383003: [wasm] Skip whole function linking phase (Closed)
Patch Set: Remove unused variable Created 3 years, 11 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 | « no previous file | 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 23 matching lines...) Expand all
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698