mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
6962931: move interned strings out of the perm gen
Reviewed-by: never, coleenp, ysr, jwilhelm
This commit is contained in:
parent
1ed31f9194
commit
fe899cc10d
14 changed files with 58 additions and 41 deletions
|
@ -162,7 +162,7 @@ Handle java_lang_String::create_from_unicode(jchar* unicode, int length, TRAPS)
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle java_lang_String::create_tenured_from_unicode(jchar* unicode, int length, TRAPS) {
|
Handle java_lang_String::create_tenured_from_unicode(jchar* unicode, int length, TRAPS) {
|
||||||
return basic_create_from_unicode(unicode, length, true, CHECK_NH);
|
return basic_create_from_unicode(unicode, length, JavaObjectsInPerm, CHECK_NH);
|
||||||
}
|
}
|
||||||
|
|
||||||
oop java_lang_String::create_oop_from_unicode(jchar* unicode, int length, TRAPS) {
|
oop java_lang_String::create_oop_from_unicode(jchar* unicode, int length, TRAPS) {
|
||||||
|
|
|
@ -530,7 +530,7 @@ oop StringTable::basic_add(int index, Handle string_or_null, jchar* name,
|
||||||
|
|
||||||
Handle string;
|
Handle string;
|
||||||
// try to reuse the string if possible
|
// try to reuse the string if possible
|
||||||
if (!string_or_null.is_null() && string_or_null()->is_perm()) {
|
if (!string_or_null.is_null() && (!JavaObjectsInPerm || string_or_null()->is_perm())) {
|
||||||
string = string_or_null;
|
string = string_or_null;
|
||||||
} else {
|
} else {
|
||||||
string = java_lang_String::create_tenured_from_unicode(name, len, CHECK_NULL);
|
string = java_lang_String::create_tenured_from_unicode(name, len, CHECK_NULL);
|
||||||
|
@ -662,7 +662,7 @@ void StringTable::verify() {
|
||||||
for ( ; p != NULL; p = p->next()) {
|
for ( ; p != NULL; p = p->next()) {
|
||||||
oop s = p->literal();
|
oop s = p->literal();
|
||||||
guarantee(s != NULL, "interned string is NULL");
|
guarantee(s != NULL, "interned string is NULL");
|
||||||
guarantee(s->is_perm(), "interned string not in permspace");
|
guarantee(s->is_perm() || !JavaObjectsInPerm, "interned string not in permspace");
|
||||||
|
|
||||||
int length;
|
int length;
|
||||||
jchar* chars = java_lang_String::as_unicode_string(s, length);
|
jchar* chars = java_lang_String::as_unicode_string(s, length);
|
||||||
|
|
|
@ -5930,14 +5930,18 @@ void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
TraceTime t("scrub symbol & string tables", PrintGCDetails, false, gclog_or_tty);
|
TraceTime t("scrub symbol table", PrintGCDetails, false, gclog_or_tty);
|
||||||
// Now clean up stale oops in StringTable
|
|
||||||
StringTable::unlink(&_is_alive_closure);
|
|
||||||
// Clean up unreferenced symbols in symbol table.
|
// Clean up unreferenced symbols in symbol table.
|
||||||
SymbolTable::unlink();
|
SymbolTable::unlink();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (should_unload_classes() || !JavaObjectsInPerm) {
|
||||||
|
TraceTime t("scrub string table", PrintGCDetails, false, gclog_or_tty);
|
||||||
|
// Now clean up stale oops in StringTable
|
||||||
|
StringTable::unlink(&_is_alive_closure);
|
||||||
|
}
|
||||||
|
|
||||||
verify_work_stacks_empty();
|
verify_work_stacks_empty();
|
||||||
// Restore any preserved marks as a result of mark stack or
|
// Restore any preserved marks as a result of mark stack or
|
||||||
// work queue overflow
|
// work queue overflow
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/symbolTable.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/cardTableExtension.hpp"
|
#include "gc_implementation/parallelScavenge/cardTableExtension.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
|
#include "gc_implementation/parallelScavenge/gcTaskManager.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/generationSizer.hpp"
|
#include "gc_implementation/parallelScavenge/generationSizer.hpp"
|
||||||
|
@ -439,6 +440,14 @@ bool PSScavenge::invoke_no_policy() {
|
||||||
reference_processor()->enqueue_discovered_references(NULL);
|
reference_processor()->enqueue_discovered_references(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!JavaObjectsInPerm) {
|
||||||
|
// Unlink any dead interned Strings
|
||||||
|
StringTable::unlink(&_is_alive_closure);
|
||||||
|
// Process the remaining live ones
|
||||||
|
PSScavengeRootsClosure root_closure(promotion_manager);
|
||||||
|
StringTable::oops_do(&root_closure);
|
||||||
|
}
|
||||||
|
|
||||||
// Finally, flush the promotion_manager's labs, and deallocate its stacks.
|
// Finally, flush the promotion_manager's labs, and deallocate its stacks.
|
||||||
PSPromotionManager::post_scavenge();
|
PSPromotionManager::post_scavenge();
|
||||||
|
|
||||||
|
|
|
@ -86,4 +86,21 @@ inline void PSScavenge::copy_and_push_safe_barrier(PSPromotionManager* pm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PSScavengeRootsClosure: public OopClosure {
|
||||||
|
private:
|
||||||
|
PSPromotionManager* _promotion_manager;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
template <class T> void do_oop_work(T *p) {
|
||||||
|
if (PSScavenge::should_scavenge(p)) {
|
||||||
|
// We never card mark roots, maybe call a func without test?
|
||||||
|
PSScavenge::copy_and_push_safe_barrier(_promotion_manager, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
PSScavengeRootsClosure(PSPromotionManager* pm) : _promotion_manager(pm) { }
|
||||||
|
void do_oop(oop* p) { PSScavengeRootsClosure::do_oop_work(p); }
|
||||||
|
void do_oop(narrowOop* p) { PSScavengeRootsClosure::do_oop_work(p); }
|
||||||
|
};
|
||||||
|
|
||||||
#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSSCAVENGE_INLINE_HPP
|
#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSSCAVENGE_INLINE_HPP
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "gc_implementation/parallelScavenge/psMarkSweep.hpp"
|
#include "gc_implementation/parallelScavenge/psMarkSweep.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
|
#include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
|
#include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/psScavenge.hpp"
|
#include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/psTasks.hpp"
|
#include "gc_implementation/parallelScavenge/psTasks.hpp"
|
||||||
#include "memory/iterator.hpp"
|
#include "memory/iterator.hpp"
|
||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
|
@ -46,24 +46,6 @@
|
||||||
// ScavengeRootsTask
|
// ScavengeRootsTask
|
||||||
//
|
//
|
||||||
|
|
||||||
// Define before use
|
|
||||||
class PSScavengeRootsClosure: public OopClosure {
|
|
||||||
private:
|
|
||||||
PSPromotionManager* _promotion_manager;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
template <class T> void do_oop_work(T *p) {
|
|
||||||
if (PSScavenge::should_scavenge(p)) {
|
|
||||||
// We never card mark roots, maybe call a func without test?
|
|
||||||
PSScavenge::copy_and_push_safe_barrier(_promotion_manager, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
PSScavengeRootsClosure(PSPromotionManager* pm) : _promotion_manager(pm) { }
|
|
||||||
void do_oop(oop* p) { PSScavengeRootsClosure::do_oop_work(p); }
|
|
||||||
void do_oop(narrowOop* p) { PSScavengeRootsClosure::do_oop_work(p); }
|
|
||||||
};
|
|
||||||
|
|
||||||
void ScavengeRootsTask::do_it(GCTaskManager* manager, uint which) {
|
void ScavengeRootsTask::do_it(GCTaskManager* manager, uint which) {
|
||||||
assert(Universe::heap()->is_gc_active(), "called outside gc");
|
assert(Universe::heap()->is_gc_active(), "called outside gc");
|
||||||
|
|
||||||
|
|
|
@ -1561,6 +1561,7 @@ void GenCollectedHeap::preload_and_dump(TRAPS) {
|
||||||
// thread because it requires object allocation.
|
// thread because it requires object allocation.
|
||||||
LinkClassesClosure lcc(Thread::current());
|
LinkClassesClosure lcc(Thread::current());
|
||||||
object_iterate(&lcc);
|
object_iterate(&lcc);
|
||||||
|
ensure_parsability(false); // arg is actually don't care
|
||||||
tty->print_cr("done. ");
|
tty->print_cr("done. ");
|
||||||
|
|
||||||
// Create and dump the shared spaces.
|
// Create and dump the shared spaces.
|
||||||
|
|
|
@ -171,11 +171,13 @@ void SharedHeap::process_strong_roots(bool activate_scope,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) {
|
if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) {
|
||||||
if (so & SO_Strings) {
|
if (so & SO_Strings || (!collecting_perm_gen && !JavaObjectsInPerm)) {
|
||||||
StringTable::oops_do(roots);
|
StringTable::oops_do(roots);
|
||||||
}
|
}
|
||||||
// Verify if the string table contents are in the perm gen
|
if (JavaObjectsInPerm) {
|
||||||
NOT_PRODUCT(StringTable::oops_do(&assert_is_perm_closure));
|
// Verify the string table contents are in the perm gen
|
||||||
|
NOT_PRODUCT(StringTable::oops_do(&assert_is_perm_closure));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) {
|
if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) {
|
||||||
|
|
|
@ -285,10 +285,11 @@ int constantPoolKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
|
||||||
void constantPoolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
|
void constantPoolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
|
||||||
assert(obj->is_constantPool(), "should be constant pool");
|
assert(obj->is_constantPool(), "should be constant pool");
|
||||||
constantPoolOop cp = (constantPoolOop) obj;
|
constantPoolOop cp = (constantPoolOop) obj;
|
||||||
if (AnonymousClasses && cp->has_pseudo_string() && cp->tags() != NULL) {
|
if (cp->tags() != NULL &&
|
||||||
oop* base = (oop*)cp->base();
|
(!JavaObjectsInPerm || (AnonymousClasses && cp->has_pseudo_string()))) {
|
||||||
for (int i = 0; i < cp->length(); ++i, ++base) {
|
for (int i = 1; i < cp->length(); ++i) {
|
||||||
if (cp->tag_at(i).is_string()) {
|
if (cp->tag_at(i).is_string()) {
|
||||||
|
oop* base = cp->obj_at_addr_raw(i);
|
||||||
if (PSScavenge::should_scavenge(base)) {
|
if (PSScavenge::should_scavenge(base)) {
|
||||||
pm->claim_or_forward_depth(base);
|
pm->claim_or_forward_depth(base);
|
||||||
}
|
}
|
||||||
|
@ -460,7 +461,8 @@ void constantPoolKlass::oop_verify_on(oop obj, outputStream* st) {
|
||||||
if (cp->tag_at(i).is_string()) {
|
if (cp->tag_at(i).is_string()) {
|
||||||
if (!cp->has_pseudo_string()) {
|
if (!cp->has_pseudo_string()) {
|
||||||
if (entry.is_oop()) {
|
if (entry.is_oop()) {
|
||||||
guarantee(entry.get_oop()->is_perm(), "should be in permspace");
|
guarantee(!JavaObjectsInPerm || entry.get_oop()->is_perm(),
|
||||||
|
"should be in permspace");
|
||||||
guarantee(entry.get_oop()->is_instance(), "should be instance");
|
guarantee(entry.get_oop()->is_instance(), "should be instance");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1116,7 +1116,7 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar
|
||||||
Node* sourcea = basic_plus_adr(string_object, string_object, value_offset);
|
Node* sourcea = basic_plus_adr(string_object, string_object, value_offset);
|
||||||
Node* source = make_load(no_ctrl, sourcea, source_type, T_OBJECT, string_type->add_offset(value_offset));
|
Node* source = make_load(no_ctrl, sourcea, source_type, T_OBJECT, string_type->add_offset(value_offset));
|
||||||
|
|
||||||
Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array)) );
|
Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array, true)) );
|
||||||
jint target_length = target_array->length();
|
jint target_length = target_array->length();
|
||||||
const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin));
|
const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin));
|
||||||
const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot);
|
const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot);
|
||||||
|
|
|
@ -1573,9 +1573,9 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const {
|
||||||
return TypeInt::make(constant.as_int());
|
return TypeInt::make(constant.as_int());
|
||||||
} else if (constant.basic_type() == T_ARRAY) {
|
} else if (constant.basic_type() == T_ARRAY) {
|
||||||
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
|
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
|
||||||
return TypeNarrowOop::make_from_constant(constant.as_object());
|
return TypeNarrowOop::make_from_constant(constant.as_object(), true);
|
||||||
} else {
|
} else {
|
||||||
return TypeOopPtr::make_from_constant(constant.as_object());
|
return TypeOopPtr::make_from_constant(constant.as_object(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -910,7 +910,7 @@ Node* PhaseStringOpts::fetch_static_field(GraphKit& kit, ciField* field) {
|
||||||
ciObject* con = field->constant_value().as_object();
|
ciObject* con = field->constant_value().as_object();
|
||||||
// Do not "join" in the previous type; it doesn't add value,
|
// Do not "join" in the previous type; it doesn't add value,
|
||||||
// and may yield a vacuous result if the field is of interface type.
|
// and may yield a vacuous result if the field is of interface type.
|
||||||
type = TypeOopPtr::make_from_constant(con)->isa_oopptr();
|
type = TypeOopPtr::make_from_constant(con, true)->isa_oopptr();
|
||||||
assert(type != NULL, "field singleton type must be consistent");
|
assert(type != NULL, "field singleton type must be consistent");
|
||||||
} else {
|
} else {
|
||||||
type = TypeOopPtr::make_from_klass(field_klass->as_klass());
|
type = TypeOopPtr::make_from_klass(field_klass->as_klass());
|
||||||
|
|
|
@ -988,8 +988,8 @@ public:
|
||||||
|
|
||||||
static const TypeNarrowOop *make( const TypePtr* type);
|
static const TypeNarrowOop *make( const TypePtr* type);
|
||||||
|
|
||||||
static const TypeNarrowOop* make_from_constant(ciObject* con) {
|
static const TypeNarrowOop* make_from_constant(ciObject* con, bool require_constant = false) {
|
||||||
return make(TypeOopPtr::make_from_constant(con));
|
return make(TypeOopPtr::make_from_constant(con, require_constant));
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the equivalent ptr type for this compressed pointer
|
// returns the equivalent ptr type for this compressed pointer
|
||||||
|
|
|
@ -851,7 +851,7 @@ class CommandLineFlags {
|
||||||
diagnostic(bool, TraceNMethodInstalls, false, \
|
diagnostic(bool, TraceNMethodInstalls, false, \
|
||||||
"Trace nmethod intallation") \
|
"Trace nmethod intallation") \
|
||||||
\
|
\
|
||||||
diagnostic(intx, ScavengeRootsInCode, 0, \
|
diagnostic(intx, ScavengeRootsInCode, 1, \
|
||||||
"0: do not allow scavengable oops in the code cache; " \
|
"0: do not allow scavengable oops in the code cache; " \
|
||||||
"1: allow scavenging from the code cache; " \
|
"1: allow scavenging from the code cache; " \
|
||||||
"2: emit as many constants as the compiler can see") \
|
"2: emit as many constants as the compiler can see") \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue