Skip to content

Commit

Permalink
feat: add quickjs_common to maintain dependecy list
Browse files Browse the repository at this point in the history
  • Loading branch information
shiqimei committed Jun 13, 2023
1 parent 7a8cb7a commit 0643e95
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 7 deletions.
7 changes: 7 additions & 0 deletions src/crates/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion src/crates/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ resolver = "2"
members = [
"quickjs",
"quickjs_gc",
"quickjs_backtrace"
"quickjs_backtrace",
"quickjs_common"
]
3 changes: 1 addition & 2 deletions src/crates/quickjs_backtrace/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ version = "0.1.0"
edition = "2021"

[dependencies]
backtrace = "0.3.67"
libc = "0.2.146"
quickjs_common = { path = "../quickjs_common" }
7 changes: 3 additions & 4 deletions src/crates/quickjs_backtrace/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
extern crate backtrace;
extern crate libc;
extern crate quickjs_common;

use backtrace::Backtrace;
use libc::c_char;
use quickjs_common::backtrace::Backtrace;
use quickjs_common::libc::c_char;
use std::ffi::CString;

/// Function that captures a backtrace and returns it as a C-compatible string.
Expand Down
10 changes: 10 additions & 0 deletions src/crates/quickjs_common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "quickjs_common"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
backtrace = "0.3.67"
libc = "0.2.146"
2 changes: 2 additions & 0 deletions src/crates/quickjs_common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub use libc;
pub use backtrace;
3 changes: 3 additions & 0 deletions src/crates/quickjs_gc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#![feature(offset_of)]

mod record;

use std::mem::offset_of;

/// Represents a node in a doubly linked list.
Expand Down
58 changes: 58 additions & 0 deletions src/crates/quickjs_gc/src/record.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use std::mem::offset_of;
use backtrace::Backtrace;
use crate::{JSGCObjectHeader, ListHead, print_gc_objects};

// Global GC objects map
lazy_static::lazy_static! {
static ref GC_OBJECTS: Mutex<HashMap<*const JSGCObjectHeader, Backtrace>> = Mutex::new(HashMap::new());
}

/// Records the creation of a new GC object in the global map.
///
/// # Safety
///
/// This function is `unsafe` because it takes a raw pointer.
/// The caller must ensure that `gc_object` is a valid pointer.
#[no_mangle]
pub unsafe extern "C" fn record_gc_object_creation(gc_object: *mut JSGCObjectHeader) {
let bt = Backtrace::new();
GC_OBJECTS.lock().unwrap().insert(gc_object, bt);
}

/// Prints the details of leaked GC objects, if any.
#[no_mangle]
pub extern "C" fn get_leaked_gc_objects() {
unsafe {
print_gc_objects(list_head);

// Leverage the `print_gc_objects` function to access each object
// in the list, and compare it with the objects in the map.
let map = GC_OBJECTS.lock().unwrap();
for (&gc_object, bt) in map.iter() {
if !is_in_list(list_head, gc_object) {
// This object is not in the list, so it must be leaked.
println!("Leaked GC object at address {:?} with backtrace:\n{:?}", gc_object, bt);
}
}
}
}

/// Checks if the given GC object is in the list.
///
/// # Safety
///
/// This function is `unsafe` because it takes a raw pointer and dereferences it.
/// The caller must ensure that both `list_head` and `gc_object` are valid pointers.
unsafe fn is_in_list(list_head: *mut ListHead, gc_object: *const JSGCObjectHeader) -> bool {
let mut cur_node = (*list_head).next();
while cur_node as *const _ != list_head {
let cur_gc_object = (cur_node as *mut ListHead as *mut u8)
.offset(-(offset_of!(JSGCObjectHeader, link) as isize))
as *mut JSGCObjectHeader;
if cur_gc_object == gc_object {
return true;
}
cur_node = (*cur_node).next();
}
false
}

0 comments on commit 0643e95

Please sign in to comment.