mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
6964458: Reimplement class meta-data storage to use native memory
Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes Co-authored-by: Stefan Karlsson <stefan.karlsson@oracle.com> Co-authored-by: Mikael Gerdin <mikael.gerdin@oracle.com> Co-authored-by: Tom Rodriguez <tom.rodriguez@oracle.com> Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
This commit is contained in:
parent
36eee7c8c8
commit
5c58d27aac
853 changed files with 26124 additions and 82956 deletions
|
@ -34,6 +34,7 @@
|
|||
#include "interpreter/oopMapCache.hpp"
|
||||
#include "jvmtifiles/jvmtiEnv.hpp"
|
||||
#include "memory/gcLocker.inline.hpp"
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "memory/oopFactory.hpp"
|
||||
#include "memory/universe.inline.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
|
@ -219,6 +220,7 @@ Thread::Thread() {
|
|||
set_osthread(NULL);
|
||||
set_resource_area(new (mtThread)ResourceArea());
|
||||
set_handle_area(new (mtThread) HandleArea(NULL));
|
||||
set_metadata_handles(new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(300, true));
|
||||
set_active_handles(NULL);
|
||||
set_free_handle_block(NULL);
|
||||
set_last_handle_mark(NULL);
|
||||
|
@ -346,6 +348,7 @@ Thread::~Thread() {
|
|||
ParkEvent::Release (_MuxEvent) ; _MuxEvent = NULL ;
|
||||
|
||||
delete handle_area();
|
||||
delete metadata_handles();
|
||||
|
||||
// osthread() can be NULL, if creation of thread failed.
|
||||
if (osthread() != NULL) os::free_thread(osthread());
|
||||
|
@ -817,6 +820,14 @@ void Thread::nmethods_do(CodeBlobClosure* cf) {
|
|||
// no nmethods in a generic thread...
|
||||
}
|
||||
|
||||
void Thread::metadata_do(void f(Metadata*)) {
|
||||
if (metadata_handles() != NULL) {
|
||||
for (int i = 0; i< metadata_handles()->length(); i++) {
|
||||
f(metadata_handles()->at(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::print_on(outputStream* st) const {
|
||||
// get_priority assumes osthread initialized
|
||||
if (osthread() != NULL) {
|
||||
|
@ -916,6 +927,8 @@ void Thread::check_for_valid_safepoint_state(bool potential_vm_operation) {
|
|||
bool Thread::is_in_stack(address adr) const {
|
||||
assert(Thread::current() == this, "is_in_stack can only be called from current thread");
|
||||
address end = os::current_stack_pointer();
|
||||
// Allow non Java threads to call this without stack_base
|
||||
if (_stack_base == NULL) return true;
|
||||
if (stack_base() >= adr && adr >= end) return true;
|
||||
|
||||
return false;
|
||||
|
@ -937,14 +950,14 @@ bool Thread::set_as_starting_thread() {
|
|||
}
|
||||
|
||||
static void initialize_class(Symbol* class_name, TRAPS) {
|
||||
klassOop klass = SystemDictionary::resolve_or_fail(class_name, true, CHECK);
|
||||
instanceKlass::cast(klass)->initialize(CHECK);
|
||||
Klass* klass = SystemDictionary::resolve_or_fail(class_name, true, CHECK);
|
||||
InstanceKlass::cast(klass)->initialize(CHECK);
|
||||
}
|
||||
|
||||
|
||||
// Creates the initial ThreadGroup
|
||||
static Handle create_initial_thread_group(TRAPS) {
|
||||
klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ThreadGroup(), true, CHECK_NH);
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ThreadGroup(), true, CHECK_NH);
|
||||
instanceKlassHandle klass (THREAD, k);
|
||||
|
||||
Handle system_instance = klass->allocate_instance_handle(CHECK_NH);
|
||||
|
@ -977,7 +990,7 @@ static Handle create_initial_thread_group(TRAPS) {
|
|||
|
||||
// Creates the initial Thread
|
||||
static oop create_initial_thread(Handle thread_group, JavaThread* thread, TRAPS) {
|
||||
klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_NULL);
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_NULL);
|
||||
instanceKlassHandle klass (THREAD, k);
|
||||
instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
|
||||
|
||||
|
@ -999,7 +1012,7 @@ static oop create_initial_thread(Handle thread_group, JavaThread* thread, TRAPS)
|
|||
}
|
||||
|
||||
static void call_initializeSystemClass(TRAPS) {
|
||||
klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
|
||||
instanceKlassHandle klass (THREAD, k);
|
||||
|
||||
JavaValue result(T_VOID);
|
||||
|
@ -1011,11 +1024,11 @@ char java_runtime_name[128] = "";
|
|||
|
||||
// extract the JRE name from sun.misc.Version.java_runtime_name
|
||||
static const char* get_java_runtime_name(TRAPS) {
|
||||
klassOop k = SystemDictionary::find(vmSymbols::sun_misc_Version(),
|
||||
Klass* k = SystemDictionary::find(vmSymbols::sun_misc_Version(),
|
||||
Handle(), Handle(), CHECK_AND_CLEAR_NULL);
|
||||
fieldDescriptor fd;
|
||||
bool found = k != NULL &&
|
||||
instanceKlass::cast(k)->find_local_field(vmSymbols::java_runtime_name_name(),
|
||||
InstanceKlass::cast(k)->find_local_field(vmSymbols::java_runtime_name_name(),
|
||||
vmSymbols::string_signature(), &fd);
|
||||
if (found) {
|
||||
oop name_oop = k->java_mirror()->obj_field(fd.offset());
|
||||
|
@ -1033,7 +1046,7 @@ static const char* get_java_runtime_name(TRAPS) {
|
|||
// General purpose hook into Java code, run once when the VM is initialized.
|
||||
// The Java library method itself may be changed independently from the VM.
|
||||
static void call_postVMInitHook(TRAPS) {
|
||||
klassOop k = SystemDictionary::PostVMInitHook_klass();
|
||||
Klass* k = SystemDictionary::PostVMInitHook_klass();
|
||||
instanceKlassHandle klass (THREAD, k);
|
||||
if (klass.not_null()) {
|
||||
JavaValue result(T_VOID);
|
||||
|
@ -1049,7 +1062,7 @@ static void reset_vm_info_property(TRAPS) {
|
|||
const char *vm_info = VM_Version::vm_info_string();
|
||||
|
||||
// java.lang.System class
|
||||
klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
|
||||
instanceKlassHandle klass (THREAD, k);
|
||||
|
||||
// setProperty arguments
|
||||
|
@ -1074,7 +1087,7 @@ void JavaThread::allocate_threadObj(Handle thread_group, char* thread_name, bool
|
|||
assert(thread_group.not_null(), "thread group should be specified");
|
||||
assert(threadObj() == NULL, "should only create Java thread object once");
|
||||
|
||||
klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK);
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK);
|
||||
instanceKlassHandle klass (THREAD, k);
|
||||
instanceHandle thread_oop = klass->allocate_instance_handle(CHECK);
|
||||
|
||||
|
@ -1982,7 +1995,7 @@ void JavaThread::check_and_handle_async_exceptions(bool check_unsafe_error) {
|
|||
frame f = last_frame();
|
||||
tty->print(" (pc: " INTPTR_FORMAT " sp: " INTPTR_FORMAT " )", f.pc(), f.sp());
|
||||
}
|
||||
tty->print_cr(" of type: %s", instanceKlass::cast(_pending_async_exception->klass())->external_name());
|
||||
tty->print_cr(" of type: %s", InstanceKlass::cast(_pending_async_exception->klass())->external_name());
|
||||
}
|
||||
_pending_async_exception = NULL;
|
||||
clear_has_async_exception();
|
||||
|
@ -2103,10 +2116,10 @@ void JavaThread::send_thread_stop(oop java_throwable) {
|
|||
|
||||
if (TraceExceptions) {
|
||||
ResourceMark rm;
|
||||
tty->print_cr("Pending Async. exception installed of type: %s", instanceKlass::cast(_pending_async_exception->klass())->external_name());
|
||||
tty->print_cr("Pending Async. exception installed of type: %s", InstanceKlass::cast(_pending_async_exception->klass())->external_name());
|
||||
}
|
||||
// for AbortVMOnException flag
|
||||
NOT_PRODUCT(Exceptions::debug_check_abort(instanceKlass::cast(_pending_async_exception->klass())->external_name()));
|
||||
NOT_PRODUCT(Exceptions::debug_check_abort(InstanceKlass::cast(_pending_async_exception->klass())->external_name()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2656,7 +2669,6 @@ void JavaThread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
|
|||
// around using this function
|
||||
f->do_oop((oop*) &_threadObj);
|
||||
f->do_oop((oop*) &_vm_result);
|
||||
f->do_oop((oop*) &_vm_result_2);
|
||||
f->do_oop((oop*) &_exception_oop);
|
||||
f->do_oop((oop*) &_pending_async_exception);
|
||||
|
||||
|
@ -2679,6 +2691,22 @@ void JavaThread::nmethods_do(CodeBlobClosure* cf) {
|
|||
}
|
||||
}
|
||||
|
||||
void JavaThread::metadata_do(void f(Metadata*)) {
|
||||
Thread::metadata_do(f);
|
||||
if (has_last_Java_frame()) {
|
||||
// Traverse the execution stack to call f() on the methods in the stack
|
||||
for(StackFrameStream fst(this); !fst.is_done(); fst.next()) {
|
||||
fst.current()->metadata_do(f);
|
||||
}
|
||||
} else if (is_Compiler_thread()) {
|
||||
// need to walk ciMetadata in current compile tasks to keep alive.
|
||||
CompilerThread* ct = (CompilerThread*)this;
|
||||
if (ct->env() != NULL) {
|
||||
ct->env()->metadata_do(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Printing
|
||||
const char* _get_thread_state_name(JavaThreadState _thread_state) {
|
||||
switch (_thread_state) {
|
||||
|
@ -2869,7 +2897,7 @@ void JavaThread::prepare(jobject jni_thread, ThreadPriority prio) {
|
|||
|
||||
Handle thread_oop(Thread::current(),
|
||||
JNIHandles::resolve_non_null(jni_thread));
|
||||
assert(instanceKlass::cast(thread_oop->klass())->is_linked(),
|
||||
assert(InstanceKlass::cast(thread_oop->klass())->is_linked(),
|
||||
"must be initialized");
|
||||
set_threadObj(thread_oop());
|
||||
java_lang_Thread::set_thread(thread_oop(), this);
|
||||
|
@ -3070,7 +3098,7 @@ javaVFrame* JavaThread::last_java_vframe(RegisterMap *reg_map) {
|
|||
}
|
||||
|
||||
|
||||
klassOop JavaThread::security_get_caller_class(int depth) {
|
||||
Klass* JavaThread::security_get_caller_class(int depth) {
|
||||
vframeStream vfst(this);
|
||||
vfst.security_get_caller_frame(depth);
|
||||
if (!vfst.at_end()) {
|
||||
|
@ -3123,6 +3151,9 @@ int Threads::_number_of_threads = 0;
|
|||
int Threads::_number_of_non_daemon_threads = 0;
|
||||
int Threads::_return_code = 0;
|
||||
size_t JavaThread::_stack_size_at_create = 0;
|
||||
#ifdef ASSERT
|
||||
bool Threads::_vm_complete = false;
|
||||
#endif
|
||||
|
||||
// All JavaThreads
|
||||
#define ALL_JAVA_THREADS(X) for (JavaThread* X = _thread_list; X; X = X->next())
|
||||
|
@ -3320,9 +3351,8 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
|||
// At this point, the Universe is initialized, but we have not executed
|
||||
// any byte code. Now is a good time (the only time) to dump out the
|
||||
// internal state of the JVM for sharing.
|
||||
|
||||
if (DumpSharedSpaces) {
|
||||
Universe::heap()->preload_and_dump(CHECK_0);
|
||||
MetaspaceShared::preload_and_dump(CHECK_0);
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
|
@ -3351,10 +3381,10 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
|||
// Forcibly initialize java/util/HashMap and mutate the private
|
||||
// static final "frontCacheEnabled" field before we start creating instances
|
||||
#ifdef ASSERT
|
||||
klassOop tmp_k = SystemDictionary::find(vmSymbols::java_util_HashMap(), Handle(), Handle(), CHECK_0);
|
||||
Klass* tmp_k = SystemDictionary::find(vmSymbols::java_util_HashMap(), Handle(), Handle(), CHECK_0);
|
||||
assert(tmp_k == NULL, "java/util/HashMap should not be loaded yet");
|
||||
#endif
|
||||
klassOop k_o = SystemDictionary::resolve_or_null(vmSymbols::java_util_HashMap(), Handle(), Handle(), CHECK_0);
|
||||
Klass* k_o = SystemDictionary::resolve_or_null(vmSymbols::java_util_HashMap(), Handle(), Handle(), CHECK_0);
|
||||
KlassHandle k = KlassHandle(THREAD, k_o);
|
||||
guarantee(k.not_null(), "Must find java/util/HashMap");
|
||||
instanceKlassHandle ik = instanceKlassHandle(THREAD, k());
|
||||
|
@ -3369,7 +3399,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
|||
if (UseStringCache) {
|
||||
// Forcibly initialize java/lang/StringValue and mutate the private
|
||||
// static final "stringCacheEnabled" field before we start creating instances
|
||||
klassOop k_o = SystemDictionary::resolve_or_null(vmSymbols::java_lang_StringValue(), Handle(), Handle(), CHECK_0);
|
||||
Klass* k_o = SystemDictionary::resolve_or_null(vmSymbols::java_lang_StringValue(), Handle(), Handle(), CHECK_0);
|
||||
// Possible that StringValue isn't present: if so, silently don't break
|
||||
if (k_o != NULL) {
|
||||
KlassHandle k = KlassHandle(THREAD, k_o);
|
||||
|
@ -3574,6 +3604,9 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
|||
os::init_3();
|
||||
|
||||
create_vm_timer.end();
|
||||
#ifdef ASSERT
|
||||
_vm_complete = true;
|
||||
#endif
|
||||
return JNI_OK;
|
||||
}
|
||||
|
||||
|
@ -3781,7 +3814,7 @@ void JavaThread::invoke_shutdown_hooks() {
|
|||
}
|
||||
|
||||
EXCEPTION_MARK;
|
||||
klassOop k =
|
||||
Klass* k =
|
||||
SystemDictionary::resolve_or_null(vmSymbols::java_lang_Shutdown(),
|
||||
THREAD);
|
||||
if (k != NULL) {
|
||||
|
@ -3840,6 +3873,9 @@ void JavaThread::invoke_shutdown_hooks() {
|
|||
bool Threads::destroy_vm() {
|
||||
JavaThread* thread = JavaThread::current();
|
||||
|
||||
#ifdef ASSERT
|
||||
_vm_complete = false;
|
||||
#endif
|
||||
// Wait until we are the last non-daemon thread to execute
|
||||
{ MutexLocker nu(Threads_lock);
|
||||
while (Threads::number_of_non_daemon_threads() > 1 )
|
||||
|
@ -4100,6 +4136,12 @@ void Threads::nmethods_do(CodeBlobClosure* cf) {
|
|||
VMThread::vm_thread()->nmethods_do(cf);
|
||||
}
|
||||
|
||||
void Threads::metadata_do(void f(Metadata*)) {
|
||||
ALL_JAVA_THREADS(p) {
|
||||
p->metadata_do(f);
|
||||
}
|
||||
}
|
||||
|
||||
void Threads::gc_epilogue() {
|
||||
ALL_JAVA_THREADS(p) {
|
||||
p->gc_epilogue();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue