YJIT: Enable default rustc lints (warnings) (#5864)

`rustc` performs in depth dead code analysis and issues warning
even for things like unused struct fields and unconstructed enum
variants. This was annoying for us during the port but hopefully
they are less of an issue now.

This patch enables all the unused warnings we disabled and address
all the warnings we previously ignored. Generally, the approach I've
taken is to use `cfg!` instead of using the `cfg` attribute and
to delete code where it makes sense. I've put `#[allow(unused)]`
on things we intentionally keep around for printf style debugging
and on items that are too annoying to keep warning-free in all
build configs.
This commit is contained in:
Alan Wu 2022-04-29 18:20:23 -04:00 коммит произвёл GitHub
Родитель 7c039e423c
Коммит 5c843a1a6e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 285 добавлений и 285 удалений

Просмотреть файл

@ -1,6 +1,8 @@
use std::collections::BTreeMap;
use std::mem;
#[cfg(feature = "asm_comments")]
use std::collections::BTreeMap;
// Lots of manual vertical alignment in there that rustfmt doesn't handle well.
#[rustfmt::skip]
pub mod x86_64;
@ -23,6 +25,7 @@ impl CodePtr {
*ptr as i64
}
#[allow(unused)]
fn into_usize(&self) -> usize {
let CodePtr(ptr) = self;
*ptr as usize
@ -36,21 +39,6 @@ impl From<*mut u8> for CodePtr {
}
}
/// Compute an offset in bytes of a given struct field
macro_rules! offset_of {
($struct_type:ty, $field_name:tt) => {{
// Null pointer to our struct type
let foo = (0 as *const $struct_type);
unsafe {
let ptr_field = (&(*foo).$field_name as *const _ as usize);
let ptr_base = (foo as usize);
ptr_field - ptr_base
}
}};
}
pub(crate) use offset_of;
//
// TODO: need a field_size_of macro, to compute the size of a struct field in bytes
//
@ -71,6 +59,7 @@ struct LabelRef {
pub struct CodeBlock {
// Block of non-executable memory used for dummy code blocks
// This memory is owned by this block and lives as long as the block
#[allow(unused)]
dummy_block: Vec<u8>,
// Pointer to memory we are writing into
@ -110,6 +99,7 @@ pub struct CodeBlock {
}
impl CodeBlock {
#[cfg(test)]
pub fn new_dummy(mem_size: usize) -> Self {
// Allocate some non-executable memory
let mut dummy_block = vec![0; mem_size];
@ -131,6 +121,7 @@ impl CodeBlock {
}
}
#[cfg(not(test))]
pub fn new(mem_block: *mut u8, mem_size: usize, page_size: usize) -> Self {
Self {
dummy_block: vec![0; 0],
@ -175,11 +166,6 @@ impl CodeBlock {
pub fn comments_at(&self, pos: usize) -> Option<&Vec<String>> {
self.asm_comments.get(&pos)
}
#[cfg(not(feature = "asm_comments"))]
#[inline]
pub fn comments_at(&self, _: usize) -> Option<&Vec<String>> {
None
}
pub fn get_mem_size(&self) -> usize {
self.mem_size
@ -246,12 +232,6 @@ impl CodeBlock {
}
}
// Read a single byte at the given position
pub fn read_byte(&self, pos: usize) -> u8 {
assert!(pos < self.mem_size);
unsafe { self.mem_block.add(pos).read() }
}
// Write multiple bytes starting from the current position
pub fn write_bytes(&mut self, bytes: &[u8]) {
for byte in bytes {

Просмотреть файл

@ -1,5 +1,5 @@
use std::io::{Result, Write};
use std::mem;
#![allow(dead_code)] // For instructions we don't currently generate
use crate::asm::*;
// Import the assembler tests module

Просмотреть файл

@ -7,7 +7,7 @@ use std::fmt;
impl<'a> fmt::LowerHex for super::CodeBlock {
fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
for pos in 0..self.write_pos {
let byte = self.read_byte(pos);
let byte = unsafe { self.mem_block.add(pos).read() };
fmtr.write_fmt(format_args!("{:02x}", byte))?;
}
Ok(())

Просмотреть файл

@ -28,7 +28,7 @@ pub const REG0: X86Opnd = RAX;
pub const REG0_32: X86Opnd = EAX;
pub const REG0_8: X86Opnd = AL;
pub const REG1: X86Opnd = RCX;
pub const REG1_32: X86Opnd = ECX;
// pub const REG1_32: X86Opnd = ECX;
/// Status returned by code generation functions
#[derive(PartialEq, Debug)]
@ -106,10 +106,6 @@ impl JITState {
self.opcode
}
pub fn set_opcode(self: &mut JITState, opcode: usize) {
self.opcode = opcode;
}
pub fn add_gc_object_offset(self: &mut JITState, ptr_offset: u32) {
let mut gc_obj_vec: RefMut<_> = self.block.borrow_mut();
gc_obj_vec.add_gc_object_offset(ptr_offset);
@ -118,15 +114,11 @@ impl JITState {
pub fn get_pc(self: &JITState) -> *mut VALUE {
self.pc
}
pub fn set_pc(self: &mut JITState, pc: *mut VALUE) {
self.pc = pc;
}
}
use crate::codegen::JCCKinds::*;
#[allow(non_camel_case_types)]
#[allow(non_camel_case_types, unused)]
pub enum JCCKinds {
JCC_JNE,
JCC_JNZ,
@ -749,8 +741,7 @@ pub fn gen_single_block(
}
// In debug mode, verify our existing assumption
#[cfg(debug_assertions)]
if get_option!(verify_ctx) && jit_at_current_insn(&jit) {
if cfg!(debug_assertions) && get_option!(verify_ctx) && jit_at_current_insn(&jit) {
verify_ctx(&jit, &ctx);
}
@ -6007,7 +5998,7 @@ mod tests {
let mut value_array: [u64; 2] = [0, 2]; // We only compile for n == 2
let pc: *mut VALUE = &mut value_array as *mut u64 as *mut VALUE;
jit.set_pc(pc);
jit.pc = pc;
let status = gen_dupn(&mut jit, &mut context, &mut cb, &mut ocb);
@ -6056,7 +6047,7 @@ mod tests {
let mut value_array: [u64; 2] = [0, Qtrue.into()];
let pc: *mut VALUE = &mut value_array as *mut u64 as *mut VALUE;
jit.set_pc(pc);
jit.pc = pc;
let status = gen_putobject(&mut jit, &mut context, &mut cb, &mut ocb);
@ -6075,7 +6066,7 @@ mod tests {
// The Fixnum 7 is encoded as 7 * 2 + 1, or 15
let mut value_array: [u64; 2] = [0, 15];
let pc: *mut VALUE = &mut value_array as *mut u64 as *mut VALUE;
jit.set_pc(pc);
jit.pc = pc;
let status = gen_putobject(&mut jit, &mut context, &mut cb, &mut ocb);
@ -6117,7 +6108,7 @@ mod tests {
let mut value_array: [u64; 2] = [0, 2];
let pc: *mut VALUE = &mut value_array as *mut u64 as *mut VALUE;
jit.set_pc(pc);
jit.pc = pc;
let status = gen_setn(&mut jit, &mut context, &mut cb, &mut ocb);
@ -6138,7 +6129,7 @@ mod tests {
let mut value_array: [u64; 2] = [0, 1];
let pc: *mut VALUE = &mut value_array as *mut u64 as *mut VALUE;
jit.set_pc(pc);
jit.pc = pc;
let status = gen_topn(&mut jit, &mut context, &mut cb, &mut ocb);
@ -6160,7 +6151,7 @@ mod tests {
let mut value_array: [u64; 3] = [0, 2, 0];
let pc: *mut VALUE = &mut value_array as *mut u64 as *mut VALUE;
jit.set_pc(pc);
jit.pc = pc;
let status = gen_adjuststack(&mut jit, &mut context, &mut cb, &mut ocb);

Просмотреть файл

@ -10,8 +10,7 @@ use std::cell::*;
use std::hash::{Hash, Hasher};
use std::mem;
use std::mem::size_of;
use std::ptr;
use std::rc::{Rc, Weak};
use std::rc::{Rc};
use InsnOpnd::*;
use TempMapping::*;
@ -35,7 +34,10 @@ pub enum Type {
Array,
Hash,
ImmSymbol,
#[allow(unused)]
HeapSymbol,
String,
}
@ -242,6 +244,7 @@ struct Branch {
end_addr: Option<CodePtr>,
// Context right after the branch instruction
#[allow(unused)] // set but not read at the moment
src_ctx: Context,
// Branch target blocks and their contexts
@ -416,7 +419,6 @@ pub unsafe fn load_iseq_payload(iseq: IseqPtr) -> Option<&'static mut IseqPayloa
/// Get the payload object associated with an iseq. Create one if none exists.
fn get_iseq_payload(iseq: IseqPtr) -> &'static mut IseqPayload {
use core::ffi::c_void;
type VoidPtr = *mut c_void;
let payload_non_null = unsafe {
@ -799,10 +801,12 @@ impl Block {
self.ctx
}
#[allow(unused)]
pub fn get_start_addr(&self) -> Option<CodePtr> {
self.start_addr
}
#[allow(unused)]
pub fn get_end_addr(&self) -> Option<CodePtr> {
self.end_addr
}
@ -1018,11 +1022,7 @@ impl Context {
/// Get the currently tracked type for a local variable
pub fn get_local_type(&self, idx: usize) -> Type {
if idx > MAX_LOCAL_TYPES {
return Type::Unknown;
}
return self.local_types[idx];
*self.local_types.get(idx).unwrap_or(&Type::Unknown)
}
/// Upgrade (or "learn") the type of an instruction operand
@ -1251,6 +1251,7 @@ impl Context {
impl BlockId {
/// Print Ruby source location for debugging
#[cfg(debug_assertions)]
#[allow(dead_code)]
pub fn dump_src_loc(&self) {
unsafe { rb_yjit_dump_iseq_loc(self.iseq, self.idx) }
}

Просмотреть файл

@ -84,7 +84,7 @@
use std::convert::From;
use std::ffi::CString;
use std::os::raw::{c_char, c_int, c_long, c_uint, c_void};
use std::os::raw::{c_char, c_int, c_long, c_uint};
use std::panic::{catch_unwind, UnwindSafe};
// We check that we can do this with the configure script and a couple of
@ -95,8 +95,13 @@ pub type size_t = u64;
/// shifted 1s but not explicitly an enum.
pub type RedefinitionFlag = u32;
// Textually include output from rust-bindgen as suggested by its user guide.
include!("cruby_bindings.inc.rs");
#[allow(dead_code)]
mod autogened {
use super::*;
// Textually include output from rust-bindgen as suggested by its user guide.
include!("cruby_bindings.inc.rs");
}
pub use autogened::*;
// TODO: For #defines that affect memory layout, we need to check for them
// on build and fail if they're wrong. e.g. USE_FLONUM *must* be true.
@ -104,6 +109,7 @@ include!("cruby_bindings.inc.rs");
// TODO:
// Temporary, these external bindings will likely be auto-generated
// and textually included in this file
#[cfg_attr(test, allow(unused))] // We don't link against C code when testing
extern "C" {
#[link_name = "rb_yjit_alloc_exec_mem"] // we can rename functions with this attribute
pub fn alloc_exec_mem(mem_size: u32) -> *mut u8;
@ -135,9 +141,6 @@ extern "C" {
#[link_name = "rb_get_cme_def_type"]
pub fn get_cme_def_type(cme: *const rb_callable_method_entry_t) -> rb_method_type_t;
#[link_name = "rb_get_cme_def_method_serial"]
pub fn get_cme_def_method_serial(cme: *const rb_callable_method_entry_t) -> u64;
#[link_name = "rb_get_cme_def_body_attr_id"]
pub fn get_cme_def_body_attr_id(cme: *const rb_callable_method_entry_t) -> ID;
@ -178,9 +181,6 @@ extern "C" {
#[link_name = "rb_get_iseq_body_iseq_encoded"]
pub fn get_iseq_body_iseq_encoded(iseq: IseqPtr) -> *mut VALUE;
#[link_name = "rb_get_iseq_body_builtin_inline_p"]
pub fn get_iseq_body_builtin_inline_p(iseq: IseqPtr) -> bool;
#[link_name = "rb_get_iseq_body_stack_max"]
pub fn get_iseq_body_stack_max(iseq: IseqPtr) -> c_uint;
@ -272,8 +272,6 @@ extern "C" {
pub fn rb_aliased_callable_method_entry(
me: *const rb_callable_method_entry_t,
) -> *const rb_callable_method_entry_t;
pub fn rb_iseq_only_optparam_p(iseq: IseqPtr) -> bool;
pub fn rb_iseq_only_kwparam_p(iseq: IseqPtr) -> bool;
pub fn rb_vm_getclassvariable(iseq: IseqPtr, cfp: CfpPtr, id: ID, ic: ICVARC) -> VALUE;
pub fn rb_vm_setclassvariable(
iseq: IseqPtr,
@ -299,12 +297,6 @@ extern "C" {
#[link_name = "rb_METHOD_ENTRY_VISI"]
pub fn METHOD_ENTRY_VISI(me: *const rb_callable_method_entry_t) -> rb_method_visibility_t;
pub fn rb_yjit_branch_stub_hit(
branch_ptr: *const c_void,
target_idx: u32,
ec: EcPtr,
) -> *const c_void;
pub fn rb_str_bytesize(str: VALUE) -> VALUE;
#[link_name = "rb_RCLASS_ORIGIN"]
@ -607,6 +599,7 @@ impl From<VALUE> for i32 {
}
/// Produce a Ruby string from a Rust string slice
#[cfg(feature = "asm_comments")]
pub fn rust_str_to_ruby(str: &str) -> VALUE {
unsafe { rb_utf8_str_new(str.as_ptr() as *const i8, str.len() as i64) }
}
@ -670,7 +663,7 @@ where
Err(_) => {
// Theoretically we can recover from some of these panics,
// but it's too late if the unwind reaches here.
use std::{io, process, str};
use std::{process, str};
let _ = catch_unwind(|| {
// IO functions can panic too.
@ -699,221 +692,231 @@ pub const Qtrue: VALUE = VALUE(20);
#[allow(non_upper_case_globals)]
pub const Qundef: VALUE = VALUE(52);
pub const RUBY_SYMBOL_FLAG: usize = 0x0c;
#[allow(unused)]
mod manual_defs {
use super::*;
pub const RUBY_LONG_MIN: isize = std::os::raw::c_long::MIN as isize;
pub const RUBY_LONG_MAX: isize = std::os::raw::c_long::MAX as isize;
pub const RUBY_SYMBOL_FLAG: usize = 0x0c;
pub const RUBY_FIXNUM_MIN: isize = RUBY_LONG_MIN / 2;
pub const RUBY_FIXNUM_MAX: isize = RUBY_LONG_MAX / 2;
pub const RUBY_FIXNUM_FLAG: usize = 0x1;
pub const RUBY_LONG_MIN: isize = std::os::raw::c_long::MIN as isize;
pub const RUBY_LONG_MAX: isize = std::os::raw::c_long::MAX as isize;
pub const RUBY_FLONUM_FLAG: usize = 0x2;
pub const RUBY_FLONUM_MASK: usize = 0x3;
pub const RUBY_FIXNUM_MIN: isize = RUBY_LONG_MIN / 2;
pub const RUBY_FIXNUM_MAX: isize = RUBY_LONG_MAX / 2;
pub const RUBY_FIXNUM_FLAG: usize = 0x1;
pub const RUBY_IMMEDIATE_MASK: usize = 0x7;
pub const RUBY_FLONUM_FLAG: usize = 0x2;
pub const RUBY_FLONUM_MASK: usize = 0x3;
pub const RUBY_SPECIAL_SHIFT: usize = 8;
pub const RUBY_IMMEDIATE_MASK: usize = 0x7;
// Constants from vm_core.h
pub const VM_SPECIAL_OBJECT_VMCORE: usize = 0x1;
pub const VM_ENV_DATA_INDEX_SPECVAL: isize = -1;
pub const VM_ENV_DATA_INDEX_FLAGS: isize = 0;
pub const VM_ENV_DATA_SIZE: usize = 3;
pub const RUBY_SPECIAL_SHIFT: usize = 8;
// From vm_callinfo.h
pub const VM_CALL_ARGS_SPLAT: u32 = 1 << VM_CALL_ARGS_SPLAT_bit;
pub const VM_CALL_ARGS_BLOCKARG: u32 = 1 << VM_CALL_ARGS_BLOCKARG_bit;
pub const VM_CALL_FCALL: u32 = 1 << VM_CALL_FCALL_bit;
pub const VM_CALL_KWARG: u32 = 1 << VM_CALL_KWARG_bit;
pub const VM_CALL_KW_SPLAT: u32 = 1 << VM_CALL_KW_SPLAT_bit;
pub const VM_CALL_TAILCALL: u32 = 1 << VM_CALL_TAILCALL_bit;
// Constants from vm_core.h
pub const VM_SPECIAL_OBJECT_VMCORE: usize = 0x1;
pub const VM_ENV_DATA_INDEX_SPECVAL: isize = -1;
pub const VM_ENV_DATA_INDEX_FLAGS: isize = 0;
pub const VM_ENV_DATA_SIZE: usize = 3;
pub const SIZEOF_VALUE: usize = 8;
pub const SIZEOF_VALUE_I32: i32 = SIZEOF_VALUE as i32;
// From vm_callinfo.h
pub const VM_CALL_ARGS_SPLAT: u32 = 1 << VM_CALL_ARGS_SPLAT_bit;
pub const VM_CALL_ARGS_BLOCKARG: u32 = 1 << VM_CALL_ARGS_BLOCKARG_bit;
pub const VM_CALL_FCALL: u32 = 1 << VM_CALL_FCALL_bit;
pub const VM_CALL_KWARG: u32 = 1 << VM_CALL_KWARG_bit;
pub const VM_CALL_KW_SPLAT: u32 = 1 << VM_CALL_KW_SPLAT_bit;
pub const VM_CALL_TAILCALL: u32 = 1 << VM_CALL_TAILCALL_bit;
pub const RUBY_FL_SINGLETON: usize = RUBY_FL_USER_0;
pub const SIZEOF_VALUE: usize = 8;
pub const SIZEOF_VALUE_I32: i32 = SIZEOF_VALUE as i32;
pub const ROBJECT_EMBED: usize = RUBY_FL_USER_1;
pub const ROBJECT_EMBED_LEN_MAX: usize = 3; // This is a complex calculation in ruby/internal/core/robject.h
pub const RUBY_FL_SINGLETON: usize = RUBY_FL_USER_0;
pub const RMODULE_IS_REFINEMENT: usize = RUBY_FL_USER_3;
pub const ROBJECT_EMBED: usize = RUBY_FL_USER_1;
pub const ROBJECT_EMBED_LEN_MAX: usize = 3; // This is a complex calculation in ruby/internal/core/robject.h
// Constants from include/ruby/internal/fl_type.h
pub const RUBY_FL_USHIFT: usize = 12;
pub const RUBY_FL_USER_0: usize = 1 << (RUBY_FL_USHIFT + 0);
pub const RUBY_FL_USER_1: usize = 1 << (RUBY_FL_USHIFT + 1);
pub const RUBY_FL_USER_2: usize = 1 << (RUBY_FL_USHIFT + 2);
pub const RUBY_FL_USER_3: usize = 1 << (RUBY_FL_USHIFT + 3);
pub const RUBY_FL_USER_4: usize = 1 << (RUBY_FL_USHIFT + 4);
pub const RUBY_FL_USER_5: usize = 1 << (RUBY_FL_USHIFT + 5);
pub const RUBY_FL_USER_6: usize = 1 << (RUBY_FL_USHIFT + 6);
pub const RUBY_FL_USER_7: usize = 1 << (RUBY_FL_USHIFT + 7);
pub const RUBY_FL_USER_8: usize = 1 << (RUBY_FL_USHIFT + 8);
pub const RUBY_FL_USER_9: usize = 1 << (RUBY_FL_USHIFT + 9);
pub const RUBY_FL_USER_10: usize = 1 << (RUBY_FL_USHIFT + 10);
pub const RUBY_FL_USER_11: usize = 1 << (RUBY_FL_USHIFT + 11);
pub const RUBY_FL_USER_12: usize = 1 << (RUBY_FL_USHIFT + 12);
pub const RUBY_FL_USER_13: usize = 1 << (RUBY_FL_USHIFT + 13);
pub const RUBY_FL_USER_14: usize = 1 << (RUBY_FL_USHIFT + 14);
pub const RUBY_FL_USER_15: usize = 1 << (RUBY_FL_USHIFT + 15);
pub const RUBY_FL_USER_16: usize = 1 << (RUBY_FL_USHIFT + 16);
pub const RUBY_FL_USER_17: usize = 1 << (RUBY_FL_USHIFT + 17);
pub const RUBY_FL_USER_18: usize = 1 << (RUBY_FL_USHIFT + 18);
pub const RUBY_FL_USER_19: usize = 1 << (RUBY_FL_USHIFT + 19);
pub const RMODULE_IS_REFINEMENT: usize = RUBY_FL_USER_3;
// Constants from include/ruby/internal/core/rarray.h
pub const RARRAY_EMBED_FLAG: usize = RUBY_FL_USER_1;
pub const RARRAY_EMBED_LEN_SHIFT: usize = RUBY_FL_USHIFT + 3;
pub const RARRAY_EMBED_LEN_MASK: usize = RUBY_FL_USER_3 | RUBY_FL_USER_4;
// Constants from include/ruby/internal/fl_type.h
pub const RUBY_FL_USHIFT: usize = 12;
pub const RUBY_FL_USER_0: usize = 1 << (RUBY_FL_USHIFT + 0);
pub const RUBY_FL_USER_1: usize = 1 << (RUBY_FL_USHIFT + 1);
pub const RUBY_FL_USER_2: usize = 1 << (RUBY_FL_USHIFT + 2);
pub const RUBY_FL_USER_3: usize = 1 << (RUBY_FL_USHIFT + 3);
pub const RUBY_FL_USER_4: usize = 1 << (RUBY_FL_USHIFT + 4);
pub const RUBY_FL_USER_5: usize = 1 << (RUBY_FL_USHIFT + 5);
pub const RUBY_FL_USER_6: usize = 1 << (RUBY_FL_USHIFT + 6);
pub const RUBY_FL_USER_7: usize = 1 << (RUBY_FL_USHIFT + 7);
pub const RUBY_FL_USER_8: usize = 1 << (RUBY_FL_USHIFT + 8);
pub const RUBY_FL_USER_9: usize = 1 << (RUBY_FL_USHIFT + 9);
pub const RUBY_FL_USER_10: usize = 1 << (RUBY_FL_USHIFT + 10);
pub const RUBY_FL_USER_11: usize = 1 << (RUBY_FL_USHIFT + 11);
pub const RUBY_FL_USER_12: usize = 1 << (RUBY_FL_USHIFT + 12);
pub const RUBY_FL_USER_13: usize = 1 << (RUBY_FL_USHIFT + 13);
pub const RUBY_FL_USER_14: usize = 1 << (RUBY_FL_USHIFT + 14);
pub const RUBY_FL_USER_15: usize = 1 << (RUBY_FL_USHIFT + 15);
pub const RUBY_FL_USER_16: usize = 1 << (RUBY_FL_USHIFT + 16);
pub const RUBY_FL_USER_17: usize = 1 << (RUBY_FL_USHIFT + 17);
pub const RUBY_FL_USER_18: usize = 1 << (RUBY_FL_USHIFT + 18);
pub const RUBY_FL_USER_19: usize = 1 << (RUBY_FL_USHIFT + 19);
// From internal/struct.h
pub const RSTRUCT_EMBED_LEN_MASK: usize = RUBY_FL_USER_2 | RUBY_FL_USER_1;
// Constants from include/ruby/internal/core/rarray.h
pub const RARRAY_EMBED_FLAG: usize = RUBY_FL_USER_1;
pub const RARRAY_EMBED_LEN_SHIFT: usize = RUBY_FL_USHIFT + 3;
pub const RARRAY_EMBED_LEN_MASK: usize = RUBY_FL_USER_3 | RUBY_FL_USER_4;
// From iseq.h
pub const ISEQ_TRANSLATED: usize = RUBY_FL_USER_7;
// From internal/struct.h
pub const RSTRUCT_EMBED_LEN_MASK: usize = RUBY_FL_USER_2 | RUBY_FL_USER_1;
// We'll need to encode a lot of Ruby struct/field offsets as constants unless we want to
// redeclare all the Ruby C structs and write our own offsetof macro. For now, we use constants.
pub const RUBY_OFFSET_RBASIC_FLAGS: i32 = 0; // struct RBasic, field "flags"
pub const RUBY_OFFSET_RBASIC_KLASS: i32 = 8; // struct RBasic, field "klass"
pub const RUBY_OFFSET_RARRAY_AS_HEAP_LEN: i32 = 16; // struct RArray, subfield "as.heap.len"
pub const RUBY_OFFSET_RARRAY_AS_HEAP_PTR: i32 = 32; // struct RArray, subfield "as.heap.ptr"
pub const RUBY_OFFSET_RARRAY_AS_ARY: i32 = 16; // struct RArray, subfield "as.ary"
// From iseq.h
pub const ISEQ_TRANSLATED: usize = RUBY_FL_USER_7;
pub const RUBY_OFFSET_RSTRUCT_AS_HEAP_PTR: i32 = 24; // struct RStruct, subfield "as.heap.ptr"
pub const RUBY_OFFSET_RSTRUCT_AS_ARY: i32 = 16; // struct RStruct, subfield "as.ary"
// We'll need to encode a lot of Ruby struct/field offsets as constants unless we want to
// redeclare all the Ruby C structs and write our own offsetof macro. For now, we use constants.
pub const RUBY_OFFSET_RBASIC_FLAGS: i32 = 0; // struct RBasic, field "flags"
pub const RUBY_OFFSET_RBASIC_KLASS: i32 = 8; // struct RBasic, field "klass"
pub const RUBY_OFFSET_RARRAY_AS_HEAP_LEN: i32 = 16; // struct RArray, subfield "as.heap.len"
pub const RUBY_OFFSET_RARRAY_AS_HEAP_PTR: i32 = 32; // struct RArray, subfield "as.heap.ptr"
pub const RUBY_OFFSET_RARRAY_AS_ARY: i32 = 16; // struct RArray, subfield "as.ary"
pub const RUBY_OFFSET_ROBJECT_AS_ARY: i32 = 16; // struct RObject, subfield "as.ary"
pub const RUBY_OFFSET_ROBJECT_AS_HEAP_NUMIV: i32 = 16; // struct RObject, subfield "as.heap.numiv"
pub const RUBY_OFFSET_ROBJECT_AS_HEAP_IVPTR: i32 = 24; // struct RObject, subfield "as.heap.ivptr"
pub const RUBY_OFFSET_RSTRUCT_AS_HEAP_PTR: i32 = 24; // struct RStruct, subfield "as.heap.ptr"
pub const RUBY_OFFSET_RSTRUCT_AS_ARY: i32 = 16; // struct RStruct, subfield "as.ary"
// Constants from rb_control_frame_t vm_core.h
pub const RUBY_OFFSET_CFP_PC: i32 = 0;
pub const RUBY_OFFSET_CFP_SP: i32 = 8;
pub const RUBY_OFFSET_CFP_ISEQ: i32 = 16;
pub const RUBY_OFFSET_CFP_SELF: i32 = 24;
pub const RUBY_OFFSET_CFP_EP: i32 = 32;
pub const RUBY_OFFSET_CFP_BLOCK_CODE: i32 = 40;
pub const RUBY_OFFSET_CFP_BP: i32 = 48; // field __bp__
pub const RUBY_OFFSET_CFP_JIT_RETURN: i32 = 56;
pub const RUBY_SIZEOF_CONTROL_FRAME: usize = 64;
pub const RUBY_OFFSET_ROBJECT_AS_ARY: i32 = 16; // struct RObject, subfield "as.ary"
pub const RUBY_OFFSET_ROBJECT_AS_HEAP_NUMIV: i32 = 16; // struct RObject, subfield "as.heap.numiv"
pub const RUBY_OFFSET_ROBJECT_AS_HEAP_IVPTR: i32 = 24; // struct RObject, subfield "as.heap.ivptr"
// Constants from rb_execution_context_t vm_core.h
pub const RUBY_OFFSET_EC_CFP: i32 = 16;
pub const RUBY_OFFSET_EC_INTERRUPT_FLAG: i32 = 32; // rb_atomic_t (u32)
pub const RUBY_OFFSET_EC_INTERRUPT_MASK: i32 = 36; // rb_atomic_t (u32)
pub const RUBY_OFFSET_EC_THREAD_PTR: i32 = 48;
// Constants from rb_control_frame_t vm_core.h
pub const RUBY_OFFSET_CFP_PC: i32 = 0;
pub const RUBY_OFFSET_CFP_SP: i32 = 8;
pub const RUBY_OFFSET_CFP_ISEQ: i32 = 16;
pub const RUBY_OFFSET_CFP_SELF: i32 = 24;
pub const RUBY_OFFSET_CFP_EP: i32 = 32;
pub const RUBY_OFFSET_CFP_BLOCK_CODE: i32 = 40;
pub const RUBY_OFFSET_CFP_BP: i32 = 48; // field __bp__
pub const RUBY_OFFSET_CFP_JIT_RETURN: i32 = 56;
pub const RUBY_SIZEOF_CONTROL_FRAME: usize = 64;
// Constants from rb_thread_t in vm_core.h
pub const RUBY_OFFSET_THREAD_SELF: i32 = 16;
// Constants from rb_execution_context_t vm_core.h
pub const RUBY_OFFSET_EC_CFP: i32 = 16;
pub const RUBY_OFFSET_EC_INTERRUPT_FLAG: i32 = 32; // rb_atomic_t (u32)
pub const RUBY_OFFSET_EC_INTERRUPT_MASK: i32 = 36; // rb_atomic_t (u32)
pub const RUBY_OFFSET_EC_THREAD_PTR: i32 = 48;
// Constants from iseq_inline_constant_cache (IC) and iseq_inline_constant_cache_entry (ICE) in vm_core.h
pub const RUBY_OFFSET_IC_ENTRY: i32 = 0;
pub const RUBY_OFFSET_ICE_VALUE: i32 = 8;
// Constants from rb_thread_t in vm_core.h
pub const RUBY_OFFSET_THREAD_SELF: i32 = 16;
// TODO: need to dynamically autogenerate constants for all the YARV opcodes from insns.def
// TODO: typing of these adds unnecessary casting
pub const OP_NOP: usize = 0;
pub const OP_GETLOCAL: usize = 1;
pub const OP_SETLOCAL: usize = 2;
pub const OP_GETBLOCKPARAM: usize = 3;
pub const OP_SETBLOCKPARAM: usize = 4;
pub const OP_GETBLOCKPARAMPROXY: usize = 5;
pub const OP_GETSPECIAL: usize = 6;
pub const OP_SETSPECIAL: usize = 7;
pub const OP_GETINSTANCEVARIABLE: usize = 8;
pub const OP_SETINSTANCEVARIABLE: usize = 9;
pub const OP_GETCLASSVARIABLE: usize = 10;
pub const OP_SETCLASSVARIABLE: usize = 11;
pub const OP_GETCONSTANT: usize = 12;
pub const OP_SETCONSTANT: usize = 13;
pub const OP_GETGLOBAL: usize = 14;
pub const OP_SETGLOBAL: usize = 15;
pub const OP_PUTNIL: usize = 16;
pub const OP_PUTSELF: usize = 17;
pub const OP_PUTOBJECT: usize = 18;
pub const OP_PUTSPECIALOBJECT: usize = 19;
pub const OP_PUTSTRING: usize = 20;
pub const OP_CONCATSTRINGS: usize = 21;
pub const OP_ANYTOSTRING: usize = 22;
pub const OP_TOREGEXP: usize = 23;
pub const OP_INTERN: usize = 24;
pub const OP_NEWARRAY: usize = 25;
pub const OP_NEWARRAYKWSPLAT: usize = 26;
pub const OP_DUPARRAY: usize = 27;
pub const OP_DUPHASH: usize = 28;
pub const OP_EXPANDARRAY: usize = 29;
pub const OP_CONCATARRAY: usize = 30;
pub const OP_SPLATARRAY: usize = 31;
pub const OP_NEWHASH: usize = 32;
pub const OP_NEWRANGE: usize = 33;
pub const OP_POP: usize = 34;
pub const OP_DUP: usize = 35;
pub const OP_DUPN: usize = 36;
pub const OP_SWAP: usize = 37;
pub const OP_TOPN: usize = 38;
pub const OP_SETN: usize = 39;
pub const OP_ADJUSTSTACK: usize = 40;
pub const OP_DEFINED: usize = 41;
pub const OP_CHECKMATCH: usize = 42;
pub const OP_CHECKKEYWORD: usize = 43;
pub const OP_CHECKTYPE: usize = 44;
pub const OP_DEFINECLASS: usize = 45;
pub const OP_DEFINEMETHOD: usize = 46;
pub const OP_DEFINESMETHOD: usize = 47;
pub const OP_SEND: usize = 48;
pub const OP_OPT_SEND_WITHOUT_BLOCK: usize = 49;
pub const OP_OBJTOSTRING: usize = 50;
pub const OP_OPT_STR_FREEZE: usize = 51;
pub const OP_OPT_NIL_P: usize = 52;
pub const OP_OPT_STR_UMINUS: usize = 53;
pub const OP_OPT_NEWARRAY_MAX: usize = 54;
pub const OP_OPT_NEWARRAY_MIN: usize = 55;
pub const OP_INVOKESUPER: usize = 56;
pub const OP_INVOKEBLOCK: usize = 57;
pub const OP_LEAVE: usize = 58;
pub const OP_THROW: usize = 59;
pub const OP_JUMP: usize = 60;
pub const OP_BRANCHIF: usize = 61;
pub const OP_BRANCHUNLESS: usize = 62;
pub const OP_BRANCHNIL: usize = 63;
pub const OP_OPT_GETINLINECACHE: usize = 64;
pub const OP_OPT_SETINLINECACHE: usize = 65;
pub const OP_ONCE: usize = 66;
pub const OP_OPT_CASE_DISPATCH: usize = 67;
pub const OP_OPT_PLUS: usize = 68;
pub const OP_OPT_MINUS: usize = 69;
pub const OP_OPT_MULT: usize = 70;
pub const OP_OPT_DIV: usize = 71;
pub const OP_OPT_MOD: usize = 72;
pub const OP_OPT_EQ: usize = 73;
pub const OP_OPT_NEQ: usize = 74;
pub const OP_OPT_LT: usize = 75;
pub const OP_OPT_LE: usize = 76;
pub const OP_OPT_GT: usize = 77;
pub const OP_OPT_GE: usize = 78;
pub const OP_OPT_LTLT: usize = 79;
pub const OP_OPT_AND: usize = 80;
pub const OP_OPT_OR: usize = 81;
pub const OP_OPT_AREF: usize = 82;
pub const OP_OPT_ASET: usize = 83;
pub const OP_OPT_ASET_WITH: usize = 84;
pub const OP_OPT_AREF_WITH: usize = 85;
pub const OP_OPT_LENGTH: usize = 86;
pub const OP_OPT_SIZE: usize = 87;
pub const OP_OPT_EMPTY_P: usize = 88;
pub const OP_OPT_SUCC: usize = 89;
pub const OP_OPT_NOT: usize = 90;
pub const OP_OPT_REGEXPMATCH2: usize = 91;
pub const OP_INVOKEBUILTIN: usize = 92;
pub const OP_OPT_INVOKEBUILTIN_DELEGATE: usize = 93;
pub const OP_OPT_INVOKEBUILTIN_DELEGATE_LEAVE: usize = 94;
pub const OP_GETLOCAL_WC_0: usize = 95;
pub const OP_GETLOCAL_WC_1: usize = 96;
pub const OP_SETLOCAL_WC_0: usize = 97;
pub const OP_SETLOCAL_WC_1: usize = 98;
pub const OP_PUTOBJECT_INT2FIX_0_: usize = 99;
pub const OP_PUTOBJECT_INT2FIX_1_: usize = 100;
// Constants from iseq_inline_constant_cache (IC) and iseq_inline_constant_cache_entry (ICE) in vm_core.h
pub const RUBY_OFFSET_IC_ENTRY: i32 = 0;
pub const RUBY_OFFSET_ICE_VALUE: i32 = 8;
}
pub use manual_defs::*;
pub const VM_INSTRUCTION_SIZE: usize = 202;
#[allow(unused)]
mod vm_opcodes {
// TODO: need to dynamically autogenerate constants for all the YARV opcodes from insns.def
// TODO: typing of these adds unnecessary casting
pub const OP_NOP: usize = 0;
pub const OP_GETLOCAL: usize = 1;
pub const OP_SETLOCAL: usize = 2;
pub const OP_GETBLOCKPARAM: usize = 3;
pub const OP_SETBLOCKPARAM: usize = 4;
pub const OP_GETBLOCKPARAMPROXY: usize = 5;
pub const OP_GETSPECIAL: usize = 6;
pub const OP_SETSPECIAL: usize = 7;
pub const OP_GETINSTANCEVARIABLE: usize = 8;
pub const OP_SETINSTANCEVARIABLE: usize = 9;
pub const OP_GETCLASSVARIABLE: usize = 10;
pub const OP_SETCLASSVARIABLE: usize = 11;
pub const OP_GETCONSTANT: usize = 12;
pub const OP_SETCONSTANT: usize = 13;
pub const OP_GETGLOBAL: usize = 14;
pub const OP_SETGLOBAL: usize = 15;
pub const OP_PUTNIL: usize = 16;
pub const OP_PUTSELF: usize = 17;
pub const OP_PUTOBJECT: usize = 18;
pub const OP_PUTSPECIALOBJECT: usize = 19;
pub const OP_PUTSTRING: usize = 20;
pub const OP_CONCATSTRINGS: usize = 21;
pub const OP_ANYTOSTRING: usize = 22;
pub const OP_TOREGEXP: usize = 23;
pub const OP_INTERN: usize = 24;
pub const OP_NEWARRAY: usize = 25;
pub const OP_NEWARRAYKWSPLAT: usize = 26;
pub const OP_DUPARRAY: usize = 27;
pub const OP_DUPHASH: usize = 28;
pub const OP_EXPANDARRAY: usize = 29;
pub const OP_CONCATARRAY: usize = 30;
pub const OP_SPLATARRAY: usize = 31;
pub const OP_NEWHASH: usize = 32;
pub const OP_NEWRANGE: usize = 33;
pub const OP_POP: usize = 34;
pub const OP_DUP: usize = 35;
pub const OP_DUPN: usize = 36;
pub const OP_SWAP: usize = 37;
pub const OP_TOPN: usize = 38;
pub const OP_SETN: usize = 39;
pub const OP_ADJUSTSTACK: usize = 40;
pub const OP_DEFINED: usize = 41;
pub const OP_CHECKMATCH: usize = 42;
pub const OP_CHECKKEYWORD: usize = 43;
pub const OP_CHECKTYPE: usize = 44;
pub const OP_DEFINECLASS: usize = 45;
pub const OP_DEFINEMETHOD: usize = 46;
pub const OP_DEFINESMETHOD: usize = 47;
pub const OP_SEND: usize = 48;
pub const OP_OPT_SEND_WITHOUT_BLOCK: usize = 49;
pub const OP_OBJTOSTRING: usize = 50;
pub const OP_OPT_STR_FREEZE: usize = 51;
pub const OP_OPT_NIL_P: usize = 52;
pub const OP_OPT_STR_UMINUS: usize = 53;
pub const OP_OPT_NEWARRAY_MAX: usize = 54;
pub const OP_OPT_NEWARRAY_MIN: usize = 55;
pub const OP_INVOKESUPER: usize = 56;
pub const OP_INVOKEBLOCK: usize = 57;
pub const OP_LEAVE: usize = 58;
pub const OP_THROW: usize = 59;
pub const OP_JUMP: usize = 60;
pub const OP_BRANCHIF: usize = 61;
pub const OP_BRANCHUNLESS: usize = 62;
pub const OP_BRANCHNIL: usize = 63;
pub const OP_OPT_GETINLINECACHE: usize = 64;
pub const OP_OPT_SETINLINECACHE: usize = 65;
pub const OP_ONCE: usize = 66;
pub const OP_OPT_CASE_DISPATCH: usize = 67;
pub const OP_OPT_PLUS: usize = 68;
pub const OP_OPT_MINUS: usize = 69;
pub const OP_OPT_MULT: usize = 70;
pub const OP_OPT_DIV: usize = 71;
pub const OP_OPT_MOD: usize = 72;
pub const OP_OPT_EQ: usize = 73;
pub const OP_OPT_NEQ: usize = 74;
pub const OP_OPT_LT: usize = 75;
pub const OP_OPT_LE: usize = 76;
pub const OP_OPT_GT: usize = 77;
pub const OP_OPT_GE: usize = 78;
pub const OP_OPT_LTLT: usize = 79;
pub const OP_OPT_AND: usize = 80;
pub const OP_OPT_OR: usize = 81;
pub const OP_OPT_AREF: usize = 82;
pub const OP_OPT_ASET: usize = 83;
pub const OP_OPT_ASET_WITH: usize = 84;
pub const OP_OPT_AREF_WITH: usize = 85;
pub const OP_OPT_LENGTH: usize = 86;
pub const OP_OPT_SIZE: usize = 87;
pub const OP_OPT_EMPTY_P: usize = 88;
pub const OP_OPT_SUCC: usize = 89;
pub const OP_OPT_NOT: usize = 90;
pub const OP_OPT_REGEXPMATCH2: usize = 91;
pub const OP_INVOKEBUILTIN: usize = 92;
pub const OP_OPT_INVOKEBUILTIN_DELEGATE: usize = 93;
pub const OP_OPT_INVOKEBUILTIN_DELEGATE_LEAVE: usize = 94;
pub const OP_GETLOCAL_WC_0: usize = 95;
pub const OP_GETLOCAL_WC_1: usize = 96;
pub const OP_SETLOCAL_WC_0: usize = 97;
pub const OP_SETLOCAL_WC_1: usize = 98;
pub const OP_PUTOBJECT_INT2FIX_0_: usize = 99;
pub const OP_PUTOBJECT_INT2FIX_1_: usize = 100;
pub const VM_INSTRUCTION_SIZE: usize = 202;
}
pub use vm_opcodes::*;

Просмотреть файл

@ -1,9 +1,6 @@
use crate::asm::*;
use crate::codegen::*;
use crate::core::*;
use crate::cruby::*;
use crate::yjit::yjit_enabled_p;
use std::fmt::Write;
/// Primitive called in yjit.rb
/// Produce a string representing the disassembly for an ISEQ
@ -43,7 +40,7 @@ fn disasm_iseq(iseq: IseqPtr) -> String {
let mut block_list = get_iseq_block_list(iseq);
// Get a list of codeblocks relevant to this iseq
let global_cb = CodegenGlobals::get_inline_cb();
let global_cb = crate::codegen::CodegenGlobals::get_inline_cb();
// Sort the blocks by increasing start addresses
block_list.sort_by(|a, b| {

Просмотреть файл

@ -1,9 +1,3 @@
// Silence dead code warnings until we are done porting YJIT
#![allow(unused_imports)]
#![allow(dead_code)]
#![allow(unused_assignments)]
#![allow(unused_macros)]
// Clippy disagreements
#![allow(clippy::style)] // We are laid back about style
#![allow(clippy::too_many_arguments)] // :shrug:

Просмотреть файл

@ -1,6 +1,8 @@
//! Everything related to the collection of runtime stats in YJIT
//! See the stats feature and the --yjit-stats command-line option
#![allow(dead_code)] // Counters are only used with the stats features
use crate::codegen::CodegenGlobals;
use crate::cruby::*;
use crate::options::*;
@ -12,17 +14,17 @@ static mut EXIT_OP_COUNT: [u64; VM_INSTRUCTION_SIZE] = [0; VM_INSTRUCTION_SIZE];
// Macro to declare the stat counters
macro_rules! make_counters {
($($counter_name:ident,)+) => {
// Struct containing the counter values
/// Struct containing the counter values
#[derive(Default, Debug)]
pub struct Counters { $(pub $counter_name: u64),+ }
// Global counters instance, initialized to zero
/// Global counters instance, initialized to zero
pub static mut COUNTERS: Counters = Counters { $($counter_name: 0),+ };
// Counter names constant
/// Counter names constant
const COUNTER_NAMES: &'static [&'static str] = &[ $(stringify!($counter_name)),+ ];
// Map a counter name string to a counter pointer
/// Map a counter name string to a counter pointer
fn get_counter_ptr(name: &str) -> *mut u64 {
match name {
$( stringify!($counter_name) => { ptr_to_counter!($counter_name) } ),+

Просмотреть файл

@ -1,3 +1,5 @@
#![allow(dead_code)] // Some functions for print debugging in here
use crate::asm::x86_64::*;
use crate::asm::*;
use crate::cruby::*;
@ -50,6 +52,25 @@ impl IntoUsize for u8 {
}
}
/// Compute an offset in bytes of a given struct field
#[allow(unused)]
macro_rules! offset_of {
($struct_type:ty, $field_name:tt) => {{
// This is basically the exact example for
// "creating a pointer to uninitialized data" from `std::ptr::addr_of_mut`.
// We make a dummy local that hopefully is optimized away because we never
// read or write its contents. Doing this dance to avoid UB.
let mut instance = std::mem::MaybeUninit::<$struct_type>::uninit();
let base_ptr = instance.as_mut_ptr();
let field_ptr = unsafe { std::ptr::addr_of_mut!((*base_ptr).$field_name) };
(field_ptr as usize) - (base_ptr as usize)
}};
}
#[allow(unused)]
pub(crate) use offset_of;
#[cfg(test)]
mod tests {
#[test]
@ -66,6 +87,18 @@ mod tests {
let max: usize = u32::MAX.as_usize();
assert_eq!(max, u32::MAX.try_into().unwrap());
}
#[test]
fn test_offset_of() {
#[repr(C)]
struct Foo {
a: u8,
b: u64,
}
assert_eq!(0, offset_of!(Foo, a), "C99 6.7.2.1p13 says no padding at the front");
assert_eq!(8, offset_of!(Foo, b), "ABI dependent, but should hold");
}
}
// TODO: we may want to move this function into yjit.c, maybe add a convenient Rust-side wrapper
@ -170,7 +203,7 @@ pub fn print_value(cb: &mut CodeBlock, opnd: X86Opnd) {
pop_regs(cb);
}
// Generate code to print constant string to stdout
/// Generate code to print constant string to stdout
pub fn print_str(cb: &mut CodeBlock, str: &str) {
extern "sysv64" fn print_str_cfun(ptr: *const u8, num_bytes: usize) {
unsafe {

Просмотреть файл

@ -86,8 +86,7 @@ pub extern "C" fn rb_yjit_simulate_oom_bang(_ec: EcPtr, _ruby_self: VALUE) -> VA
}
// Enabled in debug mode only for security
#[cfg(debug_assertions)]
{
if cfg!(debug_assertions) {
let cb = CodegenGlobals::get_inline_cb();
let ocb = CodegenGlobals::get_outlined_cb().unwrap();
cb.set_pos(cb.get_mem_size() - 1);