1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
* Implement PosMarker instruction

* Implement PosMarker in the arm backend

* Make bindgen run only for clang image

* Fix if-else in cirrus CI file

* Add missing semicolon

* Try removing trailing semicolon

* Try to fix shell/YAML syntax

Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
This commit is contained in:
Maxime Chevalier-Boisvert 2022-07-20 10:43:14 -04:00 committed by Takashi Kokubun
parent 4ae2c744ac
commit 90137f5194
No known key found for this signature in database
GPG key ID: 6FFC433B12EE23DD
6 changed files with 99 additions and 47 deletions

View file

@ -116,7 +116,12 @@ yjit_task:
--prefix="$RUBY_PREFIX"
--enable-yjit=dev
make_miniruby_script: source $HOME/.cargo/env && make -j miniruby
make_bindgen_script: source $HOME/.cargo/env && make -j yjit-bindgen
make_bindgen_script: |
if [[ "$CC" = "clang-12" ]]; then
source $HOME/.cargo/env && make -j yjit-bindgen
else
echo "only running bindgen on clang image"
fi
boot_miniruby_script: RUST_BACKTRACE=1 ./miniruby --yjit-call-threshold=1 -e0
test_dump_insns_script: RUST_BACKTRACE=1 ./miniruby --yjit-call-threshold=1 --yjit-dump-insns -e0
# output_stats_script: RUST_BACKTRACE=1 ./miniruby --yjit-call-threshold=1 --yjit-stats -e0

View file

