| 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 |