Commit 406f4ffa authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Fix serialization of {WasmCode} with jump tables.

This correctly serializes {RelocInfo::INTERNAL_REFERENCE} addresses in a
position-independent form, so that they can be properly relocated when
the code is deserialized again. We store the offset within the code in
the serialized stream.

R=clemensh@chromium.org
TEST=mjsunit/wasm/compiled-module-serialization
BUG=chromium:857049

Change-Id: Ie8c84ee67bdfc17a65faa159a21cc1f2a78ac924
Reviewed-on: https://chromium-review.googlesource.com/1122414Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54140}
parent 110f78f0
......@@ -315,7 +315,9 @@ void NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) {
// Relocate the code.
int mask = RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE);
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
RelocIterator orig_iter(code->instructions(), code->reloc_info(),
code->constant_pool(), mask);
for (RelocIterator iter(
......@@ -345,6 +347,13 @@ void NativeModuleSerializer::WriteCode(const WasmCode* code, Writer* writer) {
uint32_t tag = ref_iter->second;
SetWasmCalleeTag(iter.rinfo(), tag);
} break;
case RelocInfo::INTERNAL_REFERENCE:
case RelocInfo::INTERNAL_REFERENCE_ENCODED: {
Address orig_target = orig_iter.rinfo()->target_internal_reference();
Address offset = orig_target - code->instruction_start();
Assembler::deserialization_set_target_internal_reference_at(
iter.rinfo()->pc(), offset, mode);
} break;
default:
UNREACHABLE();
}
......@@ -463,7 +472,9 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) {
// Relocate the code.
int mask = RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE);
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
for (RelocIterator iter(code->instructions(), code->reloc_info(),
code->constant_pool(), mask);
!iter.done(); iter.next()) {
......@@ -492,6 +503,14 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) {
iter.rinfo()->set_target_external_reference(address, SKIP_ICACHE_FLUSH);
break;
}
case RelocInfo::INTERNAL_REFERENCE:
case RelocInfo::INTERNAL_REFERENCE_ENCODED: {
Address offset = iter.rinfo()->target_internal_reference();
Address target = code->instruction_start() + offset;
Assembler::deserialization_set_target_internal_reference_at(
iter.rinfo()->pc(), target, mode);
break;
}
default:
UNREACHABLE();
}
......
......@@ -352,3 +352,55 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
assertEquals(65, instance.exports.main());
})();
(function BranchTableAfterSerialization() {
print(arguments.callee.name);
const builder = new WasmModuleBuilder();
builder.addFunction('main', kSig_i_i)
.addBody([kExprBlock, kWasmStmt,
kExprBlock, kWasmStmt,
kExprBlock, kWasmStmt,
kExprBlock, kWasmStmt,
kExprBlock, kWasmStmt,
kExprBlock, kWasmStmt,
kExprBlock, kWasmStmt,
kExprGetLocal, 0,
kExprBrTable, 6, 0, 1, 2, 3, 4, 5, 6,
kExprEnd,
kExprI32Const, 3,
kExprReturn,
kExprEnd,
kExprI32Const, 7,
kExprReturn,
kExprEnd,
kExprI32Const, 9,
kExprReturn,
kExprEnd,
kExprI32Const, 11,
kExprReturn,
kExprEnd,
kExprI32Const, 23,
kExprReturn,
kExprEnd,
kExprI32Const, 35,
kExprReturn,
kExprEnd,
kExprI32Const, 42,
kExprReturn])
.exportFunc();
var wire_bytes = builder.toBuffer();
var module = new WebAssembly.Module(wire_bytes);
var buffer = %SerializeWasmModule(module);
module = %DeserializeWasmModule(buffer, wire_bytes);
var instance = new WebAssembly.Instance(module);
assertEquals(3, instance.exports.main(0));
assertEquals(7, instance.exports.main(1));
assertEquals(9, instance.exports.main(2));
assertEquals(11, instance.exports.main(3));
assertEquals(23, instance.exports.main(4));
assertEquals(35, instance.exports.main(5));
assertEquals(42, instance.exports.main(6));
assertEquals(42, instance.exports.main(9));
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment