6962931: move interned strings out of the perm gen
Reviewed-by: never, coleenp, ysr, jwilhelm
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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) {
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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);
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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();
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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 <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
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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 <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) {
assert(Universe::heap()->is_gc_active(), "called outside gc");
--- a/hotspot/src/share/vm/memory/dump.cpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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.
--- a/hotspot/src/share/vm/memory/sharedHeap.cpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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)) {
--- a/hotspot/src/share/vm/oops/constantPoolKlass.cpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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 {
--- a/hotspot/src/share/vm/opto/library_call.cpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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);
--- a/hotspot/src/share/vm/opto/memnode.cpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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);
}
}
}
--- a/hotspot/src/share/vm/opto/stringopts.cpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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());
--- a/hotspot/src/share/vm/opto/type.hpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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
--- a/hotspot/src/share/vm/runtime/globals.hpp Mon Mar 21 18:38:00 2011 -0700
+++ b/hotspot/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") \