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:
parent
7c039e423c
commit
5c843a1a6e
Notes:
git
2022-04-30 07:20:44 +09:00
Merged-By: maximecb <maximecb@ruby-lang.org>
@ -1,6 +1,8 @@
|
|||||||
use std::collections::BTreeMap;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
#[cfg(feature = "asm_comments")]
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
// Lots of manual vertical alignment in there that rustfmt doesn't handle well.
|
// Lots of manual vertical alignment in there that rustfmt doesn't handle well.
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub mod x86_64;
|
pub mod x86_64;
|
||||||
@ -23,6 +25,7 @@ impl CodePtr {
|
|||||||
*ptr as i64
|
*ptr as i64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
fn into_usize(&self) -> usize {
|
fn into_usize(&self) -> usize {
|
||||||
let CodePtr(ptr) = self;
|
let CodePtr(ptr) = self;
|
||||||
*ptr as usize
|
*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
|
// 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 {
|
pub struct CodeBlock {
|
||||||
// Block of non-executable memory used for dummy code blocks
|
// Block of non-executable memory used for dummy code blocks
|
||||||
// This memory is owned by this block and lives as long as the block
|
// This memory is owned by this block and lives as long as the block
|
||||||
|
#[allow(unused)]
|
||||||
dummy_block: Vec<u8>,
|
dummy_block: Vec<u8>,
|
||||||
|
|
||||||
// Pointer to memory we are writing into
|
// Pointer to memory we are writing into
|
||||||
@ -110,6 +99,7 @@ pub struct CodeBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CodeBlock {
|
impl CodeBlock {
|
||||||
|
#[cfg(test)]
|
||||||
pub fn new_dummy(mem_size: usize) -> Self {
|
pub fn new_dummy(mem_size: usize) -> Self {
|
||||||
// Allocate some non-executable memory
|
// Allocate some non-executable memory
|
||||||
let mut dummy_block = vec![0; mem_size];
|
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 {
|
pub fn new(mem_block: *mut u8, mem_size: usize, page_size: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
dummy_block: vec![0; 0],
|
dummy_block: vec![0; 0],
|
||||||
@ -175,11 +166,6 @@ impl CodeBlock {
|
|||||||
pub fn comments_at(&self, pos: usize) -> Option<&Vec<String>> {
|
pub fn comments_at(&self, pos: usize) -> Option<&Vec<String>> {
|
||||||
self.asm_comments.get(&pos)
|
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 {
|
pub fn get_mem_size(&self) -> usize {
|
||||||
self.mem_size
|
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
|
// Write multiple bytes starting from the current position
|
||||||
pub fn write_bytes(&mut self, bytes: &[u8]) {
|
pub fn write_bytes(&mut self, bytes: &[u8]) {
|
||||||
for byte in bytes {
|
for byte in bytes {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use std::io::{Result, Write};
|
#![allow(dead_code)] // For instructions we don't currently generate
|
||||||
use std::mem;
|
|
||||||
use crate::asm::*;
|
use crate::asm::*;
|
||||||
|
|
||||||
// Import the assembler tests module
|
// Import the assembler tests module
|
||||||
|
@ -7,7 +7,7 @@ use std::fmt;
|
|||||||
impl<'a> fmt::LowerHex for super::CodeBlock {
|
impl<'a> fmt::LowerHex for super::CodeBlock {
|
||||||
fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
|
||||||
for pos in 0..self.write_pos {
|
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))?;
|
fmtr.write_fmt(format_args!("{:02x}", byte))?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -28,7 +28,7 @@ pub const REG0: X86Opnd = RAX;
|
|||||||
pub const REG0_32: X86Opnd = EAX;
|
pub const REG0_32: X86Opnd = EAX;
|
||||||
pub const REG0_8: X86Opnd = AL;
|
pub const REG0_8: X86Opnd = AL;
|
||||||
pub const REG1: X86Opnd = RCX;
|
pub const REG1: X86Opnd = RCX;
|
||||||
pub const REG1_32: X86Opnd = ECX;
|
// pub const REG1_32: X86Opnd = ECX;
|
||||||
|
|
||||||
/// Status returned by code generation functions
|
/// Status returned by code generation functions
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
@ -106,10 +106,6 @@ impl JITState {
|
|||||||
self.opcode
|
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) {
|
pub fn add_gc_object_offset(self: &mut JITState, ptr_offset: u32) {
|
||||||
let mut gc_obj_vec: RefMut<_> = self.block.borrow_mut();
|
let mut gc_obj_vec: RefMut<_> = self.block.borrow_mut();
|
||||||
gc_obj_vec.add_gc_object_offset(ptr_offset);
|
gc_obj_vec.add_gc_object_offset(ptr_offset);
|
||||||
@ -118,15 +114,11 @@ impl JITState {
|
|||||||
pub fn get_pc(self: &JITState) -> *mut VALUE {
|
pub fn get_pc(self: &JITState) -> *mut VALUE {
|
||||||
self.pc
|
self.pc
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_pc(self: &mut JITState, pc: *mut VALUE) {
|
|
||||||
self.pc = pc;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::codegen::JCCKinds::*;
|
use crate::codegen::JCCKinds::*;
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types, unused)]
|
||||||
pub enum JCCKinds {
|
pub enum JCCKinds {
|
||||||
JCC_JNE,
|
JCC_JNE,
|
||||||
JCC_JNZ,
|
JCC_JNZ,
|
||||||
@ -749,8 +741,7 @@ pub fn gen_single_block(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// In debug mode, verify our existing assumption
|
// In debug mode, verify our existing assumption
|
||||||
#[cfg(debug_assertions)]
|
if cfg!(debug_assertions) && get_option!(verify_ctx) && jit_at_current_insn(&jit) {
|
||||||
if get_option!(verify_ctx) && jit_at_current_insn(&jit) {
|
|
||||||
verify_ctx(&jit, &ctx);
|
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 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;
|
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);
|
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 mut value_array: [u64; 2] = [0, Qtrue.into()];
|
||||||
let pc: *mut VALUE = &mut value_array as *mut u64 as *mut VALUE;
|
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);
|
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
|
// The Fixnum 7 is encoded as 7 * 2 + 1, or 15
|
||||||
let mut value_array: [u64; 2] = [0, 15];
|
let mut value_array: [u64; 2] = [0, 15];
|
||||||
let pc: *mut VALUE = &mut value_array as *mut u64 as *mut VALUE;
|
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);
|
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 mut value_array: [u64; 2] = [0, 2];
|
||||||
let pc: *mut VALUE = &mut value_array as *mut u64 as *mut VALUE;
|
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);
|
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 mut value_array: [u64; 2] = [0, 1];
|
||||||
let pc: *mut VALUE = &mut value_array as *mut u64 as *mut VALUE;
|
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);
|
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 mut value_array: [u64; 3] = [0, 2, 0];
|
||||||
let pc: *mut VALUE = &mut value_array as *mut u64 as *mut VALUE;
|
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);
|
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::hash::{Hash, Hasher};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::ptr;
|
use std::rc::{Rc};
|
||||||
use std::rc::{Rc, Weak};
|
|
||||||
use InsnOpnd::*;
|
use InsnOpnd::*;
|
||||||
use TempMapping::*;
|
use TempMapping::*;
|
||||||
|
|
||||||
@ -35,7 +34,10 @@ pub enum Type {
|
|||||||
Array,
|
Array,
|
||||||
Hash,
|
Hash,
|
||||||
ImmSymbol,
|
ImmSymbol,
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
HeapSymbol,
|
HeapSymbol,
|
||||||
|
|
||||||
String,
|
String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,6 +244,7 @@ struct Branch {
|
|||||||
end_addr: Option<CodePtr>,
|
end_addr: Option<CodePtr>,
|
||||||
|
|
||||||
// Context right after the branch instruction
|
// Context right after the branch instruction
|
||||||
|
#[allow(unused)] // set but not read at the moment
|
||||||
src_ctx: Context,
|
src_ctx: Context,
|
||||||
|
|
||||||
// Branch target blocks and their contexts
|
// 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.
|
/// Get the payload object associated with an iseq. Create one if none exists.
|
||||||
fn get_iseq_payload(iseq: IseqPtr) -> &'static mut IseqPayload {
|
fn get_iseq_payload(iseq: IseqPtr) -> &'static mut IseqPayload {
|
||||||
use core::ffi::c_void;
|
|
||||||
type VoidPtr = *mut c_void;
|
type VoidPtr = *mut c_void;
|
||||||
|
|
||||||
let payload_non_null = unsafe {
|
let payload_non_null = unsafe {
|
||||||
@ -799,10 +801,12 @@ impl Block {
|
|||||||
self.ctx
|
self.ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn get_start_addr(&self) -> Option<CodePtr> {
|
pub fn get_start_addr(&self) -> Option<CodePtr> {
|
||||||
self.start_addr
|
self.start_addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn get_end_addr(&self) -> Option<CodePtr> {
|
pub fn get_end_addr(&self) -> Option<CodePtr> {
|
||||||
self.end_addr
|
self.end_addr
|
||||||
}
|
}
|
||||||
@ -1018,11 +1022,7 @@ impl Context {
|
|||||||
|
|
||||||
/// Get the currently tracked type for a local variable
|
/// Get the currently tracked type for a local variable
|
||||||
pub fn get_local_type(&self, idx: usize) -> Type {
|
pub fn get_local_type(&self, idx: usize) -> Type {
|
||||||
if idx > MAX_LOCAL_TYPES {
|
*self.local_types.get(idx).unwrap_or(&Type::Unknown)
|
||||||
return Type::Unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.local_types[idx];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Upgrade (or "learn") the type of an instruction operand
|
/// Upgrade (or "learn") the type of an instruction operand
|
||||||
@ -1251,6 +1251,7 @@ impl Context {
|
|||||||
impl BlockId {
|
impl BlockId {
|
||||||
/// Print Ruby source location for debugging
|
/// Print Ruby source location for debugging
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn dump_src_loc(&self) {
|
pub fn dump_src_loc(&self) {
|
||||||
unsafe { rb_yjit_dump_iseq_loc(self.iseq, self.idx) }
|
unsafe { rb_yjit_dump_iseq_loc(self.iseq, self.idx) }
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@
|
|||||||
|
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use std::ffi::CString;
|
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};
|
use std::panic::{catch_unwind, UnwindSafe};
|
||||||
|
|
||||||
// We check that we can do this with the configure script and a couple of
|
// 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.
|
/// shifted 1s but not explicitly an enum.
|
||||||
pub type RedefinitionFlag = u32;
|
pub type RedefinitionFlag = u32;
|
||||||
|
|
||||||
// Textually include output from rust-bindgen as suggested by its user guide.
|
#[allow(dead_code)]
|
||||||
include!("cruby_bindings.inc.rs");
|
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
|
// 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.
|
// 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:
|
// TODO:
|
||||||
// Temporary, these external bindings will likely be auto-generated
|
// Temporary, these external bindings will likely be auto-generated
|
||||||
// and textually included in this file
|
// and textually included in this file
|
||||||
|
#[cfg_attr(test, allow(unused))] // We don't link against C code when testing
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "rb_yjit_alloc_exec_mem"] // we can rename functions with this attribute
|
#[link_name = "rb_yjit_alloc_exec_mem"] // we can rename functions with this attribute
|
||||||
pub fn alloc_exec_mem(mem_size: u32) -> *mut u8;
|
pub fn alloc_exec_mem(mem_size: u32) -> *mut u8;
|
||||||
@ -135,9 +141,6 @@ extern "C" {
|
|||||||
#[link_name = "rb_get_cme_def_type"]
|
#[link_name = "rb_get_cme_def_type"]
|
||||||
pub fn get_cme_def_type(cme: *const rb_callable_method_entry_t) -> rb_method_type_t;
|
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"]
|
#[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;
|
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"]
|
#[link_name = "rb_get_iseq_body_iseq_encoded"]
|
||||||
pub fn get_iseq_body_iseq_encoded(iseq: IseqPtr) -> *mut VALUE;
|
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"]
|
#[link_name = "rb_get_iseq_body_stack_max"]
|
||||||
pub fn get_iseq_body_stack_max(iseq: IseqPtr) -> c_uint;
|
pub fn get_iseq_body_stack_max(iseq: IseqPtr) -> c_uint;
|
||||||
|
|
||||||
@ -272,8 +272,6 @@ extern "C" {
|
|||||||
pub fn rb_aliased_callable_method_entry(
|
pub fn rb_aliased_callable_method_entry(
|
||||||
me: *const rb_callable_method_entry_t,
|
me: *const rb_callable_method_entry_t,
|
||||||
) -> *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_getclassvariable(iseq: IseqPtr, cfp: CfpPtr, id: ID, ic: ICVARC) -> VALUE;
|
||||||
pub fn rb_vm_setclassvariable(
|
pub fn rb_vm_setclassvariable(
|
||||||
iseq: IseqPtr,
|
iseq: IseqPtr,
|
||||||
@ -299,12 +297,6 @@ extern "C" {
|
|||||||
#[link_name = "rb_METHOD_ENTRY_VISI"]
|
#[link_name = "rb_METHOD_ENTRY_VISI"]
|
||||||
pub fn METHOD_ENTRY_VISI(me: *const rb_callable_method_entry_t) -> rb_method_visibility_t;
|
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;
|
pub fn rb_str_bytesize(str: VALUE) -> VALUE;
|
||||||
|
|
||||||
#[link_name = "rb_RCLASS_ORIGIN"]
|
#[link_name = "rb_RCLASS_ORIGIN"]
|
||||||
@ -607,6 +599,7 @@ impl From<VALUE> for i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Produce a Ruby string from a Rust string slice
|
/// Produce a Ruby string from a Rust string slice
|
||||||
|
#[cfg(feature = "asm_comments")]
|
||||||
pub fn rust_str_to_ruby(str: &str) -> VALUE {
|
pub fn rust_str_to_ruby(str: &str) -> VALUE {
|
||||||
unsafe { rb_utf8_str_new(str.as_ptr() as *const i8, str.len() as i64) }
|
unsafe { rb_utf8_str_new(str.as_ptr() as *const i8, str.len() as i64) }
|
||||||
}
|
}
|
||||||
@ -670,7 +663,7 @@ where
|
|||||||
Err(_) => {
|
Err(_) => {
|
||||||
// Theoretically we can recover from some of these panics,
|
// Theoretically we can recover from some of these panics,
|
||||||
// but it's too late if the unwind reaches here.
|
// but it's too late if the unwind reaches here.
|
||||||
use std::{io, process, str};
|
use std::{process, str};
|
||||||
|
|
||||||
let _ = catch_unwind(|| {
|
let _ = catch_unwind(|| {
|
||||||
// IO functions can panic too.
|
// IO functions can panic too.
|
||||||
@ -699,221 +692,231 @@ pub const Qtrue: VALUE = VALUE(20);
|
|||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
pub const Qundef: VALUE = VALUE(52);
|
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_SYMBOL_FLAG: usize = 0x0c;
|
||||||
pub const RUBY_LONG_MAX: isize = std::os::raw::c_long::MAX as isize;
|
|
||||||
|
|
||||||
pub const RUBY_FIXNUM_MIN: isize = RUBY_LONG_MIN / 2;
|
pub const RUBY_LONG_MIN: isize = std::os::raw::c_long::MIN as isize;
|
||||||
pub const RUBY_FIXNUM_MAX: isize = RUBY_LONG_MAX / 2;
|
pub const RUBY_LONG_MAX: isize = std::os::raw::c_long::MAX as isize;
|
||||||
pub const RUBY_FIXNUM_FLAG: usize = 0x1;
|
|
||||||
|
|
||||||
pub const RUBY_FLONUM_FLAG: usize = 0x2;
|
pub const RUBY_FIXNUM_MIN: isize = RUBY_LONG_MIN / 2;
|
||||||
pub const RUBY_FLONUM_MASK: usize = 0x3;
|
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 RUBY_SPECIAL_SHIFT: usize = 8;
|
||||||
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;
|
|
||||||
|
|
||||||
// From vm_callinfo.h
|
// Constants from vm_core.h
|
||||||
pub const VM_CALL_ARGS_SPLAT: u32 = 1 << VM_CALL_ARGS_SPLAT_bit;
|
pub const VM_SPECIAL_OBJECT_VMCORE: usize = 0x1;
|
||||||
pub const VM_CALL_ARGS_BLOCKARG: u32 = 1 << VM_CALL_ARGS_BLOCKARG_bit;
|
pub const VM_ENV_DATA_INDEX_SPECVAL: isize = -1;
|
||||||
pub const VM_CALL_FCALL: u32 = 1 << VM_CALL_FCALL_bit;
|
pub const VM_ENV_DATA_INDEX_FLAGS: isize = 0;
|
||||||
pub const VM_CALL_KWARG: u32 = 1 << VM_CALL_KWARG_bit;
|
pub const VM_ENV_DATA_SIZE: usize = 3;
|
||||||
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 SIZEOF_VALUE: usize = 8;
|
// From vm_callinfo.h
|
||||||
pub const SIZEOF_VALUE_I32: i32 = SIZEOF_VALUE as i32;
|
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 RUBY_FL_SINGLETON: usize = RUBY_FL_USER_0;
|
||||||
pub const ROBJECT_EMBED_LEN_MAX: usize = 3; // This is a complex calculation in ruby/internal/core/robject.h
|
|
||||||
|
|
||||||
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 RMODULE_IS_REFINEMENT: usize = RUBY_FL_USER_3;
|
||||||
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);
|
|
||||||
|
|
||||||
// Constants from include/ruby/internal/core/rarray.h
|
// Constants from include/ruby/internal/fl_type.h
|
||||||
pub const RARRAY_EMBED_FLAG: usize = RUBY_FL_USER_1;
|
pub const RUBY_FL_USHIFT: usize = 12;
|
||||||
pub const RARRAY_EMBED_LEN_SHIFT: usize = RUBY_FL_USHIFT + 3;
|
pub const RUBY_FL_USER_0: usize = 1 << (RUBY_FL_USHIFT + 0);
|
||||||
pub const RARRAY_EMBED_LEN_MASK: usize = RUBY_FL_USER_3 | RUBY_FL_USER_4;
|
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
|
// Constants from include/ruby/internal/core/rarray.h
|
||||||
pub const RSTRUCT_EMBED_LEN_MASK: usize = RUBY_FL_USER_2 | RUBY_FL_USER_1;
|
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
|
// From internal/struct.h
|
||||||
pub const ISEQ_TRANSLATED: usize = RUBY_FL_USER_7;
|
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
|
// From iseq.h
|
||||||
// redeclare all the Ruby C structs and write our own offsetof macro. For now, we use constants.
|
pub const ISEQ_TRANSLATED: usize = RUBY_FL_USER_7;
|
||||||
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_RSTRUCT_AS_HEAP_PTR: i32 = 24; // struct RStruct, subfield "as.heap.ptr"
|
// We'll need to encode a lot of Ruby struct/field offsets as constants unless we want to
|
||||||
pub const RUBY_OFFSET_RSTRUCT_AS_ARY: i32 = 16; // struct RStruct, subfield "as.ary"
|
// 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_RSTRUCT_AS_HEAP_PTR: i32 = 24; // struct RStruct, subfield "as.heap.ptr"
|
||||||
pub const RUBY_OFFSET_ROBJECT_AS_HEAP_NUMIV: i32 = 16; // struct RObject, subfield "as.heap.numiv"
|
pub const RUBY_OFFSET_RSTRUCT_AS_ARY: i32 = 16; // struct RStruct, subfield "as.ary"
|
||||||
pub const RUBY_OFFSET_ROBJECT_AS_HEAP_IVPTR: i32 = 24; // struct RObject, subfield "as.heap.ivptr"
|
|
||||||
|
|
||||||
// Constants from rb_control_frame_t vm_core.h
|
pub const RUBY_OFFSET_ROBJECT_AS_ARY: i32 = 16; // struct RObject, subfield "as.ary"
|
||||||
pub const RUBY_OFFSET_CFP_PC: i32 = 0;
|
pub const RUBY_OFFSET_ROBJECT_AS_HEAP_NUMIV: i32 = 16; // struct RObject, subfield "as.heap.numiv"
|
||||||
pub const RUBY_OFFSET_CFP_SP: i32 = 8;
|
pub const RUBY_OFFSET_ROBJECT_AS_HEAP_IVPTR: i32 = 24; // struct RObject, subfield "as.heap.ivptr"
|
||||||
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_execution_context_t vm_core.h
|
// Constants from rb_control_frame_t vm_core.h
|
||||||
pub const RUBY_OFFSET_EC_CFP: i32 = 16;
|
pub const RUBY_OFFSET_CFP_PC: i32 = 0;
|
||||||
pub const RUBY_OFFSET_EC_INTERRUPT_FLAG: i32 = 32; // rb_atomic_t (u32)
|
pub const RUBY_OFFSET_CFP_SP: i32 = 8;
|
||||||
pub const RUBY_OFFSET_EC_INTERRUPT_MASK: i32 = 36; // rb_atomic_t (u32)
|
pub const RUBY_OFFSET_CFP_ISEQ: i32 = 16;
|
||||||
pub const RUBY_OFFSET_EC_THREAD_PTR: i32 = 48;
|
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
|
// Constants from rb_execution_context_t vm_core.h
|
||||||
pub const RUBY_OFFSET_THREAD_SELF: i32 = 16;
|
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
|
// Constants from rb_thread_t in vm_core.h
|
||||||
pub const RUBY_OFFSET_IC_ENTRY: i32 = 0;
|
pub const RUBY_OFFSET_THREAD_SELF: i32 = 16;
|
||||||
pub const RUBY_OFFSET_ICE_VALUE: i32 = 8;
|
|
||||||
|
|
||||||
// TODO: need to dynamically autogenerate constants for all the YARV opcodes from insns.def
|
// Constants from iseq_inline_constant_cache (IC) and iseq_inline_constant_cache_entry (ICE) in vm_core.h
|
||||||
// TODO: typing of these adds unnecessary casting
|
pub const RUBY_OFFSET_IC_ENTRY: i32 = 0;
|
||||||
pub const OP_NOP: usize = 0;
|
pub const RUBY_OFFSET_ICE_VALUE: i32 = 8;
|
||||||
pub const OP_GETLOCAL: usize = 1;
|
}
|
||||||
pub const OP_SETLOCAL: usize = 2;
|
pub use manual_defs::*;
|
||||||
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;
|
#[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::core::*;
|
||||||
use crate::cruby::*;
|
use crate::cruby::*;
|
||||||
use crate::yjit::yjit_enabled_p;
|
use crate::yjit::yjit_enabled_p;
|
||||||
use std::fmt::Write;
|
|
||||||
|
|
||||||
/// Primitive called in yjit.rb
|
/// Primitive called in yjit.rb
|
||||||
/// Produce a string representing the disassembly for an ISEQ
|
/// 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);
|
let mut block_list = get_iseq_block_list(iseq);
|
||||||
|
|
||||||
// Get a list of codeblocks relevant to this 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
|
// Sort the blocks by increasing start addresses
|
||||||
block_list.sort_by(|a, b| {
|
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
|
// Clippy disagreements
|
||||||
#![allow(clippy::style)] // We are laid back about style
|
#![allow(clippy::style)] // We are laid back about style
|
||||||
#![allow(clippy::too_many_arguments)] // :shrug:
|
#![allow(clippy::too_many_arguments)] // :shrug:
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
//! Everything related to the collection of runtime stats in YJIT
|
//! Everything related to the collection of runtime stats in YJIT
|
||||||
//! See the stats feature and the --yjit-stats command-line option
|
//! 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::codegen::CodegenGlobals;
|
||||||
use crate::cruby::*;
|
use crate::cruby::*;
|
||||||
use crate::options::*;
|
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 to declare the stat counters
|
||||||
macro_rules! make_counters {
|
macro_rules! make_counters {
|
||||||
($($counter_name:ident,)+) => {
|
($($counter_name:ident,)+) => {
|
||||||
// Struct containing the counter values
|
/// Struct containing the counter values
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct Counters { $(pub $counter_name: u64),+ }
|
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),+ };
|
pub static mut COUNTERS: Counters = Counters { $($counter_name: 0),+ };
|
||||||
|
|
||||||
// Counter names constant
|
/// Counter names constant
|
||||||
const COUNTER_NAMES: &'static [&'static str] = &[ $(stringify!($counter_name)),+ ];
|
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 {
|
fn get_counter_ptr(name: &str) -> *mut u64 {
|
||||||
match name {
|
match name {
|
||||||
$( stringify!($counter_name) => { ptr_to_counter!($counter_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::x86_64::*;
|
||||||
use crate::asm::*;
|
use crate::asm::*;
|
||||||
use crate::cruby::*;
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
@ -66,6 +87,18 @@ mod tests {
|
|||||||
let max: usize = u32::MAX.as_usize();
|
let max: usize = u32::MAX.as_usize();
|
||||||
assert_eq!(max, u32::MAX.try_into().unwrap());
|
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
|
// 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);
|
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) {
|
pub fn print_str(cb: &mut CodeBlock, str: &str) {
|
||||||
extern "sysv64" fn print_str_cfun(ptr: *const u8, num_bytes: usize) {
|
extern "sysv64" fn print_str_cfun(ptr: *const u8, num_bytes: usize) {
|
||||||
unsafe {
|
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
|
// Enabled in debug mode only for security
|
||||||
#[cfg(debug_assertions)]
|
if cfg!(debug_assertions) {
|
||||||
{
|
|
||||||
let cb = CodegenGlobals::get_inline_cb();
|
let cb = CodegenGlobals::get_inline_cb();
|
||||||
let ocb = CodegenGlobals::get_outlined_cb().unwrap();
|
let ocb = CodegenGlobals::get_outlined_cb().unwrap();
|
||||||
cb.set_pos(cb.get_mem_size() - 1);
|
cb.set_pos(cb.get_mem_size() - 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user