@ -81,7 +81,7 @@ impl Assembler
/// have no memory operands.
fn arm64_split(mut self) -> Assembler
{
self.forward_pass(|asm, index, op, opnds, target, text| {
self.forward_pass(|asm, index, op, opnds, target, text, pos_marker| {
// Load all Value operands into registers that aren't already a part
// of Load instructions.
let opnds = match op {
@ -103,15 +103,15 @@ impl Assembler
(Opnd::Mem(_), Opnd::Mem(_)) => {
let opnd0 = asm.load(opnds[0]);
let opnd1 = asm.load(opnds[1]);
asm.push_insn(op, vec![opnd0, opnd1], target, text);
asm.push_insn(op, vec![opnd0, opnd1], target, text, pos_marker);
},
(mem_opnd @ Opnd::Mem(_), other_opnd) |
(other_opnd, mem_opnd @ Opnd::Mem(_)) => {
let opnd0 = asm.load(mem_opnd);
asm.push_insn(op, vec![opnd0, other_opnd], target, text);
asm.push_insn(op, vec![opnd0, other_opnd], target, text, pos_marker);
},
_ => {
asm.push_insn(op, opnds, target, text);
asm.push_insn(op, opnds, target, text, pos_marker);
}
}
},
@ -146,7 +146,7 @@ impl Assembler
}
}).collect();
asm.push_insn(op, new_opnds, target, text);
asm.push_insn(op, new_opnds, target, text, pos_marker);
},
Op::IncrCounter => {
// Every operand to the IncrCounter instruction need to be a
@ -250,7 +250,7 @@ impl Assembler
asm.test(opnd0, opnds[1]);
},
_ => {
asm.push_insn(op, opnds, target, text);
asm.push_insn(op, opnds, target, text, pos_marker);
}
};
})
@ -402,9 +402,18 @@ impl Assembler
cb.add_comment(&insn.text.as_ref().unwrap());
}
},
Op::Label => {
cb.write_label(insn.target.unwrap().unwrap_label_idx());
},
// Report back the current position in the generated code
Op::PosMarker => {
let pos = cb.get_write_ptr();
let pos_marker_fn = insn.pos_marker.as_ref().unwrap();
pos_marker_fn(pos);
}
Op::BakeString => {
let str = insn.text.as_ref().unwrap();
for byte in str.as_bytes() {

View file

@ -35,6 +35,9 @@ pub enum Op
// Add a label into the IR at the point that this instruction is added.
Label,
// Mark a position in the generated code
PosMarker,
// Bake a string directly into the instruction stream.
BakeString,
@ -342,8 +345,9 @@ impl From<CodePtr> for Target {
}
}
type PosMarkerFn = Box<dyn Fn(CodePtr)>;
/// YJIT IR instruction
#[derive(Clone)]
pub struct Insn
{
// Opcode for the instruction
@ -361,9 +365,9 @@ pub struct Insn
// List of branch targets (branch instructions only)
pub(super) target: Option<Target>,
// Position in the generated machine code
// Useful for comments and for patching jumps
pub(super) pos: Option<CodePtr>,
// Callback to mark the position of this instruction
// in the generated code
pub(super) pos_marker: Option<PosMarkerFn>,
}
impl fmt::Debug for Insn {
@ -387,9 +391,6 @@ impl fmt::Debug for Insn {
if let Some(target) = self.target {
write!(fmt, " target={target:?}")?;
}
if let Some(pos) = self.pos {
write!(fmt, " pos={pos:?}")?;
}
write!(fmt, " -> {:?}", self.out)
}
@ -420,7 +421,14 @@ impl Assembler
}
/// Append an instruction to the list
pub(super) fn push_insn(&mut self, op: Op, opnds: Vec<Opnd>, target: Option<Target>, text: Option<String>) -> Opnd
pub(super) fn push_insn(
&mut self,
op: Op,
opnds: Vec<Opnd>,
target: Option<Target>,
text: Option<String>,
pos_marker: Option<PosMarkerFn>
) -> Opnd
{
// Index of this instruction
let insn_idx = self.insns.len();
@ -471,7 +479,7 @@ impl Assembler
opnds,
out: out_opnd,
target,
pos: None
pos_marker,
};
self.insns.push(insn);
@ -490,7 +498,7 @@ impl Assembler
opnds: vec![],
out: Opnd::None,
target: None,
pos: None
pos_marker: None,
};
self.insns.push(insn);
self.live_ranges.push(self.insns.len());
@ -505,7 +513,7 @@ impl Assembler
opnds: vec![],
out: Opnd::None,
target: None,
pos: None
pos_marker: None,
};
self.insns.push(insn);
self.live_ranges.push(self.insns.len());
@ -514,7 +522,7 @@ impl Assembler
/// Load an address relative to the given label.
#[must_use]
pub fn lea_label(&mut self, target: Target) -> Opnd {
self.push_insn(Op::LeaLabel, vec![], Some(target), None)
self.push_insn(Op::LeaLabel, vec![], Some(target), None, None)
}
/// Create a new label instance that we can jump to
@ -538,7 +546,7 @@ impl Assembler
opnds: vec![],
out: Opnd::None,
target: Some(label),
pos: None
pos_marker: None,
};
self.insns.push(insn);
self.live_ranges.push(self.insns.len());
@ -546,7 +554,7 @@ impl Assembler
/// Transform input instructions, consumes the input assembler
pub(super) fn forward_pass<F>(mut self, mut map_insn: F) -> Assembler
where F: FnMut(&mut Assembler, usize, Op, Vec<Opnd>, Option<Target>, Option<String>)
where F: FnMut(&mut Assembler, usize, Op, Vec<Opnd>, Option<Target>, Option<String>, Option<PosMarkerFn>)
{
let mut asm = Assembler {
insns: Vec::default(),
@ -582,7 +590,7 @@ impl Assembler
asm.comment(insn.text.unwrap().as_str());
},
_ => {
map_insn(&mut asm, index, insn.op, opnds, insn.target, insn.text);
map_insn(&mut asm, index, insn.op, opnds, insn.target, insn.text, insn.pos_marker);
}
};
@ -644,7 +652,7 @@ impl Assembler
let live_ranges: Vec<usize> = std::mem::take(&mut self.live_ranges);
let asm = self.forward_pass(|asm, index, op, opnds, target, text| {
let asm = self.forward_pass(|asm, index, op, opnds, target, text, pos_marker| {
// Check if this is the last instruction that uses an operand that
// spans more than one instruction. In that case, return the
// allocated register to the pool.
@ -725,7 +733,7 @@ impl Assembler
}
).collect();
asm.push_insn(op, reg_opnds, target, text);
asm.push_insn(op, reg_opnds, target, text, pos_marker);
// Set the output register for this instruction
let num_insns = asm.insns.len();
@ -776,7 +784,13 @@ impl Assembler
pub fn ccall(&mut self, fptr: *const u8, opnds: Vec<Opnd>) -> Opnd
{
let target = Target::FunPtr(fptr);
self.push_insn(Op::CCall, opnds, Some(target), None)
self.push_insn(Op::CCall, opnds, Some(target), None, None)
}
//pub fn pos_marker<F: FnMut(CodePtr)>(&mut self, marker_fn: F)
pub fn pos_marker(&mut self, marker_fn: PosMarkerFn)
{
self.push_insn(Op::PosMarker, vec![], None, None, Some(marker_fn));
}
}
@ -786,7 +800,7 @@ macro_rules! def_push_jcc {
{
pub fn $op_name(&mut self, target: Target)
{
self.push_insn($opcode, vec![], Some(target), None);
self.push_insn($opcode, vec![], Some(target), None, None);
}
}
};
@ -799,7 +813,7 @@ macro_rules! def_push_0_opnd {
#[must_use]
pub fn $op_name(&mut self) -> Opnd
{
self.push_insn($opcode, vec![], None, None)
self.push_insn($opcode, vec![], None, None, None)
}
}
};
@ -811,7 +825,7 @@ macro_rules! def_push_0_opnd_no_out {
{
pub fn $op_name(&mut self)
{
self.push_insn($opcode, vec![], None, None);
self.push_insn($opcode, vec![], None, None, None);
}
}
};
@ -824,7 +838,7 @@ macro_rules! def_push_1_opnd {
#[must_use]
pub fn $op_name(&mut self, opnd0: Opnd) -> Opnd
{
self.push_insn($opcode, vec![opnd0], None, None)
self.push_insn($opcode, vec![opnd0], None, None, None)
}
}
};
@ -836,7 +850,7 @@ macro_rules! def_push_1_opnd_no_out {
{
pub fn $op_name(&mut self, opnd0: Opnd)
{
self.push_insn($opcode, vec![opnd0], None, None);
self.push_insn($opcode, vec![opnd0], None, None, None);
}
}
};
@ -849,7 +863,7 @@ macro_rules! def_push_2_opnd {
#[must_use]
pub fn $op_name(&mut self, opnd0: Opnd, opnd1: Opnd) -> Opnd
{
self.push_insn($opcode, vec![opnd0, opnd1], None, None)
self.push_insn($opcode, vec![opnd0, opnd1], None, None, None)
}
}
};
@ -861,7 +875,7 @@ macro_rules! def_push_2_opnd_no_out {
{
pub fn $op_name(&mut self, opnd0: Opnd, opnd1: Opnd)
{
self.push_insn($opcode, vec![opnd0, opnd1], None, None);
self.push_insn($opcode, vec![opnd0, opnd1], None, None, None);
}
}
};

