OLD | NEW |
1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 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/wasm/wasm-code-specialization.h" | 5 #include "src/wasm/wasm-code-specialization.h" |
6 | 6 |
7 #include "src/assembler-inl.h" | 7 #include "src/assembler-inl.h" |
8 #include "src/objects-inl.h" | 8 #include "src/objects-inl.h" |
9 #include "src/source-position-table.h" | 9 #include "src/source-position-table.h" |
10 #include "src/wasm/decoder.h" | 10 #include "src/wasm/decoder.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 int func_index = Smi::cast(deopt_data->get(1))->value(); | 49 int func_index = Smi::cast(deopt_data->get(1))->value(); |
50 func_bytes = comp_mod->module_bytes()->GetChars() + | 50 func_bytes = comp_mod->module_bytes()->GetChars() + |
51 comp_mod->module()->functions[func_index].code_start_offset; | 51 comp_mod->module()->functions[func_index].code_start_offset; |
52 } | 52 } |
53 | 53 |
54 SourcePositionTableIterator source_pos_it; | 54 SourcePositionTableIterator source_pos_it; |
55 Decoder decoder; | 55 Decoder decoder; |
56 const byte* func_bytes; | 56 const byte* func_bytes; |
57 }; | 57 }; |
58 | 58 |
| 59 bool IsAtWasmDirectCallTarget(RelocIterator& it) { |
| 60 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode())); |
| 61 Code* code = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
| 62 return code->kind() == Code::WASM_FUNCTION || |
| 63 code->kind() == Code::WASM_TO_JS_FUNCTION || |
| 64 code->builtin_index() == Builtins::kIllegal; |
| 65 } |
| 66 |
59 } // namespace | 67 } // namespace |
60 | 68 |
61 CodeSpecialization::CodeSpecialization(Isolate* isolate, Zone* zone) | 69 CodeSpecialization::CodeSpecialization(Isolate* isolate, Zone* zone) |
62 : objects_to_relocate(isolate->heap(), ZoneAllocationPolicy(zone)) {} | 70 : objects_to_relocate(isolate->heap(), ZoneAllocationPolicy(zone)) {} |
63 | 71 |
64 CodeSpecialization::~CodeSpecialization() {} | 72 CodeSpecialization::~CodeSpecialization() {} |
65 | 73 |
66 void CodeSpecialization::RelocateMemoryReferences(Address old_start, | 74 void CodeSpecialization::RelocateMemoryReferences(Address old_start, |
67 uint32_t old_size, | 75 uint32_t old_size, |
68 Address new_start, | 76 Address new_start, |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 Code* wasm_function = Code::cast(code_table->get(func_index)); | 132 Code* wasm_function = Code::cast(code_table->get(func_index)); |
125 changed |= ApplyToWasmCode(wasm_function, icache_flush_mode); | 133 changed |= ApplyToWasmCode(wasm_function, icache_flush_mode); |
126 } | 134 } |
127 | 135 |
128 // Patch all exported functions. | 136 // Patch all exported functions. |
129 for (auto exp : module->export_table) { | 137 for (auto exp : module->export_table) { |
130 if (exp.kind != kExternalFunction) continue; | 138 if (exp.kind != kExternalFunction) continue; |
131 Code* export_wrapper = Code::cast(code_table->get(func_index)); | 139 Code* export_wrapper = Code::cast(code_table->get(func_index)); |
132 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind()); | 140 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind()); |
133 // There must be exactly one call to WASM_FUNCTION or WASM_TO_JS_FUNCTION. | 141 // There must be exactly one call to WASM_FUNCTION or WASM_TO_JS_FUNCTION. |
134 int num_wasm_calls = 0; | |
135 for (RelocIterator it(export_wrapper, | 142 for (RelocIterator it(export_wrapper, |
136 RelocInfo::ModeMask(RelocInfo::CODE_TARGET)); | 143 RelocInfo::ModeMask(RelocInfo::CODE_TARGET)); |
137 !it.done(); it.next()) { | 144 ; it.next()) { |
138 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode())); | 145 DCHECK(!it.done()); |
139 Code* code = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | |
140 // Ignore calls to other builtins like ToNumber. | 146 // Ignore calls to other builtins like ToNumber. |
141 if (code->kind() != Code::WASM_FUNCTION && | 147 if (!IsAtWasmDirectCallTarget(it)) continue; |
142 code->kind() != Code::WASM_TO_JS_FUNCTION && | |
143 code->builtin_index() != Builtins::kIllegal) | |
144 continue; | |
145 ++num_wasm_calls; | |
146 Code* new_code = Code::cast(code_table->get(exp.index)); | 148 Code* new_code = Code::cast(code_table->get(exp.index)); |
147 DCHECK(new_code->kind() == Code::WASM_FUNCTION || | 149 DCHECK(new_code->kind() == Code::WASM_FUNCTION || |
148 new_code->kind() == Code::WASM_TO_JS_FUNCTION); | 150 new_code->kind() == Code::WASM_TO_JS_FUNCTION); |
149 it.rinfo()->set_target_address(new_code->instruction_start(), | 151 it.rinfo()->set_target_address(new_code->instruction_start(), |
150 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); | 152 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
151 changed = true; | 153 break; |
152 } | 154 } |
153 DCHECK_EQ(1, num_wasm_calls); | 155 changed = true; |
154 func_index++; | 156 func_index++; |
155 } | 157 } |
156 DCHECK_EQ(code_table->length(), func_index); | 158 DCHECK_EQ(code_table->length(), func_index); |
157 return changed; | 159 return changed; |
158 } | 160 } |
159 | 161 |
160 bool CodeSpecialization::ApplyToWasmCode(Code* code, | 162 bool CodeSpecialization::ApplyToWasmCode(Code* code, |
161 ICacheFlushMode icache_flush_mode) { | 163 ICacheFlushMode icache_flush_mode) { |
162 DisallowHeapAllocation no_gc; | 164 DisallowHeapAllocation no_gc; |
163 DCHECK_EQ(Code::WASM_FUNCTION, code->kind()); | 165 DCHECK_EQ(Code::WASM_FUNCTION, code->kind()); |
(...skipping 30 matching lines...) Expand all Loading... |
194 changed = true; | 196 changed = true; |
195 break; | 197 break; |
196 case RelocInfo::WASM_GLOBAL_REFERENCE: | 198 case RelocInfo::WASM_GLOBAL_REFERENCE: |
197 DCHECK(reloc_globals); | 199 DCHECK(reloc_globals); |
198 it.rinfo()->update_wasm_global_reference( | 200 it.rinfo()->update_wasm_global_reference( |
199 old_globals_start, new_globals_start, icache_flush_mode); | 201 old_globals_start, new_globals_start, icache_flush_mode); |
200 changed = true; | 202 changed = true; |
201 break; | 203 break; |
202 case RelocInfo::CODE_TARGET: { | 204 case RelocInfo::CODE_TARGET: { |
203 DCHECK(reloc_direct_calls); | 205 DCHECK(reloc_direct_calls); |
204 Code* old_code = | |
205 Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); | |
206 // Skip everything which is not a wasm call (stack checks, traps, ...). | 206 // Skip everything which is not a wasm call (stack checks, traps, ...). |
207 if (old_code->kind() != Code::WASM_FUNCTION && | 207 if (!IsAtWasmDirectCallTarget(it)) continue; |
208 old_code->kind() != Code::WASM_TO_JS_FUNCTION && | |
209 old_code->builtin_index() != Builtins::kIllegal) | |
210 continue; | |
211 // Iterate simultaneously over the relocation information and the source | 208 // Iterate simultaneously over the relocation information and the source |
212 // position table. For each call in the reloc info, move the source | 209 // position table. For each call in the reloc info, move the source |
213 // position iterator forward to that position to find the byte offset of | 210 // position iterator forward to that position to find the byte offset of |
214 // the respective call. Then extract the call index from the module wire | 211 // the respective call. Then extract the call index from the module wire |
215 // bytes to find the new compiled function. | 212 // bytes to find the new compiled function. |
216 size_t offset = it.rinfo()->pc() - code->instruction_start(); | 213 size_t offset = it.rinfo()->pc() - code->instruction_start(); |
217 if (!patch_direct_calls_helper) { | 214 if (!patch_direct_calls_helper) { |
218 patch_direct_calls_helper.reset(new PatchDirectCallsHelper( | 215 patch_direct_calls_helper.reset(new PatchDirectCallsHelper( |
219 *relocate_direct_calls_instance, code)); | 216 *relocate_direct_calls_instance, code)); |
220 } | 217 } |
(...skipping 27 matching lines...) Expand all Loading... |
248 icache_flush_mode); | 245 icache_flush_mode); |
249 changed = true; | 246 changed = true; |
250 break; | 247 break; |
251 default: | 248 default: |
252 UNREACHABLE(); | 249 UNREACHABLE(); |
253 } | 250 } |
254 } | 251 } |
255 | 252 |
256 return changed; | 253 return changed; |
257 } | 254 } |
OLD | NEW |