mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 01:05:45 +00:00
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:
parent
1e8eaa6511
commit
c811b52449
@ -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)),
|
||||
|
@ -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;
|
||||
|
@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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))
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user