constantPoolKlass.cpp revision 1493
0N/A/*
579N/A * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
0N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0N/A * CA 95054 USA or visit www.sun.com if you need additional information or
0N/A * have any questions.
0N/A *
0N/A */
0N/A
0N/A# include "incls/_precompiled.incl"
0N/A# include "incls/_constantPoolKlass.cpp.incl"
0N/A
518N/AconstantPoolOop constantPoolKlass::allocate(int length, bool is_conc_safe, TRAPS) {
0N/A int size = constantPoolOopDesc::object_size(length);
0N/A KlassHandle klass (THREAD, as_klassOop());
0N/A constantPoolOop c =
113N/A (constantPoolOop)CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL);
0N/A
113N/A c->set_length(length);
0N/A c->set_tags(NULL);
0N/A c->set_cache(NULL);
0N/A c->set_pool_holder(NULL);
431N/A c->set_flags(0);
0N/A // only set to non-zero if constant pool is merged by RedefineClasses
0N/A c->set_orig_length(0);
518N/A // if constant pool may change during RedefineClasses, it is created
518N/A // unsafe for GC concurrent processing.
518N/A c->set_is_conc_safe(is_conc_safe);
0N/A // all fields are initialized; needed for GC
0N/A
0N/A // initialize tag array
0N/A // Note: cannot introduce constant pool handle before since it is not
0N/A // completely initialized (no class) -> would cause assertion failure
0N/A constantPoolHandle pool (THREAD, c);
0N/A typeArrayOop t_oop = oopFactory::new_permanent_byteArray(length, CHECK_NULL);
0N/A typeArrayHandle tags (THREAD, t_oop);
0N/A for (int index = 0; index < length; index++) {
0N/A tags()->byte_at_put(index, JVM_CONSTANT_Invalid);
0N/A }
0N/A pool->set_tags(tags());
0N/A
0N/A return pool();
0N/A}
0N/A
0N/AklassOop constantPoolKlass::create_klass(TRAPS) {
0N/A constantPoolKlass o;
113N/A KlassHandle h_this_klass(THREAD, Universe::klassKlassObj());
113N/A KlassHandle k = base_create_klass(h_this_klass, header_size(), o.vtbl_value(), CHECK_NULL);
113N/A // Make sure size calculation is right
113N/A assert(k()->size() == align_object_size(header_size()), "wrong size for object");
113N/A java_lang_Class::create_mirror(k, CHECK_NULL); // Allocate mirror
0N/A return k();
0N/A}
0N/A
0N/Aint constantPoolKlass::oop_size(oop obj) const {
0N/A assert(obj->is_constantPool(), "must be constantPool");
0N/A return constantPoolOop(obj)->object_size();
0N/A}
0N/A
0N/A
0N/Avoid constantPoolKlass::oop_follow_contents(oop obj) {
0N/A assert (obj->is_constantPool(), "obj must be constant pool");
0N/A constantPoolOop cp = (constantPoolOop) obj;
0N/A // Performance tweak: We skip iterating over the klass pointer since we
0N/A // know that Universe::constantPoolKlassObj never moves.
0N/A
0N/A // If the tags array is null we are in the middle of allocating this constant pool
0N/A if (cp->tags() != NULL) {
0N/A // gc of constant pool contents
0N/A oop* base = (oop*)cp->base();
0N/A for (int i = 0; i < cp->length(); i++) {
0N/A if (cp->is_pointer_entry(i)) {
0N/A if (*base != NULL) MarkSweep::mark_and_push(base);
0N/A }
0N/A base++;
0N/A }
0N/A // gc of constant pool instance variables
0N/A MarkSweep::mark_and_push(cp->tags_addr());
0N/A MarkSweep::mark_and_push(cp->cache_addr());
0N/A MarkSweep::mark_and_push(cp->pool_holder_addr());
0N/A }
0N/A}
0N/A
0N/A#ifndef SERIALGC
0N/Avoid constantPoolKlass::oop_follow_contents(ParCompactionManager* cm,
0N/A oop obj) {
0N/A assert (obj->is_constantPool(), "obj must be constant pool");
0N/A constantPoolOop cp = (constantPoolOop) obj;
0N/A // Performance tweak: We skip iterating over the klass pointer since we
0N/A // know that Universe::constantPoolKlassObj never moves.
0N/A
0N/A // If the tags array is null we are in the middle of allocating this constant
0N/A // pool.
0N/A if (cp->tags() != NULL) {
0N/A // gc of constant pool contents
0N/A oop* base = (oop*)cp->base();
0N/A for (int i = 0; i < cp->length(); i++) {
0N/A if (cp->is_pointer_entry(i)) {
0N/A if (*base != NULL) PSParallelCompact::mark_and_push(cm, base);
0N/A }
0N/A base++;
0N/A }
0N/A // gc of constant pool instance variables
0N/A PSParallelCompact::mark_and_push(cm, cp->tags_addr());
0N/A PSParallelCompact::mark_and_push(cm, cp->cache_addr());
0N/A PSParallelCompact::mark_and_push(cm, cp->pool_holder_addr());
0N/A }
0N/A}
0N/A#endif // SERIALGC
0N/A
0N/A
0N/Aint constantPoolKlass::oop_adjust_pointers(oop obj) {
0N/A assert (obj->is_constantPool(), "obj must be constant pool");
0N/A constantPoolOop cp = (constantPoolOop) obj;
0N/A // Get size before changing pointers.
0N/A // Don't call size() or oop_size() since that is a virtual call.
0N/A int size = cp->object_size();
0N/A // Performance tweak: We skip iterating over the klass pointer since we
0N/A // know that Universe::constantPoolKlassObj never moves.
0N/A
0N/A // If the tags array is null we are in the middle of allocating this constant
0N/A // pool.
0N/A if (cp->tags() != NULL) {
0N/A oop* base = (oop*)cp->base();
0N/A for (int i = 0; i< cp->length(); i++) {
0N/A if (cp->is_pointer_entry(i)) {
0N/A MarkSweep::adjust_pointer(base);
0N/A }
0N/A base++;
0N/A }
0N/A }
0N/A MarkSweep::adjust_pointer(cp->tags_addr());
0N/A MarkSweep::adjust_pointer(cp->cache_addr());
0N/A MarkSweep::adjust_pointer(cp->pool_holder_addr());
0N/A return size;
0N/A}
0N/A
0N/A
0N/Aint constantPoolKlass::oop_oop_iterate(oop obj, OopClosure* blk) {
0N/A assert (obj->is_constantPool(), "obj must be constant pool");
0N/A // Performance tweak: We skip iterating over the klass pointer since we
0N/A // know that Universe::constantPoolKlassObj never moves.
0N/A constantPoolOop cp = (constantPoolOop) obj;
0N/A // Get size before changing pointers.
0N/A // Don't call size() or oop_size() since that is a virtual call.
0N/A int size = cp->object_size();
0N/A
0N/A // If the tags array is null we are in the middle of allocating this constant
0N/A // pool.
0N/A if (cp->tags() != NULL) {
0N/A oop* base = (oop*)cp->base();
0N/A for (int i = 0; i < cp->length(); i++) {
0N/A if (cp->is_pointer_entry(i)) {
0N/A blk->do_oop(base);
0N/A }
0N/A base++;
0N/A }
0N/A }
0N/A blk->do_oop(cp->tags_addr());
0N/A blk->do_oop(cp->cache_addr());
0N/A blk->do_oop(cp->pool_holder_addr());
0N/A return size;
0N/A}
0N/A
0N/A
0N/Aint constantPoolKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) {
0N/A assert (obj->is_constantPool(), "obj must be constant pool");
0N/A // Performance tweak: We skip iterating over the klass pointer since we
0N/A // know that Universe::constantPoolKlassObj never moves.
0N/A constantPoolOop cp = (constantPoolOop) obj;
0N/A // Get size before changing pointers.
0N/A // Don't call size() or oop_size() since that is a virtual call.
0N/A int size = cp->object_size();
0N/A
0N/A // If the tags array is null we are in the middle of allocating this constant
0N/A // pool.
0N/A if (cp->tags() != NULL) {
0N/A oop* base = (oop*)cp->base();
0N/A for (int i = 0; i < cp->length(); i++) {
0N/A if (mr.contains(base)) {
0N/A if (cp->is_pointer_entry(i)) {
0N/A blk->do_oop(base);
0N/A }
0N/A }
0N/A base++;
0N/A }
0N/A }
0N/A oop* addr;
0N/A addr = cp->tags_addr();
0N/A blk->do_oop(addr);
0N/A addr = cp->cache_addr();
0N/A blk->do_oop(addr);
0N/A addr = cp->pool_holder_addr();
0N/A blk->do_oop(addr);
0N/A return size;
0N/A}
0N/A
518N/Abool constantPoolKlass::oop_is_conc_safe(oop obj) const {
518N/A assert(obj->is_constantPool(), "must be constantPool");
518N/A return constantPoolOop(obj)->is_conc_safe();
518N/A}
518N/A
0N/A#ifndef SERIALGC
0N/Aint constantPoolKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
0N/A assert (obj->is_constantPool(), "obj must be constant pool");
0N/A constantPoolOop cp = (constantPoolOop) obj;
0N/A
0N/A // If the tags array is null we are in the middle of allocating this constant
0N/A // pool.
0N/A if (cp->tags() != NULL) {
0N/A oop* base = (oop*)cp->base();
0N/A for (int i = 0; i < cp->length(); ++i, ++base) {
0N/A if (cp->is_pointer_entry(i)) {
0N/A PSParallelCompact::adjust_pointer(base);
0N/A }
0N/A }
0N/A }
0N/A PSParallelCompact::adjust_pointer(cp->tags_addr());
0N/A PSParallelCompact::adjust_pointer(cp->cache_addr());
0N/A PSParallelCompact::adjust_pointer(cp->pool_holder_addr());
0N/A return cp->object_size();
0N/A}
0N/A
0N/Aint
0N/AconstantPoolKlass::oop_update_pointers(ParCompactionManager* cm, oop obj,
0N/A HeapWord* beg_addr, HeapWord* end_addr) {
0N/A assert (obj->is_constantPool(), "obj must be constant pool");
0N/A constantPoolOop cp = (constantPoolOop) obj;
0N/A
0N/A // If the tags array is null we are in the middle of allocating this constant
0N/A // pool.
0N/A if (cp->tags() != NULL) {
0N/A oop* base = (oop*)cp->base();
0N/A oop* const beg_oop = MAX2((oop*)beg_addr, base);
0N/A oop* const end_oop = MIN2((oop*)end_addr, base + cp->length());
0N/A const size_t beg_idx = pointer_delta(beg_oop, base, sizeof(oop*));
0N/A const size_t end_idx = pointer_delta(end_oop, base, sizeof(oop*));
0N/A for (size_t cur_idx = beg_idx; cur_idx < end_idx; ++cur_idx, ++base) {
0N/A if (cp->is_pointer_entry(int(cur_idx))) {
0N/A PSParallelCompact::adjust_pointer(base);
0N/A }
0N/A }
0N/A }
0N/A
0N/A oop* p;
0N/A p = cp->tags_addr();
0N/A PSParallelCompact::adjust_pointer(p, beg_addr, end_addr);
0N/A p = cp->cache_addr();
0N/A PSParallelCompact::adjust_pointer(p, beg_addr, end_addr);
0N/A p = cp->pool_holder_addr();
0N/A PSParallelCompact::adjust_pointer(p, beg_addr, end_addr);
0N/A
0N/A return cp->object_size();
0N/A}
0N/A
0N/Avoid constantPoolKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
0N/A assert(obj->is_constantPool(), "should be constant pool");
431N/A constantPoolOop cp = (constantPoolOop) obj;
431N/A if (AnonymousClasses && cp->has_pseudo_string() && cp->tags() != NULL) {
431N/A oop* base = (oop*)cp->base();
431N/A for (int i = 0; i < cp->length(); ++i, ++base) {
431N/A if (cp->tag_at(i).is_string()) {
431N/A if (PSScavenge::should_scavenge(base)) {
431N/A pm->claim_or_forward_breadth(base);
431N/A }
431N/A }
431N/A }
431N/A }
0N/A}
0N/A
0N/Avoid constantPoolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
0N/A assert(obj->is_constantPool(), "should be constant pool");
431N/A constantPoolOop cp = (constantPoolOop) obj;
431N/A if (AnonymousClasses && cp->has_pseudo_string() && cp->tags() != NULL) {
431N/A oop* base = (oop*)cp->base();
431N/A for (int i = 0; i < cp->length(); ++i, ++base) {
431N/A if (cp->tag_at(i).is_string()) {
431N/A if (PSScavenge::should_scavenge(base)) {
431N/A pm->claim_or_forward_depth(base);
431N/A }
431N/A }
431N/A }
431N/A }
0N/A}
0N/A#endif // SERIALGC
0N/A
0N/A#ifndef PRODUCT
0N/A
0N/A// Printing
0N/A
0N/Avoid constantPoolKlass::oop_print_on(oop obj, outputStream* st) {
0N/A EXCEPTION_MARK;
0N/A oop anObj;
0N/A assert(obj->is_constantPool(), "must be constantPool");
113N/A Klass::oop_print_on(obj, st);
0N/A constantPoolOop cp = constantPoolOop(obj);
431N/A if (cp->flags() != 0) {
1493N/A st->print(" - flags: 0x%x", cp->flags());
431N/A if (cp->has_pseudo_string()) st->print(" has_pseudo_string");
726N/A if (cp->has_invokedynamic()) st->print(" has_invokedynamic");
431N/A st->cr();
431N/A }
1493N/A st->print_cr(" - cache: " INTPTR_FORMAT, cp->cache());
0N/A
0N/A for (int index = 1; index < cp->length(); index++) { // Index 0 is unused
0N/A st->print(" - %3d : ", index);
0N/A cp->tag_at(index).print_on(st);
0N/A st->print(" : ");
0N/A switch (cp->tag_at(index).value()) {
0N/A case JVM_CONSTANT_Class :
0N/A { anObj = cp->klass_at(index, CATCH);
0N/A anObj->print_value_on(st);
0N/A st->print(" {0x%lx}", (address)anObj);
0N/A }
0N/A break;
0N/A case JVM_CONSTANT_Fieldref :
0N/A case JVM_CONSTANT_Methodref :
0N/A case JVM_CONSTANT_InterfaceMethodref :
1493N/A st->print("klass_index=%d", cp->uncached_klass_ref_index_at(index));
1493N/A st->print(" name_and_type_index=%d", cp->uncached_name_and_type_ref_index_at(index));
0N/A break;
0N/A case JVM_CONSTANT_UnresolvedString :
0N/A case JVM_CONSTANT_String :
431N/A if (cp->is_pseudo_string_at(index)) {
431N/A anObj = cp->pseudo_string_at(index);
431N/A } else {
431N/A anObj = cp->string_at(index, CATCH);
431N/A }
0N/A anObj->print_value_on(st);
0N/A st->print(" {0x%lx}", (address)anObj);
0N/A break;
0N/A case JVM_CONSTANT_Integer :
0N/A st->print("%d", cp->int_at(index));
0N/A break;
0N/A case JVM_CONSTANT_Float :
0N/A st->print("%f", cp->float_at(index));
0N/A break;
0N/A case JVM_CONSTANT_Long :
0N/A st->print_jlong(cp->long_at(index));
0N/A index++; // Skip entry following eigth-byte constant
0N/A break;
0N/A case JVM_CONSTANT_Double :
0N/A st->print("%lf", cp->double_at(index));
0N/A index++; // Skip entry following eigth-byte constant
0N/A break;
0N/A case JVM_CONSTANT_NameAndType :
0N/A st->print("name_index=%d", cp->name_ref_index_at(index));
0N/A st->print(" signature_index=%d", cp->signature_ref_index_at(index));
0N/A break;
0N/A case JVM_CONSTANT_Utf8 :
0N/A cp->symbol_at(index)->print_value_on(st);
0N/A break;
0N/A case JVM_CONSTANT_UnresolvedClass : // fall-through
0N/A case JVM_CONSTANT_UnresolvedClassInError: {
0N/A // unresolved_klass_at requires lock or safe world.
0N/A oop entry = *cp->obj_at_addr(index);
0N/A entry->print_value_on(st);
0N/A }
0N/A break;
0N/A default:
0N/A ShouldNotReachHere();
0N/A break;
0N/A }
0N/A st->cr();
0N/A }
0N/A st->cr();
0N/A}
0N/A
1155N/A#endif
0N/A
1155N/Avoid constantPoolKlass::oop_print_value_on(oop obj, outputStream* st) {
1155N/A assert(obj->is_constantPool(), "must be constantPool");
1155N/A constantPoolOop cp = constantPoolOop(obj);
1155N/A st->print("constant pool [%d]", cp->length());
1155N/A if (cp->has_pseudo_string()) st->print("/pseudo_string");
1155N/A if (cp->has_invokedynamic()) st->print("/invokedynamic");
1155N/A cp->print_address_on(st);
1155N/A st->print(" for ");
1155N/A cp->pool_holder()->print_value_on(st);
1493N/A if (cp->cache() != NULL) {
1493N/A st->print(" cache=" PTR_FORMAT, cp->cache());
1493N/A }
1155N/A}
0N/A
0N/Aconst char* constantPoolKlass::internal_name() const {
0N/A return "{constant pool}";
0N/A}
0N/A
0N/A// Verification
0N/A
0N/Avoid constantPoolKlass::oop_verify_on(oop obj, outputStream* st) {
0N/A Klass::oop_verify_on(obj, st);
0N/A guarantee(obj->is_constantPool(), "object must be constant pool");
0N/A constantPoolOop cp = constantPoolOop(obj);
0N/A guarantee(cp->is_perm(), "should be in permspace");
0N/A if (!cp->partially_loaded()) {
0N/A oop* base = (oop*)cp->base();
0N/A for (int i = 0; i< cp->length(); i++) {
0N/A if (cp->tag_at(i).is_klass()) {
0N/A guarantee((*base)->is_perm(), "should be in permspace");
0N/A guarantee((*base)->is_klass(), "should be klass");
0N/A }
0N/A if (cp->tag_at(i).is_unresolved_klass()) {
0N/A guarantee((*base)->is_perm(), "should be in permspace");
0N/A guarantee((*base)->is_symbol() || (*base)->is_klass(),
0N/A "should be symbol or klass");
0N/A }
0N/A if (cp->tag_at(i).is_symbol()) {
0N/A guarantee((*base)->is_perm(), "should be in permspace");
0N/A guarantee((*base)->is_symbol(), "should be symbol");
0N/A }
0N/A if (cp->tag_at(i).is_unresolved_string()) {
0N/A guarantee((*base)->is_perm(), "should be in permspace");
0N/A guarantee((*base)->is_symbol() || (*base)->is_instance(),
0N/A "should be symbol or instance");
0N/A }
0N/A if (cp->tag_at(i).is_string()) {
431N/A if (!cp->has_pseudo_string()) {
431N/A guarantee((*base)->is_perm(), "should be in permspace");
431N/A guarantee((*base)->is_instance(), "should be instance");
431N/A } else {
431N/A // can be non-perm, can be non-instance (array)
431N/A }
0N/A }
0N/A base++;
0N/A }
0N/A guarantee(cp->tags()->is_perm(), "should be in permspace");
0N/A guarantee(cp->tags()->is_typeArray(), "should be type array");
0N/A if (cp->cache() != NULL) {
0N/A // Note: cache() can be NULL before a class is completely setup or
0N/A // in temporary constant pools used during constant pool merging
0N/A guarantee(cp->cache()->is_perm(), "should be in permspace");
0N/A guarantee(cp->cache()->is_constantPoolCache(), "should be constant pool cache");
0N/A }
0N/A if (cp->pool_holder() != NULL) {
0N/A // Note: pool_holder() can be NULL in temporary constant pools
0N/A // used during constant pool merging
0N/A guarantee(cp->pool_holder()->is_perm(), "should be in permspace");
0N/A guarantee(cp->pool_holder()->is_klass(), "should be klass");
0N/A }
0N/A }
0N/A}
0N/A
0N/Abool constantPoolKlass::oop_partially_loaded(oop obj) const {
0N/A assert(obj->is_constantPool(), "object must be constant pool");
0N/A constantPoolOop cp = constantPoolOop(obj);
0N/A return cp->tags() == NULL || cp->pool_holder() == (klassOop) cp; // Check whether pool holder points to self
0N/A}
0N/A
0N/A
0N/Avoid constantPoolKlass::oop_set_partially_loaded(oop obj) {
0N/A assert(obj->is_constantPool(), "object must be constant pool");
0N/A constantPoolOop cp = constantPoolOop(obj);
0N/A assert(cp->pool_holder() == NULL, "just checking");
0N/A cp->set_pool_holder((klassOop) cp); // Temporarily set pool holder to point to self
0N/A}
0N/A
0N/A#ifndef PRODUCT
0N/A// CompileTheWorld support. Preload all classes loaded references in the passed in constantpool
0N/Avoid constantPoolKlass::preload_and_initialize_all_classes(oop obj, TRAPS) {
0N/A guarantee(obj->is_constantPool(), "object must be constant pool");
0N/A constantPoolHandle cp(THREAD, (constantPoolOop)obj);
0N/A guarantee(!cp->partially_loaded(), "must be fully loaded");
0N/A
0N/A for (int i = 0; i< cp->length(); i++) {
0N/A if (cp->tag_at(i).is_unresolved_klass()) {
0N/A // This will force loading of the class
0N/A klassOop klass = cp->klass_at(i, CHECK);
0N/A if (klass->is_instance()) {
0N/A // Force initialization of class
0N/A instanceKlass::cast(klass)->initialize(CHECK);
0N/A }
0N/A }
0N/A }
0N/A}
0N/A
0N/A#endif