mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-23 12:34:32 +02:00
Merge
This commit is contained in:
commit
f457cabe80
95 changed files with 6896 additions and 1025 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue