Merge
authorehelin
Thu, 20 Jun 2013 10:03:58 +0200
changeset 18094 1856e0a7879d
parent 18089 4b83f9d7a626 (current diff)
parent 18093 39cccba02d17 (diff)
child 18106 fff80ba1282e
Merge
hotspot/src/share/vm/memory/allocation.hpp
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp	Wed Jun 19 18:13:52 2013 +0200
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp	Thu Jun 20 10:03:58 2013 +0200
@@ -598,6 +598,8 @@
 
 bool StringTable::_needs_rehashing = false;
 
+volatile int StringTable::_parallel_claimed_idx = 0;
+
 // Pick hashing algorithm
 unsigned int StringTable::hash_string(const jchar* s, int len) {
   return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
@@ -761,8 +763,18 @@
   }
 }
 
-void StringTable::oops_do(OopClosure* f) {
-  for (int i = 0; i < the_table()->table_size(); ++i) {
+void StringTable::buckets_do(OopClosure* f, int start_idx, int end_idx) {
+  const int limit = the_table()->table_size();
+
+  assert(0 <= start_idx && start_idx <= limit,
+         err_msg("start_idx (" INT32_FORMAT ") oob?", start_idx));
+  assert(0 <= end_idx && end_idx <= limit,
+         err_msg("end_idx (" INT32_FORMAT ") oob?", end_idx));
+  assert(start_idx <= end_idx,
+         err_msg("Ordering: start_idx=" INT32_FORMAT", end_idx=" INT32_FORMAT,
+                 start_idx, end_idx));
+
+  for (int i = start_idx; i < end_idx; i += 1) {
     HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
     while (entry != NULL) {
       assert(!entry->is_shared(), "CDS not used for the StringTable");
@@ -774,6 +786,27 @@
   }
 }
 
+void StringTable::oops_do(OopClosure* f) {
+  buckets_do(f, 0, the_table()->table_size());
+}
+
+void StringTable::possibly_parallel_oops_do(OopClosure* f) {
+  const int ClaimChunkSize = 32;
+  const int limit = the_table()->table_size();
+
+  for (;;) {
+    // Grab next set of buckets to scan
+    int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize;
+    if (start_idx >= limit) {
+      // End of table
+      break;
+    }
+
+    int end_idx = MIN2(limit, start_idx + ClaimChunkSize);
+    buckets_do(f, start_idx, end_idx);
+  }
+}
+
 void StringTable::verify() {
   for (int i = 0; i < the_table()->table_size(); ++i) {
     HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp	Wed Jun 19 18:13:52 2013 +0200
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp	Thu Jun 20 10:03:58 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -246,12 +246,19 @@
   // Set if one bucket is out of balance due to hash algorithm deficiency
   static bool _needs_rehashing;
 
+  // Claimed high water mark for parallel chunked scanning
+  static volatile int _parallel_claimed_idx;
+
   static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS);
   oop basic_add(int index, Handle string_or_null, jchar* name, int len,
                 unsigned int hashValue, TRAPS);
 
   oop lookup(int index, jchar* chars, int length, unsigned int hashValue);
 
+  // Apply the give oop closure to the entries to the buckets
+  // in the range [start_idx, end_idx).
+  static void buckets_do(OopClosure* f, int start_idx, int end_idx);
+
   StringTable() : Hashtable<oop, mtSymbol>((int)StringTableSize,
                               sizeof (HashtableEntry<oop, mtSymbol>)) {}
 
@@ -277,9 +284,12 @@
     unlink_or_oops_do(cl, NULL);
   }
 
-  // Invoke "f->do_oop" on the locations of all oops in the table.
+  // Serially invoke "f->do_oop" on the locations of all oops in the table.
   static void oops_do(OopClosure* f);
 
+  // Possibly parallel version of the above
+  static void possibly_parallel_oops_do(OopClosure* f);
+
   // Hashing algorithm, used as the hash value used by the
   //     StringTable for bucket selection and comparison (stored in the
   //     HashtableEntry structures).  This is used in the String.intern() method.
@@ -315,5 +325,8 @@
   // Rehash the symbol table if it gets out of balance
   static void rehash_table();
   static bool needs_rehashing() { return _needs_rehashing; }
+
+  // Parallel chunked scanning
+  static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; }
 };
 #endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp	Wed Jun 19 18:13:52 2013 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp	Thu Jun 20 10:03:58 2013 +0200
@@ -1250,14 +1250,13 @@
                   avg_promoted()->deviation());
     }
 
-    gclog_or_tty->print( "  avg_promoted_padded_avg: %f"
+    gclog_or_tty->print_cr( "  avg_promoted_padded_avg: %f"
                 "  avg_pretenured_padded_avg: %f"
                 "  tenuring_thresh: %d"
                 "  target_size: " SIZE_FORMAT,
                 avg_promoted()->padded_average(),
                 _avg_pretenured->padded_average(),
                 tenuring_threshold, target_size);
-    tty->cr();
   }
 
   set_survivor_size(target_size);
@@ -1279,7 +1278,7 @@
   avg_promoted()->sample(promoted + _avg_pretenured->padded_average());
 
   if (PrintAdaptiveSizePolicy) {
-    gclog_or_tty->print(
+    gclog_or_tty->print_cr(
                   "AdaptiveSizePolicy::update_averages:"
                   "  survived: "  SIZE_FORMAT
                   "  promoted: "  SIZE_FORMAT
--- a/hotspot/src/share/vm/memory/allocation.hpp	Wed Jun 19 18:13:52 2013 +0200
+++ b/hotspot/src/share/vm/memory/allocation.hpp	Thu Jun 20 10:03:58 2013 +0200
@@ -732,13 +732,21 @@
 // is set so that we always use malloc except for Solaris where we set the
 // limit to get mapped memory.
 template <class E, MEMFLAGS F>
-class ArrayAllocator : StackObj {
+class ArrayAllocator VALUE_OBJ_CLASS_SPEC {
   char* _addr;
   bool _use_malloc;
   size_t _size;
+  bool _free_in_destructor;
  public:
-  ArrayAllocator() : _addr(NULL), _use_malloc(false), _size(0) { }
-  ~ArrayAllocator() { free(); }
+  ArrayAllocator(bool free_in_destructor = true) :
+    _addr(NULL), _use_malloc(false), _size(0), _free_in_destructor(free_in_destructor) { }
+
+  ~ArrayAllocator() {
+    if (_free_in_destructor) {
+      free();
+    }
+  }
+
   E* allocate(size_t length);
   void free();
 };
--- a/hotspot/src/share/vm/memory/sharedHeap.cpp	Wed Jun 19 18:13:52 2013 +0200
+++ b/hotspot/src/share/vm/memory/sharedHeap.cpp	Thu Jun 20 10:03:58 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,6 @@
   SH_PS_SystemDictionary_oops_do,
   SH_PS_ClassLoaderDataGraph_oops_do,
   SH_PS_jvmti_oops_do,
-  SH_PS_StringTable_oops_do,
   SH_PS_CodeCache_oops_do,
   // Leave this one last.
   SH_PS_NumElements
@@ -127,6 +126,8 @@
 {
   if (_active) {
     outer->change_strong_roots_parity();
+    // Zero the claimed high water mark in the StringTable
+    StringTable::clear_parallel_claimed_index();
   }
 }
 
@@ -154,14 +155,16 @@
   // Global (strong) JNI handles
   if (!_process_strong_tasks->is_task_claimed(SH_PS_JNIHandles_oops_do))
     JNIHandles::oops_do(roots);
+
   // All threads execute this; the individual threads are task groups.
   CLDToOopClosure roots_from_clds(roots);
   CLDToOopClosure* roots_from_clds_p = (is_scavenging ? NULL : &roots_from_clds);
-  if (ParallelGCThreads > 0) {
-    Threads::possibly_parallel_oops_do(roots, roots_from_clds_p ,code_roots);
+  if (CollectedHeap::use_parallel_gc_threads()) {
+    Threads::possibly_parallel_oops_do(roots, roots_from_clds_p, code_roots);
   } else {
     Threads::oops_do(roots, roots_from_clds_p, code_roots);
   }
+
   if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do))
     ObjectSynchronizer::oops_do(roots);
   if (!_process_strong_tasks->is_task_claimed(SH_PS_FlatProfiler_oops_do))
@@ -189,8 +192,12 @@
     }
   }
 
-  if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) {
-    if (so & SO_Strings) {
+  // All threads execute the following. A specific chunk of buckets
+  // from the StringTable are the individual tasks.
+  if (so & SO_Strings) {
+    if (CollectedHeap::use_parallel_gc_threads()) {
+      StringTable::possibly_parallel_oops_do(roots);
+    } else {
       StringTable::oops_do(roots);
     }
   }
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Wed Jun 19 18:13:52 2013 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Thu Jun 20 10:03:58 2013 +0200
@@ -1566,6 +1566,15 @@
   return result;
 }
 
+void Arguments::set_heap_base_min_address() {
+  if (FLAG_IS_DEFAULT(HeapBaseMinAddress) && UseG1GC && HeapBaseMinAddress < 1*G) {
+    // By default HeapBaseMinAddress is 2G on all platforms except Solaris x86.
+    // G1 currently needs a lot of C-heap, so on Solaris we have to give G1
+    // some extra space for the C-heap compared to other collectors.
+    FLAG_SET_ERGO(uintx, HeapBaseMinAddress, 1*G);
+  }
+}
+
 void Arguments::set_heap_size() {
   if (!FLAG_IS_DEFAULT(DefaultMaxRAMFraction)) {
     // Deprecated flag
@@ -3525,6 +3534,8 @@
     }
   }
 
+  set_heap_base_min_address();
+
   // Set heap size based on available physical memory
   set_heap_size();
 
--- a/hotspot/src/share/vm/runtime/arguments.hpp	Wed Jun 19 18:13:52 2013 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.hpp	Thu Jun 20 10:03:58 2013 +0200
@@ -315,6 +315,8 @@
   // limits the given memory size by the maximum amount of memory this process is
   // currently allowed to allocate or reserve.
   static julong limit_by_allocatable_memory(julong size);
+  // Setup HeapBaseMinAddress
+  static void set_heap_base_min_address();
   // Setup heap size
   static void set_heap_size();
   // Based on automatic selection criteria, should the
--- a/hotspot/src/share/vm/utilities/bitMap.cpp	Wed Jun 19 18:13:52 2013 +0200
+++ b/hotspot/src/share/vm/utilities/bitMap.cpp	Thu Jun 20 10:03:58 2013 +0200
@@ -41,7 +41,7 @@
 
 
 BitMap::BitMap(bm_word_t* map, idx_t size_in_bits) :
-  _map(map), _size(size_in_bits)
+  _map(map), _size(size_in_bits), _map_allocator(false)
 {
   assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");
   assert(size_in_bits >= 0, "just checking");
@@ -49,7 +49,7 @@
 
 
 BitMap::BitMap(idx_t size_in_bits, bool in_resource_area) :
-  _map(NULL), _size(0)
+  _map(NULL), _size(0), _map_allocator(false)
 {
   assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");
   resize(size_in_bits, in_resource_area);
@@ -65,8 +65,10 @@
   if (in_resource_area) {
     _map = NEW_RESOURCE_ARRAY(bm_word_t, new_size_in_words);
   } else {
-    if (old_map != NULL) FREE_C_HEAP_ARRAY(bm_word_t, _map, mtInternal);
-    _map = NEW_C_HEAP_ARRAY(bm_word_t, new_size_in_words, mtInternal);
+    if (old_map != NULL) {
+      _map_allocator.free();
+    }
+    _map = _map_allocator.allocate(new_size_in_words);
   }
   Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map,
                        MIN2(old_size_in_words, new_size_in_words));
--- a/hotspot/src/share/vm/utilities/bitMap.hpp	Wed Jun 19 18:13:52 2013 +0200
+++ b/hotspot/src/share/vm/utilities/bitMap.hpp	Thu Jun 20 10:03:58 2013 +0200
@@ -48,6 +48,7 @@
   } RangeSizeHint;
 
  private:
+  ArrayAllocator<bm_word_t, mtInternal> _map_allocator;
   bm_word_t* _map;     // First word in bitmap
   idx_t      _size;    // Size of bitmap (in bits)
 
@@ -113,7 +114,7 @@
  public:
 
   // Constructs a bitmap with no map, and size 0.
-  BitMap() : _map(NULL), _size(0) {}
+  BitMap() : _map(NULL), _size(0), _map_allocator(false) {}
 
   // Constructs a bitmap with the given map and size.
   BitMap(bm_word_t* map, idx_t size_in_bits);