You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by xl...@apache.org on 2007/07/25 13:08:50 UTC
svn commit: r559396 - in /harmony/enhanced/drlvm/trunk/vm/gc_gen/src:
mark_compact/space_tune_mark_scan.cpp mark_sweep/gc_ms.cpp mark_sweep/gc_ms.h
Author: xli
Date: Wed Jul 25 04:08:49 2007
New Revision: 559396
URL: http://svn.apache.org/viewvc?view=rev&rev=559396
Log:
HARMONY-4531 : (Added missing files) performance improvement patch and code refactoring. It also fixed a couple of bugs. (The main design in this patch is to include mark-sweep LOS for minor collection and always slide-compact LOS for major collection.
Added:
harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_compact/space_tune_mark_scan.cpp (with props)
harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.cpp (with props)
harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.h (with props)
Added: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_compact/space_tune_mark_scan.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_compact/space_tune_mark_scan.cpp?view=auto&rev=559396
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_compact/space_tune_mark_scan.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_compact/space_tune_mark_scan.cpp Wed Jul 25 04:08:49 2007
@@ -0,0 +1,213 @@
+/*
+ * 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 "../common/gc_metadata.h"
+#include "../thread/collector.h"
+#include "../gen/gen.h"
+#include "../finalizer_weakref/finalizer_weakref.h"
+
+static FORCE_INLINE void scan_slot(Collector* collector, REF *p_ref)
+{
+ Partial_Reveal_Object *p_obj = read_slot(p_ref);
+ if(p_obj == NULL) return;
+
+ if(obj_mark_in_vt(p_obj)){
+ collector_tracestack_push(collector, p_obj);
+ unsigned int obj_size = vm_object_size(p_obj);
+#ifdef USE_32BITS_HASHCODE
+ obj_size += (hashcode_is_set(p_obj))?GC_OBJECT_ALIGNMENT:0;
+#endif
+ if(!obj_belongs_to_space(p_obj, gc_get_los((GC_Gen*)collector->gc))){
+ collector->non_los_live_obj_size += obj_size;
+ collector->segment_live_size[SIZE_TO_SEGMENT_INDEX(obj_size)] += obj_size;
+ } else {
+ collector->los_live_obj_size += round_up_to_size(obj_size, KB);
+ }
+ }
+
+ return;
+}
+
+static FORCE_INLINE void scan_object(Collector* collector, Partial_Reveal_Object *p_obj)
+{
+ vm_notify_obj_alive( (void *)p_obj);
+ assert((((POINTER_SIZE_INT)p_obj) % GC_OBJECT_ALIGNMENT) == 0);
+ if( !object_has_ref_field(p_obj) ) return;
+
+ REF *p_ref;
+
+ if (object_is_array(p_obj)) { /* scan array object */
+
+ Partial_Reveal_Array* array = (Partial_Reveal_Array*)p_obj;
+ unsigned int array_length = array->array_len;
+
+ p_ref = (REF *)((POINTER_SIZE_INT)array + (int)array_first_element_offset(array));
+
+ for (unsigned int i = 0; i < array_length; i++) {
+ scan_slot(collector, p_ref+i);
+ }
+
+ }else{ /* scan non-array object */
+
+ unsigned int num_refs = object_ref_field_num(p_obj);
+
+ int* ref_iterator = object_ref_iterator_init(p_obj);
+
+ for(unsigned int i=0; i<num_refs; i++){
+ p_ref = object_ref_iterator_get(ref_iterator+i, p_obj);
+ scan_slot(collector, p_ref);
+ }
+
+#ifndef BUILD_IN_REFERENT
+ scan_weak_reference(collector, p_obj, scan_slot);
+#endif
+ }
+
+ return;
+}
+
+
+static void trace_object(Collector* collector, Partial_Reveal_Object *p_obj)
+{
+ scan_object(collector, p_obj);
+
+ Vector_Block* trace_stack = collector->trace_stack;
+ while( !vector_stack_is_empty(trace_stack)){
+ p_obj = (Partial_Reveal_Object *)vector_stack_pop(trace_stack);
+ scan_object(collector, p_obj);
+ trace_stack = collector->trace_stack;
+ }
+
+ return;
+}
+
+/* for marking phase termination detection */
+static volatile unsigned int num_finished_collectors = 0;
+
+/* NOTE:: Only marking in object header is idempotent.
+ Originally, we have to mark the object before put it into markstack, to
+ guarantee there is only one occurrance of an object in markstack. This is to
+ guarantee there is only one occurrance of a repointed ref slot in repset (they
+ are put to the set when the object is scanned). If the same object is put to
+ markstack twice, they will be scanned twice and their ref slots will be recorded twice.
+ Problem occurs when the ref slot is updated first time with new position,
+ the second time the value in the ref slot is not the old position as expected.
+ It needs to read the original obj header for forwarding pointer. With the new value,
+ it will read something nonsense since the obj is not moved yet.
+ This can be worked around if we want.
+ To do this we have to use atomic instruction for marking, which is undesirable.
+ So we abondoned this design. We no longer use the repset to remember repointed slots
+*/
+
+void mark_scan_heap_for_space_tune(Collector *collector)
+{
+ GC* gc = collector->gc;
+ GC_Metadata* metadata = gc->metadata;
+
+ /* reset the num_finished_collectors to be 0 by one collector. This is necessary for the barrier later. */
+ unsigned int num_active_collectors = gc->num_active_collectors;
+ atomic_cas32( &num_finished_collectors, 0, num_active_collectors);
+
+ collector->trace_stack = free_task_pool_get_entry(metadata);
+
+ Vector_Block* root_set = pool_iterator_next(metadata->gc_rootset_pool);
+
+ /* first step: copy all root objects to mark tasks.
+ FIXME:: can be done sequentially before coming here to eliminate atomic ops */
+ while(root_set){
+ POINTER_SIZE_INT* iter = vector_block_iterator_init(root_set);
+ while(!vector_block_iterator_end(root_set,iter)){
+ REF *p_ref = (REF *)*iter;
+ iter = vector_block_iterator_advance(root_set,iter);
+
+ Partial_Reveal_Object *p_obj = read_slot(p_ref);
+ /* root ref can't be NULL, (remset may have NULL ref entry, but this function is only for MAJOR_COLLECTION */
+ assert(p_obj!=NULL);
+ /* we have to mark the object before put it into marktask, because
+ it is possible to have two slots containing a same object. They will
+ be scanned twice and their ref slots will be recorded twice. Problem
+ occurs after the ref slot is updated first time with new position
+ and the second time the value is the ref slot is the old position as expected.
+ This can be worked around if we want.
+ */
+ if(obj_mark_in_vt(p_obj)){
+ collector_tracestack_push(collector, p_obj);
+ unsigned int obj_size = vm_object_size(p_obj);
+#ifdef USE_32BITS_HASHCODE
+ obj_size += (hashcode_is_set(p_obj))?GC_OBJECT_ALIGNMENT:0;
+#endif
+ if(!obj_belongs_to_space(p_obj, gc_get_los((GC_Gen*)gc))){
+ collector->non_los_live_obj_size += obj_size;
+ collector->segment_live_size[SIZE_TO_SEGMENT_INDEX(obj_size)] += obj_size;
+ } else {
+ collector->los_live_obj_size += round_up_to_size(obj_size, KB);
+ }
+ }
+
+ }
+ root_set = pool_iterator_next(metadata->gc_rootset_pool);
+ }
+ /* put back the last trace_stack task */
+ pool_put_entry(metadata->mark_task_pool, collector->trace_stack);
+
+ /* second step: iterate over the mark tasks and scan objects */
+ /* get a task buf for the mark stack */
+ collector->trace_stack = free_task_pool_get_entry(metadata);
+
+retry:
+ Vector_Block* mark_task = pool_get_entry(metadata->mark_task_pool);
+
+ while(mark_task){
+ POINTER_SIZE_INT* iter = vector_block_iterator_init(mark_task);
+ while(!vector_block_iterator_end(mark_task,iter)){
+ Partial_Reveal_Object* p_obj = (Partial_Reveal_Object *)*iter;
+ iter = vector_block_iterator_advance(mark_task,iter);
+
+ /* FIXME:: we should not let mark_task empty during working, , other may want to steal it.
+ degenerate my stack into mark_task, and grab another mark_task */
+ trace_object(collector, p_obj);
+ }
+ /* run out one task, put back to the pool and grab another task */
+ vector_stack_clear(mark_task);
+ pool_put_entry(metadata->free_task_pool, mark_task);
+ mark_task = pool_get_entry(metadata->mark_task_pool);
+ }
+
+ /* termination detection. This is also a barrier.
+ NOTE:: We can simply spin waiting for num_finished_collectors, because each
+ generated new task would surely be processed by its generating collector eventually.
+ So code below is only for load balance optimization. */
+ atomic_inc32(&num_finished_collectors);
+ while(num_finished_collectors != num_active_collectors){
+ if( !pool_is_empty(metadata->mark_task_pool)){
+ atomic_dec32(&num_finished_collectors);
+ goto retry;
+ }
+ }
+
+ /* put back the last mark stack to the free pool */
+ mark_task = (Vector_Block*)collector->trace_stack;
+ vector_stack_clear(mark_task);
+ pool_put_entry(metadata->free_task_pool, mark_task);
+ collector->trace_stack = NULL;
+
+ return;
+}
+
+void trace_obj_in_space_tune_marking(Collector *collector, void *p_obj)
+{
+ trace_object(collector, (Partial_Reveal_Object *)p_obj);
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_compact/space_tune_mark_scan.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.cpp?view=auto&rev=559396
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.cpp Wed Jul 25 04:08:49 2007
@@ -0,0 +1,88 @@
+/*
+ * 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 "../common/gc_common.h"
+
+#ifdef ONLY_SSPACE_IN_HEAP
+
+#include "gc_ms.h"
+#include "port_sysinfo.h"
+
+#include "../finalizer_weakref/finalizer_weakref.h"
+#include "../common/compressed_ref.h"
+#ifdef USE_32BITS_HASHCODE
+#include "../common/hashcode.h"
+#endif
+
+static void gc_ms_get_system_info(GC_MS *gc_ms)
+{
+ gc_ms->_machine_page_size_bytes = (unsigned int)port_vmem_page_sizes()[0];
+ gc_ms->_num_processors = port_CPUs_number();
+ gc_ms->_system_alloc_unit = vm_get_system_alloc_unit();
+ SPACE_ALLOC_UNIT = max(gc_ms->_system_alloc_unit, GC_BLOCK_SIZE_BYTES);
+}
+
+void gc_ms_initialize(GC_MS *gc_ms, POINTER_SIZE_INT min_heap_size, POINTER_SIZE_INT max_heap_size)
+{
+ assert(gc_ms);
+ gc_ms_get_system_info(gc_ms);
+
+ max_heap_size = round_down_to_size(max_heap_size, SPACE_ALLOC_UNIT);
+ min_heap_size = round_up_to_size(min_heap_size, SPACE_ALLOC_UNIT);
+ assert(max_heap_size <= max_heap_size_bytes);
+ assert(max_heap_size >= min_heap_size_bytes);
+
+ void *sspace_base;
+ sspace_base = vm_reserve_mem(0, max_heap_size);
+ sspace_initialize((GC*)gc_ms, sspace_base, max_heap_size, max_heap_size);
+
+ HEAP_NULL = (POINTER_SIZE_INT)sspace_base;
+
+ gc_ms->heap_start = sspace_base;
+ gc_ms->heap_end = (void*)((POINTER_SIZE_INT)sspace_base + max_heap_size);
+ gc_ms->reserved_heap_size = max_heap_size;
+ gc_ms->committed_heap_size = max_heap_size;
+ gc_ms->num_collections = 0;
+ gc_ms->time_collections = 0;
+}
+
+void gc_ms_destruct(GC_MS *gc_ms)
+{
+ Sspace *sspace = gc_ms->sspace;
+ void *sspace_start = sspace->heap_start;
+ sspace_destruct(sspace);
+ gc_ms->sspace = NULL;
+ vm_unmap_mem(sspace_start, space_committed_size((Space*)sspace));
+}
+
+void gc_ms_reclaim_heap(GC_MS *gc)
+{
+ sspace_collection(gc_ms_get_sspace(gc));
+
+ /* FIXME:: clear root set here to support verify */
+#ifdef COMPRESS_REFERENCE
+ gc_set_pool_clear(gc->metadata->gc_uncompressed_rootset_pool);
+#endif
+}
+
+void gc_ms_iterate_heap(GC_MS *gc)
+{
+}
+
+unsigned int gc_ms_get_processor_num(GC_MS *gc)
+{ return gc->_num_processors; }
+
+#endif // ONLY_SSPACE_IN_HEAP
Propchange: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.h?view=auto&rev=559396
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.h Wed Jul 25 04:08:49 2007
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+#ifndef _GC_MS_H_
+#define _GC_MS_H_
+
+#ifdef ONLY_SSPACE_IN_HEAP
+
+#include "sspace.h"
+
+
+/* heap size limit is not interesting. only for manual tuning purpose */
+extern POINTER_SIZE_INT min_heap_size_bytes;
+extern POINTER_SIZE_INT max_heap_size_bytes;
+
+typedef struct GC_MS {
+ /* <-- First couple of fields overloaded as GC */
+ void *heap_start;
+ void *heap_end;
+ POINTER_SIZE_INT reserved_heap_size;
+ POINTER_SIZE_INT committed_heap_size;
+ unsigned int num_collections;
+ int64 time_collections;
+ float survive_ratio;
+
+ /* mutation related info */
+ Mutator *mutator_list;
+ SpinLock mutator_list_lock;
+ unsigned int num_mutators;
+
+ /* collection related info */
+ Collector **collectors;
+ unsigned int num_collectors;
+ unsigned int num_active_collectors; /* not all collectors are working */
+
+ /* metadata is the pool for rootset, markstack, etc. */
+ GC_Metadata *metadata;
+ Finref_Metadata *finref_metadata;
+
+ unsigned int collect_kind; /* MAJOR or MINOR */
+ unsigned int last_collect_kind;
+ unsigned int cause; /*GC_CAUSE_LOS_IS_FULL, GC_CAUSE_NOS_IS_FULL, or GC_CAUSE_RUNTIME_FORCE_GC*/
+ Boolean collect_result; /* succeed or fail */
+
+ Boolean generate_barrier;
+
+ /* FIXME:: this is wrong! root_set belongs to mutator */
+ Vector_Block *root_set;
+ Vector_Block *uncompressed_root_set;
+
+ //For_LOS_extend
+ Space_Tuner *tuner;
+ /* END of GC --> */
+
+ Sspace *sspace;
+
+ /* system info */
+ unsigned int _system_alloc_unit;
+ unsigned int _machine_page_size_bytes;
+ unsigned int _num_processors;
+
+} GC_MS;
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+inline void *gc_ms_fast_alloc(unsigned size, Allocator *allocator)
+{ return sspace_thread_local_alloc(size, allocator); }
+
+inline void *gc_ms_alloc(unsigned size, Allocator *allocator)
+{ return sspace_alloc(size, allocator); }
+
+inline Sspace *gc_ms_get_sspace(GC_MS *gc)
+{ return gc->sspace; }
+
+inline void gc_ms_set_sspace(GC_MS *gc, Sspace *sspace)
+{ gc->sspace = sspace; }
+
+inline POINTER_SIZE_INT gc_ms_free_memory_size(GC_MS *gc)
+{ return sspace_free_memory_size(gc_ms_get_sspace(gc)); }
+
+inline POINTER_SIZE_INT gc_ms_total_memory_size(GC_MS *gc)
+{ return space_committed_size((Space*)gc_ms_get_sspace(gc)); }
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void gc_ms_initialize(GC_MS *gc, POINTER_SIZE_INT initial_heap_size, POINTER_SIZE_INT final_heap_size);
+void gc_ms_destruct(GC_MS *gc);
+void gc_ms_reclaim_heap(GC_MS *gc);
+void gc_ms_iterate_heap(GC_MS *gc);
+unsigned int gc_ms_get_processor_num(GC_MS *gc);
+
+
+#endif // ONLY_SSPACE_IN_HEAP
+
+#endif // _GC_MS_H_
Propchange: harmony/enhanced/drlvm/trunk/vm/gc_gen/src/mark_sweep/gc_ms.h
------------------------------------------------------------------------------
svn:eol-style = native