harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From x..@apache.org
Subject 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
Date Wed, 25 Jul 2007 11:08:50 GMT
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



Mime
View raw message