constantPoolOop.cpp revision 773
/*
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
# include "incls/_precompiled.incl"
# include "incls/_constantPoolOop.cpp.incl"
const int MAX_STATE_CHANGES = 2;
for (int i = MAX_STATE_CHANGES + 10; i > 0; i--) {
return;
}
assert(false, "failed to cmpxchg flags");
}
// A resolved constantPool entry will contain a klassOop, otherwise a symbolOop.
// It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
// tag is not updated atomicly.
// Already resolved - return entry.
}
// Acquire lock on constant oop while doing update. After we get the lock, we check if another object
// already has updated the object
bool do_resolve = false;
bool in_error = false;
in_error = true;
} else {
do_resolve = true;
}
}
} // unlocking constantPool
// The original attempt to resolve this constant pool entry failed so find the
// original error and throw it again (JVMS 5.4.3).
if (in_error) {
// exception text will be the class name
}
if (do_resolve) {
// this_oop must be unlocked during resolve_or_fail
KlassHandle k;
if (!HAS_PENDING_EXCEPTION) {
// Do access check for klasses
}
// Failed to resolve class. We must record the errors so that subsequent attempts
// to resolve this constant pool entry fail with the same error (JVMS 5.4.3).
if (HAS_PENDING_EXCEPTION) {
bool throw_orig_error = false;
{
// some other thread has beaten us and has resolved the class.
}
if (!PENDING_EXCEPTION->
// Just throw the exception and don't prevent these classes from
// being loaded due to virtual machine errors like StackOverflow
// and OutOfMemoryError, etc, or if the thread was hit by stop()
// Needs clarification to section 5.4.3 of the VM spec (see 6308271)
}
} else {
// some other thread has put the class in error state.
throw_orig_error = true;
}
} // unlocked
if (throw_orig_error) {
}
return 0;
}
// skip resolving the constant pool so that this code get's
// called the next time some bytecodes refer to this class.
int line_number = -1;
const char * source_file = NULL;
// try to identify the method which called this function.
if (s != NULL) {
source_file = s->as_C_string();
}
}
}
if (k() != this_oop->pool_holder()) {
// only print something if the classes are different
if (source_file != NULL) {
} else {
}
}
return k();
} else {
// Only updated constant pool - if it is resolved.
if (do_resolve) {
}
}
}
}
// Does not update constantPoolOop - to avoid any exception throwing. Used
// by compiler and exception handling. Also used to avoid classloads for
// instanceof operations. Returns NULL if the class has not been loaded or
// if the verification of constant pool failed
} else {
if (k != NULL) {
// Make sure that resolving is legal
// return NULL if verification fails
if (HAS_PENDING_EXCEPTION) {
return NULL;
}
return klass();
} else {
return k;
}
}
}
}
// This is an interface for the compiler that allows accessing non-resolved entries
// in the constant pool - but still performs the validations tests. Must be used
// in a pre-parse of the compiler - to determine what it can do and not do.
// Note: We cannot update the ConstantPool from the vm_thread.
klassOop constantPoolOopDesc::klass_ref_at_if_loaded_check(constantPoolHandle this_oop, int index, TRAPS) {
} else {
// Do access check for klasses
return k();
}
}
return symbol_at(name_index);
}
return symbol_at(signature_index);
}
return extract_high_short_from_int(ref_index);
}
return extract_low_short_from_int(ref_index);
}
}
}
void constantPoolOopDesc::verify_constant_pool_resolve(constantPoolHandle this_oop, KlassHandle k, TRAPS) {
if (k->oop_is_instance() || k->oop_is_objArray()) {
// The element type could be a typeArray - we only need the access check if it is
// an reference to another class
if (element->oop_is_instance()) {
}
}
}
return extract_low_short_from_int(ref_index);
}
return extract_high_short_from_int(ref_index);
}
}
"Corrupted constant pool");
// A resolved constantPool entry will contain a klassOop, otherwise a symbolOop.
// It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
// tag is not updated atomicly.
// Already resolved - return entry's name.
} else {
}
}
return klass_at_noresolve(ref_index);
}
// Test entry type in case string is resolved while in here.
} else {
return (char*)"<pseudo-string>";
}
}
}
}
}
}
// Intern string
} else {
// Another thread beat us and interned string, read string from constant pool
}
}
return entry;
}
// Not yet resolved, but it will resolve to a string.
return false;
return false; // actually, it might be a non-interned or non-perm string
else
// truly pseudo
return true;
}
int which) {
// Names are interned, so we can compare symbolOops directly
}
int count = 0;
// Intern string
}
}
return count;
}
// Iterate over symbols which are used as class, field, method names and
// signatures (in preparation for writing to the shared archive).
break;
case JVM_CONSTANT_NameAndType:
{
int i = *int_at_addr(index);
}
break;
case JVM_CONSTANT_Class:
case JVM_CONSTANT_Fieldref:
case JVM_CONSTANT_Methodref:
case JVM_CONSTANT_Integer:
case JVM_CONSTANT_Float:
// Do nothing! Not an oop.
// These constant types do not reference symbols at this point.
break;
case JVM_CONSTANT_String:
// Do nothing! Not a symbol.
break;
case JVM_CONSTANT_Utf8:
// These constants are symbols, but unless these symbols are
// actually to be used for something, we don't want to mark them.
break;
case JVM_CONSTANT_Long:
case JVM_CONSTANT_Double:
// Do nothing! Not an oop. (But takes two pool entries.)
++index;
break;
default:
break;
}
}
}
// Iterate over the [one] tags array (in preparation for writing to the
// shared archive).
}
// Iterate over String objects (in preparation for writing to the shared
// archive).
case JVM_CONSTANT_NameAndType:
// Do nothing! Not a String.
break;
case JVM_CONSTANT_Class:
case JVM_CONSTANT_Fieldref:
case JVM_CONSTANT_Methodref:
case JVM_CONSTANT_Integer:
case JVM_CONSTANT_Float:
// Do nothing! Not an oop.
// These constant types do not reference symbols at this point.
break;
case JVM_CONSTANT_String:
break;
case JVM_CONSTANT_Utf8:
// These constants are symbols, but unless these symbols are
// actually to be used for something, we don't want to mark them.
break;
case JVM_CONSTANT_Long:
case JVM_CONSTANT_Double:
// Do nothing! Not an oop. (But takes two pool entries.)
++index;
break;
default:
break;
}
}
}
// Compare this constant pool's entry at index1 to the constant pool
// cp2's entry at index2.
// JVM_CONSTANT_UnresolvedClassInError is equal to JVM_CONSTANT_UnresolvedClass
// when comparing
if (t1 == JVM_CONSTANT_UnresolvedClassInError) {
}
if (t2 == JVM_CONSTANT_UnresolvedClassInError) {
}
// Not the same entry type so there is nothing else to check. Note
// that this style of checking will consider resolved/unresolved
// class pairs and resolved/unresolved string pairs as different.
// From the constantPoolOop API point of view, this is correct
// behavior. See constantPoolKlass::merge() to see how this plays
// out in the context of constantPoolOop merging.
return false;
}
switch (t1) {
case JVM_CONSTANT_Class:
{
return true;
}
} break;
case JVM_CONSTANT_ClassIndex:
{
if (match) {
return true;
}
} break;
case JVM_CONSTANT_Double:
{
return true;
}
} break;
case JVM_CONSTANT_Fieldref:
case JVM_CONSTANT_Methodref:
{
if (match) {
if (match) {
return true;
}
}
} break;
case JVM_CONSTANT_Float:
{
return true;
}
} break;
case JVM_CONSTANT_Integer:
{
return true;
}
} break;
case JVM_CONSTANT_Long:
{
return true;
}
} break;
case JVM_CONSTANT_NameAndType:
{
if (match) {
if (match) {
return true;
}
}
} break;
case JVM_CONSTANT_String:
{
return true;
}
} break;
case JVM_CONSTANT_StringIndex:
{
if (match) {
return true;
}
} break;
{
return true;
}
} break;
{
return true;
}
} break;
case JVM_CONSTANT_Utf8:
{
return true;
}
} break;
// Invalid is used as the tag for the second constant pool entry
// occupied by JVM_CONSTANT_Double or JVM_CONSTANT_Long. It should
// not be seen by itself.
case JVM_CONSTANT_Invalid: // fall through
default:
break;
}
return false;
} // end compare_entry_to()
// Copy this constant pool's entries at start_i to end_i (inclusive)
// to the constant pool to_cp's entries starting at to_i. A total of
// (end_i - start_i) + 1 entries are copied.
case JVM_CONSTANT_Double:
case JVM_CONSTANT_Long:
// double and long take two constant pool entries
src_i += 2;
dest_i += 2;
break;
default:
// all others take one constant pool entry
src_i++;
dest_i++;
break;
}
}
} // end copy_cp_to()
// Copy this constant pool's entry at from_i to the constant pool
// to_cp's entry at to_i.
case JVM_CONSTANT_Class:
{
} break;
case JVM_CONSTANT_ClassIndex:
{
} break;
case JVM_CONSTANT_Double:
{
// double takes two constant pool entries so init second entry's tag
} break;
case JVM_CONSTANT_Fieldref:
{
} break;
case JVM_CONSTANT_Float:
{
} break;
case JVM_CONSTANT_Integer:
{
} break;
{
} break;
case JVM_CONSTANT_Long:
{
// long takes two constant pool entries so init second entry's tag
} break;
case JVM_CONSTANT_Methodref:
{
} break;
case JVM_CONSTANT_NameAndType:
{
} break;
case JVM_CONSTANT_String:
{
} break;
case JVM_CONSTANT_StringIndex:
{
} break;
{
} break;
{
} break;
{
} break;
case JVM_CONSTANT_Utf8:
{
} break;
// Invalid is used as the tag for the second constant pool entry
// occupied by JVM_CONSTANT_Double or JVM_CONSTANT_Long. It should
// not be seen by itself.
case JVM_CONSTANT_Invalid: // fall through
default:
{
} break;
}
} // end copy_entry_to()
// Search constant pool search_cp for an entry that matches this
// constant pool's entry at pattern_i. Returns the index of a
// matching entry or zero (0) if there is no matching entry.
// index zero (0) is not used
if (found) {
return i;
}
}
return 0; // entry not found; return unused index zero (0)
} // end find_matching_entry()
#ifndef PRODUCT
return string_at_noresolve(which);
}
return "";
}
#endif // PRODUCT
// JVMTI GetConstantPool support
// For temporary use until code is stable.
static const char* WARN_MSG = "Must not be such entry!";
size++; // count tag
switch(tag) {
case JVM_CONSTANT_Invalid: {
printf("Invalid");
break;
}
case JVM_CONSTANT_Unicode: {
break;
}
case JVM_CONSTANT_Utf8: {
char str[128];
if (len > 127) {
len = 127;
}
break;
}
case JVM_CONSTANT_Integer: {
ent_size = 4;
break;
}
case JVM_CONSTANT_Float: {
ent_size = 4;
break;
}
case JVM_CONSTANT_Long: {
ent_size = 8;
idx++; // Long takes two cpool slots
break;
}
case JVM_CONSTANT_Double: {
ent_size = 8;
idx++; // Double takes two cpool slots
break;
}
case JVM_CONSTANT_Class: {
ent_size = 2;
break;
}
case JVM_CONSTANT_String: {
ent_size = 2;
break;
}
case JVM_CONSTANT_Fieldref: {
ent_size = 4;
break;
}
case JVM_CONSTANT_Methodref: {
ent_size = 4;
break;
}
case JVM_CONSTANT_InterfaceMethodref: {
ent_size = 4;
break;
}
case JVM_CONSTANT_NameAndType: {
ent_size = 4;
break;
}
case JVM_CONSTANT_ClassIndex: {
break;
}
case JVM_CONSTANT_UnresolvedClass: {
break;
}
break;
}
case JVM_CONSTANT_StringIndex: {
break;
}
case JVM_CONSTANT_UnresolvedString: {
break;
}
}
printf(";\n");
}
fflush(0);
return;
} /* end print_cpool_bytes */
// Returns size of constant pool entry.
case JVM_CONSTANT_Invalid:
case JVM_CONSTANT_Unicode:
return 1;
case JVM_CONSTANT_Utf8:
case JVM_CONSTANT_Class:
case JVM_CONSTANT_String:
case JVM_CONSTANT_ClassIndex:
case JVM_CONSTANT_StringIndex:
return 3;
case JVM_CONSTANT_Integer:
case JVM_CONSTANT_Float:
case JVM_CONSTANT_Fieldref:
case JVM_CONSTANT_Methodref:
case JVM_CONSTANT_NameAndType:
return 5;
case JVM_CONSTANT_Long:
case JVM_CONSTANT_Double:
return 9;
}
assert(false, "cpool_entry_size: Invalid constant pool entry tag");
return 1;
} /* end cpool_entry_size */
// SymbolHashMap is used to find a constant pool index from a string.
// This function fills in SymbolHashMaps, one for utf8s and one for
// class names, returns size of the cpool raw bytes.
switch(tag) {
case JVM_CONSTANT_Utf8: {
break;
}
case JVM_CONSTANT_Class:
break;
}
case JVM_CONSTANT_Long:
case JVM_CONSTANT_Double: {
idx++; // Both Long and Double take two cpool slots
break;
}
}
}
return size;
} /* end hash_utf8_entries_to */
// Copy cpool bytes.
// Returns:
// 0, in case of OutOfMemoryError
// -1, in case of internal error
// > 0, count of the raw cpool bytes that have been copied
unsigned char *bytes) {
unsigned char *start_bytes = bytes;
switch(tag) {
case JVM_CONSTANT_Invalid: {
break;
}
case JVM_CONSTANT_Unicode: {
assert(false, "Wrong constant pool tag: JVM_CONSTANT_Unicode");
break;
}
case JVM_CONSTANT_Utf8: {
// Warning! It's crashing on x86 with len = sym->utf8_length()
for (int i = 0; i < len; i++) {
}
break;
}
case JVM_CONSTANT_Integer: {
break;
}
case JVM_CONSTANT_Float: {
break;
}
case JVM_CONSTANT_Long: {
idx++; // Long takes two cpool slots
break;
}
case JVM_CONSTANT_Double: {
idx++; // Double takes two cpool slots
break;
}
case JVM_CONSTANT_Class:
break;
}
case JVM_CONSTANT_String: {
unsigned int hash;
// sym can be NULL if string refers to incorrectly encoded JVM_CONSTANT_Utf8
// this can happen with JVM TI; see CR 6839599 for more details
idx1 = 0;
int length;
break;
}
}
}
} else {
}
break;
}
case JVM_CONSTANT_UnresolvedString: {
break;
}
case JVM_CONSTANT_Fieldref:
case JVM_CONSTANT_Methodref:
case JVM_CONSTANT_InterfaceMethodref: {
break;
}
case JVM_CONSTANT_NameAndType: {
break;
}
case JVM_CONSTANT_ClassIndex: {
break;
}
case JVM_CONSTANT_StringIndex: {
break;
}
}
}
// Keep temorarily for debugging until it's stable.
return (int)(bytes - start_bytes);
} /* end copy_cpool_bytes */
// check if already in map
// we prefer the first entry since it is more likely to be what was used in
// the class file
return; // already there
}
}
}
return en;
}
}
return NULL;
}