Chromium Code Reviews| Index: src/wasm/wasm-module.cc |
| diff --git a/src/wasm/wasm-module.cc b/src/wasm/wasm-module.cc |
| index 57e3c60752cfb41b658376ef0849fc3175d96987..6b6019478461f4df6ebc17cb562899c885d893e6 100644 |
| --- a/src/wasm/wasm-module.cc |
| +++ b/src/wasm/wasm-module.cc |
| @@ -445,36 +445,86 @@ void CompileSequentially(Isolate* isolate, ModuleBytesEnv* module_env, |
| } |
| } |
| -void PatchDirectCalls(Handle<FixedArray> old_functions, |
| - Handle<FixedArray> new_functions, int start) { |
| - DCHECK_EQ(new_functions->length(), old_functions->length()); |
| +int ExtractDirectCallIndex(wasm::Decoder& decoder, const byte* pc) { |
| + DCHECK_EQ(static_cast<int>(kExprCallFunction), static_cast<int>(*pc)); |
| + decoder.Reset(pc + 1, pc + 6); |
| + uint32_t call_idx = decoder.consume_u32v("call index"); |
| + DCHECK(decoder.ok()); |
| + DCHECK_GE(kMaxInt, call_idx); |
| + return static_cast<int>(call_idx); |
| +} |
| +void PatchDirectCalls(Handle<FixedArray> new_functions, |
| + Handle<WasmCompiledModule> compiled_module, |
| + WasmModule* module, int start) { |
| DisallowHeapAllocation no_gc; |
| - std::map<Code*, Code*> old_to_new_code; |
| - for (int i = 0; i < new_functions->length(); ++i) { |
| - old_to_new_code.insert(std::make_pair(Code::cast(old_functions->get(i)), |
| - Code::cast(new_functions->get(i)))); |
| - } |
| - int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET); |
| AllowDeferredHandleDereference embedding_raw_address; |
| - for (int i = start; i < new_functions->length(); ++i) { |
| + SeqOneByteString* module_bytes = compiled_module->module_bytes(); |
| + std::vector<WasmFunction>* wasm_functions = |
| + &compiled_module->module()->functions; |
| + DCHECK_EQ(wasm_functions->size() + |
| + compiled_module->module()->num_exported_functions, |
| + new_functions->length()); |
| + DCHECK_EQ(start, compiled_module->module()->num_imported_functions); |
| + |
| + // Allocate decoder outside of the loop and reuse it to decode all function |
| + // indexes. |
| + wasm::Decoder decoder(nullptr, nullptr); |
| + int num_wasm_functions = static_cast<int>(wasm_functions->size()); |
| + for (int i = start; i < num_wasm_functions; ++i) { |
|
titzer
2017/01/11 18:34:04
Can you add a comment here about what we are doing
Clemens Hammacher
2017/01/12 09:03:12
Done.
|
| Code* wasm_function = Code::cast(new_functions->get(i)); |
| - for (RelocIterator it(wasm_function, mode_mask); !it.done(); it.next()) { |
| - Code* old_code = |
| - Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); |
| - if (old_code->kind() == Code::WASM_TO_JS_FUNCTION || |
| - old_code->kind() == Code::WASM_FUNCTION) { |
| - auto found = old_to_new_code.find(old_code); |
| - DCHECK(found != old_to_new_code.end()); |
| - Code* new_code = found->second; |
| - if (new_code != old_code) { |
| - it.rinfo()->set_target_address(new_code->instruction_start(), |
| - UPDATE_WRITE_BARRIER, |
| - SKIP_ICACHE_FLUSH); |
| - } |
| - } |
| + DCHECK(wasm_function->kind() == Code::WASM_FUNCTION); |
| + SourcePositionTableIterator source_pos_iterator( |
| + wasm_function->source_position_table()); |
| + const byte* func_bytes = |
| + module_bytes->GetChars() + |
| + compiled_module->module()->functions[i].code_start_offset; |
| + for (RelocIterator it(wasm_function, RelocInfo::kCodeTargetMask); |
| + !it.done(); it.next()) { |
| + Code::Kind kind = |
| + Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind(); |
| + if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION) |
| + continue; |
| + size_t offset_l = it.rinfo()->pc() - wasm_function->instruction_start(); |
| + DCHECK_GE(kMaxInt, offset_l); |
| + int offset = static_cast<int>(offset_l); |
| + DCHECK(!source_pos_iterator.done()); |
| + int byte_pos; |
| + do { |
| + byte_pos = source_pos_iterator.source_position().ScriptOffset(); |
| + source_pos_iterator.Advance(); |
| + } while (!source_pos_iterator.done() && |
| + source_pos_iterator.code_offset() <= offset); |
| + int called_func_index = |
| + ExtractDirectCallIndex(decoder, func_bytes + byte_pos); |
| + Code* new_code = Code::cast(new_functions->get(called_func_index)); |
| + it.rinfo()->set_target_address(new_code->instruction_start(), |
| + UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
| } |
| } |
| + int func_index = num_wasm_functions; |
| + for (auto exp : module->export_table) { |
| + if (exp.kind != kExternalFunction) continue; |
| + Code* export_wrapper = Code::cast(new_functions->get(func_index)); |
| + DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind()); |
| + // There must be exactly one call to WASM_FUNCTION or WASM_TO_JS_FUNCTION. |
| + int num_wasm_calls = 0; |
| + for (RelocIterator it(export_wrapper, RelocInfo::kCodeTargetMask); |
| + !it.done(); it.next()) { |
| + Code::Kind kind = |
| + Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind(); |
| + if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION) |
| + continue; |
| + ++num_wasm_calls; |
| + Code* new_code = Code::cast(new_functions->get(exp.index)); |
| + DCHECK_EQ(kind, new_code->kind()); |
| + it.rinfo()->set_target_address(new_code->instruction_start(), |
| + UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); |
| + } |
| + DCHECK_EQ(1, num_wasm_calls); |
| + func_index++; |
| + } |
| + DCHECK_EQ(new_functions->length(), func_index); |
| } |
| static void ResetCompiledModule(Isolate* isolate, WasmInstanceObject* owner, |
| @@ -1305,7 +1355,8 @@ class WasmInstanceBuilder { |
| if (num_imported_functions > 0 || !owner.is_null()) { |
| // If the code was cloned, or new imports were compiled, patch. |
| - PatchDirectCalls(old_code_table, code_table, num_imported_functions); |
| + PatchDirectCalls(code_table, compiled_module_, module_, |
| + num_imported_functions); |
| } |
| FlushICache(isolate_, code_table); |