mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-23 20:44:41 +02:00
Merge
This commit is contained in:
commit
39b0e57fdd
5098 changed files with 176905 additions and 81175 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
|
@ -245,8 +245,8 @@ BufferBlob* BufferBlob::create(const char* name, CodeBuffer* cb) {
|
|||
}
|
||||
|
||||
|
||||
void* BufferBlob::operator new(size_t s, unsigned size) {
|
||||
void* p = CodeCache::allocate(size);
|
||||
void* BufferBlob::operator new(size_t s, unsigned size, bool is_critical) throw() {
|
||||
void* p = CodeCache::allocate(size, is_critical);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -277,7 +277,10 @@ AdapterBlob* AdapterBlob::create(CodeBuffer* cb) {
|
|||
unsigned int size = allocation_size(cb, sizeof(AdapterBlob));
|
||||
{
|
||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
blob = new (size) AdapterBlob(size, cb);
|
||||
// The parameter 'true' indicates a critical memory allocation.
|
||||
// This means that CodeCacheMinimumFreeSpace is used, if necessary
|
||||
const bool is_critical = true;
|
||||
blob = new (size, is_critical) AdapterBlob(size, cb);
|
||||
}
|
||||
// Track memory usage statistic after releasing CodeCache_lock
|
||||
MemoryService::track_code_cache_memory_usage();
|
||||
|
@ -299,7 +302,10 @@ MethodHandlesAdapterBlob* MethodHandlesAdapterBlob::create(int buffer_size) {
|
|||
size += round_to(buffer_size, oopSize);
|
||||
{
|
||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
blob = new (size) MethodHandlesAdapterBlob(size);
|
||||
// The parameter 'true' indicates a critical memory allocation.
|
||||
// This means that CodeCacheMinimumFreeSpace is used, if necessary
|
||||
const bool is_critical = true;
|
||||
blob = new (size, is_critical) MethodHandlesAdapterBlob(size);
|
||||
}
|
||||
// Track memory usage statistic after releasing CodeCache_lock
|
||||
MemoryService::track_code_cache_memory_usage();
|
||||
|
@ -347,14 +353,14 @@ RuntimeStub* RuntimeStub::new_runtime_stub(const char* stub_name,
|
|||
}
|
||||
|
||||
|
||||
void* RuntimeStub::operator new(size_t s, unsigned size) {
|
||||
void* RuntimeStub::operator new(size_t s, unsigned size) throw() {
|
||||
void* p = CodeCache::allocate(size, true);
|
||||
if (!p) fatal("Initial size of CodeCache is too small");
|
||||
return p;
|
||||
}
|
||||
|
||||
// operator new shared by all singletons:
|
||||
void* SingletonBlob::operator new(size_t s, unsigned size) {
|
||||
void* SingletonBlob::operator new(size_t s, unsigned size) throw() {
|
||||
void* p = CodeCache::allocate(size, true);
|
||||
if (!p) fatal("Initial size of CodeCache is too small");
|
||||
return p;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
|
@ -209,7 +209,7 @@ class BufferBlob: public CodeBlob {
|
|||
BufferBlob(const char* name, int size);
|
||||
BufferBlob(const char* name, int size, CodeBuffer* cb);
|
||||
|
||||
void* operator new(size_t s, unsigned size);
|
||||
void* operator new(size_t s, unsigned size, bool is_critical = false) throw();
|
||||
|
||||
public:
|
||||
// Creation
|
||||
|
@ -253,7 +253,6 @@ public:
|
|||
class MethodHandlesAdapterBlob: public BufferBlob {
|
||||
private:
|
||||
MethodHandlesAdapterBlob(int size) : BufferBlob("MethodHandles adapters", size) {}
|
||||
MethodHandlesAdapterBlob(int size, CodeBuffer* cb) : BufferBlob("MethodHandles adapters", size, cb) {}
|
||||
|
||||
public:
|
||||
// Creation
|
||||
|
@ -283,7 +282,7 @@ class RuntimeStub: public CodeBlob {
|
|||
bool caller_must_gc_arguments
|
||||
);
|
||||
|
||||
void* operator new(size_t s, unsigned size);
|
||||
void* operator new(size_t s, unsigned size) throw();
|
||||
|
||||
public:
|
||||
// Creation
|
||||
|
@ -321,7 +320,7 @@ class SingletonBlob: public CodeBlob {
|
|||
friend class VMStructs;
|
||||
|
||||
protected:
|
||||
void* operator new(size_t s, unsigned size);
|
||||
void* operator new(size_t s, unsigned size) throw();
|
||||
|
||||
public:
|
||||
SingletonBlob(
|
||||
|
|
|
@ -124,7 +124,6 @@ int CodeCache::_number_of_nmethods = 0;
|
|||
int CodeCache::_number_of_nmethods_with_dependencies = 0;
|
||||
bool CodeCache::_needs_cache_clean = false;
|
||||
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
|
||||
nmethod* CodeCache::_saved_nmethods = NULL;
|
||||
|
||||
int CodeCache::_codemem_full_count = 0;
|
||||
|
||||
|
@ -464,96 +463,11 @@ void CodeCache::verify_perm_nmethods(CodeBlobClosure* f_or_null) {
|
|||
}
|
||||
#endif //PRODUCT
|
||||
|
||||
/**
|
||||
* Remove and return nmethod from the saved code list in order to reanimate it.
|
||||
*/
|
||||
nmethod* CodeCache::reanimate_saved_code(Method* m) {
|
||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
nmethod* saved = _saved_nmethods;
|
||||
nmethod* prev = NULL;
|
||||
while (saved != NULL) {
|
||||
if (saved->is_in_use() && saved->method() == m) {
|
||||
if (prev != NULL) {
|
||||
prev->set_saved_nmethod_link(saved->saved_nmethod_link());
|
||||
} else {
|
||||
_saved_nmethods = saved->saved_nmethod_link();
|
||||
}
|
||||
assert(saved->is_speculatively_disconnected(), "shouldn't call for other nmethods");
|
||||
saved->set_speculatively_disconnected(false);
|
||||
saved->set_saved_nmethod_link(NULL);
|
||||
if (PrintMethodFlushing) {
|
||||
saved->print_on(tty, " ### nmethod is reconnected");
|
||||
}
|
||||
if (LogCompilation && (xtty != NULL)) {
|
||||
ttyLocker ttyl;
|
||||
xtty->begin_elem("nmethod_reconnected compile_id='%3d'", saved->compile_id());
|
||||
xtty->method(m);
|
||||
xtty->stamp();
|
||||
xtty->end_elem();
|
||||
}
|
||||
return saved;
|
||||
}
|
||||
prev = saved;
|
||||
saved = saved->saved_nmethod_link();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove nmethod from the saved code list in order to discard it permanently
|
||||
*/
|
||||
void CodeCache::remove_saved_code(nmethod* nm) {
|
||||
// For conc swpr this will be called with CodeCache_lock taken by caller
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
assert(nm->is_speculatively_disconnected(), "shouldn't call for other nmethods");
|
||||
nmethod* saved = _saved_nmethods;
|
||||
nmethod* prev = NULL;
|
||||
while (saved != NULL) {
|
||||
if (saved == nm) {
|
||||
if (prev != NULL) {
|
||||
prev->set_saved_nmethod_link(saved->saved_nmethod_link());
|
||||
} else {
|
||||
_saved_nmethods = saved->saved_nmethod_link();
|
||||
}
|
||||
if (LogCompilation && (xtty != NULL)) {
|
||||
ttyLocker ttyl;
|
||||
xtty->begin_elem("nmethod_removed compile_id='%3d'", nm->compile_id());
|
||||
xtty->stamp();
|
||||
xtty->end_elem();
|
||||
}
|
||||
return;
|
||||
}
|
||||
prev = saved;
|
||||
saved = saved->saved_nmethod_link();
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
void CodeCache::speculatively_disconnect(nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
assert(nm->is_in_use() && !nm->is_speculatively_disconnected(), "should only disconnect live nmethods");
|
||||
nm->set_saved_nmethod_link(_saved_nmethods);
|
||||
_saved_nmethods = nm;
|
||||
if (PrintMethodFlushing) {
|
||||
nm->print_on(tty, " ### nmethod is speculatively disconnected");
|
||||
}
|
||||
if (LogCompilation && (xtty != NULL)) {
|
||||
ttyLocker ttyl;
|
||||
xtty->begin_elem("nmethod_disconnected compile_id='%3d'", nm->compile_id());
|
||||
xtty->method(nm->method());
|
||||
xtty->stamp();
|
||||
xtty->end_elem();
|
||||
}
|
||||
nm->method()->clear_code();
|
||||
nm->set_speculatively_disconnected(true);
|
||||
}
|
||||
|
||||
|
||||
void CodeCache::gc_prologue() {
|
||||
assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_epilogue must be called");
|
||||
}
|
||||
|
||||
|
||||
void CodeCache::gc_epilogue() {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
FOR_ALL_ALIVE_BLOBS(cb) {
|
||||
|
|
|
@ -57,7 +57,6 @@ class CodeCache : AllStatic {
|
|||
static int _number_of_nmethods_with_dependencies;
|
||||
static bool _needs_cache_clean;
|
||||
static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link()
|
||||
static nmethod* _saved_nmethods; // Linked list of speculatively disconnected nmethods.
|
||||
|
||||
static void verify_if_often() PRODUCT_RETURN;
|
||||
|
||||
|
@ -167,17 +166,12 @@ class CodeCache : AllStatic {
|
|||
static size_t capacity() { return _heap->capacity(); }
|
||||
static size_t max_capacity() { return _heap->max_capacity(); }
|
||||
static size_t unallocated_capacity() { return _heap->unallocated_capacity(); }
|
||||
static bool needs_flushing() { return unallocated_capacity() < CodeCacheFlushingMinimumFreeSpace; }
|
||||
static double reverse_free_ratio();
|
||||
|
||||
static bool needs_cache_clean() { return _needs_cache_clean; }
|
||||
static void set_needs_cache_clean(bool v) { _needs_cache_clean = v; }
|
||||
static void clear_inline_caches(); // clear all inline caches
|
||||
|
||||
static nmethod* reanimate_saved_code(Method* m);
|
||||
static void remove_saved_code(nmethod* nm);
|
||||
static void speculatively_disconnect(nmethod* nm);
|
||||
|
||||
// Deoptimization
|
||||
static int mark_for_deoptimization(DepChange& changes);
|
||||
#ifdef HOTSWAP
|
||||
|
|
|
@ -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
|
||||
|
@ -160,32 +160,42 @@ address CompiledIC::stub_address() const {
|
|||
// High-level access to an inline cache. Guaranteed to be MT-safe.
|
||||
|
||||
|
||||
void CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS) {
|
||||
methodHandle method = call_info->selected_method();
|
||||
bool is_invoke_interface = (bytecode == Bytecodes::_invokeinterface && !call_info->has_vtable_index());
|
||||
bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS) {
|
||||
assert(CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
|
||||
assert(!is_optimized(), "cannot set an optimized virtual call to megamorphic");
|
||||
assert(is_call_to_compiled() || is_call_to_interpreted(), "going directly to megamorphic?");
|
||||
|
||||
address entry;
|
||||
if (is_invoke_interface) {
|
||||
int index = klassItable::compute_itable_index(call_info->resolved_method()());
|
||||
entry = VtableStubs::create_stub(false, index, method());
|
||||
assert(entry != NULL, "entry not computed");
|
||||
if (call_info->call_kind() == CallInfo::itable_call) {
|
||||
assert(bytecode == Bytecodes::_invokeinterface, "");
|
||||
int itable_index = call_info->itable_index();
|
||||
entry = VtableStubs::find_itable_stub(itable_index);
|
||||
if (entry == false) {
|
||||
return false;
|
||||
}
|
||||
#ifdef ASSERT
|
||||
int index = call_info->resolved_method()->itable_index();
|
||||
assert(index == itable_index, "CallInfo pre-computes this");
|
||||
#endif //ASSERT
|
||||
InstanceKlass* k = call_info->resolved_method()->method_holder();
|
||||
assert(k->is_interface(), "sanity check");
|
||||
assert(k->verify_itable_index(itable_index), "sanity check");
|
||||
InlineCacheBuffer::create_transition_stub(this, k, entry);
|
||||
} else {
|
||||
// Can be different than method->vtable_index(), due to package-private etc.
|
||||
assert(call_info->call_kind() == CallInfo::vtable_call, "either itable or vtable");
|
||||
// Can be different than selected_method->vtable_index(), due to package-private etc.
|
||||
int vtable_index = call_info->vtable_index();
|
||||
entry = VtableStubs::create_stub(true, vtable_index, method());
|
||||
InlineCacheBuffer::create_transition_stub(this, method(), entry);
|
||||
assert(call_info->resolved_klass()->verify_vtable_index(vtable_index), "sanity check");
|
||||
entry = VtableStubs::find_vtable_stub(vtable_index);
|
||||
if (entry == NULL) {
|
||||
return false;
|
||||
}
|
||||
InlineCacheBuffer::create_transition_stub(this, NULL, entry);
|
||||
}
|
||||
|
||||
if (TraceICs) {
|
||||
ResourceMark rm;
|
||||
tty->print_cr ("IC@" INTPTR_FORMAT ": to megamorphic %s entry: " INTPTR_FORMAT,
|
||||
instruction_address(), method->print_value_string(), entry);
|
||||
instruction_address(), call_info->selected_method()->print_value_string(), entry);
|
||||
}
|
||||
|
||||
// We can't check this anymore. With lazy deopt we could have already
|
||||
|
@ -195,6 +205,7 @@ void CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecod
|
|||
// race because the IC entry was complete when we safepointed so
|
||||
// cleaning it immediately is harmless.
|
||||
// assert(is_megamorphic(), "sanity check");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -226,7 +226,10 @@ class CompiledIC: public ResourceObj {
|
|||
//
|
||||
void set_to_clean(); // Can only be called during a safepoint operation
|
||||
void set_to_monomorphic(CompiledICInfo& info);
|
||||
void set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS);
|
||||
|
||||
// Returns true if successful and false otherwise. The call can fail if memory
|
||||
// allocation in the code cache fails.
|
||||
bool set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS);
|
||||
|
||||
static void compute_monomorphic_entry(methodHandle method, KlassHandle receiver_klass,
|
||||
bool is_optimized, bool static_bound, CompiledICInfo& info, TRAPS);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
|
@ -38,7 +38,7 @@ class DIR_Chunk {
|
|||
int _length; // number of bytes in the stream
|
||||
int _hash; // hash of stream bytes (for quicker reuse)
|
||||
|
||||
void* operator new(size_t ignore, DebugInformationRecorder* dir) {
|
||||
void* operator new(size_t ignore, DebugInformationRecorder* dir) throw() {
|
||||
assert(ignore == sizeof(DIR_Chunk), "");
|
||||
if (dir->_next_chunk >= dir->_next_chunk_limit) {
|
||||
const int CHUNK = 100;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
|
@ -812,8 +812,8 @@ class ClassHierarchyWalker {
|
|||
Klass* k = ctxk;
|
||||
Method* lm = k->lookup_method(m->name(), m->signature());
|
||||
if (lm == NULL && k->oop_is_instance()) {
|
||||
// It might be an abstract interface method, devoid of mirandas.
|
||||
lm = ((InstanceKlass*)k)->lookup_method_in_all_interfaces(m->name(),
|
||||
// It might be an interface method
|
||||
lm = ((InstanceKlass*)k)->lookup_method_in_ordered_interfaces(m->name(),
|
||||
m->signature());
|
||||
}
|
||||
if (lm == m)
|
||||
|
|
|
@ -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
|
||||
|
@ -93,18 +93,21 @@ HS_DTRACE_PROBE_DECL6(hotspot, compiled__method__unload,
|
|||
#endif
|
||||
|
||||
bool nmethod::is_compiled_by_c1() const {
|
||||
if (compiler() == NULL || method() == NULL) return false; // can happen during debug printing
|
||||
if (is_native_method()) return false;
|
||||
if (compiler() == NULL) {
|
||||
return false;
|
||||
}
|
||||
return compiler()->is_c1();
|
||||
}
|
||||
bool nmethod::is_compiled_by_c2() const {
|
||||
if (compiler() == NULL || method() == NULL) return false; // can happen during debug printing
|
||||
if (is_native_method()) return false;
|
||||
if (compiler() == NULL) {
|
||||
return false;
|
||||
}
|
||||
return compiler()->is_c2();
|
||||
}
|
||||
bool nmethod::is_compiled_by_shark() const {
|
||||
if (is_native_method()) return false;
|
||||
assert(compiler() != NULL, "must be");
|
||||
if (compiler() == NULL) {
|
||||
return false;
|
||||
}
|
||||
return compiler()->is_shark();
|
||||
}
|
||||
|
||||
|
@ -459,7 +462,6 @@ void nmethod::init_defaults() {
|
|||
_state = alive;
|
||||
_marked_for_reclamation = 0;
|
||||
_has_flushed_dependencies = 0;
|
||||
_speculatively_disconnected = 0;
|
||||
_has_unsafe_access = 0;
|
||||
_has_method_handle_invokes = 0;
|
||||
_lazy_critical_native = 0;
|
||||
|
@ -478,7 +480,6 @@ void nmethod::init_defaults() {
|
|||
_osr_link = NULL;
|
||||
_scavenge_root_link = NULL;
|
||||
_scavenge_root_state = 0;
|
||||
_saved_nmethod_link = NULL;
|
||||
_compiler = NULL;
|
||||
|
||||
#ifdef HAVE_DTRACE_H
|
||||
|
@ -683,6 +684,7 @@ nmethod::nmethod(
|
|||
_osr_entry_point = NULL;
|
||||
_exception_cache = NULL;
|
||||
_pc_desc_cache.reset_to(NULL);
|
||||
_hotness_counter = NMethodSweeper::hotness_counter_reset_val();
|
||||
|
||||
code_buffer->copy_values_to(this);
|
||||
if (ScavengeRootsInCode && detect_scavenge_root_oops()) {
|
||||
|
@ -767,6 +769,7 @@ nmethod::nmethod(
|
|||
_osr_entry_point = NULL;
|
||||
_exception_cache = NULL;
|
||||
_pc_desc_cache.reset_to(NULL);
|
||||
_hotness_counter = NMethodSweeper::hotness_counter_reset_val();
|
||||
|
||||
code_buffer->copy_values_to(this);
|
||||
debug_only(verify_scavenge_root_oops());
|
||||
|
@ -800,7 +803,7 @@ nmethod::nmethod(
|
|||
}
|
||||
#endif // def HAVE_DTRACE_H
|
||||
|
||||
void* nmethod::operator new(size_t size, int nmethod_size) {
|
||||
void* nmethod::operator new(size_t size, int nmethod_size) throw() {
|
||||
// Not critical, may return null if there is too little continuous memory
|
||||
return CodeCache::allocate(nmethod_size);
|
||||
}
|
||||
|
@ -839,6 +842,7 @@ nmethod::nmethod(
|
|||
_comp_level = comp_level;
|
||||
_compiler = compiler;
|
||||
_orig_pc_offset = orig_pc_offset;
|
||||
_hotness_counter = NMethodSweeper::hotness_counter_reset_val();
|
||||
|
||||
// Section offsets
|
||||
_consts_offset = content_offset() + code_buffer->total_offset_of(code_buffer->consts());
|
||||
|
@ -1173,7 +1177,7 @@ void nmethod::cleanup_inline_caches() {
|
|||
|
||||
// This is a private interface with the sweeper.
|
||||
void nmethod::mark_as_seen_on_stack() {
|
||||
assert(is_not_entrant(), "must be a non-entrant method");
|
||||
assert(is_alive(), "Must be an alive method");
|
||||
// Set the traversal mark to ensure that the sweeper does 2
|
||||
// cleaning passes before moving to zombie.
|
||||
set_stack_traversal_mark(NMethodSweeper::traversal_count());
|
||||
|
@ -1258,7 +1262,7 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
|
|||
|
||||
set_osr_link(NULL);
|
||||
//set_scavenge_root_link(NULL); // done by prune_scavenge_root_nmethods
|
||||
NMethodSweeper::notify(this);
|
||||
NMethodSweeper::notify();
|
||||
}
|
||||
|
||||
void nmethod::invalidate_osr_method() {
|
||||
|
@ -1348,6 +1352,15 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
|||
nmethod_needs_unregister = true;
|
||||
}
|
||||
|
||||
// Must happen before state change. Otherwise we have a race condition in
|
||||
// nmethod::can_not_entrant_be_converted(). I.e., a method can immediately
|
||||
// transition its state from 'not_entrant' to 'zombie' without having to wait
|
||||
// for stack scanning.
|
||||
if (state == not_entrant) {
|
||||
mark_as_seen_on_stack();
|
||||
OrderAccess::storestore();
|
||||
}
|
||||
|
||||
// Change state
|
||||
_state = state;
|
||||
|
||||
|
@ -1366,11 +1379,6 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
|||
HandleMark hm;
|
||||
method()->clear_code();
|
||||
}
|
||||
|
||||
if (state == not_entrant) {
|
||||
mark_as_seen_on_stack();
|
||||
}
|
||||
|
||||
} // leave critical region under Patching_lock
|
||||
|
||||
// When the nmethod becomes zombie it is no longer alive so the
|
||||
|
@ -1401,6 +1409,9 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
|||
// nmethods aren't scanned for GC.
|
||||
_oops_are_stale = true;
|
||||
#endif
|
||||
// the Method may be reclaimed by class unloading now that the
|
||||
// nmethod is in zombie state
|
||||
set_method(NULL);
|
||||
} else {
|
||||
assert(state == not_entrant, "other cases may need to be handled differently");
|
||||
}
|
||||
|
@ -1410,7 +1421,7 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
|
|||
}
|
||||
|
||||
// Make sweeper aware that there is a zombie method that needs to be removed
|
||||
NMethodSweeper::notify(this);
|
||||
NMethodSweeper::notify();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1445,10 +1456,6 @@ void nmethod::flush() {
|
|||
CodeCache::drop_scavenge_root_nmethod(this);
|
||||
}
|
||||
|
||||
if (is_speculatively_disconnected()) {
|
||||
CodeCache::remove_saved_code(this);
|
||||
}
|
||||
|
||||
#ifdef SHARK
|
||||
((SharkCompiler *) compiler())->free_compiled_method(insts_begin());
|
||||
#endif // SHARK
|
||||
|
@ -1959,7 +1966,7 @@ public:
|
|||
if (!_detected_scavenge_root) _print_nm->print_on(tty, "new scavenge root");
|
||||
tty->print_cr(""PTR_FORMAT"[offset=%d] detected scavengable oop "PTR_FORMAT" (found at "PTR_FORMAT")",
|
||||
_print_nm, (int)((intptr_t)p - (intptr_t)_print_nm),
|
||||
(intptr_t)(*p), (intptr_t)p);
|
||||
(void *)(*p), (intptr_t)p);
|
||||
(*p)->print();
|
||||
}
|
||||
#endif //PRODUCT
|
||||
|
@ -2339,7 +2346,7 @@ public:
|
|||
_ok = false;
|
||||
}
|
||||
tty->print_cr("*** non-oop "PTR_FORMAT" found at "PTR_FORMAT" (offset %d)",
|
||||
(intptr_t)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm));
|
||||
(void *)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm));
|
||||
}
|
||||
virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
|
||||
};
|
||||
|
@ -2460,7 +2467,7 @@ public:
|
|||
_ok = false;
|
||||
}
|
||||
tty->print_cr("*** scavengable oop "PTR_FORMAT" found at "PTR_FORMAT" (offset %d)",
|
||||
(intptr_t)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm));
|
||||
(void *)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm));
|
||||
(*p)->print();
|
||||
}
|
||||
virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
|
||||
|
|
|
@ -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
|
||||
|
@ -119,7 +119,6 @@ class nmethod : public CodeBlob {
|
|||
// To support simple linked-list chaining of nmethods:
|
||||
nmethod* _osr_link; // from InstanceKlass::osr_nmethods_head
|
||||
nmethod* _scavenge_root_link; // from CodeCache::scavenge_root_nmethods
|
||||
nmethod* _saved_nmethod_link; // from CodeCache::speculatively_disconnect
|
||||
|
||||
static nmethod* volatile _oops_do_mark_nmethods;
|
||||
nmethod* volatile _oops_do_mark_link;
|
||||
|
@ -165,7 +164,6 @@ class nmethod : public CodeBlob {
|
|||
|
||||
// protected by CodeCache_lock
|
||||
bool _has_flushed_dependencies; // Used for maintenance of dependencies (CodeCache_lock)
|
||||
bool _speculatively_disconnected; // Marked for potential unload
|
||||
|
||||
bool _marked_for_reclamation; // Used by NMethodSweeper (set only by sweeper)
|
||||
bool _marked_for_deoptimization; // Used for stack deoptimization
|
||||
|
@ -180,7 +178,7 @@ class nmethod : public CodeBlob {
|
|||
unsigned int _has_wide_vectors:1; // Preserve wide vectors at safepoints
|
||||
|
||||
// Protected by Patching_lock
|
||||
unsigned char _state; // {alive, not_entrant, zombie, unloaded}
|
||||
volatile unsigned char _state; // {alive, not_entrant, zombie, unloaded}
|
||||
|
||||
#ifdef ASSERT
|
||||
bool _oops_are_stale; // indicates that it's no longer safe to access oops section
|
||||
|
@ -202,11 +200,18 @@ class nmethod : public CodeBlob {
|
|||
|
||||
// not_entrant method removal. Each mark_sweep pass will update
|
||||
// this mark to current sweep invocation count if it is seen on the
|
||||
// stack. An not_entrant method can be removed when there is no
|
||||
// stack. An not_entrant method can be removed when there are no
|
||||
// more activations, i.e., when the _stack_traversal_mark is less than
|
||||
// current sweep traversal index.
|
||||
long _stack_traversal_mark;
|
||||
|
||||
// The _hotness_counter indicates the hotness of a method. The higher
|
||||
// the value the hotter the method. The hotness counter of a nmethod is
|
||||
// set to [(ReservedCodeCacheSize / (1024 * 1024)) * 2] each time the method
|
||||
// is active while stack scanning (mark_active_nmethods()). The hotness
|
||||
// counter is decreased (by 1) while sweeping.
|
||||
int _hotness_counter;
|
||||
|
||||
ExceptionCache *_exception_cache;
|
||||
PcDescCache _pc_desc_cache;
|
||||
|
||||
|
@ -265,7 +270,7 @@ class nmethod : public CodeBlob {
|
|||
int comp_level);
|
||||
|
||||
// helper methods
|
||||
void* operator new(size_t size, int nmethod_size);
|
||||
void* operator new(size_t size, int nmethod_size) throw();
|
||||
|
||||
const char* reloc_string_for(u_char* begin, u_char* end);
|
||||
// Returns true if this thread changed the state of the nmethod or
|
||||
|
@ -382,6 +387,10 @@ class nmethod : public CodeBlob {
|
|||
|
||||
int total_size () const;
|
||||
|
||||
void dec_hotness_counter() { _hotness_counter--; }
|
||||
void set_hotness_counter(int val) { _hotness_counter = val; }
|
||||
int hotness_counter() const { return _hotness_counter; }
|
||||
|
||||
// Containment
|
||||
bool consts_contains (address addr) const { return consts_begin () <= addr && addr < consts_end (); }
|
||||
bool insts_contains (address addr) const { return insts_begin () <= addr && addr < insts_end (); }
|
||||
|
@ -408,8 +417,8 @@ class nmethod : public CodeBlob {
|
|||
// alive. It is used when an uncommon trap happens. Returns true
|
||||
// if this thread changed the state of the nmethod or false if
|
||||
// another thread performed the transition.
|
||||
bool make_not_entrant() { return make_not_entrant_or_zombie(not_entrant); }
|
||||
bool make_zombie() { return make_not_entrant_or_zombie(zombie); }
|
||||
bool make_not_entrant() { return make_not_entrant_or_zombie(not_entrant); }
|
||||
bool make_zombie() { return make_not_entrant_or_zombie(zombie); }
|
||||
|
||||
// used by jvmti to track if the unload event has been reported
|
||||
bool unload_reported() { return _unload_reported; }
|
||||
|
@ -437,9 +446,6 @@ class nmethod : public CodeBlob {
|
|||
bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
|
||||
void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }
|
||||
|
||||
bool is_speculatively_disconnected() const { return _speculatively_disconnected; }
|
||||
void set_speculatively_disconnected(bool z) { _speculatively_disconnected = z; }
|
||||
|
||||
bool is_lazy_critical_native() const { return _lazy_critical_native; }
|
||||
void set_lazy_critical_native(bool z) { _lazy_critical_native = z; }
|
||||
|
||||
|
@ -499,9 +505,6 @@ public:
|
|||
nmethod* scavenge_root_link() const { return _scavenge_root_link; }
|
||||
void set_scavenge_root_link(nmethod *n) { _scavenge_root_link = n; }
|
||||
|
||||
nmethod* saved_nmethod_link() const { return _saved_nmethod_link; }
|
||||
void set_saved_nmethod_link(nmethod *n) { _saved_nmethod_link = n; }
|
||||
|
||||
public:
|
||||
|
||||
// Sweeper support
|
||||
|
|
|
@ -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
|
||||
|
@ -678,7 +678,7 @@ class Relocation VALUE_OBJ_CLASS_SPEC {
|
|||
}
|
||||
|
||||
public:
|
||||
void* operator new(size_t size, const RelocationHolder& holder) {
|
||||
void* operator new(size_t size, const RelocationHolder& holder) throw() {
|
||||
if (size > sizeof(holder._relocbuf)) guarantee_size();
|
||||
assert((void* const *)holder.reloc() == &holder._relocbuf[0], "ptrs must agree");
|
||||
return holder.reloc();
|
||||
|
|
|
@ -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
|
||||
|
@ -46,12 +46,9 @@ address VtableStub::_chunk = NULL;
|
|||
address VtableStub::_chunk_end = NULL;
|
||||
VMReg VtableStub::_receiver_location = VMRegImpl::Bad();
|
||||
|
||||
static int num_vtable_chunks = 0;
|
||||
|
||||
|
||||
void* VtableStub::operator new(size_t size, int code_size) {
|
||||
void* VtableStub::operator new(size_t size, int code_size) throw() {
|
||||
assert(size == sizeof(VtableStub), "mismatched size");
|
||||
num_vtable_chunks++;
|
||||
// compute real VtableStub size (rounded to nearest word)
|
||||
const int real_size = round_to(code_size + sizeof(VtableStub), wordSize);
|
||||
// malloc them in chunks to minimize header overhead
|
||||
|
@ -60,7 +57,7 @@ void* VtableStub::operator new(size_t size, int code_size) {
|
|||
const int bytes = chunk_factor * real_size + pd_code_alignment();
|
||||
BufferBlob* blob = BufferBlob::create("vtable chunks", bytes);
|
||||
if (blob == NULL) {
|
||||
vm_exit_out_of_memory(bytes, OOM_MALLOC_ERROR, "CodeCache: no room for vtable chunks");
|
||||
return NULL;
|
||||
}
|
||||
_chunk = blob->content_begin();
|
||||
_chunk_end = _chunk + bytes;
|
||||
|
@ -111,7 +108,7 @@ void VtableStubs::initialize() {
|
|||
}
|
||||
|
||||
|
||||
address VtableStubs::create_stub(bool is_vtable_stub, int vtable_index, Method* method) {
|
||||
address VtableStubs::find_stub(bool is_vtable_stub, int vtable_index) {
|
||||
assert(vtable_index >= 0, "must be positive");
|
||||
|
||||
VtableStub* s = ShareVtableStubs ? lookup(is_vtable_stub, vtable_index) : NULL;
|
||||
|
@ -121,6 +118,12 @@ address VtableStubs::create_stub(bool is_vtable_stub, int vtable_index, Method*
|
|||
} else {
|
||||
s = create_itable_stub(vtable_index);
|
||||
}
|
||||
|
||||
// Creation of vtable or itable can fail if there is not enough free space in the code cache.
|
||||
if (s == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enter(is_vtable_stub, vtable_index, s);
|
||||
if (PrintAdapterHandlers) {
|
||||
tty->print_cr("Decoding VtableStub %s[%d]@%d",
|
||||
|
|
|
@ -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
|
||||
|
@ -46,7 +46,7 @@ class VtableStub {
|
|||
bool _is_vtable_stub; // True if vtable stub, false, is itable stub
|
||||
/* code follows here */ // The vtableStub code
|
||||
|
||||
void* operator new(size_t size, int code_size);
|
||||
void* operator new(size_t size, int code_size) throw();
|
||||
|
||||
VtableStub(bool is_vtable_stub, int index)
|
||||
: _next(NULL), _is_vtable_stub(is_vtable_stub),
|
||||
|
@ -121,9 +121,11 @@ class VtableStubs : AllStatic {
|
|||
static VtableStub* lookup (bool is_vtable_stub, int vtable_index);
|
||||
static void enter (bool is_vtable_stub, int vtable_index, VtableStub* s);
|
||||
static inline uint hash (bool is_vtable_stub, int vtable_index);
|
||||
static address find_stub (bool is_vtable_stub, int vtable_index);
|
||||
|
||||
public:
|
||||
static address create_stub(bool is_vtable_stub, int vtable_index, Method* method); // return the entry point of a stub for this call
|
||||
static address find_vtable_stub(int vtable_index) { return find_stub(true, vtable_index); }
|
||||
static address find_itable_stub(int itable_index) { return find_stub(false, itable_index); }
|
||||
static bool is_entry_point(address pc); // is pc a vtable stub entry point?
|
||||
static bool contains(address pc); // is pc within any stub?
|
||||
static VtableStub* stub_containing(address pc); // stub containing pc or NULL
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue