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
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2012, 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
|
||||
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/loaderConstraints.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
|
@ -30,16 +31,20 @@
|
|||
#include "runtime/safepoint.hpp"
|
||||
#include "utilities/hashtable.inline.hpp"
|
||||
|
||||
void LoaderConstraintEntry::set_loader(int i, oop p) {
|
||||
set_loader_data(i, ClassLoaderData::class_loader_data(p));
|
||||
}
|
||||
|
||||
LoaderConstraintTable::LoaderConstraintTable(int nof_buckets)
|
||||
: Hashtable<klassOop, mtClass>(nof_buckets, sizeof(LoaderConstraintEntry)) {};
|
||||
: Hashtable<Klass*, mtClass>(nof_buckets, sizeof(LoaderConstraintEntry)) {};
|
||||
|
||||
|
||||
LoaderConstraintEntry* LoaderConstraintTable::new_entry(
|
||||
unsigned int hash, Symbol* name,
|
||||
klassOop klass, int num_loaders,
|
||||
Klass* klass, int num_loaders,
|
||||
int max_loaders) {
|
||||
LoaderConstraintEntry* entry;
|
||||
entry = (LoaderConstraintEntry*)Hashtable<klassOop, mtClass>::new_entry(hash, klass);
|
||||
entry = (LoaderConstraintEntry*)Hashtable<Klass*, mtClass>::new_entry(hash, klass);
|
||||
entry->set_name(name);
|
||||
entry->set_num_loaders(num_loaders);
|
||||
entry->set_max_loaders(max_loaders);
|
||||
|
@ -49,27 +54,21 @@ LoaderConstraintEntry* LoaderConstraintTable::new_entry(
|
|||
void LoaderConstraintTable::free_entry(LoaderConstraintEntry *entry) {
|
||||
// decrement name refcount before freeing
|
||||
entry->name()->decrement_refcount();
|
||||
Hashtable<klassOop, mtClass>::free_entry(entry);
|
||||
Hashtable<Klass*, mtClass>::free_entry(entry);
|
||||
}
|
||||
|
||||
|
||||
void LoaderConstraintTable::oops_do(OopClosure* f) {
|
||||
// Enhanced Class Redefinition support
|
||||
void LoaderConstraintTable::classes_do(KlassClosure* f) {
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
for (LoaderConstraintEntry* probe = bucket(index);
|
||||
probe != NULL;
|
||||
probe = probe->next()) {
|
||||
if (probe->klass() != NULL) {
|
||||
f->do_oop((oop*)probe->klass_addr());
|
||||
f->do_klass(probe->klass());
|
||||
}
|
||||
for (int n = 0; n < probe->num_loaders(); n++) {
|
||||
if (probe->loader(n) != NULL) {
|
||||
f->do_oop(probe->loader_addr(n));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The loaderConstraintTable must always be accessed with the
|
||||
// SystemDictionary lock held. This is true even for readers as
|
||||
|
@ -81,12 +80,14 @@ LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint(
|
|||
unsigned int hash = compute_hash(name);
|
||||
int index = hash_to_index(hash);
|
||||
LoaderConstraintEntry** pp = bucket_addr(index);
|
||||
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(loader());
|
||||
|
||||
while (*pp) {
|
||||
LoaderConstraintEntry* p = *pp;
|
||||
if (p->hash() == hash) {
|
||||
if (p->name() == name) {
|
||||
for (int i = p->num_loaders() - 1; i >= 0; i--) {
|
||||
if (p->loader(i) == loader()) {
|
||||
if (p->loader_data(i) == loader_data) {
|
||||
return pp;
|
||||
}
|
||||
}
|
||||
|
@ -98,16 +99,17 @@ LoaderConstraintEntry** LoaderConstraintTable::find_loader_constraint(
|
|||
}
|
||||
|
||||
|
||||
void LoaderConstraintTable::purge_loader_constraints(BoolObjectClosure* is_alive) {
|
||||
void LoaderConstraintTable::purge_loader_constraints() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
|
||||
// Remove unloaded entries from constraint table
|
||||
for (int index = 0; index < table_size(); index++) {
|
||||
LoaderConstraintEntry** p = bucket_addr(index);
|
||||
while(*p) {
|
||||
LoaderConstraintEntry* probe = *p;
|
||||
klassOop klass = probe->klass();
|
||||
Klass* klass = probe->klass();
|
||||
// Remove klass that is no longer alive
|
||||
if (klass != NULL && !is_alive->do_object_b(klass)) {
|
||||
if (klass != NULL &&
|
||||
klass->class_loader_data()->is_unloading()) {
|
||||
probe->set_klass(NULL);
|
||||
if (TraceLoaderConstraints) {
|
||||
ResourceMark rm;
|
||||
|
@ -116,19 +118,18 @@ void LoaderConstraintTable::purge_loader_constraints(BoolObjectClosure* is_alive
|
|||
probe->name()->as_C_string());
|
||||
for (int i = 0; i < probe->num_loaders(); i++) {
|
||||
tty->print_cr("[ [%d]: %s", i,
|
||||
SystemDictionary::loader_name(probe->loader(i)));
|
||||
SystemDictionary::loader_name(probe->loader_data(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove entries no longer alive from loader array
|
||||
int n = 0;
|
||||
while (n < probe->num_loaders()) {
|
||||
if (probe->loader(n) != NULL) {
|
||||
if (!is_alive->do_object_b(probe->loader(n))) {
|
||||
if (probe->loader_data(n)->is_unloading()) {
|
||||
if (TraceLoaderConstraints) {
|
||||
ResourceMark rm;
|
||||
tty->print_cr("[Purging loader %s from constraint for name %s",
|
||||
SystemDictionary::loader_name(probe->loader(n)),
|
||||
SystemDictionary::loader_name(probe->loader_data(n)),
|
||||
probe->name()->as_C_string()
|
||||
);
|
||||
}
|
||||
|
@ -136,22 +137,21 @@ void LoaderConstraintTable::purge_loader_constraints(BoolObjectClosure* is_alive
|
|||
// Compact array
|
||||
int num = probe->num_loaders() - 1;
|
||||
probe->set_num_loaders(num);
|
||||
probe->set_loader(n, probe->loader(num));
|
||||
probe->set_loader(num, NULL);
|
||||
probe->set_loader_data(n, probe->loader_data(num));
|
||||
probe->set_loader_data(num, NULL);
|
||||
|
||||
if (TraceLoaderConstraints) {
|
||||
ResourceMark rm;
|
||||
tty->print_cr("[New loader list:");
|
||||
for (int i = 0; i < probe->num_loaders(); i++) {
|
||||
tty->print_cr("[ [%d]: %s", i,
|
||||
SystemDictionary::loader_name(probe->loader(i)));
|
||||
SystemDictionary::loader_name(probe->loader_data(i)));
|
||||
}
|
||||
}
|
||||
|
||||
continue; // current element replaced, so restart without
|
||||
// incrementing n
|
||||
}
|
||||
}
|
||||
n++;
|
||||
}
|
||||
// Check whether entry should be purged
|
||||
|
@ -169,12 +169,9 @@ void LoaderConstraintTable::purge_loader_constraints(BoolObjectClosure* is_alive
|
|||
} else {
|
||||
#ifdef ASSERT
|
||||
if (probe->klass() != NULL) {
|
||||
assert(is_alive->do_object_b(probe->klass()), "klass should be live");
|
||||
}
|
||||
for (n = 0; n < probe->num_loaders(); n++) {
|
||||
if (probe->loader(n) != NULL) {
|
||||
assert(is_alive->do_object_b(probe->loader(n)), "loader should be live");
|
||||
}
|
||||
ClassLoaderData* loader_data =
|
||||
probe->klass()->class_loader_data();
|
||||
assert(!loader_data->is_unloading(), "klass should be live");
|
||||
}
|
||||
#endif
|
||||
// Go to next entry
|
||||
|
@ -185,14 +182,14 @@ void LoaderConstraintTable::purge_loader_constraints(BoolObjectClosure* is_alive
|
|||
}
|
||||
|
||||
bool LoaderConstraintTable::add_entry(Symbol* class_name,
|
||||
klassOop klass1, Handle class_loader1,
|
||||
klassOop klass2, Handle class_loader2) {
|
||||
Klass* klass1, Handle class_loader1,
|
||||
Klass* klass2, Handle class_loader2) {
|
||||
int failure_code = 0; // encode different reasons for failing
|
||||
|
||||
if (klass1 != NULL && klass2 != NULL && klass1 != klass2) {
|
||||
failure_code = 1;
|
||||
} else {
|
||||
klassOop klass = klass1 != NULL ? klass1 : klass2;
|
||||
Klass* klass = klass1 != NULL ? klass1 : klass2;
|
||||
|
||||
LoaderConstraintEntry** pp1 = find_loader_constraint(class_name,
|
||||
class_loader1);
|
||||
|
@ -224,7 +221,7 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name,
|
|||
int index = hash_to_index(hash);
|
||||
LoaderConstraintEntry* p;
|
||||
p = new_entry(hash, class_name, klass, 2, 2);
|
||||
p->set_loaders(NEW_C_HEAP_ARRAY(oop, 2, mtClass));
|
||||
p->set_loaders(NEW_C_HEAP_ARRAY(ClassLoaderData*, 2, mtClass));
|
||||
p->set_loader(0, class_loader1());
|
||||
p->set_loader(1, class_loader2());
|
||||
p->set_klass(klass);
|
||||
|
@ -319,11 +316,11 @@ bool LoaderConstraintTable::check_or_update(instanceKlassHandle k,
|
|||
}
|
||||
}
|
||||
|
||||
klassOop LoaderConstraintTable::find_constrained_klass(Symbol* name,
|
||||
Klass* LoaderConstraintTable::find_constrained_klass(Symbol* name,
|
||||
Handle loader) {
|
||||
LoaderConstraintEntry *p = *(find_loader_constraint(name, loader));
|
||||
if (p != NULL && p->klass() != NULL) {
|
||||
if (Klass::cast(p->klass())->oop_is_instance() && !instanceKlass::cast(p->klass())->is_loaded()) {
|
||||
if (Klass::cast(p->klass())->oop_is_instance() && !InstanceKlass::cast(p->klass())->is_loaded()) {
|
||||
// Only return fully loaded classes. Classes found through the
|
||||
// constraints might still be in the process of loading.
|
||||
return NULL;
|
||||
|
@ -340,10 +337,10 @@ void LoaderConstraintTable::ensure_loader_constraint_capacity(
|
|||
int nfree) {
|
||||
if (p->max_loaders() - p->num_loaders() < nfree) {
|
||||
int n = nfree + p->num_loaders();
|
||||
oop* new_loaders = NEW_C_HEAP_ARRAY(oop, n, mtClass);
|
||||
memcpy(new_loaders, p->loaders(), sizeof(oop) * p->num_loaders());
|
||||
ClassLoaderData** new_loaders = NEW_C_HEAP_ARRAY(ClassLoaderData*, n, mtClass);
|
||||
memcpy(new_loaders, p->loaders(), sizeof(ClassLoaderData*) * p->num_loaders());
|
||||
p->set_max_loaders(n);
|
||||
FREE_C_HEAP_ARRAY(oop, p->loaders(), mtClass);
|
||||
FREE_C_HEAP_ARRAY(ClassLoaderData*, p->loaders(), mtClass);
|
||||
p->set_loaders(new_loaders);
|
||||
}
|
||||
}
|
||||
|
@ -351,7 +348,7 @@ void LoaderConstraintTable::ensure_loader_constraint_capacity(
|
|||
|
||||
void LoaderConstraintTable::extend_loader_constraint(LoaderConstraintEntry* p,
|
||||
Handle loader,
|
||||
klassOop klass) {
|
||||
Klass* klass) {
|
||||
ensure_loader_constraint_capacity(p, 1);
|
||||
int num = p->num_loaders();
|
||||
p->set_loader(num, loader());
|
||||
|
@ -376,7 +373,7 @@ void LoaderConstraintTable::extend_loader_constraint(LoaderConstraintEntry* p,
|
|||
void LoaderConstraintTable::merge_loader_constraints(
|
||||
LoaderConstraintEntry** pp1,
|
||||
LoaderConstraintEntry** pp2,
|
||||
klassOop klass) {
|
||||
Klass* klass) {
|
||||
// make sure *pp1 has higher capacity
|
||||
if ((*pp1)->max_loaders() < (*pp2)->max_loaders()) {
|
||||
LoaderConstraintEntry** tmp = pp2;
|
||||
|
@ -391,7 +388,7 @@ void LoaderConstraintTable::merge_loader_constraints(
|
|||
|
||||
for (int i = 0; i < p2->num_loaders(); i++) {
|
||||
int num = p1->num_loaders();
|
||||
p1->set_loader(num, p2->loader(i));
|
||||
p1->set_loader_data(num, p2->loader_data(i));
|
||||
p1->set_num_loaders(num + 1);
|
||||
}
|
||||
|
||||
|
@ -403,7 +400,7 @@ void LoaderConstraintTable::merge_loader_constraints(
|
|||
|
||||
for (int i = 0; i < p1->num_loaders(); i++) {
|
||||
tty->print_cr("[ [%d]: %s", i,
|
||||
SystemDictionary::loader_name(p1->loader(i)));
|
||||
SystemDictionary::loader_name(p1->loader_data(i)));
|
||||
}
|
||||
if (p1->klass() == NULL) {
|
||||
tty->print_cr("[... and setting class object]");
|
||||
|
@ -439,33 +436,33 @@ void LoaderConstraintTable::verify(Dictionary* dictionary,
|
|||
probe != NULL;
|
||||
probe = probe->next()) {
|
||||
if (probe->klass() != NULL) {
|
||||
instanceKlass* ik = instanceKlass::cast(probe->klass());
|
||||
InstanceKlass* ik = InstanceKlass::cast(probe->klass());
|
||||
guarantee(ik->name() == probe->name(), "name should match");
|
||||
Symbol* name = ik->name();
|
||||
Handle loader(thread, ik->class_loader());
|
||||
unsigned int d_hash = dictionary->compute_hash(name, loader);
|
||||
ClassLoaderData* loader_data = ik->class_loader_data();
|
||||
unsigned int d_hash = dictionary->compute_hash(name, loader_data);
|
||||
int d_index = dictionary->hash_to_index(d_hash);
|
||||
klassOop k = dictionary->find_class(d_index, d_hash, name, loader);
|
||||
Klass* k = dictionary->find_class(d_index, d_hash, name, loader_data);
|
||||
if (k != NULL) {
|
||||
// We found the class in the system dictionary, so we should
|
||||
// make sure that the klassOop matches what we already have.
|
||||
// make sure that the Klass* matches what we already have.
|
||||
guarantee(k == probe->klass(), "klass should be in dictionary");
|
||||
} else {
|
||||
// If we don't find the class in the system dictionary, it
|
||||
// has to be in the placeholders table.
|
||||
unsigned int p_hash = placeholders->compute_hash(name, loader);
|
||||
unsigned int p_hash = placeholders->compute_hash(name, loader_data);
|
||||
int p_index = placeholders->hash_to_index(p_hash);
|
||||
PlaceholderEntry* entry = placeholders->get_entry(p_index, p_hash,
|
||||
name, loader);
|
||||
name, loader_data);
|
||||
|
||||
// The instanceKlass might not be on the entry, so the only
|
||||
// The InstanceKlass might not be on the entry, so the only
|
||||
// thing we can check here is whether we were successful in
|
||||
// finding the class in the placeholders table.
|
||||
guarantee(entry != NULL, "klass should be in the placeholders");
|
||||
}
|
||||
}
|
||||
for (int n = 0; n< probe->num_loaders(); n++) {
|
||||
guarantee(probe->loader(n)->is_oop_or_null(), "should be oop");
|
||||
assert(ClassLoaderDataGraph::contains_loader_data(probe->loader_data(n)), "The loader is missing");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -487,7 +484,7 @@ void LoaderConstraintTable::print() {
|
|||
probe->name()->print();
|
||||
tty->print(" , loaders:");
|
||||
for (int n = 0; n < probe->num_loaders(); n++) {
|
||||
probe->loader(n)->print_value();
|
||||
probe->loader_data(n)->print_value();
|
||||
tty->print(", ");
|
||||
}
|
||||
tty->cr();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue