diff -BburN svn/gc_gen/src/common/gc_common.h vm.new/gc_gen/src/common/gc_common.h --- svn/gc_gen/src/common/gc_common.h 2007-07-20 21:56:52.000000000 +0800 +++ vm.new/gc_gen/src/common/gc_common.h 2007-07-21 05:22:17.000000000 +0800 @@ -387,6 +387,7 @@ /* FIXME:: this is wrong! root_set belongs to mutator */ Vector_Block* root_set; + Vector_Block* weak_root_set; Vector_Block* uncompressed_root_set; Space_Tuner* tuner; diff -BburN svn/gc_gen/src/common/gc_for_vm.cpp vm.new/gc_gen/src/common/gc_for_vm.cpp --- svn/gc_gen/src/common/gc_for_vm.cpp 2007-07-20 21:56:52.000000000 +0800 +++ vm.new/gc_gen/src/common/gc_for_vm.cpp 2007-07-21 05:22:17.000000000 +0800 @@ -131,6 +131,24 @@ gc_compressed_rootset_add_entry(p_global_gc, p_ref); } +void gc_add_weak_root_set_entry(Managed_Object_Handle *ref, Boolean is_pinned, Boolean is_short_weak) +{ + assert(is_short_weak == FALSE); //Currently no need for short_weak_roots + Partial_Reveal_Object** p_ref = (Partial_Reveal_Object**)ref; + Partial_Reveal_Object* p_obj = *p_ref; + /* we don't enumerate NULL reference and nos_boundary + FIXME:: nos_boundary is a static field in GCHelper.java for fast write barrier, not a real object reference + this should be fixed that magic Address field should not be enumerated. */ +#ifdef COMPRESS_REFERENCE + if (p_obj == (Partial_Reveal_Object*)HEAP_NULL || p_obj == NULL || p_obj == nos_boundary ) return; +#else + if (p_obj == NULL || p_obj == nos_boundary ) return; +#endif + assert( !obj_is_marked_in_vt(p_obj)); + assert( address_belongs_to_gc_heap(p_obj, p_global_gc)); + gc_weak_rootset_add_entry(p_global_gc, p_ref, is_short_weak); +} + /* VM to force GC */ void gc_force_gc() { diff -BburN svn/gc_gen/src/common/gc_metadata.cpp vm.new/gc_gen/src/common/gc_metadata.cpp --- svn/gc_gen/src/common/gc_metadata.cpp 2007-07-20 21:56:52.000000000 +0800 +++ vm.new/gc_gen/src/common/gc_metadata.cpp 2007-07-21 05:22:17.000000000 +0800 @@ -75,6 +75,7 @@ gc_metadata.mutator_remset_pool = sync_pool_create(); gc_metadata.collector_remset_pool = sync_pool_create(); gc_metadata.collector_repset_pool = sync_pool_create(); + gc_metadata.weak_roots_pool = sync_pool_create(); #ifdef USE_32BITS_HASHCODE gc_metadata.collector_hashcode_pool = sync_pool_create(); #endif @@ -95,6 +96,7 @@ sync_pool_destruct(metadata->mutator_remset_pool); sync_pool_destruct(metadata->collector_remset_pool); sync_pool_destruct(metadata->collector_repset_pool); + sync_pool_destruct(metadata->weak_roots_pool); #ifdef USE_32BITS_HASHCODE sync_pool_destruct(metadata->collector_hashcode_pool); #endif @@ -204,6 +206,8 @@ GC* gc = collector->gc; GC_Metadata* metadata = gc->metadata; + gc_update_weak_roots_pool(gc); + /* MINOR_COLLECTION doesn't need rootset update, but need reset */ if( !gc_match_kind(gc, MINOR_COLLECTION)){ gc_update_repointed_sets(gc, metadata->gc_rootset_pool); @@ -212,6 +216,7 @@ #endif } else { gc_set_pool_clear(metadata->gc_rootset_pool); + gc_set_pool_clear(metadata->weak_roots_pool); } #ifdef COMPRESS_REFERENCE @@ -248,6 +253,12 @@ only after we know we are not going to fallback. */ // gc->root_set = NULL; + if(vector_block_is_empty(gc->weak_root_set)) + pool_put_entry(free_set_pool, gc->weak_root_set); + else + pool_put_entry(metadata->weak_roots_pool, gc->weak_root_set); + gc->weak_root_set = NULL; + if(!gc_is_gen_mode()) return; /* put back last remset block of each mutator */ @@ -315,6 +326,11 @@ gc->root_set = free_set_pool_get_entry(&gc_metadata); assert(vector_block_is_empty(gc->root_set)); + assert(pool_is_empty(gc_metadata.weak_roots_pool)); + assert(gc->weak_root_set == NULL); + gc->weak_root_set = free_set_pool_get_entry(&gc_metadata); + assert(vector_block_is_empty(gc->weak_root_set)); + #ifdef COMPRESS_REFERENCE assert(pool_is_empty(gc_metadata.gc_uncompressed_rootset_pool)); assert(gc->uncompressed_root_set == NULL); diff -BburN svn/gc_gen/src/common/gc_metadata.h vm.new/gc_gen/src/common/gc_metadata.h --- svn/gc_gen/src/common/gc_metadata.h 2007-07-20 21:56:52.000000000 +0800 +++ vm.new/gc_gen/src/common/gc_metadata.h 2007-07-21 05:22:17.000000000 +0800 @@ -43,6 +43,7 @@ Pool* mutator_remset_pool; /* list of remsets generated by app during execution */ Pool* collector_remset_pool; /* list of remsets generated by gc during collection */ Pool* collector_repset_pool; /* list of repointed ref slot sets */ + Pool* weak_roots_pool; /* list of short weak roots */ #ifdef USE_32BITS_HASHCODE Pool* collector_hashcode_pool; #endif @@ -59,6 +60,9 @@ void gc_reset_rootset(GC* gc); void gc_fix_rootset(Collector* collector); +void identify_dead_weak_roots(GC *gc, Pool *pool); +void gc_update_weak_roots_pool(GC *gc); + void gc_clear_remset(GC* gc); inline void gc_task_pool_clear(Pool* task_pool) { @@ -181,6 +185,20 @@ assert(collector->trace_stack); } +inline void gc_weak_rootset_add_entry(GC* gc, Partial_Reveal_Object** p_ref, Boolean is_short_weak) +{ + assert(is_short_weak == FALSE); //Currently no need for short_weak_roots + assert( p_ref < gc_heap_base_address() || p_ref >= gc_heap_ceiling_address()); + + Vector_Block* weak_root_set = gc->weak_root_set; + vector_block_add_entry(weak_root_set, (POINTER_SIZE_INT)p_ref); + + if( !vector_block_is_full(weak_root_set)) return; + + pool_put_entry(gc_metadata.weak_roots_pool, weak_root_set); + gc->weak_root_set = free_set_pool_get_entry(&gc_metadata); + assert(gc->weak_root_set); +} #ifdef COMPRESS_REFERENCE diff -BburN svn/gc_gen/src/common/weak_roots.cpp vm.new/gc_gen/src/common/weak_roots.cpp --- svn/gc_gen/src/common/weak_roots.cpp 1970-01-01 08:00:00.000000000 +0800 +++ vm.new/gc_gen/src/common/weak_roots.cpp 2007-07-24 01:04:46.000000000 +0800 @@ -0,0 +1,79 @@ +/* + * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gc_common.h" +#include "gc_metadata.h" +#include "../gen/gen.h" + +void identify_dead_weak_roots(GC *gc, Pool *pool) +{ + pool_iterator_init(pool); + while(Vector_Block *block = pool_iterator_next(pool)){ + POINTER_SIZE_INT *iter = vector_block_iterator_init(block); + for(; !vector_block_iterator_end(block, iter); iter = vector_block_iterator_advance(block, iter)){ + Partial_Reveal_Object** p_ref = (Partial_Reveal_Object**)*iter; + Partial_Reveal_Object *p_obj = *p_ref; + if(!p_obj){ // reference has been cleared + continue; + } + if(IS_FALLBACK_COMPACTION) { + if(obj_belongs_to_nos(p_obj) && obj_is_fw_in_oi(p_obj)){ + //this is unreachable for VTable->jlc(p_obj), but needed by general weak roots + assert(!obj_is_marked_in_vt(p_obj)); + assert(obj_get_vt(p_obj) == obj_get_vt(obj_get_fw_in_oi(p_obj))); + p_obj = obj_get_fw_in_oi(p_obj); + assert(p_obj); + *p_ref = p_obj; + } + } + if(gc_obj_is_dead(gc, p_obj)) + *p_ref = 0; + } + } +} + +extern Boolean IS_MOVE_COMPACT; + +/* parameter pointer_addr_in_pool means it is p_ref or p_obj in pool */ +void gc_update_weak_roots_pool(GC *gc) +{ + GC_Metadata* metadata = gc->metadata; + Pool *pool = metadata->weak_roots_pool; + Partial_Reveal_Object** p_ref; + Partial_Reveal_Object *p_obj; + + pool_iterator_init(pool); + while(Vector_Block *repset = pool_iterator_next(pool)){ + POINTER_SIZE_INT *iter = vector_block_iterator_init(repset); + for(; !vector_block_iterator_end(repset,iter); iter = vector_block_iterator_advance(repset,iter)){ + p_ref = (Partial_Reveal_Object**)*iter; + p_obj = *p_ref; + if(!p_obj){ // reference has been cleared + continue; + } + + if(obj_need_move(gc, p_obj)) { + if(!IS_MOVE_COMPACT){ + assert((POINTER_SIZE_INT)obj_get_fw_in_oi(p_obj) > DUAL_MARKBITS); + *p_ref = obj_get_fw_in_oi(p_obj); + } else { + assert(space_of_addr(gc, (void*)p_obj)->move_object); + *p_ref = obj_get_fw_in_table(p_obj); + } + } + } + } +} diff -BburN svn/gc_gen/src/finalizer_weakref/finalizer_weakref.cpp vm.new/gc_gen/src/finalizer_weakref/finalizer_weakref.cpp --- svn/gc_gen/src/finalizer_weakref/finalizer_weakref.cpp 2007-07-20 21:56:52.000000000 +0800 +++ vm.new/gc_gen/src/finalizer_weakref/finalizer_weakref.cpp 2007-07-21 05:22:17.000000000 +0800 @@ -31,56 +31,6 @@ Boolean IGNORE_FINREF = FALSE; Boolean DURING_RESURRECTION = FALSE; - -static inline Boolean obj_is_dead_in_gen_minor_gc(Partial_Reveal_Object *p_obj) -{ - /* - * The first condition is for supporting switch between nongen and gen minor collection - * With this kind of switch dead objects in MOS & LOS may be set the mark or fw bit in oi - */ - return obj_belongs_to_nos(p_obj) && !obj_is_marked_or_fw_in_oi(p_obj); -} - -static inline Boolean obj_is_dead_in_nongen_minor_gc(Partial_Reveal_Object *p_obj) -{ - return (obj_belongs_to_nos(p_obj) && !obj_is_fw_in_oi(p_obj)) - || (!obj_belongs_to_nos(p_obj) && !obj_is_marked_in_oi(p_obj)); -} - -static inline Boolean obj_is_dead_in_major_gc(Partial_Reveal_Object *p_obj) -{ - return !obj_is_marked_in_vt(p_obj); -} -// clear the two least significant bits of p_obj first -static inline Boolean gc_obj_is_dead(GC *gc, Partial_Reveal_Object *p_obj) -{ - assert(p_obj); - if(gc_match_kind(gc, MINOR_COLLECTION)){ - if(gc_is_gen_mode()) - return obj_is_dead_in_gen_minor_gc(p_obj); - else - return obj_is_dead_in_nongen_minor_gc(p_obj); - } else { - return obj_is_dead_in_major_gc(p_obj); - } -} - -static inline Boolean fspace_obj_to_be_forwarded(Partial_Reveal_Object *p_obj) -{ - if(!obj_belongs_to_nos(p_obj)) return FALSE; - return forward_first_half? (p_obj < object_forwarding_boundary):(p_obj>=object_forwarding_boundary); -} -static inline Boolean obj_need_move(GC *gc, Partial_Reveal_Object *p_obj) -{ - assert(!gc_obj_is_dead(gc, p_obj)); - - if(gc_is_gen_mode() && gc_match_kind(gc, MINOR_COLLECTION)) - return fspace_obj_to_be_forwarded(p_obj); - - Space *space = space_of_addr(gc, p_obj); - return space->move_object; -} - static void finref_add_repset_from_pool(GC *gc, Pool *pool) { finref_reset_repset(gc); diff -BburN svn/gc_gen/src/gen/gen.h vm.new/gc_gen/src/gen/gen.h --- svn/gc_gen/src/gen/gen.h 2007-07-20 21:56:52.000000000 +0800 +++ vm.new/gc_gen/src/gen/gen.h 2007-07-21 05:22:17.000000000 +0800 @@ -82,6 +82,7 @@ /* FIXME:: this is wrong! root_set belongs to mutator */ Vector_Block* root_set; + Vector_Block* weak_root_set; Vector_Block* uncompressed_root_set; //For_LOS_extend @@ -180,6 +181,58 @@ extern Boolean GEN_NONGEN_SWITCH ; +inline Boolean obj_is_dead_in_gen_minor_gc(Partial_Reveal_Object *p_obj) +{ + /* + * The first condition is for supporting switch between nongen and gen minor collection + * With this kind of switch dead objects in MOS & LOS may be set the mark or fw bit in oi + */ + return obj_belongs_to_nos(p_obj) && !obj_is_marked_or_fw_in_oi(p_obj); +} + +inline Boolean obj_is_dead_in_nongen_minor_gc(Partial_Reveal_Object *p_obj) +{ + return (obj_belongs_to_nos(p_obj) && !obj_is_fw_in_oi(p_obj)) + || (!obj_belongs_to_nos(p_obj) && !obj_is_marked_in_oi(p_obj)); +} + +inline Boolean obj_is_dead_in_major_gc(Partial_Reveal_Object *p_obj) +{ + return !obj_is_marked_in_vt(p_obj); +} + +// clear the two least significant bits of p_obj first +inline Boolean gc_obj_is_dead(GC *gc, Partial_Reveal_Object *p_obj) +{ + assert(p_obj); + if(gc_match_kind(gc, MINOR_COLLECTION)){ + if(gc_is_gen_mode()) + return obj_is_dead_in_gen_minor_gc(p_obj); + else + return obj_is_dead_in_nongen_minor_gc(p_obj); + } else { + return obj_is_dead_in_major_gc(p_obj); + } +} + +extern Boolean forward_first_half; +extern void* object_forwarding_boundary; + +inline Boolean fspace_obj_to_be_forwarded(Partial_Reveal_Object *p_obj) +{ + if(!obj_belongs_to_nos(p_obj)) return FALSE; + return forward_first_half? (p_obj < object_forwarding_boundary):(p_obj>=object_forwarding_boundary); +} + +inline Boolean obj_need_move(GC *gc, Partial_Reveal_Object *p_obj) +{ + if(gc_is_gen_mode() && gc_match_kind(gc, MINOR_COLLECTION)) + return fspace_obj_to_be_forwarded(p_obj); + + Space *space = space_of_addr(gc, p_obj); + return space->move_object; +} + #endif /* ifndef _GC_GEN_H_ */ diff -BburN svn/gc_gen/src/mark_compact/mspace_extend_compact.cpp vm.new/gc_gen/src/mark_compact/mspace_extend_compact.cpp --- svn/gc_gen/src/mark_compact/mspace_extend_compact.cpp 2007-07-20 21:56:52.000000000 +0800 +++ vm.new/gc_gen/src/mark_compact/mspace_extend_compact.cpp 2007-07-21 05:22:17.000000000 +0800 @@ -243,6 +243,7 @@ #ifndef BUILD_IN_REFERENT gc_update_finref_repointed_refs(gc); #endif + gc_reupdate_repointed_sets(gc, gc->metadata->weak_roots_pool, start_address, end_address, addr_diff); update_rootset_interior_pointer(); } diff -BburN svn/gc_gen/src/mark_compact/mspace_move_compact.cpp vm.new/gc_gen/src/mark_compact/mspace_move_compact.cpp --- svn/gc_gen/src/mark_compact/mspace_move_compact.cpp 2007-07-20 21:56:52.000000000 +0800 +++ vm.new/gc_gen/src/mark_compact/mspace_move_compact.cpp 2007-07-21 05:22:17.000000000 +0800 @@ -186,6 +186,7 @@ gc_update_weakref_ignore_finref(gc); } #endif + identify_dead_weak_roots(gc, gc->metadata->weak_roots_pool); /* let other collectors go */ num_marking_collectors++; @@ -244,8 +245,8 @@ mspace_reset_after_compaction(mspace); fspace_reset_for_allocation(fspace); - gc_set_pool_clear(gc->metadata->gc_rootset_pool); + gc_set_pool_clear(gc->metadata->weak_roots_pool); return; } diff -BburN svn/gc_gen/src/mark_compact/mspace_slide_compact.cpp vm.new/gc_gen/src/mark_compact/mspace_slide_compact.cpp --- svn/gc_gen/src/mark_compact/mspace_slide_compact.cpp 2007-07-20 21:56:52.000000000 +0800 +++ vm.new/gc_gen/src/mark_compact/mspace_slide_compact.cpp 2007-07-21 05:22:17.000000000 +0800 @@ -435,6 +435,7 @@ gc_update_weakref_ignore_finref(gc); } #endif + identify_dead_weak_roots(gc, gc->metadata->weak_roots_pool); if( gc->tuner->kind != TRANS_NOTHING ) gc_compute_space_tune_size_after_marking(gc); assert(!(gc->tuner->tuning_size % GC_BLOCK_SIZE_BYTES)); @@ -553,6 +554,7 @@ mspace_restore_block_chain(mspace); gc_set_pool_clear(gc->metadata->gc_rootset_pool); + gc_set_pool_clear(gc->metadata->weak_roots_pool); return; } diff -BburN svn/gc_gen/src/mark_sweep/sspace_mark_sweep.cpp vm.new/gc_gen/src/mark_sweep/sspace_mark_sweep.cpp --- svn/gc_gen/src/mark_sweep/sspace_mark_sweep.cpp 2007-07-20 21:56:52.000000000 +0800 +++ vm.new/gc_gen/src/mark_sweep/sspace_mark_sweep.cpp 2007-07-21 05:22:17.000000000 +0800 @@ -88,6 +88,8 @@ gc_update_weakref_ignore_finref(gc); } #endif + identify_dead_weak_roots(gc, gc->metadata->weak_roots_pool); + gc_init_chunk_for_sweep(gc, sspace); /* let other collectors go */ num_marking_collectors++; diff -BburN svn/gc_gen/src/trace_forward/fspace_gen_forward_pool.cpp vm.new/gc_gen/src/trace_forward/fspace_gen_forward_pool.cpp --- svn/gc_gen/src/trace_forward/fspace_gen_forward_pool.cpp 2007-07-20 21:56:52.000000000 +0800 +++ vm.new/gc_gen/src/trace_forward/fspace_gen_forward_pool.cpp 2007-07-21 05:22:17.000000000 +0800 @@ -274,6 +274,7 @@ gc_update_weakref_ignore_finref(gc); } #endif + identify_dead_weak_roots(gc, gc->metadata->weak_roots_pool); gc_fix_rootset(collector); diff -BburN svn/gc_gen/src/trace_forward/fspace_nongen_forward_pool.cpp vm.new/gc_gen/src/trace_forward/fspace_nongen_forward_pool.cpp --- svn/gc_gen/src/trace_forward/fspace_nongen_forward_pool.cpp 2007-07-20 21:56:52.000000000 +0800 +++ vm.new/gc_gen/src/trace_forward/fspace_nongen_forward_pool.cpp 2007-07-21 05:22:17.000000000 +0800 @@ -239,6 +239,7 @@ gc_update_weakref_ignore_finref(gc); } #endif + identify_dead_weak_roots(gc, gc->metadata->weak_roots_pool); gc_fix_rootset(collector);