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:
Jon Masamitsu 2012-09-01 13:25:18 -04:00 committed by Coleen Phillimore
parent 36eee7c8c8
commit 5c58d27aac
853 changed files with 26124 additions and 82956 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@ -439,6 +439,11 @@ RelocationHolder RelocationHolder::plus(int offset) const {
oop_Relocation* r = (oop_Relocation*)reloc();
return oop_Relocation::spec(r->oop_index(), r->offset() + offset);
}
case relocInfo::metadata_type:
{
metadata_Relocation* r = (metadata_Relocation*)reloc();
return metadata_Relocation::spec(r->metadata_index(), r->offset() + offset);
}
default:
ShouldNotReachHere();
}
@ -578,33 +583,33 @@ void oop_Relocation::unpack_data() {
unpack_2_ints(_oop_index, _offset);
}
void metadata_Relocation::pack_data_to(CodeSection* dest) {
short* p = (short*) dest->locs_end();
p = pack_2_ints_to(p, _metadata_index, _offset);
dest->set_locs_end((relocInfo*) p);
}
void metadata_Relocation::unpack_data() {
unpack_2_ints(_metadata_index, _offset);
}
void virtual_call_Relocation::pack_data_to(CodeSection* dest) {
short* p = (short*) dest->locs_end();
address point = dest->locs_point();
// Try to make a pointer NULL first.
if (_oop_limit >= point &&
_oop_limit <= point + NativeCall::instruction_size) {
_oop_limit = NULL;
}
// If the _oop_limit is NULL, it "defaults" to the end of the call.
// See ic_call_Relocation::oop_limit() below.
normalize_address(_first_oop, dest);
normalize_address(_oop_limit, dest);
jint x0 = scaled_offset_null_special(_first_oop, point);
jint x1 = scaled_offset_null_special(_oop_limit, point);
p = pack_2_ints_to(p, x0, x1);
normalize_address(_cached_value, dest);
jint x0 = scaled_offset_null_special(_cached_value, point);
p = pack_1_int_to(p, x0);
dest->set_locs_end((relocInfo*) p);
}
void virtual_call_Relocation::unpack_data() {
jint x0, x1; unpack_2_ints(x0, x1);
jint x0 = unpack_1_int();
address point = addr();
_first_oop = x0==0? NULL: address_from_scaled_offset(x0, point);
_oop_limit = x1==0? NULL: address_from_scaled_offset(x1, point);
_cached_value = x0==0? NULL: address_from_scaled_offset(x0, point);
}
@ -799,100 +804,48 @@ void oop_Relocation::verify_oop_relocation() {
}
}
RelocIterator virtual_call_Relocation::parse_ic(nmethod* &nm, address &ic_call, address &first_oop,
oop* &oop_addr, bool *is_optimized) {
assert(ic_call != NULL, "ic_call address must be set");
assert(ic_call != NULL || first_oop != NULL, "must supply a non-null input");
if (nm == NULL) {
CodeBlob* code;
if (ic_call != NULL) {
code = CodeCache::find_blob(ic_call);
} else if (first_oop != NULL) {
code = CodeCache::find_blob(first_oop);
}
nm = code->as_nmethod_or_null();
assert(nm != NULL, "address to parse must be in nmethod");
}
assert(ic_call == NULL || nm->contains(ic_call), "must be in nmethod");
assert(first_oop == NULL || nm->contains(first_oop), "must be in nmethod");
address oop_limit = NULL;
if (ic_call != NULL) {
// search for the ic_call at the given address
RelocIterator iter(nm, ic_call, ic_call+1);
bool ret = iter.next();
assert(ret == true, "relocInfo must exist at this address");
assert(iter.addr() == ic_call, "must find ic_call");
if (iter.type() == relocInfo::virtual_call_type) {
virtual_call_Relocation* r = iter.virtual_call_reloc();
first_oop = r->first_oop();
oop_limit = r->oop_limit();
*is_optimized = false;
// meta data versions
Metadata** metadata_Relocation::metadata_addr() {
int n = _metadata_index;
if (n == 0) {
// metadata is stored in the code stream
return (Metadata**) pd_address_in_code();
} else {
assert(iter.type() == relocInfo::opt_virtual_call_type, "must be a virtual call");
*is_optimized = true;
oop_addr = NULL;
first_oop = NULL;
return iter;
// metadata is stored in table at nmethod::metadatas_begin
return code()->metadata_addr_at(n);
}
}
// search for the first_oop, to get its oop_addr
RelocIterator all_oops(nm, first_oop);
RelocIterator iter = all_oops;
iter.set_limit(first_oop+1);
bool found_oop = false;
while (iter.next()) {
if (iter.type() == relocInfo::oop_type) {
assert(iter.addr() == first_oop, "must find first_oop");
oop_addr = iter.oop_reloc()->oop_addr();
found_oop = true;
break;
}
}
assert(found_oop, "must find first_oop");
bool did_reset = false;
while (ic_call == NULL) {
// search forward for the ic_call matching the given first_oop
while (iter.next()) {
if (iter.type() == relocInfo::virtual_call_type) {
virtual_call_Relocation* r = iter.virtual_call_reloc();
if (r->first_oop() == first_oop) {
ic_call = r->addr();
oop_limit = r->oop_limit();
break;
}
}
}
guarantee(!did_reset, "cannot find ic_call");
iter = RelocIterator(nm); // search the whole nmethod
did_reset = true;
Metadata* metadata_Relocation::metadata_value() {
Metadata* v = *metadata_addr();
// clean inline caches store a special pseudo-null
if (v == (Metadata*)Universe::non_oop_word()) v = NULL;
return v;
}
assert(oop_limit != NULL && first_oop != NULL && ic_call != NULL, "");
all_oops.set_limit(oop_limit);
return all_oops;
void metadata_Relocation::fix_metadata_relocation() {
if (!metadata_is_immediate()) {
// get the metadata from the pool, and re-insert it into the instruction:
pd_fix_value(value());
}
}
address virtual_call_Relocation::first_oop() {
assert(_first_oop != NULL && _first_oop < addr(), "must precede ic_call");
return _first_oop;
void metadata_Relocation::verify_metadata_relocation() {
if (!metadata_is_immediate()) {
// get the metadata from the pool, and re-insert it into the instruction:
verify_value(value());
}
}
address virtual_call_Relocation::oop_limit() {
if (_oop_limit == NULL)
return addr() + NativeCall::instruction_size;
else
return _oop_limit;
address virtual_call_Relocation::cached_value() {
assert(_cached_value != NULL && _cached_value < addr(), "must precede ic_call");
return _cached_value;
}
void virtual_call_Relocation::clear_inline_cache() {
// No stubs for ICs
// Clean IC
@ -1139,6 +1092,25 @@ void RelocIterator::print_current() {
}
break;
}
case relocInfo::metadata_type:
{
metadata_Relocation* r = metadata_reloc();
Metadata** metadata_addr = NULL;
Metadata* raw_metadata = NULL;
Metadata* metadata_value = NULL;
if (code() != NULL || r->metadata_is_immediate()) {
metadata_addr = r->metadata_addr();
raw_metadata = *metadata_addr;
metadata_value = r->metadata_value();
}
tty->print(" | [metadata_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]",
metadata_addr, (address)raw_metadata, r->offset());
if (metadata_value != NULL) {
tty->print("metadata_value=" INTPTR_FORMAT ": ", (address)metadata_value);
metadata_value->print_value_on(tty);
}
break;
}
case relocInfo::external_word_type:
case relocInfo::internal_word_type:
case relocInfo::section_word_type:
@ -1157,8 +1129,8 @@ void RelocIterator::print_current() {
case relocInfo::virtual_call_type:
{
virtual_call_Relocation* r = (virtual_call_Relocation*) reloc();
tty->print(" | [destination=" INTPTR_FORMAT " first_oop=" INTPTR_FORMAT " oop_limit=" INTPTR_FORMAT "]",
r->destination(), r->first_oop(), r->oop_limit());
tty->print(" | [destination=" INTPTR_FORMAT " cached_value=" INTPTR_FORMAT "]",
r->destination(), r->cached_value());
break;
}
case relocInfo::static_stub_type: