This commit is contained in:
Erik Helin 2013-06-20 10:03:58 +02:00
commit 774e23fae7
9 changed files with 97 additions and 21 deletions

View file

@ -598,6 +598,8 @@ StringTable* StringTable::_the_table = NULL;
bool StringTable::_needs_rehashing = false; bool StringTable::_needs_rehashing = false;
volatile int StringTable::_parallel_claimed_idx = 0;
// Pick hashing algorithm // Pick hashing algorithm
unsigned int StringTable::hash_string(const jchar* s, int len) { unsigned int StringTable::hash_string(const jchar* s, int len) {
return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) : return use_alternate_hashcode() ? AltHashing::murmur3_32(seed(), s, len) :
@ -761,8 +763,18 @@ void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f)
} }
} }
void StringTable::oops_do(OopClosure* f) { void StringTable::buckets_do(OopClosure* f, int start_idx, int end_idx) {
for (int i = 0; i < the_table()->table_size(); ++i) { 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); HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
while (entry != NULL) { while (entry != NULL) {
assert(!entry->is_shared(), "CDS not used for the StringTable"); assert(!entry->is_shared(), "CDS not used for the StringTable");
@ -774,6 +786,27 @@ void StringTable::oops_do(OopClosure* f) {
} }
} }
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() { void StringTable::verify() {
for (int i = 0; i < the_table()->table_size(); ++i) { for (int i = 0; i < the_table()->table_size(); ++i) {
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i); HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -246,12 +246,19 @@ private:
// Set if one bucket is out of balance due to hash algorithm deficiency // Set if one bucket is out of balance due to hash algorithm deficiency
static bool _needs_rehashing; 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); 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, oop basic_add(int index, Handle string_or_null, jchar* name, int len,
unsigned int hashValue, TRAPS); unsigned int hashValue, TRAPS);
oop lookup(int index, jchar* chars, int length, unsigned int hashValue); 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, StringTable() : Hashtable<oop, mtSymbol>((int)StringTableSize,
sizeof (HashtableEntry<oop, mtSymbol>)) {} sizeof (HashtableEntry<oop, mtSymbol>)) {}
@ -277,9 +284,12 @@ public:
unlink_or_oops_do(cl, NULL); 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); 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 // Hashing algorithm, used as the hash value used by the
// StringTable for bucket selection and comparison (stored in the // StringTable for bucket selection and comparison (stored in the
// HashtableEntry structures). This is used in the String.intern() method. // HashtableEntry structures). This is used in the String.intern() method.
@ -315,5 +325,8 @@ public:
// Rehash the symbol table if it gets out of balance // Rehash the symbol table if it gets out of balance
static void rehash_table(); static void rehash_table();
static bool needs_rehashing() { return _needs_rehashing; } 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 #endif // SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP

View file

@ -1250,14 +1250,13 @@ uint PSAdaptiveSizePolicy::compute_survivor_space_size_and_threshold(
avg_promoted()->deviation()); 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" " avg_pretenured_padded_avg: %f"
" tenuring_thresh: %d" " tenuring_thresh: %d"
" target_size: " SIZE_FORMAT, " target_size: " SIZE_FORMAT,
avg_promoted()->padded_average(), avg_promoted()->padded_average(),
_avg_pretenured->padded_average(), _avg_pretenured->padded_average(),
tenuring_threshold, target_size); tenuring_threshold, target_size);
tty->cr();
} }
set_survivor_size(target_size); set_survivor_size(target_size);
@ -1279,7 +1278,7 @@ void PSAdaptiveSizePolicy::update_averages(bool is_survivor_overflow,
avg_promoted()->sample(promoted + _avg_pretenured->padded_average()); avg_promoted()->sample(promoted + _avg_pretenured->padded_average());
if (PrintAdaptiveSizePolicy) { if (PrintAdaptiveSizePolicy) {
gclog_or_tty->print( gclog_or_tty->print_cr(
"AdaptiveSizePolicy::update_averages:" "AdaptiveSizePolicy::update_averages:"
" survived: " SIZE_FORMAT " survived: " SIZE_FORMAT
" promoted: " SIZE_FORMAT " promoted: " SIZE_FORMAT

View file

@ -732,13 +732,21 @@ public:
// is set so that we always use malloc except for Solaris where we set the // is set so that we always use malloc except for Solaris where we set the
// limit to get mapped memory. // limit to get mapped memory.
template <class E, MEMFLAGS F> template <class E, MEMFLAGS F>
class ArrayAllocator : StackObj { class ArrayAllocator VALUE_OBJ_CLASS_SPEC {
char* _addr; char* _addr;
bool _use_malloc; bool _use_malloc;
size_t _size; size_t _size;
bool _free_in_destructor;
public: public:
ArrayAllocator() : _addr(NULL), _use_malloc(false), _size(0) { } ArrayAllocator(bool free_in_destructor = true) :
~ArrayAllocator() { free(); } _addr(NULL), _use_malloc(false), _size(0), _free_in_destructor(free_in_destructor) { }
~ArrayAllocator() {
if (_free_in_destructor) {
free();
}
}
E* allocate(size_t length); E* allocate(size_t length);
void free(); void free();
}; };

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -47,7 +47,6 @@ enum SH_process_strong_roots_tasks {
SH_PS_SystemDictionary_oops_do, SH_PS_SystemDictionary_oops_do,
SH_PS_ClassLoaderDataGraph_oops_do, SH_PS_ClassLoaderDataGraph_oops_do,
SH_PS_jvmti_oops_do, SH_PS_jvmti_oops_do,
SH_PS_StringTable_oops_do,
SH_PS_CodeCache_oops_do, SH_PS_CodeCache_oops_do,
// Leave this one last. // Leave this one last.
SH_PS_NumElements SH_PS_NumElements
@ -127,6 +126,8 @@ SharedHeap::StrongRootsScope::StrongRootsScope(SharedHeap* outer, bool activate)
{ {
if (_active) { if (_active) {
outer->change_strong_roots_parity(); outer->change_strong_roots_parity();
// Zero the claimed high water mark in the StringTable
StringTable::clear_parallel_claimed_index();
} }
} }
@ -154,14 +155,16 @@ void SharedHeap::process_strong_roots(bool activate_scope,
// Global (strong) JNI handles // Global (strong) JNI handles
if (!_process_strong_tasks->is_task_claimed(SH_PS_JNIHandles_oops_do)) if (!_process_strong_tasks->is_task_claimed(SH_PS_JNIHandles_oops_do))
JNIHandles::oops_do(roots); JNIHandles::oops_do(roots);
// All threads execute this; the individual threads are task groups. // All threads execute this; the individual threads are task groups.
CLDToOopClosure roots_from_clds(roots); CLDToOopClosure roots_from_clds(roots);
CLDToOopClosure* roots_from_clds_p = (is_scavenging ? NULL : &roots_from_clds); CLDToOopClosure* roots_from_clds_p = (is_scavenging ? NULL : &roots_from_clds);
if (ParallelGCThreads > 0) { if (CollectedHeap::use_parallel_gc_threads()) {
Threads::possibly_parallel_oops_do(roots, roots_from_clds_p ,code_roots); Threads::possibly_parallel_oops_do(roots, roots_from_clds_p, code_roots);
} else { } else {
Threads::oops_do(roots, roots_from_clds_p, code_roots); Threads::oops_do(roots, roots_from_clds_p, code_roots);
} }
if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do)) if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do))
ObjectSynchronizer::oops_do(roots); ObjectSynchronizer::oops_do(roots);
if (!_process_strong_tasks->is_task_claimed(SH_PS_FlatProfiler_oops_do)) if (!_process_strong_tasks->is_task_claimed(SH_PS_FlatProfiler_oops_do))
@ -189,8 +192,12 @@ void SharedHeap::process_strong_roots(bool activate_scope,
} }
} }
if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) { // All threads execute the following. A specific chunk of buckets
// from the StringTable are the individual tasks.
if (so & SO_Strings) { if (so & SO_Strings) {
if (CollectedHeap::use_parallel_gc_threads()) {
StringTable::possibly_parallel_oops_do(roots);
} else {
StringTable::oops_do(roots); StringTable::oops_do(roots);
} }
} }

View file

@ -1566,6 +1566,15 @@ julong Arguments::limit_by_allocatable_memory(julong limit) {
return result; 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() { void Arguments::set_heap_size() {
if (!FLAG_IS_DEFAULT(DefaultMaxRAMFraction)) { if (!FLAG_IS_DEFAULT(DefaultMaxRAMFraction)) {
// Deprecated flag // Deprecated flag
@ -3525,6 +3534,8 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
} }
} }
set_heap_base_min_address();
// Set heap size based on available physical memory // Set heap size based on available physical memory
set_heap_size(); set_heap_size();

View file

@ -315,6 +315,8 @@ class Arguments : AllStatic {
// limits the given memory size by the maximum amount of memory this process is // limits the given memory size by the maximum amount of memory this process is
// currently allowed to allocate or reserve. // currently allowed to allocate or reserve.
static julong limit_by_allocatable_memory(julong size); static julong limit_by_allocatable_memory(julong size);
// Setup HeapBaseMinAddress
static void set_heap_base_min_address();
// Setup heap size // Setup heap size
static void set_heap_size(); static void set_heap_size();
// Based on automatic selection criteria, should the // Based on automatic selection criteria, should the

View file

@ -41,7 +41,7 @@
BitMap::BitMap(bm_word_t* map, idx_t size_in_bits) : 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(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");
assert(size_in_bits >= 0, "just checking"); assert(size_in_bits >= 0, "just checking");
@ -49,7 +49,7 @@ BitMap::BitMap(bm_word_t* map, idx_t size_in_bits) :
BitMap::BitMap(idx_t size_in_bits, bool in_resource_area) : 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."); assert(sizeof(bm_word_t) == BytesPerWord, "Implementation assumption.");
resize(size_in_bits, in_resource_area); resize(size_in_bits, in_resource_area);
@ -65,8 +65,10 @@ void BitMap::resize(idx_t size_in_bits, bool in_resource_area) {
if (in_resource_area) { if (in_resource_area) {
_map = NEW_RESOURCE_ARRAY(bm_word_t, new_size_in_words); _map = NEW_RESOURCE_ARRAY(bm_word_t, new_size_in_words);
} else { } else {
if (old_map != NULL) FREE_C_HEAP_ARRAY(bm_word_t, _map, mtInternal); if (old_map != NULL) {
_map = NEW_C_HEAP_ARRAY(bm_word_t, new_size_in_words, mtInternal); _map_allocator.free();
}
_map = _map_allocator.allocate(new_size_in_words);
} }
Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map, Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map,
MIN2(old_size_in_words, new_size_in_words)); MIN2(old_size_in_words, new_size_in_words));

View file

@ -48,6 +48,7 @@ class BitMap VALUE_OBJ_CLASS_SPEC {
} RangeSizeHint; } RangeSizeHint;
private: private:
ArrayAllocator<bm_word_t, mtInternal> _map_allocator;
bm_word_t* _map; // First word in bitmap bm_word_t* _map; // First word in bitmap
idx_t _size; // Size of bitmap (in bits) idx_t _size; // Size of bitmap (in bits)
@ -113,7 +114,7 @@ class BitMap VALUE_OBJ_CLASS_SPEC {
public: public:
// Constructs a bitmap with no map, and size 0. // 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. // Constructs a bitmap with the given map and size.
BitMap(bm_word_t* map, idx_t size_in_bits); BitMap(bm_word_t* map, idx_t size_in_bits);