Skip to content

Commit 2a47f81

Browse files
Merge pull request #634 from theseus-rs/isolate-vm-gc
fix: isolate GC to VM instance
2 parents 5a2f590 + 8c5853d commit 2a47f81

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1855
-1069
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ristretto_classloader/src/field.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,9 @@ impl FieldKey for &str {
316316
#[cfg(test)]
317317
mod tests {
318318
use super::*;
319+
use crate::Reference;
319320
use ristretto_classfile::FieldAccessFlags;
321+
use ristretto_gc::GarbageCollector;
320322

321323
#[test]
322324
fn test_field_new() {
@@ -447,7 +449,8 @@ mod tests {
447449
"test".to_string(),
448450
vec![],
449451
);
450-
let value: Value = vec![42i32].into();
452+
let collector = GarbageCollector::new();
453+
let value = Value::new_object(&collector, Reference::from(vec![42i32]));
451454
field.check_value(&value)?;
452455
Ok(())
453456
}

ristretto_classloader/src/object.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -713,9 +713,15 @@ impl PartialEq for Object {
713713
#[cfg(test)]
714714
mod tests {
715715
use super::*;
716+
use crate::Reference;
716717
use crate::runtime;
718+
use ristretto_gc::GarbageCollector;
717719
use std::hash::DefaultHasher;
718720

721+
fn test_ref(reference: impl Into<Reference>) -> Value {
722+
Value::new_object(&GarbageCollector::new(), reference.into())
723+
}
724+
719725
async fn java8_string_class() -> Result<Arc<Class>> {
720726
let (_java_home, _java_version, class_loader) =
721727
runtime::version_class_loader("8.472.08.1").await?;
@@ -911,7 +917,7 @@ mod tests {
911917
let mut object = Object::new(class)?;
912918
#[expect(clippy::cast_possible_wrap)]
913919
let string_bytes: Vec<i8> = "foo".as_bytes().to_vec().iter().map(|&b| b as i8).collect();
914-
let string_value = Value::from(string_bytes);
920+
let string_value = test_ref(string_bytes);
915921
object.set_value("value", string_value)?;
916922
assert_eq!("String(\"foo\")", object.to_string());
917923
Ok(())
@@ -928,12 +934,12 @@ mod tests {
928934
.iter()
929935
.map(|&b| b as i8)
930936
.collect();
931-
let string_value = Value::from(string_bytes);
937+
let string_value = test_ref(string_bytes);
932938
string_object.set_value("value", string_value)?;
933939

934940
let class = load_class("java.lang.Class").await?;
935941
let mut object = Object::new(class)?;
936-
object.set_value("name", Value::from(string_object))?;
942+
object.set_value("name", test_ref(string_object))?;
937943
assert_eq!("Class(java.lang.Integer)", object.to_string());
938944
Ok(())
939945
}
@@ -1116,7 +1122,7 @@ mod tests {
11161122
.iter()
11171123
.map(|&b| b as char)
11181124
.collect();
1119-
let string_value = Value::from(string_chars);
1125+
let string_value = test_ref(string_chars);
11201126
object.set_value("value", string_value)?;
11211127
let result = object.as_string()?;
11221128
assert_eq!("foo".to_string(), result);
@@ -1127,7 +1133,7 @@ mod tests {
11271133
async fn test_as_string_java8_invalid_byte_array_value() -> Result<()> {
11281134
let class = java8_string_class().await?;
11291135
let mut object = Object::new(class)?;
1130-
let string_value = Value::from(Vec::<i32>::new());
1136+
let string_value = test_ref(Vec::<i32>::new());
11311137
object.set_value("value", string_value)?;
11321138
let result = object.as_string();
11331139
assert!(matches!(result, Err(InvalidValueType(_))));
@@ -1141,7 +1147,7 @@ mod tests {
11411147
let mut object = Object::new(class)?;
11421148
object.set_value("coder", Value::Int(0))?;
11431149
let string_bytes: Vec<i8> = "foo".as_bytes().to_vec().iter().map(|&b| b as i8).collect();
1144-
let string_value = Value::from(string_bytes);
1150+
let string_value = test_ref(string_bytes);
11451151
object.set_value("value", string_value)?;
11461152
let result = object.as_string()?;
11471153
assert_eq!("foo".to_string(), result);
@@ -1160,7 +1166,7 @@ mod tests {
11601166
.flat_map(u16::to_be_bytes)
11611167
.map(|b| b as i8)
11621168
.collect();
1163-
let string_value = Value::from(string_bytes);
1169+
let string_value = test_ref(string_bytes);
11641170
object.set_value("value", string_value)?;
11651171
let result = object.as_string()?;
11661172
assert_eq!(value.to_string(), result);
@@ -1171,7 +1177,7 @@ mod tests {
11711177
async fn test_as_string_invalid_char_array_value() -> Result<()> {
11721178
let class = string_class().await?;
11731179
let mut object = Object::new(class)?;
1174-
let string_value = Value::from(Vec::<i32>::new());
1180+
let string_value = test_ref(Vec::<i32>::new());
11751181
object.set_value("value", string_value)?;
11761182
let result = object.as_string();
11771183
assert!(matches!(result, Err(InvalidValueType(_))));

ristretto_classloader/src/reference.rs

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -796,11 +796,19 @@ impl From<Vec<f64>> for Reference {
796796
}
797797
}
798798

799-
impl From<(Arc<Class>, Vec<Option<Reference>>)> for Reference {
800-
fn from((class, value): (Arc<Class>, Vec<Option<Reference>>)) -> Self {
801-
let elements = value.into_iter().map(Value::from).collect::<Vec<_>>();
799+
impl Reference {
800+
/// Create a new object array reference.
801+
pub fn new_array(
802+
collector: &GarbageCollector,
803+
class: Arc<Class>,
804+
value: Vec<Option<Reference>>,
805+
) -> Self {
806+
let elements = value
807+
.into_iter()
808+
.map(|opt_ref| Value::new_opt_object(collector, opt_ref))
809+
.collect::<Vec<_>>();
802810
let object_array = ObjectArray {
803-
class: class.clone(),
811+
class,
804812
elements: elements.into_boxed_slice(),
805813
};
806814
Reference::Array(object_array)
@@ -836,10 +844,16 @@ impl From<Object> for Reference {
836844
#[cfg(test)]
837845
mod tests {
838846
use super::*;
847+
839848
use crate::{Class, Result, Value, runtime};
849+
use ristretto_gc::GarbageCollector;
840850
use std::hash::{DefaultHasher, Hasher};
841851
use std::sync::Arc;
842852

853+
fn test_ref(reference: impl Into<Reference>) -> Value {
854+
Value::new_object(&GarbageCollector::new(), reference.into())
855+
}
856+
843857
async fn load_class(class: &str) -> Result<Arc<Class>> {
844858
let (_java_home, _java_version, class_loader) = runtime::default_class_loader().await?;
845859
class_loader.load(class).await
@@ -865,7 +879,7 @@ mod tests {
865879
let class = load_class("java.lang.Object").await?;
866880
let object = Object::new(class.clone())?;
867881
let values = vec![Some(Reference::from(object))];
868-
let reference = Reference::from((class, values));
882+
let reference = Reference::new_array(&GarbageCollector::new(), class, values);
869883
let collector = GarbageCollector::new();
870884
reference.trace(&collector);
871885
Ok(())
@@ -1163,7 +1177,7 @@ mod tests {
11631177
#[tokio::test]
11641178
async fn test_display_reference_array() -> Result<()> {
11651179
let class = load_class("[Ljava/lang/Object;").await?;
1166-
let reference = Reference::from((class, vec![None]));
1180+
let reference = Reference::new_array(&GarbageCollector::new(), class, vec![None]);
11671181
assert_eq!(reference.class_name()?, "[Ljava/lang/Object;");
11681182
assert_eq!(reference.to_string(), "java/lang/Object[1]");
11691183
Ok(())
@@ -1173,7 +1187,8 @@ mod tests {
11731187
async fn test_as_class_vec_ref() -> Result<()> {
11741188
let original_class = load_class("[Ljava/lang/Object;").await?;
11751189
let original_value = vec![Value::Object(None)];
1176-
let reference = Reference::from((original_class.clone(), vec![None]));
1190+
let reference =
1191+
Reference::new_array(&GarbageCollector::new(), original_class.clone(), vec![None]);
11771192
let (class, value) = reference.as_class_vec_ref()?;
11781193
assert_eq!(&original_class, class);
11791194
assert_eq!(original_value, value.to_vec());
@@ -1190,7 +1205,8 @@ mod tests {
11901205
#[tokio::test]
11911206
async fn test_as_class_vec_mut() -> Result<()> {
11921207
let object_class = load_class("[Ljava/lang/Object;").await?;
1193-
let mut reference = Reference::from((object_class.clone(), vec![None]));
1208+
let mut reference =
1209+
Reference::new_array(&GarbageCollector::new(), object_class.clone(), vec![None]);
11941210
{
11951211
let (_class, mutable_reference) = reference.as_class_vec_mut()?;
11961212
mutable_reference[0] = Value::Int(42);
@@ -1580,16 +1596,16 @@ mod tests {
15801596
#[tokio::test]
15811597
async fn test_hash_code_reference_array() -> Result<()> {
15821598
let class = load_class("java.lang.Object").await?;
1583-
let reference = Reference::from((class.clone(), vec![None]));
1599+
let reference = Reference::new_array(&GarbageCollector::new(), class.clone(), vec![None]);
15841600
assert_ne!(0, reference.hash_code());
15851601
Ok(())
15861602
}
15871603

15881604
#[tokio::test]
15891605
async fn test_hash_reference_array() -> Result<()> {
15901606
let class = load_class("java.lang.Object").await?;
1591-
let reference1 = Reference::from((class.clone(), vec![None]));
1592-
let reference2 = Reference::from((class.clone(), vec![None]));
1607+
let reference1 = Reference::new_array(&GarbageCollector::new(), class.clone(), vec![None]);
1608+
let reference2 = Reference::new_array(&GarbageCollector::new(), class.clone(), vec![None]);
15931609
let mut hasher1 = DefaultHasher::new();
15941610
reference1.hash(&mut hasher1);
15951611
let hash1 = hasher1.finish();
@@ -1603,8 +1619,8 @@ mod tests {
16031619
#[tokio::test]
16041620
async fn test_ptr_eq_reference_array() -> Result<()> {
16051621
let class = load_class("java.lang.Object").await?;
1606-
let reference1 = Reference::from((class.clone(), vec![None]));
1607-
let reference2 = Reference::from((class.clone(), vec![None]));
1622+
let reference1 = Reference::new_array(&GarbageCollector::new(), class.clone(), vec![None]);
1623+
let reference2 = Reference::new_array(&GarbageCollector::new(), class.clone(), vec![None]);
16081624
let reference3 = reference1.clone();
16091625
assert!(reference1.ptr_eq(&reference1));
16101626
assert!(!reference1.ptr_eq(&reference2));
@@ -1615,14 +1631,14 @@ mod tests {
16151631
#[tokio::test]
16161632
async fn test_clone_reference_array() -> Result<()> {
16171633
let class = load_class("java.lang.Object").await?;
1618-
let reference = Reference::from((class.clone(), vec![None]));
1634+
let reference = Reference::new_array(&GarbageCollector::new(), class.clone(), vec![None]);
16191635
let mut clone = reference.clone();
16201636
assert_eq!(reference, clone);
16211637

16221638
{
16231639
let (_class, array) = clone.as_class_vec_mut()?;
16241640
if let Some(element) = array.get_mut(0) {
1625-
*element = Value::from(vec![1i8]);
1641+
*element = test_ref(vec![1i8]);
16261642
}
16271643
}
16281644
assert_ne!(reference, clone);
@@ -1682,27 +1698,27 @@ mod tests {
16821698
#[tokio::test]
16831699
async fn test_array_eq() -> Result<()> {
16841700
let class = load_class("java.lang.Object").await?;
1685-
let reference1 = Reference::from((class.clone(), vec![]));
1686-
let reference2 = Reference::from((class, vec![]));
1701+
let reference1 = Reference::new_array(&GarbageCollector::new(), class.clone(), vec![]);
1702+
let reference2 = Reference::new_array(&GarbageCollector::new(), class, vec![]);
16871703
assert_eq!(reference1, reference2);
16881704
Ok(())
16891705
}
16901706

16911707
#[tokio::test]
16921708
async fn test_array_eq_class_ne() -> Result<()> {
16931709
let object_class = load_class("java.lang.Object").await?;
1694-
let reference1 = Reference::from((object_class, vec![]));
1710+
let reference1 = Reference::new_array(&GarbageCollector::new(), object_class, vec![]);
16951711
let string_class = load_class("java.lang.String").await?;
1696-
let reference2 = Reference::from((string_class, vec![]));
1712+
let reference2 = Reference::new_array(&GarbageCollector::new(), string_class, vec![]);
16971713
assert_ne!(reference1, reference2);
16981714
Ok(())
16991715
}
17001716

17011717
#[tokio::test]
17021718
async fn test_array_eq_value_ne() -> Result<()> {
17031719
let class = load_class("java.lang.Object").await?;
1704-
let reference1 = Reference::from((class.clone(), vec![]));
1705-
let reference2 = Reference::from((class, vec![None]));
1720+
let reference1 = Reference::new_array(&GarbageCollector::new(), class.clone(), vec![]);
1721+
let reference2 = Reference::new_array(&GarbageCollector::new(), class, vec![None]);
17061722
assert_ne!(reference1, reference2);
17071723
Ok(())
17081724
}
@@ -1919,7 +1935,11 @@ mod tests {
19191935
async fn test_from_class_vec() -> Result<()> {
19201936
let original_class = load_class("[Ljava/lang/Object;").await?;
19211937
let original_value = vec![None];
1922-
let reference = Reference::from((original_class.clone(), original_value.clone()));
1938+
let reference = Reference::new_array(
1939+
&GarbageCollector::new(),
1940+
original_class.clone(),
1941+
original_value.clone(),
1942+
);
19231943
assert!(matches!(reference, Reference::Array(_)));
19241944
Ok(())
19251945
}
@@ -1931,7 +1951,7 @@ mod tests {
19311951
let class = load_class(class_name).await?;
19321952
let mut object = Object::new(class)?;
19331953
object.set_value("value", Value::Int(42))?;
1934-
let value = Value::from(object);
1954+
let value = test_ref(object);
19351955
let original_values = vec![value];
19361956
let reference = Reference::try_from((original_class.clone(), original_values.clone()))?;
19371957
assert!(matches!(reference, Reference::Array(_)));
@@ -1941,7 +1961,7 @@ mod tests {
19411961
#[tokio::test]
19421962
async fn test_try_from_class_vec_error() -> Result<()> {
19431963
let original_class = load_class("[Ljava/lang/Object;").await?;
1944-
let value = Value::from(42);
1964+
let value = Value::Int(42);
19451965
let original_value = vec![value];
19461966
let reference = Reference::try_from((original_class.clone(), original_value.clone()));
19471967
assert!(matches!(reference, Err(InvalidValueType(_))));
@@ -2113,13 +2133,13 @@ mod tests {
21132133
Ok(())
21142134
}
21152135

2116-
#[expect(clippy::cast_possible_wrap)]
21172136
#[tokio::test]
21182137
async fn test_as_string() -> Result<()> {
21192138
let class = load_class("java/lang/String").await?;
21202139
let mut object = Object::new(class)?;
2121-
let string_bytes: Vec<i8> = "foo".as_bytes().to_vec().iter().map(|&b| b as i8).collect();
2122-
let string_value = Value::from(string_bytes);
2140+
let bytes = "foo".as_bytes();
2141+
let string_bytes: &[i8] = zerocopy::transmute_ref!(bytes);
2142+
let string_value = test_ref(string_bytes.to_vec());
21232143
object.set_value("value", string_value)?;
21242144
let reference = Reference::from(object);
21252145
let result = reference.as_string()?;
@@ -2205,7 +2225,7 @@ mod tests {
22052225
#[tokio::test]
22062226
async fn test_as_bytes_object_array_returns_none() -> Result<()> {
22072227
let class = load_class("[Ljava/lang/Object;").await?;
2208-
let reference = Reference::from((class, vec![None]));
2228+
let reference = Reference::new_array(&GarbageCollector::new(), class, vec![None]);
22092229
assert!(reference.as_bytes().is_none());
22102230
Ok(())
22112231
}
@@ -2321,7 +2341,7 @@ mod tests {
23212341
#[tokio::test]
23222342
async fn test_as_bytes_mut_object_array_returns_none() -> Result<()> {
23232343
let class = load_class("[Ljava/lang/Object;").await?;
2324-
let mut reference = Reference::from((class, vec![None]));
2344+
let mut reference = Reference::new_array(&GarbageCollector::new(), class, vec![None]);
23252345
assert!(reference.as_bytes_mut().is_none());
23262346
Ok(())
23272347
}

0 commit comments

Comments
 (0)