# HG changeset patch # User jcoomes # Date 1300826193 25200 # Node ID b099aaf51bf876c4197a9f5259889afdac2f1f2f # Parent 924777755fad2236d149bd2efad47b8a833fe680 6962931: move interned strings out of the perm gen Reviewed-by: never, coleenp, ysr, jwilhelm diff -r 924777755fad -r b099aaf51bf8 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Tue Mar 22 13:36:33 2011 -0700 @@ -162,7 +162,7 @@ } 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) { diff -r 924777755fad -r b099aaf51bf8 src/share/vm/classfile/symbolTable.cpp --- a/src/share/vm/classfile/symbolTable.cpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/classfile/symbolTable.cpp Tue Mar 22 13:36:33 2011 -0700 @@ -530,7 +530,7 @@ Handle string; // 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; } else { string = java_lang_String::create_tenured_from_unicode(name, len, CHECK_NULL); @@ -662,7 +662,7 @@ for ( ; p != NULL; p = p->next()) { oop s = p->literal(); 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; jchar* chars = java_lang_String::as_unicode_string(s, length); diff -r 924777755fad -r b099aaf51bf8 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Mar 22 13:36:33 2011 -0700 @@ -5930,14 +5930,18 @@ } { - TraceTime t("scrub symbol & string tables", PrintGCDetails, false, gclog_or_tty); - // Now clean up stale oops in StringTable - StringTable::unlink(&_is_alive_closure); + TraceTime t("scrub symbol table", PrintGCDetails, false, gclog_or_tty); // Clean up unreferenced symbols in symbol table. 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(); // Restore any preserved marks as a result of mark stack or // work queue overflow diff -r 924777755fad -r b099aaf51bf8 src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Tue Mar 22 13:36:33 2011 -0700 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/symbolTable.hpp" #include "gc_implementation/parallelScavenge/cardTableExtension.hpp" #include "gc_implementation/parallelScavenge/gcTaskManager.hpp" #include "gc_implementation/parallelScavenge/generationSizer.hpp" @@ -439,6 +440,14 @@ 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. PSPromotionManager::post_scavenge(); diff -r 924777755fad -r b099aaf51bf8 src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp Tue Mar 22 13:36:33 2011 -0700 @@ -86,4 +86,21 @@ } } +class PSScavengeRootsClosure: public OopClosure { + private: + PSPromotionManager* _promotion_manager; + + protected: + template 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 diff -r 924777755fad -r b099aaf51bf8 src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Tue Mar 22 13:36:33 2011 -0700 @@ -30,7 +30,7 @@ #include "gc_implementation/parallelScavenge/psMarkSweep.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.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 "memory/iterator.hpp" #include "memory/universe.hpp" @@ -46,24 +46,6 @@ // ScavengeRootsTask // -// Define before use -class PSScavengeRootsClosure: public OopClosure { - private: - PSPromotionManager* _promotion_manager; - - protected: - template 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) { assert(Universe::heap()->is_gc_active(), "called outside gc"); diff -r 924777755fad -r b099aaf51bf8 src/share/vm/memory/dump.cpp --- a/src/share/vm/memory/dump.cpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/memory/dump.cpp Tue Mar 22 13:36:33 2011 -0700 @@ -1561,6 +1561,7 @@ // thread because it requires object allocation. LinkClassesClosure lcc(Thread::current()); object_iterate(&lcc); + ensure_parsability(false); // arg is actually don't care tty->print_cr("done. "); // Create and dump the shared spaces. diff -r 924777755fad -r b099aaf51bf8 src/share/vm/memory/sharedHeap.cpp --- a/src/share/vm/memory/sharedHeap.cpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/memory/sharedHeap.cpp Tue Mar 22 13:36:33 2011 -0700 @@ -171,11 +171,13 @@ } if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) { - if (so & SO_Strings) { - StringTable::oops_do(roots); - } - // Verify if the string table contents are in the perm gen - NOT_PRODUCT(StringTable::oops_do(&assert_is_perm_closure)); + if (so & SO_Strings || (!collecting_perm_gen && !JavaObjectsInPerm)) { + StringTable::oops_do(roots); + } + if (JavaObjectsInPerm) { + // 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)) { diff -r 924777755fad -r b099aaf51bf8 src/share/vm/oops/constantPoolKlass.cpp --- a/src/share/vm/oops/constantPoolKlass.cpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/oops/constantPoolKlass.cpp Tue Mar 22 13:36:33 2011 -0700 @@ -285,10 +285,11 @@ void constantPoolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { assert(obj->is_constantPool(), "should be constant pool"); constantPoolOop cp = (constantPoolOop) obj; - if (AnonymousClasses && cp->has_pseudo_string() && cp->tags() != NULL) { - oop* base = (oop*)cp->base(); - for (int i = 0; i < cp->length(); ++i, ++base) { + if (cp->tags() != NULL && + (!JavaObjectsInPerm || (AnonymousClasses && cp->has_pseudo_string()))) { + for (int i = 1; i < cp->length(); ++i) { if (cp->tag_at(i).is_string()) { + oop* base = cp->obj_at_addr_raw(i); if (PSScavenge::should_scavenge(base)) { pm->claim_or_forward_depth(base); } @@ -460,7 +461,8 @@ if (cp->tag_at(i).is_string()) { if (!cp->has_pseudo_string()) { 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"); } } else { diff -r 924777755fad -r b099aaf51bf8 src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/opto/library_call.cpp Tue Mar 22 13:36:33 2011 -0700 @@ -1116,7 +1116,7 @@ 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* 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(); 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); diff -r 924777755fad -r b099aaf51bf8 src/share/vm/opto/memnode.cpp --- a/src/share/vm/opto/memnode.cpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/opto/memnode.cpp Tue Mar 22 13:36:33 2011 -0700 @@ -1573,9 +1573,9 @@ return TypeInt::make(constant.as_int()); } else if (constant.basic_type() == T_ARRAY) { 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 { - return TypeOopPtr::make_from_constant(constant.as_object()); + return TypeOopPtr::make_from_constant(constant.as_object(), true); } } } diff -r 924777755fad -r b099aaf51bf8 src/share/vm/opto/stringopts.cpp --- a/src/share/vm/opto/stringopts.cpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/opto/stringopts.cpp Tue Mar 22 13:36:33 2011 -0700 @@ -910,7 +910,7 @@ ciObject* con = field->constant_value().as_object(); // 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. - 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"); } else { type = TypeOopPtr::make_from_klass(field_klass->as_klass()); diff -r 924777755fad -r b099aaf51bf8 src/share/vm/opto/type.hpp --- a/src/share/vm/opto/type.hpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/opto/type.hpp Tue Mar 22 13:36:33 2011 -0700 @@ -988,8 +988,8 @@ static const TypeNarrowOop *make( const TypePtr* type); - static const TypeNarrowOop* make_from_constant(ciObject* con) { - return make(TypeOopPtr::make_from_constant(con)); + static const TypeNarrowOop* make_from_constant(ciObject* con, bool require_constant = false) { + return make(TypeOopPtr::make_from_constant(con, require_constant)); } // returns the equivalent ptr type for this compressed pointer diff -r 924777755fad -r b099aaf51bf8 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Mon Mar 21 18:38:00 2011 -0700 +++ b/src/share/vm/runtime/globals.hpp Tue Mar 22 13:36:33 2011 -0700 @@ -851,7 +851,7 @@ diagnostic(bool, TraceNMethodInstalls, false, \ "Trace nmethod intallation") \ \ - diagnostic(intx, ScavengeRootsInCode, 0, \ + diagnostic(intx, ScavengeRootsInCode, 1, \ "0: do not allow scavengable oops in the code cache; " \ "1: allow scavenging from the code cache; " \ "2: emit as many constants as the compiler can see") \