constantPoolOop.cpp revision 1472
0N/A/*
1472N/A * Copyright (c) 1997, 2009, Oracle and/or its affiliates. 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 *
1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1472N/A * or visit www.oracle.com if you need additional information or have any
1472N/A * questions.
0N/A *
0N/A */
0N/A
0N/A# include "incls/_precompiled.incl"
0N/A# include "incls/_constantPoolOop.cpp.incl"
0N/A
431N/Avoid constantPoolOopDesc::set_flag_at(FlagBit fb) {
431N/A const int MAX_STATE_CHANGES = 2;
431N/A for (int i = MAX_STATE_CHANGES + 10; i > 0; i--) {
431N/A int oflags = _flags;
431N/A int nflags = oflags | (1 << (int)fb);
431N/A if (Atomic::cmpxchg(nflags, &_flags, oflags) == oflags)
431N/A return;
431N/A }
431N/A assert(false, "failed to cmpxchg flags");
431N/A _flags |= (1 << (int)fb); // better than nothing
431N/A}
431N/A
0N/AklassOop constantPoolOopDesc::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
0N/A // A resolved constantPool entry will contain a klassOop, otherwise a symbolOop.
0N/A // It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
0N/A // tag is not updated atomicly.
0N/A oop entry = *(this_oop->obj_at_addr(which));
0N/A if (entry->is_klass()) {
0N/A // Already resolved - return entry.
0N/A return (klassOop)entry;
0N/A }
0N/A
0N/A // Acquire lock on constant oop while doing update. After we get the lock, we check if another object
0N/A // already has updated the object
0N/A assert(THREAD->is_Java_thread(), "must be a Java thread");
0N/A bool do_resolve = false;
0N/A bool in_error = false;
0N/A
0N/A symbolHandle name;
0N/A Handle loader;
0N/A { ObjectLocker ol(this_oop, THREAD);
0N/A
0N/A if (this_oop->tag_at(which).is_unresolved_klass()) {
0N/A if (this_oop->tag_at(which).is_unresolved_klass_in_error()) {
0N/A in_error = true;
0N/A } else {
0N/A do_resolve = true;
0N/A name = symbolHandle(THREAD, this_oop->unresolved_klass_at(which));
0N/A loader = Handle(THREAD, instanceKlass::cast(this_oop->pool_holder())->class_loader());
0N/A }
0N/A }
0N/A } // unlocking constantPool
0N/A
0N/A
0N/A // The original attempt to resolve this constant pool entry failed so find the
0N/A // original error and throw it again (JVMS 5.4.3).
0N/A if (in_error) {
0N/A symbolOop error = SystemDictionary::find_resolution_error(this_oop, which);
0N/A guarantee(error != (symbolOop)NULL, "tag mismatch with resolution error table");
0N/A ResourceMark rm;
0N/A // exception text will be the class name
0N/A const char* className = this_oop->unresolved_klass_at(which)->as_C_string();
0N/A THROW_MSG_0(error, className);
0N/A }
0N/A
0N/A if (do_resolve) {
0N/A // this_oop must be unlocked during resolve_or_fail
0N/A oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
0N/A Handle h_prot (THREAD, protection_domain);
0N/A klassOop k_oop = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD);
0N/A KlassHandle k;
0N/A if (!HAS_PENDING_EXCEPTION) {
0N/A k = KlassHandle(THREAD, k_oop);
0N/A // Do access check for klasses
0N/A verify_constant_pool_resolve(this_oop, k, THREAD);
0N/A }
0N/A
0N/A // Failed to resolve class. We must record the errors so that subsequent attempts
0N/A // to resolve this constant pool entry fail with the same error (JVMS 5.4.3).
0N/A if (HAS_PENDING_EXCEPTION) {
0N/A ResourceMark rm;
0N/A symbolHandle error(PENDING_EXCEPTION->klass()->klass_part()->name());
0N/A
0N/A bool throw_orig_error = false;
0N/A {
0N/A ObjectLocker ol (this_oop, THREAD);
0N/A
0N/A // some other thread has beaten us and has resolved the class.
0N/A if (this_oop->tag_at(which).is_klass()) {
0N/A CLEAR_PENDING_EXCEPTION;
0N/A entry = this_oop->resolved_klass_at(which);
0N/A return (klassOop)entry;
0N/A }
0N/A
0N/A if (!PENDING_EXCEPTION->
1142N/A is_a(SystemDictionary::LinkageError_klass())) {
0N/A // Just throw the exception and don't prevent these classes from
0N/A // being loaded due to virtual machine errors like StackOverflow
0N/A // and OutOfMemoryError, etc, or if the thread was hit by stop()
0N/A // Needs clarification to section 5.4.3 of the VM spec (see 6308271)
0N/A }
0N/A else if (!this_oop->tag_at(which).is_unresolved_klass_in_error()) {
0N/A SystemDictionary::add_resolution_error(this_oop, which, error);
0N/A this_oop->tag_at_put(which, JVM_CONSTANT_UnresolvedClassInError);
0N/A } else {
0N/A // some other thread has put the class in error state.
0N/A error = symbolHandle(SystemDictionary::find_resolution_error(this_oop, which));
0N/A assert(!error.is_null(), "checking");
0N/A throw_orig_error = true;
0N/A }
0N/A } // unlocked
0N/A
0N/A if (throw_orig_error) {
0N/A CLEAR_PENDING_EXCEPTION;
0N/A ResourceMark rm;
0N/A const char* className = this_oop->unresolved_klass_at(which)->as_C_string();
0N/A THROW_MSG_0(error, className);
0N/A }
0N/A
0N/A return 0;
0N/A }
0N/A
0N/A if (TraceClassResolution && !k()->klass_part()->oop_is_array()) {
0N/A // skip resolving the constant pool so that this code get's
0N/A // called the next time some bytecodes refer to this class.
0N/A ResourceMark rm;
0N/A int line_number = -1;
0N/A const char * source_file = NULL;
0N/A if (JavaThread::current()->has_last_Java_frame()) {
0N/A // try to identify the method which called this function.
0N/A vframeStream vfst(JavaThread::current());
0N/A if (!vfst.at_end()) {
0N/A line_number = vfst.method()->line_number_from_bci(vfst.bci());
0N/A symbolOop s = instanceKlass::cast(vfst.method()->method_holder())->source_file_name();
0N/A if (s != NULL) {
0N/A source_file = s->as_C_string();
0N/A }
0N/A }
0N/A }
0N/A if (k() != this_oop->pool_holder()) {
0N/A // only print something if the classes are different
0N/A if (source_file != NULL) {
0N/A tty->print("RESOLVE %s %s %s:%d\n",
0N/A instanceKlass::cast(this_oop->pool_holder())->external_name(),
0N/A instanceKlass::cast(k())->external_name(), source_file, line_number);
0N/A } else {
0N/A tty->print("RESOLVE %s %s\n",
0N/A instanceKlass::cast(this_oop->pool_holder())->external_name(),
0N/A instanceKlass::cast(k())->external_name());
0N/A }
0N/A }
0N/A return k();
0N/A } else {
0N/A ObjectLocker ol (this_oop, THREAD);
0N/A // Only updated constant pool - if it is resolved.
0N/A do_resolve = this_oop->tag_at(which).is_unresolved_klass();
0N/A if (do_resolve) {
0N/A this_oop->klass_at_put(which, k());
0N/A }
0N/A }
0N/A }
0N/A
0N/A entry = this_oop->resolved_klass_at(which);
0N/A assert(entry->is_klass(), "must be resolved at this point");
0N/A return (klassOop)entry;
0N/A}
0N/A
0N/A
0N/A// Does not update constantPoolOop - to avoid any exception throwing. Used
0N/A// by compiler and exception handling. Also used to avoid classloads for
0N/A// instanceof operations. Returns NULL if the class has not been loaded or
0N/A// if the verification of constant pool failed
0N/AklassOop constantPoolOopDesc::klass_at_if_loaded(constantPoolHandle this_oop, int which) {
0N/A oop entry = *this_oop->obj_at_addr(which);
0N/A if (entry->is_klass()) {
0N/A return (klassOop)entry;
0N/A } else {
0N/A assert(entry->is_symbol(), "must be either symbol or klass");
0N/A Thread *thread = Thread::current();
0N/A symbolHandle name (thread, (symbolOop)entry);
0N/A oop loader = instanceKlass::cast(this_oop->pool_holder())->class_loader();
0N/A oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
0N/A Handle h_prot (thread, protection_domain);
0N/A Handle h_loader (thread, loader);
0N/A klassOop k = SystemDictionary::find(name, h_loader, h_prot, thread);
0N/A
0N/A if (k != NULL) {
0N/A // Make sure that resolving is legal
0N/A EXCEPTION_MARK;
0N/A KlassHandle klass(THREAD, k);
0N/A // return NULL if verification fails
0N/A verify_constant_pool_resolve(this_oop, klass, THREAD);
0N/A if (HAS_PENDING_EXCEPTION) {
0N/A CLEAR_PENDING_EXCEPTION;
0N/A return NULL;
0N/A }
0N/A return klass();
0N/A } else {
0N/A return k;
0N/A }
0N/A }
0N/A}
0N/A
0N/A
0N/AklassOop constantPoolOopDesc::klass_ref_at_if_loaded(constantPoolHandle this_oop, int which) {
0N/A return klass_at_if_loaded(this_oop, this_oop->klass_ref_index_at(which));
0N/A}
0N/A
0N/A
0N/A// This is an interface for the compiler that allows accessing non-resolved entries
0N/A// in the constant pool - but still performs the validations tests. Must be used
0N/A// in a pre-parse of the compiler - to determine what it can do and not do.
0N/A// Note: We cannot update the ConstantPool from the vm_thread.
0N/AklassOop constantPoolOopDesc::klass_ref_at_if_loaded_check(constantPoolHandle this_oop, int index, TRAPS) {
0N/A int which = this_oop->klass_ref_index_at(index);
0N/A oop entry = *this_oop->obj_at_addr(which);
0N/A if (entry->is_klass()) {
0N/A return (klassOop)entry;
0N/A } else {
0N/A assert(entry->is_symbol(), "must be either symbol or klass");
0N/A symbolHandle name (THREAD, (symbolOop)entry);
0N/A oop loader = instanceKlass::cast(this_oop->pool_holder())->class_loader();
0N/A oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
0N/A Handle h_loader(THREAD, loader);
0N/A Handle h_prot (THREAD, protection_domain);
0N/A KlassHandle k(THREAD, SystemDictionary::find(name, h_loader, h_prot, THREAD));
0N/A
0N/A // Do access check for klasses
0N/A if( k.not_null() ) verify_constant_pool_resolve(this_oop, k, CHECK_NULL);
0N/A return k();
0N/A }
0N/A}
0N/A
0N/A
726N/AsymbolOop constantPoolOopDesc::impl_name_ref_at(int which, bool uncached) {
726N/A int name_index = name_ref_index_at(impl_name_and_type_ref_index_at(which, uncached));
0N/A return symbol_at(name_index);
0N/A}
0N/A
0N/A
726N/AsymbolOop constantPoolOopDesc::impl_signature_ref_at(int which, bool uncached) {
726N/A int signature_index = signature_ref_index_at(impl_name_and_type_ref_index_at(which, uncached));
0N/A return symbol_at(signature_index);
0N/A}
0N/A
0N/A
726N/Aint constantPoolOopDesc::impl_name_and_type_ref_index_at(int which, bool uncached) {
1059N/A int i = which;
1059N/A if (!uncached && cache() != NULL) {
1059N/A if (constantPoolCacheOopDesc::is_secondary_index(which))
1059N/A // Invokedynamic indexes are always processed in native order
1059N/A // so there is no question of reading a native u2 in Java order here.
1059N/A return cache()->main_entry_at(which)->constant_pool_index();
1059N/A // change byte-ordering and go via cache
1059N/A i = remap_instruction_operand_from_cache(which);
1059N/A } else {
1059N/A if (tag_at(which).is_name_and_type())
1059N/A // invokedynamic index is a simple name-and-type
1059N/A return which;
1059N/A }
1059N/A assert(tag_at(i).is_field_or_method(), "Corrupted constant pool");
1059N/A jint ref_index = *int_at_addr(i);
0N/A return extract_high_short_from_int(ref_index);
0N/A}
0N/A
0N/A
726N/Aint constantPoolOopDesc::impl_klass_ref_index_at(int which, bool uncached) {
1059N/A guarantee(!constantPoolCacheOopDesc::is_secondary_index(which),
1059N/A "an invokedynamic instruction does not have a klass");
1059N/A int i = which;
1059N/A if (!uncached && cache() != NULL) {
1059N/A // change byte-ordering and go via cache
1059N/A i = remap_instruction_operand_from_cache(which);
1059N/A }
1059N/A assert(tag_at(i).is_field_or_method(), "Corrupted constant pool");
1059N/A jint ref_index = *int_at_addr(i);
0N/A return extract_low_short_from_int(ref_index);
0N/A}
0N/A
0N/A
726N/A
1059N/Aint constantPoolOopDesc::remap_instruction_operand_from_cache(int operand) {
1059N/A // Operand was fetched by a stream using get_Java_u2, yet was stored
1059N/A // by Rewriter::rewrite_member_reference in native order.
1059N/A // So now we have to fix the damage by swapping back to native order.
726N/A assert((int)(u2)operand == operand, "clean u2");
1059N/A int cpc_index = Bytes::swap_u2(operand);
1059N/A int member_index = cache()->entry_at(cpc_index)->constant_pool_index();
1059N/A return member_index;
726N/A}
726N/A
726N/A
0N/Avoid constantPoolOopDesc::verify_constant_pool_resolve(constantPoolHandle this_oop, KlassHandle k, TRAPS) {
0N/A if (k->oop_is_instance() || k->oop_is_objArray()) {
0N/A instanceKlassHandle holder (THREAD, this_oop->pool_holder());
0N/A klassOop elem_oop = k->oop_is_instance() ? k() : objArrayKlass::cast(k())->bottom_klass();
0N/A KlassHandle element (THREAD, elem_oop);
0N/A
0N/A // The element type could be a typeArray - we only need the access check if it is
0N/A // an reference to another class
0N/A if (element->oop_is_instance()) {
0N/A LinkResolver::check_klass_accessability(holder, element, CHECK);
0N/A }
0N/A }
0N/A}
0N/A
0N/A
726N/Aint constantPoolOopDesc::name_ref_index_at(int which_nt) {
726N/A jint ref_index = name_and_type_at(which_nt);
0N/A return extract_low_short_from_int(ref_index);
0N/A}
0N/A
0N/A
726N/Aint constantPoolOopDesc::signature_ref_index_at(int which_nt) {
726N/A jint ref_index = name_and_type_at(which_nt);
0N/A return extract_high_short_from_int(ref_index);
0N/A}
0N/A
0N/A
0N/AklassOop constantPoolOopDesc::klass_ref_at(int which, TRAPS) {
0N/A return klass_at(klass_ref_index_at(which), CHECK_NULL);
0N/A}
0N/A
0N/A
0N/AsymbolOop constantPoolOopDesc::klass_name_at(int which) {
0N/A assert(tag_at(which).is_unresolved_klass() || tag_at(which).is_klass(),
0N/A "Corrupted constant pool");
0N/A // A resolved constantPool entry will contain a klassOop, otherwise a symbolOop.
0N/A // It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
0N/A // tag is not updated atomicly.
0N/A oop entry = *(obj_at_addr(which));
0N/A if (entry->is_klass()) {
0N/A // Already resolved - return entry's name.
0N/A return klassOop(entry)->klass_part()->name();
0N/A } else {
0N/A assert(entry->is_symbol(), "must be either symbol or klass");
0N/A return (symbolOop)entry;
0N/A }
0N/A}
0N/A
0N/AsymbolOop constantPoolOopDesc::klass_ref_at_noresolve(int which) {
0N/A jint ref_index = klass_ref_index_at(which);
0N/A return klass_at_noresolve(ref_index);
0N/A}
0N/A
0N/Achar* constantPoolOopDesc::string_at_noresolve(int which) {
0N/A // Test entry type in case string is resolved while in here.
0N/A oop entry = *(obj_at_addr(which));
0N/A if (entry->is_symbol()) {
0N/A return ((symbolOop)entry)->as_C_string();
431N/A } else if (java_lang_String::is_instance(entry)) {
431N/A return java_lang_String::as_utf8_string(entry);
0N/A } else {
431N/A return (char*)"<pseudo-string>";
0N/A }
0N/A}
0N/A
0N/A
0N/ABasicType constantPoolOopDesc::basic_type_for_signature_at(int which) {
0N/A return FieldType::basic_type(symbol_at(which));
0N/A}
0N/A
0N/A
0N/Avoid constantPoolOopDesc::resolve_string_constants_impl(constantPoolHandle this_oop, TRAPS) {
0N/A for (int index = 1; index < this_oop->length(); index++) { // Index 0 is unused
0N/A if (this_oop->tag_at(index).is_unresolved_string()) {
0N/A this_oop->string_at(index, CHECK);
0N/A }
0N/A }
0N/A}
0N/A
0N/Aoop constantPoolOopDesc::string_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
0N/A oop entry = *(this_oop->obj_at_addr(which));
0N/A if (entry->is_symbol()) {
0N/A ObjectLocker ol(this_oop, THREAD);
0N/A if (this_oop->tag_at(which).is_unresolved_string()) {
0N/A // Intern string
0N/A symbolOop sym = this_oop->unresolved_string_at(which);
0N/A entry = StringTable::intern(sym, CHECK_(constantPoolOop(NULL)));
0N/A this_oop->string_at_put(which, entry);
0N/A } else {
0N/A // Another thread beat us and interned string, read string from constant pool
0N/A entry = this_oop->resolved_string_at(which);
0N/A }
0N/A }
0N/A assert(java_lang_String::is_instance(entry), "must be string");
0N/A return entry;
0N/A}
0N/A
0N/A
431N/Abool constantPoolOopDesc::is_pseudo_string_at(int which) {
431N/A oop entry = *(obj_at_addr(which));
431N/A if (entry->is_symbol())
431N/A // Not yet resolved, but it will resolve to a string.
431N/A return false;
431N/A else if (java_lang_String::is_instance(entry))
431N/A return false; // actually, it might be a non-interned or non-perm string
431N/A else
431N/A // truly pseudo
431N/A return true;
431N/A}
431N/A
431N/A
0N/Abool constantPoolOopDesc::klass_name_at_matches(instanceKlassHandle k,
0N/A int which) {
0N/A // Names are interned, so we can compare symbolOops directly
0N/A symbolOop cp_name = klass_name_at(which);
0N/A return (cp_name == k->name());
0N/A}
0N/A
0N/A
0N/Aint constantPoolOopDesc::pre_resolve_shared_klasses(TRAPS) {
0N/A ResourceMark rm;
0N/A int count = 0;
0N/A for (int index = 1; index < tags()->length(); index++) { // Index 0 is unused
0N/A if (tag_at(index).is_unresolved_string()) {
0N/A // Intern string
0N/A symbolOop sym = unresolved_string_at(index);
0N/A oop entry = StringTable::intern(sym, CHECK_(-1));
0N/A string_at_put(index, entry);
0N/A }
0N/A }
0N/A return count;
0N/A}
0N/A
0N/A
0N/A// Iterate over symbols which are used as class, field, method names and
0N/A// signatures (in preparation for writing to the shared archive).
0N/A
0N/Avoid constantPoolOopDesc::shared_symbols_iterate(OopClosure* closure) {
0N/A for (int index = 1; index < length(); index++) { // Index 0 is unused
0N/A switch (tag_at(index).value()) {
0N/A
0N/A case JVM_CONSTANT_UnresolvedClass:
0N/A closure->do_oop(obj_at_addr(index));
0N/A break;
0N/A
0N/A case JVM_CONSTANT_NameAndType:
0N/A {
0N/A int i = *int_at_addr(index);
0N/A closure->do_oop(obj_at_addr((unsigned)i >> 16));
0N/A closure->do_oop(obj_at_addr((unsigned)i & 0xffff));
0N/A }
0N/A break;
0N/A
0N/A case JVM_CONSTANT_Class:
0N/A case JVM_CONSTANT_InterfaceMethodref:
0N/A case JVM_CONSTANT_Fieldref:
0N/A case JVM_CONSTANT_Methodref:
0N/A case JVM_CONSTANT_Integer:
0N/A case JVM_CONSTANT_Float:
0N/A // Do nothing! Not an oop.
0N/A // These constant types do not reference symbols at this point.
0N/A break;
0N/A
0N/A case JVM_CONSTANT_String:
0N/A // Do nothing! Not a symbol.
0N/A break;
0N/A
0N/A case JVM_CONSTANT_UnresolvedString:
0N/A case JVM_CONSTANT_Utf8:
0N/A // These constants are symbols, but unless these symbols are
0N/A // actually to be used for something, we don't want to mark them.
0N/A break;
0N/A
0N/A case JVM_CONSTANT_Long:
0N/A case JVM_CONSTANT_Double:
0N/A // Do nothing! Not an oop. (But takes two pool entries.)
0N/A ++index;
0N/A break;
0N/A
0N/A default:
0N/A ShouldNotReachHere();
0N/A break;
0N/A }
0N/A }
0N/A}
0N/A
0N/A
0N/A// Iterate over the [one] tags array (in preparation for writing to the
0N/A// shared archive).
0N/A
0N/Avoid constantPoolOopDesc::shared_tags_iterate(OopClosure* closure) {
0N/A closure->do_oop(tags_addr());
0N/A}
0N/A
0N/A
0N/A// Iterate over String objects (in preparation for writing to the shared
0N/A// archive).
0N/A
0N/Avoid constantPoolOopDesc::shared_strings_iterate(OopClosure* closure) {
0N/A for (int index = 1; index < length(); index++) { // Index 0 is unused
0N/A switch (tag_at(index).value()) {
0N/A
0N/A case JVM_CONSTANT_UnresolvedClass:
0N/A case JVM_CONSTANT_NameAndType:
0N/A // Do nothing! Not a String.
0N/A break;
0N/A
0N/A case JVM_CONSTANT_Class:
0N/A case JVM_CONSTANT_InterfaceMethodref:
0N/A case JVM_CONSTANT_Fieldref:
0N/A case JVM_CONSTANT_Methodref:
0N/A case JVM_CONSTANT_Integer:
0N/A case JVM_CONSTANT_Float:
0N/A // Do nothing! Not an oop.
0N/A // These constant types do not reference symbols at this point.
0N/A break;
0N/A
0N/A case JVM_CONSTANT_String:
0N/A closure->do_oop(obj_at_addr(index));
0N/A break;
0N/A
0N/A case JVM_CONSTANT_UnresolvedString:
0N/A case JVM_CONSTANT_Utf8:
0N/A // These constants are symbols, but unless these symbols are
0N/A // actually to be used for something, we don't want to mark them.
0N/A break;
0N/A
0N/A case JVM_CONSTANT_Long:
0N/A case JVM_CONSTANT_Double:
0N/A // Do nothing! Not an oop. (But takes two pool entries.)
0N/A ++index;
0N/A break;
0N/A
0N/A default:
0N/A ShouldNotReachHere();
0N/A break;
0N/A }
0N/A }
0N/A}
0N/A
0N/A
0N/A// Compare this constant pool's entry at index1 to the constant pool
0N/A// cp2's entry at index2.
0N/Abool constantPoolOopDesc::compare_entry_to(int index1, constantPoolHandle cp2,
0N/A int index2, TRAPS) {
0N/A
0N/A jbyte t1 = tag_at(index1).value();
0N/A jbyte t2 = cp2->tag_at(index2).value();
0N/A
0N/A
0N/A // JVM_CONSTANT_UnresolvedClassInError is equal to JVM_CONSTANT_UnresolvedClass
0N/A // when comparing
0N/A if (t1 == JVM_CONSTANT_UnresolvedClassInError) {
0N/A t1 = JVM_CONSTANT_UnresolvedClass;
0N/A }
0N/A if (t2 == JVM_CONSTANT_UnresolvedClassInError) {
0N/A t2 = JVM_CONSTANT_UnresolvedClass;
0N/A }
0N/A
0N/A if (t1 != t2) {
0N/A // Not the same entry type so there is nothing else to check. Note
0N/A // that this style of checking will consider resolved/unresolved
0N/A // class pairs and resolved/unresolved string pairs as different.
0N/A // From the constantPoolOop API point of view, this is correct
0N/A // behavior. See constantPoolKlass::merge() to see how this plays
0N/A // out in the context of constantPoolOop merging.
0N/A return false;
0N/A }
0N/A
0N/A switch (t1) {
0N/A case JVM_CONSTANT_Class:
0N/A {
0N/A klassOop k1 = klass_at(index1, CHECK_false);
0N/A klassOop k2 = cp2->klass_at(index2, CHECK_false);
0N/A if (k1 == k2) {
0N/A return true;
0N/A }
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_ClassIndex:
0N/A {
0N/A int recur1 = klass_index_at(index1);
0N/A int recur2 = cp2->klass_index_at(index2);
0N/A bool match = compare_entry_to(recur1, cp2, recur2, CHECK_false);
0N/A if (match) {
0N/A return true;
0N/A }
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Double:
0N/A {
0N/A jdouble d1 = double_at(index1);
0N/A jdouble d2 = cp2->double_at(index2);
0N/A if (d1 == d2) {
0N/A return true;
0N/A }
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Fieldref:
0N/A case JVM_CONSTANT_InterfaceMethodref:
0N/A case JVM_CONSTANT_Methodref:
0N/A {
0N/A int recur1 = uncached_klass_ref_index_at(index1);
0N/A int recur2 = cp2->uncached_klass_ref_index_at(index2);
0N/A bool match = compare_entry_to(recur1, cp2, recur2, CHECK_false);
0N/A if (match) {
0N/A recur1 = uncached_name_and_type_ref_index_at(index1);
0N/A recur2 = cp2->uncached_name_and_type_ref_index_at(index2);
0N/A match = compare_entry_to(recur1, cp2, recur2, CHECK_false);
0N/A if (match) {
0N/A return true;
0N/A }
0N/A }
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Float:
0N/A {
0N/A jfloat f1 = float_at(index1);
0N/A jfloat f2 = cp2->float_at(index2);
0N/A if (f1 == f2) {
0N/A return true;
0N/A }
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Integer:
0N/A {
0N/A jint i1 = int_at(index1);
0N/A jint i2 = cp2->int_at(index2);
0N/A if (i1 == i2) {
0N/A return true;
0N/A }
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Long:
0N/A {
0N/A jlong l1 = long_at(index1);
0N/A jlong l2 = cp2->long_at(index2);
0N/A if (l1 == l2) {
0N/A return true;
0N/A }
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_NameAndType:
0N/A {
0N/A int recur1 = name_ref_index_at(index1);
0N/A int recur2 = cp2->name_ref_index_at(index2);
0N/A bool match = compare_entry_to(recur1, cp2, recur2, CHECK_false);
0N/A if (match) {
0N/A recur1 = signature_ref_index_at(index1);
0N/A recur2 = cp2->signature_ref_index_at(index2);
0N/A match = compare_entry_to(recur1, cp2, recur2, CHECK_false);
0N/A if (match) {
0N/A return true;
0N/A }
0N/A }
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_String:
0N/A {
0N/A oop s1 = string_at(index1, CHECK_false);
0N/A oop s2 = cp2->string_at(index2, CHECK_false);
0N/A if (s1 == s2) {
0N/A return true;
0N/A }
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_StringIndex:
0N/A {
0N/A int recur1 = string_index_at(index1);
0N/A int recur2 = cp2->string_index_at(index2);
0N/A bool match = compare_entry_to(recur1, cp2, recur2, CHECK_false);
0N/A if (match) {
0N/A return true;
0N/A }
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_UnresolvedClass:
0N/A {
0N/A symbolOop k1 = unresolved_klass_at(index1);
0N/A symbolOop k2 = cp2->unresolved_klass_at(index2);
0N/A if (k1 == k2) {
0N/A return true;
0N/A }
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_UnresolvedString:
0N/A {
0N/A symbolOop s1 = unresolved_string_at(index1);
0N/A symbolOop s2 = cp2->unresolved_string_at(index2);
0N/A if (s1 == s2) {
0N/A return true;
0N/A }
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Utf8:
0N/A {
0N/A symbolOop s1 = symbol_at(index1);
0N/A symbolOop s2 = cp2->symbol_at(index2);
0N/A if (s1 == s2) {
0N/A return true;
0N/A }
0N/A } break;
0N/A
0N/A // Invalid is used as the tag for the second constant pool entry
0N/A // occupied by JVM_CONSTANT_Double or JVM_CONSTANT_Long. It should
0N/A // not be seen by itself.
0N/A case JVM_CONSTANT_Invalid: // fall through
0N/A
0N/A default:
0N/A ShouldNotReachHere();
0N/A break;
0N/A }
0N/A
0N/A return false;
0N/A} // end compare_entry_to()
0N/A
0N/A
0N/A// Copy this constant pool's entries at start_i to end_i (inclusive)
0N/A// to the constant pool to_cp's entries starting at to_i. A total of
0N/A// (end_i - start_i) + 1 entries are copied.
0N/Avoid constantPoolOopDesc::copy_cp_to(int start_i, int end_i,
0N/A constantPoolHandle to_cp, int to_i, TRAPS) {
0N/A
0N/A int dest_i = to_i; // leave original alone for debug purposes
0N/A
0N/A for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) {
0N/A copy_entry_to(src_i, to_cp, dest_i, CHECK);
0N/A
0N/A switch (tag_at(src_i).value()) {
0N/A case JVM_CONSTANT_Double:
0N/A case JVM_CONSTANT_Long:
0N/A // double and long take two constant pool entries
0N/A src_i += 2;
0N/A dest_i += 2;
0N/A break;
0N/A
0N/A default:
0N/A // all others take one constant pool entry
0N/A src_i++;
0N/A dest_i++;
0N/A break;
0N/A }
0N/A }
0N/A} // end copy_cp_to()
0N/A
0N/A
0N/A// Copy this constant pool's entry at from_i to the constant pool
0N/A// to_cp's entry at to_i.
0N/Avoid constantPoolOopDesc::copy_entry_to(int from_i, constantPoolHandle to_cp,
0N/A int to_i, TRAPS) {
0N/A
0N/A switch (tag_at(from_i).value()) {
0N/A case JVM_CONSTANT_Class:
0N/A {
0N/A klassOop k = klass_at(from_i, CHECK);
0N/A to_cp->klass_at_put(to_i, k);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_ClassIndex:
0N/A {
0N/A jint ki = klass_index_at(from_i);
0N/A to_cp->klass_index_at_put(to_i, ki);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Double:
0N/A {
0N/A jdouble d = double_at(from_i);
0N/A to_cp->double_at_put(to_i, d);
0N/A // double takes two constant pool entries so init second entry's tag
0N/A to_cp->tag_at_put(to_i + 1, JVM_CONSTANT_Invalid);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Fieldref:
0N/A {
0N/A int class_index = uncached_klass_ref_index_at(from_i);
0N/A int name_and_type_index = uncached_name_and_type_ref_index_at(from_i);
0N/A to_cp->field_at_put(to_i, class_index, name_and_type_index);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Float:
0N/A {
0N/A jfloat f = float_at(from_i);
0N/A to_cp->float_at_put(to_i, f);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Integer:
0N/A {
0N/A jint i = int_at(from_i);
0N/A to_cp->int_at_put(to_i, i);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_InterfaceMethodref:
0N/A {
0N/A int class_index = uncached_klass_ref_index_at(from_i);
0N/A int name_and_type_index = uncached_name_and_type_ref_index_at(from_i);
0N/A to_cp->interface_method_at_put(to_i, class_index, name_and_type_index);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Long:
0N/A {
0N/A jlong l = long_at(from_i);
0N/A to_cp->long_at_put(to_i, l);
0N/A // long takes two constant pool entries so init second entry's tag
0N/A to_cp->tag_at_put(to_i + 1, JVM_CONSTANT_Invalid);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Methodref:
0N/A {
0N/A int class_index = uncached_klass_ref_index_at(from_i);
0N/A int name_and_type_index = uncached_name_and_type_ref_index_at(from_i);
0N/A to_cp->method_at_put(to_i, class_index, name_and_type_index);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_NameAndType:
0N/A {
0N/A int name_ref_index = name_ref_index_at(from_i);
0N/A int signature_ref_index = signature_ref_index_at(from_i);
0N/A to_cp->name_and_type_at_put(to_i, name_ref_index, signature_ref_index);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_String:
0N/A {
0N/A oop s = string_at(from_i, CHECK);
0N/A to_cp->string_at_put(to_i, s);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_StringIndex:
0N/A {
0N/A jint si = string_index_at(from_i);
0N/A to_cp->string_index_at_put(to_i, si);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_UnresolvedClass:
0N/A {
0N/A symbolOop k = unresolved_klass_at(from_i);
0N/A to_cp->unresolved_klass_at_put(to_i, k);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_UnresolvedClassInError:
0N/A {
0N/A symbolOop k = unresolved_klass_at(from_i);
0N/A to_cp->unresolved_klass_at_put(to_i, k);
0N/A to_cp->tag_at_put(to_i, JVM_CONSTANT_UnresolvedClassInError);
0N/A } break;
0N/A
0N/A
0N/A case JVM_CONSTANT_UnresolvedString:
0N/A {
0N/A symbolOop s = unresolved_string_at(from_i);
0N/A to_cp->unresolved_string_at_put(to_i, s);
0N/A } break;
0N/A
0N/A case JVM_CONSTANT_Utf8:
0N/A {
0N/A symbolOop s = symbol_at(from_i);
0N/A to_cp->symbol_at_put(to_i, s);
0N/A } break;
0N/A
0N/A // Invalid is used as the tag for the second constant pool entry
0N/A // occupied by JVM_CONSTANT_Double or JVM_CONSTANT_Long. It should
0N/A // not be seen by itself.
0N/A case JVM_CONSTANT_Invalid: // fall through
0N/A
0N/A default:
0N/A {
0N/A jbyte bad_value = tag_at(from_i).value(); // leave a breadcrumb
0N/A ShouldNotReachHere();
0N/A } break;
0N/A }
0N/A} // end copy_entry_to()
0N/A
0N/A
0N/A// Search constant pool search_cp for an entry that matches this
0N/A// constant pool's entry at pattern_i. Returns the index of a
0N/A// matching entry or zero (0) if there is no matching entry.
0N/Aint constantPoolOopDesc::find_matching_entry(int pattern_i,
0N/A constantPoolHandle search_cp, TRAPS) {
0N/A
0N/A // index zero (0) is not used
0N/A for (int i = 1; i < search_cp->length(); i++) {
0N/A bool found = compare_entry_to(pattern_i, search_cp, i, CHECK_0);
0N/A if (found) {
0N/A return i;
0N/A }
0N/A }
0N/A
0N/A return 0; // entry not found; return unused index zero (0)
0N/A} // end find_matching_entry()
0N/A
0N/A
0N/A#ifndef PRODUCT
0N/A
0N/Aconst char* constantPoolOopDesc::printable_name_at(int which) {
0N/A
0N/A constantTag tag = tag_at(which);
0N/A
0N/A if (tag.is_unresolved_string() || tag.is_string()) {
0N/A return string_at_noresolve(which);
0N/A } else if (tag.is_klass() || tag.is_unresolved_klass()) {
0N/A return klass_name_at(which)->as_C_string();
0N/A } else if (tag.is_symbol()) {
0N/A return symbol_at(which)->as_C_string();
0N/A }
0N/A return "";
0N/A}
0N/A
0N/A#endif // PRODUCT
0N/A
0N/A
0N/A// JVMTI GetConstantPool support
0N/A
0N/A// For temporary use until code is stable.
0N/A#define DBG(code)
0N/A
0N/Astatic const char* WARN_MSG = "Must not be such entry!";
0N/A
0N/Astatic void print_cpool_bytes(jint cnt, u1 *bytes) {
0N/A jint size = 0;
0N/A u2 idx1, idx2;
0N/A
0N/A for (jint idx = 1; idx < cnt; idx++) {
0N/A jint ent_size = 0;
0N/A u1 tag = *bytes++;
0N/A size++; // count tag
0N/A
0N/A printf("const #%03d, tag: %02d ", idx, tag);
0N/A switch(tag) {
0N/A case JVM_CONSTANT_Invalid: {
0N/A printf("Invalid");
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Unicode: {
0N/A printf("Unicode %s", WARN_MSG);
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Utf8: {
0N/A u2 len = Bytes::get_Java_u2(bytes);
0N/A char str[128];
0N/A if (len > 127) {
0N/A len = 127;
0N/A }
0N/A strncpy(str, (char *) (bytes+2), len);
0N/A str[len] = '\0';
0N/A printf("Utf8 \"%s\"", str);
0N/A ent_size = 2 + len;
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Integer: {
0N/A u4 val = Bytes::get_Java_u4(bytes);
0N/A printf("int %d", *(int *) &val);
0N/A ent_size = 4;
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Float: {
0N/A u4 val = Bytes::get_Java_u4(bytes);
0N/A printf("float %5.3ff", *(float *) &val);
0N/A ent_size = 4;
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Long: {
0N/A u8 val = Bytes::get_Java_u8(bytes);
513N/A printf("long "INT64_FORMAT, *(jlong *) &val);
0N/A ent_size = 8;
0N/A idx++; // Long takes two cpool slots
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Double: {
0N/A u8 val = Bytes::get_Java_u8(bytes);
0N/A printf("double %5.3fd", *(jdouble *)&val);
0N/A ent_size = 8;
0N/A idx++; // Double takes two cpool slots
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Class: {
0N/A idx1 = Bytes::get_Java_u2(bytes);
0N/A printf("class #%03d", idx1);
0N/A ent_size = 2;
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_String: {
0N/A idx1 = Bytes::get_Java_u2(bytes);
0N/A printf("String #%03d", idx1);
0N/A ent_size = 2;
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Fieldref: {
0N/A idx1 = Bytes::get_Java_u2(bytes);
0N/A idx2 = Bytes::get_Java_u2(bytes+2);
0N/A printf("Field #%03d, #%03d", (int) idx1, (int) idx2);
0N/A ent_size = 4;
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Methodref: {
0N/A idx1 = Bytes::get_Java_u2(bytes);
0N/A idx2 = Bytes::get_Java_u2(bytes+2);
0N/A printf("Method #%03d, #%03d", idx1, idx2);
0N/A ent_size = 4;
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_InterfaceMethodref: {
0N/A idx1 = Bytes::get_Java_u2(bytes);
0N/A idx2 = Bytes::get_Java_u2(bytes+2);
0N/A printf("InterfMethod #%03d, #%03d", idx1, idx2);
0N/A ent_size = 4;
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_NameAndType: {
0N/A idx1 = Bytes::get_Java_u2(bytes);
0N/A idx2 = Bytes::get_Java_u2(bytes+2);
0N/A printf("NameAndType #%03d, #%03d", idx1, idx2);
0N/A ent_size = 4;
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_ClassIndex: {
0N/A printf("ClassIndex %s", WARN_MSG);
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_UnresolvedClass: {
0N/A printf("UnresolvedClass: %s", WARN_MSG);
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_UnresolvedClassInError: {
0N/A printf("UnresolvedClassInErr: %s", WARN_MSG);
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_StringIndex: {
0N/A printf("StringIndex: %s", WARN_MSG);
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_UnresolvedString: {
0N/A printf("UnresolvedString: %s", WARN_MSG);
0N/A break;
0N/A }
0N/A }
0N/A printf(";\n");
0N/A bytes += ent_size;
0N/A size += ent_size;
0N/A }
0N/A printf("Cpool size: %d\n", size);
0N/A fflush(0);
0N/A return;
0N/A} /* end print_cpool_bytes */
0N/A
0N/A
0N/A// Returns size of constant pool entry.
0N/Ajint constantPoolOopDesc::cpool_entry_size(jint idx) {
0N/A switch(tag_at(idx).value()) {
0N/A case JVM_CONSTANT_Invalid:
0N/A case JVM_CONSTANT_Unicode:
0N/A return 1;
0N/A
0N/A case JVM_CONSTANT_Utf8:
0N/A return 3 + symbol_at(idx)->utf8_length();
0N/A
0N/A case JVM_CONSTANT_Class:
0N/A case JVM_CONSTANT_String:
0N/A case JVM_CONSTANT_ClassIndex:
0N/A case JVM_CONSTANT_UnresolvedClass:
0N/A case JVM_CONSTANT_UnresolvedClassInError:
0N/A case JVM_CONSTANT_StringIndex:
0N/A case JVM_CONSTANT_UnresolvedString:
0N/A return 3;
0N/A
0N/A case JVM_CONSTANT_Integer:
0N/A case JVM_CONSTANT_Float:
0N/A case JVM_CONSTANT_Fieldref:
0N/A case JVM_CONSTANT_Methodref:
0N/A case JVM_CONSTANT_InterfaceMethodref:
0N/A case JVM_CONSTANT_NameAndType:
0N/A return 5;
0N/A
0N/A case JVM_CONSTANT_Long:
0N/A case JVM_CONSTANT_Double:
0N/A return 9;
0N/A }
0N/A assert(false, "cpool_entry_size: Invalid constant pool entry tag");
0N/A return 1;
0N/A} /* end cpool_entry_size */
0N/A
0N/A
0N/A// SymbolHashMap is used to find a constant pool index from a string.
0N/A// This function fills in SymbolHashMaps, one for utf8s and one for
0N/A// class names, returns size of the cpool raw bytes.
0N/Ajint constantPoolOopDesc::hash_entries_to(SymbolHashMap *symmap,
0N/A SymbolHashMap *classmap) {
0N/A jint size = 0;
0N/A
0N/A for (u2 idx = 1; idx < length(); idx++) {
0N/A u2 tag = tag_at(idx).value();
0N/A size += cpool_entry_size(idx);
0N/A
0N/A switch(tag) {
0N/A case JVM_CONSTANT_Utf8: {
0N/A symbolOop sym = symbol_at(idx);
0N/A symmap->add_entry(sym, idx);
0N/A DBG(printf("adding symbol entry %s = %d\n", sym->as_utf8(), idx));
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Class:
0N/A case JVM_CONSTANT_UnresolvedClass:
0N/A case JVM_CONSTANT_UnresolvedClassInError: {
0N/A symbolOop sym = klass_name_at(idx);
0N/A classmap->add_entry(sym, idx);
0N/A DBG(printf("adding class entry %s = %d\n", sym->as_utf8(), idx));
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Long:
0N/A case JVM_CONSTANT_Double: {
0N/A idx++; // Both Long and Double take two cpool slots
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A return size;
0N/A} /* end hash_utf8_entries_to */
0N/A
0N/A
0N/A// Copy cpool bytes.
0N/A// Returns:
0N/A// 0, in case of OutOfMemoryError
0N/A// -1, in case of internal error
0N/A// > 0, count of the raw cpool bytes that have been copied
0N/Aint constantPoolOopDesc::copy_cpool_bytes(int cpool_size,
0N/A SymbolHashMap* tbl,
0N/A unsigned char *bytes) {
0N/A u2 idx1, idx2;
0N/A jint size = 0;
0N/A jint cnt = length();
0N/A unsigned char *start_bytes = bytes;
0N/A
0N/A for (jint idx = 1; idx < cnt; idx++) {
0N/A u1 tag = tag_at(idx).value();
0N/A jint ent_size = cpool_entry_size(idx);
0N/A
0N/A assert(size + ent_size <= cpool_size, "Size mismatch");
0N/A
0N/A *bytes = tag;
0N/A DBG(printf("#%03hd tag=%03hd, ", idx, tag));
0N/A switch(tag) {
0N/A case JVM_CONSTANT_Invalid: {
0N/A DBG(printf("JVM_CONSTANT_Invalid"));
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Unicode: {
0N/A assert(false, "Wrong constant pool tag: JVM_CONSTANT_Unicode");
0N/A DBG(printf("JVM_CONSTANT_Unicode"));
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Utf8: {
0N/A symbolOop sym = symbol_at(idx);
0N/A char* str = sym->as_utf8();
0N/A // Warning! It's crashing on x86 with len = sym->utf8_length()
0N/A int len = (int) strlen(str);
0N/A Bytes::put_Java_u2((address) (bytes+1), (u2) len);
0N/A for (int i = 0; i < len; i++) {
0N/A bytes[3+i] = (u1) str[i];
0N/A }
0N/A DBG(printf("JVM_CONSTANT_Utf8: %s ", str));
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Integer: {
0N/A jint val = int_at(idx);
0N/A Bytes::put_Java_u4((address) (bytes+1), *(u4*)&val);
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Float: {
0N/A jfloat val = float_at(idx);
0N/A Bytes::put_Java_u4((address) (bytes+1), *(u4*)&val);
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Long: {
0N/A jlong val = long_at(idx);
0N/A Bytes::put_Java_u8((address) (bytes+1), *(u8*)&val);
0N/A idx++; // Long takes two cpool slots
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Double: {
0N/A jdouble val = double_at(idx);
0N/A Bytes::put_Java_u8((address) (bytes+1), *(u8*)&val);
0N/A idx++; // Double takes two cpool slots
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Class:
0N/A case JVM_CONSTANT_UnresolvedClass:
0N/A case JVM_CONSTANT_UnresolvedClassInError: {
0N/A *bytes = JVM_CONSTANT_Class;
0N/A symbolOop sym = klass_name_at(idx);
0N/A idx1 = tbl->symbol_to_value(sym);
0N/A assert(idx1 != 0, "Have not found a hashtable entry");
0N/A Bytes::put_Java_u2((address) (bytes+1), idx1);
0N/A DBG(printf("JVM_CONSTANT_Class: idx=#%03hd, %s", idx1, sym->as_utf8()));
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_String: {
0N/A unsigned int hash;
0N/A char *str = string_at_noresolve(idx);
0N/A symbolOop sym = SymbolTable::lookup_only(str, (int) strlen(str), hash);
773N/A if (sym == NULL) {
773N/A // sym can be NULL if string refers to incorrectly encoded JVM_CONSTANT_Utf8
773N/A // this can happen with JVM TI; see CR 6839599 for more details
773N/A oop string = *(obj_at_addr(idx));
773N/A assert(java_lang_String::is_instance(string),"Not a String");
773N/A DBG(printf("Error #%03hd tag=%03hd\n", idx, tag));
773N/A idx1 = 0;
773N/A for (int j = 0; j < tbl->table_size() && idx1 == 0; j++) {
773N/A for (SymbolHashMapEntry* cur = tbl->bucket(j); cur != NULL; cur = cur->next()) {
773N/A int length;
773N/A sym = cur->symbol();
773N/A jchar* chars = sym->as_unicode(length);
773N/A if (java_lang_String::equals(string, chars, length)) {
773N/A idx1 = cur->value();
773N/A DBG(printf("Index found: %d\n",idx1));
773N/A break;
773N/A }
773N/A }
773N/A }
773N/A } else {
773N/A idx1 = tbl->symbol_to_value(sym);
773N/A }
0N/A assert(idx1 != 0, "Have not found a hashtable entry");
0N/A Bytes::put_Java_u2((address) (bytes+1), idx1);
0N/A DBG(printf("JVM_CONSTANT_String: idx=#%03hd, %s", idx1, str));
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_UnresolvedString: {
0N/A *bytes = JVM_CONSTANT_String;
0N/A symbolOop sym = unresolved_string_at(idx);
0N/A idx1 = tbl->symbol_to_value(sym);
0N/A assert(idx1 != 0, "Have not found a hashtable entry");
0N/A Bytes::put_Java_u2((address) (bytes+1), idx1);
0N/A DBG(char *str = sym->as_utf8());
0N/A DBG(printf("JVM_CONSTANT_UnresolvedString: idx=#%03hd, %s", idx1, str));
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_Fieldref:
0N/A case JVM_CONSTANT_Methodref:
0N/A case JVM_CONSTANT_InterfaceMethodref: {
0N/A idx1 = uncached_klass_ref_index_at(idx);
0N/A idx2 = uncached_name_and_type_ref_index_at(idx);
0N/A Bytes::put_Java_u2((address) (bytes+1), idx1);
0N/A Bytes::put_Java_u2((address) (bytes+3), idx2);
0N/A DBG(printf("JVM_CONSTANT_Methodref: %hd %hd", idx1, idx2));
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_NameAndType: {
0N/A idx1 = name_ref_index_at(idx);
0N/A idx2 = signature_ref_index_at(idx);
0N/A Bytes::put_Java_u2((address) (bytes+1), idx1);
0N/A Bytes::put_Java_u2((address) (bytes+3), idx2);
0N/A DBG(printf("JVM_CONSTANT_NameAndType: %hd %hd", idx1, idx2));
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_ClassIndex: {
0N/A *bytes = JVM_CONSTANT_Class;
0N/A idx1 = klass_index_at(idx);
0N/A Bytes::put_Java_u2((address) (bytes+1), idx1);
0N/A DBG(printf("JVM_CONSTANT_ClassIndex: %hd", idx1));
0N/A break;
0N/A }
0N/A case JVM_CONSTANT_StringIndex: {
0N/A *bytes = JVM_CONSTANT_String;
0N/A idx1 = string_index_at(idx);
0N/A Bytes::put_Java_u2((address) (bytes+1), idx1);
0N/A DBG(printf("JVM_CONSTANT_StringIndex: %hd", idx1));
0N/A break;
0N/A }
0N/A }
0N/A DBG(printf("\n"));
0N/A bytes += ent_size;
0N/A size += ent_size;
0N/A }
0N/A assert(size == cpool_size, "Size mismatch");
0N/A
0N/A // Keep temorarily for debugging until it's stable.
0N/A DBG(print_cpool_bytes(cnt, start_bytes));
0N/A return (int)(bytes - start_bytes);
0N/A} /* end copy_cpool_bytes */
0N/A
0N/A
0N/Avoid SymbolHashMap::add_entry(symbolOop sym, u2 value) {
0N/A char *str = sym->as_utf8();
0N/A unsigned int hash = compute_hash(str, sym->utf8_length());
0N/A unsigned int index = hash % table_size();
0N/A
0N/A // check if already in map
0N/A // we prefer the first entry since it is more likely to be what was used in
0N/A // the class file
0N/A for (SymbolHashMapEntry *en = bucket(index); en != NULL; en = en->next()) {
0N/A assert(en->symbol() != NULL, "SymbolHashMapEntry symbol is NULL");
0N/A if (en->hash() == hash && en->symbol() == sym) {
0N/A return; // already there
0N/A }
0N/A }
0N/A
0N/A SymbolHashMapEntry* entry = new SymbolHashMapEntry(hash, sym, value);
0N/A entry->set_next(bucket(index));
0N/A _buckets[index].set_entry(entry);
0N/A assert(entry->symbol() != NULL, "SymbolHashMapEntry symbol is NULL");
0N/A}
0N/A
0N/ASymbolHashMapEntry* SymbolHashMap::find_entry(symbolOop sym) {
0N/A assert(sym != NULL, "SymbolHashMap::find_entry - symbol is NULL");
0N/A char *str = sym->as_utf8();
0N/A int len = sym->utf8_length();
0N/A unsigned int hash = SymbolHashMap::compute_hash(str, len);
0N/A unsigned int index = hash % table_size();
0N/A for (SymbolHashMapEntry *en = bucket(index); en != NULL; en = en->next()) {
0N/A assert(en->symbol() != NULL, "SymbolHashMapEntry symbol is NULL");
0N/A if (en->hash() == hash && en->symbol() == sym) {
0N/A return en;
0N/A }
0N/A }
0N/A return NULL;
0N/A}