@@ -733,7 +733,7 @@ impl Actor
733733 } ;
734734 let mut dst_map = HashMap :: new ( ) ;
735735 let msg = deepcopy ( msg, alloc_rc. lock ( ) . as_mut ( ) . unwrap ( ) , & mut dst_map) . unwrap ( ) ;
736- remap ( dst_map) ;
736+ remap ( & mut dst_map) ;
737737
738738 match actor_tx. sender . send ( Message { sender : self . actor_id , msg } ) {
739739 Ok ( _) => Ok ( ( ) ) ,
@@ -851,53 +851,41 @@ impl Actor
851851 /// allocator. If the memory is not available, perform GC.
852852 pub fn gc_check ( & mut self , num_bytes : usize , extra_roots : & mut [ & mut Value ] )
853853 {
854- if self . alloc . bytes_free ( ) >= num_bytes {
855- return ;
856- }
857-
858- println ! ( "Running GC cycle, {} bytes free" , self . alloc. bytes_free( ) ) ;
859- let start_time = crate :: host:: get_time_ms ( ) ;
860-
861- let mut new_mem_size = self . alloc . mem_size ( ) ;
862-
863- loop {
864- // Create a new allocator to copy the data into
865- let mut new_alloc = Alloc :: with_size ( new_mem_size) ;
866-
867- // Hash map for remapping copied values
868- let mut dst_map = HashMap :: new ( ) ;
869-
854+ fn try_copy (
855+ actor : & mut Actor ,
856+ dst_alloc : & mut Alloc ,
857+ dst_map : & mut HashMap < Value , Value > ,
858+ extra_roots : & mut [ & mut Value ] ,
859+ ) -> Result < ( ) , ( ) >
860+ {
870861 // Copy the global variables
871- for val in & mut self . globals {
872- * val = deepcopy ( * val, & mut new_alloc , & mut dst_map) . unwrap ( ) ;
862+ for val in & mut actor . globals {
863+ deepcopy ( * val, dst_alloc , dst_map) ? ;
873864 }
874865
875866 // Copy values on the stack
876- for val in & mut self . stack {
877- * val = deepcopy ( * val, & mut new_alloc , & mut dst_map) . unwrap ( ) ;
867+ for val in & mut actor . stack {
868+ deepcopy ( * val, dst_alloc , dst_map) ? ;
878869 }
879870
880871 // Copy closures in the stack frames
881- for frame in & mut self . frames {
882- frame . fun = deepcopy ( frame. fun , & mut new_alloc , & mut dst_map) . unwrap ( ) ;
872+ for frame in & mut actor . frames {
873+ deepcopy ( frame. fun , dst_alloc , dst_map) ? ;
883874 }
884875
885876 // Copy heap values referenced in instructions
886- for insn in & mut self . insns {
877+ for insn in & mut actor . insns {
887878 match insn {
888879 Insn :: push { val } => {
889- * val = deepcopy ( * val, & mut new_alloc , & mut dst_map) . unwrap ( ) ;
880+ deepcopy ( * val, dst_alloc , dst_map) ? ;
890881 }
891882
892883 // Instructions referencing name strings
893884 Insn :: get_field { field : s, .. } |
894885 Insn :: set_field { field : s, .. } |
895886 Insn :: call_method { name : s, .. } |
896887 Insn :: call_method_pc { name : s, .. } => {
897- * s = match deepcopy ( Value :: String ( * s) , & mut new_alloc, & mut dst_map) . unwrap ( ) {
898- Value :: String ( s) => s,
899- _ => panic ! ( ) ,
900- }
888+ deepcopy ( Value :: String ( * s) , dst_alloc, dst_map) ?;
901889 }
902890
903891 _ => { }
@@ -906,22 +894,106 @@ impl Actor
906894
907895 // Copy extra roots supplied by the user
908896 for val in extra_roots {
909- * * val = deepcopy ( * * val, & mut new_alloc , & mut dst_map) . unwrap ( ) ;
897+ deepcopy ( * * val, dst_alloc , dst_map) ? ;
910898 }
911899
912900 println ! ( "GC copied {} values" , dst_map. len( ) ) ;
913901 remap ( dst_map) ;
914902
903+ Ok ( ( ) )
904+ }
905+
906+ fn get_new_val ( val : Value , dst_map : & HashMap < Value , Value > ) -> Value
907+ {
908+ if !val. is_heap ( ) {
909+ return val;
910+ }
911+
912+ * dst_map. get ( & val) . unwrap ( )
913+ }
914+
915+ if self . alloc . bytes_free ( ) >= num_bytes {
916+ return ;
917+ }
918+
919+ println ! ( "Running GC cycle, {} bytes free" , self . alloc. bytes_free( ) ) ;
920+ let start_time = crate :: host:: get_time_ms ( ) ;
921+
922+ let mut new_mem_size = self . alloc . mem_size ( ) ;
923+
924+ // Hash map for remapping copied values
925+ let mut dst_map = HashMap :: < Value , Value > :: new ( ) ;
926+
927+ loop {
928+ // Create a new allocator to copy the data into
929+ let mut dst_alloc = Alloc :: with_size ( new_mem_size) ;
930+
931+ // Clear the value map
932+ dst_map. clear ( ) ;
933+
934+ // Try to copy all objects into the new allocator
935+ if try_copy ( self , & mut dst_alloc, & mut dst_map, extra_roots) . is_err ( ) {
936+ // If the copying fails, increase the heap size and try again
937+ new_mem_size = ( new_mem_size * 5 ) / 4 ;
938+ println ! ( "Increasing heap size to {} bytes" , new_mem_size) ;
939+ continue ;
940+ }
941+
942+
943+ // NOTE: we may want to run another GC cycle and expand the memory
944+ // if too little memory is free
945+ // Should have a target for something like 25% of memory free
946+
947+
948+
915949 // Copying successful
916950 // Drop and replace the old allocator
917- self . alloc = new_alloc ;
951+ self . alloc = dst_alloc ;
918952 break ;
919953 }
920954
955+ // Remap the global variables
956+ for val in & mut self . globals {
957+ * val = get_new_val ( * val, & dst_map) ;
958+ }
959+
960+ // Remap values on the stack
961+ for val in & mut self . stack {
962+ * val = get_new_val ( * val, & dst_map) ;
963+ }
964+
965+ // Remap closures in the stack frames
966+ for frame in & mut self . frames {
967+ frame. fun = get_new_val ( frame. fun , & dst_map) ;
968+ }
969+
970+ // Remap heap values referenced in instructions
971+ for insn in & mut self . insns {
972+ match insn {
973+ Insn :: push { val } => {
974+ * val = get_new_val ( * val, & dst_map) ;
975+ }
976+
977+ // Instructions referencing name strings
978+ Insn :: get_field { field : s, .. } |
979+ Insn :: set_field { field : s, .. } |
980+ Insn :: call_method { name : s, .. } |
981+ Insn :: call_method_pc { name : s, .. } => {
982+ match get_new_val ( Value :: String ( * s) , & dst_map) {
983+ Value :: String ( new_s) => * s = new_s,
984+ _ => panic ! ( ) ,
985+ }
986+ }
987+
988+ _ => { }
989+ }
990+ }
991+
992+ // Remap extra roots supplied by the user
993+ for val in extra_roots {
994+ * * val = get_new_val ( * * val, & dst_map) ;
995+ }
921996
922- // NOTE: we may want to run another GC cycle and expand the memory
923- // if too little memory is free
924- // Should have a target for something like 25% of memory free
925997
926998
927999
@@ -936,6 +1008,8 @@ impl Actor
9361008
9371009
9381010
1011+
1012+
9391013 let end_time = crate :: host:: get_time_ms ( ) ;
9401014 let gc_time = end_time - start_time;
9411015 println ! ( "GC time: {} ms" , gc_time) ;
@@ -2177,7 +2251,7 @@ impl VM
21772251 * val = deepcopy ( * val, & mut msg_alloc, & mut dst_map) . unwrap ( ) ;
21782252 }
21792253
2180- remap ( dst_map) ;
2254+ remap ( & mut dst_map) ;
21812255
21822256 // Wrap the message allocator in a shared mutex
21832257 let msg_alloc = Arc :: new ( Mutex :: new ( msg_alloc) ) ;
0 commit comments