From dev-return-35176-apmail-harmony-dev-archive=harmony.apache.org@harmony.apache.org Wed Oct 29 09:23:01 2008 Return-Path: Delivered-To: apmail-harmony-dev-archive@www.apache.org Received: (qmail 43185 invoked from network); 29 Oct 2008 09:23:01 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 29 Oct 2008 09:23:01 -0000 Received: (qmail 9961 invoked by uid 500); 29 Oct 2008 09:23:02 -0000 Delivered-To: apmail-harmony-dev-archive@harmony.apache.org Received: (qmail 9935 invoked by uid 500); 29 Oct 2008 09:23:02 -0000 Mailing-List: contact dev-help@harmony.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@harmony.apache.org Delivered-To: mailing list dev@harmony.apache.org Received: (qmail 9923 invoked by uid 99); 29 Oct 2008 09:23:02 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 29 Oct 2008 02:23:02 -0700 X-ASF-Spam-Status: No, hits=-0.0 required=10.0 tests=SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of sianjanuary@googlemail.com designates 209.85.146.181 as permitted sender) Received: from [209.85.146.181] (HELO wa-out-1112.google.com) (209.85.146.181) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 29 Oct 2008 09:21:45 +0000 Received: by wa-out-1112.google.com with SMTP id j5so1607983wah.4 for ; Wed, 29 Oct 2008 02:22:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to :subject:mime-version:content-type:content-transfer-encoding :content-disposition; bh=9a3AAoXgZQUaRL5viR8eXdR1vHjlk8nlQDGzQafjxJ0=; b=vf/ID3QN7Fu4SEcc4Ppyh0UBJcZqtfkCsQMeT7sb39+IVkP9dgfdxUcFL1Fe3vam6y QuRp68K70B/3bglmdF1qjTEsqEHxjpk/1+i+e2D3EsSpi1mUP7WTieYF/hlVCE5aVOR1 CzYvrrpNhKvSOiwWQM39baPbAg6m1VSUs+lCA= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=message-id:date:from:to:subject:mime-version:content-type :content-transfer-encoding:content-disposition; b=jE7nMnjMJg7dhtMQD7iwbB/Jj/GkGx+zTyEiae11DZPI2hLsDBqQe2z1niX5LujUov nKWMG1tquRceopVjJL/ZI75Y534fdg2s701GfC8zq0HF6NPWqya13uKlUF+N33oAQ48d xEr9L2KS5nx/sHS5VTzAwIzKkcXRHp9XqV3/0= Received: by 10.115.108.1 with SMTP id k1mr7111877wam.35.1225272135333; Wed, 29 Oct 2008 02:22:15 -0700 (PDT) Received: by 10.114.122.8 with HTTP; Wed, 29 Oct 2008 02:22:15 -0700 (PDT) Message-ID: Date: Wed, 29 Oct 2008 09:22:15 +0000 From: "Sian January" To: dev@harmony.apache.org Subject: Re: svn commit: r708756 [1/3] - in /harmony/enhanced/drlvm/trunk/vm: gc_gen/build/ gc_gen/src/common/ gc_gen/src/finalizer_weakref/ gc_gen/src/gen/ gc_gen/src/los/ gc_gen/src/mark_sweep/ gc_gen/src/thread/ gc_gen/src/trace_forward/ gc_gen/src/verify/ MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline X-Virus-Checked: Checked by ClamAV on apache.org Hi Xiao-Feng, This commit looks like quite a large new feature to me. Since we're in feature freeze this week for M8 I really think it should be backed out until after the milestone, as we should be focussing on testing and stability at the moment. Thanks, Sian 2008/10/29 : > Author: xli > Date: Tue Oct 28 20:01:01 2008 > New Revision: 708756 > > URL: http://svn.apache.org/viewvc?rev=708756&view=rev > Log: > HARMONY-5989 : Concurrent GC (Tick) enhancement in scheduling > > Added: > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/thread/conclctor.cpp (with props) > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/thread/conclctor.h (with props) > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/verify/verify_concurrent_mark.cpp (with props) > Removed: > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/thread/marker.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/thread/marker.h > Modified: > harmony/enhanced/drlvm/trunk/vm/gc_gen/build/gc_gen.exp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/collection_scheduler.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/collection_scheduler.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/concurrent_collection_scheduler.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/concurrent_collection_scheduler.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_common.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_common.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_concurrent.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_concurrent.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_barrier.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_barrier.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_class.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_vm.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_metadata.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_metadata.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_options.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_platform.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_properties.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/finalizer_weakref/finalizer_weakref.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/finalizer_weakref/finalizer_weakref_metadata.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/gen/gen.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/los/lspace_alloc_collect.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace_alloc.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace_alloc.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace_chunk.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace_chunk.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace_compact.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace_mark_mostly_concurrent.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace_mark_otf_concurrent.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace_mark_sweep.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace_mark_sweep.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace_sweep.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/wspace_sweep_concurrent.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/thread/collector.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/thread/mutator.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/thread/mutator.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/thread/mutator_alloc.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/trace_forward/fspace_alloc.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/verify/verifier_common.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/verify/verifier_common.h > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/verify/verifier_scanner.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/verify/verify_gc_effect.cpp > harmony/enhanced/drlvm/trunk/vm/gc_gen/src/verify/verify_live_heap.cpp > harmony/enhanced/drlvm/trunk/vm/include/open/gc.h > harmony/enhanced/drlvm/trunk/vm/vmcore/build/vmcore.exp > harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/dll_gc.cpp > harmony/enhanced/drlvm/trunk/vm/vmcore/src/object/vm_arrays.cpp > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/build/gc_gen.exp > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/build/gc_gen.exp?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/build/gc_gen.exp (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/build/gc_gen.exp Tue Oct 28 20:01:01 2008 > @@ -34,6 +34,7 @@ > gc_heap_write_global_slot; > gc_heap_write_ref; > gc_heap_wrote_object; > + gc_heap_copy_object_array; > gc_init; > gc_is_object_pinned; > gc_iterate_heap; > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/collection_scheduler.cpp > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/collection_scheduler.cpp?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/collection_scheduler.cpp (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/collection_scheduler.cpp Tue Oct 28 20:01:01 2008 > @@ -31,24 +31,16 @@ > return; > } > > -void gc_update_collection_scheduler(GC* gc, int64 time_mutator, int64 time_collection) > -{ > - if(gc_is_specify_con_gc()){ > - gc_update_con_collection_scheduler(gc, time_mutator, time_collection); > - } > - return; > -} > > Boolean gc_sched_collection(GC* gc, unsigned int gc_cause) > { > /*collection scheduler only schedules concurrent collection now.*/ > if(GC_CAUSE_CONCURRENT_GC == gc_cause){ > assert(gc_is_specify_con_gc()); > - return gc_sched_con_collection(gc, gc_cause); > + return gc_con_perform_collection( gc ); > }else{ > return FALSE; > } > } > > > - > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/collection_scheduler.h > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/collection_scheduler.h?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/collection_scheduler.h (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/collection_scheduler.h Tue Oct 28 20:01:01 2008 > @@ -26,12 +26,8 @@ > void collection_scheduler_initialize(GC* gc); > void collection_scheduler_destruct(GC* gc); > > -void gc_update_collection_scheduler(GC* gc, int64 time_mutator, int64 time_collection); > Boolean gc_sched_collection(GC* gc, unsigned int gc_cause); > > #endif > > > - > - > - > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/concurrent_collection_scheduler.cpp > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/concurrent_collection_scheduler.cpp?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/concurrent_collection_scheduler.cpp (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/concurrent_collection_scheduler.cpp Tue Oct 28 20:01:01 2008 > @@ -22,7 +22,7 @@ > #include "collection_scheduler.h" > #include "concurrent_collection_scheduler.h" > #include "gc_concurrent.h" > -#include "../thread/marker.h" > +#include "../thread/conclctor.h" > #include "../verify/verify_live_heap.h" > > #define NUM_TRIAL_COLLECTION 2 > @@ -53,6 +53,7 @@ > Boolean gc_use_space_scheduler() > { return cc_scheduler_kind & SPACE_BASED_SCHEDULER; } > > + > static int64 time_delay_to_start_mark = MAX_DELAY_TIME; > static POINTER_SIZE_INT space_threshold_to_start_mark = MAX_SPACE_THRESHOLD; > > @@ -75,6 +76,7 @@ > STD_FREE(gc->collection_scheduler); > } > > + > void gc_decide_cc_scheduler_kind(char* cc_scheduler) > { > string_to_upper(cc_scheduler); > @@ -93,281 +95,248 @@ > gc_enable_time_scheduler(); > } > > -static Boolean time_to_start_mark(GC* gc) > -{ > - if(!gc_use_time_scheduler()) return FALSE; > - > - int64 time_current = time_now(); > - return (time_current - get_collection_end_time()) > time_delay_to_start_mark; > -} > - > -static Boolean space_to_start_mark(GC* gc) > -{ > - if(!gc_use_space_scheduler()) return FALSE; > +/*====================== new scheduler ===================*/ > +extern unsigned int NUM_CON_MARKERS; > +extern unsigned int NUM_CON_SWEEPERS; > +unsigned int gc_get_mutator_number(GC *gc); > + > +#define MOSTLY_CON_MARKER_DIVISION 0.5 > +unsigned int mostly_con_final_marker_num=1; > +unsigned int mostly_con_long_marker_num=1; > + > +unsigned int gc_get_marker_number(GC* gc) { > + unsigned int mutator_num = gc_get_mutator_number(gc); > + unsigned int marker_specified = NUM_CON_MARKERS; > + if(marker_specified == 0) { > + if( gc_is_kind(ALGO_CON_OTF_OBJ) || gc_is_kind(ALGO_CON_OTF_REF) ) { > + marker_specified = min(gc->num_conclctors, mutator_num>>1); > + INFO2("gc.con.scheduler", "[Marker Num] mutator num="< - for(i = 0; i < cc_scheduler->num_window_slots; i++){ > - TRACE2("gc.con.cs",i+1<<"--"<alloc_rate_window[i]); > - } > - > - TRACE2("gc.con.cs","Tracing Rate: "); > - for(i = 0; i < cc_scheduler->num_window_slots; i++){ > - TRACE2("gc.con.cs",i+1<<"--"<trace_rate_window[i]); > - } > - > - float average_alloc_rate = sum_alloc_rate / cc_scheduler->num_window_slots; > - float average_trace_rate = sum_trace_rate / cc_scheduler->num_window_slots; > - float average_space_util_ratio = sum_space_util_ratio / cc_scheduler->num_window_slots; > - > - TRACE2("gc.con.cs","averAllocRate: "< - > - if(average_alloc_rate == 0 ){ > - time_delay_to_start_mark = MIN_DELAY_TIME; > - space_threshold_to_start_mark = MIN_SPACE_THRESHOLD; > - }else if(average_trace_rate == 0){ > - time_delay_to_start_mark = MAX_DELAY_TIME; > - space_threshold_to_start_mark = MAX_SPACE_THRESHOLD; > - }else{ > - float time_alloc_expected = (space_stat->size_free_space * average_space_util_ratio) / average_alloc_rate; > - float time_trace_expected = space_stat->num_live_obj / average_trace_rate; > - TRACE2("gc.con.cs","[GC][Con] expected alloc time "< - > - if(time_alloc_expected > time_trace_expected){ > - if(gc_is_kind(ALGO_CON_OTF_OBJ)||gc_is_kind(ALGO_CON_OTF_REF)){ > - float time_correction = gc_sweep_is_concurrent()? TIME_CORRECTION_OTF_MARK_SWEEP : TIME_CORRECTION_OTF_MARK; > - cc_scheduler->time_delay_to_start_mark = (int64)((time_alloc_expected - time_trace_expected)*time_correction); > - }else if(gc_is_kind(ALGO_CON_MOSTLY)){ > - cc_scheduler->time_delay_to_start_mark = (int64)(time_mutator* TIME_CORRECTION_MOSTLY_MARK); > - } > - }else{ > - cc_scheduler->time_delay_to_start_mark = MIN_DELAY_TIME; > + float util_rate = con_collection_stat->heap_utilization_rate; > + unsigned int space_threshold = 0; > + if( gc_is_kind(ALGO_CON_OTF_OBJ) || gc_is_kind(ALGO_CON_OTF_REF) ) { > + if( con_collection_stat->trace_rate == 0 ) //for initial iteration > + con_collection_stat->trace_rate = con_collection_stat->alloc_rate*20; > + unsigned int alloc_rate = con_collection_stat->alloc_rate; > + if(alloc_ratetrace_rate) { // THRESHOLD = Heap*utilization_rate*(1-alloc_rate/marking_rate), accurate formaler > + float alloc_marking_rate_ratio = (float)(alloc_rate)/con_collection_stat->trace_rate; > + > + space_threshold = (unsigned int)(heap_size*util_rate*(1-alloc_marking_rate_ratio)*conservative_factor); > + } else { //use default > + unsigned int alloc_while_marking = DEFAULT_MARKING_TIME*con_collection_stat->alloc_rate; > + space_threshold = (unsigned int)(heap_size*util_rate) -alloc_while_marking; > } > - > - cc_scheduler->space_threshold_to_start_mark = > - (POINTER_SIZE_INT)(space_stat->size_free_space * ((time_alloc_expected - time_trace_expected) / time_alloc_expected)); > - > - time_delay_to_start_mark = cc_scheduler->time_delay_to_start_mark + time_this_collection_correction; > - space_threshold_to_start_mark = cc_scheduler->space_threshold_to_start_mark; > + } else if(gc_is_kind(ALGO_CON_MOSTLY)) { > + unsigned int alloc_while_marking = DEFAULT_MARKING_TIME*con_collection_stat->alloc_rate; > + space_threshold = (unsigned int)(heap_size*util_rate) -alloc_while_marking; > } > - TRACE2("gc.con.cs","[GC][Con] concurrent marking will delay "<<(unsigned int)(time_delay_to_start_mark>>10)<<" ms "); > - TRACE2("gc.con.cs","[GC][Con] time correction "<<(unsigned int)(time_this_collection_correction>>10)<<" ms "); > > + if( space_threshold > con_collection_stat->surviving_size_at_gc_end ) > + alloc_space_threshold = space_threshold - con_collection_stat->surviving_size_at_gc_end; > + else > + alloc_space_threshold = MIN_SPACE_THRESHOLD; > + > + //INFO2("gc.con.info", "[Threshold] alloc_space_threshold=" << alloc_space_threshold); > + return space_threshold; > } > > -void gc_update_con_collection_scheduler(GC* gc, int64 time_mutator, int64 time_collection) > -{ > - assert(gc_is_specify_con_gc()); > - if(GC_CAUSE_RUNTIME_FORCE_GC == gc->cause) return; > - > - con_collection_scheduler_update_stat(gc, time_mutator, time_collection); > - con_collection_scheduler_update_start_point(gc, time_mutator, time_collection); > - > - return; > -} > - > -Boolean gc_sched_con_collection(GC* gc, unsigned int gc_cause) > +/* this parameters are updated at end of GC */ > +void gc_update_scheduler_parameter( GC *gc ) > { > - if(!try_lock(gc->lock_collect_sched)) return FALSE; > - vm_gc_lock_enum(); > - > - gc_try_finish_con_phase(gc); > - > - if(gc_need_start_con_enum(gc)){ > - /*TODO:Concurrent rootset enumeration.*/ > - assert(0); > - } > - > - if(gc_need_start_con_mark(gc)){ > - INFO2("gc.con.info", "[GC][Con] concurrent mark start ..."); > - gc_start_con_mark(gc); > - vm_gc_unlock_enum(); > - unlock(gc->lock_collect_sched); > - return TRUE; > - } > - > - if(gc_need_start_con_sweep(gc)){ > - gc->num_collections++; > - INFO2("gc.con.info", "[GC][Con] collection number:"<< gc->num_collections<<" "); > - gc_start_con_sweep(gc); > - vm_gc_unlock_enum(); > - unlock(gc->lock_collect_sched); > - return TRUE; > - } > - > - if(gc_need_reset_after_con_collect(gc)){ > - int64 pause_start = time_now(); > - int disable_count = vm_suspend_all_threads(); > - gc_reset_after_con_collect(gc); > - gc_start_mutator_time_measure(gc); > - set_collection_end_time(); > - vm_resume_all_threads(disable_count); > - vm_gc_unlock_enum(); > - INFO2("gc.con.time","[GC][Con]pause(reset collection): "<<((unsigned int)((time_now()-pause_start)>>10))<<" ms "); > - unlock(gc->lock_collect_sched); > - return TRUE; > + Con_Collection_Statistics *con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + last_check_time_point = time_now(); > + > + unsigned int alloc_rate = con_collection_stat->alloc_rate; > + space_check_stage_1 = alloc_rate * trans_time_unit(SPACE_CHECK_STAGE_ONE_TIME); > + space_check_stage_2 = alloc_rate * trans_time_unit(SPACE_CHECK_STAGE_TWO_TIME); > + //INFO2( "gc.con.scheduler", "space_check_stage_1=["< + > + check_delay_time = (con_collection_stat->gc_start_time - con_collection_stat->gc_end_time)>>2; > + //INFO2("gc.con.scheduler", "next check time = [" << trans_time_unit(check_delay_time) << "] ms" ); > + if(gc_is_specify_con_sweep()) { > + conservative_factor = CONSERCATIVE_FACTOR_FULLY_CONCURRENT; > + } > + calculate_start_con_space_threshold(con_collection_stat, gc->committed_heap_size); > +} > + > +void gc_force_update_scheduler_parameter( GC *gc ) > +{ > + last_check_time_point = time_now(); > + //check_delay_time = SPACE_CHECK_STAGE_ONE_TIME; > + check_delay_time = time_now(); > + //INFO2("gc.con.scheduler", "next check time = [" << trans_time_unit(check_delay_time) << "] ms" ); > + Con_Collection_Statistics *con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + con_collection_stat->alloc_rate = DEFAULT_ALLOC_RATE; > +} > + > + > + > +static inline Boolean check_start_mark( GC *gc ) > +{ > + unsigned int new_object_occupied_size = gc_get_mutator_new_obj_size(gc); > + Con_Collection_Statistics *con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + /*just debugging*/ > + float used_rate = (float)(con_collection_stat->surviving_size_at_gc_end + new_object_occupied_size)/gc->committed_heap_size; > + if( alloc_space_threshold < new_object_occupied_size ) { > + INFO2( "gc.con.info", "[Start Con] check has been delayed " << check_delay_time << " us, until ratio at start point="< + return TRUE; > + } > + > + unsigned int free_space = alloc_space_threshold - new_object_occupied_size; > + //INFO2("gc.con.info", "[GC Scheduler debug] alloc_space_threshold="< + int64 last_check_delay = check_delay_time; > + > + if( free_space < space_check_stage_2 ) { > + check_delay_time = SMALL_DELTA; > + } else if( free_space < space_check_stage_1 ) { > + if(check_delay_time>SPACE_CHECK_STAGE_TWO_TIME ) { //if time interval is too small, the alloc rate will not be updated > + unsigned int interval_time = trans_time_unit(time_now() - con_collection_stat->gc_end_time); > + unsigned int interval_space = new_object_occupied_size; > + con_collection_stat->alloc_rate = interval_space/interval_time; > + } > + check_delay_time = ((alloc_space_threshold - new_object_occupied_size)/con_collection_stat->alloc_rate)<<9; > + } > + last_check_time_point = time_now(); > + > + //INFO2("gc.con.info", "[GC Scheduler] check has been delayed=" << last_check_delay << " us, used_rate=" << used_rate << ", free_space=" << free_space << " bytes, next delay=" << check_delay_time << " us" ); > + return FALSE; > +} > + > +static SpinLock check_lock; > +static inline Boolean space_should_start_mark( GC *gc) > +{ > + if( ( time_now() -last_check_time_point ) > check_delay_time && try_lock(check_lock) ) { //first condition is checked frequently, second condition is for synchronization > + Boolean should_start = check_start_mark(gc); > + unlock(check_lock); > + return should_start; > } > - vm_gc_unlock_enum(); > - unlock(gc->lock_collect_sched); > return FALSE; > } > > -extern unsigned int NUM_MARKERS; > - > -unsigned int gc_decide_marker_number(GC* gc) > -{ > - unsigned int num_active_marker; > - Con_Collection_Scheduler* cc_scheduler = (Con_Collection_Scheduler*)gc->collection_scheduler; > +inline static Boolean gc_con_start_condition( GC* gc ) { > + return space_should_start_mark(gc); > +} > > - /*If the number of markers is specfied, just return the specified value.*/ > - if(NUM_MARKERS != 0) return NUM_MARKERS; > > - /*If the number of markers isn't specified, we decide the value dynamically.*/ > - if(NUM_TRIAL_COLLECTION == 0 || gc->num_collections < NUM_TRIAL_COLLECTION){ > - /*Start trial cycle, collection set to 1 in trial cycle and */ > - num_active_marker = 1; > - }else{ > - num_active_marker = cc_scheduler->last_marker_num; > - int64 c_time = cc_scheduler->last_collector_time; > - int64 m_time = cc_scheduler->last_mutator_time; > - int64 d_time = cc_scheduler->time_delay_to_start_mark; > - > - if(num_active_marker == 0) num_active_marker = 1; > - > - if((c_time + d_time) > m_time || (float)d_time < (m_time * 0.25)){ > - TRACE2("gc.con.cs","[GC][Con] increase marker number."); > - num_active_marker ++; > - if(num_active_marker > gc->num_markers) num_active_marker = gc->num_markers; > - }else if((float)d_time > (m_time * 0.6)){ > - TRACE2("gc.con.cs","[GC][Con] decrease marker number."); > - num_active_marker --; > - if(num_active_marker == 0) num_active_marker = 1; > - } > - > - TRACE2("gc.con.cs","[GC][Con] ctime "<<(unsigned)(c_time>>10)<<" mtime "<<(unsigned)(m_time>>10)<<" dtime "<<(unsigned)(d_time>>10)); > - TRACE2("gc.con.cs","[GC][Con] marker num : "< +void gc_reset_after_con_collection(GC *gc); > +void gc_merge_free_list_global(GC *gc); > +void gc_con_stat_information_out(GC *gc); > + > +unsigned int sub_time = 0; > +int64 pause_time = 0; > +/* > + concurrent collection entry function, it may start proper phase according to the current state. > +*/ > +Boolean gc_con_perform_collection( GC* gc ) { > + int disable_count; > + int64 pause_start; > + Con_Collection_Statistics *con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + switch( gc->gc_concurrent_status ) { > + case GC_CON_NIL : > + if( !gc_con_start_condition(gc) ) > + return FALSE; > + if( !state_transformation( gc, GC_CON_NIL, GC_CON_STW_ENUM ) ) > + return FALSE; > + > + gc->num_collections++; > + gc->cause = GC_CAUSE_CONCURRENT_GC; > + > + con_collection_stat->gc_start_time = time_now(); > + disable_count = hythread_reset_suspend_disable(); > + > + gc_start_con_enumeration(gc); //now, it is a stw enumeration > + con_collection_stat->marking_start_time = time_now(); > + state_transformation( gc, GC_CON_STW_ENUM, GC_CON_START_MARKERS ); > + gc_start_con_marking(gc); > + > + INFO2("gc.con.time","[ER] start con pause, ERSM="<<((unsigned int)(time_now()-con_collection_stat->gc_start_time))<<" us "); // ERSM means enumerate rootset and start concurrent marking > + vm_resume_threads_after(); > + hythread_set_suspend_disable(disable_count); > + break; > + > + case GC_CON_BEFORE_SWEEP : > + if(!gc_is_specify_con_sweep()) > + return FALSE; > + if( !state_transformation( gc, GC_CON_BEFORE_SWEEP, GC_CON_SWEEPING ) ) > + return FALSE; > + gc_ms_start_con_sweep((GC_MS*)gc, gc_get_sweeper_numer(gc)); > + break; > + > + > + case GC_CON_BEFORE_FINISH : > + if( !state_transformation( gc, GC_CON_BEFORE_FINISH, GC_CON_RESET ) ) > + return FALSE; > + /* thread should be suspended before the state transformation, > + it is for the case that the heap is exhausted in the reset state, although it is almost impossible */ > + disable_count = vm_suspend_all_threads(); > + pause_start = time_now(); > + > + gc_merge_free_list_global(gc); > + gc_reset_after_con_collection(gc); > + state_transformation( gc, GC_CON_RESET, GC_CON_NIL ); > + pause_time = time_now()-pause_start; > + > + vm_resume_all_threads(disable_count); > + gc_con_stat_information_out(gc); > + INFO2("gc.con.time","[GC][Con]pause(reset collection): CRST="< + break; > + default : > + return FALSE; > } > - > - cc_scheduler->last_marker_num = num_active_marker; > - return num_active_marker; > + return TRUE; > } > > + > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/concurrent_collection_scheduler.h > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/concurrent_collection_scheduler.h?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/concurrent_collection_scheduler.h (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/concurrent_collection_scheduler.h Tue Oct 28 20:01:01 2008 > @@ -20,6 +20,7 @@ > > #define STAT_SAMPLE_WINDOW_SIZE 5 > > +struct GC_MS; > typedef struct Con_Collection_Scheduler { > /*common field*/ > GC* gc; > @@ -46,10 +47,17 @@ > void con_collection_scheduler_initialize(GC* gc); > void con_collection_scheduler_destruct(GC* gc); > > +void gc_update_scheduler_parameter( GC *gc ); > +void gc_force_update_scheduler_parameter( GC *gc ); > +Boolean gc_con_perform_collection( GC* gc ); > Boolean gc_sched_con_collection(GC* gc, unsigned int gc_cause); > -void gc_update_con_collection_scheduler(GC* gc, int64 time_mutator, int64 time_collection); > > void gc_decide_cc_scheduler_kind(char* cc_scheduler); > void gc_set_default_cc_scheduler_kind(); > + > +extern unsigned int mostly_con_final_marker_num; > +extern unsigned int mostly_con_long_marker_num; > + > #endif > > + > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_common.cpp > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_common.cpp?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_common.cpp (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_common.cpp Tue Oct 28 20:01:01 2008 > @@ -22,7 +22,7 @@ > #include "gc_common.h" > #include "gc_metadata.h" > #include "../thread/mutator.h" > -#include "../thread/marker.h" > +#include "../thread/conclctor.h" > #include "../finalizer_weakref/finalizer_weakref.h" > #include "../gen/gen.h" > #include "../mark_sweep/gc_ms.h" > @@ -74,11 +74,19 @@ > static int64 collection_start_time = time_now(); > static int64 collection_end_time = time_now(); > > -int64 get_collection_end_time() > +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_collection_end_time() > -{ collection_end_time = time_now(); } > +void set_gc_end_time() > +{ > + collection_end_time = time_now(); > +} > > void gc_decide_collection_kind(GC* gc, unsigned int cause) > { > @@ -93,17 +101,17 @@ > > } > > -void gc_update_space_stat(GC_MS* gc) > +void gc_update_space_stat(GC* gc) > { > #ifdef USE_UNIQUE_MARK_SWEEP_GC > - gc_ms_update_space_stat((GC_MS*)gc); > + gc_ms_update_space_stat((GC_MS *)gc); > #endif > } > > -void gc_reset_space_stat(GC_MS* gc) > +void gc_reset_space_stat(GC* gc) > { > #ifdef USE_UNIQUE_MARK_SWEEP_GC > - gc_ms_reset_space_stat((GC_MS*)gc); > + gc_ms_reset_space_stat((GC_MS *)gc); > #endif > } > > @@ -118,7 +126,7 @@ > gc_set_rootset(gc); > } > > -void gc_reset_after_collection(GC* gc, int64 time_mutator, int64 time_collection) > +void gc_reset_after_collection(GC* gc) > { > if(gc_is_gen_mode()) gc_prepare_mutator_remset(gc); > > @@ -139,11 +147,9 @@ > #endif > } > > - gc_update_space_stat((GC_MS*)gc); > + gc_update_space_stat(gc); > > - gc_update_collection_scheduler(gc, time_mutator, time_collection); > - > - gc_reset_space_stat((GC_MS*)gc); > + gc_reset_space_stat(gc); > > gc_reset_collector_state(gc); > > @@ -154,23 +160,25 @@ > > } > > +void set_check_delay( int64 mutator_time ); > + > void gc_reclaim_heap(GC* gc, unsigned int gc_cause) > { > INFO2("gc.process", "\nGC: GC start ...\n"); > > - collection_start_time = time_now(); > - int64 time_mutator = collection_start_time - collection_end_time; > - > - gc->num_collections++; > gc->cause = gc_cause; > > if(gc_is_specify_con_gc()){ > - gc_finish_con_GC(gc, time_mutator); > - collection_end_time = time_now(); > + 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. */ > > @@ -207,16 +215,16 @@ > gc_gen_reclaim_heap((GC_Gen*)gc, collection_start_time); > #endif > > - collection_end_time = time_now(); > + set_gc_end_time(); > > - int64 time_collection = collection_end_time - collection_start_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, time_mutator, time_collection); > + gc_reset_after_collection(gc); > > gc_assign_free_area_to_mutators(gc); > > @@ -230,6 +238,3 @@ > > > > - > - > - > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_common.h > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_common.h?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_common.h (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_common.h Tue Oct 28 20:01:01 2008 > @@ -39,7 +39,8 @@ > > #include "../common/gc_for_barrier.h" > > -/* > + > + /* > #define USE_UNIQUE_MARK_SWEEP_GC //define it to only use Mark-Sweep GC (no NOS, no LOS). > #define USE_UNIQUE_MOVE_COMPACT_GC //define it to only use Move-Compact GC (no NOS, no LOS). > */ > @@ -336,19 +337,7 @@ > return TRUE; > } > > -extern volatile Boolean obj_alloced_live; > -inline Boolean is_obj_alloced_live() > -{ return obj_alloced_live; } > > -inline void gc_enable_alloc_obj_live() > -{ > - obj_alloced_live = TRUE; > -} > - > -inline void gc_disable_alloc_obj_live() > -{ > - obj_alloced_live = FALSE; > -} > > /***************************************************************/ > > @@ -391,7 +380,7 @@ > /***************************************************************/ > > /* all GCs inherit this GC structure */ > -struct Marker; > +struct Conclctor; > struct Mutator; > struct Collector; > struct GC_Metadata; > @@ -421,9 +410,12 @@ > unsigned int num_collectors; > unsigned int num_active_collectors; /* not all collectors are working */ > > - Marker** markers; > - unsigned int num_markers; > + /*concurrent markers and collectors*/ > + Conclctor** conclctors; > + unsigned int num_conclctors; > + //unsigned int num_active_conclctors; > unsigned int num_active_markers; > + unsigned int num_active_sweepers; > > /* metadata is the pool for rootset, tracestack, etc. */ > GC_Metadata* metadata; > @@ -443,7 +435,7 @@ > > Space_Tuner* tuner; > > - unsigned int gc_concurrent_status; /*concurrent GC status: only support CONCURRENT_MARK_PHASE now*/ > + volatile unsigned int gc_concurrent_status; /*concurrent GC status: only support CONCURRENT_MARK_PHASE now*/ > Collection_Scheduler* collection_scheduler; > > SpinLock lock_con_mark; > @@ -488,11 +480,15 @@ > > GC* gc_parse_options(); > void gc_reclaim_heap(GC* gc, unsigned int gc_cause); > +void gc_relaim_heap_con_mode( GC *gc); > void gc_prepare_rootset(GC* gc); > > > -int64 get_collection_end_time(); > -void set_collection_end_time(); > +int64 get_gc_start_time(); > +void set_gc_start_time(); > + > +int64 get_gc_end_time(); > +void set_gc_end_time(); > > /* generational GC related */ > > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_concurrent.cpp > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_concurrent.cpp?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_concurrent.cpp (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_concurrent.cpp Tue Oct 28 20:01:01 2008 > @@ -17,325 +17,582 @@ > #include "gc_common.h" > #include "gc_metadata.h" > #include "../thread/mutator.h" > -#include "../thread/marker.h" > +#include "../thread/conclctor.h" > #include "../thread/collector.h" > #include "../finalizer_weakref/finalizer_weakref.h" > #include "../gen/gen.h" > #include "../mark_sweep/gc_ms.h" > +#include "../mark_sweep/wspace_mark_sweep.h" > #include "interior_pointer.h" > #include "collection_scheduler.h" > #include "gc_concurrent.h" > #include "../common/gc_for_barrier.h" > +#include "concurrent_collection_scheduler.h" > +#include "../verify/verify_live_heap.h" > > -volatile Boolean concurrent_in_marking = FALSE; > -volatile Boolean concurrent_in_sweeping = FALSE; > -volatile Boolean mark_is_concurrent = FALSE; > -volatile Boolean sweep_is_concurrent = FALSE; > +struct Con_Collection_Statistics; > > volatile Boolean gc_sweep_global_normal_chunk = FALSE; > > -static void gc_check_con_mark(GC* gc) > +//just debugging > +inline void gc_ms_get_current_heap_usage(GC_MS *gc) > { > - if(!is_mark_finished(gc)){ > - lock(gc->lock_con_mark); > - if(gc_is_kind(ALGO_CON_OTF_OBJ)){ > - gc_ms_start_con_mark((GC_MS*)gc, MIN_NUM_MARKERS); > - }else if(gc_is_kind(ALGO_CON_OTF_REF)){ > - gc_ms_start_con_mark((GC_MS*)gc, MIN_NUM_MARKERS); > - }else if(gc_is_kind(ALGO_CON_MOSTLY)){ > - //ignore. > - } > - unlock(gc->lock_con_mark); > - } > + Con_Collection_Statistics *con_collection_stat = gc_ms_get_con_collection_stat(gc); > + unsigned int new_obj_size = gc_get_mutator_new_obj_size((GC *)gc); > + unsigned int current_size = con_collection_stat->surviving_size_at_gc_end + new_obj_size; > + INFO2("gc.con.scheduler", "[Heap Usage]surviving_size("<surviving_size_at_gc_end<<")+new_obj_size("< + INFO2("gc.con.scheduler", "[Heap Usage]usage rate ("<< (float)current_size/gc->committed_heap_size<<")"); > } > > -static void gc_wait_con_mark_finish(GC* gc) > +void gc_con_update_stat_before_enable_alloc_live(GC *gc) > { > - wait_mark_finish(gc); > - gc_set_barrier_function(WB_REM_NIL); > - gc_set_concurrent_status(gc,GC_CON_STATUS_NIL); > + Con_Collection_Statistics *con_collection_stat = gc_ms_get_con_collection_stat((GC_MS *)gc); > + con_collection_stat->alloc_size_before_alloc_live = gc_get_mutator_new_obj_size(gc); > } > + > +volatile Boolean obj_alloced_live; > > -unsigned int gc_decide_marker_number(GC* gc); > +void gc_enable_alloc_obj_live(GC *gc) > +{ > + gc_con_update_stat_before_enable_alloc_live(gc); > + obj_alloced_live = TRUE; > +} > > -void gc_start_con_mark(GC* gc) > +void gc_mostly_con_update_stat_after_final_marking(GC *gc) > { > - int disable_count; > - unsigned int num_marker; > - > - if(!try_lock(gc->lock_con_mark) || gc_mark_is_concurrent()) return; > - > - lock(gc->lock_enum); > - disable_count = hythread_reset_suspend_disable(); > - int64 pause_start = time_now(); > - gc_set_rootset_type(ROOTSET_IS_OBJ); > - gc_prepare_rootset(gc); > - > - gc_set_concurrent_status(gc, GC_CON_MARK_PHASE); > + POINTER_SIZE_INT num_live_obj = 0; > + POINTER_SIZE_INT size_live_obj = 0; > + POINTER_SIZE_INT num_dirty_obj_traced = 0; > > - num_marker = gc_decide_marker_number(gc); > - > - /*start concurrent mark*/ > - if(gc_is_kind(ALGO_CON_OTF_OBJ)){ > - gc_set_barrier_function(WB_REM_OBJ_SNAPSHOT); > - gc_ms_start_con_mark((GC_MS*)gc, num_marker); > - }else if(gc_is_kind(ALGO_CON_MOSTLY)){ > - gc_set_barrier_function(WB_REM_SOURCE_OBJ); > - gc_ms_start_mostly_con_mark((GC_MS*)gc, num_marker); > - }else if(gc_is_kind(ALGO_CON_OTF_REF)){ > - gc_set_barrier_function(WB_REM_OLD_VAR); > - gc_ms_start_con_mark((GC_MS*)gc, num_marker); > + unsigned int num_conclctors = gc->num_conclctors; > + for( unsigned int i=0; i + Conclctor* conclctor = gc->conclctors[i]; > + if( conclctor->role != CONCLCTOR_ROLE_MARKER ) > + continue; > + num_live_obj += conclctor->live_obj_num; > + size_live_obj += conclctor->live_obj_size; > + num_dirty_obj_traced += conclctor->num_dirty_slots_traced; > + conclctor->live_obj_num = 0; > + conclctor->live_obj_size = 0; > + conclctor->num_dirty_slots_traced = 0; > } > > - unlock(gc->lock_enum); > - INFO2("gc.con.time","[GC][Con]pause(enumeration root): "<<((unsigned int)((time_now()-pause_start)>>10))<<" ms "); > - vm_resume_threads_after(); > - assert(hythread_is_suspend_enabled()); > - hythread_set_suspend_disable(disable_count); > - > - unlock(gc->lock_con_mark); > + Con_Collection_Statistics * con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + con_collection_stat->live_size_marked += size_live_obj; > + INFO2("gc.con.scheduler", "[Final Mark Finish] live_marked_size: "<live_size_marked<<" bytes"); > + > } > > -void mostly_con_mark_terminate_reset(); > -void terminate_mostly_con_mark(); > - > -void gc_finish_con_mark(GC* gc, Boolean need_STW) > +unsigned int gc_get_conclcor_num(GC* gc, unsigned int req_role); > +//called by the marker when it finishes > +void gc_con_update_stat_after_marking(GC *gc) > { > - gc_check_con_mark(gc); > - > - if(gc_is_kind(ALGO_CON_MOSTLY)) > - terminate_mostly_con_mark(); > - > - gc_wait_con_mark_finish(gc); > + POINTER_SIZE_INT num_live_obj = 0; > + POINTER_SIZE_INT size_live_obj = 0; > + POINTER_SIZE_INT num_dirty_obj_traced = 0; > > - int disable_count; > - if(need_STW){ > - /*suspend the mutators.*/ > - lock(gc->lock_enum); > - if(gc_is_kind(ALGO_CON_MOSTLY)){ > - /*In mostly concurrent algorithm, there's a final marking pause. > - Prepare root set for final marking.*/ > - disable_count = hythread_reset_suspend_disable(); > - gc_set_rootset_type(ROOTSET_IS_OBJ); > - gc_prepare_rootset(gc); > - }else{ > - disable_count = vm_suspend_all_threads(); > - } > + unsigned int num_conclctors = gc->num_conclctors; > + for( unsigned int i=0; i + Conclctor* conclctor = gc->conclctors[i]; > + if( conclctor->role != CONCLCTOR_ROLE_MARKER ) > + continue; > + num_live_obj += conclctor->live_obj_num; > + size_live_obj += conclctor->live_obj_size; > + num_dirty_obj_traced += conclctor->num_dirty_slots_traced; > + conclctor->live_obj_num = 0; > + conclctor->live_obj_size = 0; > + conclctor->num_dirty_slots_traced = 0; > } > > - if(gc_is_kind(ALGO_CON_MOSTLY)){ > - /*In mostly concurrent algorithm, there's a final marking pause. > - Suspend the mutators once again and finish the marking phase.*/ > - > - /*prepare dirty object*/ > - gc_prepare_dirty_set(gc); > - > - gc_set_weakref_sets(gc); > - > - /*start STW mark*/ > - gc_ms_start_mostly_con_final_mark((GC_MS*)gc, MIN_NUM_MARKERS); > - > - mostly_con_mark_terminate_reset(); > - gc_clear_dirty_set(gc); > - } > - > - gc_reset_dirty_set(gc); > - > - if(need_STW){ > - unlock(gc->lock_enum); > - if(gc_is_kind(ALGO_CON_MOSTLY)){ > - vm_resume_threads_after(); > - assert(hythread_is_suspend_enabled()); > - hythread_set_suspend_disable(disable_count); > - }else{ > - vm_resume_all_threads(disable_count); > - } > - } > + unsigned int write_barrier_marked_size = gc_get_mutator_write_barrier_marked_size(gc); > + Con_Collection_Statistics * con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + con_collection_stat->live_size_marked = size_live_obj + write_barrier_marked_size; > + //INFO2("gc.con.scheduler", "[Mark Finish] live_marked_size: "<live_size_marked<<" bytes"); > > + /*statistics information update (marking_end_time, trace_rate) */ > + con_collection_stat->marking_end_time = time_now(); > + int64 marking_time = (unsigned int)(con_collection_stat->marking_end_time - con_collection_stat->marking_start_time); > + > + unsigned int heap_size = > + con_collection_stat->surviving_size_at_gc_end + > + gc_get_mutator_new_obj_size(gc); > + > + con_collection_stat->trace_rate = heap_size/trans_time_unit(marking_time); > + > + > + > + /* > + //statistics just for debugging > + unsigned int marker_num = gc_get_conclcor_num(gc, CONCLCTOR_ROLE_MARKER); > + float heap_used_rate = (float)heap_size/gc->committed_heap_size; > + unsigned int new_obj_size_marking = gc_get_mutator_new_obj_size(gc) - con_collection_stat->alloc_size_before_alloc_live; > + unsigned int alloc_rate_marking = new_obj_size_marking/trans_time_unit(con_collection_stat->marking_end_time - con_collection_stat->marking_start_time); > + INFO2("gc.con.scheduler", "[Mark Finish] tracing time=" <live_size_marked<<" bytes"); > + INFO2("gc.con.scheduler", "[Mark Finish] alloc_rate: "<alloc_rate<<" b/ms"); > + INFO2("gc.con.scheduler", "[Mark Finish] trace_rate: "<trace_rate<<" b/ms"); > } > > -int64 gc_get_con_mark_time(GC* gc) > +//Called only when heap is exhuaset > +void gc_con_update_stat_heap_exhausted(GC* gc) > { > - int64 time_mark = 0; > - Marker** markers = gc->markers; > - unsigned int i; > - for(i = 0; i < gc->num_active_markers; i++){ > - Marker* marker = markers[i]; > - if(marker->time_mark > time_mark){ > - time_mark = marker->time_mark; > - } > - marker->time_mark = 0; > - } > - return time_mark; > + unsigned int new_obj_size = gc_get_mutator_new_obj_size(gc); > + Con_Collection_Statistics * con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + con_collection_stat->heap_utilization_rate = (float)(con_collection_stat->surviving_size_at_gc_end + new_obj_size)/gc->committed_heap_size; > + //INFO2("gc.con.scheduler", "[Heap exhausted] surviving size="<surviving_size_at_gc_end<<" bytes, new_obj_size="< + //INFO2("gc.con.scheduler", "[Heap exhausted] current utilization rate="<heap_utilization_rate); > } > > -void gc_start_con_sweep(GC* gc) > + > +//just debugging > +unsigned int gc_con_get_live_size_from_sweeper(GC *gc) > { > - if(!try_lock(gc->lock_con_sweep) || gc_sweep_is_concurrent()) return; > + POINTER_SIZE_INT num_live_obj = 0; > + POINTER_SIZE_INT size_live_obj = 0; > > - /*FIXME: enable finref*/ > - if(!IGNORE_FINREF ){ > - gc_set_obj_with_fin(gc); > - Collector* collector = gc->collectors[0]; > - collector_identify_finref(collector); > -#ifndef BUILD_IN_REFERENT > - }else{ > - gc_set_weakref_sets(gc); > - gc_update_weakref_ignore_finref(gc); > -#endif > + unsigned int num_collectors = gc->num_active_collectors; > + Collector** collectors = gc->collectors; > + unsigned int i; > + for(i = 0; i < num_collectors; i++){ > + Collector* collector = collectors[i]; > + num_live_obj += collector->live_obj_num; > + size_live_obj += collector->live_obj_size; > + collector->live_obj_num = 0; > + collector->live_obj_size = 0; > } > + > + return size_live_obj; > +} > > - gc_set_concurrent_status(gc, GC_CON_SWEEP_PHASE); > +//Called when Con GC ends, must called in a STW period > +void gc_reset_con_space_stat(GC *gc) > +{ > + Con_Collection_Statistics * con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + unsigned int new_obj_size = gc_reset_mutator_new_obj_size((GC *)gc); > > - gc_set_weakref_sets(gc); > + if( gc_is_kind(ALGO_CON_MOSTLY) ) { > + con_collection_stat->live_alloc_size = 0; //mostly concurrent do not make new alloc obj live > + } else if ( gc_is_kind( ALGO_CON_OTF_OBJ ) || gc_is_kind( ALGO_CON_OTF_REF ) ) { > + con_collection_stat->live_alloc_size = new_obj_size - con_collection_stat->alloc_size_before_alloc_live; > + } > + > + /*live obj size at the end of gc = the size of objs belong to {marked_live + alloc_at_marking+alloc_at_sweeping}, > + (for mostly concurrent, con_collection_stat->surviving_size_at_gc_end = con_collection_stat->live_size_marked .)*/ > + con_collection_stat->surviving_size_at_gc_end = con_collection_stat->live_size_marked + con_collection_stat->live_alloc_size; > + //INFO2( "gc.con.scheduler", "[Mark Live] live_size_marked = " << con_collection_stat->live_size_marked << ", live_alloc_size=" << con_collection_stat->live_alloc_size ); > > - /*Note: We assumed that adding entry to weakroot_pool is happened in STW rootset enumeration. > - So, when this assumption changed, we should modified the below function.*/ > - gc_identify_dead_weak_roots(gc); > > - /*start concurrent mark*/ > - gc_ms_start_con_sweep((GC_MS*)gc, MIN_NUM_MARKERS); > + /* > + //just debugging > + if( !gc_is_specify_con_sweep() ) { > + unsigned int surviving_sweeper = gc_con_get_live_size_from_sweeper(gc); > + unsigned int surviving_marker = con_collection_stat->surviving_size_at_gc_end; > + INFO2("gc.con.scheduler", "[Surviving size] by sweeper: " << surviving_sweeper << " bytes, by marker:" << surviving_marker << " bytes, diff=" << (surviving_sweeper - surviving_marker) ); > + }*/ > > - unlock(gc->lock_con_sweep); > + int64 current_time = time_now(); > + > + if(gc->cause != GC_CAUSE_RUNTIME_FORCE_GC ) { > + unsigned int gc_interval_time = 0; > + if( con_collection_stat->pause_start_time != 0 ) //remove the stw time > + gc_interval_time = trans_time_unit(con_collection_stat->pause_start_time - con_collection_stat->gc_end_time); > + else > + gc_interval_time = trans_time_unit(current_time -con_collection_stat->gc_end_time ); > + con_collection_stat->alloc_rate = new_obj_size/gc_interval_time; > + gc_update_scheduler_parameter(gc); > + } else { > + gc_force_update_scheduler_parameter(gc); > + } > + > + con_collection_stat->gc_end_time = current_time; > + > + con_collection_stat->live_size_marked = 0; > + con_collection_stat->live_alloc_size = 0; > + con_collection_stat->alloc_size_before_alloc_live = 0; > + con_collection_stat->marking_start_time = 0; > + con_collection_stat->marking_end_time = 0; > + con_collection_stat->sweeping_time = gc_get_conclctor_time((GC *)gc, CONCLCTOR_ROLE_SWEEPER); //be 0 if not CMCS > + con_collection_stat->pause_start_time = 0; > + assert(con_collection_stat->heap_utilization_rate<1); > + > } > > -void gc_reset_con_sweep(GC* gc) > +void gc_con_stat_information_out(GC *gc) > { > - gc->num_active_collectors = 0; > - gc_sweep_unset_concurrent(); > + Con_Collection_Statistics * con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + INFO2("gc.con.scheduler","=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+="); > + INFO2("gc.con.scheduler", "[Reset] surviving_at_end: "<surviving_size_at_gc_end<<" bytes"); > + INFO2("gc.con.scheduler", "[Reset] alloc_rate: "<alloc_rate<<" b/ms"); > + INFO2("gc.con.scheduler", "[Reset] utilization_rate: "<heap_utilization_rate); > + INFO2("gc.con.scheduler", "[Reset] trace_rate: "<trace_rate<<" b/ms"); > + INFO2("gc.con.scheduler", "[Reset] sweeping time: "<sweeping_time<<" us"); > + INFO2("gc.con.scheduler", "[Reset] gc time: "<< trans_time_unit(con_collection_stat->gc_end_time - con_collection_stat->gc_start_time) ); > + INFO2("gc.con.scheduler","=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+="); > } > > -void gc_wait_con_sweep_finish(GC* gc) > +void gc_reset_after_con_collection(GC* gc) > { > - wait_collection_finish(gc); > - gc_set_concurrent_status(gc,GC_CON_STATUS_NIL); > + assert(gc_is_specify_con_gc()); > + int64 reset_start = time_now(); > + 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 > + } > + reset_start = time_now(); > + gc_reset_con_space_stat(gc); > + gc_clear_conclctor_role(gc); > + vm_reclaim_native_objs(); > } > > -void gc_finish_con_sweep(GC * gc) > + > + > +void gc_set_default_con_algo() > { > - gc_wait_con_sweep_finish(gc); > + assert((GC_PROP & ALGO_CON_MASK) == 0); > + GC_PROP |= ALGO_CON_OTF_OBJ; > } > > -void gc_try_finish_con_phase(GC * gc) > +void gc_decide_con_algo(char* concurrent_algo) > { > - /*Note: we do not finish concurrent mark here if we do not want to start concurrent sweep.*/ > - if(gc_con_is_in_marking(gc) && is_mark_finished(gc)){ > - /*Although all conditions above are satisfied, we can not guarantee concurrent marking is finished. > - Because, sometimes, the concurrent marking has not started yet. We check the concurrent mark lock > - here to guarantee this occasional case.*/ > - if(try_lock(gc->lock_con_mark)){ > - unlock(gc->lock_con_mark); > - gc_finish_con_mark(gc, TRUE); > - } > - } > - > - if(gc_con_is_in_sweeping(gc) && is_collector_finished(gc)){ > - //The reason is same as concurrent mark above. > - if(try_lock(gc->lock_con_sweep)){ > - unlock(gc->lock_con_sweep); > - gc_finish_con_sweep(gc); > - } > + string_to_upper(concurrent_algo); > + GC_PROP &= ~ALGO_CON_MASK; > + if(!strcmp(concurrent_algo, "OTF_OBJ")){ > + GC_PROP |= ALGO_CON_OTF_OBJ; > + }else if(!strcmp(concurrent_algo, "MOSTLY_CON")){ > + GC_PROP |= ALGO_CON_MOSTLY; > + }else if(!strcmp(concurrent_algo, "OTF_SLOT")){ > + GC_PROP |= ALGO_CON_OTF_REF; > } > } > > -void gc_reset_after_collection(GC* gc, int64 time_mutator, int64 time_collection); > > -void gc_reset_after_con_collect(GC* gc) > +/* > + gc start enumeration phase, now, it is in a stop-the-world manner > +*/ > +void gc_start_con_enumeration(GC * gc) > { > - assert(gc_is_specify_con_gc()); > - > - int64 time_mutator = gc_get_mutator_time(gc); > - int64 time_collection = gc_get_collector_time(gc) + gc_get_marker_time(gc); > + gc_set_rootset_type(ROOTSET_IS_OBJ); > + gc_prepare_rootset(gc); > +} > > - gc_reset_interior_pointer_table(); > +//unsigned int gc_decide_marker_number(GC* gc); > +unsigned int gc_get_marker_number(GC* gc); > +/* gc start marking phase */ > +void gc_start_con_marking(GC *gc) > +{ > + unsigned int num_marker; > + num_marker = gc_get_marker_number(gc); > > - gc_reset_after_collection(gc, time_mutator, time_collection); > - > - if(gc_mark_is_concurrent()){ > - gc_reset_con_mark(gc); > + if(gc_is_kind(ALGO_CON_OTF_OBJ)) { > + gc_enable_alloc_obj_live(gc); > + gc_set_barrier_function(WB_REM_OBJ_SNAPSHOT); > + gc_ms_start_con_mark((GC_MS*)gc, num_marker); > + } else if(gc_is_kind(ALGO_CON_MOSTLY)) { > + gc_set_barrier_function(WB_REM_SOURCE_OBJ); > + gc_ms_start_mostly_con_mark((GC_MS*)gc, num_marker); > + } else if(gc_is_kind(ALGO_CON_OTF_REF)) { > + gc_enable_alloc_obj_live(gc); > + gc_set_barrier_function(WB_REM_OLD_VAR); > + gc_ms_start_con_mark((GC_MS*)gc, num_marker); > } > +} > + > > - if(gc_sweep_is_concurrent()){ > - gc_reset_con_sweep(gc); > +/* > + gc start sweeping phase > +*/ > +void gc_prepare_sweeping(GC *gc) { > + INFO2("gc.con.info", "Concurrent collection, current collection = " << gc->num_collections ); > + /*FIXME: enable finref*/ > + if(!IGNORE_FINREF ){ > + gc_set_obj_with_fin(gc); > + Collector* collector = gc->collectors[0]; > + collector_identify_finref(collector); > + #ifndef BUILD_IN_REFERENT > + } else { > + conclctor_set_weakref_sets(gc); > + gc_update_weakref_ignore_finref(gc); > + #endif > } > + gc_identify_dead_weak_roots(gc); > } > > -void gc_finish_con_GC(GC* gc, int64 time_mutator) > -{ > +int64 get_last_check_point(); > +// for the case pure stop the world > +static void gc_partial_con_PSTW( GC *gc) { > int64 time_collection_start = time_now(); > - > + INFO2("gc.space.stat","Stop-the-world collection = "<num_collections<<""); > + INFO2("gc.con.info", "from last check point =" << (unsigned int)(time_collection_start -get_last_check_point()) ); > + // stop the world enumeration > gc->num_collections++; > - > - 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); > - > - if(gc_sweep_is_concurrent()){ > - if(gc_con_is_in_sweeping()) > - gc_finish_con_sweep(gc); > - }else{ > - if(gc_con_is_in_marking()){ > - gc_finish_con_mark(gc, FALSE); > - } > - gc->in_collection = TRUE; > - gc_reset_mutator_context(gc); > - if(!IGNORE_FINREF ) gc_set_obj_with_fin(gc); > - gc_ms_reclaim_heap((GC_MS*)gc); > - } > - > - int64 time_collection = 0; > - if(gc_mark_is_concurrent()){ > - time_collection = gc_get_con_mark_time(gc); > - gc_reset_con_mark(gc); > - }else{ > - time_collection = time_now()-time_collection_start; > - } > + > + if(gc->cause != GC_CAUSE_RUNTIME_FORCE_GC ) { > + unsigned int new_obj_size = gc_get_mutator_new_obj_size(gc); > + Con_Collection_Statistics * con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + con_collection_stat->heap_utilization_rate = (float)(con_collection_stat->surviving_size_at_gc_end + new_obj_size)/gc->committed_heap_size; > + } > + > + //reclaim heap > + gc_reset_mutator_context(gc); > + if(!IGNORE_FINREF ) gc_set_obj_with_fin(gc); > + gc_ms_reclaim_heap((GC_MS*)gc); > + > + //update live size > + gc_PSTW_update_stat_after_marking(gc); > + > + // reset the collection and resume mutators > + gc_reset_after_con_collection(gc); > > - if(gc_sweep_is_concurrent()){ > - gc_reset_con_sweep(gc); > - } > - > - gc_reset_after_collection(gc, time_mutator, time_collection); > - > - gc_start_mutator_time_measure(gc); > - > + set_con_nil(gc); // concurrent scheduling will continue after mutators are resumed > vm_resume_threads_after(); > assert(hythread_is_suspend_enabled()); > - hythread_set_suspend_disable(disable_count); > - int64 pause_time = time_now()-time_collection_start; > - > - if(GC_CAUSE_RUNTIME_FORCE_GC == gc->cause){ > - INFO2("gc.con.time","[GC][Con]pause( Forcing GC ): "<<((unsigned int)(pause_time>>10))<<" ms "); > - }else{ > - INFO2("gc.con.time","[GC][Con]pause( Heap exhuasted ): "<<((unsigned int)(pause_time>>10))<<" ms "); > - } > - return; > + hythread_set_suspend_disable(disable_count); > } > > -void gc_set_default_con_algo() > -{ > - assert((GC_PROP & ALGO_CON_MASK) == 0); > - GC_PROP |= ALGO_CON_OTF_OBJ; > +void terminate_mostly_con_mark(); > +void wspace_mostly_con_final_mark( GC *gc ); > + > +// for the case concurrent marking is not finished before heap is exhausted > +static void gc_partial_con_PMSS(GC *gc) { > + INFO2("gc.con.info", "[PMSS] Heap has been exhuasted, current collection = " << gc->num_collections ); > + // wait concurrent marking finishes > + int64 wait_start = time_now(); > + gc_disable_alloc_obj_live(gc); // in the STW manner, so we can disable it at anytime before the mutators are resumed > + //in the stop the world phase (only conclctors is running at the moment), so the spin lock will not lose more performance > + while( gc->gc_concurrent_status == GC_CON_START_MARKERS || > + gc->gc_concurrent_status == GC_CON_TRACING || > + gc->gc_concurrent_status == GC_CON_TRACE_DONE) > + { > + vm_thread_yield(); //let the unfinished marker run > + } > + > + /*just debugging*/ > + gc_ms_get_current_heap_usage((GC_MS *)gc); > + int64 pause_time = time_now() - wait_start; > + INFO2("gc.con.info", "[PMSS]wait marking time="< + Con_Collection_Statistics *con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + unsigned int marking_time_shortage = (unsigned int)(con_collection_stat->marking_end_time - wait_start); > + INFO2("gc.con.info", "[PMSS] marking late time [" << marking_time_shortage << "] us" ); > + > + // start STW reclaiming heap > + gc_con_update_stat_heap_exhausted(gc); // calculate util rate > + gc_reset_mutator_context(gc); > + if(!IGNORE_FINREF ) gc_set_obj_with_fin(gc); > + gc_ms_reclaim_heap((GC_MS*)gc); > + > + // reset after partial stop the world collection > + gc_reset_after_con_collection(gc); > + set_con_nil(gc); > +} > + > +// only when current sweep is set to false > +static void gc_partial_con_CMSS(GC *gc) { > + > + INFO2("gc.con.info", "[CMSS] Heap has been exhuasted, current collection = " << gc->num_collections ); > + gc_disable_alloc_obj_live(gc); // in the STW manner, so we can disable it at anytime before the mutators are resumed > + > + /*just debugging*/ > + gc_ms_get_current_heap_usage((GC_MS *)gc); > + Con_Collection_Statistics *con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + unsigned int from_marking_end = (unsigned int)(time_now() - con_collection_stat->marking_end_time); > + INFO2("gc.con.info", "[CMSS] marking early time [" << from_marking_end << "] us" ); > + > + gc_con_update_stat_heap_exhausted(gc); // calculate util rate > + > + // start reclaiming heap, it will skip the marking phase > + gc_reset_mutator_context(gc); > + if(!IGNORE_FINREF ) gc_set_obj_with_fin(gc); > + gc_ms_reclaim_heap((GC_MS*)gc); > + > + // reset after partial stop the world collection > + gc_reset_after_con_collection(gc); > + set_con_nil(gc); > +} > + > +void gc_merge_free_list_global(GC *gc); > +//for the case concurrent marking and partial concurrent sweeping > +static void gc_partial_con_CMPS( GC *gc ) { > + > + while(gc->gc_concurrent_status == GC_CON_SWEEPING || gc->gc_concurrent_status == GC_CON_SWEEP_DONE) { > + vm_thread_yield(); //let the unfinished sweeper run > + } > + gc_merge_free_list_global(gc); > + // reset after partial stop the world collection > + gc_reset_after_con_collection(gc); > + set_con_nil(gc); > +} > + > + > +inline static void partial_stop_the_world_info( unsigned int type, unsigned int pause_time ) { > + switch( type ) { > + case GC_PARTIAL_PSTW : > + INFO2("gc.con.time","[PT] pause ( Heap exhuasted ), PSTW=" << pause_time << " us"); > + break; > + case GC_PARTIAL_PMSS : > + INFO2("gc.con.time","[PT] pause ( Heap exhuasted ), PMSS=" << pause_time << " us"); > + break; > + case GC_PARTIAL_CMPS : > + INFO2("gc.con.time","[PT] pause ( Heap exhuasted ), CMPS=" << pause_time << " us"); > + break; > + case GC_PARTIAL_CMSS : > + INFO2("gc.con.time","[PT] pause ( Heap exhuasted ), CMSS=" << pause_time << " us"); > + break; > + case GC_PARTIAL_FCSR : > + INFO2("gc.con.time","[PT] pause ( Heap exhuasted ), FCSR=" << pause_time << " us"); > + break; > + } > +} > + > +static unsigned int gc_con_heap_full_mostly_con( GC *gc ) > +{ > + while( gc->gc_concurrent_status == GC_CON_START_MARKERS ) { // we should enumerate rootset after old rootset is traced > + vm_thread_yield(); > + } > + > + int64 final_start = time_now(); > + int disable_count = hythread_reset_suspend_disable(); > + gc_set_rootset_type(ROOTSET_IS_OBJ); > + gc_prepare_rootset(gc); > + > + gc_set_barrier_function(WB_REM_NIL); //in stw phase, so we can remove write barrier at any time > + terminate_mostly_con_mark(); // terminate current mostly concurrent marking > + > + //in the stop the world phase (only conclctors is running at the moment), so the spin lock will not lose more performance > + while(gc->gc_concurrent_status == GC_CON_TRACING) { > + vm_thread_yield(); //let the unfinished marker run > + } > + > + //final marking phase > + gc_clear_conclctor_role(gc); > + wspace_mostly_con_final_mark(gc); > + > + /*just debugging*/ > + int64 final_time = time_now() - final_start; > + INFO2("gc.scheduler", "[MOSTLY_CON] final marking time=" << final_time << " us"); > + gc_ms_get_current_heap_usage((GC_MS *)gc); > + > + // start STW reclaiming heap > + gc_con_update_stat_heap_exhausted(gc); // calculate util rate > + gc_reset_mutator_context(gc); > + if(!IGNORE_FINREF ) gc_set_obj_with_fin(gc); > + gc_ms_reclaim_heap((GC_MS*)gc); > + > + // reset after partial stop the world collection > + gc_reset_after_con_collection(gc); > + set_con_nil(gc); > + > + vm_resume_threads_after(); > + hythread_set_suspend_disable(disable_count); > + return GC_PARTIAL_PMSS; > + > +} > + > +static unsigned int gc_con_heap_full_otf( GC *gc ) > +{ > + unsigned int partial_type; //for time measuring and debugging > + int disable_count = vm_suspend_all_threads(); > + Con_Collection_Statistics *con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + con_collection_stat->pause_start_time = time_now(); > + switch(gc->gc_concurrent_status) { > + case GC_CON_START_MARKERS : > + case GC_CON_TRACING : > + case GC_CON_TRACE_DONE : > + partial_type = GC_PARTIAL_PMSS; > + gc_partial_con_PMSS(gc); > + break; > + case GC_CON_BEFORE_SWEEP : // only when current sweep is set to false > + partial_type = GC_PARTIAL_CMSS; > + gc_partial_con_CMSS(gc); > + break; > + case GC_CON_SWEEPING : > + case GC_CON_SWEEP_DONE : > + partial_type = GC_PARTIAL_CMPS; > + gc_partial_con_CMPS(gc); > + break; > + case GC_CON_BEFORE_FINISH : //heap can be exhausted when sweeping finishes, very rare > + partial_type = GC_PARTIAL_FCSR; > + gc_merge_free_list_global(gc); > + gc_reset_after_con_collection(gc); > + set_con_nil(gc); > + break; > + case GC_CON_RESET : > + case GC_CON_NIL : > + case GC_CON_STW_ENUM : > + /*do nothing, if still in gc_con_reset, will wait to finish after resuming. this case happens rarely*/ > + partial_type = GC_PARTIAL_FCSR; > + break; > + /* other state is illegal here */ > + default: > + INFO2("gc.con.info", "illegal state when the heap is out [" << gc->gc_concurrent_status << "]"); > + RAISE_ERROR; > + } > + vm_resume_all_threads(disable_count); > + return partial_type; > } > > -void gc_decide_con_algo(char* concurrent_algo) > -{ > - string_to_upper(concurrent_algo); > - GC_PROP &= ~ALGO_CON_MASK; > - if(!strcmp(concurrent_algo, "OTF_OBJ")){ > - GC_PROP |= ALGO_CON_OTF_OBJ; > - }else if(!strcmp(concurrent_algo, "MOSTLY_CON")){ > - GC_PROP |= ALGO_CON_MOSTLY; > - }else if(!strcmp(concurrent_algo, "OTF_SLOT")){ > - GC_PROP |= ALGO_CON_OTF_REF; > +void gc_con_stat_information_out(GC *gc); > +/* > +this method is called before STW gc start, there is a big lock outside > +*/ > +void gc_wait_con_finish( GC* gc ) { > + int64 time_collection_start = time_now(); > + unsigned int partial_type; //for time measuring and debugging > + > + /* cocurrent gc is idle */ > + if( state_transformation( gc, GC_CON_NIL, GC_CON_DISABLE ) ) { // for the race condition of con schduling and STW gc > + Con_Collection_Statistics *con_collection_stat = gc_ms_get_con_collection_stat((GC_MS*)gc); > + con_collection_stat->gc_start_time = time_now(); > + con_collection_stat->pause_start_time = con_collection_stat->gc_start_time; > + partial_type = GC_PARTIAL_PSTW; > + gc_partial_con_PSTW( gc ); > + } else { > + while(gc->gc_concurrent_status == GC_CON_STW_ENUM ) { //wait concurrent gc finish enumeration > + hythread_safe_point(); > + vm_thread_yield(); > + } > + if( gc_is_kind(ALGO_CON_MOSTLY) ) > + partial_type = gc_con_heap_full_mostly_con(gc); > + else if( gc_is_kind(ALGO_CON_OTF_OBJ) || gc_is_kind(ALGO_CON_OTF_REF) ) { > + partial_type = gc_con_heap_full_otf(gc); > + if(gc->gc_concurrent_status == GC_CON_RESET) { > + while( gc->gc_concurrent_status == GC_CON_RESET ) { //wait concurrent to finish > + hythread_safe_point(); > + vm_thread_yield(); > + } > + } > + } > + else > + RAISE_ERROR; > + } > + > + int64 pause_time = time_now()-time_collection_start; > + gc_con_stat_information_out(gc); > + if(GC_CAUSE_RUNTIME_FORCE_GC == gc->cause) { > + INFO2("gc.con.time","[GC][Con]pause( Forcing GC ): "<<(unsigned int)(pause_time)<<" us "); > + } else { > + partial_stop_the_world_info( partial_type, (unsigned int)pause_time ); > } > } > + > + > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_concurrent.h > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_concurrent.h?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_concurrent.h (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_concurrent.h Tue Oct 28 20:01:01 2008 > @@ -19,21 +19,69 @@ > #define _GC_CONCURRENT_H_ > #include "gc_common.h" > > -enum GC_CONCURRENT_STATUS{ > - GC_CON_STATUS_NIL = 0x00, > - GC_CON_MARK_PHASE = 0x01, > - GC_MOSTLY_CON_FINAL_MARK_PHASE = 0x11, // for mostly concurrent only. > - GC_CON_SWEEP_PHASE = 0x02 > + > +#define RATE_CALCULATE_DENOMINATOR_FACTOR 10; //trans us to ms > +inline unsigned int trans_time_unit(int64 x) > +{ > + int64 result = x>>10; > + if(result) return (unsigned int)result; > + return 1; > +} > + > +#define RAISE_ERROR assert(0); > +/* concurrent collection states in new design */ > +enum GC_CONCURRENT_STATUS { > + GC_CON_NIL = 0x00, > + GC_CON_STW_ENUM = 0x01, > + GC_CON_START_MARKERS = 0x02, > + GC_CON_TRACING = 0x03, > + GC_CON_TRACE_DONE = 0x04, > + GC_CON_BEFORE_SWEEP = 0x05, > + GC_CON_SWEEPING = 0x06, > + GC_CON_SWEEP_DONE = 0x07, > + GC_CON_BEFORE_FINISH = 0x08, > + GC_CON_RESET = 0x09, > + GC_CON_DISABLE = 0x0A, > +}; > + > +// this type is just for debugging and time measuring > +enum GC_PARTIAL_STW_TYPE { > + GC_PARTIAL_PSTW = 0x00, //pure stop the world > + GC_PARTIAL_PMSS = 0x01, //concurrent marking has finished and stop the world sweeping > + GC_PARTIAL_CMSS = 0x02, // partial concurrent marking and stop the world sweeping > + GC_PARTIAL_CMPS = 0x03, //concurrent marking and sweeping > + GC_PARTIAL_FCSR = 0x04, //fully concurrent marking and sweeping, but stw finish reset > }; > > enum HANDSHAKE_SINGAL{ > HSIG_MUTATOR_SAFE = 0x0, > - > HSIG_DISABLE_SWEEP_LOCAL_CHUNKS = 0x01, > HSIG_DISABLE_SWEEP_GLOBAL_CHUNKS = 0x02, > HSIG_MUTATOR_ENTER_ALLOC_MARK = 0x03, > }; > > +typedef struct Con_Collection_Statistics { > + POINTER_SIZE_INT live_size_marked; //marked objects size > + POINTER_SIZE_INT alloc_size_before_alloc_live; //alloc objects size before marking > + POINTER_SIZE_INT live_alloc_size; > + POINTER_SIZE_INT surviving_size_at_gc_end; //total live object size when gc is ended > + > + POINTER_SIZE_INT trace_rate; //bytes per ms > + POINTER_SIZE_INT alloc_rate; //bytes per ms > + > + float heap_utilization_rate; > + > + int64 gc_start_time; > + int64 gc_end_time; > + > + int64 marking_start_time; > + int64 marking_end_time; > + > + int64 sweeping_time; > + int64 pause_start_time; > + > +} Con_Space_Statistics; > + > inline void gc_set_con_gc(unsigned int con_phase) > { GC_PROP |= con_phase; } > > @@ -58,107 +106,101 @@ > inline Boolean gc_is_specify_con_sweep() > { return (GC_PROP & ALGO_CON_SWEEP) == ALGO_CON_SWEEP; } > > -extern volatile Boolean concurrent_in_marking; > -extern volatile Boolean concurrent_in_sweeping; > -extern volatile Boolean mark_is_concurrent; > -extern volatile Boolean sweep_is_concurrent; > > -inline Boolean gc_mark_is_concurrent() > -{ > - return mark_is_concurrent; > -} > +extern volatile Boolean obj_alloced_live; > > -inline void gc_mark_set_concurrent() > -{ > - if(gc_is_kind(ALGO_CON_OTF_OBJ) || gc_is_kind(ALGO_CON_OTF_REF)) > - gc_enable_alloc_obj_live(); > - mark_is_concurrent = TRUE; > -} > +inline Boolean is_obj_alloced_live() > +{ return obj_alloced_live; } > > -inline void gc_mark_unset_concurrent() > -{ > - gc_disable_alloc_obj_live(); > - mark_is_concurrent = FALSE; > +inline void gc_disable_alloc_obj_live(GC *gc) > +{ > + obj_alloced_live = FALSE; > } > > -inline Boolean gc_con_is_in_marking() > +void gc_enable_alloc_obj_live(GC * gc); > + > +/* > + tranform the states across the collection process, > + which should be a atomic operation because there are several collector run parallel > +*/ > +inline Boolean state_transformation( GC* gc, unsigned int from_state, unsigned int to_state ) > { > - return concurrent_in_marking; > + unsigned int old_state = apr_atomic_cas32( &gc->gc_concurrent_status, to_state, from_state ); > + if( old_state != from_state ) > + return FALSE; > + else > + return TRUE; > } > > -inline Boolean gc_con_is_in_marking(GC* gc) > -{ > - return gc->gc_concurrent_status == GC_CON_MARK_PHASE; > +/* set concurrent to idle, > + Or enable concurrent gc, called when STW gc finishes > + */ > +inline void set_con_nil( GC *gc ) { > + apr_atomic_set32( &gc->gc_concurrent_status, GC_CON_NIL ); > } > > -inline Boolean gc_sweep_is_concurrent() > -{ > - return sweep_is_concurrent; > + > +/* gc start enumeration phase, now, it is in a stop-the-world manner */ > +void gc_start_con_enumeration(GC * gc); > + > +/* gc start marking phase */ > +void gc_start_con_marking(GC *gc); > + > + > +/* prepare for sweeping */ > +void gc_prepare_sweeping(GC *gc); > + > +/* gc start sweeping phase */ > +void gc_start_con_sweeping(GC *gc); > + > +/* gc finish concurrent collection */ > +void gc_con_final_work(GC* gc); > + > + > +/* gc wait cocurrent collection finishes */ > +void gc_wait_con_finish( GC* gc ); > + > +/* is in gc marking phase */ > +inline Boolean in_con_marking_phase( GC *gc ) { > + unsigned int status = gc->gc_concurrent_status; > + return (status == GC_CON_TRACING) || (status == GC_CON_TRACE_DONE); > } > > -inline void gc_sweep_set_concurrent() > -{ > - sweep_is_concurrent = TRUE; > +/* is in gc sweeping phase */ > +inline Boolean in_con_sweeping_phase( GC *gc ) { > + unsigned int status = gc->gc_concurrent_status; > + return (status == GC_CON_SWEEPING) || (status == GC_CON_SWEEP_DONE); > } > > -inline void gc_sweep_unset_concurrent() > -{ > - sweep_is_concurrent = FALSE; > +inline Boolean in_con_idle( GC *gc ) { > + return gc->gc_concurrent_status == GC_CON_NIL; > } > > -inline Boolean gc_con_is_in_sweeping() > -{ > - return concurrent_in_sweeping; > +inline Boolean gc_con_is_in_STW( GC *gc ) { > + return gc->gc_concurrent_status == GC_CON_DISABLE; > } > > -inline Boolean gc_con_is_in_sweeping(GC* gc) > -{ > - return gc->gc_concurrent_status == GC_CON_SWEEP_PHASE; > +/* is gc ready to sweeping */ > +inline Boolean in_con_ready_sweep( GC *gc ) { > + return gc->gc_concurrent_status == GC_CON_BEFORE_SWEEP; > } > > -inline void gc_set_concurrent_status(GC*gc, unsigned int status) > -{ > - /*Reset status*/ > - concurrent_in_marking = FALSE; > - concurrent_in_sweeping = FALSE; > - > - gc->gc_concurrent_status = status; > - switch(status){ > - case GC_CON_MARK_PHASE: > - gc_mark_set_concurrent(); > - concurrent_in_marking = TRUE; > - break; > - case GC_CON_SWEEP_PHASE: > - gc_sweep_set_concurrent(); > - concurrent_in_sweeping = TRUE; > - break; > - default: > - assert(!concurrent_in_marking && !concurrent_in_sweeping); > - } > +/* is gc sweeping */ > +inline Boolean in_con_sweep( GC *gc ) { > + return ( gc->gc_concurrent_status == GC_CON_SWEEPING || gc->gc_concurrent_status == GC_CON_SWEEP_DONE ); > > - return; > } > > -void gc_reset_con_mark(GC* gc); > -void gc_start_con_mark(GC* gc); > -void gc_finish_con_mark(GC* gc, Boolean need_STW); > -int64 gc_get_con_mark_time(GC* gc); > - > -void gc_start_con_sweep(GC* gc); > -void gc_finish_con_sweep(GC * gc); > +void gc_con_update_stat_after_marking( GC *gc ); > > -void gc_reset_after_con_collect(GC* gc); > -void gc_try_finish_con_phase(GC * gc); > > void gc_decide_con_algo(char* concurrent_algo); > void gc_set_default_con_algo(); > > -void gc_reset_con_sweep(GC* gc); > - > -void gc_finish_con_GC(GC* gc, int64 time_mutator); > > extern volatile Boolean gc_sweep_global_normal_chunk; > > + > inline Boolean gc_is_sweep_global_normal_chunk() > { return gc_sweep_global_normal_chunk; } > > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_barrier.cpp > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_barrier.cpp?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_barrier.cpp (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_barrier.cpp Tue Oct 28 20:01:01 2008 > @@ -18,13 +18,17 @@ > /** > * @author Xiao-Feng Li, 2006/10/05 > */ > - > + > +#include > +#include > #include "../gen/gen.h" > #include "../thread/mutator.h" > #include "gc_for_barrier.h" > #include "../mark_sweep/wspace_mark_sweep.h" > #include "../common/gc_concurrent.h" > +#include "../common/gc_common.h" > #include "../finalizer_weakref/finalizer_weakref.h" > +#include "../verify/verify_live_heap.h" > > > /* All the write barrier interfaces need cleanup */ > @@ -117,10 +121,8 @@ > Mutator *mutator = (Mutator *)gc_get_tls(); > > //FIXME: Release lock. > - lock(mutator->dirty_set_lock); > obj_dirty_in_table((Partial_Reveal_Object *) p_obj_holding_ref); > - mutator_dirtyset_add_entry(mutator, (Partial_Reveal_Object*)p_obj_holding_ref); > - unlock(mutator->dirty_set_lock); > + mutator_dirtyset_add_entry(mutator, (Partial_Reveal_Object*)p_obj_holding_ref); > } > } > > @@ -204,7 +206,8 @@ > mutator_dirtyset_add_entry(mutator, obj_to_snapshot); > } > } > - obj_mark_black_in_table((Partial_Reveal_Object *) p_obj_holding_ref); > + obj_mark_gray_in_table((Partial_Reveal_Object *) p_obj_holding_ref); // now, the black-only obj (no gray bit been set) will also be scaned by marker, here mark it to gray to prevent this, just a workaround > + obj_mark_black_in_table((Partial_Reveal_Object *) p_obj_holding_ref, mutator); > obj_dirty_in_table((Partial_Reveal_Object *) p_obj_holding_ref); > } > } > @@ -215,32 +218,141 @@ > REF* p_obj_slot = (REF*) p_slot ; > Partial_Reveal_Object* p_obj = (Partial_Reveal_Object*)read_slot(p_obj_slot); > if(p_obj && obj_need_remember_oldvar(p_obj)){ > + mutator->dirty_obj_num++; > mutator_dirtyset_add_entry(mutator, p_obj); > } > } > > +/* > +static void write_barrier_for_check(Managed_Object_Handle p_obj_holding_ref,Managed_Object_Handle *p_slot, Managed_Object_Handle p_target) > +{ > + //Mutator *mutator = (Mutator *)gc_get_tls(); > + > + Partial_Reveal_Object* src_obj = (Partial_Reveal_Object*)p_obj_holding_ref; > + Partial_Reveal_Object* sub_obj = (Partial_Reveal_Object*)read_slot((REF*) p_slot); > + Partial_Reveal_Object* target_obj = (Partial_Reveal_Object*)p_target; > + > + if(src_obj && (!obj_is_mark_black_in_table(src_obj))){ > + INFO2("gc.verifier", "[write_barrier_for_check] [Src]"); > + analyze_bad_obj(src_obj); > + RAISE_ERROR; > + } > + > + if(sub_obj && (!obj_is_mark_black_in_table(sub_obj))){ > + INFO2("gc.verifier", "[write_barrier_for_check] [Sub]"); > + analyze_bad_obj(sub_obj); > + INFO2("gc.verifier", "[source object]"); > + analyze_bad_obj(src_obj); > + //RAISE_ERROR; > + return; > + } > + > + if(target_obj && (!obj_is_mark_black_in_table(target_obj))){ > + INFO2("gc.verifier", "[write_barrier_for_check] [Target]"); > + analyze_bad_obj(target_obj); > + RAISE_ERROR; > + } > + > + *p_slot = p_target; > +} > +*/ > //=========================================== > > /* The following routines were supposed to be the only way to alter any value in gc heap. */ > void gc_heap_write_ref (Managed_Object_Handle p_obj_holding_ref, unsigned offset, Managed_Object_Handle p_target) > { assert(0); } > > -void gc_heap_wrote_object (Managed_Object_Handle p_obj_written) > + > +Boolean gc_heap_copy_object_array(Managed_Object_Handle src_array, unsigned int src_start, Managed_Object_Handle dst_array, unsigned int dst_start, unsigned int length) > +{ > + > + > + GC_VTable_Info *src_gcvt = obj_get_gcvt((Partial_Reveal_Object*)src_array); > + GC_VTable_Info *dst_gcvt = obj_get_gcvt((Partial_Reveal_Object*)dst_array); > + > + Class_Handle src_class = src_gcvt->gc_clss; > + Class_Handle dst_class = dst_gcvt->gc_clss; > + > + > + //element size of src should be same as element size of dst > + assert(src_gcvt->array_elem_size == dst_gcvt->array_elem_size); > + unsigned int elem_size = src_gcvt->array_elem_size; > + unsigned int src_first_elem_offset = array_first_element_offset((Partial_Reveal_Array*)src_array); > + unsigned int dst_first_elem_offset = array_first_element_offset((Partial_Reveal_Array*)dst_array); > + /* > + #ifdef COMPRESS_REFERENCE > + COMPRESSED_REFERENCE *src_copy_body = (COMPRESSED_REFERENCE *)((POINTER_SIZE_INT)src_array + src_first_elem_offset + elem_size*src_start); > + COMPRESSED_REFERENCE *dst_copy_body = (COMPRESSED_REFERENCE *)((POINTER_SIZE_INT)dst_array + dst_first_elem_offset + elem_size*dst_start); > + #else > + #endif > + */ > + REF* src_copy_body = (REF*)((POINTER_SIZE_INT)src_array + src_first_elem_offset + elem_size*src_start); > + REF* dst_copy_body = (REF*)((POINTER_SIZE_INT)dst_array + dst_first_elem_offset + elem_size*dst_start); > + > + > + if(class_is_instanceof(src_class, dst_class)) { > + //rem obj before is for OTF GC barriers > + if(WB_REM_OLD_VAR == write_barrier_function) { > + for (unsigned int count = 0; count < length; count++) { > + write_barrier_rem_slot_oldvar((Managed_Object_Handle *)dst_copy_body+count); > + } > + } else if(WB_REM_OBJ_SNAPSHOT == write_barrier_function) { > + write_barrier_rem_obj_snapshot(dst_array); > + } > + > + memmove(dst_copy_body, src_copy_body, length * elem_size); > + > + } else { //for the condition src is not the type of dst > + Class_Handle dst_elem_clss = class_get_array_element_class(dst_class); > + if(WB_REM_OBJ_SNAPSHOT == write_barrier_function) { > + write_barrier_rem_obj_snapshot(dst_array); > + } > + > + for (unsigned int count = 0; count < length; count++) { > + // 1, null elements copy direct > + if (src_copy_body[count] == NULL) { > + if(WB_REM_OLD_VAR == write_barrier_function) { > + write_barrier_rem_slot_oldvar((Managed_Object_Handle *)dst_copy_body+count); > + } > + dst_copy_body[count] = NULL; > + continue; > + } > + > + // 2, For non-null elements check if types are compatible. > +/* > +#ifdef COMPRESS_REFERENCE > + ManagedObject *src_elem = (ManagedObject *)uncompress_compressed_reference(src_elem_offset); > + Class_Handle src_elem_clss = src_elem->vt()->clss; > +#else > +#endif > +*/ > + Class_Handle src_elem_clss = obj_get_gcvt(ref_to_obj_ptr(src_copy_body[count]))->gc_clss; > + > + if (!class_is_instanceof(src_elem_clss, dst_elem_clss)) { > + if(WB_REM_SOURCE_OBJ == write_barrier_function) { > + write_barrier_rem_source_obj(dst_array); > + } > + return FALSE; > + } > + > + if(WB_REM_OLD_VAR == write_barrier_function) { > + write_barrier_rem_slot_oldvar((Managed_Object_Handle *)dst_copy_body+count); > + } > + dst_copy_body[count] = src_copy_body[count]; > + } > + } > + > + //rem obj after is for mostly concurrent > + if(WB_REM_SOURCE_OBJ == write_barrier_function) { > + write_barrier_rem_source_obj(dst_array); > + } > + > + return TRUE; > +} > + > + > +void gc_heap_wrote_object (Managed_Object_Handle p_obj_written ) > { > - /*Concurrent Mark: Since object clone and array copy do not modify object slots, > - we treat it as an new object. It has already been marked when dest object was created. > - We use WB_REM_SOURCE_OBJ function here to debug. > - */ > - > - if(WB_REM_SOURCE_OBJ == write_barrier_function){ > - Mutator *mutator = (Mutator *)gc_get_tls(); > - lock(mutator->dirty_set_lock); > - > - obj_dirty_in_table((Partial_Reveal_Object *) p_obj_written); > - mutator_dirtyset_add_entry(mutator, (Partial_Reveal_Object*)p_obj_written); > - > - unlock(mutator->dirty_set_lock); > - } > > if( !gc_is_gen_mode() || !object_has_ref_field((Partial_Reveal_Object*)p_obj_written)) > return; > @@ -283,6 +395,13 @@ > write_barrier_rem_slot_oldvar(p_slot); > *p_slot = p_target; > break; > + //just debugging > + /* > + case WB_CON_DEBUG: > + write_barrier_for_check(p_obj_holding_ref, p_slot, p_target); > + //*p_slot = p_target; > + break; > + */ > default: > assert(0); > return; > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_barrier.h > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_barrier.h?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_barrier.h (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_barrier.h Tue Oct 28 20:01:01 2008 > @@ -32,7 +32,8 @@ > WB_REM_SOURCE_REF = 0x02, > WB_REM_OLD_VAR = 0x03, > WB_REM_NEW_VAR = 0x04, > - WB_REM_OBJ_SNAPSHOT = 0x05 > + WB_REM_OBJ_SNAPSHOT = 0x05, > + WB_CON_DEBUG = 0x06 > }; > > inline void gc_set_barrier_function(unsigned int wb_function) > @@ -43,4 +44,3 @@ > #endif /* _GC_FOR_BARRIER_H_ */ > > > - > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_class.cpp > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_class.cpp?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_class.cpp (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_class.cpp Tue Oct 28 20:01:01 2008 > @@ -203,4 +203,3 @@ > > > > - > > Modified: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_vm.cpp > URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_vm.cpp?rev=708756&r1=708755&r2=708756&view=diff > ============================================================================== > --- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_vm.cpp (original) > +++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/common/gc_for_vm.cpp Tue Oct 28 20:01:01 2008 > @@ -30,7 +30,7 @@ > #include "../mark_sweep/gc_ms.h" > #include "../move_compact/gc_mc.h" > #include "interior_pointer.h" > -#include "../thread/marker.h" > +#include "../thread/conclctor.h" > #include "../thread/collector.h" > #include "../verify/verify_live_heap.h" > #include "../finalizer_weakref/finalizer_weakref.h" > @@ -115,7 +115,10 @@ > collection_scheduler_initialize(gc); > > if(gc_is_specify_con_gc()){ > - marker_initialize(gc); > + gc->gc_concurrent_status = GC_CON_NIL; > + conclctor_initialize(gc); > + } else { > + gc->gc_concurrent_status = GC_CON_DISABLE; > } > > collector_initialize(gc); > @@ -134,6 +137,9 @@ > { > INFO2("gc.process", "GC: call GC wrapup ...."); > GC* gc = p_global_gc; > + // destruct threads first, and then destruct data structures > + conclctor_destruct(gc); > + collector_destruct(gc); > > #if defined(USE_UNIQUE_MARK_SWEEP_GC) > gc_ms_destruct((GC_MS*)gc); > @@ -148,8 +154,6 @@ > #ifndef BUILD_IN_REFERENT > gc_finref_metadata_destruct(gc); > #endif > - collector_destruct(gc); > - marker_destruct(gc); > > if( verify_live_heap ){ > gc_terminate_heap_verification(gc); > @@ -446,4 +450,3 @@ > > > > - > > > -- Unless stated otherwise above: IBM United Kingdom Limited - Registered in England and Wales with number 741598. Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU