| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| |
| /** |
| * @author Xiao-Feng Li, 2006/12/3 |
| */ |
| |
| #include "gc_common.h" |
| #include "gc_metadata.h" |
| #include "../thread/mutator.h" |
| #include "../thread/conclctor.h" |
| #include "../finalizer_weakref/finalizer_weakref.h" |
| #include "../gen/gen.h" |
| #include "../mark_sweep/gc_ms.h" |
| #include "../move_compact/gc_mc.h" |
| #include "../common/space_tuner.h" |
| #include "interior_pointer.h" |
| #include "collection_scheduler.h" |
| #include "gc_concurrent.h" |
| |
| unsigned int Cur_Mark_Bit = 0x1; |
| unsigned int Cur_Forward_Bit = 0x2; |
| |
| unsigned int SPACE_ALLOC_UNIT; |
| Boolean IGNORE_FORCE_GC = FALSE; |
| |
| void gc_assign_free_area_to_mutators(GC* gc) |
| { |
| #if !defined(USE_UNIQUE_MARK_SWEEP_GC) && !defined(USE_UNIQUE_MOVE_COMPACT_GC) |
| gc_gen_assign_free_area_to_mutators((GC_Gen*)gc); |
| #endif |
| } |
| |
| void gc_init_collector_alloc(GC* gc, Collector* collector) |
| { |
| #ifndef USE_UNIQUE_MARK_SWEEP_GC |
| gc_gen_init_collector_alloc((GC_Gen*)gc, collector); |
| #else |
| gc_init_collector_free_chunk_list(collector); |
| #endif |
| } |
| |
| void gc_reset_collector_alloc(GC* gc, Collector* collector) |
| { |
| #if !defined(USE_UNIQUE_MARK_SWEEP_GC) && !defined(USE_UNIQUE_MOVE_COMPACT_GC) |
| gc_gen_reset_collector_alloc((GC_Gen*)gc, collector); |
| #endif |
| } |
| |
| void gc_destruct_collector_alloc(GC* gc, Collector* collector) |
| { |
| #ifndef USE_UNIQUE_MARK_SWEEP_GC |
| gc_gen_destruct_collector_alloc((GC_Gen*)gc, collector); |
| #endif |
| } |
| |
| void gc_copy_interior_pointer_table_to_rootset(); |
| |
| /*used for computing collection time and mutator time*/ |
| static int64 collection_start_time = time_now(); |
| static int64 collection_end_time = time_now(); |
| |
| int64 get_gc_start_time() |
| { return collection_start_time; } |
| |
| void set_gc_start_time() |
| { collection_start_time = time_now(); } |
| |
| int64 get_gc_end_time() |
| { return collection_end_time; } |
| |
| void set_gc_end_time() |
| { |
| collection_end_time = time_now(); |
| } |
| |
| void gc_decide_collection_kind(GC* gc, unsigned int cause) |
| { |
| /* this is for debugging and for gen-nongen-switch. */ |
| gc->last_collect_kind = GC_PROP; |
| |
| #if !defined(USE_UNIQUE_MARK_SWEEP_GC) && !defined(USE_UNIQUE_MOVE_COMPACT_GC) |
| |
| gc_gen_decide_collection_kind((GC_Gen*)gc, cause); |
| |
| #endif |
| |
| } |
| |
| void gc_update_space_stat(GC* gc) |
| { |
| #ifdef USE_UNIQUE_MARK_SWEEP_GC |
| gc_ms_update_space_stat((GC_MS *)gc); |
| #endif |
| } |
| |
| void gc_reset_space_stat(GC* gc) |
| { |
| #ifdef USE_UNIQUE_MARK_SWEEP_GC |
| gc_ms_reset_space_stat((GC_MS *)gc); |
| #endif |
| } |
| |
| void gc_prepare_rootset(GC* gc) |
| { |
| /* Stop the threads and collect the roots. */ |
| INFO2("gc.process", "GC: stop the threads and enumerate rootset ...\n"); |
| gc_clear_rootset(gc); |
| gc_reset_rootset(gc); |
| vm_enumerate_root_set_all_threads(); |
| gc_copy_interior_pointer_table_to_rootset(); |
| gc_set_rootset(gc); |
| } |
| |
| void gc_reset_after_collection(GC* gc) |
| { |
| if(gc_is_gen_mode()) gc_prepare_mutator_remset(gc); |
| |
| /* Clear rootset pools here rather than in each collection algorithm */ |
| gc_clear_rootset(gc); |
| |
| if(!gc_is_specify_con_gc()) gc_metadata_verify(gc, FALSE); |
| |
| if(!IGNORE_FINREF ){ |
| INFO2("gc.process", "GC: finref process after collection ...\n"); |
| gc_put_finref_to_vm(gc); |
| gc_reset_finref_metadata(gc); |
| gc_activate_finref_threads((GC*)gc); |
| #ifndef BUILD_IN_REFERENT |
| } else { |
| gc_clear_weakref_pools(gc); |
| gc_clear_finref_repset_pool(gc); |
| #endif |
| } |
| |
| gc_update_space_stat(gc); |
| |
| gc_reset_space_stat(gc); |
| |
| gc_reset_collector_state(gc); |
| |
| gc_clear_dirty_set(gc); |
| |
| vm_reclaim_native_objs(); |
| gc->in_collection = FALSE; |
| |
| } |
| |
| void set_check_delay( int64 mutator_time ); |
| |
| void gc_reclaim_heap(GC* gc, unsigned int gc_cause) |
| { |
| INFO2("gc.process", "\nGC: GC start ...\n"); |
| |
| gc->cause = gc_cause; |
| |
| if(gc_is_specify_con_gc()){ |
| gc_wait_con_finish(gc); |
| INFO2("gc.process", "GC: GC end\n"); |
| return; |
| } |
| |
| set_gc_start_time(); |
| int64 time_mutator = get_gc_start_time() - get_gc_end_time(); |
| |
| gc->num_collections++; |
| |
| /* FIXME:: before mutators suspended, the ops below should be very careful |
| to avoid racing with mutators. */ |
| |
| gc_decide_collection_kind(gc, gc_cause); |
| |
| #ifdef MARK_BIT_FLIPPING |
| if(collect_is_minor()) mark_bit_flip(); |
| #endif |
| |
| gc_metadata_verify(gc, TRUE); |
| #ifndef BUILD_IN_REFERENT |
| gc_finref_metadata_verify((GC*)gc, TRUE); |
| #endif |
| |
| /* Stop the threads and collect the roots. */ |
| lock(gc->lock_enum); |
| int disable_count = hythread_reset_suspend_disable(); |
| gc_set_rootset_type(ROOTSET_IS_REF); |
| gc_prepare_rootset(gc); |
| unlock(gc->lock_enum); |
| |
| gc->in_collection = TRUE; |
| |
| /* this has to be done after all mutators are suspended */ |
| gc_reset_mutator_context(gc); |
| |
| if(!IGNORE_FINREF ) gc_set_obj_with_fin(gc); |
| |
| #if defined(USE_UNIQUE_MARK_SWEEP_GC) |
| gc_ms_reclaim_heap((GC_MS*)gc); |
| #elif defined(USE_UNIQUE_MOVE_COMPACT_GC) |
| gc_mc_reclaim_heap((GC_MC*)gc); |
| #else |
| gc_gen_reclaim_heap((GC_Gen*)gc, collection_start_time); |
| #endif |
| |
| set_gc_end_time(); |
| |
| int64 time_collection = get_gc_end_time() - get_gc_start_time(); |
| |
| #if !defined(USE_UNIQUE_MARK_SWEEP_GC)&&!defined(USE_UNIQUE_MOVE_COMPACT_GC) |
| gc_gen_collection_verbose_info((GC_Gen*)gc, time_collection, time_mutator); |
| gc_gen_space_verbose_info((GC_Gen*)gc); |
| #endif |
| |
| gc_reset_after_collection(gc); |
| |
| gc_assign_free_area_to_mutators(gc); |
| |
| vm_resume_threads_after(); |
| assert(hythread_is_suspend_enabled()); |
| hythread_set_suspend_disable(disable_count); |
| INFO2("gc.process", "GC: GC end\n"); |
| return; |
| } |
| |
| |
| |
| |