@@ -4,7 +4,7 @@ use alloc::{borrow::ToOwned, boxed::Box, collections::BTreeMap, format, string::
44use core:: {
55 fmt:: Debug ,
66 iter,
7- sync:: atomic:: { AtomicBool , Ordering } ,
7+ sync:: atomic:: { AtomicBool , AtomicU64 , Ordering } ,
88} ;
99
1010use dyn_clone:: clone_box;
@@ -17,13 +17,14 @@ use crate::{
1717 Result ,
1818 array_class_instance:: { ArrayRawBuffer , ArrayRawBufferMut } ,
1919 class_definition:: ClassDefinition ,
20- class_instance:: ClassInstance ,
20+ class_instance:: { ClassInstance , ClassInstanceRef } ,
2121 class_loader:: {
2222 BootstrapClassLoader , BootstrapClassLoaderWrapper , Class , ClassLoaderWrapper , InitState , InitializationAction , JavaClassLoaderWrapper ,
2323 } ,
2424 error:: JavaError ,
2525 field:: Field ,
2626 garbage_collector:: determine_garbage,
27+ global_ref:: { GlobalRef , GlobalReferences } ,
2728 invoke_arg:: InvokeArg ,
2829 method:: Method ,
2930 monitor:: { Monitor , MonitorWait , MonitorWaitTimeout } ,
@@ -36,6 +37,7 @@ use crate::{
3637struct JvmInner {
3738 classes : RwLock < BTreeMap < String , Class > > ,
3839 threads : RwLock < BTreeMap < u64 , JvmThread > > ,
40+ global_references : Arc < GlobalReferences > ,
3941 all_objects : RwLock < HashSet < Box < dyn ClassInstance > > > ,
4042 string_pool : RwLock < BTreeMap < Vec < u16 > , Box < dyn ClassInstance > > > ,
4143 monitors : RwLock < BTreeMap < usize , Arc < Monitor > > > ,
@@ -59,6 +61,10 @@ impl Jvm {
5961 inner : Arc :: new ( JvmInner {
6062 classes : RwLock :: new ( BTreeMap :: new ( ) ) ,
6163 threads : RwLock :: new ( BTreeMap :: new ( ) ) ,
64+ global_references : Arc :: new ( GlobalReferences {
65+ next_id : AtomicU64 :: new ( 0 ) ,
66+ objects : RwLock :: new ( BTreeMap :: new ( ) ) ,
67+ } ) ,
6268 all_objects : RwLock :: new ( HashSet :: new ( ) ) ,
6369 string_pool : RwLock :: new ( BTreeMap :: new ( ) ) ,
6470 monitors : RwLock :: new ( BTreeMap :: new ( ) ) ,
@@ -107,6 +113,16 @@ impl Jvm {
107113
108114 jvm. inner . bootstrapping . store ( false , Ordering :: Relaxed ) ;
109115
116+ let thread_id = ( jvm. inner . get_current_thread_id ) ( ) ;
117+ jvm. inner
118+ . threads
119+ . write ( )
120+ . get_mut ( & thread_id)
121+ . unwrap ( )
122+ . top_frame_mut ( )
123+ . local_variables_mut ( )
124+ . clear ( ) ;
125+
110126 Ok ( jvm)
111127 }
112128
@@ -188,7 +204,19 @@ impl Jvm {
188204
189205 self . ensure_initialized ( & declaring_class) . await ?;
190206
191- Ok ( declaring_class. definition . get_static_field ( & * field) ?. into ( ) )
207+ let value = declaring_class. definition . get_static_field ( & * field) ?;
208+ if let JavaValue :: Object ( Some ( instance) ) = & value {
209+ let thread_id = ( self . inner . get_current_thread_id ) ( ) ;
210+ self . inner
211+ . threads
212+ . write ( )
213+ . get_mut ( & thread_id)
214+ . unwrap ( )
215+ . top_frame_mut ( )
216+ . local_variables_mut ( )
217+ . push ( instance. clone ( ) ) ;
218+ }
219+ Ok ( value. into ( ) )
192220 } else {
193221 Err ( self
194222 . exception ( "java/lang/NoSuchFieldError" , & format ! ( "{class_name}.{name}:{descriptor}" ) )
@@ -230,7 +258,19 @@ impl Jvm {
230258 let field = self . find_field ( & * instance. class_definition ( ) , name, descriptor) ?;
231259
232260 if let Some ( field) = field {
233- Ok ( instance. get_field ( & * field) ?. into ( ) )
261+ let value = instance. get_field ( & * field) ?;
262+ if let JavaValue :: Object ( Some ( instance) ) = & value {
263+ let thread_id = ( self . inner . get_current_thread_id ) ( ) ;
264+ self . inner
265+ . threads
266+ . write ( )
267+ . get_mut ( & thread_id)
268+ . unwrap ( )
269+ . top_frame_mut ( )
270+ . local_variables_mut ( )
271+ . push ( instance. clone ( ) ) ;
272+ }
273+ Ok ( value. into ( ) )
234274 } else {
235275 Err ( self
236276 . exception (
@@ -407,6 +447,15 @@ impl Jvm {
407447 if let Some ( array) = array {
408448 let values = array. load ( offset, count) ?;
409449
450+ let thread_id = ( self . inner . get_current_thread_id ) ( ) ;
451+ let mut threads = self . inner . threads . write ( ) ;
452+ let local_variables = threads. get_mut ( & thread_id) . unwrap ( ) . top_frame_mut ( ) . local_variables_mut ( ) ;
453+ values. iter ( ) . for_each ( |value| {
454+ if let JavaValue :: Object ( Some ( instance) ) = value {
455+ local_variables. push ( instance. clone ( ) ) ;
456+ }
457+ } ) ;
458+
410459 Ok ( iter:: IntoIterator :: into_iter ( values) . map ( |x| x. into ( ) ) . collect :: < Vec < _ > > ( ) )
411460 } else {
412461 Err ( self . exception ( "java/lang/IllegalArgumentException" , "Not an array" ) . await )
@@ -761,11 +810,12 @@ impl Jvm {
761810
762811 let garbage = {
763812 let threads = self . inner . threads . read ( ) ;
813+ let global_references = self . inner . global_references . objects . read ( ) ;
764814 let all_objects = self . inner . all_objects . read ( ) ;
765815 let classes = self . inner . classes . read ( ) ;
766816 let interned_strings = self . interned_strings ( ) ;
767817
768- determine_garbage ( self , & threads, & all_objects, & classes, & interned_strings)
818+ determine_garbage ( self , & threads, & global_references , & all_objects, & classes, & interned_strings)
769819 } ;
770820
771821 let garbage_count = garbage. len ( ) ;
@@ -888,6 +938,18 @@ impl Jvm {
888938 Ok ( ( ) )
889939 }
890940
941+ pub fn new_global_ref < T > ( & self , reference : & ClassInstanceRef < T > ) -> Option < GlobalRef < T > > {
942+ let instance = reference. instance . as_ref ( ) ?. clone ( ) ;
943+ let id = self . inner . global_references . next_id . fetch_add ( 1 , Ordering :: Relaxed ) ;
944+ self . inner . global_references . objects . write ( ) . insert ( id, instance) ;
945+
946+ Some ( GlobalRef {
947+ references : self . inner . global_references . clone ( ) ,
948+ id,
949+ reference : reference. clone ( ) ,
950+ } )
951+ }
952+
891953 pub fn detach_thread ( & self ) -> Result < ( ) > {
892954 let thread_id = ( self . inner . get_current_thread_id ) ( ) ;
893955 self . inner . threads . write ( ) . remove ( & thread_id) ;
@@ -1043,13 +1105,25 @@ impl Jvm {
10431105 . write ( )
10441106 . get_mut ( & thread_id)
10451107 . unwrap ( )
1046- . push_java_frame ( class, class_instance, & method_str) ;
1108+ . push_java_frame ( class, class_instance, & method_str, & args ) ;
10471109
10481110 let result = method. run ( self , args) . await ;
10491111
10501112 tracing:: trace!( "Execute result: {result:?}" ) ;
10511113
1052- self . inner . threads . write ( ) . get_mut ( & thread_id) . unwrap ( ) . pop_frame ( ) ;
1114+ let returned_reference = match & result {
1115+ Ok ( JavaValue :: Object ( Some ( instance) ) ) => Some ( instance. clone ( ) ) ,
1116+ Err ( JavaError :: JavaException ( exception) ) => Some ( exception. clone ( ) ) ,
1117+ _ => None ,
1118+ } ;
1119+ {
1120+ let mut threads = self . inner . threads . write ( ) ;
1121+ let thread = threads. get_mut ( & thread_id) . unwrap ( ) ;
1122+ thread. pop_frame ( ) ;
1123+ if let Some ( returned_reference) = returned_reference {
1124+ thread. top_frame_mut ( ) . local_variables_mut ( ) . push ( returned_reference) ;
1125+ }
1126+ }
10531127
10541128 if let Some ( object) = & synchronized_object
10551129 && let Err ( error) = self . monitor_exit ( object) . await
0 commit comments