This commit is contained in:
Nils Eliasson 2014-03-11 11:26:14 -04:00
commit f457cabe80
95 changed files with 6896 additions and 1025 deletions

View file

@ -198,14 +198,12 @@ CodeBlob* CodeCache::allocate(int size, bool is_critical) {
}
maxCodeCacheUsed = MAX2(maxCodeCacheUsed, ((address)_heap->high_boundary() -
(address)_heap->low_boundary()) - unallocated_capacity());
verify_if_often();
print_trace("allocation", cb, size);
return cb;
}
void CodeCache::free(CodeBlob* cb) {
assert_locked_or_safepoint(CodeCache_lock);
verify_if_often();
print_trace("free", cb);
if (cb->is_nmethod()) {
@ -221,7 +219,6 @@ void CodeCache::free(CodeBlob* cb) {
_heap->deallocate(cb);
verify_if_often();
assert(_number_of_blobs >= 0, "sanity check");
}
@ -244,12 +241,6 @@ void CodeCache::commit(CodeBlob* cb) {
}
void CodeCache::flush() {
assert_locked_or_safepoint(CodeCache_lock);
Unimplemented();
}
// Iteration over CodeBlobs
#define FOR_ALL_BLOBS(var) for (CodeBlob *var = first() ; var != NULL; var = next(var) )
@ -269,7 +260,7 @@ bool CodeCache::contains(void *p) {
CodeBlob* CodeCache::find_blob(void* start) {
CodeBlob* result = find_blob_unsafe(start);
if (result == NULL) return NULL;
// We could potientially look up non_entrant methods
// We could potentially look up non_entrant methods
guarantee(!result->is_zombie() || result->is_locked_by_vm() || is_error_reported(), "unsafe access to zombie method");
return result;
}
@ -741,17 +732,26 @@ void CodeCache::report_codemem_full() {
}
}
void CodeCache::print_memory_overhead() {
size_t wasted_bytes = 0;
CodeBlob *cb;
for (cb = first(); cb != NULL; cb = next(cb)) {
HeapBlock* heap_block = ((HeapBlock*)cb) - 1;
wasted_bytes += heap_block->length() * CodeCacheSegmentSize - cb->size();
}
// Print bytes that are allocated in the freelist
ttyLocker ttl;
tty->print_cr("Number of elements in freelist: %d", freelist_length());
tty->print_cr("Allocated in freelist: %dkB", bytes_allocated_in_freelist()/K);
tty->print_cr("Unused bytes in CodeBlobs: %dkB", (int)(wasted_bytes/K));
tty->print_cr("Segment map size: %dkB", allocated_segments()/K); // 1 byte per segment
}
//------------------------------------------------------------------------------------------------
// Non-product version
#ifndef PRODUCT
void CodeCache::verify_if_often() {
if (VerifyCodeCacheOften) {
_heap->verify();
}
}
void CodeCache::print_trace(const char* event, CodeBlob* cb, int size) {
if (PrintCodeCache2) { // Need to add a new flag
ResourceMark rm;
@ -774,7 +774,7 @@ void CodeCache::print_internals() {
int nmethodUnloaded = 0;
int nmethodJava = 0;
int nmethodNative = 0;
int maxCodeSize = 0;
int max_nm_size = 0;
ResourceMark rm;
CodeBlob *cb;
@ -798,13 +798,11 @@ void CodeCache::print_internals() {
if(nm->is_not_entrant()) { nmethodNotEntrant++; }
if(nm->is_zombie()) { nmethodZombie++; }
if(nm->is_unloaded()) { nmethodUnloaded++; }
if(nm->is_native_method()) { nmethodNative++; }
if(nm->method() != NULL && nm->is_native_method()) { nmethodNative++; }
if(nm->method() != NULL && nm->is_java_method()) {
nmethodJava++;
if (nm->insts_size() > maxCodeSize) {
maxCodeSize = nm->insts_size();
}
max_nm_size = MAX2(max_nm_size, nm->size());
}
} else if (cb->is_runtime_stub()) {
runtimeStubCount++;
@ -820,18 +818,19 @@ void CodeCache::print_internals() {
}
int bucketSize = 512;
int bucketLimit = maxCodeSize / bucketSize + 1;
int bucketLimit = max_nm_size / bucketSize + 1;
int *buckets = NEW_C_HEAP_ARRAY(int, bucketLimit, mtCode);
memset(buckets,0,sizeof(int) * bucketLimit);
memset(buckets, 0, sizeof(int) * bucketLimit);
for (cb = first(); cb != NULL; cb = next(cb)) {
if (cb->is_nmethod()) {
nmethod* nm = (nmethod*)cb;
if(nm->is_java_method()) {
buckets[nm->insts_size() / bucketSize]++;
}
buckets[nm->size() / bucketSize]++;
}
}
}
tty->print_cr("Code Cache Entries (total of %d)",total);
tty->print_cr("-------------------------------------------------");
tty->print_cr("nmethods: %d",nmethodCount);
@ -858,6 +857,7 @@ void CodeCache::print_internals() {
}
FREE_C_HEAP_ARRAY(int, buckets, mtCode);
print_memory_overhead();
}
#endif // !PRODUCT

View file

@ -58,12 +58,13 @@ class CodeCache : AllStatic {
static bool _needs_cache_clean;
static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link()
static void verify_if_often() PRODUCT_RETURN;
static void mark_scavenge_root_nmethods() PRODUCT_RETURN;
static void verify_perm_nmethods(CodeBlobClosure* f_or_null) PRODUCT_RETURN;
static int _codemem_full_count;
static size_t bytes_allocated_in_freelist() { return _heap->allocated_in_freelist(); }
static int allocated_segments() { return _heap->allocated_segments(); }
static size_t freelist_length() { return _heap->freelist_length(); }
public:
@ -78,7 +79,6 @@ class CodeCache : AllStatic {
static int alignment_unit(); // guaranteed alignment of all CodeBlobs
static int alignment_offset(); // guaranteed offset of first CodeBlob byte within alignment unit (i.e., allocation header)
static void free(CodeBlob* cb); // frees a CodeBlob
static void flush(); // flushes all CodeBlobs
static bool contains(void *p); // returns whether p is included
static void blobs_do(void f(CodeBlob* cb)); // iterates over all CodeBlobs
static void blobs_do(CodeBlobClosure* f); // iterates over all CodeBlobs
@ -150,6 +150,7 @@ class CodeCache : AllStatic {
// Printing/debugging
static void print(); // prints summary
static void print_internals();
static void print_memory_overhead();
static void verify(); // verifies the code cache
static void print_trace(const char* event, CodeBlob* cb, int size = 0) PRODUCT_RETURN;
static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage

View file

@ -725,13 +725,13 @@ Klass* Dependencies::DepStream::context_type() {
}
// ----------------- DependencySignature --------------------------------------
bool DependencySignature::equals(DependencySignature* sig) const {
if ((type() != sig->type()) || (args_count() != sig->args_count())) {
bool DependencySignature::equals(DependencySignature const& s1, DependencySignature const& s2) {
if ((s1.type() != s2.type()) || (s1.args_count() != s2.args_count())) {
return false;
}
for (int i = 0; i < sig->args_count(); i++) {
if (arg(i) != sig->arg(i)) {
for (int i = 0; i < s1.args_count(); i++) {
if (s1.arg(i) != s2.arg(i)) {
return false;
}
}

View file

@ -527,7 +527,7 @@ class Dependencies: public ResourceObj {
};
class DependencySignature : public GenericHashtableEntry<DependencySignature, ResourceObj> {
class DependencySignature : public ResourceObj {
private:
int _args_count;
uintptr_t _argument_hash[Dependencies::max_arg_count];
@ -542,12 +542,13 @@ class DependencySignature : public GenericHashtableEntry<DependencySignature, Re
}
}
bool equals(DependencySignature* sig) const;
uintptr_t key() const { return _argument_hash[0] >> 2; }
static bool equals(DependencySignature const& s1, DependencySignature const& s2);
static unsigned hash (DependencySignature const& s1) { return s1.arg(0) >> 2; }
int args_count() const { return _args_count; }
uintptr_t arg(int idx) const { return _argument_hash[idx]; }
Dependencies::DepType type() const { return _type; }
};

View file

@ -39,6 +39,7 @@
#include "prims/jvmtiImpl.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/sweeper.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/events.hpp"
#include "utilities/xmlstream.hpp"
@ -2135,7 +2136,11 @@ void nmethod::check_all_dependencies(DepChange& changes) {
// Turn off dependency tracing while actually testing dependencies.
NOT_PRODUCT( FlagSetting fs(TraceDependencies, false) );
GenericHashtable<DependencySignature, ResourceObj>* table = new GenericHashtable<DependencySignature, ResourceObj>(11027);
typedef ResourceHashtable<DependencySignature, int, &DependencySignature::hash,
&DependencySignature::equals, 11027> DepTable;
DepTable* table = new DepTable();
// Iterate over live nmethods and check dependencies of all nmethods that are not
// marked for deoptimization. A particular dependency is only checked once.
for(nmethod* nm = CodeCache::alive_nmethod(CodeCache::first()); nm != NULL; nm = CodeCache::alive_nmethod(CodeCache::next(nm))) {
@ -2143,9 +2148,10 @@ void nmethod::check_all_dependencies(DepChange& changes) {
for (Dependencies::DepStream deps(nm); deps.next(); ) {
// Construct abstraction of a dependency.
DependencySignature* current_sig = new DependencySignature(deps);
// Determine if 'deps' is already checked. table->add() returns
// 'true' if the dependency was added (i.e., was not in the hashtable).
if (table->add(current_sig)) {
// Determine if dependency is already checked. table->put(...) returns
// 'true' if the dependency is added (i.e., was not in the hashtable).
if (table->put(*current_sig, 1)) {
if (deps.check_dependency() != NULL) {
// Dependency checking failed. Print out information about the failed
// dependency and finally fail with an assert. We can fail here, since