Skip to content

Commit

Permalink
Fix givtbl handling
Browse files Browse the repository at this point in the history
  • Loading branch information
wks committed Dec 14, 2023
1 parent 9706f79 commit a59a60a
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 2 deletions.
15 changes: 15 additions & 0 deletions mmtk/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ pub const GC_THREAD_KIND_WORKER: libc::c_int = 1;
const HAS_MOVED_GIVTBL: usize = 1 << 63;
const HIDDEN_SIZE_MASK: usize = 0x0000FFFFFFFFFFFF;

// Should keep in sync with C code.
const RUBY_FL_EXIVAR: usize = 1 << 10;

/// Provide convenient methods for accessing Ruby objects.
/// TODO: Wrap C functions in `RubyUpcalls` as Rust-friendly methods.
pub struct RubyObjectAccess {
Expand Down Expand Up @@ -68,6 +71,18 @@ impl RubyObjectAccess {
self.update_hidden_field(|old| old & !HIDDEN_SIZE_MASK | size & HIDDEN_SIZE_MASK);
}

fn flags_field(&self) -> Address {
self.objref.to_raw_address()
}

pub fn load_flags(&self) -> usize {
unsafe { self.flags_field().load::<usize>() }
}

pub fn has_exivar_flag(&self) -> bool {
(self.load_flags() & RUBY_FL_EXIVAR) != 0
}

pub fn has_moved_givtbl(&self) -> bool {
(self.load_hidden_field() & HAS_MOVED_GIVTBL) != 0
}
Expand Down
2 changes: 1 addition & 1 deletion mmtk/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ pub extern "C" fn mmtk_register_ppps(objects: *const ObjectReference, len: usize
}

#[no_mangle]
pub extern "C" fn mmtk_get_givtbl(object: ObjectReference) -> *mut libc::c_void {
pub extern "C" fn mmtk_get_givtbl_during_gc(object: ObjectReference) -> *mut libc::c_void {
let acc = RubyObjectAccess::from_objref(object);
acc.get_givtbl()
}
Expand Down
6 changes: 5 additions & 1 deletion mmtk/src/object_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ impl ObjectModel<Ruby> for VMObjectModel {
copy_context: &mut GCWorkerCopyContext<Ruby>,
) -> ObjectReference {
let from_acc = RubyObjectAccess::from_objref(from);
let maybe_givtbl = from_acc.get_original_givtbl();
let maybe_givtbl = from_acc.has_exivar_flag().then(|| {
from_acc
.get_original_givtbl()
.unwrap_or_else(|| panic!("Object {} has FL_EXIVAR but no givtbl.", from))
});
let from_start = from_acc.obj_start();
let object_size = from_acc.object_size();
let to_start = copy_context.alloc_copy(from, object_size, MIN_OBJ_ALIGN, 0, semantics);
Expand Down

0 comments on commit a59a60a

Please sign in to comment.