diff --git a/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp b/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp index a2cc579..4583bb4 100644 --- a/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp +++ b/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp @@ -947,42 +947,42 @@ Opcode_LCMP(StackFrame& frame) { static bool ldc(StackFrame& frame, uint32 index) { - Class *clazz = frame.method->get_class(); - Const_Pool *cp = clazz->const_pool; + Class* clazz = frame.method->get_class(); + ConstantPool& cp = clazz->m_const_pool; #ifndef NDEBUG - switch(cp_tag(cp, index)) { + switch(cp.get_tag(index)) { case CONSTANT_String: - DEBUG_BYTECODE("#" << dec << (int)index << " String: \"" << cp[index].CONSTANT_String.string->bytes << "\""); + DEBUG_BYTECODE("#" << dec << (int)index << " String: \"" << cp.get_string_chars(index) << "\""); break; case CONSTANT_Integer: - DEBUG_BYTECODE("#" << dec << (int)index << " Integer: " << (int)cp[index].int_value); + DEBUG_BYTECODE("#" << dec << (int)index << " Integer: " << (int)cp.get_int(index)); break; case CONSTANT_Float: - DEBUG_BYTECODE("#" << dec << (int)index << " Float: " << cp[index].float_value); + DEBUG_BYTECODE("#" << dec << (int)index << " Float: " << cp.get_float(index)); break; case CONSTANT_Class: DEBUG_BYTECODE("#" << dec << (int)index << " Class: \"" << const_pool_get_class_name(clazz, index) << "\""); break; default: - DEBUG_BYTECODE("#" << dec << (int)index << " Unknown type = " << cp_tag(cp, index)); - DIE("ldc instruction: unexpected type (" << cp_tag(cp, index) + DEBUG_BYTECODE("#" << dec << (int)index << " Unknown type = " << cp.get_tag(index)); + DIE("ldc instruction: unexpected type (" << cp.get_tag(index) << ") of constant pool entry [" << index << "]"); break; } #endif frame.stack.push(); - if (cp_is_string(cp, index)) { - // FIXME: is string reference is packed?? + if(cp.is_string(index)) { + // FIXME: is string reference packed?? // possibly not - String* str = (String*) cp[index].CONSTANT_String.string; + String* str = cp.get_string(index); // FIXME: only compressed references frame.stack.pick().cr = COMPRESS_REF(vm_instantiate_cp_string_resolved(str)); frame.stack.ref() = FLAG_OBJECT; return !check_current_thread_exception(); } - else if (cp_is_class(cp, index)) + else if (cp.is_class(index)) { Class *other_class = interp_resolve_class(clazz, index); if (!other_class) { @@ -996,7 +996,7 @@ #endif return !exn_raised(); } - frame.stack.pick().u = cp[index].int_value; + frame.stack.pick().u = cp.get_4byte(index); return true; } @@ -1020,10 +1020,11 @@ Opcode_LDC2_W(StackFrame& frame) { uint32 index = read_uint16(frame.ip + 1); Class *clazz = frame.method->get_class(); - Const_Pool *cp = clazz->const_pool; + ConstantPool& cp = clazz->m_const_pool; frame.stack.push(2); Value2 val; - val.u64 = ((uint64)cp[index].CONSTANT_8byte.high_bytes << 32) | cp[index].CONSTANT_8byte.low_bytes; + val.u64 = ((uint64)cp.get_8byte_high_word(index) << 32) + | cp.get_8byte_low_word(index); frame.stack.setLong(0, val); DEBUG_BYTECODE("#" << dec << (int)index << " (val = " << hex << val.d << ")"); frame.ip += 3; diff --git a/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp b/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp index ebb2b24..746d3f6 100644 --- a/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp +++ b/enhanced/drlvm/trunk/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp @@ -31,6 +31,7 @@ #include "vm_stats.h" #include "open/types.h" #include "encoder.h" #include "interpreter.h" +#include "cci.h" #include "clog.h" diff --git a/enhanced/drlvm/trunk/vm/port/src/lil/pim/stack_iterator.cpp b/enhanced/drlvm/trunk/vm/port/src/lil/pim/stack_iterator.cpp index 6ef575b..92b39d6 100644 --- a/enhanced/drlvm/trunk/vm/port/src/lil/pim/stack_iterator.cpp +++ b/enhanced/drlvm/trunk/vm/port/src/lil/pim/stack_iterator.cpp @@ -24,6 +24,7 @@ #include "interpreter.h" #include "jit_intf_cpp.h" #include "m2n.h" #include "stack_iterator.h" +#include "cci.h" Method_Handle si_get_method(StackIterator* si) { diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/Class.h b/enhanced/drlvm/trunk/vm/vmcore/include/Class.h index b4c7a80..65fa2cd 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/Class.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/Class.h @@ -32,6 +32,7 @@ #include "open/vm_gc.h" #include "open/gc.h" #include "String_Pool.h" #include "type.h" +#include "vtable.h" // // forward declarations @@ -40,46 +41,23 @@ class Class_Member; struct Field; struct Method; struct Method_Signature; -class Package; typedef struct Class Class; -class JIT; -struct ClassLoader; -class ByteReader; struct Class_Extended_Notification_Record; -class DynoptInfo; -class Lock_Manager; -// // external declarations -// +class CodeChunkInfo; +class Lock_Manager; +class ByteReader; +struct ClassLoader; +class JIT; struct Global_Env; // defined in Environment.h - - - - -/////////////////////////////////////////////////////////////////////////////// -// Constant Java values -/////////////////////////////////////////////////////////////////////////////// -union Const_Java_Value { - uint32 i; - int64 j; - struct { - uint32 lo_bytes; - uint32 hi_bytes; - } l; - float f; - double d; - String *string; - void *object; - //Const_Java_Value() {l.lo_bytes=l.hi_bytes=0;} -}; - - +class Package; +struct AnnotationTable; /////////////////////////////////////////////////////////////////////////////// // Raw and compressed reference pointers /////////////////////////////////////////////////////////////////////////////// -#define RAW_REFERENCE ManagedObject * +#define RAW_REFERENCE ManagedObject* #define COMPRESSED_REFERENCE uint32 VMEXPORT bool is_compressed_reference(COMPRESSED_REFERENCE value); @@ -119,34 +97,6 @@ #define STORE_GLOBAL_REFERENCE(SLOT_ADDR } - -/////////////////////////////////////////////////////////////////////////////// -// class file attributes -/////////////////////////////////////////////////////////////////////////////// -enum Attributes { - ATTR_SourceFile, // Class (no more than 1 in each class file) - ATTR_InnerClasses, // Class - ATTR_ConstantValue, // Field (no more than 1 for each field) - ATTR_Code, // Method - ATTR_Exceptions, // Method - ATTR_LineNumberTable, // Code - ATTR_LocalVariableTable, // Code - ATTR_Synthetic, // Class/Field/Method - ATTR_Deprecated, // Class/Field/Method - ATTR_SourceDebugExtension, // Class (no more than 1 in each class file) - ATTR_Signature, // Class/Field/Method (spec does not limit number???) - ATTR_EnclosingMethod, // Class (1 at most) - ATTR_LocalVariableTypeTable, // Code - ATTR_RuntimeVisibleAnnotations, // Class/Field/Method (at most 1 per entity) - ATTR_RuntimeInvisibleAnnotations, // Class/Field/Method - ATTR_RuntimeVisibleParameterAnnotations, // Method - ATTR_RuntimeInvisibleParameterAnnotations, // Method - ATTR_AnnotationDefault, // Method (spec does not limit number???) - N_ATTR, - ATTR_UNDEF, - ATTR_ERROR -}; - #define N_COMMON_ATTR 5 #define N_FIELD_ATTR 1 #define N_METHOD_ATTR 5 @@ -167,28 +117,29 @@ #define CLASSFILE_MINOR 3 // Constant pool entries. /////////////////////////////////////////////////////////////////////////////// -union Const_Pool { - unsigned char *tags; // entry 0 of const pool only +union ConstPoolEntry { + unsigned char* tags; // entry 0 of const pool only struct { // CONSTANT_Class union { Class* klass; // resolved class struct { // resolution error - Const_Pool* next; // next resolution error in this constant pool + ConstPoolEntry* next; // next resolution error in this constant pool ManagedObject* cause; } error; }; uint16 name_index; } CONSTANT_Class; struct { // CONSTANT_String - String *string; // resolved entry + String* string; // resolved entry uint16 string_index; } CONSTANT_String; struct { // CONSTANT_{Field,Method,InterfaceMethod}ref union { + Class_Member* member; // generic class member for CONSTANT_*ref Field* field; // resolved entry for CONSTANT_Fieldref - Method* method; // resolved entry for CONSTANT_{Interface}Methodref + Method* method; // resolved entry for CONSTANT_[Interface]Methodref struct { // resolution error - Const_Pool* next; // next resolution error in this constant pool + ConstPoolEntry* next; // next resolution error in this constant pool ManagedObject* cause; } error; }; @@ -197,7 +148,7 @@ union Const_Pool { } CONSTANT_ref; struct { // shortcut to resolution error in CONSTANT_Class and CONSTANT_ref - Const_Pool* next; // next resolution error in this constant pool + ConstPoolEntry* next; // next resolution error in this constant pool ManagedObject* cause; } error; @@ -210,94 +161,17 @@ union Const_Pool { // Const_Pool element of the long/double unused) } CONSTANT_8byte; struct { // CONSTANT_NameAndType - String *name; // resolved entry - String *descriptor; // resolved entry + String* name; // resolved entry + String* descriptor; // resolved entry uint16 name_index; uint16 descriptor_index; } CONSTANT_NameAndType; struct { - String *string; // CONSTANT_Utf8 + String* string; // CONSTANT_Utf8 uint16 dummy; } CONSTANT_Utf8; }; -enum AnnotationValueType { - // 'B', 'C', 'D', 'F', 'I', 'J', 'S', and 'Z' 's' 'e' 'c' '@' '[' - AVT_BYTE = 'B', - AVT_CHAR = 'C', - AVT_DOUBLE = 'D', - AVT_FLOAT = 'F', - AVT_INT = 'I', - AVT_LONG = 'J', - AVT_SHORT = 'S', - AVT_BOOLEAN = 'Z', - AVT_STRING = 's', - AVT_ENUM = 'e', - AVT_CLASS = 'c', - AVT_ANNOTN = '@', - AVT_ARRAY = '[' -}; - -struct Annotation; // forward declaration - -// element-value pair of an annotation -struct AnnotationValue { - union { - Const_Java_Value const_value; - String* class_name; - Annotation * nested; - struct { - String* type; - String* name; - } enum_const; - struct { - AnnotationValue* items; - uint16 length; - } array; - }; - AnnotationValueType tag; -}; - -struct AnnotationElement { - String* name; - AnnotationValue value; -}; - -struct Annotation { - String* type; - AnnotationElement* elements; - uint16 num_elements; -}; - -struct AnnotationTable { - uint16 length; - Annotation * table[1]; -}; - -struct Line_Number_Entry { - uint16 start_pc; - uint16 line_number; -}; - -struct Line_Number_Table { - uint16 length; - Line_Number_Entry table[1]; -}; - -struct Local_Var_Entry { - uint16 start_pc; - uint16 length; - uint16 index; - String* name; - String* type; - String* generic_type; -}; - -struct Local_Var_Table { - uint16 length; - Local_Var_Entry table[1]; -}; - /////////////////////////////////////////////////////////////////////////////// // Types of constant pool entries. These are defined by a seperate byte array @@ -318,112 +192,439 @@ enum Const_Pool_Tags { CONSTANT_NameAndType = 12, }; + #define TAG_MASK 0x0F // 4 bits is sufficient for tag #define RESOLVED_MASK 0x80 // msb is resolved flag #define ERROR_MASK 0x40 // this entry contains resolution error information -#define cp_tag(cp,i) (cp[0].tags[i] & TAG_MASK) -#define cp_is_resolved(cp,i) (cp[0].tags[i] & RESOLVED_MASK) -#define cp_set_resolved(cp,i) (cp[0].tags[i] |= RESOLVED_MASK) - -#define cp_in_error(cp, i) (cp[0].tags[i] & ERROR_MASK) -#define cp_set_error(cp, i) (cp[0].tags[i] |= ERROR_MASK) - -#define cp_is_utf8(cp,i) (cp_tag(cp,i) == CONSTANT_Utf8) -#define cp_is_class(cp,i) (cp_tag(cp,i) == CONSTANT_Class) -#define cp_is_constant(cp,i) ((cp_tag(cp,i) >= CONSTANT_Integer \ - && cp_tag(cp,i) <= CONSTANT_Double) \ - || cp_tag(cp,i) == CONSTANT_String) - -#define cp_is_string(cp,i) (cp_tag(cp,i) == CONSTANT_String) -#define cp_is_fieldref(cp,i) (cp_tag(cp,i) == CONSTANT_Fieldref) -#define cp_is_methodref(cp,i) (cp_tag(cp,i) == CONSTANT_Methodref) -#define cp_is_interfacemethodref(cp,i) (cp_tag(cp,i) == CONSTANT_InterfaceMethodref) - -#define cp_resolve_to_class(cp,i,c) cp_set_resolved(cp,i); cp[i].CONSTANT_Class.klass=c; - -#define cp_resolve_to_field(cp,i,f) cp_set_resolved(cp,i); cp[i].CONSTANT_ref.field=f; - -#define cp_resolve_to_method(cp,i,m) cp_set_resolved(cp,i); cp[i].CONSTANT_ref.method=m; - -#define MAX_FAST_INSTOF_DEPTH 5 - -/////////////////////////////////////////////////////////////////////////////// -// virtual method table of a class -/////////////////////////////////////////////////////////////////////////////// -extern "C" { - -typedef struct { - unsigned char **table;// pointer into methods array of VTable below - unsigned intfc_id; // id of interface -} Intfc_Table_Entry; - -typedef struct Intfc_Table { -#ifdef POINTER64 - // see INTFC_TABLE_OVERHEAD - uint32 dummy; // padding -#endif - uint32 n_entries; - Intfc_Table_Entry entry[1]; -} Intfc_Table; - - -#define INTFC_TABLE_OVERHEAD (sizeof(void *)) - - -#ifdef POINTER64 -#define OBJECT_HEADER_SIZE 0 -// The size of an object reference. Used by arrays of object to determine -// the size of an element. -#define OBJECT_REF_SIZE 8 -#else // POINTER64 -#define OBJECT_HEADER_SIZE 0 -#define OBJECT_REF_SIZE 4 -#endif // POINTER64 - - -#define GC_BYTES_IN_VTABLE (sizeof(void *)) - -typedef struct VTable { - - Byte _gc_private_information[GC_BYTES_IN_VTABLE]; - - Class *clss; // the class - see above before change - // - // See the masks in vm_for_gc.h. - // - uint32 class_properties; +struct ConstantPool { +private: + // constant pool size + uint16 m_size; + // constant pool entries; 0-th entry contains array of constant pool tags + // for all entries + ConstPoolEntry* m_entries; + // List of constant pool entries, which resolution had failed + // Required for fast enumeration of error objects + ConstPoolEntry* m_failedResolution; - // Offset from the top by CLASS_ALLOCATED_SIZE_OFFSET - // The number of bytes allocated for this object. It is the same as - // instance_data_size with the constraint bit cleared. This includes - // the OBJECT_HEADER_SIZE as well as the OBJECT_VTABLE_POINTER_SIZE - unsigned int allocated_size; +public: + ConstantPool() : m_size(0), m_entries(NULL) {} + ~ConstantPool() { + clear(); + } - unsigned short array_element_size; - unsigned short array_element_shift; - Intfc_Table *intfc_table; // interface table; NULL if no intfc table -//#ifdef FAST_INSTOF - Class *superclasses[MAX_FAST_INSTOF_DEPTH]; //:: -//#endif - unsigned char *methods[1]; // code for method -} VTable; + /// Checks that constant pool is not empty + /// @return true if constant pool contain some entries, false otherwise + bool available() const { return m_size != 0; } + /// Returns size of this constant pool + /// @return size of constant pool + uint16 get_size() const { return m_size; } + + /// Checks that index is a valid index into this constant pool + /// @param index - index into constant pool + /// @return true if index is a valid index into constant pool, false + /// otherwise + bool is_valid_index(uint16 index) const { + return /*index > 0 && */index < m_size; + } + /// Checks that constant pool entry is resolved + /// @param index - index into constant pool + /// @return true if entry is already resolved, false otherwise + bool is_entry_resolved(uint16 index) const { + assert(is_valid_index(index)); + return (m_entries[0].tags[index] & RESOLVED_MASK) != 0; + } + /// Checks that the resolution of constant pool entry had failed + /// @param index - index into constant pool + /// @return true if resolution error is recorded for the entry + bool is_entry_in_error(uint16 index) const { + assert(is_valid_index(index)); + return (m_entries[0].tags[index] & ERROR_MASK) != 0; + } + /// Checks that the constant pool entry represents utf8 string + /// @param index - index into constant pool + /// @return true if this entry is utf8 string, false otherwise + bool is_utf8(uint16 index) const { + return get_tag(index) == CONSTANT_Utf8; + } + /// Checks that the constant pool entry refers to a class + /// @param index - index into constant pool + /// @return true if this entry is a class, false otherwise + bool is_class(uint16 index) const { + return get_tag(index) == CONSTANT_Class; + } + /// Checks that the constant pool entry contains constant + /// @param index - index into constant pool + /// @return true if this entry contains constant, false otherwise + bool is_constant(uint16 index) const { + return get_tag(index) == CONSTANT_Integer + || get_tag(index) == CONSTANT_Float + || get_tag(index) == CONSTANT_Long + || get_tag(index) == CONSTANT_Double + || get_tag(index) == CONSTANT_String + || get_tag(index) == CONSTANT_Class; + } + /// Checks that the constant pool entry is literal constant + /// @param index - index into constant pool + /// @return true if this entry contains string, false otherwise + bool is_string(uint16 index) const { + return get_tag(index) == CONSTANT_String; + } + bool is_name_and_type(uint16 index) const { + return get_tag(index) == CONSTANT_NameAndType; + } + /// Checks that the constant pool entry contains reference to a field + /// @param index - index into constant pool + /// @return true if this entry contains reference to field, false otherwise + bool is_fieldref(uint16 index) const { + return get_tag(index) == CONSTANT_Fieldref; + } + /// Checks that the constant pool entry contains reference to a method + /// @param index - index into constant pool + /// @return true if this entry contains reference to method, false otherwise + bool is_methodref(uint16 index) const { + return get_tag(index) == CONSTANT_Methodref; + } + /// Checks that the constant pool entry constains reference to an + /// interface method + /// @param index - index into constant pool + /// @return true if this entry contains reference to interface method, + /// false otherwise + bool is_interfacemethodref(uint16 index) const { + return get_tag(index) == CONSTANT_InterfaceMethodref; + } + /// Returns tag of referenced constant pool entry + /// @param index - index into constant pool + /// @return constant pool entry tag for a given index + unsigned char get_tag(uint16 index) const { + assert(is_valid_index(index)); + return m_entries[0].tags[index] & TAG_MASK; + } + /// Returns characters from utf8 string stored in constant pool + /// @param index - index into constant pool + /// @return characters from utf8 string stored in constant pool + const char* get_utf8_chars(uint16 index) const { + return get_utf8_string(index)->bytes; + } + /// Returns utf8 string stored in constant pool + /// @param index - index into constant pool + /// @return utf8 string + String* get_utf8_string(uint16 index) const { + assert(is_utf8(index)); + return m_entries[index].CONSTANT_Utf8.string; + } + /// Returns characters stored in utf8 string for CONSTANT_String entry + /// @param index - index into constant pool + /// @return utf8 string characters for this constant pool entry + const char* get_string_chars(uint16 index) const { + return get_string(index)->bytes; + } + /// Returns utf8 string stored for CONSTANT_String entry + /// @param index - index into constant pool + /// @return utf8 string stored in constant pool entry + String* get_string(uint16 index) const { + assert(is_string(index)); + return m_entries[index].CONSTANT_String.string; + } + /// Returns utf8 string representing name part of name and type + /// constant pool entry + /// @param index - index into constant pool + /// @return utf8 string with name part + String* get_name_and_type_name(uint16 index) const { + assert(is_name_and_type(index)); + assert(is_entry_resolved(index)); + return m_entries[index].CONSTANT_NameAndType.name; + } + /// Returns utf8 string representing descriptor part of name and type + /// constant pool entry + /// @param index - index into constant pool + /// @return utf8 string with descriptor part + String* get_name_and_type_descriptor(uint16 index) const { + assert(is_name_and_type(index)); + assert(is_entry_resolved(index)); + return m_entries[index].CONSTANT_NameAndType.descriptor; + } + /// Returns generic class member for CONSTANT_*ref constant pool entry + /// @param index - index into constant pool + /// @return generic class member for this constant pool entry + Class_Member* get_ref_class_member(uint16 index) const { + assert(is_fieldref(index) + || is_methodref(index) + || is_interfacemethodref(index)); + return m_entries[index].CONSTANT_ref.member; + } + /// Returns method from CONSTANT_Methodref or CONSTANT_InterfaceMethodref + /// constant pool entry + /// @param index - index into constant pool + /// @return method from this constant pool entry + Method* get_ref_method(uint16 index) const { + assert(is_methodref(index) + || is_interfacemethodref(index)); + assert(is_entry_resolved(index)); + return m_entries[index].CONSTANT_ref.method; + } + /// Returns field from CONSTANT_Fieldref constant pool entry + /// @param index - index into constant pool + /// @return field from this constant pool entry + Field* get_ref_field(uint16 index) const { + assert(is_fieldref(index)); + assert(is_entry_resolved(index)); + return m_entries[index].CONSTANT_ref.field; + } + /// Returns class for CONSTANT_Class constant pool entry + /// @param index - index into constant pool + /// @return class for this constant pool entry + Class* get_class_class(uint16 index) const { + assert(is_class(index)); + assert(is_entry_resolved(index)); + return m_entries[index].CONSTANT_Class.klass; + } + /// Returns integer value for constant stored in constant pool + /// @param index - index into constant pool + /// @return value of integer constant stored in constant pool + uint32 get_int(uint16 index) const { + assert(get_tag(index) == CONSTANT_Integer); + return m_entries[index].int_value; + } + /// Returns 32-bit value (either interger or float) + /// for constant stored in constant pool + /// @param index - index into constant pool + /// @return value of 32-bit constant stored in constant pool + uint32 get_4byte(uint16 index) const { + assert(get_tag(index) == CONSTANT_Integer + || get_tag(index) == CONSTANT_Float); + return m_entries[index].int_value; + } + /// Returns float value for constant stored in constant pool + /// @param index - index into constant pool + /// @return value of float constant stored in constant pool + float get_float(uint16 index) const { + assert(get_tag(index) == CONSTANT_Float); + return m_entries[index].float_value; + } + /// Returns low word of 64-bit constant (long or double) stored in constant pool + /// @param index - index into constant pool + /// @return value of low 32-bits of 64-bit constant + uint32 get_8byte_low_word(uint16 index) const { + assert(get_tag(index) == CONSTANT_Long + || get_tag(index) == CONSTANT_Double); + return m_entries[index].CONSTANT_8byte.low_bytes; + } + /// Returns high word of 64-bit constant (long or double) stored in constant pool + /// @param index - index into constant pool + /// @return value of high 32-bits of 64-bit constant + uint32 get_8byte_high_word(uint16 index) const { + assert(get_tag(index) == CONSTANT_Long + || get_tag(index) == CONSTANT_Double); + return m_entries[index].CONSTANT_8byte.high_bytes; + } + /// Returns address of constant stored in constant pool + /// @param index - index into constant pool + /// @return address of constant + void* get_address_of_constant(uint16 index) const { + assert(is_constant(index)); + assert(!is_string(index)); + return (void*)(m_entries + index); + } + /// Returns exception which has caused failure of + /// the referred constant pool entry + /// @param index - index into constant pool + /// @return exception object which is the cause of resolution failure + jthrowable get_error_cause(uint16 index) const { + assert(is_entry_in_error(index)); + return (jthrowable)(&(m_entries[index].error.cause)); + } + /// Returns head of single-linked list containing resolution errors + /// in this constant pool + /// @return head of signle-linked list of constant pool entries which + /// resolution had failed + ConstPoolEntry* get_error_chain() const { + return m_failedResolution; + } -#define VTABLE_OVERHEAD (sizeof(VTable) - sizeof(void *)) -// The "- sizeof(void *)" part subtracts out the "unsigned char *methods[1]" contribution. + /// Returns index in constant pool where utf8 representation + /// for CONSTANT_String is stored + /// @param index - index into constant pool for CONSTANT_String entry + /// @return index in constant pool with utf8 representation of this string + uint16 get_string_index(uint16 index) const { + assert(is_string(index)); + return m_entries[index].CONSTANT_String.string_index; + } + /// Returns index of constant pool entry containing utf8 string + /// with name part + /// @param index - index into constant pool + /// @return index in constant pool with utf8 string for name + uint16 get_name_and_type_name_index(uint16 index) const { + assert(is_name_and_type(index)); + return m_entries[index].CONSTANT_NameAndType.name_index; + } + /// Returns index of constant pool entry containing utf8 string + /// with descriptor part + /// @param index - index into constant pool + /// @return index in constant pool with utf8 string for descriptor + uint16 get_name_and_type_descriptor_index(uint16 index) const { + assert(is_name_and_type(index)); + return m_entries[index].CONSTANT_NameAndType.descriptor_index; + } + /// Returns index of constant pool entry containing class for + /// this CONSTANT_*ref entry + /// @param index - index into constant pool + /// @return index of class entry for this constant pool entry + uint16 get_ref_class_index(uint16 index) const { + assert(is_fieldref(index) + || is_methodref(index) + || is_interfacemethodref(index)); + return m_entries[index].CONSTANT_ref.class_index; + } + /// Returns index of CONSTANT_NameAndType for this constant pool entry + /// @param index - index into constant pool + /// @return index of CONSTANT_NameAndType for this constant pool entry + uint16 get_ref_name_and_type_index(uint16 index) const { + assert(is_fieldref(index) + || is_methodref(index) + || is_interfacemethodref(index)); + return m_entries[index].CONSTANT_ref.name_and_type_index; + } + /// Returns class name index in constant pool for CONSTANT_Class entry + /// @param index - index into constant pool + /// @return index of utf8 name of this class + uint16 get_class_name_index(uint16 index) const { + assert(is_class(index)); + return m_entries[index].CONSTANT_Class.name_index; + } -VTable *create_vtable(Class *p_class, unsigned n_vtable_entries); + /// Resolves entry to the class + /// @param index - index into constant pool + /// @param clss - class to resolve this entry to + void resolve_entry(uint16 index, Class* clss) { + // we do not want to resolve entry of different type + assert(is_class(index)); + set_entry_resolved(index); + m_entries[index].CONSTANT_Class.klass = clss; + } + /// Resolves entry to the field + /// @param index - index into constant pool + /// @param field - field to resolve this entry to + void resolve_entry(uint16 index, Field* field) { + // we do not want to resolve entry of different type + assert(is_fieldref(index)); + set_entry_resolved(index); + m_entries[index].CONSTANT_ref.field = field; + } + /// Resolves entry to the method + /// @param index - index into constant pool + /// @param method - method to resolve this entry to + void resolve_entry(uint16 index, Method* method) { + // we do not want to resolve entry of different type + assert(is_methodref(index) || is_interfacemethodref(index)); + set_entry_resolved(index); + m_entries[index].CONSTANT_ref.method = method; + } + /// Records resolution error into constant pool entry + /// @param index - index into constant pool + /// @param exn - cause of resolution failure + /// @note suspension must be disabled during this operation + void resolve_as_error(uint16 index, jthrowable exn) { + assert(is_class(index) + || is_fieldref(index) + || is_methodref(index) + || is_interfacemethodref(index)); + // 'if' clause is changed to 'assert' expression as this should never + // happen, i.e. class resolution should never try to resolve failing + // entry twice + // if(!cp.is_entry_in_error(cp_index)) { + assert(!is_entry_in_error(index)); + set_entry_error_state(index); + m_entries[index].error.cause = *((ManagedObject**)exn); + m_entries[index].error.next = m_failedResolution; + assert(&(m_entries[index]) != m_failedResolution); + m_failedResolution = &(m_entries[index]); + // } + } -} // extern "C" + /// Parses in constant pool for a class + /// @param clss - class, containing this constant pool + /// @param string_pool - reference to string pool to indern strings in + /// @param cfs - byte stream to parse constant pool from + /// @return true, if constant pool was parsed successfully, false, if + /// some error was discovered during parsing + bool parse(Class* clss, String_Pool& string_pool, ByteReader& cfs); + + /// Checks consistency of constant pool. Makes sure all indices to other + /// constant pool entries are in range. Makes sure contents of constant + /// pool entries are of the right type. Sets CONSTANT_Class entries + /// to point directly to String representing internal form of + /// fully qualified name of Class. Sets CONSTANT_String entries to point + /// directly to String representation of String. + /// Preresolves CONSTANT_NameAndType entries to signatures + /// @param clss - class this constant pool belongs to + /// @return true if constant pool of this class is valid, false otherwise + bool check(Class* clss); + + /// Clears content of constant pool: tags and entries arrays + void clear() { + if(m_size != 0) { + delete[] m_entries[0].tags; + delete[] m_entries; + } + init(); + } + /// Initializes constant pool to initial values + void init() { + m_size = 0; + m_entries = NULL; + m_failedResolution = NULL; + } +private: + /// Sets resolved flag in constant pool entry + /// @param index - index into constant pool + void set_entry_resolved(uint16 index) { + assert(is_valid_index(index)); + // we do not want to resolve one entry twice + assert(!is_entry_resolved(index)); + // we should not resolve failed entries + assert(!is_entry_in_error(index)); + m_entries[0].tags[index] |= RESOLVED_MASK; + } + /// Sets error flag in constant pool entry thus marking it failed + /// @param index - index into constant pool + void set_entry_error_state(uint16 index) { + assert(is_valid_index(index)); + // we do not want to reset resolved error + assert(!is_entry_resolved(index)); + // we do not want to reset reason of the failure + assert(!is_entry_in_error(index)); + m_entries[0].tags[index] |= ERROR_MASK; + } + /// Resolves CONSTANT_NameAndType constant pool entry to actual string values + /// @param index - index into constant pool + /// @param name - name-and-type name + /// @param descriptor - name-and-type type (descriptor) + void resolve_entry(uint16 index, String* name, String* descriptor) { + // we do not want to resolve entry of different type + assert(is_name_and_type(index)); + set_entry_resolved(index); + m_entries[index].CONSTANT_NameAndType.name = name; + m_entries[index].CONSTANT_NameAndType.descriptor = descriptor; + } + /// Resolves CONSTANT_String constant pool entry to actual string value + /// @param index - index into constant pool + /// @param str - actual string + void resolve_entry(uint16 index, String* str) { + assert(is_string(index)); + set_entry_resolved(index); + m_entries[index].CONSTANT_String.string = str; + } +}; /////////////////////////////////////////////////////////////////////////////// // A Java class /////////////////////////////////////////////////////////////////////////////// extern "C" { - // // state of this class // @@ -562,7 +763,6 @@ typedef struct Class { TypeDesc* array_element_type_desc; uint16 access_flags; - uint16 cp_size; uint16 n_superinterfaces; uint16 n_fields; uint16 n_static_fields; @@ -579,7 +779,7 @@ typedef struct Class { // empty string if anonymous String * simple_name; - Const_Pool *const_pool; // constant pool array; size is cp_size + ConstantPool m_const_pool; // constant pool array Field *fields; // array of fields; size is n_fields Method *methods; // array of methods; size is n_methods // @@ -749,10 +949,6 @@ #endif // class operations lock Lock_Manager* m_lock; - // List of constant pool entries, which resolution had failed - // Required for fast enumeration of error objects - Const_Pool* m_failedResolution; - // struct Class accessibility unsigned m_markBit:1; @@ -822,8 +1018,6 @@ VMEXPORT Class *class_resolve_class(Clas Boolean check_member_access(Class_Member *member, Class *other_clss); // Can "other_clss" access the "inner_clss" Boolean check_inner_class_access(Global_Env *env, Class *inner_clss, Class *other_clss); -// get class name from constant pool -extern String *cp_check_class(Const_Pool *cp, unsigned cp_size, unsigned class_index); // // parses in class description from a class file format @@ -882,808 +1076,8 @@ VMEXPORT void class_initialize(Class *cl void class_register_jit_extended_class_callback(Class *clss, JIT *jit_to_be_notified, void *callback_data); void do_jit_extended_class_callbacks(Class *clss, Class *new_subclass); -/////////////////////////////////////////////////////////////////////////////// -// A class' members are its fields and methods. Class_Member is the base -// class for Field and Method, and factors out the commonalities in these -// two classes. -/////////////////////////////////////////////////////////////////////////////// -// VMEXPORT // temporary solution for interpreter unplug -class VMEXPORT Class_Member { -public: - // - // access modifiers - // - bool is_public() {return (_access_flags&ACC_PUBLIC)?true:false;} - bool is_private() {return (_access_flags&ACC_PRIVATE)?true:false;} - bool is_protected() {return (_access_flags&ACC_PROTECTED)?true:false;} - bool is_package_private() {return !(is_public()||is_protected()||is_public())?true:false;} - bool is_static() {return (_access_flags&ACC_STATIC)?true:false;} - bool is_final() {return (_access_flags&ACC_FINAL)?true:false;} - bool is_strict() {return (_access_flags&ACC_STRICT)?true:false;} - bool is_synthetic() {return (_access_flags&ACC_SYNTHETIC)?true:_synthetic;} - bool is_deprecated() {return _deprecated;} - unsigned get_access_flags() {return _access_flags;} - - // - // field get/set methods - // - unsigned get_offset() const {return _offset;} - Class *get_class() const {return _class;} - String *get_name() const {return _name;} - - // Get the type descriptor (Sec. 4.3.2) - String *get_descriptor() const {return _descriptor;} - String *get_signature() const {return _signature;} - - AnnotationTable* get_declared_annotations() const {return _annotations;} - - friend void assign_instance_field_offset(Class *clss, Field *field, bool do_field_compaction); - friend void assign_offsets_to_static_fields(Class *clss, Field **field_ptrs, bool do_field_compaction); - friend void assign_offsets_to_class_fields(Class *); - friend void add_new_fake_method(Class *clss, Class *example, unsigned *next); - friend void add_any_fake_methods(Class *); - - /** - * Allocate a memory from a class loader pool using the class - * loader lock. - */ - void* Alloc(size_t size); - -protected: - Class_Member() - { - _access_flags = 0; - _class = NULL; - _offset = 0; -#ifdef VM_STATS - num_accesses = 0; - num_slow_accesses = 0; -#endif - _synthetic = _deprecated = false; - _annotations = NULL; - _signature = NULL; - } - - // offset of class member; - // for virtual methods, the method's offset within the vtable - // for static methods, the method's offset within the class' static method table - // for instance data, offset within the instance's data block - // for static data, offset within the class' static data block - unsigned _offset; - - bool _synthetic; - bool _deprecated; - AnnotationTable * _annotations; - - uint16 _access_flags; - String * _name; - String * _descriptor; - String * _signature; - Class * _class; - - bool parse(Class* clss, Const_Pool* cp, unsigned cp_size, ByteReader& cfs); - - /* - * returns ATTR_ERROR if attribute was recognized but parsing failed; - * returns ATTR_UNDEF if attribute was not recognized - * otherwise returns passed attr value - */ - Attributes process_common_attribute(Attributes attr, uint32 attr_len, ByteReader& cfs); - -public: -#ifdef VM_STATS - uint64 num_accesses; - uint64 num_slow_accesses; -#endif -}; // Class_Member - - - -/////////////////////////////////////////////////////////////////////////////// -// Fields within Class structures. -/////////////////////////////////////////////////////////////////////////////// -struct Field : public Class_Member{ -public: - //----------------------- - - // For all fields - bool is_offset_computed() { return (_offset_computed != 0); } - void set_offset_computed(bool is_computed) { _offset_computed = is_computed? 1 : 0; } - - // For static fields - VMEXPORT void* get_address(); - - // Return the type of this field. - Java_Type get_java_type() { - return (Java_Type)(get_descriptor()->bytes[0]); - }; - - Const_Java_Value get_const_value() { return const_value; }; - uint16 get_const_value_index() { return _const_value_index; }; - - //----------------------- - - Field() { - _const_value_index = 0; - _field_type_desc = 0; - _offset_computed = 0; - _is_injected = 0; - track_access = 0; - track_modification = 0; - } - - void Reset() { } - - void set(Class *cl, String* name, String* desc, unsigned short af) { - _class = cl; _access_flags = af; _name = name; _descriptor = desc; - } - Field& operator = (const Field& fd) { - // copy Class_Member fields - _access_flags = fd._access_flags; - _class = fd._class; - _offset = fd._offset; - _name = fd._name; - _descriptor = fd._descriptor; - _deprecated = fd._deprecated; - _synthetic = fd._synthetic; - _annotations = fd._annotations; - _signature = fd._signature; - - // copy Field fields - _const_value_index = fd._const_value_index; - _field_type_desc = fd._field_type_desc; - _is_injected = fd._is_injected; - _offset_computed = fd._offset_computed; - const_value = fd.const_value; - track_access = fd.track_access; - track_modification = fd.track_modification; - - return *this; - } - // - // access modifiers - // - unsigned is_volatile() {return (_access_flags&ACC_VOLATILE);} - unsigned is_transient() {return (_access_flags&ACC_TRANSIENT);} - bool is_enum() {return (_access_flags&ACC_ENUM)?true:false;} - - bool parse(Class* clss, Const_Pool* cp, unsigned cp_size, ByteReader& cfs); - - unsigned calculate_size() { - unsigned size = sizeof(Class_Member) + sizeof(Field); - size += sizeof(TypeDesc); - return size; - } - - TypeDesc* get_field_type_desc() { return _field_type_desc; } - void set_field_type_desc(TypeDesc* td) { _field_type_desc = td; } - - Boolean is_injected() {return _is_injected;} - void set_injected() { _is_injected = 1; } - - void set_track_access(bool value) { - track_access = value ? 1 : 0 ; - } - - void set_track_modification(bool value) { - track_modification = value ? 1 : 0 ; - } - - void get_track_access_flag(char** address, char* mask) { - *address = &track_access; - *mask = TRACK_ACCESS_MASK; - } - - void get_track_modification_flag(char** address, char* mask) { - *address = &track_modification; - *mask = TRACK_MODIFICATION_MASK; - } - -private: - // - // The initial values of static fields. This is defined by the - // ConstantValue attribute in the class file. - // - // If there was not ConstantValue attribute for that field then _const_value_index==0 - // - uint16 _const_value_index; - Const_Java_Value const_value; - TypeDesc* _field_type_desc; - unsigned _is_injected : 1; - unsigned _offset_computed : 1; - - /** Turns on sending FieldAccess events on access to this field */ - char track_access; - const static char TRACK_ACCESS_MASK = 1; - - /** Turns on sending FieldModification events on modification of this field */ - char track_modification; - const static char TRACK_MODIFICATION_MASK = 1; - - //union { - // char bit_flags; - // struct { - - // /** Turns on sending FieldAccess events on access to this field */ - // char track_access : 1; - // const static char TRACK_ACCESS_MASK = 4; - - // /** Turns on sending FieldModification events on modification of this field */ - // char track_modification : 1; - // const static char TRACK_MODIFICATION_MASK = 8; - // }; - //}; -}; // Field - - - -/////////////////////////////////////////////////////////////////////////////// -// Handler represents a catch block in a method's code array -/////////////////////////////////////////////////////////////////////////////// -class Handler { -public: - Handler(); - bool parse(Const_Pool *cp, unsigned cp_size, - unsigned code_length, ByteReader &cfs); - uint32 get_start_pc() {return _start_pc;} - uint32 get_end_pc() {return _end_pc;} - uint32 get_handler_pc() {return _handler_pc;} - uint32 get_catch_type_index() {return _catch_type_index;} - - -private: - uint32 _start_pc; - uint32 _end_pc; - uint32 _handler_pc; - uint32 _catch_type_index; // CP idx - String *_catch_type; - -}; //Handler - - - -// Representation of target handlers in the generated code. -class Target_Exception_Handler { -public: - Target_Exception_Handler(NativeCodePtr start_ip, NativeCodePtr end_ip, NativeCodePtr handler_ip, Class_Handle exn_class, bool exn_is_dead); - - NativeCodePtr get_start_ip(); - NativeCodePtr get_end_ip(); - NativeCodePtr get_handler_ip(); - Class_Handle get_exc(); - bool is_exc_obj_dead(); - - bool is_in_range(NativeCodePtr eip, bool is_ip_past); - bool is_assignable(Class_Handle exn_class); - - void update_catch_range(NativeCodePtr new_start_ip, NativeCodePtr new_end_ip); - void update_handler_address(NativeCodePtr new_handler_ip); - -private: - NativeCodePtr _start_ip; - NativeCodePtr _end_ip; - NativeCodePtr _handler_ip; - Class_Handle _exc; - bool _exc_obj_is_dead; -}; //Target_Exception_Handler - -typedef Target_Exception_Handler *Target_Exception_Handler_Ptr; - - -#define MAX_VTABLE_PATCH_ENTRIES 10 - -class VTable_Patches { -public: - void *patch_table[MAX_VTABLE_PATCH_ENTRIES]; - VTable_Patches *next; -}; - - - -///////////////////////////////////////////////////////////////// -// begin multiple-JIT support - int get_index_of_jit(JIT *jit); - -struct JIT_Data_Block { - JIT_Data_Block *next; - char bytes[1]; -}; - - -// Each callee for a given code chunk can have multiple Callee_Info structures, one for each call site in the caller. -typedef struct Callee_Info { - void *caller_ip; // the IP in the caller where the call was made - CodeChunkInfo *callee; // which code chunk was called - uint64 num_calls; -} Callee_Info; - - -#define NUM_STATIC_CALLEE_ENTRIES 8 - - -class CodeChunkInfo { - friend struct Method; -public: - CodeChunkInfo(); - - void set_jit(JIT *jit) { _jit = jit; } - JIT *get_jit() { return _jit; } - - void set_method(Method *m) { _method = m; } - Method *get_method() { return _method; } - - void set_id(int id) { _id = id; } - int get_id() { return _id; } - - void set_relocatable(Boolean r) { _relocatable = r; } - Boolean get_relocatable() { return _relocatable; } - - void set_heat(unsigned heat) { _heat = heat; } - unsigned get_heat() { return _heat; } - - void *get_code_block_addr() { return _code_block; } - void set_code_block_addr(void *addr) { _code_block = addr; } - - size_t get_code_block_size() { return _code_block_size; } - size_t get_code_block_alignment() { return _code_block_alignment; } - - void set_loaded_for_vtune(bool v) { _has_been_loaded_for_vtune = v; } - bool get_loaded_for_vtune() { return _has_been_loaded_for_vtune; } - - unsigned get_num_callees() { return _num_callees; } - Callee_Info *get_callees() { return _callee_info; } - - int get_jit_index() { return get_index_of_jit(_jit); } - - // Note: _data_blocks can only be used for inline info for now - Boolean has_inline_info() { return _data_blocks != NULL; } - void *get_inline_info() { return &_data_blocks->bytes[0]; } - - unsigned get_num_target_exception_handlers(); - Target_Exception_Handler_Ptr get_target_exception_handler_info(unsigned eh_num); - - void record_call_to_callee(CodeChunkInfo *callee, void *caller_return_ip); - uint64 num_calls_to(CodeChunkInfo *other_chunk); - - void print_name(); - void print_name(FILE *file); - void print_info(bool print_ellipses=false); // does not print callee information; see below - void print_callee_info(); // prints the callee information; usually called after print_info() - - static void initialize_code_chunk(CodeChunkInfo *chunk); - -public: - // The section id of the main code chunk for a method. Using an enum avoids a VC++ bug on Windows. - enum {main_code_chunk_id = 0}; - - // A predicate that returns true iff this is the main code chunk for a method: i.e, it 1) contains the method's entry point, - // and 2) contains the various flavors of JIT data for that method. - static bool is_main_code_chunk(CodeChunkInfo *chunk) { assert(chunk); return (chunk->get_id() == main_code_chunk_id); } - - // A predicate that returns true iff "id" is the section id of the main code chunk for a method. - static bool is_main_code_chunk_id(int id) { return (id == main_code_chunk_id); } - -private: - // The triple (_jit, _method, _id) uniquely identifies a CodeChunkInfo. - JIT *_jit; - Method *_method; - int _id; - bool _relocatable; - - // "Target" handlers. - unsigned _num_target_exception_handlers; - Target_Exception_Handler_Ptr *_target_exception_handlers; - - bool _has_been_loaded_for_vtune; - - // 20040224 This records information about the methods (actually, CodeChunkInfo's) called by this CodeChunkInfo. - // 20040405 This now records for each callee, the number of times it was called by each call IP in the caller. - // That is, this is a list of Callee_Info structures, each giving a call IP - Callee_Info *_callee_info; // points to an array of max_callees Callee_Info entries for this code chunk - unsigned _num_callees; - unsigned _max_callees; - Callee_Info _static_callee_info[NUM_STATIC_CALLEE_ENTRIES]; // Array used if a small number of callers to avoid mallocs & frees - -public: - unsigned _heat; - void *_code_block; - void *_jit_info_block; - size_t _code_block_size; - size_t _jit_info_block_size; - size_t _code_block_alignment; - JIT_Data_Block *_data_blocks; - DynoptInfo *_dynopt_info; - CodeChunkInfo *_next; - -#ifdef VM_STATS - uint64 num_throws; - uint64 num_catches; - uint64 num_unwind_java_frames_gc; - uint64 num_unwind_java_frames_non_gc; -#endif -}; //CodeChunkInfo - - -// end multiple-JIT support -///////////////////////////////////////////////////////////////// - - - -// Used to notify interested JITs whenever a method is changed: overwritten, recompiled, -// or initially compiled. -struct Method_Change_Notification_Record { - Method *method_of_interest; - JIT *jit; - void *callback_data; - Method_Change_Notification_Record *next; - - bool equals(Method *method_of_interest_, JIT *jit_, void *callback_data_) { - if ((method_of_interest == method_of_interest_) && - (jit == jit_) && - (callback_data == callback_data_)) { - return true; - } - return false; - } - // Optimized equals method. Most callbacks know method of interest, so we could skip one check. - inline bool equals(JIT *jit_, void *callback_data_) { - if ((callback_data == callback_data_) && - (jit == jit_)) { - return true; - } - return false; - } -}; - - -struct Inline_Record; - - -// 20020222 This is only temporary to support the new JIT interface. -// We will reimplement the signature support. -struct Method_Signature { -public: - TypeDesc* return_type_desc; - unsigned num_args; - TypeDesc** arg_type_descs; - Method *method; - String *sig; - - - void initialize_from_method(Method *method); - void reset(); - -private: - void initialize_from_java_method(Method *method); -}; - - - -/////////////////////////////////////////////////////////////////////////////// -// Methods defined in a class. -/////////////////////////////////////////////////////////////////////////////// - -// VMEXPORT // temporary solution for interpreter unplug -struct VMEXPORT Method : public Class_Member { - //----------------------- -public: - // - // state of this method - // - enum State { - ST_NotCompiled, // initial state - ST_NotLinked = ST_NotCompiled, // native not linked to implementation - ST_Compiled, // compiled by JIT - ST_Linked = ST_Compiled // native linked to implementation - }; - State get_state() {return _state;} - void set_state(State st) {_state=st;} - - // "Bytecode" exception handlers, i.e., those from the class file - unsigned num_bc_exception_handlers(); - Handler *get_bc_exception_handler_info(unsigned eh_number); - - // "Target" exception handlers, i.e., those in the code generated by the JIT. - void set_num_target_exception_handlers(JIT *jit, unsigned n); - unsigned get_num_target_exception_handlers(JIT *jit); - - // Arguments: - // ... - // catch_clss -- class of the exception or null (for "catch-all") - // ... - void set_target_exception_handler_info(JIT *jit, - unsigned eh_number, - void *start_ip, - void *end_ip, - void *handler_ip, - Class *catch_clss, - bool exc_obj_is_dead = false); - - Target_Exception_Handler_Ptr get_target_exception_handler_info(JIT *jit, unsigned eh_num); - - unsigned num_exceptions_method_can_throw(); - String *get_exception_name (int n); - - // Address of the memory block containing bytecodes. For best performance - // the bytecodes should not be destroyed even after the method has been - // jitted to allow re-compilation. However the interface allows for such - // deallocation. The effect would be that re-optimizing JITs would not - // show their full potential, but that may be acceptable for low-end systems - // where memory is at a premium. - // The value returned by getByteCodeAddr may be NULL in which case the - // bytecodes are not available (presumably they have been garbage collected by VM). - const Byte *get_byte_code_addr() {return _byte_codes;} - size_t get_byte_code_size() {return _byte_code_length;} - - // From the class file (Sec. 4.7.4) - unsigned get_max_stack() { return _max_stack; } - unsigned get_max_locals() { return _max_locals; } - - // Returns an iterator for the argument list. - Arg_List_Iterator get_argument_list(); - - // Returns number of bytes of arguments pushed on the stack. - // This value depends on the descriptor and the calling convention. - unsigned get_num_arg_bytes(); - - // Returns number of arguments. For non-static methods, the this pointer - // is included in this number - unsigned get_num_args(); - - // Number of arguments which are references. - unsigned get_num_ref_args(); - - - // Return the return type of this method. - Java_Type get_return_java_type(); - - // For non-primitive types (i.e., classes) get the class type information. - Class *get_return_class_type(); - - // Address of the memory location containing the address of the code. - // Used for static and special methods which have been resolved but not jitted. - // The call would be: - // call dword ptr [addr] - void *get_indirect_address() { return &_code; } - - // Entry address of the method. Points to an appropriate stub or directly - // to the code if no stub is necessary. - void *get_code_addr() { return _code; } - void set_code_addr(void *code_addr) { _code = code_addr; } - - void add_vtable_patch(void *); - void apply_vtable_patches(); - - /** - * This returns a block for jitted code. It is not used for native methods. - * It is safe to call this function from multiple threads. - */ - void *allocate_code_block_mt(size_t size, size_t alignment, JIT *jit, unsigned heat, - int id, Code_Allocation_Action action); - - void *allocate_rw_data_block(size_t size, size_t alignment, JIT *jit); - - // The JIT can store some information in a JavaMethod object. - void *allocate_jit_info_block(size_t size, JIT *jit); - - // JIT-specific data blocks. - // Access should be protected with _lock. - // FIXME - // Think about moving lock aquisition inside public methods. - void *allocate_JIT_data_block(size_t size, JIT *jit, size_t alignment); - CodeChunkInfo *get_first_JIT_specific_info() { return _jits; }; - CodeChunkInfo *get_JIT_specific_info_no_create(JIT *jit); - /** - * Find a chunk info for specific JIT. If no chunk exist for this JIT, - * create and return one. This method is safe to call - * from multiple threads. - */ - CodeChunkInfo *get_chunk_info_mt(JIT *jit, int id); - - /** - * Find a chunk info for specific JIT, or NULL if - * no chunk info is created for this JIT. This method is safe to call - * from multiple threads. - */ - CodeChunkInfo *get_chunk_info_no_create_mt(JIT *jit, int id); - - /** - * Allocate a new chunk info. This method is safe to call - * from multiple threads. - */ - CodeChunkInfo *create_code_chunk_info_mt(); - - // Notify JITs whenever this method is overridden by a newly loaded class. - void register_jit_overridden_method_callback(JIT *jit_to_be_notified, void *callback_data); - void do_jit_overridden_method_callbacks(Method *overriding_method); - - // Notify JITs whenever this method is recompiled or initially compiled. - void register_jit_recompiled_method_callback(JIT *jit_to_be_notified, void *callback_data); - void do_jit_recompiled_method_callbacks(); - - Method_Side_Effects get_side_effects() { return _side_effects; }; - void set_side_effects(Method_Side_Effects mse) { _side_effects = mse; }; - - Method_Signature *get_method_sig() { return _method_sig; }; - void set_method_sig(Method_Signature *msig) { _method_sig = msig; }; - -private: - State _state; - void *_code; - VTable_Patches *_vtable_patch; - - NativeCodePtr _counting_stub; - - CodeChunkInfo *_jits; - - Method_Side_Effects _side_effects; - Method_Signature *_method_sig; - -public: - Method(); - // destructor should be instead of this function, but it's not allowed to use it because copy for Method class is - // done with memcpy, and old value is destroyed with delete operator. - void MethodClearInternals(); - - // - // access modifiers - // - bool is_synchronized() {return (_access_flags&ACC_SYNCHRONIZED)?true:false;} - bool is_native() {return (_access_flags&ACC_NATIVE)?true:false;} - bool is_abstract() {return (_access_flags&ACC_ABSTRACT)?true:false;} - bool is_varargs() {return (_access_flags&ACC_VARARGS)?true:false;} - bool is_bridge() {return (_access_flags&ACC_BRIDGE)?true:false;} - - // method flags - bool is_init() {return _flags.is_init?true:false;} - bool is_clinit() {return _flags.is_clinit?true:false;} - bool is_finalize() {return _flags.is_finalize?true:false;} - bool is_overridden() {return _flags.is_overridden?true:false;} - bool is_registered() {return _flags.is_registered?true:false;} - Boolean is_nop() {return _flags.is_nop;} - - void set_registered( bool flag ) { _flags.is_registered = flag; } - - unsigned get_index() {return _index;} - - // Fake methods are interface methods inherited by an abstract class that are not (directly or indirectly) - // implemented by that class. They are added to the class to ensure they have thecorrect vtable offset. - // These fake methods point to the "real" interface method for which they are surrogates; this information - // is used by reflection methods. - bool is_fake_method() {return (_intf_method_for_fake_method != NULL);} - Method *get_real_intf_method() {return _intf_method_for_fake_method;} - - bool parse(Global_Env& env, Class* clss, - Const_Pool* cp, unsigned cp_size, ByteReader& cfs); - - unsigned calculate_size() { - unsigned size = sizeof(Class_Member) + sizeof(Method); - if(_local_vars_table) - size += sizeof(uint16) + _local_vars_table->length*sizeof(Local_Var_Entry); - if(_line_number_table) - size += sizeof(uint16) + _line_number_table->length*sizeof(Line_Number_Entry); - size += _n_exceptions*sizeof(String*); - size += _n_handlers*sizeof(Handler); - size += _byte_code_length; - return size; - } - - friend void assign_offsets_to_class_methods(Class* clss); - friend void add_new_fake_method(Class* clss, Class* example, unsigned* next); - friend void add_any_fake_methods(Class* clss); - - unsigned get_num_param_annotations() {return _num_param_annotations;} - AnnotationTable * get_param_annotations(unsigned index) { - return index < _num_param_annotations ? _param_annotations[index] : NULL; - } - AnnotationValue * get_default_value() {return _default_value; } - -private: - uint8 _num_param_annotations; - AnnotationTable ** _param_annotations; - AnnotationValue * _default_value; - - unsigned _index; // index in method table - uint16 _max_stack; - uint16 _max_locals; - uint16 _n_exceptions; // num exceptions method can throw - uint16 _n_handlers; // num exception handlers in byte codes - String **_exceptions; // array of exceptions method can throw - uint32 _byte_code_length; // num bytes of byte code - Byte *_byte_codes; // method's byte codes - Handler *_handlers; // array of exception handlers in code - Method *_intf_method_for_fake_method; - struct { - unsigned is_init : 1; - unsigned is_clinit : 1; - unsigned is_finalize : 1; // is finalize() method - unsigned is_overridden : 1; // has this virtual method been overridden by a loaded subclass? - unsigned is_nop : 1; - unsigned is_registered : 1; // the method is registred native method - } _flags; - - // - // private methods for parsing methods - // - bool _parse_code(Const_Pool *cp, unsigned cp_size, unsigned code_attr_len, ByteReader &cfs); - - bool _parse_line_numbers(unsigned attr_len, ByteReader &cfs); - - bool _parse_exceptions(Const_Pool *cp, unsigned cp_size, unsigned attr_len, - ByteReader &cfs); - - void _set_nop(); - - // - // debugging info - // - Line_Number_Table *_line_number_table; - Local_Var_Table *_local_vars_table; - - bool _parse_local_vars(const char* attr_name, Local_Var_Table** lvt_address, - Const_Pool *cp, unsigned cp_size, unsigned attr_len, ByteReader &cfs); - - // This is the number of breakpoints which should be set in the - // method when it is compiled. This number does not reflect - // multiple breakpoints that are set in the same location by - // different environments, it counts only unique locations - uint32 pending_breakpoints; -public: - - unsigned get_line_number_table_size() { - return (_line_number_table) ? _line_number_table->length : 0; - } - - bool get_line_number_entry(unsigned index, jlong* pc, jint* line); - - unsigned get_local_var_table_size() { - return (_local_vars_table) ? _local_vars_table->length : 0; - } - - bool get_local_var_entry(unsigned index, jlong* pc, - jint* length, jint* slot, String** name, String** type, - String** generic_type); - - // XXX - //bool get_local_var_entry(unsigned index, jlong* pc, - // jint* length, jint* slot, String** name, String** type); - - - // Returns number of line in the source file, to which the given bytecode offset - // corresponds, or -1 if it is unknown. - int get_line_number(uint16 bc_offset); - - Inline_Record *inline_records; - void set_inline_assumption(JIT *jit, Method *caller); - void method_was_overridden(); - - Method_Change_Notification_Record *_notify_override_records; - - // Records JITs to be notified when a method is recompiled or initially compiled. - Method_Change_Notification_Record *_notify_recompiled_records; - - void lock(); - void unlock(); - - uint32 get_pending_breakpoints() - { - return pending_breakpoints; - } - - void insert_pending_breakpoint() - { - pending_breakpoints++; - } - - void remove_pending_breakpoint() - { - pending_breakpoints--; - } -}; // Method - - VMEXPORT Class* load_class(Global_Env *env, const String *classname); Class* find_loaded_class(Global_Env *env, const String *classname); diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/annotation.h b/enhanced/drlvm/trunk/vm/vmcore/include/annotation.h new file mode 100644 index 0000000..50ae5a8 --- /dev/null +++ b/enhanced/drlvm/trunk/vm/vmcore/include/annotation.h @@ -0,0 +1,91 @@ +/* + * Copyright 2006 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __ANNOTATION_H__ +#define __ANNOTATION_H__ + +enum AnnotationValueType { + // 'B', 'C', 'D', 'F', 'I', 'J', 'S', and 'Z' 's' 'e' 'c' '@' '[' + AVT_BYTE = 'B', + AVT_CHAR = 'C', + AVT_DOUBLE = 'D', + AVT_FLOAT = 'F', + AVT_INT = 'I', + AVT_LONG = 'J', + AVT_SHORT = 'S', + AVT_BOOLEAN = 'Z', + AVT_STRING = 's', + AVT_ENUM = 'e', + AVT_CLASS = 'c', + AVT_ANNOTN = '@', + AVT_ARRAY = '[' +}; + +// forward declarations +struct Annotation; + +/////////////////////////////////////////////////////////////////////////////// +// Constant Java values +/////////////////////////////////////////////////////////////////////////////// +union Const_Java_Value { + uint32 i; + int64 j; + struct { + uint32 lo_bytes; + uint32 hi_bytes; + } l; + float f; + double d; + String *string; + void *object; +}; + + +// element-value pair of an annotation +struct AnnotationValue { + union { + Const_Java_Value const_value; + String* class_name; + Annotation* nested; + struct { + String* type; + String* name; + } enum_const; + struct { + AnnotationValue* items; + uint16 length; + } array; + }; + AnnotationValueType tag; +}; + +struct AnnotationElement { + String* name; + AnnotationValue value; +}; + +struct Annotation { + String* type; + AnnotationElement* elements; + uint16 num_elements; +}; + +struct AnnotationTable { + uint16 length; + Annotation* table[1]; +}; + +#endif + diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/cci.h b/enhanced/drlvm/trunk/vm/vmcore/include/cci.h new file mode 100644 index 0000000..68ae947 --- /dev/null +++ b/enhanced/drlvm/trunk/vm/vmcore/include/cci.h @@ -0,0 +1,152 @@ +/* + * Copyright 2006 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __CCI_H__ +#define __CCI_H__ + +// forward declarations +class CodeChunkInfo; + +// external declarations +class JIT; +typedef class Target_Exception_Handler* Target_Exception_Handler_Ptr; + +struct JIT_Data_Block { + JIT_Data_Block *next; + char bytes[1]; +}; + +// Each callee for a given code chunk can have multiple Callee_Info structures, +// one for each call site in the caller. +typedef struct Callee_Info { + void* caller_ip; // the IP in the caller where the call was made + CodeChunkInfo* callee; // which code chunk was called + uint64 num_calls; // number of calls to that chunk +} Callee_Info; + +#define NUM_STATIC_CALLEE_ENTRIES 8 + +class CodeChunkInfo { + friend struct Method; +public: + CodeChunkInfo(); + + void set_jit(JIT* jit) { _jit = jit; } + JIT* get_jit() const { return _jit; } + + void set_method(Method* m) { _method = m; } + Method* get_method() const { return _method; } + + void set_id(int id) { _id = id; } + int get_id() const { return _id; } + + void set_relocatable(Boolean r) { _relocatable = r; } + Boolean get_relocatable() const { return _relocatable; } + + void set_heat(unsigned heat) { _heat = heat; } + unsigned get_heat() const { return _heat; } + + void set_code_block_addr(void* addr) { _code_block = addr; } + void* get_code_block_addr() const { return _code_block; } + + size_t get_code_block_size() const { return _code_block_size; } + size_t get_code_block_alignment() const { return _code_block_alignment; } + + unsigned get_num_callees() const { return _num_callees; } + Callee_Info* get_callees() const { return _callee_info; } + + int get_jit_index() const; + + // Note: _data_blocks can only be used for inline info for now + Boolean has_inline_info() const { return _data_blocks != NULL; } + void* get_inline_info() const { return &_data_blocks->bytes[0]; } + + unsigned get_num_target_exception_handlers() const; + Target_Exception_Handler_Ptr get_target_exception_handler_info(unsigned eh_num) const; + + void record_call_to_callee(CodeChunkInfo *callee, void *caller_return_ip); + uint64 num_calls_to(CodeChunkInfo* other_chunk) const; + + void print_name() const; + void print_name(FILE* file) const; + void print_info(bool print_ellipses=false) const; // does not print callee information; see below + void print_callee_info() const; // prints the callee information; usually called after print_info() + + static void initialize_code_chunk(CodeChunkInfo* chunk) { + memset(chunk, 0, sizeof(CodeChunkInfo)); + chunk->_callee_info = chunk->_static_callee_info; + chunk->_max_callees = NUM_STATIC_CALLEE_ENTRIES; + chunk->_relocatable = TRUE; + } + +public: + // The section id of the main code chunk for a method. Using an enum avoids a VC++ bug on Windows. + enum {main_code_chunk_id = 0}; + + // Returns true if this is the main code chunk + // for a method: i.e, it + // 1) contains the method's entry point, and + // 2) contains the various flavors of JIT data for that method. + static bool is_main_code_chunk(CodeChunkInfo* chunk) { + assert(chunk); + return (chunk->get_id() == main_code_chunk_id); + } + + // Returns true if "id" is the section id of the main code chunk for a method. + static bool is_main_code_chunk_id(int id) { + return (id == main_code_chunk_id); + } + +private: + // The triple (_jit, _method, _id) uniquely identifies a CodeChunkInfo + JIT* _jit; + Method* _method; + int _id; + + bool _relocatable; + + // "Target" handlers + unsigned _num_target_exception_handlers; + Target_Exception_Handler_Ptr* _target_exception_handlers; + + // This records for each callee, the number of times it was called + // by each call IP in the caller. That is, this is a list of Callee_Info + // structures, each giving a call IP + // Points to an array of max_callees Callee_Info entries for this code chunk + Callee_Info* _callee_info; + unsigned _num_callees; + unsigned _max_callees; + // Array used if a small number of callers to avoid mallocs & frees + Callee_Info _static_callee_info[NUM_STATIC_CALLEE_ENTRIES]; + +public: + unsigned _heat; + void* _code_block; + void* _jit_info_block; + size_t _code_block_size; + size_t _jit_info_block_size; + size_t _code_block_alignment; + JIT_Data_Block* _data_blocks; + CodeChunkInfo* _next; + +#ifdef VM_STATS + uint64 num_throws; + uint64 num_catches; + uint64 num_unwind_java_frames_gc; + uint64 num_unwind_java_frames_non_gc; +#endif +}; // CodeChunkInfo + +#endif diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h b/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h new file mode 100644 index 0000000..d148275 --- /dev/null +++ b/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h @@ -0,0 +1,740 @@ +/* + * Copyright 2006 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __CLASS_MEMBER_H__ +#define __CLASS_MEMBER_H__ + +#include "String_Pool.h" +#include "annotation.h" +#include "jit_intf.h" + +struct ConstantPool; +class ByteReader; +class JIT; +class CodeChunkInfo; +struct Global_Env; + +/////////////////////////////////////////////////////////////////////////////// +// class file attributes +/////////////////////////////////////////////////////////////////////////////// +enum Attributes { + ATTR_SourceFile, // Class (no more than 1 in each class file) + ATTR_InnerClasses, // Class + ATTR_ConstantValue, // Field (no more than 1 for each field) + ATTR_Code, // Method + ATTR_Exceptions, // Method + ATTR_LineNumberTable, // Code + ATTR_LocalVariableTable, // Code + ATTR_Synthetic, // Class/Field/Method + ATTR_Deprecated, // Class/Field/Method + ATTR_SourceDebugExtension, // Class (no more than 1 in each class file) + ATTR_Signature, // Class/Field/Method (spec does not limit number???) + ATTR_EnclosingMethod, // Class (1 at most) + ATTR_LocalVariableTypeTable, // Code + ATTR_RuntimeVisibleAnnotations, // Class/Field/Method (at most 1 per entity) + ATTR_RuntimeInvisibleAnnotations, // Class/Field/Method + ATTR_RuntimeVisibleParameterAnnotations, // Method + ATTR_RuntimeInvisibleParameterAnnotations, // Method + ATTR_AnnotationDefault, // Method (spec does not limit number???) + N_ATTR, + ATTR_UNDEF, + ATTR_ERROR +}; + +/////////////////////////////////////////////////////////////////////////////// +// A class' members are its fields and methods. Class_Member is the base +// class for Field and Method, and factors out the commonalities in these +// two classes. +/////////////////////////////////////////////////////////////////////////////// +// VMEXPORT // temporary solution for interpreter unplug +class VMEXPORT Class_Member { +public: + // + // access modifiers + // + bool is_public() {return (_access_flags&ACC_PUBLIC)?true:false;} + bool is_private() {return (_access_flags&ACC_PRIVATE)?true:false;} + bool is_protected() {return (_access_flags&ACC_PROTECTED)?true:false;} + bool is_package_private() {return !(is_public()||is_protected()||is_public())?true:false;} + bool is_static() {return (_access_flags&ACC_STATIC)?true:false;} + bool is_final() {return (_access_flags&ACC_FINAL)?true:false;} + bool is_strict() {return (_access_flags&ACC_STRICT)?true:false;} + bool is_synthetic() {return (_access_flags&ACC_SYNTHETIC)?true:_synthetic;} + bool is_deprecated() {return _deprecated;} + unsigned get_access_flags() {return _access_flags;} + + // + // field get/set methods + // + unsigned get_offset() const {return _offset;} + Class *get_class() const {return _class;} + String *get_name() const {return _name;} + + // Get the type descriptor (Sec. 4.3.2) + String *get_descriptor() const {return _descriptor;} + String *get_signature() const {return _signature;} + + AnnotationTable* get_declared_annotations() const {return _annotations;} + + friend void assign_instance_field_offset(Class *clss, Field *field, bool do_field_compaction); + friend void assign_offsets_to_static_fields(Class *clss, Field **field_ptrs, bool do_field_compaction); + friend void assign_offsets_to_class_fields(Class *); + friend void add_new_fake_method(Class *clss, Class *example, unsigned *next); + friend void add_any_fake_methods(Class *); + + /** + * Allocate a memory from a class loader pool using the class + * loader lock. + */ + void* Alloc(size_t size); + +protected: + Class_Member() + { + _access_flags = 0; + _class = NULL; + _offset = 0; +#ifdef VM_STATS + num_accesses = 0; + num_slow_accesses = 0; +#endif + _synthetic = _deprecated = false; + _annotations = NULL; + _signature = NULL; + } + + // offset of class member; + // for virtual methods, the method's offset within the vtable + // for static methods, the method's offset within the class' static method table + // for instance data, offset within the instance's data block + // for static data, offset within the class' static data block + unsigned _offset; + + bool _synthetic; + bool _deprecated; + AnnotationTable* _annotations; + + uint16 _access_flags; + String* _name; + String* _descriptor; + String* _signature; + Class* _class; + + bool parse(Class* clss, ByteReader& cfs); + + /* + * returns ATTR_ERROR if attribute was recognized but parsing failed; + * returns ATTR_UNDEF if attribute was not recognized + * otherwise returns passed attr value + */ + Attributes process_common_attribute(Attributes attr, uint32 attr_len, ByteReader& cfs); + +public: +#ifdef VM_STATS + uint64 num_accesses; + uint64 num_slow_accesses; +#endif +}; // Class_Member + + + +/////////////////////////////////////////////////////////////////////////////// +// Fields within Class structures. +/////////////////////////////////////////////////////////////////////////////// +struct Field : public Class_Member{ +public: + //----------------------- + + // For all fields + bool is_offset_computed() { return (_offset_computed != 0); } + void set_offset_computed(bool is_computed) { _offset_computed = is_computed? 1 : 0; } + + // For static fields + VMEXPORT void* get_address(); + + // Return the type of this field. + Java_Type get_java_type() { + return (Java_Type)(get_descriptor()->bytes[0]); + }; + + Const_Java_Value get_const_value() { return const_value; }; + uint16 get_const_value_index() { return _const_value_index; }; + + //----------------------- + + Field() { + _const_value_index = 0; + _field_type_desc = 0; + _offset_computed = 0; + _is_injected = 0; + track_access = 0; + track_modification = 0; + } + + void Reset() { } + + void set(Class *cl, String* name, String* desc, unsigned short af) { + _class = cl; _access_flags = af; _name = name; _descriptor = desc; + } + Field& operator = (const Field& fd) { + // copy Class_Member fields + _access_flags = fd._access_flags; + _class = fd._class; + _offset = fd._offset; + _name = fd._name; + _descriptor = fd._descriptor; + _deprecated = fd._deprecated; + _synthetic = fd._synthetic; + _annotations = fd._annotations; + _signature = fd._signature; + + // copy Field fields + _const_value_index = fd._const_value_index; + _field_type_desc = fd._field_type_desc; + _is_injected = fd._is_injected; + _offset_computed = fd._offset_computed; + const_value = fd.const_value; + track_access = fd.track_access; + track_modification = fd.track_modification; + + return *this; + } + // + // access modifiers + // + unsigned is_volatile() {return (_access_flags&ACC_VOLATILE);} + unsigned is_transient() {return (_access_flags&ACC_TRANSIENT);} + bool is_enum() {return (_access_flags&ACC_ENUM)?true:false;} + + bool parse(Class* clss, ByteReader& cfs); + + unsigned calculate_size(); + + TypeDesc* get_field_type_desc() { return _field_type_desc; } + void set_field_type_desc(TypeDesc* td) { _field_type_desc = td; } + + Boolean is_injected() {return _is_injected;} + void set_injected() { _is_injected = 1; } + + void set_track_access(bool value) { + track_access = value ? 1 : 0 ; + } + + void set_track_modification(bool value) { + track_modification = value ? 1 : 0 ; + } + + void get_track_access_flag(char** address, char* mask) { + *address = &track_access; + *mask = TRACK_ACCESS_MASK; + } + + void get_track_modification_flag(char** address, char* mask) { + *address = &track_modification; + *mask = TRACK_MODIFICATION_MASK; + } + +private: + // + // The initial values of static fields. This is defined by the + // ConstantValue attribute in the class file. + // + // If there was not ConstantValue attribute for that field then _const_value_index==0 + // + uint16 _const_value_index; + Const_Java_Value const_value; + TypeDesc* _field_type_desc; + unsigned _is_injected : 1; + unsigned _offset_computed : 1; + + /** Turns on sending FieldAccess events on access to this field */ + char track_access; + const static char TRACK_ACCESS_MASK = 1; + + /** Turns on sending FieldModification events on modification of this field */ + char track_modification; + const static char TRACK_MODIFICATION_MASK = 1; + + //union { + // char bit_flags; + // struct { + + // /** Turns on sending FieldAccess events on access to this field */ + // char track_access : 1; + // const static char TRACK_ACCESS_MASK = 4; + + // /** Turns on sending FieldModification events on modification of this field */ + // char track_modification : 1; + // const static char TRACK_MODIFICATION_MASK = 8; + // }; + //}; +}; // Field + + + +/////////////////////////////////////////////////////////////////////////////// +// Handler represents a catch block in a method's code array +/////////////////////////////////////////////////////////////////////////////// +class Handler { +public: + Handler(); + bool parse(ConstantPool& cp, unsigned code_length, ByteReader &cfs); + uint32 get_start_pc() {return _start_pc;} + uint32 get_end_pc() {return _end_pc;} + uint32 get_handler_pc() {return _handler_pc;} + uint32 get_catch_type_index() {return _catch_type_index;} + + +private: + uint32 _start_pc; + uint32 _end_pc; + uint32 _handler_pc; + uint32 _catch_type_index; // CP idx + String *_catch_type; + +}; //Handler + + + +// Representation of target handlers in the generated code. +class Target_Exception_Handler { +public: + Target_Exception_Handler(NativeCodePtr start_ip, NativeCodePtr end_ip, NativeCodePtr handler_ip, Class_Handle exn_class, bool exn_is_dead); + + NativeCodePtr get_start_ip(); + NativeCodePtr get_end_ip(); + NativeCodePtr get_handler_ip(); + Class_Handle get_exc(); + bool is_exc_obj_dead(); + + bool is_in_range(NativeCodePtr eip, bool is_ip_past); + bool is_assignable(Class_Handle exn_class); + + void update_catch_range(NativeCodePtr new_start_ip, NativeCodePtr new_end_ip); + void update_handler_address(NativeCodePtr new_handler_ip); + +private: + NativeCodePtr _start_ip; + NativeCodePtr _end_ip; + NativeCodePtr _handler_ip; + Class_Handle _exc; + bool _exc_obj_is_dead; +}; //Target_Exception_Handler + +typedef class Target_Exception_Handler* Target_Exception_Handler_Ptr; + +#define MAX_VTABLE_PATCH_ENTRIES 10 + +class VTable_Patches { +public: + void *patch_table[MAX_VTABLE_PATCH_ENTRIES]; + VTable_Patches *next; +}; + +// Used to notify interested JITs whenever a method is changed: overwritten, recompiled, +// or initially compiled. +struct Method_Change_Notification_Record { + Method *method_of_interest; + JIT *jit; + void *callback_data; + Method_Change_Notification_Record *next; + + bool equals(Method *method_of_interest_, JIT *jit_, void *callback_data_) { + if ((method_of_interest == method_of_interest_) && + (jit == jit_) && + (callback_data == callback_data_)) { + return true; + } + return false; + } + // Optimized equals method. Most callbacks know method of interest, so we could skip one check. + inline bool equals(JIT *jit_, void *callback_data_) { + if ((callback_data == callback_data_) && + (jit == jit_)) { + return true; + } + return false; + } +}; + + +struct Inline_Record; + + +// 20020222 This is only temporary to support the new JIT interface. +// We will reimplement the signature support. +struct Method_Signature { +public: + TypeDesc* return_type_desc; + unsigned num_args; + TypeDesc** arg_type_descs; + Method *method; + String *sig; + + + void initialize_from_method(Method *method); + void reset(); + +private: + void initialize_from_java_method(Method *method); +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Methods defined in a class. +/////////////////////////////////////////////////////////////////////////////// + +struct Line_Number_Entry { + uint16 start_pc; + uint16 line_number; +}; + +struct Line_Number_Table { + uint16 length; + Line_Number_Entry table[1]; +}; + +struct Local_Var_Entry { + uint16 start_pc; + uint16 length; + uint16 index; + String* name; + String* type; + String* generic_type; +}; + +struct Local_Var_Table { + uint16 length; + Local_Var_Entry table[1]; +}; + + +// VMEXPORT // temporary solution for interpreter unplug +struct VMEXPORT Method : public Class_Member { + //----------------------- +public: + // + // state of this method + // + enum State { + ST_NotCompiled, // initial state + ST_NotLinked = ST_NotCompiled, // native not linked to implementation + ST_Compiled, // compiled by JIT + ST_Linked = ST_Compiled // native linked to implementation + }; + State get_state() {return _state;} + void set_state(State st) {_state=st;} + + // "Bytecode" exception handlers, i.e., those from the class file + unsigned num_bc_exception_handlers(); + Handler *get_bc_exception_handler_info(unsigned eh_number); + + // "Target" exception handlers, i.e., those in the code generated by the JIT. + void set_num_target_exception_handlers(JIT *jit, unsigned n); + unsigned get_num_target_exception_handlers(JIT *jit); + + // Arguments: + // ... + // catch_clss -- class of the exception or null (for "catch-all") + // ... + void set_target_exception_handler_info(JIT *jit, + unsigned eh_number, + void *start_ip, + void *end_ip, + void *handler_ip, + Class *catch_clss, + bool exc_obj_is_dead = false); + + Target_Exception_Handler_Ptr get_target_exception_handler_info(JIT *jit, unsigned eh_num); + + unsigned num_exceptions_method_can_throw(); + String *get_exception_name (int n); + + // Address of the memory block containing bytecodes. For best performance + // the bytecodes should not be destroyed even after the method has been + // jitted to allow re-compilation. However the interface allows for such + // deallocation. The effect would be that re-optimizing JITs would not + // show their full potential, but that may be acceptable for low-end systems + // where memory is at a premium. + // The value returned by getByteCodeAddr may be NULL in which case the + // bytecodes are not available (presumably they have been garbage collected by VM). + const Byte *get_byte_code_addr() {return _byte_codes;} + size_t get_byte_code_size() {return _byte_code_length;} + + // From the class file (Sec. 4.7.4) + unsigned get_max_stack() { return _max_stack; } + unsigned get_max_locals() { return _max_locals; } + + // Returns an iterator for the argument list. + Arg_List_Iterator get_argument_list(); + + // Returns number of bytes of arguments pushed on the stack. + // This value depends on the descriptor and the calling convention. + unsigned get_num_arg_bytes(); + + // Returns number of arguments. For non-static methods, the this pointer + // is included in this number + unsigned get_num_args(); + + // Number of arguments which are references. + unsigned get_num_ref_args(); + + + // Return the return type of this method. + Java_Type get_return_java_type(); + + // For non-primitive types (i.e., classes) get the class type information. + Class *get_return_class_type(); + + // Address of the memory location containing the address of the code. + // Used for static and special methods which have been resolved but not jitted. + // The call would be: + // call dword ptr [addr] + void *get_indirect_address() { return &_code; } + + // Entry address of the method. Points to an appropriate stub or directly + // to the code if no stub is necessary. + void *get_code_addr() { return _code; } + void set_code_addr(void *code_addr) { _code = code_addr; } + + void add_vtable_patch(void *); + void apply_vtable_patches(); + + /** + * This returns a block for jitted code. It is not used for native methods. + * It is safe to call this function from multiple threads. + */ + void *allocate_code_block_mt(size_t size, size_t alignment, JIT *jit, unsigned heat, + int id, Code_Allocation_Action action); + + void *allocate_rw_data_block(size_t size, size_t alignment, JIT *jit); + + // The JIT can store some information in a JavaMethod object. + void *allocate_jit_info_block(size_t size, JIT *jit); + + // JIT-specific data blocks. + // Access should be protected with _lock. + // FIXME + // Think about moving lock aquisition inside public methods. + void *allocate_JIT_data_block(size_t size, JIT *jit, size_t alignment); + CodeChunkInfo *get_first_JIT_specific_info() { return _jits; }; + CodeChunkInfo *get_JIT_specific_info_no_create(JIT *jit); + /** + * Find a chunk info for specific JIT. If no chunk exist for this JIT, + * create and return one. This method is safe to call + * from multiple threads. + */ + CodeChunkInfo *get_chunk_info_mt(JIT *jit, int id); + + /** + * Find a chunk info for specific JIT, or NULL if + * no chunk info is created for this JIT. This method is safe to call + * from multiple threads. + */ + CodeChunkInfo *get_chunk_info_no_create_mt(JIT *jit, int id); + + /** + * Allocate a new chunk info. This method is safe to call + * from multiple threads. + */ + CodeChunkInfo *create_code_chunk_info_mt(); + + // Notify JITs whenever this method is overridden by a newly loaded class. + void register_jit_overridden_method_callback(JIT *jit_to_be_notified, void *callback_data); + void do_jit_overridden_method_callbacks(Method *overriding_method); + + // Notify JITs whenever this method is recompiled or initially compiled. + void register_jit_recompiled_method_callback(JIT *jit_to_be_notified, void *callback_data); + void do_jit_recompiled_method_callbacks(); + + Method_Side_Effects get_side_effects() { return _side_effects; }; + void set_side_effects(Method_Side_Effects mse) { _side_effects = mse; }; + + Method_Signature *get_method_sig() { return _method_sig; }; + void set_method_sig(Method_Signature *msig) { _method_sig = msig; }; + +private: + State _state; + void *_code; + VTable_Patches *_vtable_patch; + + NativeCodePtr _counting_stub; + + CodeChunkInfo *_jits; + + Method_Side_Effects _side_effects; + Method_Signature *_method_sig; + +public: + Method(); + // destructor should be instead of this function, but it's not allowed to use it because copy for Method class is + // done with memcpy, and old value is destroyed with delete operator. + void MethodClearInternals(); + + // + // access modifiers + // + bool is_synchronized() {return (_access_flags&ACC_SYNCHRONIZED)?true:false;} + bool is_native() {return (_access_flags&ACC_NATIVE)?true:false;} + bool is_abstract() {return (_access_flags&ACC_ABSTRACT)?true:false;} + bool is_varargs() {return (_access_flags&ACC_VARARGS)?true:false;} + bool is_bridge() {return (_access_flags&ACC_BRIDGE)?true:false;} + + // method flags + bool is_init() {return _flags.is_init?true:false;} + bool is_clinit() {return _flags.is_clinit?true:false;} + bool is_finalize() {return _flags.is_finalize?true:false;} + bool is_overridden() {return _flags.is_overridden?true:false;} + bool is_registered() {return _flags.is_registered?true:false;} + Boolean is_nop() {return _flags.is_nop;} + + void set_registered( bool flag ) { _flags.is_registered = flag; } + + unsigned get_index() {return _index;} + + // Fake methods are interface methods inherited by an abstract class that are not (directly or indirectly) + // implemented by that class. They are added to the class to ensure they have thecorrect vtable offset. + // These fake methods point to the "real" interface method for which they are surrogates; this information + // is used by reflection methods. + bool is_fake_method() {return (_intf_method_for_fake_method != NULL);} + Method *get_real_intf_method() {return _intf_method_for_fake_method;} + + bool parse(Global_Env& env, Class* clss, ByteReader& cfs); + + unsigned calculate_size() { + unsigned size = sizeof(Class_Member) + sizeof(Method); + if(_local_vars_table) + size += sizeof(uint16) + _local_vars_table->length*sizeof(Local_Var_Entry); + if(_line_number_table) + size += sizeof(uint16) + _line_number_table->length*sizeof(Line_Number_Entry); + size += _n_exceptions*sizeof(String*); + size += _n_handlers*sizeof(Handler); + size += _byte_code_length; + return size; + } + + friend void assign_offsets_to_class_methods(Class* clss); + friend void add_new_fake_method(Class* clss, Class* example, unsigned* next); + friend void add_any_fake_methods(Class* clss); + + unsigned get_num_param_annotations() {return _num_param_annotations;} + AnnotationTable * get_param_annotations(unsigned index) { + return index < _num_param_annotations ? _param_annotations[index] : NULL; + } + AnnotationValue * get_default_value() {return _default_value; } + +private: + uint8 _num_param_annotations; + AnnotationTable ** _param_annotations; + AnnotationValue * _default_value; + + unsigned _index; // index in method table + uint16 _max_stack; + uint16 _max_locals; + uint16 _n_exceptions; // num exceptions method can throw + uint16 _n_handlers; // num exception handlers in byte codes + String **_exceptions; // array of exceptions method can throw + uint32 _byte_code_length; // num bytes of byte code + Byte *_byte_codes; // method's byte codes + Handler *_handlers; // array of exception handlers in code + Method *_intf_method_for_fake_method; + struct { + unsigned is_init : 1; + unsigned is_clinit : 1; + unsigned is_finalize : 1; // is finalize() method + unsigned is_overridden : 1; // has this virtual method been overridden by a loaded subclass? + unsigned is_nop : 1; + unsigned is_registered : 1; // the method is registred native method + } _flags; + + // + // private methods for parsing methods + // + bool _parse_code(ConstantPool& cp, unsigned code_attr_len, ByteReader &cfs); + + bool _parse_line_numbers(unsigned attr_len, ByteReader &cfs); + + bool _parse_exceptions(ConstantPool& cp, unsigned attr_len, ByteReader &cfs); + + void _set_nop(); + + // + // debugging info + // + Line_Number_Table *_line_number_table; + Local_Var_Table *_local_vars_table; + + bool _parse_local_vars(const char* attr_name, Local_Var_Table** lvt_address, + ConstantPool& cp, unsigned attr_len, ByteReader &cfs); + + // This is the number of breakpoints which should be set in the + // method when it is compiled. This number does not reflect + // multiple breakpoints that are set in the same location by + // different environments, it counts only unique locations + uint32 pending_breakpoints; +public: + + unsigned get_line_number_table_size() { + return (_line_number_table) ? _line_number_table->length : 0; + } + + bool get_line_number_entry(unsigned index, jlong* pc, jint* line); + + unsigned get_local_var_table_size() { + return (_local_vars_table) ? _local_vars_table->length : 0; + } + + bool get_local_var_entry(unsigned index, jlong* pc, + jint* length, jint* slot, String** name, String** type, + String** generic_type); + + // XXX + //bool get_local_var_entry(unsigned index, jlong* pc, + // jint* length, jint* slot, String** name, String** type); + + + // Returns number of line in the source file, to which the given bytecode offset + // corresponds, or -1 if it is unknown. + int get_line_number(uint16 bc_offset); + + Inline_Record *inline_records; + void set_inline_assumption(JIT *jit, Method *caller); + void method_was_overridden(); + + Method_Change_Notification_Record *_notify_override_records; + + // Records JITs to be notified when a method is recompiled or initially compiled. + Method_Change_Notification_Record *_notify_recompiled_records; + + void lock(); + void unlock(); + + uint32 get_pending_breakpoints() + { + return pending_breakpoints; + } + + void insert_pending_breakpoint() + { + pending_breakpoints++; + } + + void remove_pending_breakpoint() + { + pending_breakpoints--; + } +}; // Method + +#endif diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/jni_direct.h b/enhanced/drlvm/trunk/vm/vmcore/include/jni_direct.h index abaaa18..4afa066 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/jni_direct.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/jni_direct.h @@ -28,7 +28,7 @@ #define _JNI_DIRECT_H_ #include "jni.h" #include "open/types.h" -#include "Class.h" +#include "class_member.h" struct _jfieldID : public Field { }; diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h b/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h index 7555164..9d5101a 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h @@ -24,6 +24,7 @@ #define _JVMTI_DIRECT_H_ #include "jni_direct.h" #include "jvmti.h" +#include "vm_core_types.h" struct TIEventThread { diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/object_handles.h b/enhanced/drlvm/trunk/vm/vmcore/include/object_handles.h index 935548a..2f3c70a 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/object_handles.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/object_handles.h @@ -43,6 +43,12 @@ #include "object_layout.h" #include "vm_core_types.h" #include "jni.h" +#ifndef NDEBUG +// FIXME: this is for managed object sanity checks +// (used in monitor enter/exit functions) +#include "Class.h" +#endif + /** * GC frames store memory locations which contain managed pointers, so they are updated * during garbage collection. Note, GC suspension must be disabled when created or deleting diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/vm_log.h b/enhanced/drlvm/trunk/vm/vmcore/include/vm_log.h index f6c7031..d924261 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/vm_log.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/vm_log.h @@ -22,8 +22,11 @@ #ifndef _VM_LOG_H_ #define _VM_LOG_H_ #include "loggerstring.h" -#include "Class.h" +#include "object_layout.h" #include "object_handles.h" +#include "vtable.h" +#include "String_Pool.h" +#include "class_member.h" /** * @file diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/vtable.h b/enhanced/drlvm/trunk/vm/vmcore/include/vtable.h new file mode 100644 index 0000000..c38d7d6 --- /dev/null +++ b/enhanced/drlvm/trunk/vm/vmcore/include/vtable.h @@ -0,0 +1,81 @@ +/* + * Copyright 2006 The Apache Software Foundation or its licensors, as applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __VTABLE_H__ +#define __VTABLE_H__ + +/** + * @file + * virtual method table of a class + */ +extern "C" { + +typedef struct { + unsigned char** table; // pointer into methods array of Intfc_Table below + unsigned intfc_id; // id of interface +} Intfc_Table_Entry; + +typedef struct Intfc_Table { +#ifdef POINTER64 + // see INTFC_TABLE_OVERHEAD + uint32 dummy; // padding +#endif + uint32 n_entries; + Intfc_Table_Entry entry[1]; +} Intfc_Table; + +#define INTFC_TABLE_OVERHEAD (sizeof(void*)) + +#ifdef POINTER64 +#define OBJECT_HEADER_SIZE 0 +// The size of an object reference. Used by arrays of object to determine +// the size of an element. +#define OBJECT_REF_SIZE 8 +#else // POINTER64 +#define OBJECT_HEADER_SIZE 0 +#define OBJECT_REF_SIZE 4 +#endif // POINTER64 + +#define GC_BYTES_IN_VTABLE (sizeof(void*)) +#define MAX_FAST_INSTOF_DEPTH 5 + +typedef struct VTable { + Byte _gc_private_information[GC_BYTES_IN_VTABLE]; + Class* clss; + + // See the masks in vm_for_gc.h. + uint32 class_properties; + + // Offset from the top by CLASS_ALLOCATED_SIZE_OFFSET + // The number of bytes allocated for this object. It is the same as + // instance_data_size with the constraint bit cleared. This includes + // the OBJECT_HEADER_SIZE as well as the OBJECT_VTABLE_POINTER_SIZE + unsigned int allocated_size; + + unsigned short array_element_size; + unsigned short array_element_shift; + Intfc_Table* intfc_table; // interface table; NULL if no intfc table + Class *superclasses[MAX_FAST_INSTOF_DEPTH]; + unsigned char* methods[1]; // code for method +} VTable; +#define VTABLE_OVERHEAD (sizeof(VTable) - sizeof(void *)) +// The "- sizeof(void *)" part subtracts out the "unsigned char *methods[1]" contribution. + +VTable *create_vtable(Class *p_class, unsigned n_vtable_entries); + +} // extern "C" + + +#endif diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp index 6600df9..7f35f14 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp @@ -32,6 +32,7 @@ #include "properties.h" #include "open/hythread_ext.h" #include "thread_manager.h" +#include "cci.h" #include "Verifier_stub.h" #include "class_interface.h" @@ -740,28 +741,10 @@ const char *class_get_source_file_name(C } //class_get_source_file_name - -// If this function was exported through the public interface, we should -// change the return type to something like String_Handle. -String *class_get_const_string_handle(Class_Handle cl, unsigned index) -{ - assert(cl); - Class *clss = (Class *)cl; - String *str = 0; - assert(index < clss->cp_size); - Const_Pool *cp = clss->const_pool; - str = cp[index].CONSTANT_String.string; - return str; -} //class_get_const_string_handle - - - -const char *class_get_const_string(Class_Handle cl, unsigned index) +const char* class_get_const_string(Class_Handle cl, unsigned index) { assert(cl); - String *str = class_get_const_string_handle(cl, index); - assert(str); - return str->bytes; + return cl->m_const_pool.get_string_chars(index); } //class_get_const_string @@ -773,7 +756,7 @@ void *class_get_const_string_intern_addr { assert(cl); Global_Env *env = VM_Global_State::loader_env; - String *str = class_get_const_string_handle(cl, index); + String* str = cl->m_const_pool.get_string(index); assert(str); bool must_instantiate; @@ -791,7 +774,6 @@ void *class_get_const_string_intern_addr vm_instantiate_cp_string_resolved(str); END_RAISE_AREA; tmn_suspend_enable(); - } if (env->compress_references) { @@ -805,23 +787,21 @@ void *class_get_const_string_intern_addr const char* class_get_cp_entry_signature(Class_Handle src_class, unsigned short index) { Class* clss = (Class*)src_class; - // TODO: check that index is valid for src_class; assert for now - assert(index < clss->cp_size); - assert(cp_is_methodref(clss->const_pool, index) - || cp_is_interfacemethodref(clss->const_pool, index) - || cp_is_fieldref(clss->const_pool, index)); - - index = clss->const_pool[index].CONSTANT_ref.name_and_type_index; - index = clss->const_pool[index].CONSTANT_NameAndType.descriptor_index; - return clss->const_pool[index].CONSTANT_Utf8.string->bytes; + ConstantPool& cp = src_class->m_const_pool; + + assert(cp.is_fieldref(index) + || cp.is_methodref(index) + || cp.is_interfacemethodref(index)); + + index = cp.get_ref_name_and_type_index(index); + index = cp.get_name_and_type_descriptor_index(index); + return cp.get_utf8_chars(index); } // class_get_cp_entry_signature VM_Data_Type class_get_cp_field_type(Class_Handle src_class, unsigned short cp_index) { - // TODO: check that cp_index is valid for src_class; assert for now - assert(cp_index < ((Class*)src_class)->cp_size); - assert(cp_is_fieldref(((Class*)src_class)->const_pool, cp_index)); + assert(src_class->m_const_pool.is_fieldref(cp_index)); char class_id = (class_get_cp_entry_signature(src_class, cp_index))[0]; switch(class_id) @@ -1047,148 +1027,148 @@ Class_Handle class_find_class_from_loade // The following do not cause constant pools to be resolve, if they are not // resolved already // -const char *const_pool_get_field_name(Class_Handle cl, unsigned index) +const char* const_pool_get_field_name(Class_Handle cl, unsigned index) { assert(cl); - Const_Pool *const_pool = ((Class *)cl)->const_pool; - if (!cp_is_fieldref(const_pool,index)) { + ConstantPool& const_pool = cl->m_const_pool; + if(!const_pool.is_fieldref(index)) { ABORT("Wrong index"); return 0; } - index = const_pool[index].CONSTANT_ref.name_and_type_index; - index = const_pool[index].CONSTANT_NameAndType.name_index; - return const_pool[index].CONSTANT_Utf8.string->bytes; -} //const_pool_get_field_name + index = const_pool.get_ref_name_and_type_index(index); + index = const_pool.get_name_and_type_name_index(index); + return const_pool.get_utf8_chars(index); +} // const_pool_get_field_name -const char *const_pool_get_field_class_name(Class_Handle cl, unsigned index) +const char* const_pool_get_field_class_name(Class_Handle cl, unsigned index) { assert(cl); - Const_Pool *const_pool = ((Class *)cl)->const_pool; - if (!cp_is_fieldref(const_pool,index)) { + ConstantPool& const_pool = cl->m_const_pool; + if(!const_pool.is_fieldref(index)) { ABORT("Wrong index"); return 0; } - index = const_pool[index].CONSTANT_ref.class_index; - return const_pool_get_class_name(cl,index); + index = const_pool.get_ref_class_index(index); + return const_pool_get_class_name(cl, index); } //const_pool_get_field_class_name -const char *const_pool_get_field_descriptor(Class_Handle cl, unsigned index) +const char* const_pool_get_field_descriptor(Class_Handle cl, unsigned index) { assert(cl); - Const_Pool *const_pool = ((Class *)cl)->const_pool; - if (!cp_is_fieldref(const_pool,index)) { + ConstantPool& const_pool = cl->m_const_pool; + if (!const_pool.is_fieldref(index)) { ABORT("Wrong index"); return 0; } - index = const_pool[index].CONSTANT_ref.name_and_type_index; - index = const_pool[index].CONSTANT_NameAndType.descriptor_index; - return const_pool[index].CONSTANT_Utf8.string->bytes; -} //const_pool_get_field_descriptor + index = const_pool.get_ref_name_and_type_index(index); + index = const_pool.get_name_and_type_descriptor_index(index); + return const_pool.get_utf8_chars(index); +} // const_pool_get_field_descriptor -const char *const_pool_get_method_name(Class_Handle cl, unsigned index) +const char* const_pool_get_method_name(Class_Handle cl, unsigned index) { assert(cl); - Const_Pool *const_pool = ((Class *)cl)->const_pool; - if (!cp_is_methodref(const_pool,index)) { + ConstantPool& const_pool = cl->m_const_pool; + if (!const_pool.is_methodref(index)) { ABORT("Wrong index"); return 0; } - index = const_pool[index].CONSTANT_ref.name_and_type_index; - index = const_pool[index].CONSTANT_NameAndType.name_index; - return const_pool[index].CONSTANT_Utf8.string->bytes; -} //const_pool_get_method_name + index = const_pool.get_ref_name_and_type_index(index); + index = const_pool.get_name_and_type_name_index(index); + return const_pool.get_utf8_chars(index); +} // const_pool_get_method_name const char *const_pool_get_method_class_name(Class_Handle cl, unsigned index) { assert(cl); - Const_Pool *const_pool = ((Class *)cl)->const_pool; - if (!cp_is_methodref(const_pool,index)) { + ConstantPool& const_pool = cl->m_const_pool; + if (!const_pool.is_methodref(index)) { ABORT("Wrong index"); return 0; } - index = const_pool[index].CONSTANT_ref.class_index; + index = const_pool.get_ref_class_index(index); return const_pool_get_class_name(cl,index); } //const_pool_get_method_class_name -const char *const_pool_get_interface_method_name(Class_Handle cl, unsigned index) +const char* const_pool_get_interface_method_name(Class_Handle cl, unsigned index) { assert(cl); - Const_Pool *const_pool = ((Class *)cl)->const_pool; - if (!cp_is_interfacemethodref(const_pool,index)) { + ConstantPool& const_pool = cl->m_const_pool; + if(!const_pool.is_interfacemethodref(index)) { ABORT("Wrong index"); return 0; } - index = const_pool[index].CONSTANT_ref.name_and_type_index; - index = const_pool[index].CONSTANT_NameAndType.name_index; - return const_pool[index].CONSTANT_Utf8.string->bytes; -} //const_pool_get_interface_method_name + index = const_pool.get_ref_name_and_type_index(index); + index = const_pool.get_name_and_type_name_index(index); + return const_pool.get_utf8_chars(index); +} // const_pool_get_interface_method_name -const char *const_pool_get_interface_method_class_name(Class_Handle cl, unsigned index) +const char* const_pool_get_interface_method_class_name(Class_Handle cl, unsigned index) { assert(cl); - Const_Pool *const_pool = ((Class *)cl)->const_pool; - if (!cp_is_interfacemethodref(const_pool,index)) { + ConstantPool& const_pool = cl->m_const_pool; + if (!const_pool.is_interfacemethodref(index)) { ABORT("Wrong index"); return 0; } - index = const_pool[index].CONSTANT_ref.class_index; + index = const_pool.get_ref_class_index(index); return const_pool_get_class_name(cl,index); } //const_pool_get_interface_method_class_name -const char *const_pool_get_method_descriptor(Class_Handle cl, unsigned index) +const char* const_pool_get_method_descriptor(Class_Handle cl, unsigned index) { assert(cl); - Const_Pool *const_pool = ((Class *)cl)->const_pool; - if (!cp_is_methodref(const_pool,index)) { + ConstantPool& const_pool = cl->m_const_pool; + if (!const_pool.is_methodref(index)) { ABORT("Wrong index"); return 0; } - index = const_pool[index].CONSTANT_ref.name_and_type_index; - index = const_pool[index].CONSTANT_NameAndType.descriptor_index; - return const_pool[index].CONSTANT_Utf8.string->bytes; -} //const_pool_get_method_descriptor + index = const_pool.get_ref_name_and_type_index(index); + index = const_pool.get_name_and_type_descriptor_index(index); + return const_pool.get_utf8_chars(index); +} // const_pool_get_method_descriptor -const char *const_pool_get_interface_method_descriptor(Class_Handle cl, unsigned index) +const char* const_pool_get_interface_method_descriptor(Class_Handle cl, unsigned index) { assert(cl); - Const_Pool *const_pool = ((Class *)cl)->const_pool; - if (!cp_is_interfacemethodref(const_pool,index)) { + ConstantPool& const_pool = cl->m_const_pool; + if (!const_pool.is_interfacemethodref(index)) { ABORT("Wrong index"); return 0; } - index = const_pool[index].CONSTANT_ref.name_and_type_index; - index = const_pool[index].CONSTANT_NameAndType.descriptor_index; - return const_pool[index].CONSTANT_Utf8.string->bytes; -} //const_pool_get_interface_method_descriptor + index = const_pool.get_ref_name_and_type_index(index); + index = const_pool.get_name_and_type_descriptor_index(index); + return const_pool.get_utf8_chars(index); +} // const_pool_get_interface_method_descriptor -const char *const_pool_get_class_name(Class_Handle cl, unsigned index) +const char* const_pool_get_class_name(Class_Handle cl, unsigned index) { assert(cl); - Const_Pool *const_pool = ((Class *)cl)->const_pool; - if (!cp_is_class(const_pool,index)) { + ConstantPool& const_pool = cl->m_const_pool; + if (!const_pool.is_class(index)) { ABORT("Wrong index"); return 0; } - return const_pool[const_pool[index].CONSTANT_Class.name_index].CONSTANT_Utf8.string->bytes; -} //const_pool_get_class_name + return const_pool.get_utf8_chars(const_pool.get_class_name_index(index)); +} // const_pool_get_class_name unsigned method_number_throws(Method_Handle m) diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp index b5f1f1c..d28608f 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp @@ -195,6 +195,14 @@ void* Field::get_address() } // Field::get_address +unsigned Field::calculate_size() { + static unsigned size = sizeof(Field) + sizeof(TypeDesc); + return size; +} + + + + Method::Method() { // @@ -447,7 +455,8 @@ void set_struct_Class_field_in_java_lang void class_report_failure(Class* target, uint16 cp_index, jthrowable exn) { - assert(cp_index > 0 && cp_index < target->cp_size); + ConstantPool& cp = target->m_const_pool; + assert(cp.is_valid_index(cp_index)); assert(hythread_is_suspend_enabled()); if (exn_raised()) { TRACE2("classloader.error", "runtime exception in classloading"); @@ -458,13 +467,7 @@ void class_report_failure(Class* target, tmn_suspend_disable(); target->m_lock->_lock(); // vvv - This should be atomic change - if (!cp_in_error(target->const_pool, cp_index)) { - cp_set_error(target->const_pool, cp_index); - target->const_pool[cp_index].error.cause = ((ObjectHandle)exn)->object; - target->const_pool[cp_index].error.next = target->m_failedResolution; - assert(&(target->const_pool[cp_index]) != target->m_failedResolution); - target->m_failedResolution = &(target->const_pool[cp_index]); - } + cp.resolve_as_error(cp_index, exn); // ^^^ target->m_lock->_unlock(); tmn_suspend_enable(); @@ -473,8 +476,8 @@ void class_report_failure(Class* target, jthrowable class_get_linking_error(Class* clss, unsigned index) { - assert(cp_in_error(clss->const_pool, index)); - return (jthrowable)(&(clss->const_pool[index].error.cause)); + assert(clss->m_const_pool.is_entry_in_error(index)); + return clss->m_const_pool.get_error_cause(index); } String* class_get_java_name(Class* clss, Global_Env* env) diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class_File_Loader.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class_File_Loader.cpp index 7dfec71..1c2361e 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class_File_Loader.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class_File_Loader.cpp @@ -29,6 +29,7 @@ #include #include "environment.h" #include "classloader.h" #include "Class.h" +#include "class_member.h" #include "vm_strings.h" #include "open/vm_util.h" #include "bytereader.h" @@ -66,33 +67,29 @@ #define REPORT_FAILED_CLASS_FORMAT(klass } #define valid_cpi(clss, idx, type) \ - (idx < clss->cp_size && cp_tag(clss->const_pool, idx) == type) + (clss->m_const_pool.is_valid_index(idx) && clss->m_const_pool.get_tag(idx) == type) -String *cp_check_utf8(Const_Pool *cp, - unsigned cp_size, - unsigned utf8_index) +String* cp_check_utf8(ConstantPool& cp, unsigned utf8_index) { - if(utf8_index >= cp_size || !cp_is_utf8(cp, utf8_index)) { + if(!cp.is_valid_index(utf8_index) || !cp.is_utf8(utf8_index)) { return NULL; } - return cp[utf8_index].CONSTANT_Utf8.string; -} //cp_check_utf8 + return cp.get_utf8_string(utf8_index); +} // cp_check_utf8 -String *cp_check_class(Const_Pool *cp, - unsigned cp_size, - unsigned class_index) +String* cp_check_class(ConstantPool& cp, unsigned class_index) { - if (class_index >= cp_size || !cp_is_class(cp,class_index)) { + if(!cp.is_valid_index(class_index) || !cp.is_class(class_index)) { #ifdef _DEBUG WARN("cp_check_class: illegal const pool class index" << class_index); #endif return NULL; } - return cp[cp[class_index].CONSTANT_Class.name_index].CONSTANT_Utf8.string; + return cp.get_utf8_string(cp.get_class_name_index(class_index)); } //cp_check_class @@ -216,7 +213,7 @@ String* parse_signature_attr(ByteReader "cannot parse Signature index"); return NULL; } - String* sig = cp_check_utf8(clss->const_pool, clss->cp_size, idx); + String* sig = cp_check_utf8(clss->m_const_pool, idx); if(!sig) { REPORT_FAILED_CLASS_FORMAT(clss, "invalid Signature index : " << idx); } @@ -225,8 +222,7 @@ String* parse_signature_attr(ByteReader Attributes parse_attribute(ByteReader &cfs, - Const_Pool *cp, - unsigned cp_size, + ConstantPool& cp, String *attr_strings[], Attributes attrs[], uint32 *attr_len, @@ -243,7 +239,7 @@ Attributes parse_attribute(ByteReader &c if (!result) return ATTR_ERROR; - String *attr_name = cp_check_utf8(cp,cp_size,attr_name_index); + String* attr_name = cp_check_utf8(cp, attr_name_index); if (attr_name == NULL) { #ifdef _DEBUG WARN("parse_attribute: illegal const pool attr_name_index"); @@ -294,7 +290,7 @@ uint32 parse_annotation(Annotation** val "cannot parse type index of annotation"); return 0; } - String* type = cp_check_utf8(clss->const_pool, clss->cp_size, type_idx); + String* type = cp_check_utf8(clss->m_const_pool, type_idx); if (type == NULL) { REPORT_FAILED_CLASS_FORMAT(clss, "invalid type index of annotation : " << type_idx); @@ -325,7 +321,7 @@ uint32 parse_annotation(Annotation** val "cannot parse element_name_index of annotation element"); return 0; } - antn->elements[j].name = cp_check_utf8(clss->const_pool, clss->cp_size, name_idx); + antn->elements[j].name = cp_check_utf8(clss->m_const_pool, name_idx); if (antn->elements[j].name == NULL) { REPORT_FAILED_CLASS_FORMAT(clss, "invalid element_name_index of annotation : " << name_idx); @@ -354,8 +350,8 @@ uint32 parse_annotation_value(Annotation value.tag = (AnnotationValueType)tag; uint32 read_len = 1; - Const_Pool *cp = clss->const_pool; - unsigned cp_size = clss->cp_size; + ConstantPool& cp = clss->m_const_pool; + unsigned cp_size = cp.get_size(); char ctag = (char)tag; switch(ctag) { @@ -382,29 +378,29 @@ uint32 parse_annotation_value(Annotation case AVT_CHAR: case AVT_INT: if (valid_cpi(clss, const_idx, CONSTANT_Integer)) { - value.const_value.i = cp[const_idx].int_value; + value.const_value.i = cp.get_int(const_idx); break; } case AVT_FLOAT: if (valid_cpi(clss, const_idx, CONSTANT_Float)) { - value.const_value.f = cp[const_idx].float_value; + value.const_value.f = cp.get_float(const_idx); break; } case AVT_LONG: if (valid_cpi(clss, const_idx, CONSTANT_Long)) { - value.const_value.l.lo_bytes = cp[const_idx].CONSTANT_8byte.low_bytes; - value.const_value.l.hi_bytes = cp[const_idx].CONSTANT_8byte.high_bytes; + value.const_value.l.lo_bytes = cp.get_8byte_low_word(const_idx); + value.const_value.l.hi_bytes = cp.get_8byte_high_word(const_idx); break; } case AVT_DOUBLE: if (valid_cpi(clss, const_idx, CONSTANT_Double)) { - value.const_value.l.lo_bytes = cp[const_idx].CONSTANT_8byte.low_bytes; - value.const_value.l.hi_bytes = cp[const_idx].CONSTANT_8byte.high_bytes; + value.const_value.l.lo_bytes = cp.get_8byte_low_word(const_idx); + value.const_value.l.hi_bytes = cp.get_8byte_high_word(const_idx); break; } case AVT_STRING: if (valid_cpi(clss, const_idx, CONSTANT_Utf8)) { - value.const_value.string = cp[const_idx].CONSTANT_Utf8.string; + value.const_value.string = cp.get_utf8_string(const_idx); break; } default: @@ -425,7 +421,7 @@ uint32 parse_annotation_value(Annotation "cannot parse class_info_index of annotation value"); return 0; } - value.class_name = cp_check_utf8(cp, cp_size, class_idx); + value.class_name = cp_check_utf8(cp, class_idx); if (value.class_name == NULL) { REPORT_FAILED_CLASS_FORMAT(clss, "invalid class_info_index of annotation value: " << class_idx); @@ -443,7 +439,7 @@ uint32 parse_annotation_value(Annotation "cannot parse type_name_index of annotation enum value"); return 0; } - value.enum_const.type = cp_check_utf8(cp, cp_size, type_idx); + value.enum_const.type = cp_check_utf8(cp, type_idx); if (value.enum_const.type == NULL) { REPORT_FAILED_CLASS_FORMAT(clss, "invalid type_name_index of annotation enum value: " << type_idx); @@ -455,7 +451,7 @@ uint32 parse_annotation_value(Annotation "cannot parse const_name_index of annotation enum value"); return 0; } - value.enum_const.name = cp_check_utf8(cp, cp_size, name_idx); + value.enum_const.name = cp_check_utf8(cp, name_idx); if (value.enum_const.name == NULL) { REPORT_FAILED_CLASS_FORMAT(clss, "invalid const_name_index of annotation enum value: " << name_idx); @@ -611,7 +607,7 @@ void* Class_Member::Alloc(size_t size) { } -bool Class_Member::parse(Class *clss, Const_Pool *cp, unsigned cp_size, ByteReader &cfs) +bool Class_Member::parse(Class *clss, ByteReader &cfs) { if (!cfs.parse_u2_be(&_access_flags)) { REPORT_FAILED_CLASS_FORMAT(clss, "cannot parse member access flags"); @@ -631,12 +627,13 @@ bool Class_Member::parse(Class *clss, Co return false; } + ConstantPool& cp = clss->m_const_pool; // // look up the name_index and descriptor_index // utf8 string const pool entries // - String *name = cp_check_utf8(cp,cp_size,name_index); - String *descriptor = cp_check_utf8(cp,cp_size,descriptor_index); + String* name = cp_check_utf8(cp, name_index); + String* descriptor = cp_check_utf8(cp, descriptor_index); if (name == NULL || descriptor == NULL) { REPORT_FAILED_CLASS_FORMAT(clss, "some of member name or descriptor indexes is not CONSTANT_Utf8 entry : " @@ -740,9 +737,9 @@ check_field_descriptor( const char *desc // DIE( "unreachable code!" ); // exclude remark #111: statement is unreachable } -bool Field::parse(Class *clss, Const_Pool *cp, unsigned cp_size, ByteReader &cfs) +bool Field::parse(Class *clss, ByteReader &cfs) { - if(!Class_Member::parse(clss, cp, cp_size, cfs)) + if(!Class_Member::parse(clss, cfs)) return false; if(!check_field_name(_name)) { @@ -751,7 +748,7 @@ bool Field::parse(Class *clss, Const_Poo } // check field descriptor - const char *next; + const char* next; if(!check_field_descriptor(_descriptor->bytes, &next, false) || *next != '\0') { REPORT_FAILED_CLASS_FORMAT(clss, "illegal field descriptor : " << _descriptor->bytes); return false; @@ -790,9 +787,11 @@ bool Field::parse(Class *clss, Const_Poo uint32 attr_len = 0; + ConstantPool& cp = clss->m_const_pool; + for (unsigned j=0; j= cp_size) { + if(_const_value_index == 0 || _const_value_index >= cp.get_size()) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": invalid ConstantValue index for field " << get_name()); return false; } // type of constant must match field's type - Const_Pool_Tags tag = (Const_Pool_Tags)cp_tag(cp, _const_value_index); + Const_Pool_Tags tag = (Const_Pool_Tags)cp.get_tag(_const_value_index); Java_Type java_type = get_java_type(); @@ -838,8 +837,8 @@ bool Field::parse(Class *clss, Const_Poo << get_name()); return false; } - const_value.l.lo_bytes = cp[_const_value_index].CONSTANT_8byte.low_bytes; - const_value.l.hi_bytes = cp[_const_value_index].CONSTANT_8byte.high_bytes; + const_value.l.lo_bytes = cp.get_8byte_low_word(_const_value_index); + const_value.l.hi_bytes = cp.get_8byte_high_word(_const_value_index); break; } case CONSTANT_Float: @@ -851,7 +850,7 @@ bool Field::parse(Class *clss, Const_Poo << get_name()); return false; } - const_value.f = cp[_const_value_index].float_value; + const_value.f = cp.get_float(_const_value_index); break; } case CONSTANT_Double: @@ -863,8 +862,8 @@ bool Field::parse(Class *clss, Const_Poo << get_name()); return false; } - const_value.l.lo_bytes = cp[_const_value_index].CONSTANT_8byte.low_bytes; - const_value.l.hi_bytes = cp[_const_value_index].CONSTANT_8byte.high_bytes; + const_value.l.lo_bytes = cp.get_8byte_low_word(_const_value_index); + const_value.l.hi_bytes = cp.get_8byte_high_word(_const_value_index); break; } case CONSTANT_Integer: @@ -881,7 +880,7 @@ bool Field::parse(Class *clss, Const_Poo << get_name()); return false; } - const_value.i = cp[_const_value_index].int_value; + const_value.i = cp.get_int(_const_value_index); break; } case CONSTANT_String: @@ -893,7 +892,7 @@ bool Field::parse(Class *clss, Const_Poo << get_name()); return false; } - const_value.string = cp[_const_value_index].CONSTANT_String.string; + const_value.string = cp.get_string(_const_value_index); break; } default: @@ -942,8 +941,8 @@ bool Field::parse(Class *clss, Const_Poo } //Field::parse -bool Handler::parse(Const_Pool* cp, unsigned cp_size, unsigned code_length, - ByteReader &cfs) +bool Handler::parse(ConstantPool& cp, unsigned code_length, + ByteReader& cfs) { uint16 start = 0; if(!cfs.parse_u2_be(&start)) @@ -982,7 +981,7 @@ bool Handler::parse(Const_Pool* cp, unsi if (catch_index == 0) { _catch_type = NULL; } else { - _catch_type = cp_check_class(cp,cp_size,catch_index); + _catch_type = cp_check_class(cp, catch_index); if (_catch_type == NULL) return false; } @@ -1038,8 +1037,8 @@ #define REPORT_FAILED_METHOD(msg) REPORT << _name->bytes << _descriptor->bytes); -bool Method::_parse_exceptions(Const_Pool *cp, unsigned cp_size, unsigned attr_len, - ByteReader &cfs) +bool Method::_parse_exceptions(ConstantPool& cp, unsigned attr_len, + ByteReader& cfs) { if(!cfs.parse_u2_be(&_n_exceptions)) { REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", @@ -1059,7 +1058,7 @@ bool Method::_parse_exceptions(Const_Poo return false; } - _exceptions[i] = cp_check_class(cp,cp_size,index); + _exceptions[i] = cp_check_class(cp, index); if (_exceptions[i] == NULL) { REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", _class->name->bytes << ": exception class index " @@ -1129,7 +1128,7 @@ bool Method::_parse_line_numbers(unsigne bool Method::_parse_local_vars(const char* attr_name, Local_Var_Table** lvt_address, - Const_Pool *cp, unsigned cp_size, unsigned attr_len, ByteReader &cfs) + ConstantPool& cp, unsigned attr_len, ByteReader &cfs) { uint16 n_local_vars; if(!cfs.parse_u2_be(&n_local_vars)) { @@ -1190,14 +1189,14 @@ bool Method::_parse_local_vars(const cha return false; } - String* name = cp_check_utf8(cp,cp_size,name_index); + String* name = cp_check_utf8(cp, name_index); if(name == NULL) { REPORT_FAILED_METHOD("name index is not valid CONSTANT_Utf8 entry " "in " << attr_name << " attribute"); return false; } - String* descriptor = cp_check_utf8(cp,cp_size,descriptor_index); + String* descriptor = cp_check_utf8(cp, descriptor_index); if(descriptor == NULL) { REPORT_FAILED_METHOD("descriptor index is not valid CONSTANT_Utf8 entry " "in " << attr_name << " attribute"); @@ -1233,7 +1232,8 @@ bool Method::_parse_local_vars(const cha } //Method::_parse_local_vars -bool Method::_parse_code( Const_Pool *cp, unsigned cp_size, unsigned code_attr_len, ByteReader &cfs) +bool Method::_parse_code(ConstantPool& cp, unsigned code_attr_len, + ByteReader& cfs) { unsigned real_code_attr_len = 0; if(!cfs.parse_u2_be(&_max_stack)) { @@ -1312,7 +1312,7 @@ bool Method::_parse_code( Const_Pool *cp // ppervov: FIXME: should throw OOME for (i=0; i<_n_handlers; i++) { - if(!_handlers[i].parse(cp, cp_size, _byte_code_length, cfs)) { + if(!_handlers[i].parse(cp, _byte_code_length, cfs)) { REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", _class->name->bytes << ": could not parse exceptions for method " << _name->bytes << _descriptor->bytes); @@ -1338,7 +1338,7 @@ bool Method::_parse_code( Const_Pool *cp uint32 attr_len = 0; for (i=0; im_const_pool; for (unsigned j=0; jconst_pool, clss->cp_size, cfs)) + if(!fd.parse(clss, cfs)) return false; if(fd.is_static()) { clss->fields[clss->n_static_fields] = fd; @@ -1804,7 +1805,7 @@ static bool class_parse_methods(Class *c _total_method_bytes += sizeof(Method)*clss->n_methods; for (unsigned i=0; i < clss->n_methods; i++) { - if (!clss->methods[i].parse(*env, clss, clss->const_pool, clss->cp_size, cfs)) + if(!clss->methods[i].parse(*env, clss, cfs)) return false; Method *m = &clss->methods[i]; @@ -1826,7 +1827,7 @@ static bool class_parse_methods(Class *c } //class_parse_methods -static String* const_pool_parse_utf8data(String_Pool& string_pool, ByteReader& cfs, +static String* class_file_parse_utf8data(String_Pool& string_pool, ByteReader& cfs, uint16 len) { // buffer ends before len @@ -1847,38 +1848,38 @@ static String* const_pool_parse_utf8data } -static String* const_pool_parse_utf8(String_Pool& string_pool, +static String* class_file_parse_utf8(String_Pool& string_pool, ByteReader& cfs) { uint16 len; if(!cfs.parse_u2_be(&len)) return false; - return const_pool_parse_utf8data(string_pool, cfs, len); + return class_file_parse_utf8data(string_pool, cfs, len); } -static bool class_parse_const_pool(Class *clss, - String_Pool& string_pool, - ByteReader &cfs) +bool ConstantPool::parse(Class* clss, + String_Pool& string_pool, + ByteReader& cfs) { - if(!cfs.parse_u2_be(&clss->cp_size)) { + if(!cfs.parse_u2_be(&m_size)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": could not parse constant pool size"); return false; } - unsigned char *cp_tags = new unsigned char[clss->cp_size]; + unsigned char* cp_tags = new unsigned char[m_size]; // ppervov: FIXME: should throw OOME - clss->const_pool = new Const_Pool[clss->cp_size]; + m_entries = new ConstPoolEntry[m_size]; // ppervov: FIXME: should throw OOME // // 0'th constant pool entry is a pointer to the tags array // - clss->const_pool[0].tags = cp_tags; + m_entries[0].tags = cp_tags; cp_tags[0] = CONSTANT_Tags; - for (unsigned i=1; icp_size; i++) { + for(unsigned i = 1; i < m_size; i++) { // parse tag into tag array uint8 tag; if(!cfs.parse_u1(&tag)) { @@ -1887,9 +1888,9 @@ static bool class_parse_const_pool(Class return false; } - switch (cp_tags[i] = tag) { + switch(cp_tags[i] = tag) { case CONSTANT_Class: - if(!cfs.parse_u2_be(&clss->const_pool[i].CONSTANT_Class.name_index)) { + if(!cfs.parse_u2_be(&m_entries[i].CONSTANT_Class.name_index)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": could not parse name index " "for CONSTANT_Class entry"); @@ -1900,12 +1901,12 @@ static bool class_parse_const_pool(Class case CONSTANT_Methodref: case CONSTANT_Fieldref: case CONSTANT_InterfaceMethodref: - if(!cfs.parse_u2_be(&clss->const_pool[i].CONSTANT_ref.class_index)) { + if(!cfs.parse_u2_be(&m_entries[i].CONSTANT_ref.class_index)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": could not parse class index for CONSTANT_*ref entry"); return false; } - if(!cfs.parse_u2_be(&clss->const_pool[i].CONSTANT_ref.name_and_type_index)) { + if(!cfs.parse_u2_be(&m_entries[i].CONSTANT_ref.name_and_type_index)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": could not parse name-and-type index for CONSTANT_*ref entry"); return false; @@ -1913,7 +1914,7 @@ static bool class_parse_const_pool(Class break; case CONSTANT_String: - if(!cfs.parse_u2_be(&clss->const_pool[i].CONSTANT_String.string_index)) { + if(!cfs.parse_u2_be(&m_entries[i].CONSTANT_String.string_index)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": could not parse string index for CONSTANT_String entry"); return false; @@ -1922,7 +1923,7 @@ static bool class_parse_const_pool(Class case CONSTANT_Float: case CONSTANT_Integer: - if(!cfs.parse_u4_be(&clss->const_pool[i].int_value)) { + if(!cfs.parse_u4_be(&m_entries[i].int_value)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": could not parse value for " << (tag==CONSTANT_Integer?"CONSTANT_Integer":"CONSTANT_Float") << " entry"); @@ -1934,13 +1935,13 @@ static bool class_parse_const_pool(Class case CONSTANT_Long: // longs and doubles take up two entries // on both IA32 & IPF, first constant pool element is used, second element - unused - if(!cfs.parse_u4_be(&clss->const_pool[i].CONSTANT_8byte.high_bytes)) { + if(!cfs.parse_u4_be(&m_entries[i].CONSTANT_8byte.high_bytes)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": could not parse high four bytes for " << (tag==CONSTANT_Long?"CONSTANT_Integer":"CONSTANT_Float") << " entry"); return false; } - if(!cfs.parse_u4_be(&clss->const_pool[i].CONSTANT_8byte.low_bytes)) { + if(!cfs.parse_u4_be(&m_entries[i].CONSTANT_8byte.low_bytes)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": could not parse low four bytes for " << (tag==CONSTANT_Long?"CONSTANT_Long":"CONSTANT_Double") << " entry"); @@ -1952,13 +1953,13 @@ static bool class_parse_const_pool(Class break; case CONSTANT_NameAndType: - if(!cfs.parse_u2_be(&clss->const_pool[i].CONSTANT_NameAndType.name_index)) { + if(!cfs.parse_u2_be(&m_entries[i].CONSTANT_NameAndType.name_index)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": could not parse name index " "for CONSTANT_NameAndType entry"); return false; } - if(!cfs.parse_u2_be(&clss->const_pool[i].CONSTANT_NameAndType.descriptor_index)) { + if(!cfs.parse_u2_be(&m_entries[i].CONSTANT_NameAndType.descriptor_index)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": could not parse descriptor index " "for CONSTANT_NameAndType entry"); @@ -1969,13 +1970,13 @@ static bool class_parse_const_pool(Class case CONSTANT_Utf8: { // parse and insert string into string table - String* str = const_pool_parse_utf8(string_pool, cfs); + String* str = class_file_parse_utf8(string_pool, cfs); if(!str) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": could not parse CONTANT_Utf8 entry"); return false; } - clss->const_pool[i].CONSTANT_Utf8.string = str; + m_entries[i].CONSTANT_Utf8.string = str; } break; default: @@ -1985,36 +1986,18 @@ static bool class_parse_const_pool(Class } } return true; -} //class_parse_const_pool +} // ConstantPool::parse -// -// check consistency of constant pool -// -// make sure all indices to other constant pool entries are in range -// make sure contents of constant pool entries are of the right type -// -// Set CONSTANT_Class entries to point directly to String representing -// internal form of fully qualified name of Class. -// -// Set CONSTANT_String entries to point directly to String representation -// of String. -// -// Peresolve CONSTANT_NameAndType entries to signature -// -static bool check_const_pool(Class* clss, - Const_Pool *cp, - unsigned cp_size) +bool ConstantPool::check(Class* clss) { - unsigned char *cp_tags = cp[0].tags; - for (unsigned i=1; i= cp_size || - cp_tag(cp,name_index) != CONSTANT_Utf8) { + unsigned name_index = get_class_name_index(i); + if (!is_valid_index(name_index) || !is_utf8(name_index)) { // illegal name index REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": wrong name index for CONSTANT_Class entry"); @@ -2026,16 +2009,14 @@ static bool check_const_pool(Class* clss case CONSTANT_Fieldref: case CONSTANT_InterfaceMethodref: { - unsigned class_index = cp[i].CONSTANT_ref.class_index; - unsigned name_type_index = cp[i].CONSTANT_ref.name_and_type_index; - if (class_index >= cp_size || - cp_tag(cp,class_index) != CONSTANT_Class) { + unsigned class_index = get_ref_class_index(i); + unsigned name_type_index = get_ref_name_and_type_index(i); + if (!is_valid_index(class_index) || !is_class(class_index)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": wrong class index for CONSTANT_*ref entry"); return false; } - if (name_type_index >= cp_size || - cp_tag(cp,name_type_index) != CONSTANT_NameAndType) { + if (!is_valid_index(name_type_index) || !is_name_and_type(name_type_index)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": wrong name-and-type index for CONSTANT_*ref entry"); return false; @@ -2044,16 +2025,15 @@ static bool check_const_pool(Class* clss } case CONSTANT_String: { - unsigned string_index = cp[i].CONSTANT_String.string_index; - if (string_index >= cp_size || - cp_tag(cp,string_index) != CONSTANT_Utf8) { + unsigned string_index = get_string_index(i); + if (!is_valid_index(string_index) || !is_utf8(string_index)) { // illegal string index REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": wrong string index for CONSTANT_String entry"); return false; } // set entry to the actual string - cp[i].CONSTANT_String.string = cp[string_index].CONSTANT_Utf8.string; + resolve_entry(i, get_utf8_string(string_index)); break; } case CONSTANT_Integer: @@ -2064,23 +2044,19 @@ static bool check_const_pool(Class* clss break; case CONSTANT_NameAndType: { - unsigned name_index = cp[i].CONSTANT_NameAndType.name_index; - unsigned descriptor_index = cp[i].CONSTANT_NameAndType.descriptor_index; - if (name_index >= cp_size || - cp_tag(cp,name_index) != CONSTANT_Utf8) { + unsigned name_index = get_name_and_type_name_index(i); + unsigned descriptor_index = get_name_and_type_descriptor_index(i); + if(!is_valid_index(name_index) || !is_utf8(name_index)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": wrong name index for CONSTANT_NameAndType entry"); return false; } - if (descriptor_index >= cp_size || - cp_tag(cp,descriptor_index) != CONSTANT_Utf8) { + if (!is_valid_index(descriptor_index) || !is_utf8(descriptor_index)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": wrong descriptor index for CONSTANT_NameAndType entry"); return false; } - cp[i].CONSTANT_NameAndType.name = cp[name_index].CONSTANT_Utf8.string; - cp[i].CONSTANT_NameAndType.descriptor = cp[descriptor_index].CONSTANT_Utf8.string; - cp_set_resolved(cp,i); + resolve_entry(i, get_utf8_string(name_index), get_utf8_string(descriptor_index)); break; } case CONSTANT_Utf8: @@ -2088,12 +2064,12 @@ static bool check_const_pool(Class* clss break; default: REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": wrong constant pool tag"); + clss->name->bytes << ": wrong constant pool tag " << get_tag(i)); return false; } } return true; -} //check_const_pool +} // ConstantPool::check static bool class_parse_interfaces(Class *clss, ByteReader &cfs) @@ -2117,7 +2093,7 @@ static bool class_parse_interfaces(Class // // verify that entry in constant pool is of type CONSTANT_Class // - clss->superinterfaces[i].name = cp_check_class(clss->const_pool,clss->cp_size,interface_index); + clss->superinterfaces[i].name = cp_check_class(clss->m_const_pool, interface_index); if (clss->superinterfaces[i].name == NULL) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": constant pool index " << i << " is not CONSTANT_Class entry" @@ -2202,14 +2178,13 @@ bool class_parse(Global_Env* env, /* * allocate and parse constant pool */ - if (!class_parse_const_pool(clss, env->string_pool, cfs)) { + if(!clss->m_const_pool.parse(clss, env->string_pool, cfs)) return false; - } /* * check and preprocess the constant pool */ - if (!check_const_pool(clss, clss->const_pool, clss->cp_size)) + if(!clss->m_const_pool.check(clss)) return false; if(!cfs.parse_u2_be(&clss->access_flags)) { @@ -2236,7 +2211,7 @@ bool class_parse(Global_Env* env, return false; } - String *name = cp_check_class(clss->const_pool, clss->cp_size, this_class); + String *name = cp_check_class(clss->m_const_pool, this_class); if (name == NULL) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": this_class constant pool entry " @@ -2262,7 +2237,7 @@ bool class_parse(Global_Env* env, /* * Mark the current class as resolved. */ - cp_resolve_to_class(clss->const_pool, this_class, clss); + clss->m_const_pool.resolve_entry(this_class, clss); /* * parse the super class name @@ -2288,7 +2263,7 @@ bool class_parse(Global_Env* env, } clss->super_name = NULL; } else { - clss->super_name = cp_check_class(clss->const_pool, clss->cp_size, super_class); + clss->super_name = cp_check_class(clss->m_const_pool, super_class); if (clss->super_name == NULL) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": super_class constant pool entry " @@ -2332,7 +2307,7 @@ bool class_parse(Global_Env* env, uint32 attr_len = 0; for (unsigned i=0; iconst_pool, clss->cp_size, class_attr_strings, class_attrs, &attr_len); + Attributes cur_attr = parse_attribute(cfs, clss->m_const_pool, class_attr_strings, class_attrs, &attr_len); switch(cur_attr){ case ATTR_SourceFile: { @@ -2360,7 +2335,7 @@ bool class_parse(Global_Env* env, return false; } - clss->src_file_name = cp_check_utf8(clss->const_pool,clss->cp_size,filename_index); + clss->src_file_name = cp_check_utf8(clss->m_const_pool, filename_index); if (clss->src_file_name == NULL) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": filename index points to incorrect constant pool entry" @@ -2411,7 +2386,7 @@ bool class_parse(Global_Env* env, return false; } if(inner_clss_info_idx - && cp_tag(clss->const_pool,inner_clss_info_idx) != CONSTANT_Class) + && !valid_cpi(clss, inner_clss_info_idx, CONSTANT_Class)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": inner class info index points to incorrect constant pool entry" @@ -2420,7 +2395,7 @@ bool class_parse(Global_Env* env, } if(!found_myself){ - String *clssname = cp_check_class(clss->const_pool, clss->cp_size, inner_clss_info_idx); + String* clssname = cp_check_class(clss->m_const_pool, inner_clss_info_idx); // Only handle this class if(clss->name == clssname) found_myself = 1; @@ -2436,11 +2411,11 @@ bool class_parse(Global_Env* env, return false; } if(outer_clss_info_idx - && cp_tag(clss->const_pool,outer_clss_info_idx) != CONSTANT_Class) + && !valid_cpi(clss, outer_clss_info_idx, CONSTANT_Class)) { REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", clss->name->bytes << ": outer class info index points to incorrect constant pool entry" - << " while parsing InnerClasses attribute"); + << outer_clss_info_idx << " while parsing InnerClasses attribute"); return false; } if(found_myself == 1 && outer_clss_info_idx){ @@ -2462,7 +2437,7 @@ bool class_parse(Global_Env* env, } if(found_myself == 1 /*&& outer_clss_info_idx*/){ if (inner_name_idx) { - clss->simple_name = clss->const_pool[inner_name_idx].CONSTANT_Utf8.string; + clss->simple_name = clss->m_const_pool.get_utf8_string(inner_name_idx); } else { //anonymous class clss->simple_name = env->string_pool.lookup(""); @@ -2497,7 +2472,7 @@ bool class_parse(Global_Env* env, // cfs is at debug_extension[] which is: // The debug_extension array holds a string, which must be in UTF-8 format. // There is no terminating zero byte. - clss->sourceDebugExtension = const_pool_parse_utf8data(env->string_pool, cfs, attr_len); + clss->sourceDebugExtension = class_file_parse_utf8data(env->string_pool, cfs, attr_len); if (!clss->sourceDebugExtension) { REPORT_FAILED_CLASS_FORMAT(clss, "invalid SourceDebugExtension attribute"); return false; @@ -2811,7 +2786,7 @@ const String* class_extract_name(Global_ if(!cfs.parse_u1(&tag) && tag != CONSTANT_Utf8) return NULL; // parse class name - const String* class_name = const_pool_parse_utf8(env->string_pool, cfs); + const String* class_name = class_file_parse_utf8(env->string_pool, cfs); return class_name; } @@ -2909,7 +2884,7 @@ unsigned class_calculate_size(const Clas unsigned size = 0; size += sizeof(Class); size += klass->n_innerclasses*sizeof(uint16); - size += klass->cp_size*sizeof(Const_Pool); + size += klass->m_const_pool.get_size()*sizeof(ConstPoolEntry); for(unsigned i = 0; i < klass->n_fields; i++) { size += klass->fields[i].calculate_size(); } diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Resolve.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Resolve.cpp index c167b5c..5757126 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Resolve.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Resolve.cpp @@ -19,8 +19,6 @@ * @version $Revision: 1.1.2.6.4.5 $ */ - - // // exceptions that can be thrown during class resolution: // @@ -134,27 +132,25 @@ static Class* _resolve_class(Global_Env unsigned cp_index) { assert(hythread_is_suspend_enabled()); - Const_Pool *cp = clss->const_pool; + ConstantPool& cp = clss->m_const_pool; clss->m_lock->_lock(); - if(cp_in_error(cp, cp_index)) { + if(cp.is_entry_in_error(cp_index)) { TRACE2("resolve:testing", "Constant pool entry " << cp_index << " already contains error."); clss->m_lock->_unlock(); return NULL; } - if(cp_is_resolved(cp, cp_index)) { + if(cp.is_entry_resolved(cp_index)) { clss->m_lock->_unlock(); - return cp[cp_index].CONSTANT_Class.klass; + return cp.get_class_class(cp_index); } - String *classname = cp[cp[cp_index].CONSTANT_Class.name_index].CONSTANT_Utf8.string; + const String* classname = cp.get_utf8_string(cp.get_class_name_index(cp_index)); clss->m_lock->_unlock(); // load the class in - Class *other_clss; - - other_clss = clss->class_loader->LoadVerifyAndPrepareClass(env, classname); + Class* other_clss = clss->class_loader->LoadVerifyAndPrepareClass(env, classname); if(other_clss == NULL) { jthrowable exn = class_get_error(clss->class_loader, classname->bytes); @@ -179,7 +175,7 @@ static Class* _resolve_class(Global_Env || clss->is_not_verified) { clss->m_lock->_lock(); - cp_resolve_to_class(cp, cp_index, other_clss); + cp.resolve_entry(cp_index, other_clss); clss->m_lock->_unlock(); return other_clss; } @@ -190,7 +186,7 @@ static Class* _resolve_class(Global_Env && check_inner_class_access(env, other_clss, clss)) { clss->m_lock->_lock(); - cp_resolve_to_class(cp, cp_index, other_clss); + cp.resolve_entry(cp_index, other_clss); clss->m_lock->_unlock(); return other_clss; } @@ -392,44 +388,42 @@ check_inner_class_access(Global_Env *env */ static Field* _resolve_field(Global_Env *env, Class *clss, unsigned cp_index) { - Const_Pool *cp = clss->const_pool; + ConstantPool& cp = clss->m_const_pool; clss->m_lock->_lock(); - if(cp_in_error(cp, cp_index)) { + if(cp.is_entry_in_error(cp_index)) { TRACE2("resolve.testing", "Constant pool entry " << cp_index << " already contains error."); clss->m_lock->_unlock(); return NULL; } - if (cp_is_resolved(cp, cp_index)) { + if (cp.is_entry_resolved(cp_index)) { clss->m_lock->_unlock(); - return cp[cp_index].CONSTANT_ref.field; + return cp.get_ref_field(cp_index); } // // constant pool entry hasn't been resolved yet // - unsigned other_index = cp[cp_index].CONSTANT_ref.class_index; + unsigned other_index = cp.get_ref_class_index(cp_index); clss->m_lock->_unlock(); // // check error condition from resolve class // - Class *other_clss = _resolve_class(env, clss, other_index); + Class* other_clss = _resolve_class(env, clss, other_index); if(!other_clss) { - if(cp_in_error(clss->const_pool, other_index)) { - class_report_failure(clss, cp_index, - (jthrowable)(&(clss->const_pool[other_index].error.cause))); + if(cp.is_entry_in_error(other_index)) { + class_report_failure(clss, cp_index, + cp.get_error_cause(other_index)); } else { assert(exn_raised()); } return NULL; } - String* name = cp[cp[cp_index].CONSTANT_ref.name_and_type_index] - .CONSTANT_NameAndType.name; - String* desc = cp[cp[cp_index].CONSTANT_ref.name_and_type_index] - .CONSTANT_NameAndType.descriptor; - + uint16 name_and_type_index = cp.get_ref_name_and_type_index(cp_index); + String* name = cp.get_name_and_type_name(name_and_type_index); + String* desc = cp.get_name_and_type_descriptor(name_and_type_index); Field* field = class_lookup_field_recursive(other_clss, name, desc); if (field == NULL) { @@ -460,7 +454,7 @@ static Field* _resolve_field(Global_Env return NULL; } clss->m_lock->_lock(); - cp_resolve_to_field(cp, cp_index, field); + cp.resolve_entry(cp_index, field); clss->m_lock->_unlock(); return field; @@ -538,24 +532,24 @@ static Field* _resolve_nonstatic_field(G */ static Method* _resolve_method(Global_Env *env, Class *clss, unsigned cp_index) { - Const_Pool *cp = clss->const_pool; + ConstantPool& cp = clss->m_const_pool; clss->m_lock->_lock(); - if(cp_in_error(cp, cp_index)) { + if(cp.is_entry_in_error(cp_index)) { TRACE2("resolve:testing", "Constant pool entry " << cp_index << " already contains error."); clss->m_lock->_unlock(); return NULL; } - if (cp_is_resolved(cp,cp_index)) { + if (cp.is_entry_resolved(cp_index)) { clss->m_lock->_unlock(); - return cp[cp_index].CONSTANT_ref.method; + return cp.get_ref_method(cp_index); } // // constant pool entry hasn't been resolved yet // unsigned other_index; - other_index = cp[cp_index].CONSTANT_ref.class_index; + other_index = cp.get_ref_class_index(cp_index); clss->m_lock->_unlock(); // @@ -563,24 +557,22 @@ static Method* _resolve_method(Global_En // Class *other_clss = _resolve_class(env, clss, other_index); if(!other_clss) { - if(cp_in_error(clss->const_pool, other_index)) { + if(cp.is_entry_in_error(other_index)) { class_report_failure(clss, cp_index, - (jthrowable)(&(clss->const_pool[other_index].error.cause))); + cp.get_error_cause(other_index)); } else { assert(exn_raised()); } return NULL; } - String* name = cp[cp[cp_index].CONSTANT_ref.name_and_type_index]. - CONSTANT_NameAndType.name; - - String* desc = cp[cp[cp_index].CONSTANT_ref.name_and_type_index]. - CONSTANT_NameAndType.descriptor; + uint16 name_and_type_index = cp.get_ref_name_and_type_index(cp_index); + String* name = cp.get_name_and_type_name(name_and_type_index); + String* desc = cp.get_name_and_type_descriptor(name_and_type_index); // CONSTANT_Methodref must refer to a class, not an interface, and // CONSTANT_InterfaceMethodref must refer to an interface (vm spec 4.4.2) - if (cp_is_methodref(cp, cp_index) && class_is_interface(other_clss)) { + if(cp.is_methodref(cp_index) && class_is_interface(other_clss)) { CLASS_REPORT_FAILURE(clss, cp_index, "java/lang/IncompatibleClassChangeError", other_clss->name->bytes << " while resolving constant pool entry " << cp_index @@ -588,7 +580,7 @@ static Method* _resolve_method(Global_En return NULL; } - if(cp_is_interfacemethodref(cp, cp_index) && !class_is_interface(other_clss)) { + if(cp.is_interfacemethodref(cp_index) && !class_is_interface(other_clss)) { CLASS_REPORT_FAILURE(clss, cp_index, "java/lang/IncompatibleClassChangeError", other_clss->name->bytes << " while resolving constant pool entry " << cp_index @@ -628,7 +620,7 @@ static Method* _resolve_method(Global_En } clss->m_lock->_lock(); - cp_resolve_to_method(cp,cp_index,method); + cp.resolve_entry(cp_index, method); clss->m_lock->_unlock(); return method; @@ -771,9 +763,10 @@ static bool method_can_link_special(Clas { ASSERT_RAISE_AREA; - unsigned class_idx = clss->const_pool[index].CONSTANT_ref.class_index; - unsigned class_name_idx = clss->const_pool[class_idx].CONSTANT_Class.name_index; - String* ref_class_name = clss->const_pool[class_name_idx].CONSTANT_String.string; + ConstantPool& cp = clss->m_const_pool; + unsigned class_idx = cp.get_ref_class_index(index); + unsigned class_name_idx = cp.get_class_name_index(class_idx); + String* ref_class_name = cp.get_utf8_string(class_name_idx); if(method->get_name() == VM_Global_State::loader_env->Init_String && method->get_class()->name != ref_class_name) @@ -918,46 +911,46 @@ void class_throw_linking_error(Class_Han { ASSERT_RAISE_AREA; - Const_Pool* cp = ch->const_pool; - if(cp_in_error(cp, index)) { - exn_raise_object((jthrowable)(&(cp[index].error.cause))); + ConstantPool& cp = ch->m_const_pool; + if(cp.is_entry_in_error(index)) { + exn_raise_object(cp.get_error_cause(index)); return; // will return in interpreter mode } switch(opcode) { case OPCODE_NEW: - class_can_instantiate(cp[index].CONSTANT_Class.klass, LINK_THROW_ERRORS); + class_can_instantiate(cp.get_class_class(index), LINK_THROW_ERRORS); break; case OPCODE_PUTFIELD: - field_can_link(ch, cp[index].CONSTANT_ref.field, + field_can_link(ch, cp.get_ref_field(index), CAN_LINK_FROM_FIELD, LINK_WRITE_ACCESS, LINK_THROW_ERRORS); break; case OPCODE_GETFIELD: - field_can_link(ch, cp[index].CONSTANT_ref.field, + field_can_link(ch, cp.get_ref_field(index), CAN_LINK_FROM_FIELD, LINK_READ_ACCESS, LINK_THROW_ERRORS); break; case OPCODE_PUTSTATIC: - field_can_link(ch, cp[index].CONSTANT_ref.field, + field_can_link(ch, cp.get_ref_field(index), CAN_LINK_FROM_STATIC, LINK_WRITE_ACCESS, LINK_THROW_ERRORS); break; case OPCODE_GETSTATIC: - field_can_link(ch, cp[index].CONSTANT_ref.field, + field_can_link(ch, cp.get_ref_field(index), CAN_LINK_FROM_STATIC, LINK_READ_ACCESS, LINK_THROW_ERRORS); break; case OPCODE_INVOKEINTERFACE: - method_can_link_interface(ch, index, cp[index].CONSTANT_ref.method, + method_can_link_interface(ch, index, cp.get_ref_method(index), LINK_THROW_ERRORS); break; case OPCODE_INVOKESPECIAL: - method_can_link_special(ch, index, cp[index].CONSTANT_ref.method, + method_can_link_special(ch, index, cp.get_ref_method(index), LINK_THROW_ERRORS); break; case OPCODE_INVOKESTATIC: - method_can_link_static(ch, index, cp[index].CONSTANT_ref.method, + method_can_link_static(ch, index, cp.get_ref_method(index), LINK_THROW_ERRORS); break; case OPCODE_INVOKEVIRTUAL: - method_can_link_virtual(ch, index, cp[index].CONSTANT_ref.method, + method_can_link_virtual(ch, index, cp.get_ref_method(index), LINK_THROW_ERRORS); break; default: @@ -1023,16 +1016,14 @@ Class_Handle class_get_array_of_class(Cl } //class_get_array_of_class -static bool resolve_const_pool_item(Global_Env *env, Class *clss, unsigned cp_index) +static bool resolve_const_pool_item(Global_Env* env, Class* clss, unsigned cp_index) { - Const_Pool *cp = clss->const_pool; - unsigned char *cp_tags = cp[0].tags; + ConstantPool& cp = clss->m_const_pool; - if (cp_is_resolved(cp, cp_index)) { + if(cp.is_entry_resolved(cp_index)) return true; - } - switch (cp_tags[cp_index]) { + switch(cp.get_tag(cp_index)) { case CONSTANT_Class: return _resolve_class(env, clss, cp_index); case CONSTANT_Fieldref: @@ -1060,12 +1051,12 @@ static bool resolve_const_pool_item(Glob * Resolve whole constant pool */ unsigned resolve_const_pool(Global_Env& env, Class *clss) { - Const_Pool *cp = clss->const_pool; + ConstantPool& cp = clss->m_const_pool; // It's possible that cp is null when defining class on the fly - if (!cp) return true; - unsigned cp_size = clss->cp_size; + if(!cp.available()) return true; + unsigned cp_size = cp.get_size(); for (unsigned i = 1; i < cp_size; i++) { if(!resolve_const_pool_item(&env, clss, i)) { return i; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/class_impl.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/class_impl.cpp index 1e44d49..ea2ddb6 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/class_impl.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/class_impl.cpp @@ -203,9 +203,9 @@ class_get_method( class_handler klass, u unsigned short class_get_cp_size( class_handler klass ) { - assert( klass ); - Class *clss = (Class*)klass; - return clss->cp_size; + assert(klass); + Class* clss = (Class*)klass; + return clss->m_const_pool.get_size(); } // class_get_cp_size /** @@ -215,9 +215,9 @@ unsigned char class_get_cp_tag( class_handler klass, unsigned short index ) { assert( klass ); - Class *clss = (Class*)klass; - assert( index < clss->cp_size ); - return (unsigned char)cp_tag( clss->const_pool, index ); + Class* clss = (Class*)klass; + assert( index < clss->m_const_pool.get_size() ); + return clss->m_const_pool.get_tag(index); } // class_get_cp_tag /** @@ -227,10 +227,8 @@ unsigned short class_get_cp_class_name_index( class_handler klass, unsigned short index ) { assert( klass ); - Class *clss = (Class*)klass; - assert( index < clss->cp_size ); - assert( cp_is_class( clss->const_pool, index ) ); - return clss->const_pool[index].CONSTANT_Class.name_index; + Class* clss = (Class*)klass; + return clss->m_const_pool.get_class_name_index(index); } // class_get_cp_class_name_index /** @@ -241,11 +239,7 @@ class_get_cp_ref_class_index( class_hand { assert( klass ); Class *clss = (Class*)klass; - assert( index < clss->cp_size ); - assert( cp_is_fieldref( clss->const_pool, index ) - || cp_is_methodref( clss->const_pool, index ) - || cp_is_interfacemethodref( clss->const_pool, index ) ); - return clss->const_pool[index].CONSTANT_ref.class_index; + return clss->m_const_pool.get_ref_class_index(index); } // class_get_cp_ref_class_index /** @@ -256,24 +250,18 @@ class_get_cp_ref_name_and_type_index( cl { assert( klass ); Class *clss = (Class*)klass; - assert( index < clss->cp_size ); - assert( cp_is_fieldref( clss->const_pool, index ) - || cp_is_methodref( clss->const_pool, index ) - || cp_is_interfacemethodref( clss->const_pool, index ) ); - return clss->const_pool[index].CONSTANT_ref.name_and_type_index; + return clss->m_const_pool.get_ref_name_and_type_index(index); } // class_get_cp_ref_name_and_type_index /** * Function returns string entry index in constant pool. */ unsigned short -class_get_cp_string_index( class_handler klass, unsigned short index ) +class_get_cp_string_index(class_handler klass, unsigned short index) { - assert( klass ); - Class *clss = (Class*)klass; - assert( index < clss->cp_size ); - assert( cp_is_string( clss->const_pool, index ) ); - return clss->const_pool[index].CONSTANT_String.string_index; + assert(klass); + Class* clss = (Class*)klass; + return clss->m_const_pool.get_string_index(index); } // class_get_cp_string_index /** @@ -283,10 +271,8 @@ unsigned short class_get_cp_name_index( class_handler klass, unsigned short index ) { assert( klass ); - Class *clss = (Class*)klass; - assert( index < clss->cp_size ); - assert( cp_tag( clss->const_pool, index ) == CONSTANT_NameAndType ); - return clss->const_pool[index].CONSTANT_NameAndType.name_index; + Class* clss = (Class*)klass; + return clss->m_const_pool.get_name_and_type_name_index(index); } // class_get_cp_name_index /** @@ -296,23 +282,19 @@ unsigned short class_get_cp_descriptor_index( class_handler klass, unsigned short index ) { assert( klass ); - Class *clss = (Class*)klass; - assert( index < clss->cp_size ); - assert( cp_tag( clss->const_pool, index ) == CONSTANT_NameAndType ); - return clss->const_pool[index].CONSTANT_NameAndType.descriptor_index; + Class* clss = (Class*)klass; + return clss->m_const_pool.get_name_and_type_descriptor_index(index); } // class_get_cp_descriptor_index /** * Function returns bytes for UTF8 constant pool entry. */ -const char * +const char* class_get_cp_utf8_bytes( class_handler klass, unsigned short index ) { assert( klass ); - Class *clss = (Class*)klass; - assert( index < clss->cp_size ); - assert( cp_tag( clss->const_pool, index ) == CONSTANT_Utf8 ); - return clss->const_pool[index].CONSTANT_Utf8.string->bytes; + Class* clss = (Class*)klass; + return clss->m_const_pool.get_utf8_chars(index); } // class_get_cp_utf8_bytes /** diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp index 18c7498..81a9187 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp @@ -479,8 +479,8 @@ bool ClassLoader::FinishLoadingClass(Glo // super class was successfully loaded clss->super_class = superClass; - if( super_class_cp_index && *super_class_cp_index ) { - cp_resolve_to_class( clss->const_pool, *super_class_cp_index, superClass ); + if(super_class_cp_index && *super_class_cp_index) { + clss->m_const_pool.resolve_entry(*super_class_cp_index, superClass); } // if it's an interface, its superclass must be java/lang/Object @@ -1150,6 +1150,9 @@ #endif clss->id = class_next_id++; clss->name = name; clss->class_loader = this; + + clss->m_const_pool.init(); + clss->state = ST_Start; clss->m_lock = new Lock_Manager(); @@ -1174,13 +1177,7 @@ void ClassLoader::ClassClearInternals(Cl delete []clss->methods; clss->methods = NULL; } - if (clss->const_pool != NULL) - { - if (clss->const_pool[0].tags) - delete []clss->const_pool[0].tags; - delete []clss->const_pool; - clss->const_pool = NULL; - } + clss->m_const_pool.clear(); if (clss->vtable_descriptors) delete []clss->vtable_descriptors; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method.cpp index 857e37d..38bf941 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method.cpp @@ -31,6 +31,7 @@ #include "nogc.h" #include "open/vm_util.h" #include "jit_intf_cpp.h" #include "atomics.h" +#include "cci.h" #ifdef _IPF_ #include "vm_ipf.h" diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method_lookup.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method_lookup.cpp index 8e7452a..93f62d3 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method_lookup.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method_lookup.cpp @@ -29,6 +29,8 @@ #include #include "lock_manager.h" #include "nogc.h" #include "vm_stats.h" +#include "cci.h" +#include "class_member.h" #include "method_lookup.h" diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp index 55254e4..f8c53eb 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp @@ -34,6 +34,7 @@ #include "m2n.h" #include "object_handles.h" #include "vm_arrays.h" #include "vm_strings.h" +#include "cci.h" bool exn_raised() diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp index 3b5027a..4ea2e8f 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp @@ -42,6 +42,7 @@ #include "mon_enter_exit.h" #include "stack_iterator.h" #include "vm_stats.h" #include "jvmti_break_intf.h" +#include "cci.h" #ifdef _IPF_ #elif defined _EM64T_ diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/gc/dll_gc.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/gc/dll_gc.cpp index 4809bfc..a4b21ea 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/gc/dll_gc.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/gc/dll_gc.cpp @@ -19,8 +19,6 @@ * @version $Revision: 1.1.2.2.4.3 $ */ - - #define LOG_DOMAIN "vm.core" #include "cxxlog.h" diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/gc/root_set_enum_common.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/gc/root_set_enum_common.cpp index e7f7f97..a7d7fb9 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/gc/root_set_enum_common.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/gc/root_set_enum_common.cpp @@ -30,6 +30,7 @@ #include "vm_stats.h" #include "m2n.h" #include "open/vm_util.h" #include "finalize.h" +#include "cci.h" static void vm_enumerate_interned_strings() @@ -87,7 +88,7 @@ vm_enumerate_static_fields() (void**)&c->p_error ,FALSE); } vm_enumerate_root_reference((void**)ppc, FALSE); - Const_Pool* cp = c->m_failedResolution; + ConstPoolEntry* cp = c->m_const_pool.get_error_chain(); while(cp) { vm_enumerate_root_reference((void**)(&(cp->error.cause)), FALSE); cp = cp->error.next; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp index 87b313c..c1cf2ac 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp @@ -121,8 +121,9 @@ Class *class_resolve_class(Class *clss, // a constant of type Class, String, Integer, Float, Long or Double. Java_Type class_get_cp_const_type(Class *clss, unsigned cp_index) { - Const_Pool *cp = clss->const_pool; - switch(cp_tag(cp, cp_index)) { + ConstantPool& cp = clss->m_const_pool; + assert(cp.is_constant(cp_index)); + switch(cp.get_tag(cp_index)) { case CONSTANT_String: return JAVA_TYPE_STRING; case CONSTANT_Integer: @@ -136,7 +137,7 @@ Java_Type class_get_cp_const_type(Class case CONSTANT_Class: return JAVA_TYPE_CLASS; default: - DIE("non-constant type is requested from constant pool : " << cp_tag(cp, cp_index)); + DIE("non-constant type is requested from constant pool : " << cp.get_tag(cp_index)); } return JAVA_TYPE_INVALID; } //class_get_cp_const_type @@ -144,13 +145,10 @@ Java_Type class_get_cp_const_type(Class // Returns an address of an int, float, etc. -// For a string it returns a pointer to the utf8 representation of the string. -const void *class_get_addr_of_constant(Class *clss, unsigned cp_index) +const void* class_get_addr_of_constant(Class* clss, unsigned cp_index) { - Const_Pool *cp = clss->const_pool; - assert(cp_tag(cp, cp_index) != CONSTANT_String); - - return (void *)(cp + cp_index); + ConstantPool& cp = clss->m_const_pool; + return cp.get_address_of_constant(cp_index); } //class_get_addr_of_constant ///////////////////////////////////////////////////////////////// diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp index e6505af..709f1c0 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp @@ -38,6 +38,7 @@ #include "lil_code_generator.h" #include "stack_iterator.h" #include "interpreter.h" #include "jvmti_break_intf.h" +#include "cci.h" #include "vm_stats.h" #include "dump.h" @@ -75,7 +76,6 @@ CodeChunkInfo::CodeChunkInfo() _relocatable = TRUE; _num_target_exception_handlers = 0; _target_exception_handlers = NULL; - _has_been_loaded_for_vtune = false; _callee_info = _static_callee_info; _max_callees = NUM_STATIC_CALLEE_ENTRIES; _num_callees = 0; @@ -86,7 +86,6 @@ CodeChunkInfo::CodeChunkInfo() _jit_info_block_size = 0; _code_block_alignment = 0; _data_blocks = NULL; - _dynopt_info = NULL; _next = NULL; #ifdef VM_STATS num_throws = 0; @@ -96,35 +95,37 @@ #ifdef VM_STATS #endif } //CodeChunkInfo::CodeChunkInfo - -void CodeChunkInfo::initialize_code_chunk(CodeChunkInfo *chunk) +int CodeChunkInfo::get_jit_index() const { - memset(chunk, 0, sizeof(CodeChunkInfo)); - chunk->_callee_info = chunk->_static_callee_info; - chunk->_max_callees = NUM_STATIC_CALLEE_ENTRIES; - chunk->_relocatable = TRUE; -} //CodeChunkInfo::initialize_code_chunk - - + return get_index_of_jit(_jit); +} -unsigned CodeChunkInfo::get_num_target_exception_handlers() +unsigned CodeChunkInfo::get_num_target_exception_handlers() const { if (_id==0) { return _num_target_exception_handlers; } else { return _method->get_num_target_exception_handlers(_jit); } -} //get_num_target_exception_handlers - +} -Target_Exception_Handler_Ptr CodeChunkInfo::get_target_exception_handler_info(unsigned eh_num) +Target_Exception_Handler_Ptr CodeChunkInfo::get_target_exception_handler_info(unsigned eh_num) const { if (_id==0) { return _target_exception_handlers[eh_num]; } else { return _method->get_target_exception_handler_info(_jit, eh_num); } -} //get_target_exception_handler_info +} + + +//void CodeChunkInfo::initialize_code_chunk(CodeChunkInfo *chunk) +//{ +// memset(chunk, 0, sizeof(CodeChunkInfo)); +// chunk->_callee_info = chunk->_static_callee_info; +// chunk->_max_callees = NUM_STATIC_CALLEE_ENTRIES; +// chunk->_relocatable = TRUE; +//} //CodeChunkInfo::initialize_code_chunk // 20040224 Support for recording which methods (actually, CodeChunkInfo's) call which other methods. @@ -179,10 +180,10 @@ void CodeChunkInfo::record_call_to_calle } //CodeChunkInfo::record_call_to_callee -uint64 CodeChunkInfo::num_calls_to(CodeChunkInfo *other_chunk) +uint64 CodeChunkInfo::num_calls_to(CodeChunkInfo *other_chunk) const { assert(other_chunk); - for (unsigned i = 0; i < _num_callees; i++) { + for (unsigned i = 0; i < _num_callees; i++) { Callee_Info *info = &(_callee_info[i]); CodeChunkInfo *callee = info->callee; assert(callee); @@ -195,7 +196,7 @@ uint64 CodeChunkInfo::num_calls_to(CodeC } //CodeChunkInfo::num_calls_to -void CodeChunkInfo::print_name() +void CodeChunkInfo::print_name() const { Method *meth = get_method(); assert(meth); @@ -206,7 +207,7 @@ void CodeChunkInfo::print_name() } //CodeChunkInfo::print_name -void CodeChunkInfo::print_name(FILE *file) +void CodeChunkInfo::print_name(FILE *file) const { Method *meth = get_method(); assert(meth); @@ -217,7 +218,7 @@ void CodeChunkInfo::print_name(FILE *fil } //CodeChunkInfo::print_name -void CodeChunkInfo::print_info(bool print_ellipses) +void CodeChunkInfo::print_info(bool print_ellipses) const { size_t code_size = get_code_block_size(); print_name(); @@ -225,12 +226,12 @@ void CodeChunkInfo::print_info(bool prin } //CodeChunkInfo::print_info -void CodeChunkInfo::print_callee_info() +void CodeChunkInfo::print_callee_info() const { - for (unsigned i = 0; i < _num_callees; i++) { + for (unsigned i = 0; i < _num_callees; i++) { Callee_Info *info = &(_callee_info[i]); - // Don't print the "back edges" (e.g., b calls a whenever a calls b) added to make the graph symmetric - if (info->caller_ip != NULL) { + // Don't print the "back edges" (e.g., b calls a whenever a calls b) added to make the graph symmetric + if (info->caller_ip != NULL) { CodeChunkInfo *callee = info->callee; assert(callee); unsigned call_offset = (unsigned)((char *)info->caller_ip - (char *)_code_block); @@ -238,11 +239,10 @@ void CodeChunkInfo::print_callee_info() printf("%10" FMT64 "u calls at %u to ", info->num_calls, call_offset); callee->print_name(); printf("\n"); - } + } } } //CodeChunkInfo::print_callee_info - // end CodeChunkInfo //////////////////////////////////////////////////////////////////////// diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jit/jit_runtime_support.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jit/jit_runtime_support.cpp index db96a68..78865c3 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jit/jit_runtime_support.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jit/jit_runtime_support.cpp @@ -71,6 +71,9 @@ #include "vm_stats.h" #define OFFSET(Struct, Field) \ ((POINTER_SIZE_SINT) (&(((Struct *) NULL)->Field) - NULL)) +#define OFFSET_INST(inst_ptr, Field) \ + ((POINTER_SIZE_SINT) ((char*)inst_ptr->Field - (char*)inst_ptr)) + // macro that gets the size of a field within a struct or class #define SIZE(Struct, Field) \ (sizeof(((Struct *) NULL)->Field)) @@ -157,12 +160,12 @@ static NativeCodePtr rth_get_lil_multian static ManagedObject * rth_ldc_ref_helper(Class *c, unsigned cp_index) { ASSERT_THROW_AREA; - Const_Pool *cp = c->const_pool; - if (cp_is_string(cp, cp_index)) + ConstantPool& cp = c->m_const_pool; + if (cp.is_string(cp_index)) { return vm_instantiate_cp_string_slow(c, cp_index); } - else if (cp_is_class(cp, cp_index)) + else if (cp.is_class(cp_index)) { assert(!hythread_is_suspend_enabled()); hythread_suspend_enable(); @@ -263,8 +266,9 @@ static LilCodeStub* rth_gen_lil_type_tes } // Fast sequence - const POINTER_SIZE_INT is_fast_off = (POINTER_SIZE_INT)&((Class*)NULL)->is_suitable_for_fast_instanceof; - const POINTER_SIZE_INT depth_off = (POINTER_SIZE_INT)&((Class*)NULL)->depth; + Class* dummy = NULL; + const POINTER_SIZE_INT is_fast_off = OFFSET_INST(dummy, is_suitable_for_fast_instanceof); + const POINTER_SIZE_INT depth_off = OFFSET_INST(dummy, depth); const POINTER_SIZE_INT supertable_off = (POINTER_SIZE_INT)&((VTable*)NULL)->superclasses; bool do_slow = true; if (type) { @@ -2410,12 +2414,13 @@ static LilCodeStub* gen_lil_typecheck_fa object_get_vtable_offset()); } + Class* dummy = NULL; cs2 = lil_parse_onto_end (cs2, "ld l1, [i1 + %0i: g4],zx;" "ld l2, [l0 + %1i*l1 + %2i: pint];" "jc i1 != l2, failed;", - OFFSET(Class, depth), + OFFSET_INST(dummy, depth), sizeof(Class*), OFFSET(VTable, superclasses) - sizeof(Class*) + (vm_vtable_pointers_are_compressed() ? vm_get_vtable_base() : 0) ); @@ -2483,6 +2488,7 @@ LilCodeStub *gen_lil_typecheck_stub(bool Class::managed_null); } + Class* dummy = NULL; // check whether the fast or the slow path is appropriate cs = lil_parse_onto_end (cs, @@ -2491,7 +2497,7 @@ LilCodeStub *gen_lil_typecheck_stub(bool // check if super->is_suitable_for_fast_instanceof "ld l0, [i1 + %0i: g4];" "jc l0!=0:g4, fast;", - OFFSET(Class, is_suitable_for_fast_instanceof)); + OFFSET_INST(dummy, is_suitable_for_fast_instanceof)); // append the slow path right here cs = gen_lil_typecheck_slowpath(cs, is_checkcast); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break.cpp index e7879aa..2c210d6 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break.cpp @@ -28,6 +28,7 @@ #include "jvmti_internal.h" #include "environment.h" #include "Class.h" #include "cxxlog.h" +#include "cci.h" #include "suspend_checker.h" #include "interpreter_exports.h" diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break_intf.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break_intf.cpp index 8770425..6be7160 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break_intf.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break_intf.cpp @@ -34,6 +34,8 @@ #include "exceptions.h" #include "m2n.h" #include "stack_iterator.h" #include "open/bytecodes.h" +#include "cci.h" + #include "jvmti_break_intf.h" diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp index 85f194b..28fe55a 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp @@ -36,6 +36,7 @@ #include "open/jthread.h" #include "suspend_checker.h" #include "jit_intf_cpp.h" #include "vm_log.h" +#include "cci.h" #include "compile.h" #include "jvmti_break_intf.h" #include "stack_iterator.h" diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_locals.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_locals.cpp index 50a1b5c..3e8137a 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_locals.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_locals.cpp @@ -36,6 +36,8 @@ #include "suspend_checker.h" #include "stack_iterator.h" #include "stack_trace.h" #include "jit_intf_cpp.h" +#include "cci.h" +#include "Class.h" /* * Local Variable functions: diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp index 8b60f41..5fa263c 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp @@ -32,6 +32,7 @@ #include "m2n.h" #include "mon_enter_exit.h" #include "stack_iterator.h" #include "jvmti_break_intf.h" +#include "cci.h" #include "clog.h" static void jvmti_pop_frame_callback() diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_stack.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_stack.cpp index ae9e0cd..c7a002a 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_stack.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_stack.cpp @@ -36,6 +36,7 @@ #include "stack_trace.h" #include "stack_iterator.h" #include "jit_intf_cpp.h" #include "thread_manager.h" +#include "cci.h" static JNIEnv * jvmti_test_jenv = jni_native_intf; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp index d29ef32..64ef735 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp @@ -28,6 +28,7 @@ #include "jit_intf_cpp.h" #include "stack_iterator.h" #include "interpreter.h" #include "method_lookup.h" +#include "cci.h" #include "open/bytecodes.h" #include "open/jthread.h" #include "jvmti_break_intf.h" @@ -316,13 +317,13 @@ jvmti_SingleStepLocation( VM_thread* thr { unsigned short index = jvmti_GetHalfWordValue( bytecode, location + 1 ); Class *klass = method_get_class( method ); - assert( cp_is_resolved(klass->const_pool, index) ); + assert(klass->m_const_pool.is_entry_resolved(index)); - if( !method_is_native( klass->const_pool[index].CONSTANT_ref.method ) ) { + if(!method_is_native(klass->m_const_pool.get_ref_method(index))) { *count = 1; error = _allocate( sizeof(jvmti_StepLocation), (unsigned char**)next_step ); assert( error == JVMTI_ERROR_NONE ); - (*next_step)->method = klass->const_pool[index].CONSTANT_ref.method; + (*next_step)->method = klass->m_const_pool.get_ref_method(index); (*next_step)->location = 0; (*next_step)->native_location = NULL; (*next_step)->no_event = false; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_thread.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_thread.cpp index e229bd0..943d408 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_thread.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_thread.cpp @@ -42,6 +42,8 @@ #include "suspend_checker.h" #include "stack_iterator.h" +#include "Class.h" // FIXME: this is for Class::heap_base and Class::heap_end + #define MAX_JVMTI_ENV_NUMBER 10 static JNIEnv * jvmti_test_jenv = jni_native_intf; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_thread_group.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_thread_group.cpp index abf039b..190fc95 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_thread_group.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_thread_group.cpp @@ -29,6 +29,7 @@ #include "open/vm_util.h" #include "cxxlog.h" #include "suspend_checker.h" #include "environment.h" +#include "Class.h" static JNIEnv_Internal * jvmti_test_jenv = jni_native_intf; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.cpp index 60b9e79..6b91430 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.cpp @@ -604,15 +604,15 @@ (JNIEnv *jenv, jclass, jclass jclazz) { assert(jclazz); Class* clazz = jclass_to_struct_Class(jclazz); - unsigned m_idx = clazz->enclosing_method_index; - if (m_idx) { + unsigned method_idx = clazz->enclosing_method_index; + if (method_idx) { unsigned c_idx = clazz->enclosing_class_index; ASSERT(c_idx, "No class for enclosing method"); Class* outer_clss = class_resolve_class(clazz, c_idx); if (outer_clss) { - String* name = clazz->const_pool[m_idx].CONSTANT_NameAndType.name; - String* desc = clazz->const_pool[m_idx].CONSTANT_NameAndType.descriptor; + String* name = clazz->m_const_pool.get_name_and_type_name(method_idx); + String* desc = clazz->m_const_pool.get_name_and_type_descriptor(method_idx); TRACE("Looking for enclosing method: class="<name->bytes <<"; name="<bytes<<"; desc="<bytes); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_reflect_VMReflection.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_reflect_VMReflection.cpp index 7bc1d02..d56fec8 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_reflect_VMReflection.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_reflect_VMReflection.cpp @@ -36,6 +36,7 @@ #include "exceptions.h" #include "vm_strings.h" #include "primitives_support.h" #include "jni_utils.h" +#include "Class.h" #include "java_lang_VMClassRegistry.h" #include "java_lang_reflect_VMReflection.h" diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/object/object_handles.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/object/object_handles.cpp index 477a9b6..7027431 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/object/object_handles.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/object/object_handles.cpp @@ -37,6 +37,7 @@ #include "vm_threads.h" #include "thread_manager.h" #include "open/types.h" #include "open/vm_util.h" +#include "vtable.h" static ObjectHandlesOld* oh_allocate_object_handle(); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/stack/stack_dump.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/stack/stack_dump.cpp index 93aef97..d93b4c2 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/stack/stack_dump.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/stack/stack_dump.cpp @@ -25,7 +25,9 @@ #include "vm_threads.h" #include "port_malloc.h" #include "jit_intf_cpp.h" #include "Class.h" +#include "class_member.h" #include "stack_trace.h" +#include "cci.h" #ifdef PLATFORM_NT diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/stack/stack_trace.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/stack/stack_trace.cpp index a4e2cf1..e051969 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/stack/stack_trace.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/stack/stack_trace.cpp @@ -27,6 +27,8 @@ #include "interpreter.h" #include "jit_intf_cpp.h" #include "method_lookup.h" +#include "cci.h" +#include "class_member.h" void get_file_and_line(Method_Handle mh, void *ip, bool is_ip_past, const char **file, int *line) { Method *method = (Method*)mh; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_dump.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_dump.cpp index 3a5be10..2d3dcb0 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_dump.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_dump.cpp @@ -30,9 +30,12 @@ #include "jit_intf_cpp.h" #include "dll_jit_intf.h" #include "object_generic.h" +#include "Class.h" +#include "vtable.h" #include "root_set_enum_internal.h" #include "lock_manager.h" #include "open/gc.h" +#include "cci.h" #define LOG_DOMAIN "thread_dump" #include "cxxlog.h" diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp index 94374ec..f67e3c8 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp @@ -589,20 +589,17 @@ jstring String_to_interned_jstring(Strin } -Java_java_lang_String * -vm_instantiate_cp_string_slow(Class *c, unsigned cp_index) +Java_java_lang_String* +vm_instantiate_cp_string_slow(Class* c, unsigned cp_index) { ASSERT_THROW_AREA; #ifdef VM_STATS VM_Statistics::get_vm_stats().num_instantiate_cp_string_slow++; #endif - Java_java_lang_String *result; - assert(cp_index < c->cp_size); - Const_Pool *cp = c->const_pool; - - String *str = cp[cp_index].CONSTANT_String.string; - assert(cp_is_constant(cp, cp_index)); + Java_java_lang_String* result; + ConstantPool& cp = c->m_const_pool; + String* str = cp.get_string(cp_index); BEGIN_RAISE_AREA; result = vm_instantiate_cp_string_resolved(str);