Commit fae8a588 authored by Ben Smith's avatar Ben Smith Committed by Commit Bot

[wasm] Reloc external refs when deserializing

This is a follow-up to https://chromium-review.googlesource.com/981687.

When a wasm function has a large stack frame, the x64 code generator
performs the stack overflow check before constructing the frame. This
requires the use of the `address_of_real_stack_limit` external
reference.

This reference is thread local, so if it is not relocated the stack
overflow check will always fail.

Bug: chromium:808848
Change-Id: I0edf3fe5a006242fc50d0bff44cd9dd0e7d85bd9
Reviewed-on: https://chromium-review.googlesource.com/982906
Commit-Queue: Ben Smith <binji@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52330}
parent 229ce29a
......@@ -126,6 +126,12 @@ Address RelocInfo::target_external_reference() {
return Assembler::target_address_at(pc_, constant_pool_);
}
void RelocInfo::set_target_external_reference(
Address target, ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
Assembler::set_target_address_at(pc_, constant_pool_, target,
icache_flush_mode);
}
Address RelocInfo::target_internal_reference() {
DCHECK(rmode_ == INTERNAL_REFERENCE);
......
......@@ -656,6 +656,12 @@ Address RelocInfo::target_external_reference() {
return Assembler::target_address_at(pc_, constant_pool_);
}
void RelocInfo::set_target_external_reference(
Address target, ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
Assembler::set_target_address_at(pc_, constant_pool_, target,
icache_flush_mode);
}
Address RelocInfo::target_internal_reference() {
DCHECK(rmode_ == INTERNAL_REFERENCE);
......
......@@ -549,6 +549,8 @@ class RelocInfo {
INLINE(void set_target_cell(
Cell* cell, WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
INLINE(void set_target_external_reference(
Address, ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
// Returns the address of the constant pool entry where the target address
// is held. This should only be called if IsInConstantPool returns true.
......
......@@ -118,6 +118,14 @@ Address RelocInfo::target_external_reference() {
return Memory::Address_at(pc_);
}
void RelocInfo::set_target_external_reference(
Address target, ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
Memory::Address_at(pc_) = target;
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
Assembler::FlushICache(pc_, sizeof(Address));
}
}
Address RelocInfo::target_internal_reference() {
DCHECK(rmode_ == INTERNAL_REFERENCE);
......
......@@ -213,6 +213,12 @@ Address RelocInfo::target_external_reference() {
return Assembler::target_address_at(pc_, constant_pool_);
}
void RelocInfo::set_target_external_reference(
Address target, ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
Assembler::set_target_address_at(pc_, constant_pool_, target,
icache_flush_mode);
}
Address RelocInfo::target_internal_reference() {
if (rmode_ == INTERNAL_REFERENCE) {
......
......@@ -185,6 +185,12 @@ Address RelocInfo::target_external_reference() {
return Assembler::target_address_at(pc_, constant_pool_);
}
void RelocInfo::set_target_external_reference(
Address target, ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
Assembler::set_target_address_at(pc_, constant_pool_, target,
icache_flush_mode);
}
Address RelocInfo::target_internal_reference() {
if (rmode_ == INTERNAL_REFERENCE) {
......
......@@ -193,6 +193,12 @@ Address RelocInfo::target_external_reference() {
return Assembler::target_address_at(pc_, constant_pool_);
}
void RelocInfo::set_target_external_reference(
Address target, ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
Assembler::set_target_address_at(pc_, constant_pool_, target,
icache_flush_mode);
}
Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_));
......
......@@ -175,6 +175,13 @@ Address RelocInfo::target_external_reference() {
return Assembler::target_address_at(pc_, constant_pool_);
}
void RelocInfo::set_target_external_reference(
Address target, ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
Assembler::set_target_address_at(pc_, constant_pool_, target,
icache_flush_mode);
}
Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_));
return target_address();
......
......@@ -130,8 +130,12 @@ void SetWasmCalleeTag(RelocInfo* rinfo, uint32_t tag) {
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
*(reinterpret_cast<uint32_t*>(rinfo->target_address_address())) = tag;
#else
rinfo->set_target_address(reinterpret_cast<Address>(tag), SKIP_WRITE_BARRIER,
SKIP_ICACHE_FLUSH);
Address addr = reinterpret_cast<Address>(tag);
if (rinfo->rmode() == RelocInfo::EXTERNAL_REFERENCE) {
rinfo->set_target_external_reference(addr, SKIP_ICACHE_FLUSH);
} else {
rinfo->set_target_address(addr, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
}
#endif
}
......@@ -139,8 +143,10 @@ uint32_t GetWasmCalleeTag(RelocInfo* rinfo) {
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32
return *(reinterpret_cast<uint32_t*>(rinfo->target_address_address()));
#else
return static_cast<uint32_t>(
reinterpret_cast<size_t>(rinfo->target_address()));
Address addr = rinfo->rmode() == RelocInfo::EXTERNAL_REFERENCE
? rinfo->target_external_reference()
: rinfo->target_address();
return static_cast<uint32_t>(reinterpret_cast<size_t>(addr));
#endif
}
......@@ -365,7 +371,8 @@ void NativeModuleSerializer::BufferCodeInAllocatedScratch(
// now relocate the code
int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE);
RelocIterator orig_iter(code->instructions(), code->reloc_info(),
code->constant_pool(), mask);
for (RelocIterator
......@@ -387,7 +394,16 @@ void NativeModuleSerializer::BufferCodeInAllocatedScratch(
} break;
case RelocInfo::RUNTIME_ENTRY: {
Address orig_target = orig_iter.rinfo()->target_address();
uint32_t tag = reference_table_lookup_[orig_target];
auto ref_iter = reference_table_lookup_.find(orig_target);
DCHECK(ref_iter != reference_table_lookup_.end());
uint32_t tag = ref_iter->second;
SetWasmCalleeTag(iter.rinfo(), tag);
} break;
case RelocInfo::EXTERNAL_REFERENCE: {
Address orig_target = orig_iter.rinfo()->target_external_reference();
auto ref_iter = reference_table_lookup_.find(orig_target);
DCHECK(ref_iter != reference_table_lookup_.end());
uint32_t tag = ref_iter->second;
SetWasmCalleeTag(iter.rinfo(), tag);
} break;
default:
......@@ -565,7 +581,8 @@ bool NativeModuleDeserializer::ReadCode() {
// now relocate the code
int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE);
for (RelocIterator iter(ret->instructions(), ret->reloc_info(),
ret->constant_pool(), mask);
!iter.done(); iter.next()) {
......@@ -592,8 +609,15 @@ bool NativeModuleDeserializer::ReadCode() {
SKIP_ICACHE_FLUSH);
break;
}
default:
case RelocInfo::EXTERNAL_REFERENCE: {
uint32_t tag = GetWasmCalleeTag(iter.rinfo());
Address address =
isolate_->heap()->external_reference_table()->address(tag);
iter.rinfo()->set_target_external_reference(address, SKIP_ICACHE_FLUSH);
break;
}
default:
UNREACHABLE();
}
}
// Flush the i-cache here instead of in AddOwnedCode, to include the changes
......
......@@ -342,6 +342,14 @@ Address RelocInfo::target_external_reference() {
return Memory::Address_at(pc_);
}
void RelocInfo::set_target_external_reference(
Address target, ICacheFlushMode icache_flush_mode) {
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
Memory::Address_at(pc_) = target;
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
Assembler::FlushICache(pc_, sizeof(Address));
}
}
Address RelocInfo::target_internal_reference() {
DCHECK(rmode_ == INTERNAL_REFERENCE);
......
......@@ -53,15 +53,11 @@ let workerScript =
`onmessage = function(msg) {
let {serialized_m1, m1_bytes} = msg;
try {
let m1_clone = %DeserializeWasmModule(serialized_m1, m1_bytes);
let imports = {mod: {get: () => 3, call: () => {}}};
let i2 = new WebAssembly.Instance(m1_clone, imports);
i2.exports.main();
postMessage('done');
} catch(e) {
postMessage('done w/ exception');
}
let m1_clone = %DeserializeWasmModule(serialized_m1, m1_bytes);
let imports = {mod: {get: () => 3, call: () => {}}};
let i2 = new WebAssembly.Instance(m1_clone, imports);
i2.exports.main();
postMessage('done');
}`;
let worker = new Worker(workerScript);
......
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