Bug 1507820: Pin HeapReg in Cranelift and use it as the heap base; r=lth

Differential Revision: https://phabricator.services.mozilla.com/D45017

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Benjamin Bouvier 2019-09-11 15:58:09 +00:00
parent 1e8eaa6511
commit c811b52449
5 changed files with 51 additions and 33 deletions

View File

@ -96,13 +96,6 @@ static bool GenerateCraneliftCode(WasmMacroAssembler& masm,
uint32_t codeEnd = masm.currentOffset();
#endif
// Cranelift isn't aware of pinned registers in general, so we need to reload
// both TLS and pinned regs from the stack.
// TODO(bug 1507820): We should teach Cranelift to reload this register
// itself, so we don't have to do it manually.
masm.loadWasmTlsRegFromFrame();
masm.loadWasmPinnedRegsFromTls();
wasm::GenerateFunctionEpilogue(masm, func.framePushed, offsets);
if (func.numRodataRelocs > 0) {
@ -293,6 +286,7 @@ CraneliftStaticEnvironment::CraneliftStaticEnvironment()
#endif
staticMemoryBound(0),
memoryGuardSize(0),
memoryBaseTlsOffset(offsetof(TlsData, memoryBase)),
instanceTlsOffset(offsetof(TlsData, instance)),
interruptTlsOffset(offsetof(TlsData, interrupt)),
cxTlsOffset(offsetof(TlsData, cx)),

View File

@ -69,6 +69,7 @@ struct CraneliftStaticEnvironment {
bool platformIsWindows;
size_t staticMemoryBound;
size_t memoryGuardSize;
size_t memoryBaseTlsOffset;
size_t instanceTlsOffset;
size_t interruptTlsOffset;
size_t cxTlsOffset;

View File

@ -74,7 +74,7 @@ fn main() {
}
}
None => {
println!("cargo:warning={}", "MOZ_TOPOBJDIR should be set by default, otherwise the build is not guaranted to finish.");
println!("cargo:warning=MOZ_TOPOBJDIR should be set by default, otherwise the build is not guaranted to finish.");
}
}

View File

@ -152,6 +152,11 @@ fn make_shared_flags(
if jump_tables_enabled { "true" } else { "false" },
)?;
if cfg!(feature = "cranelift_x86") && cfg!(target_pointer_width = "64") {
sb.enable("enable_pinned_reg")?;
sb.enable("use_pinned_reg_as_heap_base")?;
}
Ok(settings::Flags::new(sb))
}
@ -191,7 +196,6 @@ fn make_isa_specific(env: &StaticEnvironment) -> DashResult<isa::Builder> {
Ok(ib)
}
/// TODO: SM runs on more than x86 chips. Support them.
#[cfg(not(feature = "cranelift_x86"))]
fn make_isa_specific(_env: &StaticEnvironment) -> DashResult<isa::Builder> {
Err("Platform not supported yet!".into())

View File

@ -248,7 +248,7 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
};
let ga = pos.ins().global_value(native_pointer_type(), gv);
pos.ins()
.load(native_pointer_type(), ir::MemFlags::new(), ga, 0)
.load(native_pointer_type(), ir::MemFlags::trusted(), ga, 0)
}
/// Generate code that loads the current instance pointer.
@ -268,7 +268,8 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
}
};
let ga = pos.ins().global_value(native_pointer_type(), gv);
pos.ins().load(ir::types::I32, ir::MemFlags::new(), ga, 0)
pos.ins()
.load(ir::types::I32, ir::MemFlags::trusted(), ga, 0)
}
/// Get a `FuncRef` for the given symbolic address.
@ -310,6 +311,7 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
})
.into();
}
if self.realm_addr.is_none() {
let vmctx = self.get_vmctx_gv(&mut pos.func);
self.realm_addr = pos
@ -323,10 +325,7 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
}
let ptr = native_pointer_type();
let mut flags = ir::MemFlags::new();
flags.set_aligned();
flags.set_notrap();
let flags = ir::MemFlags::trusted();
let cx_addr_val = pos.ins().global_value(ptr, self.cx_addr.unwrap());
let cx = pos.ins().load(ptr, flags, cx_addr_val, 0);
let realm_addr_val = pos.ins().global_value(ptr, self.realm_addr.unwrap());
@ -339,10 +338,7 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
/// an external table.
fn switch_to_indirect_callee_realm(&mut self, pos: &mut FuncCursor, vmctx: ir::Value) {
let ptr = native_pointer_type();
let mut flags = ir::MemFlags::new();
flags.set_aligned();
flags.set_notrap();
let flags = ir::MemFlags::trusted();
let cx = pos
.ins()
.load(ptr, flags, vmctx, offset32(self.static_env.cxTlsOffset));
@ -362,10 +358,7 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
gv_addr: ir::Value,
) {
let ptr = native_pointer_type();
let mut flags = ir::MemFlags::new();
flags.set_aligned();
flags.set_notrap();
let flags = ir::MemFlags::trusted();
let cx = pos
.ins()
.load(ptr, flags, vmctx, offset32(self.static_env.cxTlsOffset));
@ -378,6 +371,24 @@ impl<'a, 'b, 'c> TransEnv<'a, 'b, 'c> {
pos.ins()
.store(flags, realm, cx, offset32(self.static_env.realmCxOffset));
}
fn load_pinned_reg(&self, pos: &mut FuncCursor, vmctx: ir::Value) {
if cfg!(feature = "cranelift_x86") && cfg!(target_pointer_width = "64") {
let heap_base = pos.ins().load(
native_pointer_type(),
ir::MemFlags::trusted(),
vmctx,
self.static_env.memoryBaseTlsOffset as i32,
);
pos.ins().set_pinned_reg(heap_base);
}
}
fn reload_tls_and_pinned_regs(&mut self, pos: &mut FuncCursor) {
let vmctx_gv = self.get_vmctx_gv(&mut pos.func);
let vmctx = pos.ins().global_value(native_pointer_type(), vmctx_gv);
self.load_pinned_reg(pos, vmctx);
}
}
impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
@ -579,7 +590,7 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
let addr = pos.ins().global_value(native_pointer_type(), gv);
Some(
pos.ins()
.load(native_pointer_type(), ir::MemFlags::new(), addr, 0),
.load(native_pointer_type(), ir::MemFlags::trusted(), addr, 0),
)
}
};
@ -611,7 +622,7 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
let entry = pos.ins().iadd(tbase, callee_scaled);
let callee_func = pos
.ins()
.load(native_pointer_type(), ir::MemFlags::new(), entry, 0);
.load(native_pointer_type(), ir::MemFlags::trusted(), entry, 0);
// Check for a null callee.
pos.ins()
@ -620,19 +631,20 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
// Handle external tables, set up environment.
// A function table call could redirect execution to another module with a different realm,
// so switch to this realm just in case.
let vmctx = pos.ins().load(
let callee_vmctx = pos.ins().load(
native_pointer_type(),
ir::MemFlags::new(),
ir::MemFlags::trusted(),
entry,
native_pointer_size(),
);
self.switch_to_indirect_callee_realm(&mut pos, vmctx);
self.switch_to_indirect_callee_realm(&mut pos, callee_vmctx);
self.load_pinned_reg(&mut pos, callee_vmctx);
// First the wasm args.
let mut args = ir::ValueList::default();
args.push(callee_func, &mut pos.func.dfg.value_lists);
args.extend(call_args.iter().cloned(), &mut pos.func.dfg.value_lists);
args.push(vmctx, &mut pos.func.dfg.value_lists);
args.push(callee_vmctx, &mut pos.func.dfg.value_lists);
if let Some(sigid) = sigid_value {
args.push(sigid, &mut pos.func.dfg.value_lists);
}
@ -641,7 +653,10 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
.ins()
.CallIndirect(ir::Opcode::CallIndirect, ir::types::INVALID, sig_ref, args)
.0;
self.switch_to_wasm_tls_realm(&mut pos);
self.reload_tls_and_pinned_regs(&mut pos);
Ok(call)
}
@ -665,18 +680,19 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
// We need the first two pointer-sized fields from the `FuncImportTls` struct: `code`
// and `tls`.
let fit_code = pos
.ins()
.load(native_pointer_type(), ir::MemFlags::new(), gv_addr, 0);
let fit_code =
pos.ins()
.load(native_pointer_type(), ir::MemFlags::trusted(), gv_addr, 0);
let fit_tls = pos.ins().load(
native_pointer_type(),
ir::MemFlags::new(),
ir::MemFlags::trusted(),
gv_addr,
native_pointer_size(),
);
// Switch to the callee's realm.
self.switch_to_import_realm(&mut pos, fit_tls, gv_addr);
self.load_pinned_reg(&mut pos, fit_tls);
// The `tls` field is the VM context pointer for the callee.
args.push(fit_tls, &mut pos.func.dfg.value_lists);
@ -692,6 +708,7 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
.CallIndirect(ir::Opcode::CallIndirect, ir::types::INVALID, sig, args)
.0;
self.switch_to_wasm_tls_realm(&mut pos);
self.reload_tls_and_pinned_regs(&mut pos);
Ok(call)
} else {
// This is a call to a local function.
@ -746,6 +763,7 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
.ins()
.call_indirect(sigref, addr, &[instance, val, vmctx]);
self.switch_to_wasm_tls_realm(&mut pos);
self.reload_tls_and_pinned_regs(&mut pos);
Ok(pos.func.dfg.first_result(call))
}
@ -778,6 +796,7 @@ impl<'a, 'b, 'c> FuncEnvironment for TransEnv<'a, 'b, 'c> {
let addr = pos.ins().func_addr(native_pointer_type(), fnref);
let call = pos.ins().call_indirect(sigref, addr, &[instance, vmctx]);
self.switch_to_wasm_tls_realm(&mut pos);
self.reload_tls_and_pinned_regs(&mut pos);
Ok(pos.func.dfg.first_result(call))
}