View file

@ -94,7 +94,7 @@ impl Assembler
{
let live_ranges: Vec<usize> = std::mem::take(&mut self.live_ranges);
self.forward_pass(|asm, index, op, opnds, target, text| {
self.forward_pass(|asm, index, op, opnds, target, text, pos_marker| {
// Load heap object operands into registers because most
// instructions can't directly work with 64-bit constants
let opnds = match op {
@ -140,7 +140,7 @@ impl Assembler
_ => (opnds[0], opnds[1])
};
asm.push_insn(op, vec![opnd0, opnd1], target, text);
asm.push_insn(op, vec![opnd0, opnd1], target, text, pos_marker);
},
Op::CSelZ | Op::CSelNZ | Op::CSelE | Op::CSelNE |
Op::CSelL | Op::CSelLE | Op::CSelG | Op::CSelGE => {
@ -151,7 +151,7 @@ impl Assembler
}
}).collect();
asm.push_insn(op, new_opnds, target, text);
asm.push_insn(op, new_opnds, target, text, pos_marker);
},
Op::Mov => {
match (opnds[0], opnds[1]) {
@ -194,7 +194,7 @@ impl Assembler
asm.not(opnd0);
},
_ => {
asm.push_insn(op, opnds, target, text);
asm.push_insn(op, opnds, target, text, pos_marker);
}
};
})
@ -222,6 +222,13 @@ impl Assembler
cb.write_label(insn.target.unwrap().unwrap_label_idx());
},
// Report back the current position in the generated code
Op::PosMarker => {
let pos = cb.get_write_ptr();
let pos_marker_fn = insn.pos_marker.as_ref().unwrap();
pos_marker_fn(pos);
}
Op::BakeString => {
for byte in insn.text.as_ref().unwrap().as_bytes() {
cb.write_byte(*byte);

View file

@ -297,8 +297,10 @@ fn jit_prepare_routine_call(
/// Record the current codeblock write position for rewriting into a jump into
/// the outlined block later. Used to implement global code invalidation.
fn record_global_inval_patch(cb: &mut CodeBlock, outline_block_target_pos: CodePtr) {
CodegenGlobals::push_global_inval_patch(cb.get_write_ptr(), outline_block_target_pos);
fn record_global_inval_patch(asm: &mut Assembler, outline_block_target_pos: CodePtr) {
asm.pos_marker(Box::new(move |code_ptr| {
CodegenGlobals::push_global_inval_patch(code_ptr, outline_block_target_pos);
}));
}
/// Verify the ctx's types and mappings against the compile-time stack, self,
@ -681,7 +683,7 @@ fn gen_check_ints(asm: &mut Assembler, side_exit: CodePtr) {
fn jump_to_next_insn(
jit: &mut JITState,
current_context: &Context,
cb: &mut CodeBlock,
asm: &mut Assembler,
ocb: &mut OutlinedCb,
) {
// Reset the depth since in current usages we only ever jump to to
@ -704,10 +706,13 @@ fn jump_to_next_insn(
record_global_inval_patch(cb, exit_pos);
jit.record_boundary_patch_point = false;
*/
}
// Generate the jump instruction
gen_direct_jump(jit, &reset_depth, jump_block, cb);
gen_direct_jump(jit, &reset_depth, jump_block, asm);
}
// Compile a sequence of bytecode instructions for a given basic block version.
@ -763,7 +768,7 @@ pub fn gen_single_block(
// opt_getinlinecache wants to be in a block all on its own. Cut the block short
// if we run into it. See gen_opt_getinlinecache() for details.
if opcode == YARVINSN_opt_getinlinecache.as_usize() && insn_idx > starting_insn_idx {
jump_to_next_insn(&mut jit, &ctx, cb, ocb);
jump_to_next_insn(&mut jit, &ctx, &mut asm, ocb);
break;
}
@ -775,11 +780,9 @@ pub fn gen_single_block(
// If previous instruction requested to record the boundary
if jit.record_boundary_patch_point {
// FIXME: is this sound with the new assembler?
// Generate an exit to this instruction and record it
let exit_pos = gen_outlined_exit(jit.pc, &ctx, ocb);
record_global_inval_patch(cb, exit_pos);
record_global_inval_patch(&mut asm, exit_pos);
jit.record_boundary_patch_point = false;
}

View file

@ -1861,7 +1861,7 @@ fn gen_jump_branch(
}
}
pub fn gen_direct_jump(jit: &JITState, ctx: &Context, target0: BlockId, cb: &mut CodeBlock) {
pub fn gen_direct_jump(jit: &JITState, ctx: &Context, target0: BlockId, asm: &mut Assembler) {
let branchref = make_branch_entry(&jit.get_block(), ctx, gen_jump_branch);
let mut branch = branchref.borrow_mut();
@ -1897,6 +1897,17 @@ pub fn gen_direct_jump(jit: &JITState, ctx: &Context, target0: BlockId, cb: &mut
asm.pos_marker(Box::new(move |code_ptr| {
let mut branch = branchref.borrow_mut();
branch.start_addr = Some(code_ptr);
}));
} else {
@ -1904,8 +1915,11 @@ pub fn gen_direct_jump(jit: &JITState, ctx: &Context, target0: BlockId, cb: &mut
// target block right after this one (fallthrough).
branch.dst_addrs[0] = None;
branch.shape = BranchShape::Next0;
branch.start_addr = Some(cb.get_write_ptr());
branch.end_addr = Some(cb.get_write_ptr());
todo!();
//branch.start_addr = Some(cb.get_write_ptr());
//branch.end_addr = Some(cb.get_write_ptr());
}
}