diff --git a/enhanced/drlvm/trunk/vm/gc_cc/src/collect_copy.cpp b/enhanced/drlvm/trunk/vm/gc_cc/src/collect_copy.cpp index 4213391..63e1527 100644 --- a/enhanced/drlvm/trunk/vm/gc_cc/src/collect_copy.cpp +++ b/enhanced/drlvm/trunk/vm/gc_cc/src/collect_copy.cpp @@ -161,7 +161,6 @@ static bool gc_copy_process_reference(Sl } obj->valid(); - VMEXPORT Class_Handle vtable_get_class(VTable_Handle vh); assert(class_get_vtable(vtable_get_class((VTable_Handle)obj->vtable())) == (VTable_Handle)obj->vtable()); TRACE2("gc.debug", "0x" << obj << " is " << class_get_name(vtable_get_class((VTable_Handle)obj->vtable()))); diff --git a/enhanced/drlvm/trunk/vm/gc_cc/src/gc_for_vm.cpp b/enhanced/drlvm/trunk/vm/gc_cc/src/gc_for_vm.cpp index 3398edc..e837bac 100644 --- a/enhanced/drlvm/trunk/vm/gc_cc/src/gc_for_vm.cpp +++ b/enhanced/drlvm/trunk/vm/gc_cc/src/gc_for_vm.cpp @@ -94,10 +94,6 @@ void gc_add_weak_root_set_entry(Managed_ //GCExport void gc_add_root_set_entry_managed_pointer(void **slot, // Boolean is_pinned); // optional -#define BITS_PER_BYTE 8 -#define NEXT_TO_HIGH_BIT_SET_MASK (1<<((sizeof(unsigned) * BITS_PER_BYTE)-2)) -#define NEXT_TO_HIGH_BIT_CLEAR_MASK ~NEXT_TO_HIGH_BIT_SET_MASK - // classloader sometimes sets the bit for finalizible objects (?) inline unsigned int get_instance_data_size (unsigned int encoded_size) { diff --git a/enhanced/drlvm/trunk/vm/gcv4/src/gc_for_vm.cpp b/enhanced/drlvm/trunk/vm/gcv4/src/gc_for_vm.cpp index 809eb51..0005085 100644 --- a/enhanced/drlvm/trunk/vm/gcv4/src/gc_for_vm.cpp +++ b/enhanced/drlvm/trunk/vm/gcv4/src/gc_for_vm.cpp @@ -104,17 +104,6 @@ void gc_register_finalizer(Managed_Objec // probable need to be looked at also. //***************************************************** -#define BITS_PER_BYTE 8 - -// We want to use signed arithmetic when we do allocation pointer/limit compares. -// In order to do this all sizes must be positive so when we want to overflow instead of -// setting the high bit we set the next to high bit. If we set the high bit and the allocation buffer -// is at the top of memory we might not detect an overflow the unsigned overflow would produce -// a small positive number that is smaller then the limit. - -#define NEXT_TO_HIGH_BIT_SET_MASK (1<<((sizeof(unsigned) * BITS_PER_BYTE)-2)) -#define NEXT_TO_HIGH_BIT_CLEAR_MASK ~NEXT_TO_HIGH_BIT_SET_MASK - inline unsigned int get_instance_data_size (unsigned int encoded_size) { return (encoded_size & NEXT_TO_HIGH_BIT_CLEAR_MASK); diff --git a/enhanced/drlvm/trunk/vm/gcv4/src/mark.h b/enhanced/drlvm/trunk/vm/gcv4/src/mark.h index 9fc2fbb..32e4470 100644 --- a/enhanced/drlvm/trunk/vm/gcv4/src/mark.h +++ b/enhanced/drlvm/trunk/vm/gcv4/src/mark.h @@ -34,7 +34,7 @@ #include "characterize_heap.h" // for vtable_get_class -#include "Class.h" +#include "open/vm_gc.h" // returns address correcsponding bit index in specified block inline void* diff --git a/enhanced/drlvm/trunk/vm/gcv4/src/mark_scan.cpp b/enhanced/drlvm/trunk/vm/gcv4/src/mark_scan.cpp index 5da0672..24b8dbb 100644 --- a/enhanced/drlvm/trunk/vm/gcv4/src/mark_scan.cpp +++ b/enhanced/drlvm/trunk/vm/gcv4/src/mark_scan.cpp @@ -82,7 +82,7 @@ scan_array_object(Partial_Reveal_Object assert (type_info_is_reference(tih) || type_info_is_vector(tih) || type_info_is_general_array(tih)); int32 array_length = vector_get_length((Vector_Handle) array); - for (jint i = 0; i < array_length; i++) { + for (int i = 0; i < array_length; i++) { Slot p_element(vector_get_element_address_ref ((Vector_Handle) array, i)); diff --git a/enhanced/drlvm/trunk/vm/gcv4/src/roots.cpp b/enhanced/drlvm/trunk/vm/gcv4/src/roots.cpp index 2590087..6a3fd69 100644 --- a/enhanced/drlvm/trunk/vm/gcv4/src/roots.cpp +++ b/enhanced/drlvm/trunk/vm/gcv4/src/roots.cpp @@ -29,7 +29,6 @@ #include "port_atomic.h" #include "open/vm_gc.h" #include "open/gc.h" -#include "method_lookup.h" // GC header files #include "gc_cout.h" diff --git a/enhanced/drlvm/trunk/vm/include/interpreter_imports.h b/enhanced/drlvm/trunk/vm/include/interpreter_imports.h index a93e574..1dbbfd7 100644 --- a/enhanced/drlvm/trunk/vm/include/interpreter_imports.h +++ b/enhanced/drlvm/trunk/vm/include/interpreter_imports.h @@ -22,6 +22,7 @@ #define _INTERPRETER_IMPORTS_H_ #include "open/types.h" +#include "vm_core_types.h" #include "jvmti.h" struct ManagedObject; diff --git a/enhanced/drlvm/trunk/vm/include/jit_intf.h b/enhanced/drlvm/trunk/vm/include/jit_intf.h index 68f6e3a..3ed963e 100644 --- a/enhanced/drlvm/trunk/vm/include/jit_intf.h +++ b/enhanced/drlvm/trunk/vm/include/jit_intf.h @@ -55,35 +55,7 @@ enum Method_Side_Effects { } Method_Side_Effects; //Method_Side_Effects -/////////////////////////////////////////////////////////////////////////////// -// Access flags for Class, Class_Member, Field and Method. -/////////////////////////////////////////////////////////////////////////////// - // used by - // -#define ACC_PUBLIC 0x0001 // Class Field Method -#define ACC_PRIVATE 0x0002 // Field Method -#define ACC_PROTECTED 0x0004 // Field Method -#define ACC_STATIC 0x0008 // Field Method -#define ACC_FINAL 0x0010 // Class Field Method -#define ACC_SUPER 0x0020 // Class -#define ACC_SYNCHRONIZED 0x0020 // Method -#define ACC_BRIDGE 0x0040 // Method (this is Java 1.5 flag) -#define ACC_VOLATILE 0x0040 // Field -#define ACC_VARARGS 0x0080 // Method (this is Java 1.5 flag) -#define ACC_TRANSIENT 0x0080 // Field -#define ACC_NATIVE 0x0100 // Method -#define ACC_INTERFACE 0x0200 // Class -#define ACC_ABSTRACT 0x0400 // Class Method -#define ACC_STRICT 0x0800 // Method -// The following are Java 1.5 flags -#define ACC_SYNTHETIC 0x1000 // Class Field Method -#define ACC_ANNOTATION 0x2000 // Class -#define ACC_ENUM 0x4000 // Class Field - - //////////////// begin C interface - - // // calls from Compiler to VM // @@ -228,7 +200,6 @@ VMEXPORT void method_set_inline_assumpti // // Class // -VMEXPORT char* class_get_java_name(Class_Handle ch); VMEXPORT unsigned class_get_flags(Class_Handle cl); //VMEXPORT ClassLoaderHandle class_get_classloader(Class_Handle ch); VMEXPORT unsigned class_number_fields(Class_Handle ch); diff --git a/enhanced/drlvm/trunk/vm/include/open/gc.h b/enhanced/drlvm/trunk/vm/include/open/gc.h index 8f50601..242cca8 100644 --- a/enhanced/drlvm/trunk/vm/include/open/gc.h +++ b/enhanced/drlvm/trunk/vm/include/open/gc.h @@ -65,14 +65,20 @@ extern "C" { #define GCExport #endif /* #ifndef PLATFORM_POSIX */ +#define BITS_PER_BYTE 8 +// Signed arithmetic is used when we do allocation pointer/limit compares. +// In order to do this all sizes must be positive so when we want to overflow +// instead of setting the high bit we set the next to high bit. If we set the +// high bit and the allocation buffer is at the top of memory we might not +// detect an overflow the unsigned overflow would produce a small positive +// number that is smaller then the limit. +#define NEXT_TO_HIGH_BIT_SET_MASK (1<<((sizeof(unsigned) * BITS_PER_BYTE)-2)) +#define NEXT_TO_HIGH_BIT_CLEAR_MASK ~NEXT_TO_HIGH_BIT_SET_MASK #if defined(USE_GC_STATIC) || defined(BUILDING_GC) - - - /* * ***** * * diff --git a/enhanced/drlvm/trunk/vm/include/open/vm.h b/enhanced/drlvm/trunk/vm/include/open/vm.h index 519d5ca..f2db97f 100644 --- a/enhanced/drlvm/trunk/vm/include/open/vm.h +++ b/enhanced/drlvm/trunk/vm/include/open/vm.h @@ -305,7 +305,7 @@ VMEXPORT Boolean field_is_unmanaged_stat VMEXPORT unsigned field_get_offset(Field_Handle fh); // Returns an address of a static field. -VMEXPORT void *field_get_addr(Field_Handle fh); +VMEXPORT void *field_get_address(Field_Handle fh); // Returns a name of the field. VMEXPORT const char *field_get_name(Field_Handle fh); diff --git a/enhanced/drlvm/trunk/vm/include/open/vm_gc.h b/enhanced/drlvm/trunk/vm/include/open/vm_gc.h index 6805640..a6bde07 100644 --- a/enhanced/drlvm/trunk/vm/include/open/vm_gc.h +++ b/enhanced/drlvm/trunk/vm/include/open/vm_gc.h @@ -97,6 +97,13 @@ VMEXPORT void vm_resume_threads_after(); VMEXPORT void vm_classloader_iterate_objects(void *iterator); /** + * GC calls this function for each live object it finds in heap. + * This is used for finding unreferenced class loaders for class + * unloading. + */ +VMEXPORT void vm_notify_live_object_class(Class_Handle); + +/** * GC calls this function to hint VM that finalizers may need to be run * and references enqueued. This method is guaranteed not to hold global * GC lock. @@ -185,6 +192,19 @@ enum WeakReferenceType { */ VMEXPORT WeakReferenceType class_is_reference(Class_Handle clss); +/* + * Returns handle of a class for a specified vtable + * @param vh - handle of vtable to retrieve class for + * @return class handle for a specified vtable + */ +VMEXPORT Class_Handle vtable_get_class(VTable_Handle vh); + +/** + * Notifies VM that live object of this class was found in the heap + * @param clss - class of live object in Java heap + **/ +VMEXPORT void vm_notify_live_object_class(Class_Handle clss); + /** * Returns the offset of the referent field * in the java.lang.ref.Reference object. diff --git a/enhanced/drlvm/trunk/vm/interpreter/src/interp_defs.h b/enhanced/drlvm/trunk/vm/interpreter/src/interp_defs.h index 3ee1524..20872ff 100644 --- a/enhanced/drlvm/trunk/vm/interpreter/src/interp_defs.h +++ b/enhanced/drlvm/trunk/vm/interpreter/src/interp_defs.h @@ -27,7 +27,7 @@ #include "vm_threads.h" #include "open/bytecodes.h" #include "open/vm_util.h" -#include "ini.h" +#include "Class.h" //#define INTERPRETER_DEEP_DEBUG #define DEBUG_PRINT(a) TRACE2("interpreter", a) @@ -49,7 +49,7 @@ extern bool interpreter_enable_debug; #define ASSERT_TAGS(a) -#define ASSERT_OBJECT(a) assert((a == 0) || ((*((a)->vt()->clss->class_handle))->vt()->clss == VM_Global_State::loader_env->JavaLangClass_Class)) +#define ASSERT_OBJECT(a) assert((a == 0) || ((*((a)->vt()->clss->get_class_handle()))->vt()->clss == VM_Global_State::loader_env->JavaLangClass_Class)) #ifndef INTERPRETER_USE_MALLOC_ALLOCATION #define ALLOC_FRAME(sz) alloca(sz) diff --git a/enhanced/drlvm/trunk/vm/interpreter/src/interp_native.h b/enhanced/drlvm/trunk/vm/interpreter/src/interp_native.h index b0345ed..5f754f0 100644 --- a/enhanced/drlvm/trunk/vm/interpreter/src/interp_native.h +++ b/enhanced/drlvm/trunk/vm/interpreter/src/interp_native.h @@ -18,6 +18,8 @@ * @author Ivan Volosyuk * @version $Revision: 1.8.4.2.4.3 $ */ +#include "vm_core_types.h" + #ifdef _IPF_ #include "../m2n_ipf_internal.h" #elif defined _EM64T_ diff --git a/enhanced/drlvm/trunk/vm/interpreter/src/interp_native_ia32.cpp b/enhanced/drlvm/trunk/vm/interpreter/src/interp_native_ia32.cpp index ab7eb50..d0cd3da 100644 --- a/enhanced/drlvm/trunk/vm/interpreter/src/interp_native_ia32.cpp +++ b/enhanced/drlvm/trunk/vm/interpreter/src/interp_native_ia32.cpp @@ -84,7 +84,7 @@ interpreter_execute_native_method( assert(!hythread_is_suspend_enabled()); DEBUG_TRACE("\n<<< interpreter_invoke_native: " - << method->get_class()->name->bytes << " " + << class_get_name(method_get_class(method)) << " " << method->get_name()->bytes << method->get_descriptor()->bytes << endl); @@ -106,7 +106,7 @@ interpreter_execute_native_method( jobject _this; if (method->is_static()) { - _this = (jobject) method->get_class()->class_handle; + _this = (jobject) method->get_class()->get_class_handle(); } else { _this = args[pos++].l; } @@ -256,18 +256,18 @@ interpreterInvokeStaticNative(StackFrame } DEBUG_TRACE("\n<<< native_invoke_static : " - << method->get_class()->name->bytes << " " + << class_get_name(method_get_class(method)) << " " << method->get_name()->bytes << method->get_descriptor()->bytes << endl); DEBUG_TRACE_PLAIN("interpreter static native: " - << frame.method->get_class()->name->bytes + << class_get_name(method_get_class(frame.method)) << " " << frame.method->get_name()->bytes << frame.method->get_descriptor()->bytes << endl); M2N_ALLOC_MACRO; - frame.This = *(method->get_class()->class_handle); + frame.This = *(method->get_class()->get_class_handle()); int sz = method->get_num_arg_bytes() >> 2; uword *args = (uword*) ALLOC_FRAME((sz + 2) * sizeof(uword)); args[0] = (uword) get_jni_native_intf(); @@ -371,7 +371,7 @@ interpreterInvokeStaticNative(StackFrame DEBUG2( "VM WARNING: Reference with null value returned from jni function:\n" "VM WARNING: Method name: " - << method->get_class()->name->bytes + << class_get_name(method_get_class(method)) << "/" << method->get_name()->bytes << method->get_descriptor()->bytes << "\nVM WARNING: Not allowed, return NULL (0) instead\n"); @@ -489,12 +489,12 @@ interpreterInvokeVirtualNative(StackFram assert(!method->is_static()); DEBUG_TRACE_PLAIN("interpreter virtual native: " - << frame.method->get_class()->name->bytes + << class_get_name(method_get_class(frame.method)) << " " << frame.method->get_name()->bytes << frame.method->get_descriptor()->bytes << endl); DEBUG_TRACE("\n<<< native_invoke_virtual: " - << method->get_class()->name->bytes << " " + << class_get_name(method_get_class(method)) << " " << method->get_name()->bytes << method->get_descriptor()->bytes << endl); @@ -609,7 +609,7 @@ interpreterInvokeVirtualNative(StackFram DEBUG2( "VM WARNING: Reference with null value returned from jni function:\n" "VM WARNING: Method name: " - << method->get_class()->name->bytes + << class_get_name(method_get_class(method)) << "/" << method->get_name()->bytes << method->get_descriptor()->bytes << "\nVM WARNING: Not allowed, return NULL (0) instead\n"); diff --git a/enhanced/drlvm/trunk/vm/interpreter/src/interp_stack_trace.cpp b/enhanced/drlvm/trunk/vm/interpreter/src/interp_stack_trace.cpp index a227ebc..c03e06f 100644 --- a/enhanced/drlvm/trunk/vm/interpreter/src/interp_stack_trace.cpp +++ b/enhanced/drlvm/trunk/vm/interpreter/src/interp_stack_trace.cpp @@ -173,17 +173,17 @@ interp_enumerate_root_set_single_thread_ if (si->This) { vm_enumerate_root_reference((void**)&si->This, FALSE); - DEBUG_GC(" [THIS]: " << si->This->vt()->clss->name->bytes << endl); + DEBUG_GC(" [THIS]: " << si->This->vt()->clss->get_name()->bytes << endl); } if (si->exc) { vm_enumerate_root_reference((void**)&si->exc, FALSE); - DEBUG_GC(" [EXCEPTION]: " << si->exc->vt()->clss->name->bytes << endl); + DEBUG_GC(" [EXCEPTION]: " << si->exc->vt()->clss->get_name()->bytes << endl); } if (method->is_native()) { DEBUG_GC("[METHOD ]: " - << method->get_class()->name->bytes << "." + << method->get_class()->get_name()->bytes << "." << method->get_name()->bytes << method->get_descriptor()->bytes << endl); interp_si_goto_previous(si); @@ -191,7 +191,7 @@ interp_enumerate_root_set_single_thread_ } DEBUG_GC("[METHOD "<< si->stack.size << " " << (int)si->locals.varNum << "]: " - << method->get_class()->name->bytes << "." + << class_get_name(method_get_class(method)) << "." << method->get_name()->bytes << method->get_descriptor()->bytes << endl); @@ -204,7 +204,7 @@ interp_enumerate_root_set_single_thread_ if (obj == 0) { DEBUG_GC("NULL"); } else { - DEBUG_GC(obj->vt()->clss->name->bytes << endl); + DEBUG_GC(obj->vt()->clss->get_name()->bytes << endl); vm_enumerate(cref, FALSE); } } @@ -220,7 +220,7 @@ interp_enumerate_root_set_single_thread_ if (obj == 0) { DEBUG_GC("NULL\n"); } else { - DEBUG_GC(obj->vt()->clss->name->bytes << endl); + DEBUG_GC(obj->vt()->clss->get_name()->bytes << endl); vm_enumerate(cref, FALSE); } } diff --git a/enhanced/drlvm/trunk/vm/interpreter/src/interp_vm_helpers.h b/enhanced/drlvm/trunk/vm/interpreter/src/interp_vm_helpers.h index 0164109..5c44340 100644 --- a/enhanced/drlvm/trunk/vm/interpreter/src/interp_vm_helpers.h +++ b/enhanced/drlvm/trunk/vm/interpreter/src/interp_vm_helpers.h @@ -18,9 +18,9 @@ * @author Ivan Volosyuk * @version $Revision: 1.2.12.2.4.3 $ */ -#include "Class.h" - +#include "vm_core_types.h" +#include "Class.h" /** * Set thread-local exception with name 'exc'. diff --git a/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp b/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp index 191a1f2..b2e52fe 100644 --- a/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp +++ b/enhanced/drlvm/trunk/vm/interpreter/src/interpreter.cpp @@ -960,42 +960,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->get_constant_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) { @@ -1003,13 +1003,13 @@ ldc(StackFrame& frame, uint32 index) { } assert(!hythread_is_suspend_enabled()); - frame.stack.pick().cr = COMPRESS_REF(*(other_class->class_handle)); + frame.stack.pick().cr = COMPRESS_REF(*(other_class->get_class_handle())); frame.stack.ref() = FLAG_OBJECT; return !exn_raised(); } - frame.stack.pick().u = cp[index].int_value; + frame.stack.pick().u = cp.get_4byte(index); return true; } @@ -1033,10 +1033,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->get_constant_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; @@ -1161,8 +1162,7 @@ allocDimensions(StackFrame& frame, Class Class *c = clss[0] = arrayClass; for(d = 1; d < depth; d++) { - c = c->array_element_class; - + c = c->get_array_element_class(); clss[d] = c; } @@ -1221,7 +1221,7 @@ Opcode_MULTIANEWARRAY(StackFrame& frame) Class *arrayClass = interp_resolve_class(clazz, classId); if (!arrayClass) return; // exception - DEBUG_BYTECODE(arrayClass->name->bytes << " " << depth); + DEBUG_BYTECODE(class_get_name(arrayClass) << " " << depth); bool success = allocDimensions(frame, arrayClass, depth); if (!success) { @@ -1241,7 +1241,7 @@ Opcode_NEW(StackFrame& frame) { Class *objClass = interp_resolve_class_new(clazz, classId); if (!objClass) return; // exception - DEBUG_BYTECODE("cless = " << objClass->name->bytes); + DEBUG_BYTECODE("cless = " << class_get_name(objClass)); class_initialize(objClass); @@ -1516,8 +1516,8 @@ Opcode_AASTORE(StackFrame& frame) { // TODO: check ArrayStoreException ManagedObject *arrayObj = (ManagedObject*) array; Class *arrayClass = arrayObj->vt()->clss; - Class *elementClass = arrayClass->array_element_class; - ManagedObject *obj = UNCOMPRESS_REF(frame.stack.pick().cr); + Class *elementClass = arrayClass->get_array_element_class(); + ManagedObject* obj = UNCOMPRESS_REF(frame.stack.pick().cr); if (!(obj == 0 || vm_instanceof(obj, elementClass))) { interp_throw_exception("java/lang/ArrayStoreException"); return; @@ -1624,19 +1624,18 @@ Opcode_PUTSTATIC(StackFrame& frame) { if (field->is_final()) { - if (frame.method->get_class()->state != ST_Initializing) { + if(!frame.method->get_class()->is_initializing()) { throwIAE(field_get_name(field)); return; } } - void *addr = field->get_address(); + void* addr = field_get_address(field); DEBUG_BYTECODE(field->get_name()->bytes << " " << field->get_descriptor()->bytes << " (val = " << hex << (int)frame.stack.pick().i << ")"); switch (field->get_java_type()) { - #ifdef COMPACT_FIELDS // use compact fields on ipf case VM_DATA_TYPE_BOOLEAN: case VM_DATA_TYPE_INT8: @@ -1719,7 +1718,7 @@ Opcode_GETSTATIC(StackFrame& frame) { M2N_FREE_MACRO; } - void *addr = field->get_address(); + void *addr = field_get_address(field); frame.stack.push(); switch (field->get_java_type()) { @@ -2047,7 +2046,7 @@ Opcode_INVOKEVIRTUAL(StackFrame& frame) Method *method = interp_resolve_virtual_method(clazz, methodId); if (!method) return; // exception - DEBUG_BYTECODE(method->get_class()->name->bytes << "." + DEBUG_BYTECODE(class_get_name(method_get_class(method)) << "." << method->get_name()->bytes << "/" << method->get_descriptor()->bytes<< endl); @@ -2063,7 +2062,7 @@ Opcode_INVOKEINTERFACE(StackFrame& frame Method *method = interp_resolve_interface_method(clazz, methodId); if (!method) return; // exception - DEBUG_BYTECODE(method->get_class()->name->bytes << "." + DEBUG_BYTECODE(class_get_name(method_get_class(method)) << "." << method->get_name()->bytes << "/" << method->get_descriptor()->bytes << endl); @@ -2079,7 +2078,7 @@ Opcode_INVOKESTATIC(StackFrame& frame) { Method *method = interp_resolve_static_method(clazz, methodId); if (!method) return; // exception - DEBUG_BYTECODE(method->get_class()->name->bytes << "." + DEBUG_BYTECODE(class_get_name(method_get_class(method)) << "." << method->get_name()->bytes << "/" << method->get_descriptor()->bytes << endl); @@ -2102,7 +2101,7 @@ Opcode_INVOKESPECIAL(StackFrame& frame) Method *method = interp_resolve_special_method(clazz, methodId); if (!method) return; // exception - DEBUG_BYTECODE(method->get_class()->name->bytes << "." + DEBUG_BYTECODE(class_get_name(method_get_class(method)) << "." << method->get_name()->bytes << "/" << method->get_descriptor()->bytes << endl); @@ -2210,7 +2209,7 @@ Opcode_CHECKCAST(StackFrame& frame) { Class *objClass = interp_resolve_class(clazz, classId); if (!objClass) return; // exception - DEBUG_BYTECODE("class = " << objClass->name->bytes); + DEBUG_BYTECODE("class = " << class_get_name(objClass)); ManagedObject *obj = UNCOMPRESS_REF(frame.stack.pick().cr); @@ -2228,7 +2227,7 @@ Opcode_INSTANCEOF(StackFrame& frame) { Class *objClass = interp_resolve_class(clazz, classId); if (!objClass) return; // exception - DEBUG_BYTECODE("class = " << objClass->name->bytes); + DEBUG_BYTECODE("class = " << class_get_name(objClass)); ManagedObject *obj = UNCOMPRESS_REF(frame.stack.pick().cr); @@ -2303,7 +2302,7 @@ Opcode_ATHROW(StackFrame& frame) { interp_throw_exception("java/lang/VerifyError"); return; } - DEBUG_BYTECODE(" " << obj->vt()->clss->name->bytes << endl); + DEBUG_BYTECODE(" " << obj->vt()->clss->get_name()->bytes << endl); assert(!hythread_is_suspend_enabled()); set_current_thread_exception(obj); } @@ -2316,8 +2315,7 @@ findExceptionHandler(StackFrame& frame, Method *m = frame.method; DEBUG_BYTECODE("Searching for exception handler:"); DEBUG_BYTECODE(" In " - << m->get_class()->name->bytes - << "/" + << class_get_name(method_get_class(m)) << "/" << m->get_name()->bytes << m->get_descriptor()->bytes << endl); @@ -2363,7 +2361,7 @@ processExceptionHandler(StackFrame& fram Method *m = frame.method; Handler *h; if (findExceptionHandler(frame, exception, &h)){ - DEBUG_BYTECODE("Exception caught: " << (*exception)->vt()->clss->name->bytes << endl); + DEBUG_BYTECODE("Exception caught: " << (*exception)->vt()->clss->get_name()->bytes << endl); DEBUG_BYTECODE("Found handler!\n"); frame.ip = (uint8*)m->get_byte_code_addr() + h->get_handler_pc(); return true; @@ -2432,11 +2430,11 @@ stackDump(StackFrame& frame) { (f->n_last_bytecode-8)&7]]); #else const char *filename = class_get_source_file_name(c); - ECHO(c->name->bytes << "." - << m->get_name()->bytes - << m->get_descriptor()->bytes << " (" - << (filename != NULL ? filename : "NULL") << ":" - << line << ")"); + ECHO(class_get_name(c) << "." + << m->get_name()->bytes + << m->get_descriptor()->bytes << " (" + << (filename != NULL ? filename : "NULL") << ":" + << line << ")"); #endif f = f->prev; } @@ -2522,7 +2520,7 @@ method_exit_callback_with_frame(Method * void interpreter(StackFrame &frame) { DEBUG_TRACE_PLAIN("interpreter: " - << frame.method->get_class()->name->bytes + << class_get_name(method_get_class(frame.method)) << " " << frame.method->get_name()->bytes << frame.method->get_descriptor()->bytes << endl); @@ -2562,7 +2560,7 @@ interpreter(StackFrame &frame) { ml->next = 0; if (frame.method->is_static()) { - ml->monitor = *(frame.method->get_class()->class_handle); + ml->monitor = *(frame.method->get_class()->get_class_handle()); } else { ml->monitor = UNCOMPRESS_REF(frame.locals(0).cr); } @@ -3085,10 +3083,10 @@ interpreter_execute_method( } DEBUG_TRACE("\n{{{ interpreter_invoke: " - << method->get_class()->name->bytes << " " + << class_get_name(method_get_class(method)) << " " << method->get_name()->bytes << method->get_descriptor()->bytes << endl); - + DEBUG("\tmax stack = " << method->get_max_stack() << endl); DEBUG("\tmax locals = " << method->get_max_locals() << endl); @@ -3255,11 +3253,10 @@ interpreterInvokeStatic(StackFrame& prev } DEBUG_TRACE("\n{{{ invoke_static : " - << method->get_class()->name->bytes << " " + << class_get_name(method_get_class(method)) << " " << method->get_name()->bytes << method->get_descriptor()->bytes << endl); - DEBUG("\tmax stack = " << method->get_max_stack() << endl); DEBUG("\tmax locals = " << method->get_max_locals() << endl); @@ -3432,7 +3429,7 @@ interpreterInvokeVirtual(StackFrame& pre ASSERT_OBJECT(obj); Class *objClass = obj->vt()->clss; - method = objClass->vtable_descriptors[method->get_index()]; + method = objClass->get_method_from_vtable(method->get_index()); if (method->is_abstract()) { ostringstream str; @@ -3443,7 +3440,7 @@ interpreterInvokeVirtual(StackFrame& pre } DEBUG_TRACE("\n{{{ invoke_virtual : " - << method->get_class()->name->bytes << " " + << class_get_name(method_get_class(method)) << " " << method->get_name()->bytes << method->get_descriptor()->bytes << endl); @@ -3467,7 +3464,7 @@ interpreterInvokeInterface(StackFrame& p if (!vm_instanceof(obj, method->get_class())) { interp_throw_exception("java/lang/IncompatibleClassChangeError", - method->get_class()->name->bytes); + class_get_name(method_get_class(method))); return; } @@ -3498,7 +3495,7 @@ interpreterInvokeInterface(StackFrame& p } DEBUG_TRACE("\n{{{ invoke_interface : " - << method->get_class()->name->bytes << " " + << class_get_name(method_get_class(method)) << " " << method->get_name()->bytes << method->get_descriptor()->bytes << endl); @@ -3544,7 +3541,7 @@ interpreterInvokeSpecial(StackFrame& pre } DEBUG_TRACE("\n{{{ invoke_special : " - << method->get_class()->name->bytes << " " + << class_get_name(method_get_class(method)) << " " << method->get_name()->bytes << method->get_descriptor()->bytes << endl); diff --git a/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp b/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp index 94ad28b..c3fb631 100644 --- a/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp +++ b/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp @@ -253,7 +253,7 @@ void CodeGen::do_field_op(JavaByteCodes } else { // static s - char * fld_addr = fld ? (char*)field_get_addr(fld) : NULL; + char * fld_addr = fld ? (char*)field_get_address(fld) : NULL; where = vaddr(jt, fld_addr); } rlock(where); diff --git a/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_instr.cpp b/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_instr.cpp index b49f1a6..4a2f930 100644 --- a/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_instr.cpp +++ b/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_instr.cpp @@ -442,7 +442,7 @@ void CodeGen::gen_write_barrier(JavaByte // baseObject = Val(jobj, NULL_REF); rlock(baseObject); - void* fieldAddress = field_get_addr(fieldHandle); + void* fieldAddress = field_get_address(fieldHandle); slotAddress = Opnd(jobj, (jlong)(int_ptr)fieldAddress); rlock(slotAddress); } diff --git a/enhanced/drlvm/trunk/vm/jitrino/src/vm/drl/DrlVMInterface.h b/enhanced/drlvm/trunk/vm/jitrino/src/vm/drl/DrlVMInterface.h index fd7aa20..74ba382 100644 --- a/enhanced/drlvm/trunk/vm/jitrino/src/vm/drl/DrlVMInterface.h +++ b/enhanced/drlvm/trunk/vm/jitrino/src/vm/drl/DrlVMInterface.h @@ -205,7 +205,7 @@ public: bool isUnmanagedStatic(); Type* getFieldType(); uint32 getOffset(); - void* getAddress() {return field_get_addr(drlField);} + void* getAddress() {return field_get_address(drlField);} // the following method to be used only by the DrlVM implementation Field_Handle getFieldHandle() {return drlField; } 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 66d7010..43d7531 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 "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 "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..b246175 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/Class.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/Class.h @@ -1,4 +1,4 @@ -/* +/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /** * @author Pavel Pervov * @version $Revision: 1.1.2.7.2.1.2.5 $ @@ -22,289 +23,148 @@ #define _CLASS_H_ /** * @file - * interfaces to class functionality. + * Interfaces to class functionality. */ -#include "jit_intf.h" -// The following is included for CL_PROP_* defines. -// Should they be moved somewhere and made constants? -#include "open/vm_gc.h" +#include #include "open/gc.h" +#include "port_malloc.h" #include "String_Pool.h" -#include "type.h" +#include "vtable.h" + -// // forward declarations -// +struct Class; + +// external declarations 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 CodeChunkInfo; class Lock_Manager; - -// -// external declarations -// -struct Global_Env; // defined in Environment.h - - - - -/////////////////////////////////////////////////////////////////////////////// -// Constant Java values -/////////////////////////////////////////////////////////////////////////////// -union Const_Java_Value { - uint32 i; - int64 j; +class ByteReader; +struct ClassLoader; +class JIT; +struct Global_Env; +class Package; +class VM_thread; +struct AnnotationTable; + + +/** The constant pool entry descriptor. +* For each constant pool entry, the descriptor content varies depending +* on the constant pool tag that corresponds to this constant pool entry. +* Content of each entry is described in +* +* The Java Virtual Machine Specification, Chapter 4, The Constant +* Pool section, with the following exceptions:
    +*
  1. A zero entry of the constant pool contains an array of tags +* corresponding to entries in the constant pool entries array.
  2. +*
  3. As required by +* +* The Java Virtual Machine Specification, Chapter 5 +* Linking/Resolution section, errors are cached for entries that have +* not been resolved earlier for some reason.
+*/ +union ConstPoolEntry { + /** Zero entry of constant pool only: array of tags for constant pool.*/ + unsigned char* tags; + /** CONSTANT_Class.*/ 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;} -}; - - - -/////////////////////////////////////////////////////////////////////////////// -// Raw and compressed reference pointers -/////////////////////////////////////////////////////////////////////////////// -#define RAW_REFERENCE ManagedObject * -#define COMPRESSED_REFERENCE uint32 - -VMEXPORT bool is_compressed_reference(COMPRESSED_REFERENCE value); -VMEXPORT bool is_null_compressed_reference(COMPRESSED_REFERENCE value); - -VMEXPORT COMPRESSED_REFERENCE compress_reference(ManagedObject *obj); -VMEXPORT ManagedObject *uncompress_compressed_reference(COMPRESSED_REFERENCE compressed_ref); -VMEXPORT ManagedObject *get_raw_reference_pointer(ManagedObject **slot_addr); - -// Store the reference "VALUE" in the slot at address "SLOT_ADDR" in the object "CONTAINING_OBJECT". -// Signature: void store_reference(ManagedObject *CONTAINING_OBJECT, ManagedObject **SLOT_ADDR, ManagedObject *VALUE); -#define STORE_REFERENCE(CONTAINING_OBJECT, SLOT_ADDR, VALUE) \ - { \ - if (VM_Global_State::loader_env->compress_references) { \ - gc_heap_slot_write_ref_compressed((Managed_Object_Handle)(CONTAINING_OBJECT), \ - (uint32 *)(SLOT_ADDR), \ - (Managed_Object_Handle)(VALUE)); \ - } else { \ - gc_heap_slot_write_ref((Managed_Object_Handle)(CONTAINING_OBJECT), \ - (Managed_Object_Handle *)(SLOT_ADDR), \ - (Managed_Object_Handle)(VALUE)); \ - } \ - } - - -// Store the reference "VALUE" in the static field or other global slot at address "SLOT_ADDR". -// Signature: void store_global_reference(COMPRESSED_REFERENCE *SLOT_ADDR, ManagedObject *VALUE); -#define STORE_GLOBAL_REFERENCE(SLOT_ADDR, VALUE) \ - { \ - if (VM_Global_State::loader_env->compress_references) { \ - gc_heap_write_global_slot_compressed((uint32 *)(SLOT_ADDR), \ - (Managed_Object_Handle)(VALUE)); \ - } else { \ - gc_heap_write_global_slot((Managed_Object_Handle *)(SLOT_ADDR), \ - (Managed_Object_Handle)(VALUE)); \ - } \ - } - - - -/////////////////////////////////////////////////////////////////////////////// -// 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 -#define N_CODE_ATTR 3 -#define N_CLASS_ATTR 4 - -// -// magic number, and major/minor version numbers of class file -// -#define CLASSFILE_MAGIC 0xCAFEBABE -#define CLASSFILE_MAJOR 45 -// Supported class files up to this version -#define CLASSFILE_MAJOR_MAX 49 -#define CLASSFILE_MINOR 3 - - -/////////////////////////////////////////////////////////////////////////////// -// Constant pool entries. -/////////////////////////////////////////////////////////////////////////////// - -union Const_Pool { - 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 + /** Resolved class*/ + Class* klass; + /** Resolution error, if any.*/ + struct { + /** Next resolution error in this constant pool.*/ + ConstPoolEntry* next; + /** Exception object describing an error.*/ ManagedObject* cause; } error; }; + /** Index to class name in this constant pool.*/ uint16 name_index; } CONSTANT_Class; - struct { // CONSTANT_String - String *string; // resolved entry + /** CONSTANT_String.*/ + struct { + /** Resolved class.*/ + String* string; + /** Index of CONSTANT_Utf8 for this string.*/ uint16 string_index; } CONSTANT_String; - struct { // CONSTANT_{Field,Method,InterfaceMethod}ref + /** CONSTANT_{Field|Method|InterfaceMethod}ref.*/ + struct { union { - Field* field; // resolved entry for CONSTANT_Fieldref - Method* method; // resolved entry for CONSTANT_{Interface}Methodref - struct { // resolution error - Const_Pool* next; // next resolution error in this constant pool + /** Generic class member for CONSTANT_*ref. + * Only valid for resolved refs.*/ + Class_Member* member; + /** Resolved entry for CONSTANT_Fieldref.*/ + Field* field; + /** resolved entry for CONSTANT_[Interface]Methodref.*/ + Method* method; + /** Resolution error, if any.*/ + struct { + /** Next resolution error in this constant pool.*/ + ConstPoolEntry* next; + /** Exception object describing error.*/ ManagedObject* cause; } error; }; + /** Index of CONSTANT_Class for this CONSTANT_*ref.*/ uint16 class_index; + /** Index of CONSTANT_NameAndType for CONSTANT_*ref.*/ uint16 name_and_type_index; } CONSTANT_ref; - struct { // shortcut to resolution error in CONSTANT_Class and CONSTANT_ref - Const_Pool* next; // next resolution error in this constant pool + /** Shortcut to resolution error in CONSTANT_Class and CONSTANT_ref.*/ + struct { + /** Next resolution error in this constant pool.*/ + ConstPoolEntry* next; + /** Exception object describing error.*/ ManagedObject* cause; } error; - uint32 int_value; // CONSTANT_Integer - float float_value; // CONSTANT_Float + /** CONSTANT_Integer.*/ + uint32 int_value; + /** CONSTANT_Float.*/ + float float_value; + /** CONSTANT_Long and CONSTANT_Double. + * @note In this case we pack all 8 bytes of long/double in one + * ConstPoolEntry and leave the second ConstPoolEntry of the long/double + * unused.*/ struct { - uint32 low_bytes; // each Const_Pool element is 64bit in this case - uint32 high_bytes; // we pack all 8 bytes of long/double in one - // Const_Pool element (and leave the second - // Const_Pool element of the long/double unused) + uint32 low_bytes; + uint32 high_bytes; } CONSTANT_8byte; - struct { // CONSTANT_NameAndType - String *name; // resolved entry - String *descriptor; // resolved entry + /** CONSTANT_NameAndType.*/ + struct { + /** Resolved name.*/ + String* name; + /** Resolved descriptor.*/ + String* descriptor; + /** Name index in this constant pool.*/ uint16 name_index; + /** Descriptor index in this constant pool.*/ uint16 descriptor_index; } CONSTANT_NameAndType; + /** CONSTANT_Utf8.*/ struct { - String *string; // CONSTANT_Utf8 - uint16 dummy; + /** Content of CONSTANT_Utf8 entry.*/ + String* string; } 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 -// pointed to by the first constant pool entry. -/////////////////////////////////////////////////////////////////////////////// -enum Const_Pool_Tags { - CONSTANT_Tags = 0, // pointer to tags array +/** Types of constant pool entries. These entry types are defined by a seperate +* byte array that the first constant pool entry points at.*/ +enum ConstPoolTags { + /** pointer to the tags array.*/ + CONSTANT_Tags = 0, + /** The rest of tag values are taken from + * + * The Java Virtual Machine Specification, Chapter 4, The Constant + * Pool section.*/ CONSTANT_Utf8 = 1, CONSTANT_Integer = 3, CONSTANT_Float = 4, @@ -318,1473 +178,1828 @@ 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) +/** The constant pool of a class and related operations. + * The structure covers all operations that may be required to run + * on the constant pool, such as parsing and processing queries.*/ -#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) +struct ConstantPool { +private: + // tag mask; 4 bits are sufficient for tag + static const unsigned char TAG_MASK = 0x0F; + // this entry contains resolution error information + static const unsigned char ERROR_MASK = 0x40; + // "entry is resolved" flag; msb + static const unsigned char RESOLVED_MASK = 0x80; + + // 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; -#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) +public: + /** Initializes the constant pool to its initial values.*/ + ConstantPool() { + init(); + } + /** Clears constant pool content (if there are any).*/ + ~ConstantPool() { + clear(); + } -#define cp_resolve_to_class(cp,i,c) cp_set_resolved(cp,i); cp[i].CONSTANT_Class.klass=c; + /** Checks whether the constant pool is not empty. + * @return true if the constant pool contains + * certain entries; otherwise false.*/ + bool available() const { return m_size != 0; } + + /** Gets the size of the given constant pool. + * @return The number of entries in the constant pool.*/ + uint16 get_size() const { return m_size; } + + /** Checks whether the index is a valid one in the constant pool. + * @param[in] index - an index in the constant pool + * @return true if the index is a valid one in the constant + * pool; otherwise false.*/ + bool is_valid_index(uint16 index) const { + return /*index > 0 && */index < m_size; + } -#define cp_resolve_to_field(cp,i,f) cp_set_resolved(cp,i); cp[i].CONSTANT_ref.field=f; + /** Checks whether the constant-pool entry is resolved. + * @param[in] index - an index in the constant pool + * @return true if the entry is resolved; + * otherwise false.*/ + bool is_entry_resolved(uint16 index) const { + assert(is_valid_index(index)); + return (m_entries[0].tags[index] & RESOLVED_MASK) != 0; + } -#define cp_resolve_to_method(cp,i,m) cp_set_resolved(cp,i); cp[i].CONSTANT_ref.method=m; + /** Checks whether the resolution of the constant-pool entry has failed. + * @param[in] index - an index in the constant pool + * @return true if the 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; + } -#define MAX_FAST_INSTOF_DEPTH 5 + /** Checks whether the constant-pool entry represents the string of + * the #CONSTANT_Utf8 type. + * @param[in] index - an index in the constant pool + * @return true if the given entry is the utf8 + * string; otherwise false.*/ + bool is_utf8(uint16 index) const { + return get_tag(index) == CONSTANT_Utf8; + } -/////////////////////////////////////////////////////////////////////////////// -// virtual method table of a class -/////////////////////////////////////////////////////////////////////////////// -extern "C" { + /** Checks whether the constant-pool entry refers to a #CONSTANT_Class. + * @param[in] index - an index in the constant pool + * @return true if the given entry is a class; + * otherwise false.*/ + bool is_class(uint16 index) const { + return get_tag(index) == CONSTANT_Class; + } -typedef struct { - unsigned char **table;// pointer into methods array of VTable below - unsigned intfc_id; // id of interface -} Intfc_Table_Entry; + /** Checks whether the constant-pool entry contains a constant. + * @param[in] index - an index in the constant pool + * @return true if the given entry contains a constant; + * otherwise false.*/ + 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; + } -typedef struct Intfc_Table { -#ifdef POINTER64 - // see INTFC_TABLE_OVERHEAD - uint32 dummy; // padding -#endif - uint32 n_entries; - Intfc_Table_Entry entry[1]; -} Intfc_Table; + /** Checks whether the constant-pool entry is a literal constant. + * @param[in] index - an index in the constant pool + * @return true if the given entry contains a string; + * otherwise false.*/ + bool is_string(uint16 index) const { + return get_tag(index) == CONSTANT_String; + } + /** Checks whether the constant-pool entry is #CONSTANT_NameAndType. + * @param[in] index - an index in the constant pool + * @return true if the given entry contains name-and-type; + * otherwise false.*/ + bool is_name_and_type(uint16 index) const { + return get_tag(index) == CONSTANT_NameAndType; + } -#define INTFC_TABLE_OVERHEAD (sizeof(void *)) + /** Checks whether the constant-pool entry contains a field reference, + * #CONSTANT_Fieldref. + * @param[in] index - an index in the constant pool + * @return true if the given entry contains a field reference; + * otherwise false.*/ + bool is_fieldref(uint16 index) const { + return get_tag(index) == CONSTANT_Fieldref; + } + /** Checks whether the constant-pool entry contains a method reference, + * #CONSTANT_Methodref. + * @param[in] index - an index in the constant pool + * @return true if the given entry contains a method reference; + * otherwise false.*/ + bool is_methodref(uint16 index) const { + return get_tag(index) == CONSTANT_Methodref; + } -#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 + /** Checks whether the constant-pool entry constains an interface-method + * reference, #CONSTANT_InterfaceMethodref. + * @param[in] index - an index in the constant pool + * @return true if the given entry contains an interface-method + * reference; otherwise false.*/ + bool is_interfacemethodref(uint16 index) const { + return get_tag(index) == CONSTANT_InterfaceMethodref; + } + /** Gets a tag of the referenced constant-pool entry. + * @param[in] index - an index in the constant pool + * @return A 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; + } -#define GC_BYTES_IN_VTABLE (sizeof(void *)) + /** Gets characters from the utf8 string stored in the + * constant pool. + * @param[in] index - an index in the constant pool + * @return Characters from the utf8 string stored in + * the constant pool.*/ + const char* get_utf8_chars(uint16 index) const { + return get_utf8_string(index)->bytes; + } -typedef struct VTable { + /** Gets the utf8 string stored in the constant pool. + * @param[in] index - an index in the constant pool + * @return The utf8 string.*/ + String* get_utf8_string(uint16 index) const { + assert(is_utf8(index)); + return m_entries[index].CONSTANT_Utf8.string; + } - Byte _gc_private_information[GC_BYTES_IN_VTABLE]; + /** Gets characters stored in the utf8 string for + * the #CONSTANT_String entry. + * @param[in] index - an index in the constant pool + * @return The utf8 string characters for the given + * constant-pool entry.*/ + const char* get_string_chars(uint16 index) const { + return get_string(index)->bytes; + } - Class *clss; // the class - see above before change - // - // See the masks in vm_for_gc.h. - // - uint32 class_properties; + /** Gets the utf8 string stored for the #CONSTANT_String + * entry. + * @param[in] index - an index in the constant pool + * @return The utf8 string stored in the constant-pool entry.*/ + String* get_string(uint16 index) const { + assert(is_string(index)); + return m_entries[index].CONSTANT_String.string; + } + /** Gets the utf8 string representing the name part of the + * name-and-type constant-pool entry. + * @param[in] index - an index in the constant pool + * @return The utf8 string with the 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; + } - // 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; + /** Gets the utf8 string representing the descriptor part of + * the name-and-type constant-pool entry. + * @param[in] index - an index in the constant pool + * @return The utf8 string with the 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; + } - 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; + /** Gets the generic class member for the CONSTANT_*ref + * constant-pool entry. + * @param[in] index - an index in the constant pool + * @return The generic-class member for the given 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; + } + /** Gets the method from the #CONSTANT_Methodref or + * the #CONSTANT_InterfaceMethodref constant-pool entry + * @param[in] index - an index in the constant pool + * @return The method from the given 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; + } -#define VTABLE_OVERHEAD (sizeof(VTable) - sizeof(void *)) -// The "- sizeof(void *)" part subtracts out the "unsigned char *methods[1]" contribution. + /** Gets the field from the #CONSTANT_Fieldref + * constant-pool entry. + * @param[in] index - an index in the constant pool + * @return The field from the given 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; + } -VTable *create_vtable(Class *p_class, unsigned n_vtable_entries); + /** Gets the class for the #CONSTANT_Class + * constant-pool entry. + * @param[in] index - an index in the constant pool + * @return The class for the given 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; + } -} // extern "C" + /** Gets a 32-bit value (either interger or float) for a constant stored + * in the constant pool. + * @param[in] index - an index in the constant pool + * @return The value of a 32-bit constant stored in the 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; + } + /** Gets an integer value for a constant stored in the constant pool. + * @param[in] index - an index in the constant pool + * @return The value of integer constant stored in the constant pool.*/ + uint32 get_int(uint16 index) const { + assert(get_tag(index) == CONSTANT_Integer); + return m_entries[index].int_value; + } -/////////////////////////////////////////////////////////////////////////////// -// A Java class -/////////////////////////////////////////////////////////////////////////////// -extern "C" { + /** Gets a float value for a constant stored in the constant pool. + * @param[in] index - an index in the constant pool + * @return A value of a float constant stored in the constant pool.*/ + float get_float(uint16 index) const { + assert(get_tag(index) == CONSTANT_Float); + return m_entries[index].float_value; + } -// -// state of this class -// -enum Class_State { - ST_Start, // initial state - ST_LoadingAncestors, // loading super class and super interfaces - ST_Loaded, // successfully loaded - ST_InstanceSizeComputed, // still preparing the class but size of - // its instances is known - ST_Prepared, // successfully prepared - ST_Initializing, // initializing the class - ST_Initialized, // class initialized - ST_Error // bad class or the initializer failed -}; + /** Gets a low word of the 64-bit constant (either long or double) + * stored in the constant pool. + * @param[in] index - an index in the constant pool + * @return A 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; + } -typedef union { - String *name; - Class *clss; -} Class_Superinterface; + /** Gets a high word of the 64-bit constant (either long or double) + * stored in the constant pool. + * @param[in] index - an index in the constant pool + * @return A 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; + } -typedef struct Class { + /** Gets an address of a constant stored in the constant pool. + * @param[in] index - an index in the constant pool + * @return An address of a constant.*/ + void* get_address_of_constant(uint16 index) const { + assert(is_constant(index)); + assert(!is_string(index)); + return (void*)(m_entries + index); + } -///////////////////////////////////////////////////////////////////// -//////// The first few fields can not be changed without reflecting -//////// the changes in the type Partial_Class in vm_for_gc.h -//////////////////////////////////////////////////////////////////// + /** Gets an exception, which has caused failure of the referred + * constant-pool entry. + * @param[in] index - an index in the constant pool + * @return An exception object, which is the cause of the + * resolution failure.*/ + jthrowable get_error_cause(uint16 index) const { + assert(is_entry_in_error(index)); + return (jthrowable)(&(m_entries[index].error.cause)); + } - // - // super class of this class; initially, it is the string name of super - // class; after super class is loaded, it becomes a pointer to class - // structure of the super class. - // - // The offset of this field is returned by class_get_super_offset. - // Make sure to update this function if the field is moved around. - // - union { - String *super_name; - Class *super_class; - }; + /** Gets a head of a single-linked list containing resolution errors + * in the given constant pool. + * @return A head of a signle-linked list of constant-pool entries, + * which resolution had failed.*/ + ConstPoolEntry* get_error_chain() const { + return m_failedResolution; + } - const String * name; // class name in internal (VM, class-file) format - //String * java_name; // class canonical (Java) name - String * Signature; // generic type information (since 1.5) + /** Gets an an index in the constant pool where the utf8 + * representation for #CONSTANT_String is stored. + * @param[in] index - an index in the constant pool for the + * #CONSTANT_String entry + * @return An an index in the constant pool with the utf8 + * representation of the given string.*/ + uint16 get_string_index(uint16 index) const { + assert(is_string(index)); + return m_entries[index].CONSTANT_String.string_index; + } - // - // See the masks in vm_for_gc.h. - // + /** Gets an index of the constant-pool entry containing the + * utf8 string with the name part. + * @param[in] index - an index in the constant pool + * @return An an index in the constant pool with the utf8 + * name string.*/ + uint16 get_name_and_type_name_index(uint16 index) const { + assert(is_name_and_type(index)); + return m_entries[index].CONSTANT_NameAndType.name_index; + } - uint32 class_properties; + /** Gets an index of the constant-pool entry containing the + * utf8 string with the descriptor part. + * @param[in] index - an index in the constant pool + * @return An an index in the constant pool with the utf8 + * string for the 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; + } - // 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; + /** Gets an index of the constant-pool entry containing a class for + * the given CONSTANT_*ref entry. + * @param[in] index - an index in the constant pool + * @return An index of a class entry for the given 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; + } - unsigned int array_element_size; + /** Gets an index of CONSTANT_NameAndType for the given + * constant-pool entry. + * @param[in] index - an index in the constant pool + * @return An index of #CONSTANT_NameAndType for the given + * 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; + } + /** Gets a class-name an index in the constant pool for the + * #CONSTANT_Class entry. + * @param[in] index - an index in the constant pool + * @return An index of the utf8 name of the given class.*/ + uint16 get_class_name_index(uint16 index) const { + assert(is_class(index)); + return m_entries[index].CONSTANT_Class.name_index; + } -///////////////////////////////////////////////////////////////////// -//////// Fields above this point can not be moved without redefining -//////// the data structure Partial_Class in vm_for_gc.h -///////////////////////////////////////////////////////////////////// + /** Resolves an entry to the class. + * @param[in] index - an index in the constant pool + * @param[in] clss - a class to resolve the given entry to*/ + void resolve_entry(uint16 index, Class* clss) { + // we do not want to resolve entry of a different type + assert(is_class(index)); + set_entry_resolved(index); + m_entries[index].CONSTANT_Class.klass = clss; + } - // - // How should objects of this class be aligned by GC. - // - int alignment; + /** Resolves an entry to the field. + * @param[in] index - an index in the constant pool + * @param[in] field - a field to resolve the given 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 an entry to the method. + * @param[in] index - an index in the constant pool + * @param[in] method - a method to resolve the given entry to*/ + void resolve_entry(uint16 index, Method* method) { + // we do not want to resolve entry of a different type + assert(is_methodref(index) || is_interfacemethodref(index)); + set_entry_resolved(index); + m_entries[index].CONSTANT_ref.method = method; + } - // - // unique class id - // - unsigned id; + /** Records a resolution error into a constant-pool entry. + * @param[in] index - an index in the constant pool + * @param[in] exn - a cause of resolution failure + * @note Disable suspension during this operation.*/ + void resolve_as_error(uint16 index, jthrowable exn) { + assert(is_class(index) + || is_fieldref(index) + || is_methodref(index) + || is_interfacemethodref(index)); + // ppervov: 'if' clause is changed to 'assert' expression as this + // should never happen, i.e. class resolution should never try + // to resolve failed entry twice + // ppervov: 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]); + // ppervov: } + } + /** Parses in a constant pool for a class. + * @param[in] clss - a class containing the given constant pool + * @param[in] string_pool - a reference to the string pool to intern strings in + * @param[in] cfs - a byte stream to parse the constant pool from + * @return true if the constant pool was parsed successfully; + * false if some error was discovered during the parsing.*/ + bool parse(Class* clss, String_Pool& string_pool, ByteReader& cfs); + + /** Checks constant pool consistency. + * @param[in] clss - the class that the given constant pool belongs to + * @return true if the constant pool of clss is valid; + * otherwise false.*/ + bool check(Class* clss); + + /** Clears the constant-pool content: tags and entries arrays.*/ + void clear() { + if(m_size != 0) { + delete[] m_entries[0].tags; + delete[] m_entries; + } + init(); + } - // - // The class loader used to load this class. - // - ClassLoader* class_loader; + /** Initializes the constant pool to initial values.*/ + void init() { + m_size = 0; + m_entries = NULL; + m_failedResolution = NULL; + } +private: + /** Sets a resolved flag in the constant-pool entry. + * @param[in] index - an index in the 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 an error flag in the constant-pool entry to mark it as failed. + * @param[in] index - an index in the constant pool*/ + void set_entry_error_state(uint16 index) { + assert(is_valid_index(index)); + // we do not want to reset the resolved error + assert(!is_entry_resolved(index)); + // we do not want to reset the reason of the failure + assert(!is_entry_in_error(index)); + m_entries[0].tags[index] |= ERROR_MASK; + } - // - // Does it represent a primitive type? - // - unsigned is_primitive : 1; + /** Resolves the #CONSTANT_NameAndType constant-pool entry + * to actual string values. + * @param[in] index - an index in the constant pool + * @param[in] name - name-and-type name + * @param[in] 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; + } - // - // array information - // - unsigned is_array : 1; + /** Resolves the CONSTANT_String constant-pool entry to + * actual string values. + * @param[in] index - an index in the constant pool + * @param[in] str - an actual string*/ + void resolve_entry(uint16 index, String* str) { + assert(is_string(index)); + set_entry_resolved(index); + m_entries[index].CONSTANT_String.string = str; + } +}; - // - // This is even TRUE for multidimensional arrays as long - // as the type of the last dimension is primitve. - // - unsigned is_array_of_primitives : 1; +/** Converts a class name from an internal (VM) form to the Java form. + * @param[in] class_name - the class name in an internal form + * @return The class name in the Java form.*/ +String* class_name_get_java_name(const String* class_name); - // - // Does the class have a finalizer that is not inherited from - // java.lang.Object? - // - unsigned has_finalizer : 1; +// A Java class +extern "C" { - // Should this class not be verified (needed for certain special classes) - unsigned is_not_verified : 1; +/** The state of the Java class*/ - // - // Is this class verified by verifier - // ??? FIXME - have to be in Class_State - unsigned is_verified : 2; +enum Class_State { + ST_Start, /// the initial state + ST_LoadingAncestors, /// the loading super class and super interfaces + ST_Loaded, /// successfully loaded + ST_BytecodesVerified, /// bytecodes for methods verified for the class + ST_InstanceSizeComputed, /// preparing the class; instance size known + ST_Prepared, /// successfully prepared + ST_ConstraintsVerified, /// constraints verified for the class + ST_Initializing, /// initializing the class + ST_Initialized, /// the class initialized + ST_Error /// bad class or the class initializer failed +}; - // - // Can instances of this class be allocated using a fast inline sequence containing - // no calls to other routines. - // - unsigned char is_fast_allocation_possible; - // - // number of dimensions in array; current VM limitation is 255 - // - // Note, that you can derive the base component type of the array - // by looking at name->bytes[n_dimensions]. - // - unsigned char n_dimensions; +/** Access and properties flags for Class, Field and Method.*/ +enum AccessAndPropertiesFlags { + /** Public access modifier. Valid for Class, Field, Method. */ + ACC_PUBLIC = 0x0001, + /** Private access modifier. Valid for Field, Method.*/ + ACC_PRIVATE = 0x0002, + /** Protected access modifier. Valid for Field, Method.*/ + ACC_PROTECTED = 0x0004, + /** Static modifier. Valid for Field, Method.*/ + ACC_STATIC = 0x0008, + /** Final modifier. Valid for Class, Field, Method.*/ + ACC_FINAL = 0x0010, + /** Super modifier. Valid for Class.*/ + ACC_SUPER = 0x0020, + /** Synchronized modifier. Valid for Method.*/ + ACC_SYNCHRONIZED = 0x0020, + /** Bridge modifier. Valid for Method (since J2SE 5.0).*/ + ACC_BRIDGE = 0x0040, + /** Volatile modifier. Valid for Field.*/ + ACC_VOLATILE = 0x0040, + /** Varargs modifier. Valid for Method (since J2SE 5.0).*/ + ACC_VARARGS = 0x0080, + /** Transient modifier. Valid for Field.*/ + ACC_TRANSIENT = 0x0080, + /** Native modifier. Valid for Method.*/ + ACC_NATIVE = 0x0100, + /** Interface modifier. Valid for Class.*/ + ACC_INTERFACE = 0x0200, + /** Abstract modifier. Valid for Class, Method.*/ + ACC_ABSTRACT = 0x0400, + /** Strict modifier. Valid for Method.*/ + ACC_STRICT = 0x0800, + /** Synthetic modifier. Valid for Class, Field, Method (since J2SE 5.0).*/ + ACC_SYNTHETIC = 0x1000, + /** Annotation modifier. Valid for Class (since J2SE 5.0).*/ + ACC_ANNOTATION = 0x2000, + /** Enum modifier. Valid for Class, Field (since J2SE 5.0).*/ + ACC_ENUM = 0x4000 +}; - // - // for non-primitive arrays only, array_base_class is the base class - // of an array - // - Class *array_base_class; +/** VM representation of Java class. + * This class contains methods for parsing classes, querying class properties, + * setting external properties of a class (source file name, class file name), + * calling the verifier, preparing, resolving and initializing the class.*/ - Class *array_element_class; - TypeDesc* array_element_type_desc; +struct Class { +private: + typedef struct { + union { + const String* name; + Class* clss; + }; + unsigned cp_index; + } Class_Super; - uint16 access_flags; - uint16 cp_size; - uint16 n_superinterfaces; - uint16 n_fields; - uint16 n_static_fields; - uint16 n_methods; + // + // super class of this class; initially, it is the string name of super + // class; after super class is loaded, it becomes a pointer to class + // structure of the super class. + // + // The offset of this field is returned by class_get_super_offset. + // Make sure to update this function if the field is moved around. + // + Class_Super m_super_class; + + // class name in internal (VM, class-file) format + const String* m_name; + // class canonical (Java) name + String* m_java_name; + // generic type information (since Java 1.5.0) + String* m_signature; + // simple name of the class as given in the source code; empty string if anonymous + String* m_simple_name; + // package to which this class belongs + Package* m_package; + + // Distance in the hierarchy from java/lang/Object + int m_depth; + + // The field m_is_suitable_for_fast_instanceof should be 0 + // if depth==0 or depth>=vm_max_fast_instanceof_depth() + // or is_array or access_flags&ACC_INTERFACE + // It should be 1 otherwise + int m_is_suitable_for_fast_instanceof; + + // string name of file from which this class has been loaded + const String* m_class_file_name; + // string name of source java file from which this class has been compiled + const String* m_src_file_name; - // for inner class support - uint16 declaringclass_index; - uint16 enclosing_class_index; - uint16 enclosing_method_index; - uint16 n_innerclasses; - uint16 *innerclass_indexes; + // unique class id + // FIXME: current implementation of id is not thread safe + // so, class id may not be unique + unsigned m_id; - // simple name of the class as given in the source code - // empty string if anonymous - String * simple_name; + // The class loader used to load this class. + ClassLoader* m_class_loader; - Const_Pool *const_pool; // constant pool array; size is cp_size - Field *fields; // array of fields; size is n_fields - Method *methods; // array of methods; size is n_methods - // - // array of interfaces this class implements; size is n_superinterfaces - // initially, it is an array of string names of interfaces and then - // after superinterfaces are loaded, this becomes an array pointers - // to superinterface class structures. - // - Class_Superinterface *superinterfaces; + // This points to the location where java.lang.Class associated + // with the current class resides. Similarly, java.lang.Class has a field + // that points to the corresponding Class data structure. + ManagedObject** m_class_handle; - const String *class_file_name; // string name of file from which - // this class has been loaded - const String *src_file_name; // string name of file from which - // this class has been compiled - Class_State state; // state of this class + // Access and properties flags of a class + uint16 m_access_flags; - Package *package; // package to which this class belongs + // state of this class + Class_State m_state; - bool deprecated; - // - // the following sizes are all in bytes - // + // Is this class marked as deprecated + bool m_deprecated; - unsigned n_instance_refs; // number of instance variables that are references + // Does this class represent a primitive type? + unsigned m_is_primitive : 1; - unsigned n_virtual_method_entries; // number virtual methods in vtable - unsigned n_intfc_method_entries; // number interface methods in vtable - unsigned n_intfc_table_entries; // number intfc tables in _intfc_table - // same as _vtable->_intfc_table->n_entries + // Does this class represent an array? + unsigned m_is_array : 1; - Method *finalize_method; // NULL if none exists + // Does base class of this array is primitive + unsigned m_is_array_of_primitives : 1; - Method *static_initializer; // if it exists, NULL otherwise + // Does the class have a finalizer that is not inherited from + // java.lang.Object? + unsigned m_has_finalizer : 1; - Method *default_constructor; // for performance + // Should access from this class be checked + // (needed for certain special classes) + unsigned m_can_access_all : 1; - unsigned static_data_size; // size of this class' static data block - void *static_data_block; // block containing array of static data fields + // Can instances of this class be allocated using a fast inline sequence + // containing no calls to other routines + unsigned char m_is_fast_allocation_possible; - unsigned static_method_size; // size in bytes of this class' static method block - unsigned char **static_method_block; // array of pointers to code of - // static methods + // 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 m_allocated_size; // This is the size of an instance without any alignment padding. // It can be used while calculating the field offsets of subclasses. // It does not include the OBJECT_HEADER_SIZE but does include the // OBJECT_VTABLE_POINTER_SIZE. - // The allocated_size field will be this field properly aligned. - unsigned unpadded_instance_data_size; + // The m_allocated_size field will be this field properly aligned. + unsigned m_unpadded_instance_data_size; - // Size of java/lang/Class instances in bytes. This variable is used during bootstrapping to allocate - // the three classes (i.e. Class instances) loaded before java.lang.Class: java.lang.Object, - // java.io.Serializable and java.lang.Class. - //static unsigned sizeof_class_class; + // How should objects of this class be aligned by GC. + int m_alignment; // Try to keep instance_data_size near vtable since they are used at the same time // by the allocation routines and sharing a cache line seem to help. - // + // The next to high bit is set if allocation needs to consider class_properties. // (mumble->instance_data_size & NEXT_TO_HIGH_BIT_CLEAR_MASK) will always return the // actual size of and instance of class mumble. // Use get_instance_data_size() to get the actual size of an instance. // Use set_instance_data_size_constraint_bit() to set this bit. - unsigned instance_data_size; // For most classes the size of a class instance's - // data block. This is what is passed to the GC. - // See above for details. - // ppervov: FIXME: the next two should be joined into a union - VTable *vtable; // virtual method table; NULL for interfaces - Allocation_Handle allocation_handle; + // For most classes the size of a class instance's data block. + // This is what is passed to the GC. See above for details. + unsigned m_instance_data_size; - // - // _vtable_descriptor is an array of pointers to Method descriptors, one - // descriptor for each corresponding entry in _vtable.methods[]. - // - Method **vtable_descriptors; - // - // _intfc_table_descriptor is an array of pointers to Class descriptors, - // one descriptor for each corresponding entry in intf_table.entry[]; - // - Class **intfc_table_descriptors; // Class struture of interface - // ppervov: FIXME: to remove - void *class_object; - - bool printed_in_dump_jit; + // ppervov: FIXME: the next two can be joined into a union; + // vtable compression should be dropped in that case - void *p_initializing_thread; // this really points to VM thread data struct - ManagedObject *p_error; // enumeratable as static field + // virtual method table; NULL for interfaces + VTable* m_vtable; -#ifdef VM_STATS - uint64 num_class_init_checks; + // "Compressed VTable" - offset from the base of VTable allocation area + Allocation_Handle m_allocation_handle; - // For subclasses of java.lang.Throwable only. - uint64 num_throws; + // number of virtual methods in vtable + unsigned m_num_virtual_method_entries; - // Number of instanceof/checkcast calls both from the user code - // and the VM that were not subsumed by the fast version of instanceof. - uint64 num_instanceof_slow; + // number of interface methods in vtable + unsigned m_num_intfc_method_entries; - // Number of times an instance of the class has been created using new, newarray, etc. - uint64 num_allocations; + // number intfc tables in intfc_table + // same as vtable->intfc_table->n_entries + unsigned m_num_intfc_table_entries; - // Number of times an instance of the class has been created using new, newarray, etc. - uint64 num_allocations_from_newInstance; + // An array of pointers to Method descriptors, one descriptor + // for each corresponding entry in m_vtable.methods[]. + Method** m_vtable_descriptors; - // Number of bytes allocated for instances of the class. - uint64 num_bytes_allocated; -#endif + // An array of pointers to Class descriptors, one descriptor + // for each corresponding entry in m_intf_table.entry[]. + Class** m_intfc_table_descriptors; - // Number of "padding" bytes curently added per class instance to its fields to - // make each field at least 32 bits. - uint32 num_field_padding_bytes; - - // If set true by the "-compact_fields" command line option, the VM will not pad out fields of - // less than 32 bits to four bytes. However, fields will still be aligned to a natural boundary, - // and the num_field_padding_bytes field will reflect those alignment padding bytes. - static bool compact_fields; - - // If set true by the "-sort_fields" command line option, the VM will sort fields by size before - // assigning their offset during class preparation. - static bool sort_fields; - - // Notify JITs whenever this class is extended by calling their JIT_extended_class_callback callback function, - Class_Extended_Notification_Record *notify_extended_records; + // number of dimensions in array; current VM limitation is 255 + // Note, that you can derive the base component type of the array + // by looking at m_name->bytes[m_num_dimensions]. + unsigned char m_num_dimensions; - int depth; - // The field is_suitable_for_fast_instanceof should be 0 if depth==0 or depth>=vm_max_fast_instanceof_depth() - // or is_array or access_flags&ACC_INTERFACE. It should be 1 otherwise. - int is_suitable_for_fast_instanceof; + // for non-primitive arrays only, array_base_class is the base class + // of an array + Class* m_array_base_class; - // This points to the location where java.lang.Class associated with the current class resides. - // Similarly, java.lang.Class has a field that points to the corresponding struct Class data structure. - ManagedObject** class_handle; + // class of the element of an array + Class* m_array_element_class; - // 20030318 Gotten from the GC after gc_init() is called. - static Byte *heap_base; - static Byte *heap_end; + // size of element of array; equals zero, if this class is not an array + unsigned int m_array_element_size; - // 2003-05-13. This will be set to either NULL or heap_base depending - // on whether compressed references are used. - static Byte *managed_null; + // type descriptor for array element class + TypeDesc* m_array_element_type_desc; -//#ifdef VM_STATS - // 20020923 Total number of allocations and total number of bytes for class-related data structures. - // This includes any rounding added to make each item aligned (current alignment is to the next 16 byte boundary). - // Might need to make these uint64 for some data structures. - static unsigned num_statics_allocations; - static unsigned num_nonempty_statics_allocations; - static unsigned num_vtable_allocations; - static unsigned num_hot_statics_allocations; - static unsigned num_hot_vtable_allocations; + // Number of superinterfaces + uint16 m_num_superinterfaces; - static unsigned total_statics_bytes; - static unsigned total_vtable_bytes; - static unsigned total_hot_statics_bytes; - static unsigned total_hot_vtable_bytes; -//#endif //VM_STATS + // array of interfaces this class implements; size is m_num_superinterfaces + // initially, it is an array of string names of interfaces and then, + // after superinterfaces are loaded, this becomes an array pointers + // to superinterface class structures + Class_Super* m_superinterfaces; - Class *cha_first_child; - Class *cha_next_sibling; + // constant pool of class + ConstantPool m_const_pool; - // New field definitions start here + // number of fields in this class + uint16 m_num_fields; + // number of static fields in this class + uint16 m_num_static_fields; + // number of instance fields that are references + unsigned m_num_instance_refs; - // SourceDebugExtension support - String* sourceDebugExtension; + // array of fields; size is m_num_fields + Field* m_fields; - // class operations lock - Lock_Manager* m_lock; + // size of this class' static data block + unsigned m_static_data_size; - // List of constant pool entries, which resolution had failed - // Required for fast enumeration of error objects - Const_Pool* m_failedResolution; + // block containing array of static data fields + void* m_static_data_block; - // struct Class accessibility - unsigned m_markBit:1; + // number of methods in this class + uint16 m_num_methods; - // verify data - void *verify_data; + // array of methods; size is m_num_methods + Method* m_methods; - AnnotationTable * annotations; -} Class; // typedef struct Class + // pointer to finalize method, NULL if none exists + Method* m_finalize_method; + // pointer to method, NULL if none exists + Method* m_static_initializer; -} // extern "C" + // pointer to init()V method, cached for performance + Method* m_default_constructor; + // index of declaring class in constant pool of this class + uint16 m_declaring_class_index; -ManagedObject *struct_Class_to_java_lang_Class(Class *clss); -jclass struct_Class_to_jclass(Class *clss); -Class *jclass_to_struct_Class(jclass jc); -Class *jobject_to_struct_Class(jobject jobj); -jobject struct_Class_to_java_lang_Class_Handle(Class* clss); -Class *java_lang_Class_to_struct_Class(ManagedObject *jlc); -void set_struct_Class_field_in_java_lang_Class(const Global_Env* env, - ManagedObject** jlc, Class* clss); -void class_report_failure(Class* target, uint16 cp_index, jthrowable exn); -jthrowable class_get_linking_error(Class_Handle ch, unsigned index); -jthrowable class_get_error(ClassLoaderHandle cl, const char* name); + // index of CONSTANT_Class of outer class + uint16 m_enclosing_class_index; -void class_set_error_cause(Class *c, jthrowable exn); -jthrowable class_get_error_cause(Class *c); - -String* class_get_java_name(Class* clss, Global_Env* env); -String* class_get_simple_name(Class* clss, Global_Env* env); -// -// access modifiers -// -#define class_is_public(clss) ((clss)->access_flags & ACC_PUBLIC) -#define class_is_final(clss) ((clss)->access_flags & ACC_FINAL) -#define class_is_super(clss) ((clss)->access_flags & ACC_SUPER) -#define class_is_interface(clss) ((clss)->access_flags & ACC_INTERFACE) -#define class_is_abstract(clss) ((clss)->access_flags & ACC_ABSTRACT) -#define class_is_annotation(clss) ((clss)->access_flags & ACC_ANNOTATION) - -// -// Look up of methods and fields in class. -// Functions with the "_recursive" suffix also check superclasses. -// -VMEXPORT Field *class_lookup_field(Class *clss, const String* name, const String* desc); -VMEXPORT Field *class_lookup_field_recursive(Class *clss, const char *name, const char *descr); -Field *class_lookup_field_recursive(Class *clss, const String* name, const String* desc); -VMEXPORT Method *class_lookup_method(Class *clss, const String* name, const String* desc); -VMEXPORT Method *class_lookup_method_recursive(Class *clss, const String* name, const String* desc); -VMEXPORT Method *class_lookup_method_recursive(Class *clss, const char *name, const char *descr); -Method *class_lookup_method_init(Class*, const char*); -Method *class_lookup_method_clinit(Class*); -VMEXPORT Method *class_lookup_method(Class *clss, const char *name, const char *descr); -Method *class_get_method_from_vt_offset(VTable *vt, unsigned offset); - -VMEXPORT Java_Type class_get_cp_const_type(Class *clss, unsigned cp_index); -VMEXPORT const void *class_get_addr_of_constant(Class *clss, unsigned cp_index); -VMEXPORT Field *class_resolve_field(Class *clss, unsigned cp_index); -//VMEXPORT Field *class_resolve_static_field(Class *clss, unsigned cp_index); -VMEXPORT Field *class_resolve_nonstatic_field(Class *clss, unsigned cp_index); -//VMEXPORT Method *class_resolve_static_method(Class *clss, unsigned cp_index); -//VMEXPORT Method *class_resolve_nonstatic_method(Class *clss, unsigned cp_index); -VMEXPORT Method *class_resolve_method(Class *clss, unsigned cp_index); -VMEXPORT Class *class_resolve_class(Class *clss, unsigned cp_index); - -// Can "other_clss" access the field or method "member" -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 -// -bool class_parse(Global_Env* env, - Class* clss, - unsigned* super_class_cp_index, - ByteReader& cfs); - -const String* class_extract_name(Global_Env* env, - uint8* buffer, unsigned offset, unsigned length); - - -// -// preparation phase of class loading -// -bool class_prepare(Global_Env* env, Class *clss); - - - -// -// Load a class and perform the first two parts of the link process: verify -// and prepare. The last stage of linking, resolution, is done at JIT-time. -// See the JVM spec 2.16.3. -// - -VMEXPORT Class *class_load_verify_prepare_by_loader_jni(Global_Env* env, - const String* classname, - ClassLoader* cl); - -VMEXPORT Class *class_load_verify_prepare_from_jni(Global_Env* env, - const String* classname); - -unsigned class_calculate_size(const Class*); -void mark_classloader(ClassLoader*); -VMEXPORT void vm_notify_live_object_class(Class_Handle); - -// -// execute static initializer of class -// - -// Alexei -// migrating to C interfaces -#if (defined __cplusplus) && (defined PLATFORM_POSIX) -extern "C" { -#endif -VMEXPORT void class_initialize_from_jni(Class *clss); -#if (defined __cplusplus) && (defined PLATFORM_POSIX) -} -#endif -VMEXPORT void class_initialize_ex(Class *clss); -VMEXPORT void class_initialize(Class *clss); - - -// Notify JITs whenever this class is extended by calling their JIT_extended_class_callback callback function, -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;} + // index of CONSTANT_MethodRef of outer method + uint16 m_enclosing_method_index; - // - // 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); + // number of inner classes + uint16 m_num_innerclasses; -public: -#ifdef VM_STATS - uint64 num_accesses; - uint64 num_slow_accesses; -#endif -}; // Class_Member + struct InnerClass { + uint16 index; + uint16 access_flags; + }; + // indexes of inner classes descriptors in constant pool + InnerClass* m_innerclasses; + // annotations for this class + AnnotationTable* m_annotations; + // thread, which currently executes + VM_thread* m_initializing_thread; -/////////////////////////////////////////////////////////////////////////////// -// Fields within Class structures. -/////////////////////////////////////////////////////////////////////////////// -struct Field : public Class_Member{ -public: - //----------------------- + // error, which is the cause of changing class state to ST_Error + // enumeratable as static field + ManagedObject* m_error; - // For all fields - bool is_offset_computed() { return (_offset_computed != 0); } - void set_offset_computed(bool is_computed) { _offset_computed = is_computed? 1 : 0; } + // Notify JITs whenever tis class is extended by calling their + // JIT_extended_class_callback callback function, + Class_Extended_Notification_Record* m_notify_extended_records; - // For static fields - VMEXPORT void* get_address(); + // These fields store information for + // Class Hierarchy Analysis JIT optimizations + // first class extending this class + Class* m_cha_first_child; + // next class which extends the same superclass + Class* m_cha_next_sibling; - // Return the type of this field. - Java_Type get_java_type() { - return (Java_Type)(get_descriptor()->bytes[0]); - }; + // SourceDebugExtension class attribute support + String* m_sourceDebugExtension; - Const_Java_Value get_const_value() { return const_value; }; - uint16 get_const_value_index() { return _const_value_index; }; + // struct Class accessibility for unloading + unsigned m_markBit:1; - //----------------------- + // verifier private data pointer + void* m_verify_data; - Field() { - _const_value_index = 0; - _field_type_desc = 0; - _offset_computed = 0; - _is_injected = 0; - track_access = 0; - track_modification = 0; - } + // class operations lock + Lock_Manager* m_lock; - void Reset() { } + // Per-class statistics + // Number of times an instance of the class has been created + // using new, newarray, etc + uint64 m_num_allocations; - 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; + // Number of bytes allocated for instances of the class + uint64 m_num_bytes_allocated; - // 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; + // Number of instanceof/checkcast calls both from the user code + // and the VM that were not subsumed by the fast version of instanceof + uint64 m_num_instanceof_slow; - 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;} + // For subclasses of java.lang.Throwable only + uint64 m_num_throws; - bool parse(Class* clss, Const_Pool* cp, unsigned cp_size, ByteReader& cfs); + // Number of times class is checked for initialization + uint64 m_num_class_init_checks; - unsigned calculate_size() { - unsigned size = sizeof(Class_Member) + sizeof(Field); - size += sizeof(TypeDesc); - return size; - } + // Number of "padding" bytes added per class instance to its fields to + // make each field at least 32 bits + uint32 m_num_field_padding_bytes; +public: - TypeDesc* get_field_type_desc() { return _field_type_desc; } - void set_field_type_desc(TypeDesc* td) { _field_type_desc = td; } + /** Initializes class-member variables to their initial values. + * @param[in] env - VM environment + * @param[in] name - a class name to assign to the given class + * @param[in] cl - a class loader for the given class*/ + void init_internals(const Global_Env* env, const String* name, ClassLoader* cl); - Boolean is_injected() {return _is_injected;} - void set_injected() { _is_injected = 1; } + /** Clears member variables within a class.*/ + void clear_internals(); - void set_track_access(bool value) { - track_access = value ? 1 : 0 ; + /** Determines whether the given class has a super class. + * @return true if the current class has a super class; + * otherwise false.*/ + bool has_super_class() const { + return m_super_class.clss != NULL; } - void set_track_modification(bool value) { - track_modification = value ? 1 : 0 ; + /** Gets the name of the super class. + * + * @return The super class name or NULL, if the given class + * is java/lang/Object. + * @note It is valid until the super class is loaded; after that, use + * get_super_class()->get_name() to retrieve the + * super class name.*/ + const String* get_super_class_name() const { + return m_super_class.name; } - void get_track_access_flag(char** address, char* mask) { - *address = &track_access; - *mask = TRACK_ACCESS_MASK; + /** Gets the super class of the given class. + * @return The super class of the given class or NULL, + * if the given class is java/lang/Object.*/ + Class* get_super_class() const { + return m_super_class.clss; } - void get_track_modification_flag(char** address, char* mask) { - *address = &track_modification; - *mask = TRACK_MODIFICATION_MASK; + /** Gets the class loader of the given class. + * @return the class loader of the given class.*/ + ClassLoader* get_class_loader() const { + return m_class_loader; } + /** Gets the class handle of java.lang.Class for the given class. + * @return The java.lang.Class handle for the given class.*/ -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 + ManagedObject** get_class_handle() const { return m_class_handle; } -int get_index_of_jit(JIT *jit); + /** Gets the natively interned class name for the given class. + * @return The class name in the VM format.*/ + const String* get_name() const { return m_name; } -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; } + /** Gets a natively interned class name for the given class. + * @return A class name in the Java format.*/ + String* get_java_name() { + if(!m_java_name) { + m_java_name = class_name_get_java_name(m_name); + } + return m_java_name; + } - void set_id(int id) { _id = id; } - int get_id() { return _id; } + /** Gets a class signature. + * @return A class signature.*/ + String* get_signature() const { return m_signature; } + + /** Gets a simple name of the class. + * @return A simple name of the class.*/ + String* get_simple_name(); + + /** Gets a package containing the given class. + * @return A package to which the given class belongs.*/ + Package* get_package() const { return m_package; } + + /** Gets depth in the hierarchy of the given class. + * @return A number of classes in the super-class hierarchy.*/ + int get_depth() const { return m_depth; } + bool get_fast_instanceof_flag() const { return m_is_suitable_for_fast_instanceof; } + + /** Gets the vtable for the given class. + * @return The vtable for the given class or NULL, if the given + * class is an interface.*/ + VTable* get_vtable() const { return m_vtable; } + + /** Gets an allocation handle for the given class.*/ + Allocation_Handle get_allocation_handle() const { return m_allocation_handle; } + + /** Gets the length of the source-file name. + * @return The length in bytes of the source-file name.*/ + size_t get_source_file_name_length() { + assert(has_source_information()); + return m_src_file_name->len; + } - void set_relocatable(Boolean r) { _relocatable = r; } - Boolean get_relocatable() { return _relocatable; } + /** Gets a source-file name. + * @return A source-file name for the given class.*/ + const char* get_source_file_name() { + assert(has_source_information()); + return m_src_file_name->bytes; + } - void set_heat(unsigned heat) { _heat = heat; } - unsigned get_heat() { return _heat; } + /** Gets a method localed at method_idx in + * the m_vtable_descriptors table. + * @param method_idx - index of method in vtable descriptors table + * @return A method from the vtable descriptors table.*/ + Method* get_method_from_vtable(unsigned method_idx) const { + return m_vtable_descriptors[method_idx]; + } - void *get_code_block_addr() { return _code_block; } - void set_code_block_addr(void *addr) { _code_block = addr; } + /** Gets the first subclass for Class Hierarchy Analysis. + * @return The first subclass.*/ + Class* get_first_child() const { return m_cha_first_child; } - size_t get_code_block_size() { return _code_block_size; } - size_t get_code_block_alignment() { return _code_block_alignment; } + /** Return the next sibling for Class Hierarchy Analysis. + * @return The next sibling.*/ + Class* get_next_sibling() const { return m_cha_next_sibling; } - void set_loaded_for_vtune(bool v) { _has_been_loaded_for_vtune = v; } - bool get_loaded_for_vtune() { return _has_been_loaded_for_vtune; } + /** Gets offset of m_depth field in struct Class. + * @param dummy - dummy variable used to calculate field offset + * @note Instanceof helpers use returned offset.*/ + static size_t get_offset_of_depth(Class* dummy) { + return (size_t)((char*)(&dummy->m_depth) - (char*)dummy); + } - unsigned get_num_callees() { return _num_callees; } - Callee_Info *get_callees() { return _callee_info; } + /** Gets offset of m_is_suitable_for_fast_instanceof field in struct Class. + * @param dummy - dummy variable used to calculate field offset + * @note Instanceof helper uses returned offset.*/ + static size_t get_offset_of_fast_instanceof_flag(Class* dummy) { + return (size_t)((char*)(&dummy->m_is_suitable_for_fast_instanceof) - (char*)dummy); + } - int get_jit_index() { return get_index_of_jit(_jit); } + /** Gets an offset of m_is_fast_allocation_possible in + * the class. + * @note Allocation helpers use returned offset.*/ + size_t get_offset_of_fast_allocation_flag() { + // else one byte ld in helpers will fail + assert(sizeof(m_is_fast_allocation_possible) == 1); + return (size_t)((char*)(&m_is_fast_allocation_possible) - (char*)this); + } - // 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]; } + /** Gets an offset of m_allocation_handle in the class. + * @note Allocation helpers use returned offset.*/ + size_t get_offset_of_allocation_handle() { + return (size_t)((char*)(&m_num_class_init_checks) - (char*)this); + } - unsigned get_num_target_exception_handlers(); - Target_Exception_Handler_Ptr get_target_exception_handler_info(unsigned eh_num); + /** Gets an offset of m_instance_data_size in the class. + * @note Allocation helpers use returned offset.*/ + size_t get_offset_of_instance_data_size() { + return (size_t)((char*)(&m_instance_data_size) - (char*)this); + } - void record_call_to_callee(CodeChunkInfo *callee, void *caller_return_ip); - uint64 num_calls_to(CodeChunkInfo *other_chunk); + /** Gets an offset of m_num_class_init_checks in the class. + * @param dummy - dummy variable used to calculate field offset + * @note Class initialization helper on IPF uses returned offset.*/ + static size_t get_offset_of_class_init_checks(Class* dummy) { + return (size_t)((char*)(&dummy->m_num_class_init_checks) - (char*)dummy); + } - 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() + /** Gets the number of array dimensions. + * @return Number of dimentions in an array represented by this class.*/ + unsigned char get_number_of_dimensions() const { + assert(is_array()); + return m_num_dimensions; + } - static void initialize_code_chunk(CodeChunkInfo *chunk); + /** Gets the class of the array element. + * @return Class describing the element of an array + * represented by this class.*/ + Class* get_array_element_class() const { + assert(is_array()); + return m_array_element_class; + } -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}; + /** Gets the array-element type descriptor. + * @return Type descriptor for the element of an array + * represented by this class.*/ + TypeDesc* get_array_element_type_desc() const { + assert(is_array()); + return m_array_element_type_desc; + } - // 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); } + /** Gets the class state. + * @return The class state.*/ + Class_State get_state() const { return m_state; } + + /** Gets a number of superinterfaces. + * @return A number of superinterfaces of the given class.*/ + uint16 get_number_of_superinterfaces() const { return m_num_superinterfaces; } + + /** Gets a super-interface name from the array of super-interfaces that + * the given class implements. + * @param[in] index - an index of super-interface to return the name for + * @return The requested super-interface name.*/ + const String* get_superinterface_name(uint16 index) const { + assert(index < m_num_superinterfaces); + return m_superinterfaces[index].name; + } - // 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); } + /** Gets a superinterface from the array of superinterfaces the given class + * implements. + * @param[in] index - an index of a superinterface to return + * @return A requested superinterface.*/ + Class* get_superinterface(uint16 index) const { + assert(index < m_num_superinterfaces); + return m_superinterfaces[index].clss; + } -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 + /** Gets a constant pool of the given class. + * @return A constant pool of the given class.*/ + ConstantPool& get_constant_pool() { return m_const_pool; } + + /** Gets a number of fields in the given class. + * @return A number of fields in the given class.*/ + uint16 get_number_of_fields() const { return m_num_fields; } + + /** Gets a number of static fields in the given class. + * @return A number of static fields in the given class.*/ + uint16 get_number_of_static_fields() const { return m_num_static_fields; } + + /** Gets a field from the given class by its position in the class-fields + * array. + * @param[in] index - an index in the class-fields array of a field to + * retrieve + * @return The requested field.*/ + Field* get_field(uint16 index) const; + + /** Gets an address of the memory block containing static data of + * the given class. + * @return An address of a static data block.*/ + void* get_static_data_address() const { return m_static_data_block; } + + /** Gets a number of methods in the given class. + * @return A number of methods in the given class.*/ + uint16 get_number_of_methods() const { return m_num_methods; } + + /** Gets a method from the given class by its position in the + * class-method array. + * @param[in] index - an index in the class-method array of a + * method to retrieve + * @return A requested method.*/ + Method* get_method(uint16 index) const; + + /** Gets a constant-pool index of the declaring class. + * @return An index in the constant pool describing the requested + * declaring class.*/ + uint16 get_declaring_class_index() const { return m_declaring_class_index; } + + /** Gets a constant-pool index of the enclosing class. + * @return An index in the constant pool describing the requested + * enclosing class.*/ + uint16 get_enclosing_class_index() const { return m_enclosing_class_index; } + + /** Gets a constant-pool index of the enclosing method. + * @return An index in the constant pool describing the requested enclosing + * method.*/ + uint16 get_enclosing_method_index() const { return m_enclosing_method_index; } + + /** Gets a number of inner classes. + * @return A number of inner classes.*/ + uint16 get_number_of_inner_classes() const { return m_num_innerclasses; } + + /** Gets an index in the constant pool of the given class, which + * describes the inner class. + * @param[in] index - an index of the inner class in the array of + * inner classes in the given class + * @return An index in the constant pool describing the requested inner + * class.*/ + uint16 get_inner_class_index(uint16 index) const { + assert(index < m_num_innerclasses); + return m_innerclasses[index].index; + } -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; + /** Gets access flags for the inner class. + * @param[in] index - an index of the inner class in the array of inner + * classes in the given class + * @return Access flags of the requested inner class.*/ + uint16 get_inner_class_access_flags(uint16 index) const { + assert(index < m_num_innerclasses); + return m_innerclasses[index].access_flags; } - // 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; + /** Gets a collection of annotations. + * @return A collection of annotations.*/ + AnnotationTable* get_annotations() const { return m_annotations; } + + /** Gets a handle of exception making the class change its state + * to ST_Error. + * @return A handle of exception.*/ + jthrowable get_error_cause() const { + assert(in_error()); + return (jthrowable)(&m_error); } -}; - - -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; }; + /** Gets a class instance size. + * @return A size of the allocated instance in bytes.*/ + unsigned int get_allocated_size() const { return m_allocated_size; } + unsigned int get_instance_data_size() const { + return m_instance_data_size & NEXT_TO_HIGH_BIT_CLEAR_MASK; + } -private: - State _state; - void *_code; - VTable_Patches *_vtable_patch; + /** Gets the array-alement size. + * @return A size of the array element. + * @note The given function assumes that the class is an array class.*/ + unsigned int get_array_element_size() const { + assert(m_is_array == 1); + return m_array_element_size; + } - NativeCodePtr _counting_stub; + /** Gets the class ID.*/ + unsigned get_id() const { return m_id; } + + /** Gets access and properties flags of the given class. + * @return The 16-bit integer representing access and properties flags + * the given class.*/ + uint16 get_access_flags() const { return m_access_flags; } + + /** Checks whether the given class represents the primitive type. + * @return true if the class is primitive; otherwise + * false.*/ + bool is_primitive() const { return m_is_primitive == 1; } + + /** Checks whether the given class represents an array. + * @return true if the given class is an array, otherwise + * false.*/ + bool is_array() const { return m_is_array == 1; } + + /** Checks whether the base class of the given array is primitive. + * @return true if the base class is primitive, otherwise + * false.*/ + bool is_array_of_primitives() const { return m_is_array_of_primitives == 1; } + + /** Checks whether the class has the ACC_PUBLIC flag set. + * @return true if the class has the ACC_PUBLIC + * access flag set.*/ + bool is_public() const { return (m_access_flags & ACC_PUBLIC) != 0; } + + /** Checks whether the class has the ACC_PUBLIC flag set. + * @return true if the class has the ACC_PUBLIC + * access flag set.*/ + bool is_private() const { return (m_access_flags & ACC_PRIVATE) != 0; } + + /** Checks whether the class has the ACC_PUBLIC flag set. + * @return true if the class has the ACC_PUBLIC + * access flag set.*/ + bool is_protected() const { return (m_access_flags & ACC_PROTECTED) != 0; } + + /** Checks whether the class has the ACC_FINAL flag set. + * @return true if the class has the ACC_FINAL + * access flag set.*/ + bool is_final() const { return (m_access_flags & ACC_FINAL) != 0; } + + /** Checks whether the class has the ACC_SUPER flag set. + * @return true if the class has the ACC_SUPER + * access flag set.*/ + + bool is_super() const { return (m_access_flags & ACC_SUPER) != 0; } + + /** Checks whether the class has the ACC_INTERFACE flag set. + * @return true if the class has the ACC_INTERFACE + * access flag set.*/ + + bool is_interface() const { return (m_access_flags & ACC_INTERFACE) != 0; } + + /** Checks whether the class has the ACC_ABSTRACT flag set. + * @return true if the class has the ACC_ABSTRACT + * access flag set.*/ + bool is_abstract() const { return (m_access_flags & ACC_ABSTRACT) != 0; } + + /** Checks whether the class is enum, that is the ACC_ENUM + * flag is set. + * @return true if the class is enum.*/ + bool is_enum() const { return (m_access_flags & ACC_ENUM) != 0; } + + /** Checks whether the class is an annotation. + * @return true if the class is an annotation.*/ + bool is_annotation() const { return (m_access_flags & ACC_ANNOTATION) != 0; } + + /** Checks whether the given class has a finalizer. + * @return true if the given class (or its super class) has + * a finalize method; otherwise false.*/ + bool has_finalizer() const { return m_has_finalizer == 1; } + + /** Checks whether the given class is an inner class of some other class. + * @return true if the given class is an inner class of some + * other class, otherwise false.*/ + bool is_inner_class() const { return m_declaring_class_index != 0; } + + /** Checks whether the given class can access inner_class. + * @param[in] env - VM environment + * @param[in] inner_class - an inner class to check access to + * @return true if the given class has access to the inner + * class; otherwise false.*/ + bool can_access_inner_class(Global_Env* env, Class* inner_class); + + /** Checks whether the given class can access a member class. + * @param[in] member - a class member to check access to + * @return true if the given class can access a member class; + * otherwise false.*/ + bool can_access_member(Class_Member* member); + + /** Checks whether the given class has a source-file name available. + * @return true if source file name is available for the given class; + * otherwise false.*/ + bool has_source_information() const { return m_src_file_name != NULL; } + + /** Checks whether the given class is in the process of initialization. + * @return true if the class initialization method is executed; + * otherwise false.*/ + + bool is_initializing() const { return m_state == ST_Initializing; } + + /** Checks whether the class is initialized. + * @return true if the class is initialized; + * otherwise false.*/ + + bool is_initialized() const { return m_state == ST_Initialized; } + + /** Checks whether the class is in the error state. + * @return true if the class is in the error state; + * otherwise false.*/ + bool in_error() const { return m_state == ST_Error; } + + /** Checks whether the given class has a passed preparation stage. + * @return true if the class has a passed preparation stage; + * otherwise false.*/ + bool is_at_least_prepared() const { + return m_state == ST_Prepared + || m_state == ST_ConstraintsVerified + || m_state == ST_Initializing + || m_state == ST_Initialized; + } - CodeChunkInfo *_jits; + /** Checks whether the given class represents a class that is a subtype of + * clss, according to the Java instance of rules. + * @param[in] clss - a class to check for being super relative + * @return true if the given class represents a class that is + * a subtype of clss, otherwise false.*/ + bool is_instanceof(Class* clss); + + /** FIXME: all setter functions must be rethought to become private + * or to be removed altogether, if possible. + * Sets the name of a file from which the given class has been loaded. + * @param[in] cf_name - a class-file name*/ + void set_class_file_name(const String* cf_name) { + assert(cf_name); + m_class_file_name = cf_name; + } - Method_Side_Effects _side_effects; - Method_Signature *_method_sig; + /** Sets instance data size constraint bit to let the allocation know + * there are constraints on the way instance should be allocated. + * @note Constaints are recorded in the class_properties + * field of the class VTable.*/ + void set_instance_data_size_constraint_bit() { + m_instance_data_size |= NEXT_TO_HIGH_BIT_SET_MASK; + } -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(); + /** Sets a class handle of java.lang.Class for the given class. + * @param[in] oh - a class handle of java.lang.Class*/ + void set_class_handle(ManagedObject** oh) { m_class_handle = oh; } + + /** Records a cause of changing state to ST_Error for the given + * class. + * @param[in] exn - an exception object with error*/ + void set_error_cause(jthrowable exn); + + /** Constructs internal representation of a class from the byte array + * (defines class). + * @param[in] env - VM environment + * @param[in] cfs - a class-file stream; byte array contaning class data*/ + bool parse(Global_Env* env, ByteReader& cfs); + + /** Loads a super class and super interfaces of the given class. + * The given class's class loader is used for it. + * @param[in] env - VM environment*/ + bool load_ancestors(Global_Env* env); + + /** Verifies bytecodes of the class. + * @param[in] env - VM environment + * @return true if bytecodes of a class were successfully verified; + * otherwise false.*/ + bool verify(const Global_Env* env); + + /** Verifies constraints for the given class collected during the bytecodes + * verification. + * @param[in] env - VM environment + * @return true if constraints successfully pass verification; + * otherwise false.*/ + bool verify_constraints(const Global_Env* env); + + /** Setups the given class as representing a primitive type. + * @param[in] cl - a class loader the given class belongs to + * @note FIXME: cl is always a bootstrap class loader + * for primitive types. Retrieve the bootstrap class loader + * from VM environment here, not one level up the calling stack.*/ + void setup_as_primitive(ClassLoader* cl) { + m_is_primitive = 1; + m_class_loader = cl; + m_access_flags = ACC_ABSTRACT | ACC_FINAL | ACC_PUBLIC; + m_state = ST_Initialized; + } - // - // 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; + /** Sets up the given class as representing an array. + * @param[in] env - VM environment + * @param[in] num_dimentions - a number of dimentions this array has + * @param[in] isArrayOfPrimitives - does this array is an array of primitives + * @param[in] baseClass - base class of this array; for example, + * for [[[Ljava/lang/String; + * base class is java/lang/String + * @param[in] elementClass - class representing element of this array; + * for example, for [[I, element + * the class is [I + * @note For single-dimentional arrays baseClass and + * elementClass are the same.*/ + void setup_as_array(Global_Env* env, unsigned char num_dimensions, + bool isArrayOfPrimitives, Class* baseClass, Class* elementClass); + + /** Prepares a class:
    + *
  1. assigns offsets: + * - the offset of instance data fields + * - virtual methods in a vtable + * - static data fields in a static data block
  2. + *
  3. creates a class vtable
  4. + *
  5. creates a static field block
  6. + *
  7. creates a static method block
+ * @param[in] env - vm environment + * @return true if the class was successfully prepared; + * otherwise false.*/ + bool prepare(Global_Env* env); + + /** Resolves a constant-pool entry to a class. Loads a class if neccessary. + * @param[in] env - VM environment + * @param[in] cp_index - a constant-pool index of CONSTANT_Class + * to resolve + * @return A resolved class, if a resolution attempt succeeds; + * otherwise NULL. + * @note Should become private as soon as wrappers become members of the + * struct #Class.*/ + Class* _resolve_class(Global_Env* env, unsigned cp_index); + + /** Resolves a declaring class. + * @return A declaring class, if the given class is inner class of some + * other class and if the resolution was successful; + * otherwise NULL.*/ + Class* resolve_declaring_class(Global_Env* env); + + /** Resolves a field in the constant pool of the given class. + * @param[in] env - VM environment + * @param[in] cp_index - an index of an entry in the constant pool, + * which describes field to be resolved + * @return A resolved field, if a resolution attempt succeeds; + * otherwise NULL. + * @note Should become private as soon as wrappers + * become members of the struct #Class.*/ + Field* _resolve_field(Global_Env* env, unsigned cp_index); + + /** Resolves a method in the constant pool of the given class. + * @param[in] env - VM environment + * @param[in] cp_index - an index of an entry in the constant pool, + * which describes method to be resolved + * @return A resolved method, if a resolution attempt succeeds; + * otherwise NULL. + * @note Should become private as soon as wrappers become members of + * the struct #Class.*/ + Method* _resolve_method(Global_Env* env, unsigned cp_index); + + /** Initializes the class. + * @param[in] throw_exception - defines whether the exception should + * be thrown or raised + * @note The given method may raise exception, if an error occurs during + * the initialization of the class.*/ + void initialize(); + + /** Looks up the field with specified name and descriptor in the given class only. + * @param[in] name - the field name to look up for + * @param[in] desc - the field descriptor to look up for + * @return The looked up field if found in the given class, + * otherwise NULL.*/ + Field* lookup_field(const String* name, const String* descriptor); + + /** Looks up the field with specified name and descriptor in the given class + * and also in the super class and super-interfaces recursively. + * @param[in] name - field name to look up for + * @param[in] desc - field descriptor to look up for + * @return The looked up field if found, NULL otherwise*/ + Field* lookup_field_recursive(const String* name, const String* descriptor); + + /** Looks up a method with a specified name and descriptor in the given + * class only. + * @param[in] name - a method name to look up for + * @param[in] desc - a method descriptor to look up for + * @return The looked-up method, if found in the given class; + * otherwise NULL.*/ + Method* lookup_method(const String* name, const String* desc); + + /** Allocates an instance of the given class and returns a pointer to it. + * @return A managed pointer to the allocated class instance; + * NULL, if no memory is available and + * OutOfMemoryError exception is raised on a + * caller thread.*/ + ManagedObject* allocate_instance(); + + /** Calculates a size of the block allocated for the array, which is represented by + * the given class. + * @param[in] length - the length of the array + * @return The size of the array of specified length in bytes.*/ + unsigned calculate_array_size(int length) const { + assert(length >= 0); + assert(is_array()); + assert(m_array_element_size); + unsigned first_elem_offset; + if(m_array_element_size < 8) { + first_elem_offset = VM_VECTOR_FIRST_ELEM_OFFSET_1_2_4; + } else { + first_elem_offset = VM_VECTOR_FIRST_ELEM_OFFSET_8; + } + unsigned size = first_elem_offset + length*m_array_element_size; + size = (((size + (GC_OBJECT_ALIGNMENT - 1)) & (~(GC_OBJECT_ALIGNMENT - 1)))); + assert((size % GC_OBJECT_ALIGNMENT) == 0); 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); + /** Estimates the amount of memory allocated for C++ part of the given class. + * @return The size of memory allocated for the given class.*/ + unsigned calculate_size(); + + /** Gets the interface vtable for interface iid within + * object obj. + * @param[in] obj - an object to retrieve an interface table entry from + * @param[in] iid - an interface class to retrieve vtable for + * @return An interface vtable from object; NULL, if no + * such interface exists for the object.*/ + void* helper_get_interface_vtable(ManagedObject* obj, Class* iid); + + /** Registers a callback that is called to notify the given JIT + * whenever the given class is extended. The callback_data + * pointer will be passed back to the JIT during the callback. The JIT's callback + * function is JIT_extended_class_callback. + * @param[in] jit_to_be_notified - JIT to notify on extending the class + * @param[in] callback_data - data to be passed back to JIT, when the callback + * is called*/ + void register_jit_extended_class_callback(JIT* jit_to_be_notified, void* callback_data); + + /** Calls registered JITs callbacks to notify that the given class was + * extended by new_class. + * @param[in] new_subclass - a subclass extending the given class*/ + void do_jit_extended_class_callbacks(Class* new_subclass); + + // SourceDebugExtension class attribute support + + /** Checks whether the given class has the + * SourceDebugExtension attribute. + * @return true if the SourceDebugExtension + * attribute is available for the given class; + * otherwise false.*/ + bool has_source_debug_extension() const { + return m_sourceDebugExtension != NULL; + } - unsigned get_num_param_annotations() {return _num_param_annotations;} - AnnotationTable * get_param_annotations(unsigned index) { - return index < _num_param_annotations ? _param_annotations[index] : NULL; + /** Gets length of the SourceDebugExtension attribute. + * @return The SourceDebugExtension attribute length.*/ + unsigned get_source_debug_extension_length() const { + return m_sourceDebugExtension->len; } - 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; + /** Gets data from the SourceDebugExtension attribute. + * @return SourceDebugExtension attribute bytes.*/ + const char* get_source_debug_extension() const { + return m_sourceDebugExtension->bytes; + } - // - // private methods for parsing methods - // - bool _parse_code(Const_Pool *cp, unsigned cp_size, unsigned code_attr_len, ByteReader &cfs); + // Class unloading support - bool _parse_line_numbers(unsigned attr_len, ByteReader &cfs); + /** Checks whether the given class is reachable through its loader + * or any live object. + * @return true if the given class is reachable, + * otherwise false.*/ + bool is_reachable() { return m_markBit == 1; } - bool _parse_exceptions(Const_Pool *cp, unsigned cp_size, unsigned attr_len, - ByteReader &cfs); + /** Clears a reachability mark.*/ + void reset_reachable() { m_markBit = 0; } - void _set_nop(); + /** Marks the given class as reachable.*/ + void mark_reachable() { m_markBit = 1; } - // - // debugging info - // - Line_Number_Table *_line_number_table; - Local_Var_Table *_local_vars_table; + /** Stores a verifier specific pointer into the given class. + * @param[in] data - a verifier specific data pointer*/ + void set_verification_data(void* data) { + assert(m_verify_data == NULL); + m_verify_data = data; + } - bool _parse_local_vars(const char* attr_name, Local_Var_Table** lvt_address, - Const_Pool *cp, unsigned cp_size, unsigned attr_len, ByteReader &cfs); + /** Gets a pointer to verifier specific data, previously stored with + * the call to set_verification_data. + * @return A pointer to verifier specific data or NULL, if + * none was set.*/ + void* get_verification_data() { + return m_verify_data; + } - // 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: + /** Locks access to the given class.*/ + void lock(); - unsigned get_line_number_table_size() { - return (_line_number_table) ? _line_number_table->length : 0; - } + /** Unlocks access to the given class.*/ + void unlock(); - bool get_line_number_entry(unsigned index, jlong* pc, jint* line); + // Statistics update - unsigned get_local_var_table_size() { - return (_local_vars_table) ? _local_vars_table->length : 0; + /** Updates allocation statistics. + * @param[in] size - a size of an allocated instance*/ + void instance_allocated(unsigned size) { + m_num_allocations++; + m_num_bytes_allocated += size; } - bool get_local_var_entry(unsigned index, jlong* pc, - jint* length, jint* slot, String** name, String** type, - String** generic_type); + /** Updates an instance of slow path statistics.*/ + void instanceof_slow_path_taken() { m_num_instanceof_slow++; } - // XXX - //bool get_local_var_entry(unsigned index, jlong* pc, - // jint* length, jint* slot, String** name, String** type); + /** Updates throwing statistics for java/lang/Throwable decendants.*/ + void class_thrown() { m_num_throws++; } + /** Updates initialization check statistics.*/ + void initialization_checked() { m_num_class_init_checks++; } - // 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); + /** Gets the number of times instance of the given class was allocated. + * @return The number of allocations of the given class.*/ + uint64 get_times_allocated() const { return m_num_allocations; } - Inline_Record *inline_records; - void set_inline_assumption(JIT *jit, Method *caller); - void method_was_overridden(); + /** Gets the total number of bytes allocated for instances of the given class. + * @return The number of bytes allocated for all instances of the given class.*/ + uint64 get_total_bytes_allocated() const { return m_num_bytes_allocated; } - Method_Change_Notification_Record *_notify_override_records; + /** Gets the number of times the slow path of the check instance was taken. + * @return The number of times the slow path was taken.*/ + uint64 get_times_instanceof_slow_path_taken() const { return m_num_instanceof_slow; } - // Records JITs to be notified when a method is recompiled or initially compiled. - Method_Change_Notification_Record *_notify_recompiled_records; + /** Gets the number of times the given class was thrown. + * @return The number of times the given class was thrown.*/ + uint64 get_times_thrown() const { return m_num_throws; } - void lock(); - void unlock(); + /** Gets the number of times the initialization of the given class + * was checked by run-time helpers. + * @return The number of times initialization of the given class was checked.*/ + uint64 get_times_init_checked() const { return m_num_class_init_checks; } + + /** Gets the number of excessive bytes used for aligning class fields. + * @return A number of excessive bytes used for aligning class fields.*/ + uint64 get_total_padding_bytes() const { return m_num_field_padding_bytes; } +private: + + /** Parses super-interfaces information from a class-file stream. + * @param[in] cfs - a class-file stream to parse superinterfaces information from + * @return true if information was succesfully parsed; + * otherwise false.*/ + bool parse_interfaces(ByteReader &cfs); + + /** Parses class fields from a class-file stream. + * @param[in] env - VM enviroment + * @param[in] cfs - a class-file stream + * @return true if successfully parses fields; false + * if any parse error occurs.*/ + bool parse_fields(Global_Env* env, ByteReader &cfs); + + /** Parses class methods from a class-file stream. + * @param[in] env - VM enviroment + * @param[in] cfs - a class file stream + * @return true if successfully parses methods; false + * if any parse error occurs.*/ + bool parse_methods(Global_Env* env, ByteReader &cfs); + + /** Calculates and assigns offsets to class fields during preparation.*/ + void assign_offsets_to_fields(); + + /** Assign offsets to class-instance fields. + * @param[in] field_ptrs - an array of class fields to assign + * offsets to + * @param[in] do_field_compaction - defines whether the class fields should + * be compacted*/ + void assign_offsets_to_instance_fields(Field** field_ptrs, bool do_field_compaction); + + /** Assigns an offset to an instance field. + * @param[in] field - a field to calculate offset for + * @param[in] do_field_compaction - defines whether the class fields should + * be compacted*/ + void assign_offset_to_instance_field(Field* field, bool do_field_compaction); + + /** Assigns offsets to static fields of a class. + * @param[in] field_ptrs - an array of fields + * @param[in] do_field_compaction - defines whether the class fields should + * be compacted*/ + void assign_offsets_to_static_fields(Field** field_ptrs, bool do_field_compaction); + + /** Initializes an interface class. + * @return true if the interface was successfully initialized; + * otherwise false.*/ + bool initialize_static_fields_for_interface(); + + /** Assigns offsets (from the base of the vtable) and the VTable index to + * class methods. + * @param[in] env - VM environment*/ + void assign_offsets_to_methods(Global_Env* env); + + /** Creates the vtable for the given class. + * @param[in] n_vtable_entries - a number of entries for the vtable*/ + void create_vtable(unsigned n_vtable_entries); + + /** Populates the vtable descriptors table with methods overriding as neccessary.*/ + void populate_vtable_descriptors_table_and_override_methods(); + + /** Creates and populates an interface table for a class. + * @return The created interface table.*/ + Intfc_Table* create_and_populate_interface_table(); + + /** Constructs an interface table descriptors table.*/ + void build_interface_table_descriptors(); + + /** Sets vtable entries to methods addresses.*/ + void point_vtable_entries_to_stubs(); + + /** Adds any required "fake" methods to a class. These are interface methods + * inherited by an abstract class that are not implemented by that class + * or any superclass. Such methods will never be called, but they are added + * so they have the correct offset in the virtual method part of the vtable + * (that is the offset of the "real" method in the vtable for a concrete class).*/ + void add_any_fake_methods(); +}; // struct Class +} // extern "C" - 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); - -#define BITS_PER_BYTE 8 -// We want to use signed arithmetic when we do allocation pointer/limit compares. -// In order to do this all sizes must be positive so when we want to overflow instead of -// setting the high bit we set the next to high bit. If we set the high bit and the allocation buffer -// is at the top of memory we might not detect an overflow the unsigned overflow would produce -// a small positive number that is smaller then the limit. - -#define NEXT_TO_HIGH_BIT_SET_MASK (1<<((sizeof(unsigned) * BITS_PER_BYTE)-2)) -#define NEXT_TO_HIGH_BIT_CLEAR_MASK ~NEXT_TO_HIGH_BIT_SET_MASK - -inline unsigned int get_instance_data_size (Class *c) -{ - return (c->instance_data_size & NEXT_TO_HIGH_BIT_CLEAR_MASK); -} - -inline void set_instance_data_size_constraint_bit (Class *c) -{ - c->instance_data_size = (c->instance_data_size | NEXT_TO_HIGH_BIT_SET_MASK); -} - -// Setter functions for the class property field. -inline void set_prop_alignment_mask (Class *c, unsigned int the_mask) -{ - c->class_properties = (c->class_properties | the_mask); - c->vtable->class_properties = c->class_properties; - set_instance_data_size_constraint_bit (c); -} -inline void set_prop_non_ref_array (Class *c) -{ - c->class_properties = (c->class_properties | CL_PROP_NON_REF_ARRAY_MASK); - c->vtable->class_properties = c->class_properties; -} -inline void set_prop_array (Class *c) -{ - c->class_properties = (c->class_properties | CL_PROP_ARRAY_MASK); - c->vtable->class_properties = c->class_properties; -} -inline void set_prop_pinned (Class *c) -{ - c->class_properties = (c->class_properties | CL_PROP_PINNED_MASK); - c->vtable->class_properties = c->class_properties; - set_instance_data_size_constraint_bit (c); -} -inline void set_prop_finalizable (Class *c) -{ - c->class_properties = (c->class_properties | CL_PROP_FINALIZABLE_MASK); - c->vtable->class_properties = c->class_properties; - set_instance_data_size_constraint_bit (c); -} - -// get functions for the class property field. -inline unsigned int get_prop_alignment (unsigned int class_properties) -{ - return (unsigned int)(class_properties & CL_PROP_ALIGNMENT_MASK); -} -inline unsigned int get_prop_non_ref_array (unsigned int class_properties) -{ - return (class_properties & CL_PROP_NON_REF_ARRAY_MASK); -} -inline unsigned int get_prop_array (unsigned int class_properties) -{ - return (class_properties & CL_PROP_ARRAY_MASK); -} -inline unsigned int get_prop_pinned (unsigned int class_properties) -{ - return (class_properties & CL_PROP_PINNED_MASK); -} -inline unsigned int get_prop_finalizable (unsigned int class_properties) -{ - return (class_properties & CL_PROP_FINALIZABLE_MASK); -} - -VMEXPORT Class_Handle vtable_get_class(VTable_Handle vh); -/** - * Function registers a number of native methods to a given class. - * - * @param klass - specified class - * @param methods - array of methods - * @param num_methods - number of methods - * - * @return FALSE if methods resistration is successful, - * otherwise - TRUE. - * - * @note Function raises NoSuchMethodError with method name in exception message - * if one of the methods in JNINativeMethod* array is not present in a specified class. - */ +/** Gets instance of java/lang/Class associated with this class. + * @param[in] clss - class to retrieve java/lang/Class instance for. + * @return Instance of java/lang/Class associated with class.*/ +ManagedObject* struct_Class_to_java_lang_Class(Class* clss); +/** Gets handle of java/lang/Class instance associated with this class. + * @param[in] clss - class to retrieve handle with java/lang/Class instance for. + * @return Handle with instance of java/lang/Class associated with class. + * @note This function allocates local handle and stores reference to + * java/lang/Class into it.*/ +jclass struct_Class_to_jclass(Class* clss); +/** Gets native class from the java/lang/Class handle. + * @param[in] jc - handle to retrieve struct Class from. + * @return Class for the given handle.*/ +Class* jclass_to_struct_Class(jclass jc); +/** Gets native class for any given object handle. + * @param[in] jobj - object to retrieve class for. + * @return Class for the given object handle.*/ +Class* jobject_to_struct_Class(jobject jobj); +/** Gets pointer to instance of java/lang/Class associated with the class. + * @param[in] clss - class to retrieve pointer to instance of java/lang/Class for. + * @return Pointer to instance of java/lang/Class associated with the class. + * @note This is NOT real handle, so, when using this function, make sure the + * returned value will never be passed to ANY user code including JVMTI + * agent callbacks.*/ +jobject struct_Class_to_java_lang_Class_Handle(Class* clss); +/** Gets native class from instance of java/lang/Class. + * @param[in] jlc - instance of java/lang/Class to retrieve class from. + * @return Native class from instance of java/lang/Class.*/ +Class* java_lang_Class_to_struct_Class(ManagedObject* jlc); +/** Gets loading error for a class with the given name. + * @param[in] cl - class loader which attempted to load the class. + * @param[in] name - name of a class which loading had failed. + * @return Exception describing class loading failure.*/ +jthrowable class_get_error(ClassLoaderHandle cl, const char* name); + +/** Looks up field in class and its superclasses. + * @param[in] clss - class to lookup field in. + * @param[in] name - name of the field. + * @param[in] desc - descriptor of the field. + * @return Requested field, if the field exists, NULL otherwise.*/ +Field* class_lookup_field_recursive(Class* clss, const char* name, const char* desc); +/** Looks up method in class and its superclasses. + * @param[in] clss - class to lookup method in. + * @param[in] name - name of the method as VM String. + * @param[in] desc - descriptor of the method as VM String. + * @return Requested method, if the method exists, + * NULL otherwise. + * @note VMEXPORT specifier is solely for interpreter.*/ +VMEXPORT +Method* class_lookup_method_recursive(Class* clss, const String* name, const String* desc); +/** Looks up method in class and its superclasses. + * @param[in] clss - class to lookup method in. + * @param[in] name - name of the method. + * @param[in] desc - descriptor of the method. + * @return Requested method, if the method exists, + * NULL otherwise.*/ +Method* class_lookup_method_recursive(Class* clss, const char* name, const char* desc); +/** Looks up method in the given class only. + * @param[in] clss - class to lookup method in. + * @param[in] name - name of the method. + * @param[in] desc - descriptor of the method. + * @return Requested method, if the method exists, + * NULL otherwise.*/ +Method* class_lookup_method(Class* clss, const char* name, const char* desc); +/** Gets method given its offset in the vtable. + * @param[in] vt - vtable containing method. + * @param[in] offset - offset of the method in the vtable. + * @return Method at the specified offset.*/ +Method* class_get_method_from_vt_offset(VTable* vt, unsigned offset); +/** Resolves non-static field at the specified index in + * the constant pool of the class. + * @param[in] clss - class to resolve field in. + * @param[in] cp_index - index in the constant pool of the class. + * @return Resolved field, if resolution succeeded, + * NULL otherwise.*/ +Field* class_resolve_nonstatic_field(Class* clss, unsigned cp_index); + + +/** Loads a class and performs the first two parts of the link process: + * verify and prepare. + * @param[in] env - VM environment. + * @param[in] classname - name of a class to load. + * @param[in] cl - class loader to load class with. + * @return Loaded class, if loading and linking succeeded, + * NULL otherwise.*/ +Class* class_load_verify_prepare_by_loader_jni(Global_Env* env, + const String* classname, + ClassLoader* cl); + +/** Loads a class with bootstrap class loader and performs the first two parts + * of the link process: verify and prepare. + * @param[in] env - VM environment. + * @param[in] classname - name of a class to load. + * @param[in] cl - class loader to load class with. + * @return Loaded class, if loading and linking succeeded, + * NULL otherwise. + * @note The class is loaded .*/ +Class* class_load_verify_prepare_from_jni(Global_Env* env, + const String* classname); + +/** Executes static initializer of class. + * @param[in] clss - class to initialize.*/ +void class_initialize_from_jni(Class *clss); +/** Executes static initializer of class. + * @param[in] clss - class to initialize.*/ +void class_initialize_ex(Class *clss); +/** Executes static initializer of class. + * @param[in] clss - class to initialize. + * @note VMEXPORT specifier is solely for interpreter.*/ +VMEXPORT +void class_initialize(Class *clss); + + +/** Registers a number of native methods to a given class. + * @param[in] klass - a specified class + * @param[in] methods - an array of methods + * @param[in] num_methods - a number of methods + * @return false, if methods resistration is successful; + * otherwise true. + * @note Function raises NoSuchMethodError with the method name in + * exception message, if one of the methods in the JNINativeMethod* + * array is not present in a specified class.*/ bool class_register_methods(Class_Handle klass, const JNINativeMethod* methods, int num_methods); -/** - * Function unregisters a native methods of a given class. - * - * @param klass - specified class - * - * @return FALSE if methods unresistration is successful, - * otherwise - TRUE. - */ +/** Unregisters a native methods off a given class. + * @param[in] klass - specified class + * @return false, if methods unresistration is successful; + * otherwise true.*/ bool class_unregister_methods(Class_Handle klass); diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/String_Pool.h b/enhanced/drlvm/trunk/vm/vmcore/include/String_Pool.h index 69954b8..75b7999 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/String_Pool.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/String_Pool.h @@ -30,30 +30,29 @@ #define STRING_PADDING 4 -extern "C" { - typedef struct String { +struct String +{ #ifdef _DEBUG - unsigned id; // id for debugging + unsigned id; // id for debugging #endif - // 20030507 Ref to the interned string used by java.lang.String.intern(). - // It is compressed when compressing refs. - union { - // raw reference to interned string if not compressing references - ManagedObject * raw_ref; - // equivalent compressed reference. - uint32 compressed_ref; - } intern; - unsigned len; - char bytes[STRING_PADDING]; - } String; -} + // 20030507 Ref to the interned string used by java.lang.String.intern(). + // It is compressed when compressing refs. + union { + // raw reference to interned string if not compressing references + ManagedObject * raw_ref; + // equivalent compressed reference. + uint32 compressed_ref; + } intern; + unsigned len; + char bytes[STRING_PADDING]; +}; class String_Pool { public: String_Pool(); // lookup string in string table & insert if not found - VMEXPORT String * lookup(const char *str); + String * lookup(const char *str); String * lookup(const char *str, unsigned len); // Iterators for GC diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/Verifier_stub.h b/enhanced/drlvm/trunk/vm/vmcore/include/Verifier_stub.h deleted file mode 100644 index 2f35f40..0000000 --- a/enhanced/drlvm/trunk/vm/vmcore/include/Verifier_stub.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ -/** - * @author Pavel Rebriy - * @version $Revision: 1.1.2.1.4.4 $ - */ - -#ifndef _VERIFIER_STUB_H_ -#define _VERIFIER_STUB_H_ - -#include "environment.h" -#include "Class.h" - -bool class_verify(const Global_Env* env, Class* klass); -bool class_verify_constraints(const Global_Env* env, Class* klass); - -#endif // _VERIFIER_STUB_H_ 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..996c0f6 --- /dev/null +++ b/enhanced/drlvm/trunk/vm/vmcore/include/annotation.h @@ -0,0 +1,93 @@ +/* + * 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__ + +struct String; + +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..b5cd08e --- /dev/null +++ b/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h @@ -0,0 +1,761 @@ +/* + * 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 "annotation.h" +#include "Class.h" +#include "jit_intf.h" + +struct String; +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. +/////////////////////////////////////////////////////////////////////////////// +class 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_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, not used, always zero + // 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(unsigned off) { _offset = off; _offset_computed = 1; } + + // For static fields + 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; + 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]; +}; + + +struct Method : public Class_Member { + friend void add_new_fake_method(Class* clss, Class* example, unsigned* next); + friend void add_any_fake_methods(Class* clss); + //----------------------- +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() const { return _n_handlers; } + Handler* get_bc_exception_handler_info(unsigned eh_number) { + assert(eh_number < _n_handlers); + return _handlers + 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() { + return initialize_arg_list_iterator(_descriptor->bytes); + } + + // 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() const { return _arguments_size; } + + // 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() { + const char *descr = get_descriptor()->bytes; + while(*descr != ')') descr++; + return (Java_Type)*(descr + 1); + } + + // 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; } + + /// Sets index in vtable and offset from the base of vtable for this method + /// @param index - index in vtable + /// @param offset - for instance methods: offset from the base of vtable + void set_position_in_vtable(unsigned index, unsigned offset) { + assert(!is_static()); + _index = index; + _offset = offset; + } +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); + + void calculate_arguments_size(); + + 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; + } + + 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 + unsigned _arguments_size; // size of method arguments on the stack + 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) { + if(!_line_number_table) return -1; + Line_Number_Table* lnt = _line_number_table; + for(int i = 0; i < lnt->length - 1; i++) { + if(bc >= lnt->table[i].start_pc && bc < lnt->table[i+1].start_pc) + return lnt->table[i].line_number; + } + if(bc >= lnt->table[lnt->length-1].start_pc && bc < _byte_code_length) + return lnt->table[lnt->length-1].line_number; + return -1; + } + + 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/classloader.h b/enhanced/drlvm/trunk/vm/vmcore/include/classloader.h index 9e679e9..f36e879 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/classloader.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/classloader.h @@ -36,6 +36,7 @@ #include "hashtable.h" #include "loggerstring.h" #include "jarfile_support.h" +#include "type.h" class ClassTable : public MapEx {}; @@ -187,12 +188,13 @@ public: } void InsertClass(Class* clss) { LMAutoUnlock aulock(&m_lock); - m_loadedClasses->Insert(clss->name, clss); - m_initiatedClasses->Insert(clss->name, clss); + m_loadedClasses->Insert(clss->get_name(), clss); + m_initiatedClasses->Insert(clss->get_name(), clss); } Class* AllocateAndReportInstance(const Global_Env* env, Class* klass); Class* NewClass(const Global_Env* env, const String* name); ManagedObject** RegisterClassInstance(const String* className, ManagedObject* instance); + Package* ProvidePackage(Global_Env* env, const String *class_name, const char *jar); Class* DefineClass(Global_Env* env, const char* class_name, uint8* bytecode, unsigned offset, unsigned length, const String** res_name = NULL); Class* LoadClass( Global_Env* UNREF env, const String* UNREF name); @@ -221,8 +223,6 @@ public: protected: virtual Class* DoLoadClass( Global_Env* UNREF env, const String* UNREF name) = 0; Class* StartLoadingClass(Global_Env* env, const String* className); - bool FinishLoadingClass(Global_Env *env, Class* clss, - unsigned int* super_class_cp_index); void RemoveLoadingClass(const String* className, LoadingClass* loading); void SuccessLoadingClass(const String* className); void AddFailedClass(const String* className, const jthrowable exn); @@ -298,10 +298,8 @@ protected: // methods Class* WaitDefinition(Global_Env* env, const String* className); Class* SetupAsArray(Global_Env* env, const String* klass); - Package* ProvidePackage(Global_Env* env, const String *class_name, const char *jar); private: - Class* InitClassFields(const Global_Env* env, Class* clss, const String* name); void FieldClearInternals(Class*); // clean Field internals in Class }; // class ClassLoader diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/environment.h b/enhanced/drlvm/trunk/vm/vmcore/include/environment.h index 109fe26..983ffbb 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/environment.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/environment.h @@ -68,6 +68,27 @@ struct Global_Env { bool verify_all; // psrebriy 20050815 Verify all classes including loaded by bootstrap class loader bool pin_interned_strings; // if true, interned strings are never moved + // If set to true by the "-compact_fields" command line option, + // the VM will not pad out fields of less than 32 bits to four bytes. + // However, fields will still be aligned to a natural boundary, + // and the num_field_padding_bytes field will reflect those alignment padding bytes. + bool compact_fields; + + // If set to true by the "-sort_fields" command line option, + // the VM will sort fields by size before assigning their offset during + // class preparation. + bool sort_fields; + + // Base address of Java heap + Byte* heap_base; + // Ceiling of Java heap. + // NOTE: we assume Java heap uses one continuous memory block. + Byte* heap_end; + + // This will be set to either NULL or heap_base depending + // on whether compressed references are used. + Byte* managed_null; + // // preloaded strings // diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/jni_direct.h b/enhanced/drlvm/trunk/vm/vmcore/include/jni_direct.h index a542a89..e719d57 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/jni_direct.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/jni_direct.h @@ -29,7 +29,8 @@ #include "open/types.h" #include "jni.h" -#include "Class.h" +#include "open/types.h" +#include "class_member.h" typedef struct JavaVM_Internal JavaVM_Internal; typedef struct JNIEnv_Internal JNIEnv_Internal; diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/jni_utils.h b/enhanced/drlvm/trunk/vm/vmcore/include/jni_utils.h index 5686f60..e2b70fb 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/jni_utils.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/jni_utils.h @@ -23,9 +23,7 @@ #ifndef _JNI_UTILS_H_ #define _JNI_UTILS_H_ -#include "environment.h" #include "object_handles.h" -#include "platform.h" #include "jni_direct.h" #include "ini.h" #include "String_Pool.h" @@ -53,8 +51,6 @@ VMEXPORT Method* LookupMethod (Class*, c VMEXPORT char* ParameterTypesToMethodSignature (JNIEnv*, jobjectArray, const char *name); VMEXPORT char PrimitiveNameToSignature (const char*); -VMEXPORT Boolean class_is_subclass(Class_Handle subclss, Class_Handle superclss); - #ifdef __cplusplus } #endif @@ -82,9 +78,6 @@ void PrimitiveSignatureToName (const cha const char* SignatureToName (const char* sig); void SignatureToName (const char* sig, char *name); -jclass struct_Class_to_jclass(Class *c); -Class *jclass_to_struct_Class(jclass jc); - jclass FindClassWithClassLoader(JNIEnv* env_ext, const char *name, ClassLoader *loader); jclass FindClassWithClassLoader(JNIEnv* env_ext, String*name, ClassLoader *loader); diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h b/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h index bc48f16..cd44818 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 @@ #include "jni_direct.h" #include "jvmti.h" +#include "vm_core_types.h" struct TIEventThread { diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/lock_manager.h b/enhanced/drlvm/trunk/vm/vmcore/include/lock_manager.h index 509a018..f42b332 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/lock_manager.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/lock_manager.h @@ -33,11 +33,11 @@ class Lock_Manager { public: - VMEXPORT Lock_Manager(); - VMEXPORT ~Lock_Manager(); + Lock_Manager(); + ~Lock_Manager(); - VMEXPORT void _lock(); - VMEXPORT void _unlock(); + void _lock(); + void _unlock(); bool _tryLock(); void _lock_enum(); diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/method_lookup.h b/enhanced/drlvm/trunk/vm/vmcore/include/method_lookup.h index 5e7229a..f13933f 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/method_lookup.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/method_lookup.h @@ -33,8 +33,8 @@ enum VM_Code_Type { }; -VMEXPORT VM_Code_Type vm_identify_eip(void *addr); -VM_Code_Type vm_identify_eip_deadlock_free(void *addr); +VM_Code_Type vm_identify_eip(void *addr); +VM_Code_Type vm_identify_eip_deadlock_free(void *addr); diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/object_handles.h b/enhanced/drlvm/trunk/vm/vmcore/include/object_handles.h index 935548a..4932ac8 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/object_handles.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/object_handles.h @@ -38,9 +38,8 @@ * A function creates handles for the references and passes the handles rather than the references. */ - -#include "object_layout.h" #include "vm_core_types.h" +#include "object_layout.h" #include "jni.h" /** diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/object_layout.h b/enhanced/drlvm/trunk/vm/vmcore/include/object_layout.h index c620670..05e1c11 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/object_layout.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/object_layout.h @@ -43,13 +43,58 @@ typedef struct VTable VTable; extern "C" { #endif +/// Raw and compressed reference pointers + +typedef ManagedObject* RAW_REFERENCE; +typedef uint32 COMPRESSED_REFERENCE; + +VMEXPORT bool is_compressed_reference(COMPRESSED_REFERENCE value); +VMEXPORT bool is_null_compressed_reference(COMPRESSED_REFERENCE value); + +VMEXPORT COMPRESSED_REFERENCE compress_reference(ManagedObject *obj); +VMEXPORT ManagedObject* uncompress_compressed_reference(COMPRESSED_REFERENCE compressed_ref); +VMEXPORT ManagedObject* get_raw_reference_pointer(ManagedObject **slot_addr); + +// Store the reference "VALUE" in the slot at address "SLOT_ADDR" +// in the object "CONTAINING_OBJECT". +// Signature: void store_reference(ManagedObject* CONTAINING_OBJECT, +// ManagedObject** SLOT_ADDR, +// ManagedObject* VALUE); +#define STORE_REFERENCE(CONTAINING_OBJECT, SLOT_ADDR, VALUE) \ + { \ + if (VM_Global_State::loader_env->compress_references) { \ + gc_heap_slot_write_ref_compressed((Managed_Object_Handle)(CONTAINING_OBJECT), \ + (uint32*)(SLOT_ADDR), \ + (Managed_Object_Handle)(VALUE)); \ + } else { \ + gc_heap_slot_write_ref((Managed_Object_Handle)(CONTAINING_OBJECT), \ + (Managed_Object_Handle*)(SLOT_ADDR), \ + (Managed_Object_Handle)(VALUE)); \ + } \ + } + +// Store the reference "VALUE" in the static field or +// other global slot at address "SLOT_ADDR". +// Signature: void store_global_reference(COMPRESSED_REFERENCE* SLOT_ADDR, +// ManagedObject* VALUE); +#define STORE_GLOBAL_REFERENCE(SLOT_ADDR, VALUE) \ + { \ + if (VM_Global_State::loader_env->compress_references) { \ + gc_heap_write_global_slot_compressed((uint32*)(SLOT_ADDR), \ + (Managed_Object_Handle)(VALUE)); \ + } else { \ + gc_heap_write_global_slot((Managed_Object_Handle*)(SLOT_ADDR), \ + (Managed_Object_Handle)(VALUE)); \ + } \ + } + // // Built-in types // -// Note: if the header layout of the object changes, VM_VECTOR_RT_OVERHEAD must changed -// below as well. +// Note: if the header layout of the object changes, VM_VECTOR_RT_OVERHEAD +// must be changed below as well. typedef struct ManagedObjectCompressedVtablePtr { uint32 vt_offset; uint32 obj_info; diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/vm_arrays.h b/enhanced/drlvm/trunk/vm/vmcore/include/vm_arrays.h index c5794c5..d562b65 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/vm_arrays.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/vm_arrays.h @@ -30,21 +30,10 @@ #include "open/vm_util.h" #include "heap.h" -inline unsigned vm_array_size(VTable *vector_vtable, int length) -{ - unsigned array_element_size = vector_vtable->array_element_size; - assert(array_element_size); - unsigned first_elem_offset; - if(array_element_size < 8) { - first_elem_offset = VM_VECTOR_FIRST_ELEM_OFFSET_1_2_4; - } else { - first_elem_offset = VM_VECTOR_FIRST_ELEM_OFFSET_8; - } - unsigned size = first_elem_offset + length * array_element_size; - size = ( ((size + (GC_OBJECT_ALIGNMENT - 1)) & (~(GC_OBJECT_ALIGNMENT - 1))) ); - assert((size % GC_OBJECT_ALIGNMENT) == 0); - return size; -} //vm_array_size + +#define HIGH_BIT_SET_MASK (1<<((sizeof(unsigned) * BITS_PER_BYTE)-1)) +#define HIGH_BIT_CLEAR_MASK (~HIGH_BIT_SET_MASK) +#define TWO_HIGHEST_BITS_SET_MASK (HIGH_BIT_SET_MASK|NEXT_TO_HIGH_BIT_SET_MASK) inline VTable *get_vector_vtable(Vector_Handle vector) diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/vm_log.h b/enhanced/drlvm/trunk/vm/vmcore/include/vm_log.h index f6c7031..38d2f4e 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/vm_log.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/vm_log.h @@ -22,8 +22,12 @@ #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" +#include "Class.h" /** * @file @@ -47,7 +51,7 @@ inline LoggerString& operator<<(LoggerSt */ inline LoggerString& operator<<(LoggerString& log, const Class* clss) { if (clss) { - log << clss->name; + log << clss->get_name(); } else { log << ""; } diff --git a/enhanced/drlvm/trunk/vm/vmcore/include/vm_stats.h b/enhanced/drlvm/trunk/vm/vmcore/include/vm_stats.h index 8fa4f2e..dfd0c40 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/include/vm_stats.h +++ b/enhanced/drlvm/trunk/vm/vmcore/include/vm_stats.h @@ -14,10 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** +/** * @author Intel, Alexei Fedotov * @version $Revision: 1.1.2.1.4.3 $ - */ + */ #ifndef _VM_STATS_H_ #define _VM_STATS_H_ @@ -223,10 +223,24 @@ public: uint64 codemgr_total_code_allocated; uint64 codemgr_total_data_pool_size; uint64 codemgr_total_data_allocated; - + uint64 num_compileme_generated; uint64 num_compileme_used; + // Total number of allocations and total number of bytes for class-related + // data structures. This includes any rounding added to make each item + // aligned (current alignment is to the next 16 byte boundary). + uint64 num_statics_allocations; + uint64 num_nonempty_statics_allocations; + uint64 num_vtable_allocations; + uint64 num_hot_statics_allocations; + uint64 num_hot_vtable_allocations; + + uint64 total_statics_bytes; + uint64 total_vtable_bytes; + uint64 total_hot_statics_bytes; + uint64 total_hot_vtable_bytes; + SimpleHashtable rt_function_map; SimpleHashtable rt_function_requests; SimpleHashtable rt_function_calls; 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..a1fc8b4 --- /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 methods +} 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 4bb45aa..479b18e 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,42 +32,41 @@ #include "open/hythread_ext.h" #include "thread_manager.h" +#include "cci.h" -#include "Verifier_stub.h" #include "class_interface.h" #include "Package.h" -Boolean class_property_is_final(Class_Handle cl) { +Boolean class_property_is_final(Class_Handle cl) { assert(cl); - return class_is_final((Class*)cl); + return cl->is_final(); } -Boolean class_property_is_abstract(Class_Handle cl) { +Boolean class_property_is_abstract(Class_Handle cl) { assert(cl); - return class_is_abstract((Class*)cl); + return cl->is_abstract(); } -Boolean class_property_is_interface2(Class_Handle cl) { +Boolean class_property_is_interface2(Class_Handle cl) { assert(cl); - return class_is_interface((Class*)cl); + return cl->is_interface(); } - Boolean class_is_array(Class_Handle cl) { assert(cl); - return ((Class*)cl)->is_array; + return cl->is_array(); } //class_is_array Boolean class_get_array_num_dimensions(Class_Handle cl) { assert(cl); - return ((Class*)cl)->n_dimensions; + return cl->get_number_of_dimensions(); } const char* class_get_package_name(Class_Handle cl) { assert(cl); - return ((Class*)cl)->package->get_name()->bytes; + return cl->get_package()->get_name()->bytes; } Boolean method_is_abstract(Method_Handle m) { @@ -125,12 +124,12 @@ unsigned field_get_offset(Field_Handle f -void *field_get_addr(Field_Handle f) +void* field_get_address(Field_Handle f) { assert(f); - assert(((Field *)f)->is_static()); - return ((Field *)f)->get_address(); -} //field_get_addr + assert(f->is_static()); + return f->get_address(); +} // field_get_address @@ -522,40 +521,36 @@ Method_Handle method_get_method_jit(Meth const char* class_get_name(Class_Handle cl) { assert(cl); - return ((Class *)cl)->name->bytes; + return cl->get_name()->bytes; } //class_get_name -char* class_get_java_name(Class_Handle ch) -{ - assert(ch); - return class_get_java_name((Class *)ch, VM_Global_State::loader_env)->bytes; -} + unsigned class_get_flags(Class_Handle cl) { assert(cl); - return ((Class *)cl)->access_flags; + return cl->get_access_flags(); } //class_get_flags int class_get_super_offset() { - return sizeof(VTable *); + return sizeof(VTable*); } //class_get_super_offset -//#ifdef FAST_INSTOF int vtable_get_super_array_offset() { VTable *vtable = 0; return (int) (((Byte *)&vtable->superclasses) - (Byte *)vtable); }//vtable_get_super_array_offset + int class_get_depth(Class_Handle cl) { assert(cl); - return ((Class *)cl)->depth; + return cl->get_depth(); } //class_get_depth -//#endif + VMEXPORT Class_Handle vtable_get_class(VTable_Handle vh) { @@ -565,8 +560,7 @@ Class_Handle vtable_get_class(VTable_Han Boolean class_is_initialized(Class_Handle ch) { assert(ch); - Class *clss = (Class *)ch; - return clss->state == ST_Initialized; + return ch->is_initialized(); } //class_is_initialized @@ -574,9 +568,7 @@ Boolean class_is_initialized(Class_Handl Boolean class_needs_initialization(Class_Handle ch) { assert(ch); - Class *clss = (Class *)ch; - //LMAutoUnlock init_state_lock(clss->m_lock); - return clss->state != ST_Initialized; + return !ch->is_initialized(); } //class_needs_initialization @@ -584,7 +576,7 @@ Boolean class_needs_initialization(Class Boolean class_has_non_default_finalizer(Class_Handle cl) { assert(cl); - return ((Class *)cl)->has_finalizer == 1; + return cl->has_finalizer(); } //class_has_non_default_finalizer @@ -592,57 +584,51 @@ Boolean class_has_non_default_finalizer( Class_Handle class_get_super_class(Class_Handle cl) { assert(cl); -//sundr printf("class %p %p\n", cl, cl->super_class); - return (Class_Handle)((Class *)cl)->super_class; + return cl->get_super_class(); } //class_get_super_class unsigned class_number_implements(Class_Handle ch) { assert(ch); - return ((Class*)ch)->n_superinterfaces; + return ch->get_number_of_superinterfaces(); } Class_Handle class_get_implements(Class_Handle ch, unsigned idx) { assert(ch); - return (Class_Handle)((Class*)ch)->superinterfaces[idx].clss; + return ch->get_superinterface(idx); } Class_Handle class_get_declaring_class(Class_Handle ch) { - Class* clss = (Class*)ch; - assert(clss); - uint16 cp_index = clss->declaringclass_index; - if (cp_index==0) return NULL; - return class_resolve_class(clss, cp_index); + return ch->resolve_declaring_class(VM_Global_State::loader_env); } unsigned class_number_inner_classes(Class_Handle ch) { assert(ch); - return ((Class*)ch)->n_innerclasses; + return ch->get_number_of_inner_classes(); } Boolean class_is_inner_class_public(Class_Handle ch, unsigned idx) { assert(ch); - return ((Class*)ch)->innerclass_indexes[2*idx+1] & ACC_PUBLIC; + return (ch->get_inner_class_access_flags(idx) & ACC_PUBLIC) != 0; } Class_Handle class_get_inner_class(Class_Handle ch, unsigned idx) { assert(ch); - Class* clss = (Class*)ch; - uint16 cp_index = clss->innerclass_indexes[2*idx]; - return class_resolve_class(clss, cp_index); + uint16 cp_index = ch->get_inner_class_index(idx); + return ch->_resolve_class(VM_Global_State::loader_env, cp_index); } Boolean class_is_instanceof(Class_Handle s, Class_Handle t) { assert(s); assert(t); - return class_is_subtype((Class *)s, (Class *)t); + return class_is_subtype(s, t); } //class_get_super_class @@ -650,7 +636,7 @@ Boolean class_is_instanceof(Class_Handle Class_Handle class_get_array_element_class(Class_Handle cl) { assert(cl); - return (Class_Handle)((Class *)cl)->array_element_class; + return cl->get_array_element_class(); } //class_get_array_element_class @@ -730,41 +716,23 @@ Class_Handle class_get_class_of_primitiv VTable_Handle class_get_vtable(Class_Handle cl) { assert(cl); - return ((Class *)cl)->vtable; + return cl->get_vtable(); } //class_get_vtable -const char *class_get_source_file_name(Class_Handle cl) -{ - if (cl == 0) return 0; - if ( ((Class *)cl)->src_file_name == 0 ) - return 0; - return ((Class *)cl)->src_file_name->bytes; -} //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) +const char* class_get_source_file_name(Class_Handle cl) { 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 - + if(!cl->has_source_information()) + return NULL; + return cl->get_source_file_name(); +} // class_get_source_file_name -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->get_constant_pool().get_string_chars(index); } //class_get_const_string @@ -775,8 +743,8 @@ const char *class_get_const_string(Class void *class_get_const_string_intern_addr(Class_Handle cl, unsigned index) { assert(cl); - Global_Env *env = VM_Global_State::loader_env; - String *str = class_get_const_string_handle(cl, index); + Global_Env* env = VM_Global_State::loader_env; + String* str = cl->get_constant_pool().get_string(index); assert(str); bool must_instantiate; @@ -794,7 +762,6 @@ void *class_get_const_string_intern_addr vm_instantiate_cp_string_resolved(str); END_RAISE_AREA; tmn_suspend_enable(); - } if (env->compress_references) { @@ -808,23 +775,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->get_constant_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->get_constant_pool().is_fieldref(cp_index)); char class_id = (class_get_cp_entry_signature(src_class, cp_index))[0]; switch(class_id) @@ -858,7 +823,32 @@ VM_Data_Type class_get_cp_field_type(Cla VM_Data_Type class_get_const_type(Class_Handle cl, unsigned index) { assert(cl); - return (VM_Data_Type)class_get_cp_const_type((Class *)cl, index); + Java_Type jt = JAVA_TYPE_INVALID; + ConstantPool& cp = cl->get_constant_pool(); + switch(cp.get_tag(index)) { + case CONSTANT_String: + jt = JAVA_TYPE_STRING; + break; + case CONSTANT_Integer: + jt = JAVA_TYPE_INT; + break; + case CONSTANT_Float: + jt = JAVA_TYPE_FLOAT; + break; + case CONSTANT_Long: + jt = JAVA_TYPE_LONG; + break; + case CONSTANT_Double: + jt = JAVA_TYPE_DOUBLE; + break; + case CONSTANT_Class: + jt = JAVA_TYPE_CLASS; + break; + default: + DIE("non-constant type is requested from constant pool : " << cp.get_tag(index)); + } + + return (VM_Data_Type)jt; } //class_get_const_type @@ -866,7 +856,7 @@ VM_Data_Type class_get_const_type(Class_ const void *class_get_const_addr(Class_Handle cl, unsigned index) { assert(cl); - return class_get_addr_of_constant((Class *)cl, index); + return cl->get_constant_pool().get_address_of_constant(index); } //class_get_const_addr @@ -907,7 +897,7 @@ vm_resolve_class_new(Compile_Handle h, Class_Handle resolve_class_from_constant_pool(Class_Handle c_handle, unsigned index) { assert(c_handle); - return class_resolve_class(c_handle, index); + return c_handle->_resolve_class(VM_Global_State::loader_env, index); } @@ -916,20 +906,19 @@ ClassLoaderHandle class_get_class_loader(Class_Handle ch) { assert(ch); - return ch->class_loader; + return ch->get_class_loader(); } //class_get_class_loader Class_Handle class_load_class_by_name(const char *name, - Class_Handle c) + Class_Handle ch) { - assert(c); + assert(ch); Global_Env *env = VM_Global_State::loader_env; String *n = env->string_pool.lookup(name); - Class *clss = ((Class *)c)->class_loader->LoadClass(env, n); - return (Class_Handle)clss; + return ch->get_class_loader()->LoadClass(env, n); } //class_load_class_by_name @@ -947,9 +936,9 @@ class_load_class_by_name_using_system_cl Class_Handle class_load_class_by_descriptor(const char *descr, - Class_Handle c) + Class_Handle ch) { - assert(c); + assert(ch); Global_Env *env = VM_Global_State::loader_env; String *n; switch(descr[0]) { @@ -982,8 +971,7 @@ class_load_class_by_descriptor(const cha n = 0; } assert(n); - Class *clss = ((Class *)c)->class_loader->LoadClass( env, n); - return (Class_Handle)clss; + return ch->get_class_loader()->LoadClass(env, n);; } //class_load_class_by_descriptor @@ -1050,148 +1038,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->get_constant_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->get_constant_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->get_constant_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->get_constant_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->get_constant_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->get_constant_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->get_constant_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->get_constant_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->get_constant_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->get_constant_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) @@ -1207,7 +1195,7 @@ Class_Handle method_get_throws(Method_Ha Method* m = (Method*)mh; String* exn_name = m->get_exception_name(idx); if (!exn_name) return NULL; - ClassLoader* class_loader = m->get_class()->class_loader; + ClassLoader* class_loader = m->get_class()->get_class_loader(); Class *c = class_loader->LoadVerifyAndPrepareClass(VM_Global_State::loader_env, exn_name); if (!c && !exn_raised()) { @@ -1392,7 +1380,7 @@ int vector_first_element_offset_unboxed( assert(element_type); Class *clss = (Class *)element_type; int offset = 0; - if(clss->is_primitive) { + if(clss->is_primitive()) { Global_Env *env = VM_Global_State::loader_env; if(clss == env->Double_Class) { offset = VM_VECTOR_FIRST_ELEM_OFFSET_8; @@ -1472,7 +1460,7 @@ Boolean class_is_compact_field() Boolean class_is_enum(Class_Handle ch) { assert(ch); - return ((ch->access_flags & ACC_ENUM) == 0) ? FALSE : TRUE; + return ch->is_enum() ? TRUE : FALSE; } //class_is_enum @@ -1549,8 +1537,7 @@ Boolean field_is_unmanaged_static(Field_ Boolean class_is_primitive(Class_Handle ch) { assert(ch); - Class *clss = (Class *)ch; - return clss->is_primitive; + return ch->is_primitive(); } //class_is_primitive @@ -1620,7 +1607,7 @@ void Method_Signature::initialize_from_j assert(meth); num_args = meth->get_num_args(); - ClassLoader* cl = meth->get_class()->class_loader; + ClassLoader* cl = meth->get_class()->get_class_loader(); const char* d = meth->get_descriptor()->bytes; assert(d[0]=='('); d++; @@ -1702,14 +1689,13 @@ Boolean method_args_has_this(Method_Sign unsigned class_number_fields(Class_Handle ch) { assert(ch); - return ((Class*)ch)->n_fields; + return ch->get_number_of_fields(); } unsigned class_num_instance_fields(Class_Handle ch) { assert(ch); - Class *clss = (Class *)ch; - return clss->n_fields - clss->n_static_fields; + return ch->get_number_of_fields() - ch->get_number_of_static_fields(); } //class_num_instance_fields @@ -1723,25 +1709,21 @@ unsigned class_num_instance_fields_recur ch = class_get_super_class(ch); } return num_inst_fields; -} //class_num_instance_fields_recursive +} // class_num_instance_fields_recursive Field_Handle class_get_field(Class_Handle ch, unsigned idx) { assert(ch); - Class* clss = (Class*)ch; - if (idx>=clss->n_fields) return NULL; - return clss->fields+idx; -} + if(idx >= ch->get_number_of_fields()) return NULL; + return ch->get_field(idx); +} // class_get_field Field_Handle class_get_instance_field(Class_Handle ch, unsigned idx) { assert(ch); - Class *clss = (Class *)ch; - assert( (unsigned short)idx < clss->n_fields - clss->n_static_fields); - Field *f = clss->fields + clss->n_static_fields + idx; - return f; -} //class_get_instance_field + return ch->get_field(ch->get_number_of_static_fields() + idx); +} // class_get_instance_field @@ -1750,7 +1732,7 @@ Field_Handle class_get_instance_field_re assert(ch); unsigned num_fields_recursive = class_num_instance_fields_recursive(ch); assert(idx < num_fields_recursive); - while (ch) { + while(ch) { unsigned num_fields = class_num_instance_fields(ch); unsigned num_inherited_fields = num_fields_recursive - num_fields; if(idx >= num_inherited_fields) { @@ -1761,25 +1743,23 @@ Field_Handle class_get_instance_field_re ch = class_get_super_class(ch); } return 0; -} //class_get_instance_field_recursive +} // class_get_instance_field_recursive unsigned class_get_number_methods(Class_Handle ch) { assert(ch); - return ((Class*)ch)->n_methods; -} //class_get_number_methods + return ch->get_number_of_methods(); +} // class_get_number_methods Method_Handle class_get_method(Class_Handle ch, unsigned index) { assert(ch); - Class *clss = (Class *)ch; - if (index >= clss->n_methods) { + if(index >= ch->get_number_of_methods()) return NULL; - } - return (clss->methods + index); -} //class_get_method + return ch->get_method(index); +} // class_get_method // -gc magic needs this to do the recursive load. @@ -1789,9 +1769,9 @@ Class_Handle field_get_class_of_field_va assert(fh); Class_Handle ch = class_load_class_by_descriptor(field_get_descriptor(fh), field_get_class(fh)); - if(!class_verify(VM_Global_State::loader_env, ch)) + if(!ch->verify(VM_Global_State::loader_env)) return NULL; - if(!class_prepare(VM_Global_State::loader_env, ch)) + if(!ch->prepare(VM_Global_State::loader_env)) return NULL; return ch; } //field_get_class_of_field_value @@ -2033,8 +2013,8 @@ Class_Handle type_info_get_class(Type_In assert(td); Class* c = td->load_type_desc(); if(!c) return NULL; - if(!class_verify(VM_Global_State::loader_env, c)) return NULL; - if(!class_prepare(VM_Global_State::loader_env, c)) return NULL; + if(!c->verify(VM_Global_State::loader_env)) return NULL; + if(!c->prepare(VM_Global_State::loader_env)) return NULL; return c; } //type_info_get_class @@ -2098,8 +2078,7 @@ Type_Info_Handle field_get_type_info_of_ Type_Info_Handle class_get_element_type_info(Class_Handle ch) { assert(ch); - Class *clss = (Class *)ch; - TypeDesc* td = clss->array_element_type_desc; + TypeDesc* td = ch->get_array_element_type_desc(); assert(td); return td; } //class_get_element_type_info @@ -2109,46 +2088,34 @@ Type_Info_Handle class_get_element_type_ ///////////////////////////////////////////////////// // New GC stuff - - Boolean class_is_non_ref_array(Class_Handle ch) { assert(ch); - Class *clss = (Class *)ch; // Use the if statement to normalize the value of TRUE - if(get_prop_non_ref_array(clss->class_properties)) { - assert (class_is_array(ch)); + if((ch->get_vtable()->class_properties & CL_PROP_NON_REF_ARRAY_MASK) != 0) + { + assert(ch->is_array()); return TRUE; } else { return FALSE; } -} //class_is_pinned +} // class_is_non_ref_array + Boolean class_is_pinned(Class_Handle ch) { assert(ch); - Class *clss = (Class *)ch; - // Use the if statement to normalize the value of TRUE - if(get_prop_pinned(clss->class_properties)) { - return TRUE; - } else { - return FALSE; - } -} //class_is_pinned - + return (ch->get_vtable()->class_properties & CL_PROP_PINNED_MASK) != 0 + ? TRUE : FALSE; +} // class_is_pinned Boolean class_is_finalizable(Class_Handle ch) { assert(ch); - Class *clss = (Class *)ch; - // Use the if statement to normalize the value of TRUE - if(get_prop_finalizable(clss->class_properties)) { - return TRUE; - } else { - return FALSE; - } -} //class_is_finalizable + return (ch->get_vtable()->class_properties & CL_PROP_FINALIZABLE_MASK) != 0 + ? TRUE : FALSE; +} // class_is_finalizable WeakReferenceType class_is_reference(Class_Handle clss) { @@ -2170,16 +2137,15 @@ int class_get_referent_offset(Class_Hand if (!referent) { DIE("Class " << class_get_name(ch) << " have no 'Object referent' field"); } - int offset = field_get_offset(referent); - return offset; + return referent->get_offset(); } unsigned class_get_alignment(Class_Handle ch) { assert(ch); - Class *clss = (Class *)ch; - return get_prop_alignment(clss->class_properties); + return (unsigned)(ch->get_vtable()->class_properties + & CL_PROP_ALIGNMENT_MASK); } //class_get_alignment @@ -2197,9 +2163,7 @@ unsigned class_get_alignment_unboxed(Cla unsigned class_element_size(Class_Handle ch) { assert(ch); - assert (class_is_array(ch)); - Class *clss = (Class *)ch; - return clss->array_element_size; + return ch->get_array_element_size(); } //class_element_size @@ -2207,8 +2171,7 @@ unsigned class_element_size(Class_Handle unsigned class_get_boxed_data_size(Class_Handle ch) { assert(ch); - Class *clss = (Class *)ch; - return clss->allocated_size; + return ch->get_allocated_size(); } //class_get_boxed_data_size @@ -2257,19 +2220,18 @@ Method_Handle method_find_overridden_met { assert(ch); assert(mh); - Class *clss = (Class *)ch; Method *method = (Method *)mh; - assert(!class_is_interface(clss)); // ch cannot be an interface + assert(!ch->is_interface()); // ch cannot be an interface const String *name = method->get_name(); const String *desc = method->get_descriptor(); Method *m = NULL; - for(; clss; clss = clss->super_class) { - m = class_lookup_method(clss, name, desc); + for(; ch; ch = ch->get_super_class()) { + m = ch->lookup_method(name, desc); if (m != NULL) { - // The method m can only override mh/method if m's class can access mh/method (JLS 6.6.5). - Class *m_clss = m->get_class(); - if (check_member_access(method, m_clss) == 1) { + // The method m can only override mh/method + // if m's class can access mh/method (JLS 6.6.5). + if(m->get_class()->can_access_member(method)) { break; } } @@ -2307,8 +2269,8 @@ Managed_Object_Handle *vector_get_elemen unsigned vm_vector_size(Class_Handle vector_class, int length) { assert(vector_class); - return vm_array_size(((Class *) vector_class)->vtable, length); -} //vm_vector_size + return vector_class->calculate_array_size(length); +} // vm_vector_size @@ -2361,13 +2323,13 @@ VMEXPORT Boolean vm_references_are_compr VMEXPORT void *vm_heap_base_address() { - return (void *)Class::heap_base; + return (void*)VM_Global_State::loader_env->heap_base; } //vm_heap_base_address VMEXPORT void *vm_heap_ceiling_address() { - return (void *)Class::heap_end; + return (void *)VM_Global_State::loader_env->heap_end; } //vm_heap_ceiling_address @@ -2397,20 +2359,20 @@ Class_Handle allocation_handle_get_class Allocation_Handle class_get_allocation_handle(Class_Handle ch) { assert(ch); - return ((Class *) ch)->allocation_handle; + return ch->get_allocation_handle(); } Runtime_Type_Handle class_get_runtime_type_handle(Class_Handle ch) { assert(ch); - return (Runtime_Type_Handle) ((Class *) ch)->allocation_handle; + return (Runtime_Type_Handle)ch->get_allocation_handle(); } unsigned vm_get_runtime_type_handle_width() { - if (vm_vtable_pointers_are_compressed()) + if(vm_vtable_pointers_are_compressed()) { return sizeof(uint32); } @@ -2466,25 +2428,24 @@ int vm_max_fast_instanceof_depth() // is extended. The callback_data pointer will be passed back to the JIT during the callback. // The callback function is JIT_extended_class_callback. void vm_register_jit_extended_class_callback(JIT_Handle jit, Class_Handle clss, - void *callback_data) + void* callback_data) { assert(clss); - JIT *jit_to_be_notified = (JIT *)jit; + JIT* jit_to_be_notified = (JIT*)jit; Class *c = (Class *)clss; - class_register_jit_extended_class_callback(c, jit_to_be_notified, callback_data); -} //vm_register_jit_extended_class_callback + clss->register_jit_extended_class_callback(jit_to_be_notified, callback_data); +} // vm_register_jit_extended_class_callback // Called by a JIT in order to be notified whenever the given method is overridden by a newly // loaded class. The callback_data pointer will be passed back to the JIT during the callback. // The callback function is JIT_overridden_method_callback. void vm_register_jit_overridden_method_callback(JIT_Handle jit, Method_Handle method, - void *callback_data) + void* callback_data) { assert(method); - JIT *jit_to_be_notified = (JIT *)jit; - Method *m = (Method *)method; - m->register_jit_overridden_method_callback(jit_to_be_notified, callback_data); + JIT* jit_to_be_notified = (JIT*)jit; + method->register_jit_overridden_method_callback(jit_to_be_notified, callback_data); } //vm_register_jit_overridden_method_callback @@ -2547,7 +2508,7 @@ Boolean class_iterator_initialize(ChaCla chaClassIterator->_root_class = root_class; // Partial implementation for now. - if (!class_is_interface((Class *)root_class) && !class_is_array(root_class)) + if (!root_class->is_interface() && !root_class->is_array()) { chaClassIterator->_is_valid = TRUE; chaClassIterator->_current = root_class; @@ -2563,29 +2524,29 @@ Class_Handle class_iterator_get_current( } // class_iterator_get_current -void class_iterator_advance(ChaClassIterator *chaClassIterator) +void class_iterator_advance(ChaClassIterator* chaClassIterator) { if (!chaClassIterator->_is_valid) return; if (chaClassIterator->_current == NULL) return; - Class *clss = (Class *) chaClassIterator->_current; - if (clss->cha_first_child != NULL) + Class* clss = (Class*)chaClassIterator->_current; + if(clss->get_first_child() != NULL) { - chaClassIterator->_current = (Class_Handle) clss->cha_first_child; + chaClassIterator->_current = (Class_Handle)clss->get_first_child(); return; } - Class *next = clss; - while (next != NULL) + Class* next = clss; + while(next != NULL) { - if (next->cha_next_sibling != NULL) + if(next->get_next_sibling() != NULL) { - next = next->cha_next_sibling; + next = next->get_next_sibling(); break; } - next = next->super_class; + next = next->get_super_class(); } - if (next != NULL && next->depth <= ((Class *) chaClassIterator->_root_class)->depth) + if(next != NULL && next->get_depth() <= chaClassIterator->_root_class->get_depth()) next = NULL; chaClassIterator->_current = next; } // class_iterator_advance @@ -2650,7 +2611,7 @@ void method_iterator_advance(ChaMethodIt chaClassIterator->_current = NULL; return; } - Method *next = class_lookup_method(c, name, desc); + Method *next = c->lookup_method(name, desc); if (next != NULL && next->get_class() == c) { chaClassIterator->_current = (Method_Handle) next; 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 fc227ab..8ebbd9f 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp @@ -24,51 +24,397 @@ #include +#include + #include "Class.h" +#include "classloader.h" #include "environment.h" #include "lock_manager.h" #include "exceptions.h" #include "compile.h" #include "open/gc.h" #include "nogc.h" +#include "vm_stats.h" +#include "jit_intf_cpp.h" +#include "type.h" + +// +// private static variable containing the id of the next class +// access to this needs to be thread safe; also, this will have to +// change if we want to reuse class ids +// +// an id of 0 is reserved to mean null; therefore, ids start from 1 +// +// ppervov: FIXME: usage of this variable is not currently thread safe +unsigned class_next_id = 1; + +void Class::init_internals(const Global_Env* env, const String* name, ClassLoader* cl) +{ + memset(this, 0, sizeof(Class)); + + m_super_class.name = NULL; + m_name = name; + m_simple_name = m_java_name = m_signature = NULL; + + m_allocated_size = 0; + m_array_element_size = 0; + +#ifdef POINTER64 + m_alignment = ((GC_OBJECT_ALIGNMENT<8)?8:GC_OBJECT_ALIGNMENT);; +#else + m_alignment = GC_OBJECT_ALIGNMENT; +#endif + + m_id = class_next_id++; + m_class_loader = cl; + m_class_handle = NULL; + m_is_primitive = 0; + m_is_array = 0; + m_is_array_of_primitives = 0; + m_has_finalizer = 0; + m_can_access_all = 0; + m_is_fast_allocation_possible = 0; + + m_num_dimensions = 0; + m_array_base_class = m_array_element_class = NULL; + m_array_element_type_desc = NULL; + + m_access_flags = 0; + m_num_superinterfaces = 0; + m_num_fields = m_num_static_fields = m_num_methods = 0; + + m_declaring_class_index = 0; + m_enclosing_class_index = 0; + m_enclosing_method_index = 0; + m_num_innerclasses = 0; + m_innerclasses = NULL; + + m_fields = NULL; + m_methods = NULL; + + m_superinterfaces = NULL; + + m_const_pool.init(); + + m_class_file_name = m_src_file_name = NULL; + + m_state = ST_Start; + + m_package = NULL; + + m_num_instance_refs = 0; + + m_num_virtual_method_entries = m_num_intfc_method_entries = + m_num_intfc_table_entries = 0; + + m_finalize_method = m_static_initializer = m_default_constructor = NULL; + + m_static_data_size = 0; + m_static_data_block = NULL; + + m_unpadded_instance_data_size = m_instance_data_size = 0; + m_vtable = NULL; + m_allocation_handle = 0; + + m_vtable_descriptors = NULL; + m_intfc_table_descriptors = NULL; + + m_initializing_thread = NULL; + m_error = NULL; + + m_num_class_init_checks = m_num_throws = m_num_instanceof_slow + = m_num_allocations = m_num_bytes_allocated = 0; + + m_num_field_padding_bytes = 0; + + m_notify_extended_records = 0; + + m_depth = 0; + m_is_suitable_for_fast_instanceof = 0; + + m_cha_first_child = m_cha_next_sibling = NULL; + + m_sourceDebugExtension = NULL; + m_lock = new Lock_Manager(); + m_markBit = 0; + m_verify_data = 0; +} + + +void Class::clear_internals() { + if(m_fields != NULL) + { + delete[] m_fields; + m_fields = NULL; + } + if(m_methods != NULL) { + for (int i = 0; i < m_num_methods; i++){ + m_methods[i].MethodClearInternals(); + } + delete[] m_methods; + m_methods = NULL; + } + m_const_pool.clear(); + if(m_vtable_descriptors) + delete[] m_vtable_descriptors; + + if(m_lock) + delete m_lock; + + if(m_array_element_type_desc) + { + delete m_array_element_type_desc; + m_array_element_type_desc = NULL; + } +} + + +Field* Class::get_field(uint16 index) const +{ + assert(index < m_num_fields); + return &(m_fields[index]); +} + + +Method* Class::get_method(uint16 index) const +{ + assert(index < m_num_methods); + return &m_methods[index]; +} + + +bool Class::is_instanceof(Class* clss) +{ + assert(!is_interface()); + +#ifdef VM_STATS + VM_Statistics::get_vm_stats().num_type_checks++; + if(this == clss) + VM_Statistics::get_vm_stats().num_type_checks_equal_type++; + if(clss->m_is_suitable_for_fast_instanceof) + VM_Statistics::get_vm_stats().num_type_checks_fast_decision++; + else if(clss->is_array()) + VM_Statistics::get_vm_stats().num_type_checks_super_is_array++; + else if(clss->is_interface()) + VM_Statistics::get_vm_stats().num_type_checks_super_is_interface ++; + else if(clss->m_depth >= vm_max_fast_instanceof_depth()) + VM_Statistics::get_vm_stats().num_type_checks_super_is_too_deep++; +#endif // VM_STATS + + if(this == clss) return true; + + Global_Env* env = VM_Global_State::loader_env; + + if(is_array()) { + Class* object_class = env->JavaLangObject_Class; + assert(object_class != NULL); + if(clss == object_class) return true; + if(clss == env->java_io_Serializable_Class) return true; + if(clss == env->java_lang_Cloneable_Class) return true; + if(!clss->is_array()) return false; + + return class_is_subtype(get_array_element_class(), clss->get_array_element_class()); + } else { + if(clss->m_is_suitable_for_fast_instanceof) + { + return m_vtable->superclasses[clss->m_depth - 1] == clss; + } + + if(!clss->is_interface()) { + for(Class *c = this; c; c = c->get_super_class()) { + if(c == clss) return true; + } + } else { + for(Class *c = this; c; c = c->get_super_class()) { + unsigned n_intf = c->get_number_of_superinterfaces(); + for(unsigned i = 0; i < n_intf; i++) { + Class* intf = c->get_superinterface(i); + assert(intf); + assert(intf->is_interface()); + if(class_is_subtype(intf, clss)) return true; + } + } + } + } + + return false; +} + + +bool Class::load_ancestors(Global_Env* env) +{ + m_state = ST_LoadingAncestors; + + const String* superName = get_super_class_name(); + + if(superName == NULL) { + if(env->InBootstrap() || get_name() != env->JavaLangClass_String) { + // This class better be java.lang.Object + if(get_name() != env->JavaLangObject_String) { + // ClassFormatError + std::stringstream ss; + ss << get_name()->bytes + << ": class does not have superclass " + << "but the class is not java.lang.Object"; + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, + "java/lang/ClassFormatError", ss.str().c_str()); + return false; + } + } + } else { + // Load super class + Class* superClass; + m_super_class.name = NULL; + superClass = m_class_loader->LoadVerifyAndPrepareClass(env, superName); + if(superClass == NULL) { + if(!m_class_loader->GetClassError(get_name()->bytes)) { + // Don't report failed classes more than one time + REPORT_FAILED_CLASS_CLASS_EXN(m_class_loader, this, + m_class_loader->GetClassError(superName->bytes)); + } + return false; + } + if(superClass->is_interface() || superClass->is_final()) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, + "java/lang/IncompatibleClassChangeError", + get_name()->bytes); + return false; + } + + // super class was successfully loaded + m_super_class.clss = superClass; + if(m_super_class.cp_index) { + m_const_pool.resolve_entry(m_super_class.cp_index, superClass); + } + + // if it's an interface, its superclass must be java/lang/Object + if(is_interface()) { + if((env->JavaLangObject_Class != NULL) && (superClass != env->JavaLangObject_Class)) { + std::stringstream ss; + ss << get_name()->bytes << ": interface superclass is not java.lang.Object"; + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, + "java/lang/ClassFormatError", ss.str().c_str()); + return false; + } + } + + // Update the cha_first_child and cha_next_sibling fields. + m_cha_first_child = NULL; + if(has_super_class()) + { + m_cha_next_sibling = get_super_class()->m_cha_first_child; + get_super_class()->m_cha_first_child = this; + } + // Notify interested JITs that the superclass has been extended. + superClass->do_jit_extended_class_callbacks(this); + } -// 20020923 Total number of allocations and total number of bytes for class-related data structures. -// This includes any rounding added to make each item aligned (current alignment is to the next 16 byte boundary). -unsigned Class::num_nonempty_statics_allocations = 0; -unsigned Class::num_statics_allocations = 0; -unsigned Class::num_vtable_allocations = 0; -unsigned Class::num_hot_statics_allocations = 0; -unsigned Class::num_hot_vtable_allocations = 0; + // + // load in super interfaces + // + for(unsigned i = 0; i < m_num_superinterfaces; i++ ) { + const String* intfc_name = m_superinterfaces[i].name; + Class* intfc = m_class_loader->LoadVerifyAndPrepareClass(env, intfc_name); + if(intfc == NULL) { + if(!m_class_loader->GetClassError(get_name()->bytes)) { + REPORT_FAILED_CLASS_CLASS_EXN(m_class_loader, this, + m_class_loader->GetClassError(intfc_name->bytes)); + } + return false; + } + if(!intfc->is_interface()) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, + "java/lang/IncompatibleClassChangeError", + get_name()->bytes << ": " << intfc->get_name()->bytes + << " is not an interface"); + return false; + } -unsigned Class::total_statics_bytes = 0; -unsigned Class::total_vtable_bytes = 0; -unsigned Class::total_hot_statics_bytes = 0; -unsigned Class::total_hot_vtable_bytes = 0; + // superinterface was successfully loaded + m_superinterfaces[i].clss = intfc; + if(m_superinterfaces[i].cp_index != 0) { + // there are no constant pool entries for array classes + m_const_pool.resolve_entry(m_superinterfaces[i].cp_index, intfc); + } + } + // class, superclass, and superinterfaces successfully loaded + m_state = ST_Loaded; + if(!is_array()) + m_package = m_class_loader->ProvidePackage(env, m_name, NULL); + + return true; +} -// 2003-01-10: This is a temporary hack to make field compaction the default on IPF -// while not destabilizing JIT work on IA32. Ultimately both fields should be -// true by default on all platforms. -#if defined _IPF_ || defined _EM64T_ -bool Class::compact_fields = true; -bool Class::sort_fields = true; -#else // !_IPF_ -bool Class::compact_fields = false; -bool Class::sort_fields = false; -#endif // !IPF_ + +Class* Class::resolve_declaring_class(Global_Env* env) +{ + if(m_declaring_class_index == 0) return NULL; + return _resolve_class(env, m_declaring_class_index); +} + + +void Class::setup_as_array(Global_Env* env, unsigned char num_dimensions, + bool isArrayOfPrimitives, Class* baseClass, Class* elementClass) +{ + m_is_array = 1; + m_num_dimensions = (unsigned char)num_dimensions; + if(m_num_dimensions == 1) { + m_is_array_of_primitives = isArrayOfPrimitives; + } else { + m_is_array_of_primitives = false; + } + m_array_element_class = elementClass; + m_array_base_class = baseClass; + m_state = ST_Initialized; + + assert(elementClass); + m_array_element_type_desc = type_desc_create_from_class(elementClass); + + // insert Java field, required by spec - 'length I' + m_num_fields = 1; + m_fields = new Field[1]; + m_fields[0].set(this, env->Length_String, + env->string_pool.lookup("I"), ACC_PUBLIC|ACC_FINAL); + m_fields[0].set_field_type_desc( + type_desc_create_from_java_descriptor("I", NULL)); + m_fields[0].set_injected(); + + m_super_class.name = env->JavaLangObject_String; + m_super_class.cp_index = 0; + + m_access_flags = (ACC_FINAL | ACC_ABSTRACT); + if(isArrayOfPrimitives) { + m_access_flags |= ACC_PUBLIC; + } else { + // set array access flags the same as in its base class + m_access_flags = (uint16)(m_access_flags + | (baseClass->get_access_flags() + & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED))); + } + m_package = elementClass->m_package; + + // array classes implement two interfaces: Cloneable and Serializable + m_superinterfaces = (Class_Super*) STD_MALLOC(2 * sizeof(Class_Super)); + m_superinterfaces[0].name = env->Clonable_String; + m_superinterfaces[0].cp_index = 0; + m_superinterfaces[1].name = env->Serializable_String; + m_superinterfaces[1].cp_index = 0; + m_num_superinterfaces = 2; +} // // This function doesn't check for fields inherited from superclasses. // -Field *class_lookup_field(Class *clss, const String* name, const String* desc) +Field* Class::lookup_field(const String* name, const String* desc) { - for (unsigned i=0; in_fields; i++) { - if (clss->fields[i].get_name() == name && clss->fields[i].get_descriptor() == desc) - return &clss->fields[i]; + for(uint16 i = 0; i < m_num_fields; i++) { + if(m_fields[i].get_name() == name && m_fields[i].get_descriptor() == desc) + return &m_fields[i]; } return NULL; -} //class_lookup_field +} // Class::lookup_field Field* class_lookup_field_recursive(Class* clss, @@ -80,59 +426,119 @@ Field* class_lookup_field_recursive(Clas String *field_descr = VM_Global_State::loader_env->string_pool.lookup(descr); - return class_lookup_field_recursive(clss, field_name, field_descr); + return clss->lookup_field_recursive(field_name, field_descr); } -Field* class_lookup_field_recursive(Class *clss, - const String* name, const String* desc) +Field* Class::lookup_field_recursive(const String* name, const String* desc) { // Step 1: lookup in self - Field* field = class_lookup_field(clss, name, desc); + Field* field = lookup_field(name, desc); if(field) return field; // Step 2: lookup in direct superinterfaces recursively - for (int in = 0; in < clss->n_superinterfaces && !field; in++) { - field = class_lookup_field_recursive(clss->superinterfaces[in].clss, name, desc); + for(uint16 in = 0; in < m_num_superinterfaces; in++) { + field = get_superinterface(in)->lookup_field_recursive(name, desc); if(field) return field; } // Step 3: lookup in super classes recursively - if(clss->super_class) { - field = class_lookup_field_recursive(clss->super_class, name, desc); + if(has_super_class()) { + field = get_super_class()->lookup_field_recursive(name, desc); } return field; -} //class_lookup_field_recursive +} // Class::lookup_field_recursive + + +Method* Class::lookup_method(const String* name, const String* desc) +{ + for(unsigned i = 0; i < m_num_methods; i++) { + if(m_methods[i].get_name() == name && m_methods[i].get_descriptor() == desc) + return &m_methods[i]; + } + return NULL; +} // Class::lookup_method + + +ManagedObject* Class::allocate_instance() +{ + assert(!hythread_is_suspend_enabled()); + ManagedObject* new_instance = + (ManagedObject*)vm_alloc_and_report_ti(m_instance_data_size, + m_allocation_handle, vm_get_gc_thread_local(), this); + if(new_instance == NULL) + { + return NULL; + } +#ifdef VM_STATS + VM_Statistics::get_vm_stats().num_class_alloc_new_object++; + instance_allocated(m_instance_data_size); +#endif //VM_STATS + + return new_instance; +} -Method *class_lookup_method(Class *clss, const String* name, const String* desc) +void* Class::helper_get_interface_vtable(ManagedObject* obj, Class* iid) { - for (unsigned i=0; in_methods; i++) { - if (clss->methods[i].get_name() == name && clss->methods[i].get_descriptor() == desc) - return &clss->methods[i]; + unsigned num_intfc = m_num_intfc_table_entries; +#ifdef VM_STATS + VM_Statistics::get_vm_stats().num_invokeinterface_calls++; + switch(num_intfc) { + case 1: VM_Statistics::get_vm_stats().num_invokeinterface_calls_size_1++; break; + case 2: VM_Statistics::get_vm_stats().num_invokeinterface_calls_size_2++; break; + default: VM_Statistics::get_vm_stats().num_invokeinterface_calls_size_many++; break; + } + if(num_intfc > VM_Statistics::get_vm_stats().invokeinterface_calls_size_max) + VM_Statistics::get_vm_stats().invokeinterface_calls_size_max = num_intfc; +#endif + for(unsigned i = 0; i < num_intfc; i++) { + Class* intfc = m_intfc_table_descriptors[i]; + if(intfc == iid) { +#ifdef VM_STATS + switch(i) { + case 0: VM_Statistics::get_vm_stats().num_invokeinterface_calls_searched_1++; break; + case 1: VM_Statistics::get_vm_stats().num_invokeinterface_calls_searched_2++; break; + default: VM_Statistics::get_vm_stats().num_invokeinterface_calls_searched_many++; break; + } + if(i > VM_Statistics::get_vm_stats().invokeinterface_calls_searched_max) + VM_Statistics::get_vm_stats().invokeinterface_calls_searched_max = i; +#endif + unsigned char** table = m_vtable->intfc_table->entry[i].table; + return (void*)table; + } } return NULL; -} //class_lookup_method +} +void Class::set_error_cause(jthrowable exn) +{ + tmn_suspend_disable(); + lock(); + m_state = ST_Error; + m_error = exn->object; + unlock(); + tmn_suspend_enable(); +} -Method *class_lookup_method_recursive(Class *clss, const String* name, const String* desc) + +Method* class_lookup_method_recursive(Class *clss, const String* name, const String* desc) { assert(clss); Method *m = 0; Class *oclss = clss; - for(; clss && !m; clss = clss->super_class) { - m = class_lookup_method(clss, name, desc); + for(; clss && !m; clss = clss->get_super_class()) { + m = clss->lookup_method(name, desc); } if(m)return m; //if not found, search in interfaces, that means // clss itself is also interface - Class_Superinterface *intfs = oclss->superinterfaces; - for(int i = 0; i < oclss->n_superinterfaces; i++) - if((m = class_lookup_method_recursive(intfs[i].clss, name, desc))) + for(int i = 0; i < oclss->get_number_of_superinterfaces(); i++) + if((m = class_lookup_method_recursive(oclss->get_superinterface(i), name, desc))) return m; return NULL; } //class_lookup_method_recursive @@ -152,49 +558,42 @@ Method *class_lookup_method_recursive(Cl } //class_lookup_method_recursive -Method *class_lookup_method_init(Class *clss, - const char *descr) -{ - String *method_name = VM_Global_State::loader_env->Init_String; - String *method_descr = - VM_Global_State::loader_env->string_pool.lookup(descr); - - return class_lookup_method(clss, method_name, method_descr); -} //class_lookup_method_init - -Method *class_lookup_method_clinit(Class *clss) +Method* class_lookup_method(Class* clss, + const char* name, + const char* descr) { - return class_lookup_method(clss, VM_Global_State::loader_env->Clinit_String, VM_Global_State::loader_env->VoidVoidDescriptor_String); -} //class_lookup_method_clinit - -Method *class_lookup_method(Class *clss, - const char *name, - const char *descr) -{ - String *method_name = + String* method_name = VM_Global_State::loader_env->string_pool.lookup(name); - String *method_descr = + String* method_descr = VM_Global_State::loader_env->string_pool.lookup(descr); - return class_lookup_method(clss, method_name, method_descr); -} //class_lookup_method + return clss->lookup_method(method_name, method_descr); +} // class_lookup_method -Method *class_get_method_from_vt_offset(VTable *vt, +Method* class_get_method_from_vt_offset(VTable* vt, unsigned offset) { assert(vt); unsigned index = (offset - VTABLE_OVERHEAD) / sizeof(void*); - return vt->clss->vtable_descriptors[index]; + return vt->clss->get_method_from_vtable(index); } // class_get_method_from_vt_offset void* Field::get_address() { assert(is_static()); assert(is_offset_computed()); - return (char *)(get_class()->static_data_block) + get_offset(); + return (char*)(get_class()->get_static_data_address()) + get_offset(); } // Field::get_address +unsigned Field::calculate_size() { + static unsigned size = sizeof(Field) + sizeof(TypeDesc); + return size; +} + + + + Method::Method() { // @@ -296,12 +695,12 @@ void Method::MethodClearInternals() void Method::lock() { - _class->m_lock->_lock(); + _class->lock(); } void Method::unlock() { - _class->m_lock->_unlock(); + _class->unlock(); } @@ -334,7 +733,7 @@ ManagedObject *struct_Class_to_java_lang //sundr printf("struct to class %s, %p, %p\n", clss->name->bytes, clss, clss->super_class); assert(!hythread_is_suspend_enabled()); assert(clss); - ManagedObject** hjlc = clss->class_handle; + ManagedObject** hjlc = clss->get_class_handle(); assert(hjlc); ManagedObject* jlc = *hjlc; assert(jlc != NULL); @@ -356,9 +755,9 @@ jobject struct_Class_to_java_lang_Class_ tmn_suspend_disable_recursive(); #endif assert(clss); - assert(clss->class_handle); - assert(*(clss->class_handle)); - ManagedObject* UNUSED jlc = *(clss->class_handle); + assert(clss->get_class_handle()); + ManagedObject* UNUSED jlc = *(clss->get_class_handle()); + assert(jlc); assert(jlc->vt()); //assert(jlc->vt()->clss == VM_Global_State::loader_env->JavaLangClass_Class); #ifndef NDEBUG @@ -377,7 +776,7 @@ jobject struct_Class_to_java_lang_Class_ // // ppervov 2005-04-18 // redone struct Class to contain class handle instead of raw ManagedObject* - return (jclass)(clss->class_handle); + return (jclass)(clss->get_class_handle()); } /* The following two utility functions to ease @@ -386,10 +785,10 @@ jobject struct_Class_to_java_lang_Class_ jclass struct_Class_to_jclass(Class *c) { assert(hythread_is_suspend_enabled()); - tmn_suspend_disable(); // ------------------------vvv + tmn_suspend_disable(); // ----------vvv ObjectHandle h = oh_allocate_local_handle(); h->object = struct_Class_to_java_lang_Class(c); - tmn_suspend_enable(); // -------------------------^^^ + tmn_suspend_enable(); // ----------^^^ return (jclass)h; } @@ -427,94 +826,39 @@ Class *java_lang_Class_to_struct_Class(M Class* clss = *vm_class_ptr; assert(clss != NULL); - assert(clss->class_handle); - assert(*(clss->class_handle) == jlc); + assert(clss->get_class_handle()); + assert(*(clss->get_class_handle()) == jlc); assert(clss != (Class*) jlc); // else the two structures still overlap! return clss; } //java_lang_Class_to_struct_Class - -void set_struct_Class_field_in_java_lang_Class(const Global_Env* env, ManagedObject** jlc, Class *clss) +String* Class::get_simple_name() { - assert(managed_object_is_java_lang_class(*jlc)); - assert(env->vm_class_offset != 0); - - Class** vm_class_ptr = (Class **)(((Byte *)(*jlc)) + env->vm_class_offset); - *vm_class_ptr = clss; -} //set_struct_Class_field_in_java_lang_Class - - -void class_report_failure(Class* target, uint16 cp_index, jthrowable exn) -{ - assert(cp_index > 0 && cp_index < target->cp_size); - assert(hythread_is_suspend_enabled()); - if (exn_raised()) { - TRACE2("classloader.error", "runtime exception in classloading"); - return; - } - assert(exn); - - 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]); - } - // ^^^ - target->m_lock->_unlock(); - tmn_suspend_enable(); -} - - -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)); -} - -String* class_get_java_name(Class* clss, Global_Env* env) -{ - unsigned len = clss->name->len + 1; - char * name = (char*) STD_ALLOCA(len); - char * tmp_name = name; - memcpy(name, clss->name->bytes, len); - while (tmp_name = strchr(tmp_name, '/')) { - *tmp_name = '.'; - ++tmp_name; - } - return VM_Global_State::loader_env->string_pool.lookup(name); -} - -String* class_get_simple_name(Class* clss, Global_Env* env) -{ - if (!clss->simple_name) + Global_Env* env = VM_Global_State::loader_env; + if(m_simple_name == NULL) { - if (clss->is_array) + if (is_array()) { - String* simple_base_name = class_get_simple_name(clss->array_base_class, env); + String* simple_base_name = m_array_base_class->get_simple_name(); unsigned len = simple_base_name->len; - unsigned dims = clss->n_dimensions; + unsigned dims = m_num_dimensions; char * buf = (char*)STD_ALLOCA(dims * 2 + len); strcpy(buf, simple_base_name->bytes); while (dims-- > 0) { buf[len++] = '['; buf[len++] = ']'; } - clss->simple_name = env->string_pool.lookup(buf, len); + m_simple_name = env->string_pool.lookup(buf, len); } else { - const char* fn = clss->name->bytes; + const char* fn = m_name->bytes; const char* start; - if (clss->enclosing_class_index) + if(m_enclosing_class_index) { - const char* enclosing_name = const_pool_get_class_name(clss, - clss->enclosing_class_index); + const char* enclosing_name = + const_pool_get_class_name(this, m_enclosing_class_index); start = fn + strlen(enclosing_name); while (*start == '$' || isdigit(*start)) start++; } @@ -523,21 +867,45 @@ String* class_get_simple_name(Class* cls start = strrchr(fn, '/'); } - if (start) { - clss->simple_name = env->string_pool.lookup(start + 1); + if(start) { + m_simple_name = env->string_pool.lookup(start + 1); } else { - clss->simple_name = const_cast (clss->name); + m_simple_name = const_cast(m_name); } } } - return clss->simple_name; + return m_simple_name; +} + + +String* class_name_get_java_name(const String* class_name) { + unsigned len = class_name->len + 1; + char* name = (char*)STD_ALLOCA(len); + memcpy(name, class_name->bytes, len); + for(char *p = name; *p; ++p) { + if (*p=='/') *p='.'; + } + String* str = VM_Global_State::loader_env->string_pool.lookup(name); + return str; +} + + +static void mark_classloader(ClassLoader* cl) +{ + if(cl->GetLoader() && cl->NotMarked()) { + TRACE2("classloader.unloading.markloader", " Marking loader " + << cl << " (" << (void*)cl->GetLoader() << " : " + << cl->GetLoader()->vt()->clss->get_name()->bytes << ")"); + cl->Mark(); + } } + void vm_notify_live_object_class(Class_Handle clss) { - if(!clss->m_markBit) { - clss->m_markBit = 1; - mark_classloader(clss->class_loader); + if(!clss->is_reachable()) { + clss->mark_reachable(); + mark_classloader(clss->get_class_loader()); } } @@ -550,15 +918,11 @@ void vm_notify_live_object_class(Class_H //////////////////////////////////////////////////////////////////// // begin Support for compressed and raw reference pointers -Byte *Class::heap_base = (Byte *)NULL; -Byte *Class::heap_end = (Byte *)NULL; -Byte *Class::managed_null = (Byte *)NULL; - - bool is_compressed_reference(COMPRESSED_REFERENCE compressed_ref) { // A compressed reference is an offset into the heap. - uint64 heap_max_size = (Class::heap_end - Class::heap_base); + uint64 heap_max_size = (VM_Global_State::loader_env->heap_end + - VM_Global_State::loader_env->heap_base); return ((uint64) compressed_ref) < heap_max_size; } // is_compressed_reference @@ -578,7 +942,8 @@ COMPRESSED_REFERENCE compress_reference( if(obj == NULL) compressed_ref = 0; else - compressed_ref = (COMPRESSED_REFERENCE)((POINTER_SIZE_INT)obj - (POINTER_SIZE_INT)Class::heap_base); + compressed_ref = (COMPRESSED_REFERENCE)((POINTER_SIZE_INT)obj + - (POINTER_SIZE_INT)VM_Global_State::loader_env->heap_base); assert(is_compressed_reference(compressed_ref)); return compressed_ref; } //compress_reference @@ -591,7 +956,7 @@ ManagedObject *uncompress_compressed_ref if (compressed_ref == 0) { return NULL; } else { - return (ManagedObject *)(Class::heap_base + compressed_ref); + return (ManagedObject *)(VM_Global_State::loader_env->heap_base + compressed_ref); } } //uncompress_compressed_reference @@ -606,7 +971,7 @@ ManagedObject *get_raw_reference_pointer COMPRESSED_REFERENCE offset = *((COMPRESSED_REFERENCE *)slot_addr); assert(is_compressed_reference(offset)); if (offset != 0) { - obj = (ManagedObject *)(Class::heap_base + offset); + obj = (ManagedObject *)(VM_Global_State::loader_env->heap_base + offset); } } else { obj = *slot_addr; @@ -618,50 +983,6 @@ ManagedObject *get_raw_reference_pointer // end Support for compressed and raw reference pointers //////////////////////////////////////////////////////////////////// - - - -VTable *create_vtable(Class *p_class, unsigned n_vtable_entries) -{ - unsigned vtable_size = VTABLE_OVERHEAD + n_vtable_entries * sizeof(void *); - - // Always allocate vtable data from vtable_data_pool - void *p_gc_hdr = allocate_vtable_data_from_pool(vtable_size); - -#ifdef VM_STATS - // For allocation statistics, include any rounding added to make each item aligned (current alignment is to the next 16 byte boundary). - unsigned num_bytes = (vtable_size + 15) & ~15; - // 20020923 Total number of allocations and total number of bytes for class-related data structures. - Class::num_vtable_allocations++; - Class::total_vtable_bytes += num_bytes; -#endif - assert(p_gc_hdr); - memset(p_gc_hdr, 0, vtable_size); - - VTable *vtable = (VTable *)p_gc_hdr; - - if(p_class && p_class->super_class) { - p_class->depth = p_class->super_class->depth + 1; - memcpy(&vtable->superclasses, - &p_class->super_class->vtable->superclasses, - sizeof(vtable->superclasses)); - for(int i = 0; i < vm_max_fast_instanceof_depth(); i++) { - if(vtable->superclasses[i] == NULL) { - vtable->superclasses[i] = p_class; - break; - } - } - } - if (p_class->depth > 0 && - p_class->depth < vm_max_fast_instanceof_depth() && - !p_class->is_array && - !class_is_interface(p_class)) - { - p_class->is_suitable_for_fast_instanceof = 1; - } - return vtable; -} //create_vtable - // Function registers a number of native methods to a given class. bool class_register_methods(Class_Handle klass, @@ -677,15 +998,16 @@ class_register_methods(Class_Handle klas // find method from class bool not_found = true; - for( int count = 0; count < klass->n_methods; count++ ) { - Method *class_method = &klass->methods[count]; + for(int count = 0; count < klass->get_number_of_methods(); count++ ) { + Method *class_method = klass->get_method(count); const String *method_name = class_method->get_name(); const String *method_desc = class_method->get_descriptor(); if( method_name == name && method_desc == desc ) { // trace TRACE2("class.native", "Register native method: " - << klass->name->bytes << "." << name->bytes << desc->bytes); + << klass->get_name()->bytes + << "." << name->bytes << desc->bytes); // found method not_found = false; @@ -695,21 +1017,21 @@ class_register_methods(Class_Handle klas jvmti_process_native_method_bind_event( (jmethodID) class_method, native_addr, &native_addr); // lock class - klass->m_lock->_lock(); + klass->lock(); class_method->set_code_addr( native_addr ); class_method->set_registered( true ); - klass->m_lock->_unlock(); + klass->unlock(); break; } } if( not_found ) { // create error string ". - int clen = strlen(klass->name->bytes); - int mlen = strlen(name->bytes); - int dlen = strlen(desc->bytes); + int clen = klass->get_name()->len; + int mlen = name->len; + int dlen = desc->len; int len = clen + 1 + mlen + dlen; char *error = (char*)STD_ALLOCA(len + 1); - memcpy(error, klass->name->bytes, clen); + memcpy(error, klass->get_name()->bytes, clen); error[clen] = '.'; memcpy(error + clen + 1, name->bytes, mlen); memcpy(error + clen + 1 + mlen, desc->bytes, dlen); @@ -717,7 +1039,7 @@ class_register_methods(Class_Handle klas // trace TRACE2("class.native", "Native could not be registered: " - << klass->name->bytes << "." << name->bytes << desc->bytes); + << klass->get_name()->bytes << "." << name->bytes << desc->bytes); // raise an exception jthrowable exc_object = exn_create("java/lang/NoSuchMethodError", error); @@ -728,25 +1050,126 @@ class_register_methods(Class_Handle klas return false; } // class_register_methods -// Function unregisters a native methods of a given class. +// Function unregisters registered native methods of a given class. bool class_unregister_methods(Class_Handle klass) { // lock class - klass->m_lock->_lock(); - for( int count = 0; count < klass->n_methods; count++ ) { - Method *method = &klass->methods[count]; + klass->lock(); + for(int count = 0; count < klass->get_number_of_methods(); count++ ) { + Method* method = klass->get_method(count); if( method->is_registered() ) { // trace TRACE2("class.native", "Unregister native method: " - << klass->name << "." << method->get_name()->bytes + << klass->get_name() << "." << method->get_name()->bytes << method->get_descriptor()->bytes); // reset registered flag - method->set_registered( false ); + method->set_registered(false); } } // unlock class - klass->m_lock->_unlock(); + klass->unlock(); return false; } // class_unregister_methods + + +//////////////////////////////////////////////////////////////////// +// begin support for JIT notification when classes are extended + +struct Class_Extended_Notification_Record { + Class *class_of_interest; + JIT *jit; + void *callback_data; + Class_Extended_Notification_Record *next; + + bool equals(Class *class_of_interest_, JIT *jit_, void *callback_data_) { + if ((class_of_interest == class_of_interest_) && + (jit == jit_) && + (callback_data == callback_data_)) { + return true; + } + return false; + } +}; + + +void Class::register_jit_extended_class_callback(JIT* jit_to_be_notified, void* callback_data) +{ + // Don't insert the same entry repeatedly on the notify_extended_records list. + Class_Extended_Notification_Record* nr = m_notify_extended_records; + while(nr != NULL) { + if(nr->equals(this, jit_to_be_notified, callback_data)) { + return; + } + nr = nr->next; + } + + // Insert a new notification record. + Class_Extended_Notification_Record* new_nr = + (Class_Extended_Notification_Record*)STD_MALLOC(sizeof(Class_Extended_Notification_Record)); + new_nr->class_of_interest = this; + new_nr->jit = jit_to_be_notified; + new_nr->callback_data = callback_data; + new_nr->next = m_notify_extended_records; + m_notify_extended_records = new_nr; +} // Class::register_jit_extended_class_callback + + +void Class::do_jit_extended_class_callbacks(Class* new_subclass) +{ + Class_Extended_Notification_Record* nr; + for(nr = m_notify_extended_records; nr != NULL; nr = nr->next) { + JIT* jit_to_be_notified = nr->jit; + Boolean code_was_modified = + jit_to_be_notified->extended_class_callback(this, + new_subclass, nr->callback_data); + if(code_was_modified) { +#ifdef _IPF_ + sync_i_cache(); + do_mf(); +#endif // _IPF_ + } + } +} // Class::do_jit_extended_class_callbacks + + +void Class::lock() +{ + m_lock->_lock(); +} + + +void Class::unlock() +{ + m_lock->_unlock(); +} + + +unsigned Class::calculate_size() +{ + unsigned size = 0; + size += sizeof(Class); + size += m_num_innerclasses*sizeof(InnerClass); + size += sizeof(ConstantPool) + + m_const_pool.get_size()*sizeof(ConstPoolEntry); + for(unsigned i = 0; i < m_num_fields; i++) { + size += m_fields[i].calculate_size(); + } + for(unsigned i = 0; i < m_num_methods; i++) { + size += m_methods[i].calculate_size(); + } + size += m_num_superinterfaces*sizeof(Class_Super); + size += m_static_data_size; + if(!is_interface()) + size += sizeof(VTable); + size += m_num_intfc_table_entries*sizeof(Class*); + for(Class_Extended_Notification_Record* mcnr = m_notify_extended_records; + mcnr != NULL; mcnr = mcnr->next) + { + size += sizeof(Class_Extended_Notification_Record); + } + size += sizeof(Lock_Manager); + + return size; +} 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..15ab17c 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,11 +29,11 @@ #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" #include "compile.h" -#include "jit_intf_cpp.h" #include "interpreter_exports.h" #include "jarfile_util.h" @@ -61,41 +61,44 @@ #define REPORT_FAILED_CLASS_FORMAT(klass, msg) \ { \ std::stringstream ss; \ - ss << klass->name->bytes << " : " << msg; \ - klass->class_loader->ReportFailedClass(klass, "java/lang/ClassFormatError", ss); \ + ss << klass->get_name()->bytes << " : " << msg; \ + klass->get_class_loader()->ReportFailedClass(klass, "java/lang/ClassFormatError", ss); \ } #define valid_cpi(clss, idx, type) \ - (idx < clss->cp_size && cp_tag(clss->const_pool, idx) == type) + (clss->get_constant_pool().is_valid_index(idx) \ + && clss->get_constant_pool().get_tag(idx) == type) -String *cp_check_utf8(Const_Pool *cp, - unsigned cp_size, - unsigned utf8_index) +static 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) +static 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 +#define N_COMMON_ATTR 5 +#define N_FIELD_ATTR 1 +#define N_METHOD_ATTR 5 +#define N_CODE_ATTR 3 +#define N_CLASS_ATTR 4 + static String *common_attr_strings[N_COMMON_ATTR+1]; static Attributes common_attrs[N_COMMON_ATTR]; @@ -216,7 +219,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->get_constant_pool(), idx); if(!sig) { REPORT_FAILED_CLASS_FORMAT(clss, "invalid Signature index : " << idx); } @@ -225,8 +228,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 +245,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 +296,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->get_constant_pool(), type_idx); if (type == NULL) { REPORT_FAILED_CLASS_FORMAT(clss, "invalid type index of annotation : " << type_idx); @@ -308,7 +310,7 @@ uint32 parse_annotation(Annotation** val return 0; } - Annotation* antn = (Annotation*) clss->class_loader->Alloc( + Annotation* antn = (Annotation*) clss->get_class_loader()->Alloc( sizeof(Annotation) + num_elements * sizeof(AnnotationElement)); antn->type = type; antn->num_elements = num_elements; @@ -325,7 +327,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->get_constant_pool(), name_idx); if (antn->elements[j].name == NULL) { REPORT_FAILED_CLASS_FORMAT(clss, "invalid element_name_index of annotation : " << name_idx); @@ -354,8 +356,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->get_constant_pool(); + unsigned cp_size = cp.get_size(); char ctag = (char)tag; switch(ctag) { @@ -382,29 +384,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 +427,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 +445,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 +457,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); @@ -486,7 +488,7 @@ uint32 parse_annotation_value(Annotation read_len += 2; value.array.length = num; if (num) { - value.array.items = (AnnotationValue*) clss->class_loader->Alloc( + value.array.items = (AnnotationValue*) clss->get_class_loader()->Alloc( num * sizeof(AnnotationValue)); for (int i = 0; i < num; i++) { uint32 size = parse_annotation_value(value.array.items[i], cfs, clss); @@ -520,7 +522,7 @@ uint32 parse_annotation_table(Annotation uint32 read_len = 2; if (num_annotations) { - *table = (AnnotationTable*) clss->class_loader->Alloc( + *table = (AnnotationTable*) clss->get_class_loader()->Alloc( sizeof (AnnotationTable) + (num_annotations - 1)*sizeof(Annotation*)); (*table)->length = num_annotations; @@ -605,13 +607,13 @@ Attributes Class_Member::process_common_ } void* Class_Member::Alloc(size_t size) { - ClassLoader* cl = get_class()->class_loader; + ClassLoader* cl = get_class()->get_class_loader(); assert(cl); return cl->Alloc(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 +633,13 @@ bool Class_Member::parse(Class *clss, Co return false; } + ConstantPool& cp = clss->get_constant_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 +743,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,13 +754,13 @@ 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; } // check interface fields access flags - if( class_is_interface(clss) ) { + if( clss->is_interface() ) { if(!(is_public() && is_static() && is_final())){ REPORT_FAILED_CLASS_FORMAT(clss, "interface field " << get_name()->bytes << " does not have one of ACC_PUBLIC, ACC_STATIC, or ACC_FINAL access flags set"); @@ -765,7 +768,7 @@ bool Field::parse(Class *clss, Const_Poo } if(_access_flags & ~(ACC_FINAL | ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC)){ REPORT_FAILED_CLASS_FORMAT(clss, "interface field " << get_name()->bytes - << " has illegal access flags set : " << _access_flags); //FIXME to hex format + << " has illegal access flags set : " << _access_flags); //FIXME to literal form return false; } } else if((is_public() && is_protected() @@ -773,14 +776,14 @@ bool Field::parse(Class *clss, Const_Poo || is_public() && is_private()) || (is_final() && is_volatile())) { REPORT_FAILED_CLASS_FORMAT(clss, " field " << get_name()->bytes - << " has invalid combination of access flags : " << _access_flags); //FIXME to hex format + << " has invalid combination of access flags : " << _access_flags); //FIXME to literal form return false; } uint16 attr_count; if(!cfs.parse_u2_be(&attr_count)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse attribute count for field " << get_name()); + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": could not parse attribute count for field " << get_name()); return false; } @@ -790,9 +793,11 @@ bool Field::parse(Class *clss, Const_Poo uint32 attr_len = 0; + ConstantPool& cp = clss->get_constant_pool(); + for (unsigned j=0; j 1) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": field " << get_name() << " has more then one ConstantValue attribute"); + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": field " << get_name() << " has more then one ConstantValue attribute"); return false; } // attribute length must be two (vm spec reference 4.7.3) if (attr_len != 2) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": ConstantValue attribute has invalid length for field " << get_name()); + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": ConstantValue attribute has invalid length for field " << get_name()); return false; } if(!cfs.parse_u2_be(&_const_value_index)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse ConstantValue index for field " << get_name()); + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, + "java/lang/ClassFormatError", + clss->get_name()->bytes << ": could not parse " + << "ConstantValue index for field " << get_name()); return false; } - if(_const_value_index == 0 || _const_value_index >= cp_size) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": invalid ConstantValue index for field " << get_name()); + if(_const_value_index == 0 || _const_value_index >= cp.get_size()) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_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); Java_Type java_type = get_java_type(); - switch(tag) { + switch(cp.get_tag(_const_value_index)) { case CONSTANT_Long: { if (java_type != JAVA_TYPE_LONG) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": data type CONSTANT_Long of ConstantValue does not correspond to the type of field " << 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; - break; + 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: { if (java_type != JAVA_TYPE_FLOAT) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": data type CONSTANT_Float of ConstantValue does not correspond to the type of field " << get_name()); return false; } - const_value.f = cp[_const_value_index].float_value; - break; + const_value.f = cp.get_float(_const_value_index); + break; } case CONSTANT_Double: { if (java_type != JAVA_TYPE_DOUBLE) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": data type CONSTANT_Double of ConstantValue does not correspond to the type of field " << 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; - break; + 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: { @@ -875,32 +880,36 @@ bool Field::parse(Class *clss, Const_Poo java_type == JAVA_TYPE_BYTE || java_type == JAVA_TYPE_CHAR) ) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": data type CONSTANT_Integer of ConstantValue does not correspond to the type of field " << get_name()); return false; } - const_value.i = cp[_const_value_index].int_value; - break; + const_value.i = cp.get_int(_const_value_index); + break; } case CONSTANT_String: { if (java_type != JAVA_TYPE_CLASS) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes - << ": data type CONSTANT_String of ConstantValue does not correspond to the type of field " - << get_name()); + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, + "java/lang/ClassFormatError", + clss->get_name()->bytes + << ": data type " << "CONSTANT_String of " + << "ConstantValue does not correspond " + << "to the type of field " << get_name()); return false; } - const_value.string = cp[_const_value_index].CONSTANT_String.string; - break; + const_value.string = cp.get_string(_const_value_index); + break; } default: { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes - << ": invalid data type tag of ConstantValue for field " << get_name()); + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, + "java/lang/ClassFormatError", + clss->get_name()->bytes + << ": invalid data type tag of ConstantValue " + << "for field " << get_name()); return false; } } @@ -917,21 +926,21 @@ bool Field::parse(Class *clss, Const_Poo return false; case ATTR_UNDEF: // unprocessed - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/InternalError", - clss->name->bytes + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/InternalError", + clss->get_name()->bytes << ": error parsing attributes for field " - << get_name() + << get_name()->bytes << "; unprocessed attribute " << cur_attr); return false; } // switch } // switch } // for - TypeDesc* td = type_desc_create_from_java_descriptor(get_descriptor()->bytes, clss->class_loader); + TypeDesc* td = type_desc_create_from_java_descriptor(get_descriptor()->bytes, clss->get_class_loader()); if( td == NULL ) { // ppervov: the fact we don't have td indicates we could not allocate one //std::stringstream ss; - //ss << clss->name->bytes << ": could not create type descriptor for field " << get_name(); + //ss << clss->get_name()->bytes << ": could not create type descriptor for field " << get_name(); //jthrowable exn = exn_create("java/lang/OutOfMemoryError", ss.str().c_str()); exn_raise_object(VM_Global_State::loader_env->java_lang_OutOfMemoryError); return false; @@ -942,8 +951,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,28 +991,13 @@ 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; } return true; } //Handler::parse -int Method::get_line_number(uint16 bc) { - int line = -1; - if (_line_number_table) { - uint16 prev = 0; - for (int i = _line_number_table->length - 1; i >= 0; --i){ - uint16 start = _line_number_table->table[i].start_pc; - if (bc >= start && start >= prev) { - prev = start; - line = _line_number_table->table[i].line_number; - } - } - } - - return line; -} bool Method::get_line_number_entry(unsigned index, jlong* pc, jint* line) { if (_line_number_table && index < _line_number_table->length) { @@ -1032,18 +1026,18 @@ bool Method::get_local_var_entry(unsigne } } -#define REPORT_FAILED_METHOD(msg) REPORT_FAILED_CLASS_CLASS(_class->class_loader, \ +#define REPORT_FAILED_METHOD(msg) REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), \ _class, "java/lang/ClassFormatError", \ - _class->name->bytes << " : " << msg << " for method "\ + _class->get_name()->bytes << " : " << msg << " for method "\ << _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", - _class->name->bytes << ": could not parse number of exceptions for method " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": could not parse number of exceptions for method " << _name->bytes << _descriptor->bytes); return false; } @@ -1052,17 +1046,17 @@ bool Method::_parse_exceptions(Const_Poo for (unsigned i=0; i<_n_exceptions; i++) { uint16 index; if(!cfs.parse_u2_be(&index)) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": could not parse exception class index " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": could not parse exception class index " << "while parsing excpetions for method " << _name->bytes << _descriptor->bytes); 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 " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": exception class index " << index << "is not a valid CONSTANT_class entry " << "while parsing excpetions for method " << _name->bytes << _descriptor->bytes); @@ -1070,8 +1064,8 @@ bool Method::_parse_exceptions(Const_Poo } } if (attr_len != _n_exceptions * sizeof(uint16) + sizeof(_n_exceptions) ) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": invalid Exceptions attribute length " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": invalid Exceptions attribute length " << "while parsing excpetions for method " << _name->bytes << _descriptor->bytes); return false; @@ -1129,7 +1123,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)) { @@ -1149,7 +1143,7 @@ bool Method::_parse_local_vars(const cha return true; } - Local_Var_Table* table = (Local_Var_Table *)_class->class_loader->Alloc( + Local_Var_Table* table = (Local_Var_Table *)_class->get_class_loader()->Alloc( sizeof(Local_Var_Table) + sizeof(Local_Var_Entry) * (n_local_vars - 1)); // ppervov: FIXME: should throw OOME @@ -1190,14 +1184,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,36 +1227,37 @@ 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)) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": could not parse max_stack " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": could not parse max_stack " << "while parsing Code attribute for method " << _name->bytes << _descriptor->bytes); return false; } if(!cfs.parse_u2_be(&_max_locals)) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": could not parse max_locals " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": could not parse max_locals " << "while parsing Code attribute for method " << _name->bytes << _descriptor->bytes); return false; } - if(_max_locals < (get_num_arg_bytes() / 4) ) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": wrong max_locals count " + if(_max_locals < _arguments_size/4) { + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": wrong max_locals count " << "while parsing Code attribute for method " << _name->bytes << _descriptor->bytes); return false; } if(!cfs.parse_u4_be(& _byte_code_length)) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": could not parse bytecode length " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": could not parse bytecode length " << "while parsing Code attribute for method " << _name->bytes << _descriptor->bytes); return false; @@ -1272,8 +1267,8 @@ bool Method::_parse_code( Const_Pool *cp if(_byte_code_length == 0 || (_byte_code_length >= (1<<16) && !is_native() && !is_abstract())) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": bytecode length for method " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": bytecode length for method " << _name->bytes << _descriptor->bytes << " has zero length"); return false; @@ -1289,8 +1284,8 @@ bool Method::_parse_code( Const_Pool *cp unsigned i; for (i=0; i<_byte_code_length; i++) { if(!cfs.parse_u1((uint8 *)&_byte_codes[i])) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": could not parse bytecode for method " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": could not parse bytecode for method " << _name->bytes << _descriptor->bytes); return false; } @@ -1298,8 +1293,8 @@ bool Method::_parse_code( Const_Pool *cp real_code_attr_len += _byte_code_length; if(!cfs.parse_u2_be(&_n_handlers)) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": could not parse number of exception handlers for method " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": could not parse number of exception handlers for method " << _name->bytes << _descriptor->bytes); return false; } @@ -1312,9 +1307,9 @@ 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)) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": could not parse exceptions for method " + if(!_handlers[i].parse(cp, _byte_code_length, cfs)) { + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": could not parse exceptions for method " << _name->bytes << _descriptor->bytes); return false; } @@ -1326,8 +1321,8 @@ bool Method::_parse_code( Const_Pool *cp // uint16 n_attrs; if(!cfs.parse_u2_be(&n_attrs)) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": could not parse number of attributes for method " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": could not parse number of attributes for method " << _name->bytes << _descriptor->bytes); return false; } @@ -1338,7 +1333,7 @@ bool Method::_parse_code( Const_Pool *cp uint32 attr_len = 0; for (i=0; iclass_loader, _class, "java/lang/InternalError", - _class->name->bytes << ": unknown error occured " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/InternalError", + _class->get_name()->bytes << ": unknown error occured " "while parsing attributes for code of method " << _name->bytes << _descriptor->bytes << "; unprocessed attribute " << cur_attr); @@ -1394,8 +1389,8 @@ bool Method::_parse_code( Const_Pool *cp } // for if(code_attr_len != real_code_attr_len) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": Code attribute length does not match real length " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": Code attribute length does not match real length " "in class file (" << code_attr_len << " vs. " << real_code_attr_len << ") while parsing attributes for code of method " << _name->bytes << _descriptor->bytes); @@ -1442,10 +1437,10 @@ check_method_descriptor( const char *des } -bool Method::parse(Global_Env& env, Class *clss, Const_Pool *cp, unsigned cp_size, +bool Method::parse(Global_Env& env, Class* clss, ByteReader &cfs) { - if (!Class_Member::parse(clss, cp, cp_size, cfs)) + if(!Class_Member::parse(clss, cfs)) return false; if(!check_method_name(_name, env)) { @@ -1455,29 +1450,26 @@ bool Method::parse(Global_Env& env, Clas // check method descriptor if(!check_method_descriptor(_descriptor->bytes)) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": invalid descriptor " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": invalid descriptor " "while parsing method " << _name->bytes << _descriptor->bytes); return false; } + calculate_arguments_size(); uint16 attr_count; if (!cfs.parse_u2_be(&attr_count)) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": could not parse attributes count for method " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": could not parse attributes count for method " << _name->bytes << _descriptor->bytes); return false; } _intf_method_for_fake_method = NULL; - // + // set the has_finalizer, is_clinit and is_init flags - // if (_name == env.FinalizeName_String && _descriptor == env.VoidVoidDescriptor_String) { _flags.is_finalize = 1; - if(clss->name != env.JavaLangObject_String) { - clss->has_finalizer = 1; - } } else if (_name == env.Init_String) _flags.is_init = 1; @@ -1489,8 +1481,8 @@ bool Method::parse(Global_Env& env, Clas if(is_private() && is_protected() || is_private() && is_public() || is_protected() && is_public()) { bool bout = false; - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": invalid combination of access flags (" + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": invalid combination of access flags (" << ((bout = is_public())?"ACC_PUBLIC":"") << (bout?"|":"") << ((bout |= is_protected())?"ACC_PROTECTED":"") @@ -1504,8 +1496,8 @@ bool Method::parse(Global_Env& env, Clas && (is_final() || is_native() || is_private() || is_static() || is_strict() || is_synchronized())) { bool bout = false; - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": invalid combination of access flags (ACC_ABSTRACT|" + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": invalid combination of access flags (ACC_ABSTRACT|" << ((bout = is_final())?"ACC_FINAL":"") << (bout?"|":"") << ((bout |= is_native())?"ACC_NATIVE":"") @@ -1521,28 +1513,28 @@ bool Method::parse(Global_Env& env, Clas << _name->bytes << _descriptor->bytes); return false; } - if(class_is_interface(_class) && !(is_abstract() && is_public())) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << "." << _name->bytes << _descriptor->bytes + if(_class->is_interface() && !(is_abstract() && is_public())) { + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << "." << _name->bytes << _descriptor->bytes << ": interface method cannot have access flags other then " "ACC_ABSTRACT and ACC_PUBLIC set" ); return false; } - if(class_is_interface(_class) && + if(_class->is_interface() && (is_private() || is_protected() || is_static() || is_final() || is_synchronized() || is_native() || is_strict())) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << "." << _name->bytes << _descriptor->bytes + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << "." << _name->bytes << _descriptor->bytes << ": interface method cannot have access flags other then " "ACC_ABSTRACT and ACC_PUBLIC set"); return false; } } if(is_init() && (is_static() || is_final() || is_synchronized() || is_native() || is_abstract() || is_bridge())) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << "." << _name->bytes << _descriptor->bytes + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << "." << _name->bytes << _descriptor->bytes << ": constructor cannot have access flags other then " "ACC_STRICT and one of ACC_PUBLIC, ACC_PRIVATE, or ACC_PROTECTED set"); return false; @@ -1564,22 +1556,23 @@ bool Method::parse(Global_Env& env, Clas unsigned n_code_attr = 0; unsigned n_exceptions_attr = 0; uint32 attr_len = 0; + ConstantPool& cp = clss->get_constant_pool(); for (unsigned j=0; jclass_loader->Alloc( + _param_annotations = (AnnotationTable**)_class->get_class_loader()->Alloc( _num_param_annotations * sizeof (AnnotationTable*)); for (unsigned i = 0; i < _num_param_annotations; i++) @@ -1634,7 +1627,7 @@ bool Method::parse(Global_Env& env, Clas REPORT_FAILED_METHOD("more than one AnnotationDefault attribute"); return false; } - _default_value = (AnnotationValue *)_class->class_loader->Alloc( + _default_value = (AnnotationValue *)_class->get_class_loader()->Alloc( sizeof(AnnotationValue)); uint16 read_len = parse_annotation_value(*_default_value, cfs, clss); @@ -1661,8 +1654,8 @@ bool Method::parse(Global_Env& env, Clas return false; case ATTR_UNDEF: // unprocessed - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/InternalError", - clss->name->bytes + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/InternalError", + clss->get_name()->bytes << " : error parsing attributes for method " << _name->bytes << _descriptor->bytes << "; unprocessed attribute " << cur_attr); @@ -1676,29 +1669,29 @@ bool Method::parse(Global_Env& env, Clas // attribute per method // if (n_code_attr > 1) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": there is more than one Code attribute for method " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": there is more than one Code attribute for method " << _name->bytes << _descriptor->bytes); return false; } if(n_exceptions_attr > 1) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << ": there is more than one Exceptions attribute for method " + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << ": there is more than one Exceptions attribute for method " << _name->bytes << _descriptor->bytes); return false; } if((is_abstract() || is_native()) && n_code_attr > 0) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << "." << _name->bytes << _descriptor->bytes + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << "." << _name->bytes << _descriptor->bytes << ": " << (is_abstract()?"abstract":(is_native()?"native":"")) << " method should not have Code attribute present"); return false; } if(!(is_abstract() || is_native()) && n_code_attr == 0) { - REPORT_FAILED_CLASS_CLASS(_class->class_loader, _class, "java/lang/ClassFormatError", - _class->name->bytes << "." << _name->bytes << _descriptor->bytes + REPORT_FAILED_CLASS_CLASS(_class->get_class_loader(), _class, "java/lang/ClassFormatError", + _class->get_name()->bytes << "." << _name->bytes << _descriptor->bytes << ": Java method should have Code attribute present"); return false; } @@ -1707,17 +1700,11 @@ bool Method::parse(Global_Env& env, Clas } //Method::parse - - - - -static bool class_parse_fields(Global_Env* env, - Class *clss, - ByteReader &cfs) +bool Class::parse_fields(Global_Env* env, ByteReader& cfs) { // Those fields are added by the loader even though they are nor defined // in their corresponding class files. - static struct VMExtraFieldDescription { + static struct VMExtraFieldDescription { const String* classname; String* fieldname; String* descriptor; @@ -1733,53 +1720,53 @@ static bool class_parse_fields(Global_En env->string_pool.lookup("vm_class"), env->string_pool.lookup("J"), ACC_PRIVATE}, }; - if(!cfs.parse_u2_be(&clss->n_fields)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse number of fields"); + if(!cfs.parse_u2_be(&m_num_fields)) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + get_name()->bytes << ": could not parse number of fields"); return false; } - int num_fields_in_class_file = clss->n_fields; + int num_fields_in_class_file = m_num_fields; int i; for(i = 0; i < int(sizeof(vm_extra_fields)/sizeof(VMExtraFieldDescription)); i++) { - if(clss->name == vm_extra_fields[i].classname) { - clss->n_fields++; + if(get_name() == vm_extra_fields[i].classname) { + m_num_fields++; } } - clss->fields = new Field[clss->n_fields]; + m_fields = new Field[m_num_fields]; // ppervov: FIXME: should throw OOME - clss->n_static_fields = 0; + m_num_static_fields = 0; unsigned short last_nonstatic_field = (unsigned short)num_fields_in_class_file; - for (i=0; i < num_fields_in_class_file; i++) { + for(i=0; i < num_fields_in_class_file; i++) { Field fd; - if(!fd.parse(clss, clss->const_pool, clss->cp_size, cfs)) + if(!fd.parse(this, cfs)) return false; if(fd.is_static()) { - clss->fields[clss->n_static_fields] = fd; - clss->n_static_fields++; + m_fields[m_num_static_fields] = fd; + m_num_static_fields++; } else { last_nonstatic_field--; - clss->fields[last_nonstatic_field] = fd; + m_fields[last_nonstatic_field] = fd; } } - assert(last_nonstatic_field == clss->n_static_fields); + assert(last_nonstatic_field == m_num_static_fields); for(i = 0; i < int(sizeof(vm_extra_fields)/sizeof(VMExtraFieldDescription)); i++) { - if(clss->name == vm_extra_fields[i].classname) { - Field* f = clss->fields+num_fields_in_class_file; - f->set(clss, vm_extra_fields[i].fieldname, + if(get_name() == vm_extra_fields[i].classname) { + Field& f = m_fields[num_fields_in_class_file]; + f.set(this, vm_extra_fields[i].fieldname, vm_extra_fields[i].descriptor, vm_extra_fields[i].accessflags); - f->set_injected(); + f.set_injected(); TypeDesc* td = type_desc_create_from_java_descriptor( - vm_extra_fields[i].descriptor->bytes, clss->class_loader); + vm_extra_fields[i].descriptor->bytes, m_class_loader); if( td == NULL ) { // error occured // ppervov: FIXME: should throw OOME return false; } - f->set_field_type_desc(td); + f.set_field_type_desc(td); num_fields_in_class_file++; } } @@ -1790,43 +1777,44 @@ static bool class_parse_fields(Global_En long _total_method_bytes = 0; -static bool class_parse_methods(Class *clss, - ByteReader &cfs, - Global_Env* env) +bool Class::parse_methods(Global_Env* env, ByteReader &cfs) { - if(!cfs.parse_u2_be(&clss->n_methods)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse number of methods"); + if(!cfs.parse_u2_be(&m_num_methods)) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + get_name()->bytes << ": could not parse number of methods"); return false; } - clss->methods = new Method[clss->n_methods]; + m_methods = new Method[m_num_methods]; - _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)) + _total_method_bytes += sizeof(Method)*m_num_methods; + for(unsigned i = 0; i < m_num_methods; i++) { + if(!m_methods[i].parse(*env, this, cfs)) { return false; - Method *m = &clss->methods[i]; + } + Method* m = &m_methods[i]; if(m->is_clinit()) { // There can be at most one clinit per class. - if(clss->static_initializer) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": there is more than one class initialization method"); + if(m_static_initializer) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + get_name()->bytes << ": there is more than one class initialization method"); return false; } - clss->static_initializer = &(clss->methods[i]); + m_static_initializer = &(m_methods[i]); } // to cache the default constructor - if (m->get_name() == VM_Global_State::loader_env->Init_String && m->get_descriptor() == VM_Global_State::loader_env->VoidVoidDescriptor_String) { - clss->default_constructor = &(clss->methods[i]); - } + if (m->get_name() == VM_Global_State::loader_env->Init_String + && m->get_descriptor() == VM_Global_State::loader_env->VoidVoidDescriptor_String) + { + m_default_constructor = &m_methods[i]; + } } return true; // success } //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,51 +1835,51 @@ 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)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse constant pool size"); + if(!cfs.parse_u2_be(&m_size)) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_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)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse constant pool tag for index " << i); + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": could not parse constant pool tag for index " << i); 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)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse name index " + if(!cfs.parse_u2_be(&m_entries[i].CONSTANT_Class.name_index)) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": could not parse name index " "for CONSTANT_Class entry"); return false; } @@ -1900,31 +1888,31 @@ 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)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse class index for CONSTANT_*ref entry"); + if(!cfs.parse_u2_be(&m_entries[i].CONSTANT_ref.class_index)) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_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)) { - 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"); + if(!cfs.parse_u2_be(&m_entries[i].CONSTANT_ref.name_and_type_index)) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": could not parse name-and-type index for CONSTANT_*ref entry"); return false; } break; case CONSTANT_String: - if(!cfs.parse_u2_be(&clss->const_pool[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"); + if(!cfs.parse_u2_be(&m_entries[i].CONSTANT_String.string_index)) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": could not parse string index for CONSTANT_String entry"); return false; } break; case CONSTANT_Float: case CONSTANT_Integer: - if(!cfs.parse_u4_be(&clss->const_pool[i].int_value)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse value for " + if(!cfs.parse_u4_be(&m_entries[i].int_value)) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": could not parse value for " << (tag==CONSTANT_Integer?"CONSTANT_Integer":"CONSTANT_Float") << " entry"); return false; } @@ -1934,15 +1922,15 @@ 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)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse high four bytes for " + if(!cfs.parse_u4_be(&m_entries[i].CONSTANT_8byte.high_bytes)) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_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)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse low four bytes for " + if(!cfs.parse_u4_be(&m_entries[i].CONSTANT_8byte.low_bytes)) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": could not parse low four bytes for " << (tag==CONSTANT_Long?"CONSTANT_Long":"CONSTANT_Double") << " entry"); return false; } @@ -1952,15 +1940,15 @@ static bool class_parse_const_pool(Class break; case CONSTANT_NameAndType: - if(!cfs.parse_u2_be(&clss->const_pool[i].CONSTANT_NameAndType.name_index)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse name index " + if(!cfs.parse_u2_be(&m_entries[i].CONSTANT_NameAndType.name_index)) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_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)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse descriptor index " + if(!cfs.parse_u2_be(&m_entries[i].CONSTANT_NameAndType.descriptor_index)) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": could not parse descriptor index " "for CONSTANT_NameAndType entry"); return false; } @@ -1969,55 +1957,37 @@ 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"); + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_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: - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": unknown constant pool tag " << cp_tags[i]); + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": unknown constant pool tag " << cp_tags[i]); return false; } } 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"); + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": wrong name index for CONSTANT_Class entry"); return false; } break; @@ -2026,34 +1996,31 @@ 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) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": wrong class index for CONSTANT_*ref entry"); + 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->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_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) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": wrong name-and-type index for CONSTANT_*ref entry"); + if (!is_valid_index(name_type_index) || !is_name_and_type(name_type_index)) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": wrong name-and-type index for CONSTANT_*ref entry"); return false; } break; } 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"); + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_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,74 +2031,80 @@ 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) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": wrong name index for CONSTANT_NameAndType entry"); + 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->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_name()->bytes << ": wrong name index for CONSTANT_NameAndType entry"); return false; } - if (descriptor_index >= cp_size || - cp_tag(cp,descriptor_index) != CONSTANT_Utf8) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": wrong descriptor index for CONSTANT_NameAndType entry"); + if (!is_valid_index(descriptor_index) || !is_utf8(descriptor_index)) { + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_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: // nothing to do here break; default: - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": wrong constant pool tag"); + REPORT_FAILED_CLASS_CLASS(clss->get_class_loader(), clss, "java/lang/ClassFormatError", + clss->get_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) +bool Class::parse_interfaces(ByteReader &cfs) { - if(!cfs.parse_u2_be(&clss->n_superinterfaces)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse number of superinterfaces"); + if(!cfs.parse_u2_be(&m_num_superinterfaces)) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + get_name()->bytes << ": could not parse number of superinterfaces"); return false; } - clss->superinterfaces = (Class_Superinterface *) clss->class_loader-> - Alloc(sizeof(Class_Superinterface)*clss->n_superinterfaces); + m_superinterfaces = (Class_Super*)m_class_loader-> + Alloc(sizeof(Class_Super)*m_num_superinterfaces); // ppervov: FIXME: should throw OOME - for (unsigned i=0; in_superinterfaces; i++) { + for (unsigned i=0; iclass_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse superinterface index"); + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + get_name()->bytes << ": could not parse superinterface index"); return false; } // // 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); - 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" + m_superinterfaces[i].name = cp_check_class(m_const_pool, interface_index); + if(m_superinterfaces[i].name == NULL) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + get_name()->bytes << ": constant pool index " + << i << " is not CONSTANT_Class entry" " while parsing superinterfaces"); return false; } + m_superinterfaces[i].cp_index = interface_index; } return true; -} //class_parse_interfaces +} // Class::parse_interfaces +// +// magic number, and major/minor version numbers of class file +// +#define CLASSFILE_MAGIC 0xCAFEBABE +#define CLASSFILE_MAJOR 45 +// Supported class files up to this version +#define CLASSFILE_MAJOR_MAX 49 +#define CLASSFILE_MINOR 3 /* - * Parses and verifies the classfile. Format is (from JVM spec) : + * Parses and verifies the classfile. Format is (from JVM spec): * * ClassFile { * u4 magic; @@ -2152,24 +2125,22 @@ static bool class_parse_interfaces(Class * attribute_info attributes[attributes_count]; * } */ -bool class_parse(Global_Env* env, - Class* clss, - unsigned* super_class_cp_index, - ByteReader& cfs) +bool Class::parse(Global_Env* env, + ByteReader& cfs) { /* * get and check magic number (Oxcafebabe) */ uint32 magic; if (!cfs.parse_u4_be(&magic)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ".class is not a valid Java class file"); + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + "class is not a valid Java class file"); return false; } if (magic != CLASSFILE_MAGIC) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": invalid magic"); + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + "invalid magic"); return false; } @@ -2179,51 +2150,50 @@ bool class_parse(Global_Env* env, */ uint16 minor_version; if (!cfs.parse_u2_be(&minor_version)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse minor version"); + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + "could not parse minor version"); return false; } uint16 major_version; if (!cfs.parse_u2_be(&major_version)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse major version"); + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + "could not parse major version"); return false; } if (!(major_version >= CLASSFILE_MAJOR && major_version <= CLASSFILE_MAJOR_MAX)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/UnsupportedClassVersionError", - clss->name->bytes << " has version number " << major_version); + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/UnsupportedClassVersionError", + "class has version number " << major_version); return false; } /* * allocate and parse constant pool */ - if (!class_parse_const_pool(clss, env->string_pool, cfs)) { + if(!m_const_pool.parse(this, env->string_pool, cfs)) return false; - } /* * check and preprocess the constant pool */ - if (!check_const_pool(clss, clss->const_pool, clss->cp_size)) + if(!m_const_pool.check(this)) return false; - if(!cfs.parse_u2_be(&clss->access_flags)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse access flags"); + if(!cfs.parse_u2_be(&m_access_flags)) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": could not parse access flags"); return false; } - if (class_is_interface(clss)) { - // NOTE: Fix for the bug that an interface should have + if(is_interface()) { + // NOTE: Fix for the statement that an interface should have // abstract flag set. // spec/harness/BenchmarkDone has interface flag, but it does not // have abstract flag. - clss->access_flags |= ACC_ABSTRACT; + m_access_flags |= ACC_ABSTRACT; } /* @@ -2231,15 +2201,15 @@ bool class_parse(Global_Env* env, */ uint16 this_class; if (!cfs.parse_u2_be(&this_class)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse this class index"); + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": could not parse this class index"); return false; } - String *name = cp_check_class(clss->const_pool, clss->cp_size, this_class); - if (name == NULL) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": this_class constant pool entry " + String * class_name = cp_check_class(m_const_pool, this_class); + if (class_name == NULL) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": this_class constant pool entry " << this_class << " is an illegal CONSTANT_Class entry"); return false; } @@ -2248,50 +2218,49 @@ bool class_parse(Global_Env* env, * When defineClass from byte stream, there are cases that clss->name is null, * so we should add a check here */ - if (clss->name && name != clss->name) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, + if(m_name != NULL && class_name != m_name) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, VM_Global_State::loader_env->JavaLangNoClassDefFoundError_String->bytes, - clss->name->bytes << ": class name in class data does not match class name passed"); + m_name->bytes << ": class name in class data does not match class name passed"); return false; } - if (!clss->name) { - clss->name = name; + if(m_name == NULL) { + m_name = class_name; } /* * Mark the current class as resolved. */ - cp_resolve_to_class(clss->const_pool, this_class, clss); + m_const_pool.resolve_entry(this_class, this); /* * parse the super class name */ uint16 super_class; if (!cfs.parse_u2_be(&super_class)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse super class index"); + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": could not parse super class index"); return false; } - *super_class_cp_index = super_class; - + m_super_class.cp_index = super_class; if (super_class == 0) { // // this class must represent java.lang.Object // - if(clss->name != env->JavaLangObject_String) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": class does not contain super class " + if(m_name != env->JavaLangObject_String) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": class does not contain super class " << "but is not java.lang.Object class"); return false; } - clss->super_name = NULL; + m_super_class.name = NULL; } else { - clss->super_name = cp_check_class(clss->const_pool, clss->cp_size, 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 " + m_super_class.name = cp_check_class(m_const_pool, super_class); + if (m_super_class.name == NULL) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": super_class constant pool entry " << super_class << " is an illegal CONSTANT_Class entry"); return false; } @@ -2300,20 +2269,19 @@ bool class_parse(Global_Env* env, /* * allocate and parse class' interfaces */ - if (!class_parse_interfaces(clss, cfs)) + if(!parse_interfaces(cfs)) return false; /* * allocate and parse class' fields */ - if (!class_parse_fields(env, clss, cfs)) + if(!parse_fields(env, cfs)) return false; - /* * allocate and parse class' methods */ - if (!class_parse_methods(clss, cfs, env)) + if(!parse_methods(env, cfs)) return false; /* @@ -2321,8 +2289,8 @@ bool class_parse(Global_Env* env, */ uint16 n_attrs; if (!cfs.parse_u2_be(&n_attrs)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse number of attributes"); + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": could not parse number of attributes"); return false; } @@ -2332,21 +2300,21 @@ 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, m_const_pool, class_attr_strings, class_attrs, &attr_len); switch(cur_attr){ case ATTR_SourceFile: { // a class file can have at most one source file attribute if (++n_source_file_attr > 1) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": there is more than one SourceFile attribute"); + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": there is more than one SourceFile attribute"); return false; } // attribute length must be two (vm spec 4.7.2) if (attr_len != 2) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": SourceFile attribute has incorrect length (" + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": SourceFile attribute has incorrect length (" << attr_len << " bytes, should be 2 bytes)"); return false; } @@ -2354,16 +2322,16 @@ bool class_parse(Global_Env* env, // constant value attribute uint16 filename_index; if(!cfs.parse_u2_be(&filename_index)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse filename index" + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": could not parse filename index" << " while parsing SourceFile attribute"); return false; } - clss->src_file_name = cp_check_utf8(clss->const_pool,clss->cp_size,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" + m_src_file_name = cp_check_utf8(m_const_pool, filename_index); + if(m_src_file_name == NULL) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": filename index points to incorrect constant pool entry" << " while parsing SourceFile attribute"); return false; } @@ -2372,115 +2340,115 @@ bool class_parse(Global_Env* env, case ATTR_InnerClasses: { - if (clss->declaringclass_index || clss->innerclass_indexes) { - REPORT_FAILED_CLASS_FORMAT(clss, "more than one InnerClasses attribute"); + if (m_declaring_class_index || m_innerclasses) { + REPORT_FAILED_CLASS_FORMAT(this, "more than one InnerClasses attribute"); } bool isinner = false; // found_myself == 2: myself is not inner class or has passed myself when iterating inner class attribute arrays // found_myself == 1: myself is inner class, current index of inner class attribute arrays is just myself // found_myself == 0: myself is inner class, hasn't met myself in inner class attribute arrays int found_myself = 2; - if(strchr(clss->name->bytes, '$')){ + if(strchr(m_name->bytes, '$')){ isinner = true; found_myself = 0; } //Only handle inner class uint16 num_of_classes; if(!cfs.parse_u2_be(&num_of_classes)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse number of classes" + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": could not parse number of classes" << " while parsing InnerClasses attribute"); return false; } if(isinner) - clss->n_innerclasses = (uint16)(num_of_classes - 1); //exclude itself + m_num_innerclasses = (uint16)(num_of_classes - 1); //exclude itself else - clss->n_innerclasses = num_of_classes; + m_num_innerclasses = num_of_classes; if(num_of_classes) - clss->innerclass_indexes = (uint16*) clss->class_loader-> - Alloc(2*sizeof(uint16)*clss->n_innerclasses); + m_innerclasses = (InnerClass*) m_class_loader-> + Alloc(2*sizeof(InnerClass)*m_num_innerclasses); // ppervov: FIXME: should throw OOME int index = 0; for(int i = 0; i < num_of_classes; i++){ uint16 inner_clss_info_idx; if(!cfs.parse_u2_be(&inner_clss_info_idx)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse inner class info index" + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": could not parse inner class info index" << " while parsing InnerClasses attribute"); return false; } if(inner_clss_info_idx - && cp_tag(clss->const_pool,inner_clss_info_idx) != CONSTANT_Class) + && !valid_cpi(this, 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" + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": inner class info index points to incorrect constant pool entry" << " while parsing InnerClasses attribute"); return false; } if(!found_myself){ - String *clssname = cp_check_class(clss->const_pool, clss->cp_size, inner_clss_info_idx); + String* clssname = cp_check_class(m_const_pool, inner_clss_info_idx); // Only handle this class - if(clss->name == clssname) + if(m_name == clssname) found_myself = 1; } if(found_myself != 1) - clss->innerclass_indexes[index++] = inner_clss_info_idx; + m_innerclasses[index].index = inner_clss_info_idx; uint16 outer_clss_info_idx; if(!cfs.parse_u2_be(&outer_clss_info_idx)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse outer class info index" + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": could not parse outer class info index" << " while parsing InnerClasses attribute"); return false; } if(outer_clss_info_idx - && cp_tag(clss->const_pool,outer_clss_info_idx) != CONSTANT_Class) + && !valid_cpi(this, 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"); + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": outer class info index points to incorrect constant pool entry" + << outer_clss_info_idx << " while parsing InnerClasses attribute"); return false; } if(found_myself == 1 && outer_clss_info_idx){ - clss->declaringclass_index = outer_clss_info_idx; + m_declaring_class_index = outer_clss_info_idx; } uint16 inner_name_idx; if(!cfs.parse_u2_be(&inner_name_idx)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse inner name index" + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": could not parse inner name index" << " while parsing InnerClasses attribute"); return false; } - if(inner_name_idx && !valid_cpi(clss, inner_name_idx, CONSTANT_Utf8)) + if(inner_name_idx && !valid_cpi(this, inner_name_idx, CONSTANT_Utf8)) { - REPORT_FAILED_CLASS_FORMAT(clss, + REPORT_FAILED_CLASS_FORMAT(this, "inner name index points to incorrect constant pool entry"); return false; } - if(found_myself == 1 /*&& outer_clss_info_idx*/){ + if(found_myself == 1){ if (inner_name_idx) { - clss->simple_name = clss->const_pool[inner_name_idx].CONSTANT_Utf8.string; + m_simple_name = m_const_pool.get_utf8_string(inner_name_idx); } else { //anonymous class - clss->simple_name = env->string_pool.lookup(""); + m_simple_name = env->string_pool.lookup(""); } } uint16 inner_clss_access_flag; if(!cfs.parse_u2_be(&inner_clss_access_flag)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": could not parse inner class access flags" + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": could not parse inner class access flags" << " while parsing InnerClasses attribute"); return false; } if(found_myself == 1) { found_myself = 2; - clss->access_flags = inner_clss_access_flag; + m_access_flags = inner_clss_access_flag; } else - clss->innerclass_indexes[index++] = inner_clss_access_flag; + m_innerclasses[index++].access_flags = inner_clss_access_flag; } // for num_of_classes }break; //case ATTR_InnerClasses @@ -2489,17 +2457,17 @@ bool class_parse(Global_Env* env, // attribute length is already recorded in attr_len // now reading debug extension information if( ++numSourceDebugExtensions > 1 ) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/ClassFormatError", - clss->name->bytes << ": there is more than one SourceDebugExtension attribute"); + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", + m_name->bytes << ": there is more than one SourceDebugExtension attribute"); return false; } // 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); - if (!clss->sourceDebugExtension) { - REPORT_FAILED_CLASS_FORMAT(clss, "invalid SourceDebugExtension attribute"); + m_sourceDebugExtension = class_file_parse_utf8data(env->string_pool, cfs, attr_len); + if(!m_sourceDebugExtension) { + REPORT_FAILED_CLASS_FORMAT(this, "invalid SourceDebugExtension attribute"); return false; } } @@ -2508,74 +2476,74 @@ bool class_parse(Global_Env* env, case ATTR_EnclosingMethod: { if ( ++numEnclosingMethods > 1 ) { - REPORT_FAILED_CLASS_FORMAT(clss,"more than one EnclosingMethod attribute"); + REPORT_FAILED_CLASS_FORMAT(this, "more than one EnclosingMethod attribute"); return false; } if (attr_len != 4) { - REPORT_FAILED_CLASS_FORMAT(clss, + REPORT_FAILED_CLASS_FORMAT(this, "unexpected length of EnclosingMethod attribute: " << attr_len); return false; } uint16 class_idx; if(!cfs.parse_u2_be(&class_idx)) { - REPORT_FAILED_CLASS_FORMAT(clss, + REPORT_FAILED_CLASS_FORMAT(this, "could not parse class index of EnclosingMethod attribute"); return false; } - if(!valid_cpi(clss, class_idx, CONSTANT_Class)) + if(!valid_cpi(this, class_idx, CONSTANT_Class)) { - REPORT_FAILED_CLASS_FORMAT(clss, + REPORT_FAILED_CLASS_FORMAT(this, "incorrect class index of EnclosingMethod attribute"); return false; } - clss->enclosing_class_index = class_idx; + m_enclosing_class_index = class_idx; uint16 method_idx; if(!cfs.parse_u2_be(&method_idx)) { - REPORT_FAILED_CLASS_FORMAT(clss, + REPORT_FAILED_CLASS_FORMAT(this, "could not parse method index of EnclosingMethod attribute"); return false; } - if(method_idx && !valid_cpi(clss, method_idx, CONSTANT_NameAndType)) + if(method_idx && !valid_cpi(this, method_idx, CONSTANT_NameAndType)) { - REPORT_FAILED_CLASS_FORMAT(clss, + REPORT_FAILED_CLASS_FORMAT(this, "incorrect method index of EnclosingMethod attribute"); return false; } - clss->enclosing_method_index = method_idx; + m_enclosing_method_index = method_idx; } break; case ATTR_Synthetic: { if(attr_len != 0) { - REPORT_FAILED_CLASS_FORMAT(clss, + REPORT_FAILED_CLASS_FORMAT(this, "attribute Synthetic has non-zero length"); return false; } - clss->access_flags |= ACC_SYNTHETIC; + m_access_flags |= ACC_SYNTHETIC; } break; case ATTR_Deprecated: { if(attr_len != 0) { - REPORT_FAILED_CLASS_FORMAT(clss, + REPORT_FAILED_CLASS_FORMAT(this, "attribute Deprecated has non-zero length"); return false; } - clss->deprecated = true; + m_deprecated = true; } break; case ATTR_Signature: { - if(clss->Signature) { - REPORT_FAILED_CLASS_FORMAT(clss, + if(m_signature != NULL) { + REPORT_FAILED_CLASS_FORMAT(this, "more than one Signature attribute for the class"); return false; } - if (!(clss->Signature = parse_signature_attr(cfs, attr_len, clss))) { + if (!(m_signature = parse_signature_attr(cfs, attr_len, this))) { return false; } } @@ -2583,9 +2551,9 @@ bool class_parse(Global_Env* env, case ATTR_RuntimeVisibleAnnotations: { - uint32 read_len = parse_annotation_table(&(clss->annotations), cfs, clss); + uint32 read_len = parse_annotation_table(&m_annotations, cfs, this); if (attr_len != read_len) { - REPORT_FAILED_CLASS_FORMAT(clss, + REPORT_FAILED_CLASS_FORMAT(this, "error parsing Annotations attribute" << "; declared length " << attr_len << " does not match actual " << read_len); @@ -2597,7 +2565,7 @@ bool class_parse(Global_Env* env, case ATTR_RuntimeInvisibleAnnotations: { if(!cfs.skip(attr_len)) { - REPORT_FAILED_CLASS_FORMAT(clss, + REPORT_FAILED_CLASS_FORMAT(this, "failed to skip RuntimeInvisibleAnnotations attribute"); return false; } @@ -2609,8 +2577,8 @@ bool class_parse(Global_Env* env, break; default: // error occured - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, "java/lang/InternalError", - clss->name->bytes << ": unknown error occured" + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/InternalError", + m_name->bytes << ": unknown error occured" " while parsing attributes for class" << "; unprocessed attribute " << cur_attr); return false; @@ -2618,27 +2586,26 @@ bool class_parse(Global_Env* env, } // for if (cfs.have(1)) { - REPORT_FAILED_CLASS_FORMAT(clss, "Extra bytes at the end of class file"); + REPORT_FAILED_CLASS_FORMAT(this, "Extra bytes at the end of class file"); return false; } - if (clss->enclosing_class_index && !clss->simple_name) { + if (m_enclosing_class_index && m_simple_name == NULL) { WARN("Attention: EnclosingMethod attribute does not imply " - "InnerClasses presence for class " << clss->name->bytes); + "InnerClasses presence for class " << m_name->bytes); } - /* * can't be both final and interface, or both final and abstract */ - if (class_is_final(clss) && class_is_interface(clss)) + if(is_final() && is_interface()) { - REPORT_FAILED_CLASS_FORMAT(clss, "interface cannot be final"); + REPORT_FAILED_CLASS_FORMAT(this, "interface cannot be final"); return false; } - if (class_is_final(clss) && class_is_abstract(clss)) { - REPORT_FAILED_CLASS_FORMAT(clss, "abstract class cannot be final"); + if(is_final() && is_abstract()) { + REPORT_FAILED_CLASS_FORMAT(this, "abstract class cannot be final"); return false; } @@ -2649,14 +2616,14 @@ bool class_parse(Global_Env* env, // return false; //} - if(class_is_annotation(clss) && !class_is_interface(clss)) + if(is_annotation() && !is_interface()) { - REPORT_FAILED_CLASS_FORMAT(clss, "annotation type must be interface"); + REPORT_FAILED_CLASS_FORMAT(this, "annotation type must be interface"); return false; } return true; -} //class_parse +} // Class::parse static bool const_pool_find_entry(ByteReader& cp, uint16 cp_count, uint16 index) @@ -2811,7 +2778,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; } @@ -2833,101 +2800,3 @@ Class *class_load_verify_prepare_from_jn Class *clss = env->bootstrap_class_loader->LoadVerifyAndPrepareClass(env, classname); return clss; } - - -//////////////////////////////////////////////////////////////////// -// begin support for JIT notification when classes are extended - -struct Class_Extended_Notification_Record { - Class *class_of_interest; - JIT *jit; - void *callback_data; - Class_Extended_Notification_Record *next; - - bool equals(Class *class_of_interest_, JIT *jit_, void *callback_data_) { - if ((class_of_interest == class_of_interest_) && - (jit == jit_) && - (callback_data == callback_data_)) { - return true; - } - return false; - } -}; - - -// Notify the given JIT whenever the class "clss" is extended. -// The callback_data pointer will be passed back to the JIT during the callback. -// The JIT's callback function is JIT_extended_class_callback. -void class_register_jit_extended_class_callback(Class *clss, JIT *jit_to_be_notified, void *callback_data) -{ - // Don't insert the same entry repeatedly on the notify_extended_records list. - Class_Extended_Notification_Record *nr = clss->notify_extended_records; - while (nr != NULL) { - if (nr->equals(clss, jit_to_be_notified, callback_data)) { - return; - } - nr = nr->next; - } - - // Insert a new notification record. - Class_Extended_Notification_Record *new_nr = - (Class_Extended_Notification_Record *)STD_MALLOC(sizeof(Method_Change_Notification_Record)); - new_nr->class_of_interest = clss; - new_nr->jit = jit_to_be_notified; - new_nr->callback_data = callback_data; - new_nr->next = clss->notify_extended_records; - clss->notify_extended_records = new_nr; -} //class_register_jit_extended_class_callback - - -void do_jit_extended_class_callbacks(Class *clss, Class *new_subclass) -{ - Class_Extended_Notification_Record *nr; - for (nr = clss->notify_extended_records; nr != NULL; nr = nr->next) { - JIT *jit_to_be_notified = nr->jit; - Boolean code_was_modified = - jit_to_be_notified->extended_class_callback(/*extended_class*/ clss, - /*new_class*/ new_subclass, - nr->callback_data); - if (code_was_modified) { -#ifdef _IPF_ - // 20030128 I don't think we have to do a flush_hw_cache() here since that should - // be done by the recompiled_method callbacks. - sync_i_cache(); - do_mf(); -#endif //_IPF_ - } - } -} //do_jit_extended_class_callbacks - -// end support for JIT notification when classes are extended -//////////////////////////////////////////////////////////////////// - - -unsigned class_calculate_size(const Class* klass) -{ - unsigned size = 0; - size += sizeof(Class); - size += klass->n_innerclasses*sizeof(uint16); - size += klass->cp_size*sizeof(Const_Pool); - for(unsigned i = 0; i < klass->n_fields; i++) { - size += klass->fields[i].calculate_size(); - } - for(unsigned i = 0; i < klass->n_methods; i++) { - size += klass->methods[i].calculate_size(); - } - size += klass->n_superinterfaces*sizeof(Class_Superinterface); - size += klass->static_data_size; - size += klass->static_method_size; - if(!class_is_interface(klass)) - size += sizeof(VTable); - size += klass->n_intfc_table_entries*sizeof(Class*); - for(Class_Extended_Notification_Record* mcnr = klass->notify_extended_records; - mcnr != NULL; mcnr = mcnr->next) - { - size += sizeof(Class_Extended_Notification_Record); - } - size += sizeof(Lock_Manager); - - return size; -} diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp index 6c1e828..443617b 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp @@ -51,9 +51,18 @@ ready_for_exceptions(false) // TODO: Use proper MM. properties = new Properties(); bootstrap_class_loader = new BootstrapClassLoader(this); - + hythread_lib_create(&hythread_lib); +#if defined _IPF_ || defined _EM64T_ + compact_fields = true; + sort_fields = true; +#else // !_IPF_ + compact_fields = false; + sort_fields = false; +#endif // !IPF_ + heap_base = heap_end = managed_null = NULL; + JavaLangString_String = string_pool.lookup("java/lang/String"); JavaLangStringBuffer_String = string_pool.lookup("java/lang/StringBuffer"); JavaLangObject_String = string_pool.lookup("java/lang/Object"); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Initialize.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Initialize.cpp index 4d13103..9faa13c 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Initialize.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Initialize.cpp @@ -24,9 +24,9 @@ #include "Class.h" #include "open/jthread.h" +#include "open/gc.h" #include "exceptions.h" #include "thread_manager.h" -#include "Verifier_stub.h" #include "vm_strings.h" #include "classloader.h" #include "ini.h" @@ -34,7 +34,7 @@ // Initializes a class. -static void class_initialize1(Class *clss) +void Class::initialize() { ASSERT_RAISE_AREA; assert(!exn_raised()); @@ -44,74 +44,68 @@ static void class_initialize1(Class *cls // described in page 226, section 12.4.2 of Java Language Spec, 1996 // ISBN 0-201-63451-1 - TRACE2("class.init", "initializing class " << clss->name->bytes); + TRACE2("class.init", "initializing class " << m_name->bytes); // --- step 1 ---------------------------------------------------------- assert(!hythread_is_suspend_enabled()); - jobject jlc = struct_Class_to_java_lang_Class_Handle(clss); + jobject jlc = struct_Class_to_java_lang_Class_Handle(this); jthread_monitor_enter(jlc); // --- step 2 ---------------------------------------------------------- - TRACE2("class.init", "initializing class " << clss->name->bytes << " STEP 2" ); + TRACE2("class.init", "initializing class " << m_name->bytes << " STEP 2" ); - while(((VM_thread *)(clss->p_initializing_thread) != p_TLS_vmthread) && - (clss->state == ST_Initializing) ) { - // thread_object_wait had been expecting the only unsafe reference - // to be its parameter, so enable_gc() should be safe here -salikh + while(m_initializing_thread != p_TLS_vmthread && is_initializing()) { jthread_monitor_wait(jlc); - if (exn_raised()) { - jthread_monitor_exit(jlc); + if(exn_raised()) { + jthread_monitor_exit(jlc); return; } } // --- step 3 ---------------------------------------------------------- - - if ( (VM_thread *)(clss->p_initializing_thread) == p_TLS_vmthread) { + if(m_initializing_thread == p_TLS_vmthread) { jthread_monitor_exit(jlc); return; } // --- step 4 ---------------------------------------------------------- - - if (clss->state == ST_Initialized) { + if(is_initialized()) { jthread_monitor_exit(jlc); return; } // --- step 5 ---------------------------------------------------------- - - if (clss->state == ST_Error) { + if(in_error()) { jthread_monitor_exit(jlc); tmn_suspend_enable(); - exn_raise_by_name("java/lang/NoClassDefFoundError", clss->name->bytes); + exn_raise_by_name("java/lang/NoClassDefFoundError", m_name->bytes); tmn_suspend_disable(); return; } // --- step 6 ---------------------------------------------------------- - TRACE2("class.init", "initializing class " << clss->name->bytes << "STEP 6" ); + TRACE2("class.init", "initializing class " << m_name->bytes << "STEP 6" ); - assert(clss->state == ST_Prepared); - clss->state = ST_Initializing; - assert(clss->p_initializing_thread == 0); - clss->p_initializing_thread = (void *)p_TLS_vmthread; + assert(m_state == ST_ConstraintsVerified); + m_state = ST_Initializing; + assert(m_initializing_thread == 0); + m_initializing_thread = p_TLS_vmthread; jthread_monitor_exit(jlc); // --- step 7 ------------------------------------------------------------ - if (clss->super_class) { - class_initialize_ex(clss->super_class); + if(has_super_class()) { + class_initialize_ex(get_super_class()); - if (clss->super_class->state == ST_Error) { + if(get_super_class()->in_error()) { jthread_monitor_enter(jlc); tmn_suspend_enable(); - REPORT_FAILED_CLASS_CLASS_EXN(clss->class_loader, clss, - class_get_error_cause(clss->super_class)); + REPORT_FAILED_CLASS_CLASS_EXN(m_class_loader, this, + get_super_class()->get_error_cause()); tmn_suspend_disable(); - clss->p_initializing_thread = 0; - clss->state = ST_Error; + m_initializing_thread = NULL; + m_state = ST_Error; assert(!hythread_is_suspend_enabled()); jthread_monitor_notify_all(jlc); jthread_monitor_exit(jlc); @@ -119,63 +113,21 @@ static void class_initialize1(Class *cls } } - // --- step pre-8 ------------------------------------------------------ - // This is an extra step needed to initialize static final fields - - unsigned n_fields = clss->n_fields; - - for (unsigned i = 0; i < n_fields; i++) { - Field *f = &clss->fields[i]; - if (f->is_static() && f->get_const_value_index()) { - void *addr = f->get_address(); - Const_Java_Value cv = f->get_const_value(); - switch (f->get_java_type()) { - case JAVA_TYPE_BYTE: - case JAVA_TYPE_BOOLEAN: - *(int8 *)addr = (int8)cv.i; - break; - case JAVA_TYPE_CHAR: - case JAVA_TYPE_SHORT: - *(int16 *)addr = (int16)cv.i; - break; - case JAVA_TYPE_INT: - *(int32 *)addr = cv.i; - break; - case JAVA_TYPE_LONG: - *(int64 *)addr = cv.j; - break; - case JAVA_TYPE_FLOAT: - *(float *)addr = cv.f; - break; - case JAVA_TYPE_DOUBLE: - *(double *)addr = cv.d; - break; - default: - assert(!strcmp("Ljava/lang/String;", f->get_descriptor()->bytes)); - String *str = cv.string; - Java_java_lang_String *jls = string_create_from_utf8(str->bytes, str->len); - assert(jls != NULL); - STORE_GLOBAL_REFERENCE((COMPRESSED_REFERENCE *)addr, jls); - break; - } - } - } - // --- step 8 ---------------------------------------------------------- - Method *meth = clss->static_initializer; - if (meth == NULL) { + Method* meth = m_static_initializer; + if(meth == NULL) { jthread_monitor_enter(jlc); - clss->state = ST_Initialized; - TRACE2("classloader", "class " << clss->name->bytes << " initialized"); - clss->p_initializing_thread = 0; + m_state = ST_Initialized; + TRACE2("classloader", "class " << m_name->bytes << " initialized"); + m_initializing_thread = NULL; assert(!hythread_is_suspend_enabled()); jthread_monitor_notify_all(jlc); jthread_monitor_exit(jlc); return; } - TRACE2("class.init", "initializing class " << clss->name->bytes << " STEP 8" ); + TRACE2("class.init", "initializing class " << m_name->bytes << " STEP 8" ); jthrowable p_error_object; assert(!hythread_is_suspend_enabled()); @@ -183,14 +135,14 @@ static void class_initialize1(Class *cls p_error_object = exn_get(); // --- step 9 ---------------------------------------------------------- - TRACE2("class.init", "initializing class " << clss->name->bytes << " STEP 9" ); + TRACE2("class.init", "initializing class " << m_name->bytes << " STEP 9" ); if(!p_error_object) { jthread_monitor_enter(jlc); - clss->state = ST_Initialized; - TRACE2("classloader", "class " << clss->name->bytes << " initialized"); - clss->p_initializing_thread = 0; - assert(clss->p_error == 0); + m_state = ST_Initialized; + TRACE2("classloader", "class " << m_name->bytes << " initialized"); + m_initializing_thread = NULL; + assert(m_error == NULL); assert(!hythread_is_suspend_enabled()); jthread_monitor_notify_all(jlc); jthread_monitor_exit(jlc); @@ -202,10 +154,10 @@ static void class_initialize1(Class *cls if(p_error_object) { assert(!hythread_is_suspend_enabled()); exn_clear(); - Class *p_error_class = p_error_object->object->vt()->clss; - Class *jle = VM_Global_State::loader_env->java_lang_Error_Class; + Class* p_error_class = p_error_object->object->vt()->clss; + Class* jle = VM_Global_State::loader_env->java_lang_Error_Class; while(p_error_class && p_error_class != jle) { - p_error_class = p_error_class->super_class; + p_error_class = p_error_class->get_super_class(); } assert(!hythread_is_suspend_enabled()); if((!p_error_class) || (p_error_class != jle) ) { @@ -220,15 +172,14 @@ static void class_initialize1(Class *cls tmn_suspend_disable(); } tmn_suspend_enable(); - class_set_error_cause(clss, p_error_object); - //REPORT_FAILED_CLASS_CLASS_EXN(clss->class_loader, clss, p_error_object); + set_error_cause(p_error_object); tmn_suspend_disable(); // --- step 11 ---------------------------------------------------------- assert(!hythread_is_suspend_enabled()); jthread_monitor_enter(jlc); - clss->state = ST_Error; - clss->p_initializing_thread = 0; + m_state = ST_Error; + m_initializing_thread = NULL; assert(!hythread_is_suspend_enabled()); jthread_monitor_notify_all(jlc); jthread_monitor_exit(jlc); @@ -238,21 +189,16 @@ static void class_initialize1(Class *cls } //class_initialize1 -// Alexei -// migrating to C interfaces -#if (defined __cplusplus) && (defined PLATFORM_POSIX) -extern "C" { -#endif void class_initialize_from_jni(Class *clss) { ASSERT_RAISE_AREA; assert(hythread_is_suspend_enabled()); // check verifier constraints - if(!class_verify_constraints(VM_Global_State::loader_env, clss)) { + if(!clss->verify_constraints(VM_Global_State::loader_env)) { if (!exn_raised()) { tmn_suspend_disable(); - exn_raise_object(class_get_error(clss->class_loader, clss->name->bytes)); + exn_raise_object(class_get_error(clss->get_class_loader(), clss->get_name()->bytes)); tmn_suspend_enable(); } return; @@ -260,15 +206,12 @@ void class_initialize_from_jni(Class *cl tmn_suspend_disable(); if (class_needs_initialization(clss)) { - class_initialize1(clss); + clss->initialize(); } tmn_suspend_enable(); } // class_initialize_from_jni -#if (defined __cplusplus) && (defined PLATFORM_POSIX) -} -#endif -// VMEXPORT + void class_initialize(Class *clss) { ASSERT_RAISE_AREA; @@ -282,16 +225,16 @@ void class_initialize_ex(Class *clss) // check verifier constraints tmn_suspend_enable(); - if(!class_verify_constraints(VM_Global_State::loader_env, clss)) { + if(!clss->verify_constraints(VM_Global_State::loader_env)) { if (!exn_raised()) { tmn_suspend_disable(); - exn_raise_object(class_get_error(clss->class_loader, clss->name->bytes)); + exn_raise_object(class_get_error(clss->get_class_loader(), clss->get_name()->bytes)); } return; } tmn_suspend_disable(); - if ( class_needs_initialization(clss)) { - class_initialize1(clss); + if(class_needs_initialization(clss)) { + clss->initialize(); } -} //class_initialize +} // class_initialize_ex diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp index d604613..167cf54 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp @@ -39,6 +39,7 @@ #include "interpreter.h" #include "lil.h" #include "lil_code_generator.h" +#include "vm_stats.h" #ifdef _DEBUG #include "jni.h" @@ -47,23 +48,13 @@ #include "dump.h" -static void class_initialize_if_no_side_effects(Class *clss); - -static Boolean should_class_not_be_verified(Class* UNREF clss) -{ - return FALSE; -} - - - - // For Java currently, fields are not packed: an int16 occupies a full 32 bit word. // "do_field_compaction" is true, e.g., for packed ("sequential") layout. // If the "clss" pointer is non-NULL, the type must be that of an instance field and any // "padding" bytes for the field are added to the class's total number of field padding bytes. // If "clss" is NULL, no padding information is gathered. -static unsigned sizeof_field_type(Field *field, bool do_field_compaction, Class *clss) +static unsigned sizeof_field_type(Field *field, bool do_field_compaction) { unsigned sz = 0; unsigned pad_bytes = 0; @@ -111,21 +102,16 @@ static unsigned sizeof_field_type(Field ABORT("Invalid type descriptor"); } - if (clss != NULL) { - clss->num_field_padding_bytes += pad_bytes; - } return sz; -} //sizeof_field_type +} // sizeof_field_type - - -// Given a clss that is an primitive array return the size -// of an element in an instance of the class. -// Beware the the class is not fully formed at this time. +// Given a class that is a primitive array returns the size +// of an element in an instance of the class +// NOTE: the class is not fully formed at this time unsigned sizeof_primitive_array_element(Class *p_class) { - const String *elt_type = p_class->name; + const String *elt_type = p_class->get_name(); char elt = elt_type->bytes[1]; unsigned int sz; switch (elt) { @@ -168,18 +154,18 @@ unsigned sizeof_primitive_array_element( // // Is this array class a one dimensional array (vector) with a primitive component type. // -bool +inline bool is_vector_of_primitives(Class* p_class) { // I parse the following character of the class name // to see if it is an array of arrays. - if(p_class->name->bytes[1] == '[') // An array of array + if(p_class->get_name()->bytes[1] == '[') // An array of array return false; - if(p_class->name->bytes[1] == 'L') // An array of objects + if(p_class->get_name()->bytes[1] == 'L') // An array of objects return false; - if(p_class->is_array_of_primitives == 0) // base type is not primitive + if(!p_class->is_array_of_primitives()) // base type is not primitive return false; - if(p_class->is_array) + if(p_class->is_array()) return true; ABORT("Should never be called unless p_class is an array"); return true; @@ -187,12 +173,13 @@ is_vector_of_primitives(Class* p_class) -void assign_instance_field_offset(Class *clss, Field *field, bool do_field_compaction) +void Class::assign_offset_to_instance_field(Field *field, bool do_field_compaction) { - if (!field->is_static() && !field->is_offset_computed()) { - int sz = sizeof_field_type(field, do_field_compaction, clss); - int offset = clss->unpadded_instance_data_size; - // 20020927 We must continue to align fields on natural boundaries: e.g., Java ints on a 4 byte boundary. + if(!field->is_static() && !field->is_offset_computed()) { + int sz = sizeof_field_type(field, do_field_compaction); + int offset = m_unpadded_instance_data_size; + // We must continue to align fields on natural boundaries: + // e.g., Java ints on a 4 byte boundary. // This is required for IPF and can improve IA32 performance. int inc = sz; int delta = offset % sz; @@ -200,46 +187,46 @@ void assign_instance_field_offset(Class int pad_bytes = (sz - delta); offset += pad_bytes; inc += pad_bytes; - clss->num_field_padding_bytes += pad_bytes; + m_num_field_padding_bytes += pad_bytes; } - field->_offset = offset; - clss->unpadded_instance_data_size += inc; + field->set_offset(offset); + m_unpadded_instance_data_size += inc; char c_type = *(field->get_descriptor()->bytes); if ((c_type == '[') || (c_type == 'L')) { - clss->n_instance_refs += 1; + m_num_instance_refs += 1; } - - field->set_offset_computed(true); } -} //assign_instance_field_offset +} // Class::assign_offset_to_instance_field // "field_ptrs" is an array of pointers to the class's fields. -void assign_offsets_to_instance_fields(Class *clss, Field **field_ptrs, bool do_field_compaction) +void Class::assign_offsets_to_instance_fields(Field** field_ptrs, bool do_field_compaction) { int i, sz; - if (clss->n_fields == 0) { - return; - } - - // Try to align the first field on a 4 byte boundary. It might not be if -compact_fields was specified on the command line. - // See whether there are any short instance fields towards the end of the field array (since that is where -sort_fields puts them) - // and try to fill in some bytes before the "first" field. - if (Class::sort_fields && Class::compact_fields) { - if ((clss->unpadded_instance_data_size % 4) != 0) { - int delta = (clss->unpadded_instance_data_size % 4); + if(m_num_fields == 0) return; + + // Try to align the first field on a 4 byte boundary. It might not be if + // -compact_fields was specified on the command line. See whether there are + // any short instance fields towards the end of the field array (since that + // is where -sort_fields puts them) and try to fill in some bytes before + // the "first" field. + if(VM_Global_State::loader_env->sort_fields + && VM_Global_State::loader_env->compact_fields) + { + if((m_unpadded_instance_data_size % 4) != 0) { + int delta = (m_unpadded_instance_data_size % 4); int pad_bytes = (4 - delta); // the number of bytes remaining to fill in - int last_field = (clss->n_fields - 1); - while (pad_bytes > 0) { + int last_field = (m_num_fields - 1); + while(pad_bytes > 0) { // Find a field to allocate int field_to_allocate = -1; - for (i = last_field; i >= clss->n_static_fields; i--) { + for(i = last_field; i >= get_number_of_static_fields(); i--) { Field* field = field_ptrs[i]; - if (!field->is_static() && !field->is_offset_computed()) { - sz = sizeof_field_type(field, do_field_compaction, clss); - if (sz > pad_bytes) { - break; // field is too big + if(!field->is_static() && !field->is_offset_computed()) { + sz = sizeof_field_type(field, do_field_compaction); + if(sz > pad_bytes) { + break; // field is too big } field_to_allocate = i; break; @@ -247,15 +234,16 @@ void assign_offsets_to_instance_fields(C } // Now allocate that field, if one was found if (field_to_allocate == -1) { - // No field could be found to fill in. "pad_bytes" is the number of padding bytes to insert. - clss->unpadded_instance_data_size += pad_bytes; - clss->num_field_padding_bytes += pad_bytes; + // No field could be found to fill in. + // "pad_bytes" is the number of padding bytes to insert. + m_unpadded_instance_data_size += pad_bytes; + m_num_field_padding_bytes += pad_bytes; break; } else { last_field = (i - 1); Field* victim_field = field_ptrs[field_to_allocate]; - assign_instance_field_offset(clss, victim_field, do_field_compaction); - delta = (clss->unpadded_instance_data_size % 4); + assign_offset_to_instance_field(victim_field, do_field_compaction); + delta = (m_unpadded_instance_data_size % 4); pad_bytes = ((delta > 0)? (4 - delta) : 0); } } @@ -263,23 +251,23 @@ void assign_offsets_to_instance_fields(C } // Place the remaining instance fields. - for (i = clss->n_static_fields; i < clss->n_fields; i++) { - assign_instance_field_offset(clss, field_ptrs[i], do_field_compaction); + for(i = get_number_of_static_fields(); i < m_num_fields; i++) { + assign_offset_to_instance_field(field_ptrs[i], do_field_compaction); } -} //assign_offsets_to_instance_fields +} // Class::assign_offsets_to_instance_fields // "field_ptrs" is an array of pointers to the class's fields. -void assign_offsets_to_static_fields(Class *clss, Field **field_ptrs, bool do_field_compaction) +void Class::assign_offsets_to_static_fields(Field** field_ptrs, bool do_field_compaction) { - for (int i=0; in_static_fields; i++) { + for(int i = 0; i < get_number_of_static_fields(); i++) { Field* field = field_ptrs[i]; assert(field->is_static()); // static (i.e., class) data field // is this needed for interface static constants? int field_size; - field_size = sizeof_field_type(field, do_field_compaction, /*clss*/ NULL); // NULL clss since this is a static field + field_size = sizeof_field_type(field, do_field_compaction); // Align the static field if necessary. #ifdef POINTER64 @@ -287,17 +275,16 @@ void assign_offsets_to_static_fields(Cla #else // not POINTER64 if (field->get_descriptor()->bytes[0] == 'D') { #endif // not POINTER64 - if ((clss->static_data_size%8)!=0) { - clss->static_data_size += 4; - assert((clss->static_data_size%8)==0); + if((m_static_data_size%8)!=0) { + m_static_data_size += 4; + assert((m_static_data_size%8)==0); } } - field->_offset = clss->static_data_size; - field->set_offset_computed(true); - clss->static_data_size += field_size; + field->set_offset(m_static_data_size); + m_static_data_size += field_size; } -} //assign_offsets_to_static_fields +} // Class::assign_offsets_to_static_fields // Return the field's size before any padding: e.g., 1 for a Byte, 2 for a Char. @@ -307,7 +294,7 @@ static int field_size(Field *field, Clas } int sz; - sz = sizeof_field_type(field, /*do_field_compaction*/ true, /*clss*/ NULL); // NULL clss since no padding is wanted + sz = sizeof_field_type(field, /*do_field_compaction*/ true); return sz; } //field_size @@ -358,45 +345,48 @@ static void qsort(Field *A[], int l, int } } //qsort -void assign_offsets_to_class_fields(Class *clss) + +void Class::assign_offsets_to_fields() { - assert(clss->state != ST_InstanceSizeComputed); - bool do_field_compaction = Class::compact_fields; - bool do_field_sorting = Class::sort_fields; + assert(m_state != ST_InstanceSizeComputed); + bool do_field_compaction = VM_Global_State::loader_env->compact_fields; + bool do_field_sorting = VM_Global_State::loader_env->sort_fields; // Create a temporary array of pointers to the class's fields. We do this to support sorting the fields // by size if the command line option "-sort_fields" is given, and because elements of the clss->fields array // cannot be rearranged without copying their entire Field structure. - Field **field_ptrs = new Field*[clss->n_fields]; - for (int i=0; in_fields; i++) { - field_ptrs[i] = &(clss->fields[i]); + Field** field_ptrs = new Field*[m_num_fields]; + for(int i = 0; i < m_num_fields; i++) { + field_ptrs[i] = &m_fields[i]; } - if (clss->state != ST_InstanceSizeComputed) { + assert(m_state < ST_InstanceSizeComputed); + if(m_state != ST_InstanceSizeComputed) { // Sort the instance fields by size before allocating their offsets. But not if doing sequential layout! // Note: we must sort the instance fields separately from the static fields since for some classes the offsets // of statics can only be determined after the offsets of instance fields are found. - if (do_field_sorting && (clss->n_fields > 0)) { - qsort(field_ptrs, clss->n_static_fields, (clss->n_fields - 1), - clss, /*doing_instance_flds:*/ true); + if(do_field_sorting && (m_num_fields > 0)) { + qsort(field_ptrs, m_num_static_fields, + (m_num_fields - 1), this, + /*doing_instance_flds:*/ true); } // We have to assign offsets to a type's instance fields first because // a static field of that type needs the instance size if it's a value type. - assign_offsets_to_instance_fields(clss, field_ptrs, do_field_compaction); + assign_offsets_to_instance_fields(field_ptrs, do_field_compaction); #ifdef DEBUG_FIELD_SORTING if (do_field_sorting) { - printf("\nInstance fields for %s, size=%d\n", clss->name->bytes, clss->unpadded_instance_data_size); - if (clss->super_class != NULL) { - printf(" super_class: %s\n", clss->super_class->name->bytes); + printf("\nInstance fields for %s, size=%d\n", m_name->bytes, m_unpadded_instance_data_size); + if(m_super_class != NULL) { + printf(" super_class: %s\n", m_super_class->get_name()->bytes); } - for (int i=0; in_fields; i++) { - Field *field = field_ptrs[i]; - if (!field->is_static()) { - const String *typeDesc = field->get_descriptor(); - int sz = field_size(field, clss, /*doing_instance_flds:*/ true); - printf(" %40s %c %4d %4d\n", field->get_name()->bytes, typeDesc->bytes[0], sz, field->_offset); + for(int i = 0; i < m_num_fields; i++) { + Field* field = field_ptrs[i]; + if(!field->is_static()) { + const String* typeDesc = field->get_descriptor(); + int sz = field_size(field, this, /*doing_instance_flds:*/ true); + printf(" %40s %c %4d %4d\n", field->get_name()->bytes, typeDesc->bytes[0], sz, field->_offset); fflush(stdout); } } @@ -404,24 +394,24 @@ void assign_offsets_to_class_fields(Clas #endif // DEBUG_FIELD_SORTING // Set class to ST_InstanceSizeComputed state. - clss->state = ST_InstanceSizeComputed; + m_state = ST_InstanceSizeComputed; } // Sort the static fields by size before allocating their offsets. - if (do_field_sorting && (clss->n_static_fields > 0)) { - qsort(field_ptrs, 0, (clss->n_static_fields - 1), - clss, /*doing_instance_flds:*/ false); + if(do_field_sorting && (m_num_static_fields > 0)) { + qsort(field_ptrs, 0, m_num_static_fields - 1, + this, /*doing_instance_flds:*/ false); } - assign_offsets_to_static_fields(clss, field_ptrs, do_field_compaction); + assign_offsets_to_static_fields(field_ptrs, do_field_compaction); #ifdef DEBUG_FIELD_SORTING if (do_field_sorting) { - printf("Static fields for %s, size=%d\n", clss->name->bytes, clss->static_data_size); - for (int i=0; in_fields; i++) { - Field *field = field_ptrs[i]; - if (field->is_static()) { + printf("Static fields for %s, size=%d\n", m_name->bytes, static_data_size); + for(int i = 0; i < m_num_fields; i++) { + Field* field = field_ptrs[i]; + if(field->is_static()) { const String *typeDesc = field->get_descriptor(); - int sz = field_size(field, clss, /*doing_instance_flds:*/ false); + int sz = field_size(field, this, /*doing_instance_flds:*/ false); printf(" %40s %c %4d %4d\n", field->get_name()->bytes, typeDesc->bytes[0], sz, field->_offset); fflush(stdout); } @@ -429,24 +419,25 @@ void assign_offsets_to_class_fields(Clas } #endif // DEBUG_FIELD_SORTING delete[] field_ptrs; -} //assign_offsets_to_class_fields +} // Class::assign_offsets_to_fields // Required for reflection. See class_prepare STEP20 for further explanation. bool assign_values_to_class_static_final_fields(Class *clss) { ASSERT_RAISE_AREA; - bool do_field_compaction = Class::compact_fields; + assert(!hythread_is_suspend_enabled()); + bool do_field_compaction = VM_Global_State::loader_env->compact_fields; - for (int i=0; in_fields; i++) { - Field& field = clss->fields[i]; - if (field.is_static()) { - Java_Type field_type = field.get_java_type(); - void *field_addr = field.get_address(); + for(int i = 0; i < clss->get_number_of_fields(); i++) { + Field* field = clss->get_field(i); + if(field->is_static()) { + Java_Type field_type = field->get_java_type(); + void* field_addr = field->get_address(); // If static field is constant it should be initialized by its constant value,... - if (field.get_const_value_index()) { - Const_Java_Value cvalue = field.get_const_value(); + if(field->get_const_value_index()) { + Const_Java_Value cvalue = field->get_const_value(); switch(field_type) { case '[': case 'L': @@ -463,8 +454,7 @@ bool assign_values_to_class_static_final static const String* jlstring_desc_string = VM_Global_State::loader_env-> string_pool.lookup("Ljava/lang/String;"); - if (field.get_descriptor() == jlstring_desc_string) { - tmn_suspend_disable(); + if (field->get_descriptor() == jlstring_desc_string) { // ------------------------------------------------------------vv Java_java_lang_String *str = vm_instantiate_cp_string_resolved(cvalue.string); @@ -472,19 +462,18 @@ bool assign_values_to_class_static_final assert(exn_raised()); tmn_suspend_enable(); TRACE2("classloader.prepare", "failed instantiate final field : " - << clss->name->bytes << "." << field.get_name()->bytes); + << clss->get_name()->bytes << "." << field->get_name()->bytes); return false; } STORE_GLOBAL_REFERENCE((COMPRESSED_REFERENCE *)field_addr, str); // ------------------------------------------------------------^^ - tmn_suspend_enable(); } else { ABORT("Unexpected type descriptor"); } break; } default: - int field_size = sizeof_field_type(&field, do_field_compaction, /*clss*/ NULL); // NULL clss since field is static + int field_size = sizeof_field_type(field, do_field_compaction); memmove(field_addr, (void*)&cvalue, field_size); } @@ -503,123 +492,73 @@ bool assign_values_to_class_static_final } //assign_values_to_class_static_final_fields -void build_gc_class_ref_map(Global_Env* env, Class *clss) -{ - // Add 1 to the size of the information since it includes a zero delimiter. - // Please note where this get deleted when we unload a class!!!!? - // It should be done by a call to the gc side of the interface. - unsigned *local_gc_information = new unsigned[clss->n_instance_refs + 1]; - unsigned int current_index = 0; - - // Copy the superclasses gc_information into this refs_offset_map incrementing current_index as needed. - if (clss->super_class) { // We might be in initialization. - assert (clss->n_instance_refs >= clss->super_class->n_instance_refs); - - // Ask the GC to fill the local_gc_information with the super class offsets. - current_index = clss->super_class->n_instance_refs; - } else { - assert (current_index == 0); - - //extern bool bootstrapped; - //// gloss over bootstrap inconsistency - //if (bootstrapped == true) { - if(env->InBootstrap()) { - assert(clss->n_instance_refs == 0); - } - } - assert (current_index <= clss->n_instance_refs); - - for (int i = 0; in_fields; i++) { - Field& field = clss->fields[i]; - if (field.is_static()) { - // static (i.e., class) data field - // Since refs_offset only deals with instance fields - // this can be skipped. We don't change current offset for statics. - } else { - // instance data field - // - char c_type = *(field.get_descriptor()->bytes); - if ((c_type == '[') || (c_type == 'L')) { - assert (field.get_offset() != 0); // Only the vtable can have this offset. - local_gc_information[current_index] = field.get_offset(); - current_index = current_index + 1; - } - } - } - assert (current_index == (clss->n_instance_refs)); - local_gc_information[current_index] = 0; - // delimit with 0 since and offsetwill never be zero, that is where the vtable is we are OK. - delete[] local_gc_information; - // gc_information is not created, and populated and zero deliminted. - // Pass this to the GC since it responsible for the format of the - // information saved in clss->gc_information. -} //build_gc_class_ref_map - // // create_intfc_table // Intfc_Table *create_intfc_table(Class* clss, unsigned n_entries) { unsigned size = INTFC_TABLE_OVERHEAD + (n_entries * sizeof(Intfc_Table_Entry)); - Intfc_Table *table = (Intfc_Table*) clss->class_loader->Alloc(size); + Intfc_Table *table = (Intfc_Table*) clss->get_class_loader()->Alloc(size); memset(table,0,size); return table; } -void build_class_interface_table_descriptors(Class *clss) +void Class::build_interface_table_descriptors() { - // Compute the number of methods that are in the interface part of the vtable. Also, create the array of - // interfaces (clss->intfc_table_descriptors[]) this class directly or indirectly implements. Note that - // _n_intfc_table_entries was initialized earlier. This is an upperbound because we eliminate duplicate - // entries in the table below. + // Compute the number of methods that are in the interface part of + // the vtable. Also, create the array of interfaces (intfc_table_descriptors[]) + // this class directly or indirectly implements. Note that + // m_num_intfc_table_entries was initialized earlier. This is an upperbound + // because we eliminate duplicate entries in the table below. unsigned i, k; - for (i = 0; i < clss->n_superinterfaces; i++) { - Class *intfc = clss->superinterfaces[i].clss; - clss->n_intfc_table_entries += intfc->n_intfc_table_entries; + for (i = 0; i < m_num_superinterfaces; i++) { + Class* intfc = get_superinterface(i); + m_num_intfc_table_entries += intfc->m_num_intfc_table_entries; } // allocate the class's intfc_table_descriptors[] array - if (clss->n_intfc_table_entries != 0) { - clss->intfc_table_descriptors = (Class **) clss->class_loader->Alloc(clss->n_intfc_table_entries * sizeof(Class *)); - } else { - clss->intfc_table_descriptors = NULL; + if(m_num_intfc_table_entries != 0) { + m_intfc_table_descriptors = (Class**)m_class_loader + ->Alloc(m_num_intfc_table_entries * sizeof(Class*)); } - for (k = 0; k < clss->n_intfc_table_entries; k++) { - clss->intfc_table_descriptors[k] = NULL; + for(k = 0; k < m_num_intfc_table_entries; k++) { + m_intfc_table_descriptors[k] = NULL; } // fill in intfc_table_descriptors with the descriptors from the superclass and the superinterfaces unsigned intfc_table_entry = 0; - if (clss->super_class != NULL) { - for (unsigned i = 0; i < clss->super_class->n_intfc_table_entries; i++) { - clss->intfc_table_descriptors[intfc_table_entry] = clss->super_class->intfc_table_descriptors[i]; + if(has_super_class()) { + for(unsigned i = 0; i < get_super_class()->m_num_intfc_table_entries; i++) { + m_intfc_table_descriptors[intfc_table_entry] = + get_super_class()->m_intfc_table_descriptors[i]; intfc_table_entry++; } } - for (k = 0; k < clss->n_superinterfaces; k++) { - Class *intfc = clss->superinterfaces[k].clss; - for (i = 0; i < intfc->n_intfc_table_entries; i++) { - clss->intfc_table_descriptors[intfc_table_entry] = intfc->intfc_table_descriptors[i]; + for(k = 0; k < m_num_superinterfaces; k++) { + Class* intfc = get_superinterface(k); + for(i = 0; i < intfc->m_num_intfc_table_entries; i++) { + m_intfc_table_descriptors[intfc_table_entry] = + intfc->m_intfc_table_descriptors[i]; intfc_table_entry++; } } // if this class is an interface, add it to the interface table - if (class_is_interface(clss)) { - clss->intfc_table_descriptors[intfc_table_entry] = clss; + if(is_interface()) { + m_intfc_table_descriptors[intfc_table_entry] = this; intfc_table_entry++; } // sort the interfaces in intfc_table_descriptors, eliminating duplicate entries unsigned last_min_id = 0; - for (i = 0; i < clss->n_intfc_table_entries; i++) { + for (i = 0; i < m_num_intfc_table_entries; i++) { // // select the next interface C with smallest id and insert // into i'th position; delete entry of C if C is the same // as i-1'th entry // - Class *intfc = clss->intfc_table_descriptors[i]; - unsigned min_index = i; // index of intfc with min id - unsigned min_id = intfc->id; // id of intfc with min id - for (unsigned k = i+1; k < clss->n_intfc_table_entries; k++) { - unsigned id = clss->intfc_table_descriptors[k]->id; + Class* intfc = m_intfc_table_descriptors[i]; + unsigned min_index = i; // index of intfc with min id + unsigned min_id = intfc->get_id(); // id of intfc with min id + for(unsigned k = i + 1; k < m_num_intfc_table_entries; k++) { + unsigned id = m_intfc_table_descriptors[k]->get_id(); if (id < min_id) { // new min min_index = k; @@ -627,23 +566,25 @@ void build_class_interface_table_descrip continue; } } - // if the id of the min is the same as the i-1'th entry's id, then we have a duplicate - if (min_id == last_min_id) { - // duplicate found -- insert the last entry in place of the duplicate's entry - clss->intfc_table_descriptors[min_index] = clss->intfc_table_descriptors[clss->n_intfc_table_entries-1]; - clss->n_intfc_table_entries--; + // if the id of the min is the same as the i-1'th entry's id, + // then we have a duplicate + if(min_id == last_min_id) { + // duplicate found - insert the last entry in place of the duplicate's entry + m_intfc_table_descriptors[min_index] = + m_intfc_table_descriptors[m_num_intfc_table_entries-1]; + m_num_intfc_table_entries--; continue; } last_min_id = min_id; - if (min_index == i) { + if(min_index == i) { continue; } // swap i'th entry with min entry - Class *min_intfc = clss->intfc_table_descriptors[min_index]; - clss->intfc_table_descriptors[min_index] = clss->intfc_table_descriptors[i]; - clss->intfc_table_descriptors[i] = min_intfc; + Class* min_intfc = m_intfc_table_descriptors[min_index]; + m_intfc_table_descriptors[min_index] = m_intfc_table_descriptors[i]; + m_intfc_table_descriptors[i] = min_intfc; } -} //build_class_interface_table_descriptors +} // Class::build_interface_table_descriptors // Returns the method matching the Signature "sig" that is implemented directly or indirectly by "clss", or NULL if not found. @@ -651,8 +592,8 @@ Method *find_method_impl_by_class(Class { assert(clss); Method *m = NULL; - for(; ((clss != NULL) && (m == NULL)); clss = clss->super_class) { - m = class_lookup_method(clss, name, desc); + for(; ((clss != NULL) && (m == NULL)); clss = clss->get_super_class()) { + m = clss->lookup_method(name, desc); } return m; } //find_method_impl_by_class @@ -660,25 +601,25 @@ Method *find_method_impl_by_class(Class // Add the new fake methods to class. void inline add_new_fake_method( Class *clss, Class *example, unsigned *next) { - for (unsigned i = 0; i < clss->n_superinterfaces; i++) { - Class *intf_clss = clss->superinterfaces[i].clss; + for (unsigned i = 0; i < clss->get_number_of_superinterfaces(); i++) { + Class *intf_clss = clss->get_superinterface(i); add_new_fake_method(intf_clss, example, next); - for (unsigned k = 0; k < intf_clss->n_methods; k++) { - Method &intf_method = intf_clss->methods[k]; - if (intf_method.is_clinit()) { + for(unsigned k = 0; k < intf_clss->get_number_of_methods(); k++) { + Method* intf_method = intf_clss->get_method(k); + if(intf_method->is_clinit()) { continue; } // See if the interface method "intf_method" is implemented by clss. - const String* intf_name = intf_method.get_name(); - const String* intf_desc = intf_method.get_descriptor(); - Method *impl_method = find_method_impl_by_class(example, intf_name, intf_desc); + const String* intf_name = intf_method->get_name(); + const String* intf_desc = intf_method->get_descriptor(); + Method* impl_method = find_method_impl_by_class(example, intf_name, intf_desc); if (impl_method == NULL) { #ifdef DEBUG_FAKE_METHOD_ADDITION printf("** Adding fake method to class %s for unimplemented method %s of interface %s.\n", example->name->bytes, intf_name->bytes, intf_clss->name->bytes); #endif - Method *fake_method = &(example->methods[(*next)]); + Method* fake_method = example->get_method(*next); (*next)++; fake_method->_class = example; @@ -688,7 +629,7 @@ void inline add_new_fake_method( Class * fake_method->_state = Method::ST_NotCompiled; fake_method->_access_flags = (ACC_PUBLIC | ACC_ABSTRACT); // Setting its "_intf_method_for_fake_method" field marks the method as being fake. - fake_method->_intf_method_for_fake_method = &intf_method; + fake_method->_intf_method_for_fake_method = intf_method; // The rest of the method's fields were zero'd above } } @@ -701,17 +642,17 @@ void inline add_new_fake_method( Class * unsigned inline count_fake_interface_method( Class *clss, Class *example ) { unsigned count = 0; - for (unsigned i = 0; i < clss->n_superinterfaces; i++) { - Class *intf_clss = clss->superinterfaces[i].clss; + for (unsigned i = 0; i < clss->get_number_of_superinterfaces(); i++) { + Class *intf_clss = clss->get_superinterface(i); count += count_fake_interface_method(intf_clss, example); - for (unsigned k = 0; k < intf_clss->n_methods; k++) { - Method &intf_method = intf_clss->methods[k]; - if (intf_method.is_clinit()) { + for(unsigned k = 0; k < intf_clss->get_number_of_methods(); k++) { + Method* intf_method = intf_clss->get_method(k); + if(intf_method->is_clinit()) { continue; } // See if the interface method "intf_method" is implemented by clss. - const String *intf_name = intf_method.get_name(); - const String *intf_desc = intf_method.get_descriptor(); + const String *intf_name = intf_method->get_name(); + const String *intf_desc = intf_method->get_descriptor(); Method *impl_method = find_method_impl_by_class(example, intf_name, intf_desc); if (impl_method == NULL) { count++; @@ -721,16 +662,13 @@ unsigned inline count_fake_interface_met return count; } // count_fake_interface_method -// Add any required "fake" methods to a class. These are interface methods inherited by an abstract class that -// are not implemented by that class or any superclass. Such methods will never be called, but they are added -// so they have the correct offset in the virtual method part of the vtable (i.e., the offset of the "real" method -// in the vtable for a concrete class). -void add_any_fake_methods(Class *clss) + +void Class::add_any_fake_methods() { - assert(class_is_abstract(clss)); + assert(is_abstract()); // First, count the fake methods. These are the interface methods that are not implemented by the class. - unsigned num_fake_methods = count_fake_interface_method(clss, clss); + unsigned num_fake_methods = count_fake_interface_method(this, this); // If no fake methods are needed, just return. if (num_fake_methods == 0) { @@ -741,119 +679,118 @@ void add_any_fake_methods(Class *clss) #ifdef DEBUG_FAKE_METHOD_ADDITION printf("\n** %u fake methods needed for class %s \n", num_fake_methods, clss->name->bytes); #endif - unsigned new_num_methods = (clss->n_methods + num_fake_methods); - Method *new_meth_array = new Method[new_num_methods]; - if (clss->methods != NULL) { - memcpy(new_meth_array, clss->methods, (clss->n_methods * sizeof(Method))); + unsigned new_num_methods = (m_num_methods + num_fake_methods); + Method* new_meth_array = new Method[new_num_methods]; + if(m_methods != NULL) { + memcpy(new_meth_array, m_methods, (m_num_methods * sizeof(Method))); } - unsigned next_fake_method_idx = clss->n_methods; + unsigned next_fake_method_idx = m_num_methods; memset(&(new_meth_array[next_fake_method_idx]), 0, (num_fake_methods * sizeof(Method))); - // Regenerate the existing compile-me/delegate/unboxer stubs and redirect the class's static_initializer and default_constructor fields - // since they refer to the old method block. We regenerate the stubs because any code to update the addresses in - // the existing stubs would be very fragile, fake methods very rarely need to be added, and the stubs are small. - for (unsigned i = 0; i < clss->n_methods; i++) { // Note that this is still the old number of methods. - Method *m = &clss->methods[i]; - Method *m_copy = &new_meth_array[i]; - if (m_copy->get_method_sig()) { + // Regenerate the existing compile-me/delegate/unboxer stubs and redirect + // the class's static_initializer and default_constructor fields since + // they refer to the old method block. We regenerate the stubs + // because any code to update the addresses in the existing stubs would be + // very fragile, fake methods very rarely need to be added, and the stubs + // are small. + // Note that this is still the old number of methods. + for(unsigned i = 0; i < m_num_methods; i++) { + Method* m = &m_methods[i]; + Method* m_copy = &new_meth_array[i]; + if(m_copy->get_method_sig()) + { m_copy->get_method_sig()->method = m_copy; } - if (m->is_clinit()) { - clss->static_initializer = m_copy; + if(m->is_clinit()) + { + m_static_initializer = m_copy; } - if (m->get_name() == VM_Global_State::loader_env->Init_String && m->get_descriptor() == VM_Global_State::loader_env->VoidVoidDescriptor_String) { - clss->default_constructor = m_copy; + if(m->get_name() == VM_Global_State::loader_env->Init_String + && m->get_descriptor() == VM_Global_State::loader_env->VoidVoidDescriptor_String) + { + m_default_constructor = m_copy; } } // Free the old storage area for the class's methods, and have the class point to the new method storage area. - if (clss->methods != NULL) { - delete [] clss->methods; + if(m_methods != NULL) { + delete[] m_methods; } - clss->methods = new_meth_array; + m_methods = new_meth_array; + m_num_methods = (uint16)new_num_methods; // Add the new fake methods. - add_new_fake_method( clss, clss, &next_fake_method_idx ); + add_new_fake_method( this, this, &next_fake_method_idx ); // some methods could be counted several times as "fake" methods (count_fake_interface_method()) // however they are added only once. So we adjust the number of added methods. assert(next_fake_method_idx <= new_num_methods); - clss->n_methods = (uint16)next_fake_method_idx; + m_num_methods = (uint16)next_fake_method_idx; } //add_any_fake_methods -void assign_offsets_to_class_methods(Class *clss) + +void Class::assign_offsets_to_methods(Global_Env* env) { - // At this point we have an array of the interfaces implemented by this class. We also know the number of - // methods in the interface part of the vtable. We now need to find the number of virtual methods that are in - // the virtual method part of the vtable, before we can allocate _vtable and _vtable_descriptors. - - // First, if the class is abstract, add any required "fake" methods: these are abstract methods inherited - // by an abstract class that are not implemented by that class or any superclass. - if (class_is_abstract(clss) && !class_is_interface(clss)) { - add_any_fake_methods(clss); + // At this point we have an array of the interfaces implemented by + // this class. We also know the number of methods in the interface part + // of the vtable. We now need to find the number of virtual methods + // that are in the virtual method part of the vtable, before we can + // allocate _vtable and _vtable_descriptors. + + // First, if the class is abstract, add any required "fake" methods: + // these are abstract methods inherited by an abstract class that are + // not implemented by that class or any superclass. + if(is_abstract() && !is_interface()) { + add_any_fake_methods(); } - Method **super_vtable_descriptors = NULL; + Method** super_vtable_descriptors = NULL; unsigned n_super_virtual_method_entries = 0; - if (clss->super_class != NULL) { - super_vtable_descriptors = clss->super_class->vtable_descriptors; - n_super_virtual_method_entries = clss->super_class->n_virtual_method_entries; + if(has_super_class()) { + super_vtable_descriptors = get_super_class()->m_vtable_descriptors; + n_super_virtual_method_entries = + get_super_class()->m_num_virtual_method_entries; } // Offset of the next entry in the vtable to use. #ifdef POINTER64 - unsigned next_vtable_offset = clss->n_virtual_method_entries << 3; + unsigned next_vtable_offset = m_num_virtual_method_entries << 3; #else - unsigned next_vtable_offset = clss->n_virtual_method_entries << 2; + unsigned next_vtable_offset = m_num_virtual_method_entries << 2; #endif - if (!class_is_interface(clss)) { + if(!is_interface()) { // Classes have an additional overhead for the class pointer and interface table. next_vtable_offset += VTABLE_OVERHEAD; } unsigned i, j; - for (i = 0; i < clss->n_methods; i++) { - Method& method = clss->methods[i]; + for(i = 0; i < m_num_methods; i++) { + Method& method = m_methods[i]; // check if the method hasn't already been initialized or even compiled assert(method.get_code_addr() == NULL); // initialize method's code address method.set_code_addr((char*)compile_gen_compile_me(&method)); - if (method.is_static()) { - // A static method - if (method.is_clinit()) { - method._offset = 0; - method._index = 0; - } else { - // the class better not be an interface! - // To do : make sure this is not an interface - assert(!class_is_interface(clss)); - method._offset = clss->static_method_size; -#ifdef POINTER64 - clss->static_method_size += 8; -#else - clss->static_method_size += 4; -#endif - } - } else { - // A virtual method. Look it up in virtual method tables of the super classes; if not found, then assign a new offset. - + if(!method.is_static()) { + // A virtual method. Look it up in virtual method tables of the + // super classes; if not found, then assign a new offset. + // Ignore initializers. if (method.is_init()) { continue; } -#ifdef REMOVE_FINALIZE_FROM_VTABLES - // skip over finalize() method, but remember it if (method.is_finalize()) { - clss->finalize_method = &method; + if(get_name() != env->JavaLangObject_String) { + m_has_finalizer = 1; + } +#ifdef REMOVE_FINALIZE_FROM_VTABLES + // skip over finalize() method, but remember it + finalize_method = &method; continue; - } #endif + } unsigned off = 0; unsigned index = 0; if (super_vtable_descriptors != NULL) { - bool same_runtime_package_as_super = - (clss->package == clss->super_class->package); - const String *name = method.get_name(); const String *desc = method.get_descriptor(); for (j = 0; j < n_super_virtual_method_entries; j++) { @@ -862,7 +799,7 @@ void assign_offsets_to_class_methods(Cla if(m->is_final()) { if(m->is_private() || (m->is_package_private() - && m->get_class()->package != method.get_class()->package)) + && m->get_class()->get_package() != method.get_class()->get_package())) { // We allow to override private final and // default (package private) final methods @@ -871,17 +808,17 @@ void assign_offsets_to_class_methods(Cla // Note: for package private methods this statement // is true only for classes from different packages } else { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, + REPORT_FAILED_CLASS_CLASS(get_class_loader(), this, "java/lang/VerifyError", "An attempt is made to override final method " - << m->get_class()->name->bytes << "." + << m->get_class()->get_name()->bytes << "." << m->get_name()->bytes << m->get_descriptor()->bytes); return; } } // method doesn't override m if method has package access // and is in a different runtime package than m. - if(same_runtime_package_as_super + if(m_package == m->get_class()->get_package() || m->is_public() || m->is_protected() || m->is_private()) @@ -898,130 +835,126 @@ void assign_offsets_to_class_methods(Cla } } } - if (off == 0 || class_is_interface(clss)) { - // Didn't find a matching signature in any super class; add a new entry to this class' vtable. - off = next_vtable_offset; - index = clss->n_virtual_method_entries; + if (off == 0 || is_interface()) { + // Didn't find a matching signature in any super class; + // add a new entry to this class' vtable. + off = next_vtable_offset; + index = m_num_virtual_method_entries; #ifdef POINTER64 - next_vtable_offset += 8; + next_vtable_offset += 8; #else - next_vtable_offset += 4; + next_vtable_offset += 4; #endif - clss->n_virtual_method_entries++; + m_num_virtual_method_entries++; } - method._offset = off; - method._index = index; + method.set_position_in_vtable(index, off); } } // Figure out which methods don't do anything - for (i = 0; i < clss->n_methods; i++) { - Method& method = clss->methods[i]; - method._set_nop(); - } + // ppervov: suspending this check, as it only detects empty constructors + //for (i = 0; i < n_methods; i++) { + // Method& method = methods[i]; + // method._set_nop(); + //} // Decide whether it is possible to allocate instances of this class using a fast inline sequence containing // no calls to other routines. This means no calls to raise exceptions or to invoke constructors. It will also be // necessary that the allocation itself can be done without needing to call a separate function. bool is_not_instantiable = ( // if true, will raise java_lang_InstantiationException - (clss->default_constructor == NULL) || - (clss->is_primitive || clss->is_array || class_is_interface(clss) || class_is_abstract(clss)) || - (clss == VM_Global_State::loader_env->Void_Class)); - if (!is_not_instantiable && clss->default_constructor->is_nop()) { - clss->is_fast_allocation_possible = TRUE; + (m_default_constructor == NULL) + || (is_primitive() || is_array() || is_interface() || is_abstract()) + || (this == VM_Global_State::loader_env->Void_Class)); + if(!is_not_instantiable && m_default_constructor->is_nop()) { + m_is_fast_allocation_possible = 1; } -} //assign_offsets_to_class_methods +} // Class::assign_offsets_to_methods -bool initialize_static_fields_for_interface(Class *clss) +bool Class::initialize_static_fields_for_interface() { ASSERT_RAISE_AREA; tmn_suspend_disable(); + m_state = ST_Prepared; // Initialize static fields - clss->state = ST_Prepared; - unsigned i; - for (i=0; in_fields; i++) { - Field& field = clss->fields[i]; - if (field.is_static() && field.get_const_value_index()) { - char *field_addr = ((char *)clss->static_data_block) + field.get_offset(); - Const_Java_Value field_const_value = field.get_const_value(); - switch(field.get_java_type()) { - case JAVA_TYPE_INT: - *((int32 *)field_addr) = field_const_value.i; - break; - case JAVA_TYPE_SHORT: - case JAVA_TYPE_CHAR: - *((int16 *)field_addr) = (int16)field_const_value.i; - break; - case JAVA_TYPE_BYTE: - case JAVA_TYPE_BOOLEAN: - *((int8 *)field_addr) = (int8)field_const_value.i; - break; - case JAVA_TYPE_LONG: - *(((int32 *)field_addr)) = field_const_value.l.lo_bytes; - *(((int32 *)field_addr) + 1) = field_const_value.l.hi_bytes; - break; - case JAVA_TYPE_DOUBLE: - *(((int32 *)field_addr)) = field_const_value.l.lo_bytes; - *(((int32 *)field_addr) + 1) = field_const_value.l.hi_bytes; - break; - case JAVA_TYPE_FLOAT: - *((float *)field_addr) = field_const_value.f; - break; - case JAVA_TYPE_CLASS: - { - // compress static reference fields. - // It must be a String - assert(strcmp(field.get_descriptor()->bytes, "Ljava/lang/String;") == 0); - Java_java_lang_String *str - = vm_instantiate_cp_string_resolved(field_const_value.string); - - if (!str) { - assert(exn_raised()); - tmn_suspend_enable(); - TRACE2("classloader.prepare", "failed instantiate final field : " - << clss->name->bytes << "." << field.get_name()->bytes); - return false; - } - STORE_GLOBAL_REFERENCE((COMPRESSED_REFERENCE *)field_addr, str); - break; - } - default: - // This should never happen. - ABORT("Unexpected java type"); - break; - } - } + if(!assign_values_to_class_static_final_fields(this)) { + tmn_suspend_enable(); + return false; } - clss->n_virtual_method_entries = 0; // interfaces don't have vtables - for (i=0; in_methods; i++) { - Method *method = &clss->methods[i]; - if (method->is_clinit()) { - assert(clss->static_initializer == method); + tmn_suspend_enable(); + +#ifndef NDEBUG + for(uint16 i = 0; i < m_num_methods; i++) { + if(m_methods[i].is_clinit()) { + assert(m_static_initializer == &(m_methods[i])); } } - tmn_suspend_enable(); - TRACE2("classloader.prepare", "interface " << clss->name->bytes << " prepared"); - class_initialize_if_no_side_effects(clss); +#endif + TRACE2("classloader.prepare", "interface " << m_name->bytes << " prepared"); return true; -} //initialize_static_fields_for_interface +} // Class::initialize_static_fields_for_interface + + +void Class::create_vtable(unsigned n_vtable_entries) +{ + unsigned vtable_size = VTABLE_OVERHEAD + n_vtable_entries * sizeof(void *); + + // Always allocate vtable data from vtable_data_pool + void* p_gc_hdr = allocate_vtable_data_from_pool(vtable_size); + +#ifdef VM_STATS + // For allocation statistics, include any rounding added to make each + // item aligned (current alignment is to the next 16 byte boundary). + unsigned num_bytes = (vtable_size + 15) & ~15; + // 20020923 Total number of allocations and total number of + // bytes for class-related data structures. + VM_Statistics::get_vm_stats().num_vtable_allocations++; + VM_Statistics::get_vm_stats().total_vtable_bytes += num_bytes; +#endif + assert(p_gc_hdr); + memset(p_gc_hdr, 0, vtable_size); + + VTable* vtable = (VTable*)p_gc_hdr; + + if(has_super_class()) { + m_depth = get_super_class()->m_depth + 1; + memcpy(&vtable->superclasses, + &get_super_class()->m_vtable->superclasses, + sizeof(vtable->superclasses)); + for(int i = 0; i < vm_max_fast_instanceof_depth(); i++) { + if(vtable->superclasses[i] == NULL) { + vtable->superclasses[i] = this; + break; + } + } + } + if(m_depth > 0 + && m_depth < vm_max_fast_instanceof_depth() + && !is_array() + && !is_interface()) + { + m_is_suitable_for_fast_instanceof = 1; + } + m_vtable = vtable; +} // Class::create_vtable -void populate_vtable_descriptors_table_and_override_methods(Class *clss) +void Class::populate_vtable_descriptors_table_and_override_methods() { - // Populate _vtable_descriptors first with _n_virtual_method_entries from super class - if (clss->super_class != NULL) { - for (unsigned i = 0; i < clss->super_class->n_virtual_method_entries; i++) { - clss->vtable_descriptors[i] = clss->super_class->vtable_descriptors[i]; + // Populate _vtable_descriptors first with _n_virtual_method_entries + // from super class + if(has_super_class()) { + for(unsigned i = 0; i < get_super_class()->m_num_virtual_method_entries; i++) { + m_vtable_descriptors[i] = get_super_class()->m_vtable_descriptors[i]; } } // NOW OVERRIDE with this class' methods unsigned i; - for (i = 0; i < clss->n_methods; i++) { - Method *method = &clss->methods[i]; - if (method->is_clinit()) { - assert(clss->static_initializer == method); + for(i = 0; i < m_num_methods; i++) { + Method* method = &(m_methods[i]); + if(method->is_clinit()) { + assert(m_static_initializer == method); } if(method->is_static() || method->is_init() @@ -1030,60 +963,61 @@ void populate_vtable_descriptors_table_a #endif ) continue; - clss->vtable_descriptors[method->get_index()] = method; + m_vtable_descriptors[method->get_index()] = method; } // finally, the interface methods - unsigned index = clss->n_virtual_method_entries; - for (i = 0; i < clss->n_intfc_table_entries; i++) { - Class *intfc = clss->intfc_table_descriptors[i]; - for (unsigned k = 0; k < intfc->n_methods; k++) { - if (intfc->methods[k].is_clinit()) { + unsigned index = m_num_virtual_method_entries; + for(i = 0; i < m_num_intfc_table_entries; i++) { + Class* intfc = m_intfc_table_descriptors[i]; + for(unsigned k = 0; k < intfc->get_number_of_methods(); k++) { + if(intfc->get_method(k)->is_clinit()) { continue; } // Find method with matching signature and replace - const String *sig_name = intfc->methods[k].get_name(); - const String *sig_desc = intfc->methods[k].get_descriptor(); - Method *method = NULL; - for (unsigned j = 0; j < clss->n_virtual_method_entries; j++) { - if (clss->vtable_descriptors[j]->get_name() == sig_name && clss->vtable_descriptors[j]->get_descriptor() == sig_desc) { - method = clss->vtable_descriptors[j]; + const String* sig_name = intfc->get_method(k)->get_name(); + const String* sig_desc = intfc->get_method(k)->get_descriptor(); + Method* method = NULL; + for(unsigned j = 0; j < m_num_virtual_method_entries; j++) { + if(m_vtable_descriptors[j]->get_name() == sig_name + && m_vtable_descriptors[j]->get_descriptor() == sig_desc) + { + method = m_vtable_descriptors[j]; break; // a match! } - } - if (method == NULL && !class_is_abstract(clss)) { - // wgs: I think we should comment out this assert, because there're many cases VM/Classpath - // will run apps built on previous JDK version, and without implementations of newly added methods + if(method == NULL && !is_abstract()) { + // There're many cases VM will run apps built on previous JDK + // version, and without implementations of newly added methods // for specific interfaces, we allow them to continue to run - TRACE2("classloader.prepare", "No implementation in class " << clss->name->bytes - << " for method " << sig_name->bytes << " of interface " << intfc->name->bytes + TRACE2("classloader.prepare", "No implementation in class " + << get_name()->bytes << " for method " + << sig_name->bytes << " of interface " + << intfc->get_name()->bytes << ". \n\nCheck whether you used another set of class library.\n"); } - clss->vtable_descriptors[index] = method; + m_vtable_descriptors[index] = method; index++; } } -} //populate_vtable_descriptors_table_and_override_methods +} // Class::populate_vtable_descriptors_table_and_override_methods -void point_class_vtable_entries_to_stubs(Class *clss) +void Class::point_vtable_entries_to_stubs() { - - for (unsigned i = 0; i < clss->n_virtual_method_entries; i++) { - assert(clss->vtable_descriptors[i]); - Method& method = *(clss->vtable_descriptors[i]); - assert(!method.is_static()); - //if (!method.is_static() && !is_ignored_method) { - if(!method.is_static()) { - unsigned meth_idx = method.get_index(); - // 2003-03-17: Make this assert independent of POINTER64. There are already several - // assumptions in the code that the width of each method pointer is the same as void* . - assert((method.get_offset() - VTABLE_OVERHEAD) / sizeof(void *) == method.get_index()); - clss->vtable->methods[meth_idx] = - (unsigned char *)method.get_code_addr(); - method.add_vtable_patch(&(clss->vtable->methods[meth_idx])); - assert(method.is_fake_method() || interpreter_enabled() || method.get_code_addr()); + for (unsigned i = 0; i < m_num_virtual_method_entries; i++) { + assert(m_vtable_descriptors[i]); + Method* method = m_vtable_descriptors[i]; + assert(!method->is_static()); + if(!method->is_static()) { + unsigned meth_idx = method->get_index(); + // There are several assumptions in the code that the width + // of each method pointer is the same as void*. + assert((method->get_offset() - VTABLE_OVERHEAD)/sizeof(void*) == method->get_index()); + m_vtable->methods[meth_idx] = + (unsigned char*)method->get_code_addr(); + method->add_vtable_patch(&(m_vtable->methods[meth_idx])); + assert(method->is_fake_method() || interpreter_enabled() || method->get_code_addr()); } } } @@ -1093,9 +1027,9 @@ extern bool dump_stubs; // It's a rutime helper. So should be named as rth_prepare_throw_abstract_method_error void prepare_throw_abstract_method_error(Class_Handle clss, Method_Handle method) { - char* buf = (char*)STD_ALLOCA(clss->name->len + method->get_name()->len + char* buf = (char*)STD_ALLOCA(clss->get_name()->len + method->get_name()->len + method->get_descriptor()->len + 2); // . + \0 - sprintf(buf, "%s.%s%s", clss->name->bytes, + sprintf(buf, "%s.%s%s", clss->get_name()->bytes, method->get_name()->bytes, method->get_descriptor()->bytes); tmn_suspend_enable(); @@ -1130,11 +1064,11 @@ NativeCodePtr prepare_gen_throw_abstract // It's a rutime helper. So should be named as rth_prepare_throw_illegal_access_error void prepare_throw_illegal_access_error(Class_Handle to, Method_Handle from) { - char* buf = (char*)STD_ALLOCA(from->get_class()->name->len - + to->name->len + from->get_name()->len + char* buf = (char*)STD_ALLOCA(from->get_class()->get_name()->len + + to->get_name()->len + from->get_name()->len + from->get_descriptor()->len + 12); // from + to + . + \0 - sprintf(buf, "from %s to %s.%s%s", from->get_class()->name->bytes, - to->name->bytes, + sprintf(buf, "from %s to %s.%s%s", from->get_class()->get_name()->bytes, + to->get_name()->bytes, from->get_name()->bytes, from->get_descriptor()->bytes); tmn_suspend_enable(); @@ -1166,48 +1100,49 @@ NativeCodePtr prepare_gen_throw_illegal_ return addr; } -Intfc_Table *create_populate_class_interface_table(Class *clss) +Intfc_Table* Class::create_and_populate_interface_table() { - Intfc_Table *intfc_table; - if (clss->n_intfc_table_entries != 0) { - unsigned vtable_offset = clss->n_virtual_method_entries; + Intfc_Table* intfc_table; + if(m_num_intfc_table_entries != 0) { + unsigned vtable_offset = m_num_virtual_method_entries; // shouldn't it be called vtable_index? - intfc_table = create_intfc_table(clss, clss->n_intfc_table_entries); + intfc_table = create_intfc_table(this, m_num_intfc_table_entries); unsigned i; - for (i = 0; i < clss->n_intfc_table_entries; i++) { - Class *intfc = clss->intfc_table_descriptors[i]; - intfc_table->entry[i].intfc_id = intfc->id; - intfc_table->entry[i].table = &clss->vtable->methods[vtable_offset]; - vtable_offset += intfc->n_methods; - if(intfc->static_initializer) { + for (i = 0; i < m_num_intfc_table_entries; i++) { + Class* intfc = m_intfc_table_descriptors[i]; + intfc_table->entry[i].intfc_id = intfc->get_id(); + intfc_table->entry[i].table = &m_vtable->methods[vtable_offset]; + vtable_offset += intfc->get_number_of_methods(); + if(intfc->m_static_initializer) { // Don't count static initializers of interfaces. vtable_offset--; } } // Set the vtable entries to point to the code address. - unsigned meth_idx = clss->n_virtual_method_entries; - for (i = 0; i < clss->n_intfc_table_entries; i++) { - Class *intfc = clss->intfc_table_descriptors[i]; - for (unsigned k = 0; k < intfc->n_methods; k++) { - if (intfc->methods[k].is_clinit()) { + unsigned meth_idx = m_num_virtual_method_entries; + for (i = 0; i < m_num_intfc_table_entries; i++) { + Class* intfc = m_intfc_table_descriptors[i]; + for(unsigned k = 0; k < intfc->get_number_of_methods(); k++) { + if (intfc->get_method(k)->is_clinit()) { continue; } - Method *method = clss->vtable_descriptors[meth_idx]; + Method* method = m_vtable_descriptors[meth_idx]; if(method == NULL || method->is_abstract()) { TRACE2("classloader.prepare.ame", "Inserting Throw_AbstractMethodError stub for method\n\t" - << clss->name->bytes << "." - << intfc->methods[k].get_name()->bytes << intfc->methods[k].get_descriptor()->bytes); - clss->vtable->methods[meth_idx] = - (unsigned char*)prepare_gen_throw_abstract_method_error(clss, &intfc->methods[k]); + << m_name->bytes << "." + << intfc->get_method(k)->get_name()->bytes + << intfc->get_method(k)->get_descriptor()->bytes); + m_vtable->methods[meth_idx] = + (unsigned char*)prepare_gen_throw_abstract_method_error(this, intfc->get_method(k)); } else if(method->is_public()) { - clss->vtable->methods[meth_idx] = + m_vtable->methods[meth_idx] = (unsigned char *)method->get_code_addr(); - method->add_vtable_patch(&(clss->vtable->methods[meth_idx])); + method->add_vtable_patch(&(m_vtable->methods[meth_idx])); } else { TRACE2("classloader.prepare.iae", "Inserting Throw_IllegalAccessError stub for method\n\t" - << method->get_class()->name->bytes << "." + << method->get_class()->get_name()->bytes << "." << method->get_name()->bytes << method->get_descriptor()->bytes); - clss->vtable->methods[meth_idx] = + m_vtable->methods[meth_idx] = (unsigned char*)prepare_gen_throw_illegal_access_error(intfc, method); } meth_idx++; @@ -1217,498 +1152,375 @@ Intfc_Table *create_populate_class_inter intfc_table = NULL; } return intfc_table; -} //create_populate_class_interface_table - - -void initialize_interface_class_data(Class *clss) -{ - // this is an interface - clss->instance_data_size = 0; // no instance data - clss->unpadded_instance_data_size = 0; - clss->allocated_size = 0; - clss->n_instance_refs = 0; - clss->n_virtual_method_entries = 0; // thus no virtual method entries - clss->n_intfc_table_entries = 1; // need table entry for this interface -} //initialize_interface_class_data - - -void initialize_java_lang_object_class(Class *clss) -{ - // java.lang.Object -- Java ROOT. - clss->instance_data_size = 0; // set below use the unpadded_instace_data_size. - clss->allocated_size = 0; // set below. - clss->unpadded_instance_data_size = /*sizeof(ManagedObject)*/(unsigned)ManagedObject::get_size(); - clss->n_instance_refs = 0; - clss->n_virtual_method_entries = clss->n_intfc_table_entries = 0; -} //initialize_java_lang_object_class - - -static void initialize_regular_class_data(Global_Env* env, Class *clss) -{ - clss->instance_data_size = 0; // set below. - clss->allocated_size = 0; // set below. - // Roll over instance size, instance refs, static fields #, and num_field_padding_bytes from the super class. - clss->unpadded_instance_data_size = clss->super_class->unpadded_instance_data_size; - if (clss->name == env->JavaLangClass_String) { - clss->unpadded_instance_data_size = - ( (/*sizeof(ManagedObject)*/(unsigned)ManagedObject::get_size() + (GC_OBJECT_ALIGNMENT - 1)) / GC_OBJECT_ALIGNMENT) * GC_OBJECT_ALIGNMENT; - } - clss->n_instance_refs = clss->super_class->n_instance_refs; - clss->num_field_padding_bytes = clss->super_class->num_field_padding_bytes; - // Roll over all virtual methods and interface methods of super class. - clss->n_virtual_method_entries = clss->super_class->n_virtual_method_entries; - clss->n_intfc_table_entries = clss->super_class->n_intfc_table_entries; -} //initialize_regular_class_data +} // Class::create_and_populate_interface_table -// -// prepares a class: -// (1) assign offsets -// - offset of instance data fields -// - virtual methods in vtable -// - static data fields in static data block -// - static methods in static method block -// -// (2) create class vtable -// (3) create static field block -// (4) create static method block -// -// -// - -bool class_prepare(Global_Env* env, Class *clss) +bool Class::prepare(Global_Env* env) { ASSERT_RAISE_AREA; - // fast path - switch(clss->state) - { - case ST_Prepared: - case ST_Initializing: - case ST_Initialized: - case ST_Error: - return true; - default: - break; - } - - LMAutoUnlock autoUnlocker(clss->m_lock); - - // // // STEP 1 ::: SIMPLY RETURN IF already prepared, initialized, or currently initializing. // - // - switch(clss->state) - { - case ST_Prepared: - case ST_Initializing: - case ST_Initialized: - case ST_Error: + if(is_at_least_prepared() || in_error()) // try fast path return true; - default: - break; - } - TRACE2("classloader.prepare", "BEGIN class prepare, class name = " << clss->name->bytes); - assert(clss->is_verified); + LMAutoUnlock autoUnlocker(m_lock); + + if(is_at_least_prepared() || in_error()) // try slow path + return true; + + TRACE2("classloader.prepare", "BEGIN class prepare, class name = " << m_name->bytes); + assert(m_state == ST_BytecodesVerified); - // // // STEP 2 ::: PREPARE SUPER-INTERFACES // - // unsigned i; - for (i=0; in_superinterfaces; i++) { - if(!class_is_interface(clss->superinterfaces[i].clss)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, - "java/lang/IncompatibleClassChangeError", - clss->name->bytes << ": " - << clss->superinterfaces[i].clss->name->bytes << " is not an interface"); - return false; - } - if(!class_prepare(env, clss->superinterfaces[i].clss)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, + for(i = 0; i < m_num_superinterfaces; i++) { + assert(m_superinterfaces[i].clss->is_interface()); + if(!m_superinterfaces[i].clss->prepare(env)) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, VM_Global_State::loader_env->JavaLangNoClassDefFoundError_String->bytes, - clss->name->bytes << ": error preparing superinterface " - << clss->superinterfaces[i].clss->name->bytes); + m_name->bytes << ": error preparing superinterface " + << m_superinterfaces[i].clss->get_name()->bytes); return false; } } // + // STEP 3 ::: PREPARE SUPERCLASS if needed // - // STEP 3 ::: PREPARE SUPERCLASS if needed; simply initialize if interface. - // - // - if (class_is_interface(clss)) { - initialize_interface_class_data(clss); - } else if (clss->super_class != NULL) { - // Regular class with super-class. - if(!class_prepare(env, clss->super_class)) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, + if(!is_interface() && has_super_class()) + { + // Regular class with super-class + if(!get_super_class()->prepare(env)) { + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, VM_Global_State::loader_env->JavaLangNoClassDefFoundError_String->bytes, - clss->name->bytes << ": error preparing superclass " - << clss->super_class->name->bytes); + m_name->bytes << ": error preparing superclass " + << get_super_class()->get_name()->bytes); return false; } - // CLASS_VTABLE_REWORK - these will eventually be moved into the vtable but we don't have one yet. - // Before we start adding properties make sure they are clear. - assert(clss->class_properties == 0); - if(clss->super_class->has_finalizer) { - clss->has_finalizer = 1; - } - initialize_regular_class_data(env, clss); - } else { - initialize_java_lang_object_class(clss); } - clss->static_data_size = 0; - clss->static_method_size = 0; - // - // - // STEP 4 :::: ASSIGN OFFSETS to the class and instance data FIELDS. - // This SETs class to ST_InstanceSizeComputed state. - // - // - assign_offsets_to_class_fields(clss); - assert(clss->state == ST_InstanceSizeComputed); - // - // - // STEP 5 :::: Build GC REFERENCE OFFSET MAP - // - // - build_gc_class_ref_map(env, clss); + // + // STEP 4 ::: setup selected class properties // - // STEP 6 :::: Calculate # of INTERFACES METHODS and build interface table DESCRIPTORS for C + if(!is_interface()) { + if(has_super_class()) { + if(get_super_class()->has_finalizer()) { + m_has_finalizer = 1; + } + // Copy over instance size, instance refs, static fields #, + // and num_field_padding_bytes from the super class. + if(m_name == env->JavaLangClass_String) { + // calculate unpadded instance data size + // for java/lang/Class separately + m_unpadded_instance_data_size = + (((unsigned)ManagedObject::get_size() + (GC_OBJECT_ALIGNMENT - 1)) + / GC_OBJECT_ALIGNMENT) + * GC_OBJECT_ALIGNMENT; + } else { + m_unpadded_instance_data_size = + get_super_class()->m_unpadded_instance_data_size; + } + m_num_instance_refs = get_super_class()->m_num_instance_refs; + m_num_field_padding_bytes = + get_super_class()->m_num_field_padding_bytes; + // Copy over number of virtual methods + // and interface methods of super class + m_num_virtual_method_entries = + get_super_class()->m_num_virtual_method_entries; + m_num_intfc_table_entries = get_super_class()->m_num_intfc_table_entries; + } else { + // this is java/lang/Object + // FIXME: primitive classes also get here, but this assignment + // has no effect on them really + m_unpadded_instance_data_size = (unsigned)ManagedObject::get_size(); + } + } else { + // this is interface + m_num_intfc_table_entries = 1; // need table entry for this interface + } + // + // STEP 5 ::: ASSIGN OFFSETS to the class and instance data FIELDS. + // This SETs class to ST_InstanceSizeComputed state. // - build_class_interface_table_descriptors(clss); + assign_offsets_to_fields(); + assert(m_state == ST_InstanceSizeComputed); + // + // STEP 6 ::: Calculate # of INTERFACES METHODS and build interface table DESCRIPTORS for C // - // STEP 7 :::: ASSIGN OFFSETS to the class and virtual METHODS + build_interface_table_descriptors(); + // + // STEP 7 ::: ASSIGN OFFSETS to the class and virtual METHODS // - assign_offsets_to_class_methods(clss); - if(clss->state == ST_Error) { + assign_offsets_to_methods(env); + if(m_state == ST_Error) return false; - } - // - // - // STEP 8 :::: Create the static field and method blocks + // + // STEP 8 ::: Create the static field block // - clss->static_data_block = (char *) clss->class_loader->Alloc(clss->static_data_size); - memset(clss->static_data_block, 0, clss->static_data_size); + m_static_data_block = (char*)m_class_loader->Alloc(m_static_data_size); + memset(m_static_data_block, 0, m_static_data_size); #ifdef VM_STATS - // 20020923 Total number of allocations and total number of bytes for class-related data structures. + // Total number of allocations and total number of bytes for class-related data structures. // This includes any rounding added to make each item aligned (current alignment is to the next 16 byte boundary). - unsigned num_bytes = (clss->static_data_size + 15) & ~15; - Class::num_statics_allocations++; - if (clss->static_data_size > 0) { - Class::num_nonempty_statics_allocations++; + unsigned num_bytes = (m_static_data_size + 15) & ~15; + VM_Statistics::get_vm_stats().num_statics_allocations++; + if(m_static_data_size > 0) { + VM_Statistics::get_vm_stats().num_nonempty_statics_allocations++; } - Class::total_statics_bytes += num_bytes; + VM_Statistics::get_vm_stats().total_statics_bytes += num_bytes; #endif - assert(clss->static_data_block); - assert(( ((POINTER_SIZE_INT)(clss->static_data_block)) % 8) == 0); // block must be on a 8 byte boundary - memset(clss->static_data_block, 0, clss->static_data_size); + assert(m_static_data_block); + // block must be on a 8 byte boundary + assert((((POINTER_SIZE_INT)(m_static_data_block)) % 8) == 0); - clss->static_method_block = (unsigned char**) new char[clss->static_method_size]; - memset(clss->static_method_block, 0, clss->static_method_size); - // - // - // STEP 9 :::: For INTERFACES intialize static fields and return. // + // STEP 9 ::: For INTERFACES intialize static fields and return. // - if (class_is_interface(clss)) { - bool init_fields = initialize_static_fields_for_interface(clss); - //if((env->java_io_Serializable_Class != NULL && clss->name != env->java_io_Serializable_Class->name)) + if(is_interface()) { + bool init_fields = initialize_static_fields_for_interface(); if(!env->InBootstrap()) { autoUnlocker.ForceUnlock(); assert(hythread_is_suspend_enabled()); if (init_fields) { - jvmti_send_class_prepare_event(clss); + jvmti_send_class_prepare_event(this); } } // DONE for interfaces - TRACE2("classloader.prepare", "END class prepare, class name = " << clss->name->bytes); + TRACE2("classloader.prepare", "END class prepare, class name = " + << m_name->bytes); return init_fields; } + // + // STEP 10 ::: COMPUTE number of interface method entries. // - // STEP 10 :::: COMPUTE number of interface method entries. - // - // - for (i = 0; i < clss->n_intfc_table_entries; i++) { - Class *intfc = clss->intfc_table_descriptors[i]; - clss->n_intfc_method_entries += intfc->n_methods; - if (intfc->static_initializer) { + for(i = 0; i < m_num_intfc_table_entries; i++) { + Class* intfc = m_intfc_table_descriptors[i]; + m_num_intfc_method_entries += intfc->get_number_of_methods(); + if(intfc->m_static_initializer) { // Don't count static initializers of interfaces. - clss->n_intfc_method_entries--; + m_num_intfc_method_entries--; } } + // + // STEP 11 ::: ALLOCATE the Vtable descriptors array // - // STEP 11 :::: ALLOCATE the Vtable descriptors array - // - // - unsigned n_vtable_entries = clss->n_virtual_method_entries + clss->n_intfc_method_entries; - if (n_vtable_entries != 0) { - clss->vtable_descriptors = new Method*[n_vtable_entries]; + unsigned n_vtable_entries = + m_num_virtual_method_entries + m_num_intfc_method_entries; + if(n_vtable_entries != 0) { + m_vtable_descriptors = new Method*[n_vtable_entries]; // ppervov: FIXME: should throw OOME - } else { - clss->vtable_descriptors = NULL; } + // + // STEP 12 ::: POPULATE with interface descriptors and virtual method descriptors + // Also, OVERRIDE superclass' methods with those of this one's // - // STEP 12 :::: POPULATE with interface descriptors and virtual method descriptors. - // Also, OVERRIDE superclass' methods with those of this one's - // - populate_vtable_descriptors_table_and_override_methods(clss); - // - // - // STEP 13 :::: CREATE VTABLE and set the Vtable entries to point to the - // code address (a stub or jitted code) + populate_vtable_descriptors_table_and_override_methods(); + // + // STEP 13 ::: CREATE VTABLE and set the Vtable entries to point to the + // code address (a stub or jitted code) // - clss->vtable = create_vtable(clss, n_vtable_entries); - for (i = 0; i < n_vtable_entries; i++) { + create_vtable(n_vtable_entries); + assert(m_vtable); + for(i = 0; i < n_vtable_entries; i++) { // need to populate with pointers to stubs or compiled code - clss->vtable->methods[i] = NULL; // for now + m_vtable->methods[i] = NULL; // for now } - if (vm_vtable_pointers_are_compressed()) + + if(vm_vtable_pointers_are_compressed()) { - clss->allocation_handle = (Allocation_Handle) ((POINTER_SIZE_INT)clss->vtable - vm_get_vtable_base()); + m_allocation_handle = + (Allocation_Handle)((POINTER_SIZE_INT)m_vtable - vm_get_vtable_base()); } else { - clss->allocation_handle = (Allocation_Handle) clss->vtable; + m_allocation_handle = (Allocation_Handle)m_vtable; } - clss->vtable->clss = clss; + m_vtable->clss = this; // Set the vtable entries to point to the code address (a stub or jitted code) - point_class_vtable_entries_to_stubs(clss); + point_vtable_entries_to_stubs(); // + // STEP 14 ::: CREATE and POPULATE the CLASS INTERFACE TABLE // - // STEP 14 :::: CREATE and POPULATE the CLASS INTERFACE TABLE - // - // - clss->vtable->intfc_table = create_populate_class_interface_table(clss); - - // - // - // STEP 15 :::: HANDLE JAVA CLASSCLASS separately + m_vtable->intfc_table = create_and_populate_interface_table(); + // + // STEP 15 ::: HANDLE JAVA CLASS CLASS separately // - - // Make sure on one hasn't prematurely set these fields since all calculations + // Make sure noone hasn't prematurely set these fields since all calculations // up to this point should be based on clss->unpadded_instance_data_size. - assert (clss->instance_data_size == 0); - assert (clss->allocated_size == 0); + assert(m_instance_data_size == 0); + assert(m_allocated_size == 0); // Add any needed padding including the OBJECT_HEADER which is used to hold // things like gc forwarding pointers, mark bits, hashes and locks.. - clss->allocated_size = - (((clss->unpadded_instance_data_size + (GC_OBJECT_ALIGNMENT - 1)) + m_allocated_size = + (((m_unpadded_instance_data_size + (GC_OBJECT_ALIGNMENT - 1)) / GC_OBJECT_ALIGNMENT) * GC_OBJECT_ALIGNMENT) + OBJECT_HEADER_SIZE; // Move the size to the vtable. - clss->vtable->allocated_size = clss->allocated_size; - clss->instance_data_size = clss->allocated_size; + m_vtable->allocated_size = m_allocated_size; + m_instance_data_size = m_allocated_size; // - // // STEP 16 :::: HANDLE PINNING and Class PROPERTIES if needed. // - // - - if (clss->super_class) { - if (get_prop_pinned (clss->super_class->class_properties)) { - // If the super class is pinned then this class is pinned. - set_prop_pinned (clss); - } + if(has_super_class() + && (get_super_class()->m_vtable->class_properties & CL_PROP_PINNED_MASK) != 0) + { + // If the super class is pinned then this class is pinned + m_vtable->class_properties |= CL_PROP_PINNED_MASK; + set_instance_data_size_constraint_bit(); } + // Set up the class_properties field. - if (clss->is_array == 1) { - clss->array_element_size = (vm_references_are_compressed() ? sizeof(COMPRESSED_REFERENCE) : sizeof(RAW_REFERENCE)); - set_prop_array (clss); - if (is_vector_of_primitives (clss)) { - clss->array_element_size = sizeof_primitive_array_element (clss); - set_prop_non_ref_array (clss); + if(is_array()) { + m_array_element_size = (vm_references_are_compressed() + ? sizeof(COMPRESSED_REFERENCE) : sizeof(RAW_REFERENCE)); + m_vtable->class_properties |= CL_PROP_ARRAY_MASK; + if(is_vector_of_primitives(this)) { + m_array_element_size = sizeof_primitive_array_element(this); + m_vtable->class_properties |= CL_PROP_NON_REF_ARRAY_MASK; } - clss->vtable->array_element_size = (unsigned short)clss->array_element_size; - switch (clss->vtable->array_element_size) + m_vtable->array_element_size = (unsigned short)m_array_element_size; + switch(m_vtable->array_element_size) { case 1: - clss->vtable->array_element_shift = 0; + m_vtable->array_element_shift = 0; break; case 2: - clss->vtable->array_element_shift = 1; + m_vtable->array_element_shift = 1; break; case 4: - clss->vtable->array_element_shift = 2; + m_vtable->array_element_shift = 2; break; case 8: - clss->vtable->array_element_shift = 3; + m_vtable->array_element_shift = 3; break; default: - clss->vtable->array_element_shift = 65535; - ASSERT(0, "Unexpected array element size: " << clss->vtable->array_element_size); + m_vtable->array_element_shift = 65535; + ASSERT(0, "Unexpected array element size: " << m_vtable->array_element_size); break; } - }else{ - clss->array_element_size = 0; - } - - if (clss->has_finalizer) { - set_prop_finalizable(clss); } #ifndef POINTER64 - if(!strcmp("[D", clss->name->bytes)) { + if(!strcmp("[D", m_name->bytes)) { // In IA32, Arrays of Doubles need to be eight byte aligned to improve // performance. In IPF all objects (arrays, class data structures, heap objects) // get aligned on eight byte boundaries. So, this special code is not needed. - clss->alignment = ((GC_OBJECT_ALIGNMENT<8)?8:GC_OBJECT_ALIGNMENT);; - - // align doubles on 8, clear alignment field and put - // in 8. - set_prop_alignment_mask (clss, 8); + m_alignment = ((GC_OBJECT_ALIGNMENT<8)?8:GC_OBJECT_ALIGNMENT);; + + // align doubles on 8, clear alignment field and put in 8. + m_vtable->class_properties |= 8; // Set high bit in size so that gc knows there are constraints + set_instance_data_size_constraint_bit(); } #endif // + // STEP 17 ::: HANDLE ALIGNMENT and Class FINALIZER if needed. // - // STEP 17 :::: HANDLE ALIGNMENT and Class FINALIZER if needed. - // - // - if (clss->alignment) { - if (clss->alignment != GC_OBJECT_ALIGNMENT) { + if(m_alignment) { + if(m_alignment != GC_OBJECT_ALIGNMENT) { // The GC will align on 4 byte boundaries by default on IA32.... #ifdef POINTER64 ASSERT(0, "Allignment is supposed to be appropriate"); #endif // Make sure it is a legal mask. - assert ((clss->alignment & CL_PROP_ALIGNMENT_MASK) <= CL_PROP_ALIGNMENT_MASK); - set_prop_alignment_mask (clss, clss->alignment); + assert((m_alignment & CL_PROP_ALIGNMENT_MASK) <= CL_PROP_ALIGNMENT_MASK); + m_vtable->class_properties |= m_alignment; + set_instance_data_size_constraint_bit(); // make sure constraintbit was set. - assert (get_instance_data_size(clss) != clss->instance_data_size); + assert(get_instance_data_size() != m_instance_data_size); } } + if(has_finalizer()) { + m_vtable->class_properties |= CL_PROP_FINALIZABLE_MASK; + set_instance_data_size_constraint_bit(); + } + // + // STEP 18 ::: SET Class ALLOCATED SIZE to INSTANCE SIZE // - // STEP 18 :::: SET Class ALLOCATED SIZE to INSTANCE SIZE - // - // - // Finally set the allocated size field. - clss->allocated_size = get_instance_data_size(clss); + m_allocated_size = get_instance_data_size(); - - // // - // STEP 18a: Determine if class should have special verification treatment. - // This is needed to handle magic classes that are not verifiable but needed for, eg, reflection implementation + // STEP 18a: Determine if class should have special access check treatment. // - // - if (should_class_not_be_verified(clss)) - clss->is_not_verified = TRUE; + static const char* reflect = "java/lang/reflect/"; + static const size_t reflect_len = strlen(reflect); + if(strncmp(m_name->bytes, reflect, reflect_len) == 0) + m_can_access_all = 1; // - // // STEP 19 :::: SET class to ST_Prepared state. // - // - gc_class_prepared(clss, clss->vtable); - assert(clss->state == ST_InstanceSizeComputed); - clss->state = ST_Prepared; - TRACE2("classloader.prepare","class " << clss->name->bytes << " prepared"); - class_initialize_if_no_side_effects(clss); + gc_class_prepared(this, m_vtable); + assert(m_state == ST_InstanceSizeComputed); + m_state = ST_Prepared; + TRACE2("classloader.prepare","class " << m_name->bytes << " prepared"); // - // STEP 20 :::: ASSIGN VALUE to static final fields + // STEP 20 ::: ASSIGN VALUE to static final fields // - // Generally speaking final value is inlined, so we needn't worry about the - // initialization of to those static final fields. But when we use reflection - // mechanisms-Field.getXXX()- to access them, we got null values. Consider this, - // We must initialize those static final fields. - // Also related to this is Binary Compatibility chapter of the JLS. - // Section 13.4.8 - // - if (!assign_values_to_class_static_final_fields(clss)) + // Generally speaking final value is inlined, so we wooldn't need to worry + // about the initialization of those static final fields. But when we use + // reflection mechanisms - Field.getXXX() - to access them, we got + // null values. Considering this, we must initialize those static + // final fields. Also related to this is Binary Compatibility chapter + // section 13.4.8 of the JLS + // + tmn_suspend_disable(); + if(!assign_values_to_class_static_final_fields(this)) { //OOME happened - assert(hythread_is_suspend_enabled()); + tmn_suspend_enable(); return false; } + tmn_suspend_enable(); // - // STEP 21 :::: Link java.lang.Class to struct Class + // STEP 21 ::: Link java.lang.Class to struct Class // // VM adds an extra field, 'vm_class', to all instances of // java.lang.Class (see an entry in vm_extra_fields). // This field is set to point to the corresponding struct Class. // // The code below stores the offset to that field in the VM environment. - // Note that due to the complexity of bootstrapping, Java classes loaded - // before java.lang.Class must be handled in a special way. At the time - // of writing this comment (2002-04-19), there are two classes loaded - // before java.lang.Class: java.lang.Object and java.io.Serializable. - if(clss->name == env->JavaLangClass_String) { - String *name = env->string_pool.lookup("vm_class"); - String* desc = env->string_pool.lookup("J"); - Field *vm_class_field = class_lookup_field(clss, name, desc); + // + if(m_name == env->JavaLangClass_String) { + String* name = env->string_pool.lookup("vm_class"); + String* desc = env->string_pool.lookup("J"); + Field* vm_class_field = lookup_field(name, desc); assert(vm_class_field != NULL); env->vm_class_offset = vm_class_field->get_offset(); } - assert(clss->class_properties == clss->vtable->class_properties); - assert(clss->allocated_size == clss->vtable->allocated_size); - assert(clss->array_element_size == clss->vtable->array_element_size); + assert(m_allocated_size == m_vtable->allocated_size); + assert(m_array_element_size == m_vtable->array_element_size); - //if( (env->JavaLangObject_Class != NULL && clss->name != env->JavaLangObject_Class->name) - // && (env->JavaLangClass_Class != NULL && clss->name != env->JavaLangClass_Class->name) ) if(!env->InBootstrap()) { autoUnlocker.ForceUnlock(); assert(hythread_is_suspend_enabled()); - jvmti_send_class_prepare_event(clss); + jvmti_send_class_prepare_event(this); } - TRACE2("classloader.prepare", "END class prepare, class name = " << clss->name->bytes); + TRACE2("classloader.prepare", "END class prepare, class name = " << m_name->bytes); return true; -} //class_prepare - - -static void class_initialize_if_no_side_effects(Class *clss) -{ - if(clss->state == ST_Initialized) { - return; - } - - Class *c; - for(c = clss; c; c = c->super_class) { - if(c->state == ST_Initialized) { - // 1. c and all its superclasses have been initialized. - // 2. all the superclases of clss which are a subclass of c - // have no static constructors. - break; - } - if(c->static_initializer) { - // c is not initialized and has a static constructor. - // Side effects are possible. - return; - } - } - - // If we get here, initializing clss has no side effects - for(c = clss; c; c = c->super_class) { - if(c->state == ST_Initialized) { - break; - } - c->state = ST_Initialized; - } -} //class_initialize_if_no_side_effects +} // Class::prepare 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 b57642a..dfc67f3 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: // @@ -107,13 +105,27 @@ #include "open/vm_util.h" -#define CLASS_REPORT_FAILURE(target, cp_index, exnclass, exnmsg) \ -{ \ - std::stringstream ss; \ - ss << exnmsg; \ - class_report_failure(target, cp_index, exnclass, ss); \ +static void class_report_failure(Class* target, uint16 cp_index, jthrowable exn) +{ + ConstantPool& cp = target->get_constant_pool(); + assert(cp.is_valid_index(cp_index)); + assert(hythread_is_suspend_enabled()); + if (exn_raised()) { + TRACE2("classloader.error", "runtime exception in classloading"); + return; + } + assert(exn); + + tmn_suspend_disable(); + target->lock(); + // vvv - This should be atomic change + cp.resolve_as_error(cp_index, exn); + // ^^^ + target->unlock(); + tmn_suspend_enable(); } + static void class_report_failure(Class* target, uint16 cp_index, const char* exnname, std::stringstream& exnmsg) { @@ -123,43 +135,43 @@ static void class_report_failure(Class* class_report_failure(target, cp_index, exn); } -// check is class "first" in the same runtime package with class "second" -static bool is_class_in_same_runtime_package( Class *first, Class *second) -{ - return first->package == second->package; + +#define CLASS_REPORT_FAILURE(target, cp_index, exnclass, exnmsg) \ +{ \ + std::stringstream ss; \ + ss << exnmsg; \ + class_report_failure(target, cp_index, exnclass, ss); \ } -static Class* _resolve_class(Global_Env *env, - Class *clss, + +Class* Class::_resolve_class(Global_Env* env, unsigned cp_index) { assert(hythread_is_suspend_enabled()); - Const_Pool *cp = clss->const_pool; + ConstantPool& cp = m_const_pool; - clss->m_lock->_lock(); - if(cp_in_error(cp, cp_index)) { - TRACE2("resolve:testing", "Constant pool entry " << cp_index << " already contains error."); - clss->m_lock->_unlock(); + lock(); + if(cp.is_entry_in_error(cp_index)) { + TRACE2("resolve.testing", "Constant pool entry " << cp_index << " already contains error."); + unlock(); return NULL; } - if(cp_is_resolved(cp, cp_index)) { - clss->m_lock->_unlock(); - return cp[cp_index].CONSTANT_Class.klass; + if(cp.is_entry_resolved(cp_index)) { + unlock(); + return cp.get_class_class(cp_index); } - String *classname = cp[cp[cp_index].CONSTANT_Class.name_index].CONSTANT_Utf8.string; - clss->m_lock->_unlock(); + const String* classname = cp.get_utf8_string(cp.get_class_name_index(cp_index)); + unlock(); // load the class in - Class *other_clss; - - other_clss = clss->class_loader->LoadVerifyAndPrepareClass(env, classname); + Class* other_clss = m_class_loader->LoadVerifyAndPrepareClass(env, classname); if(other_clss == NULL) { - jthrowable exn = class_get_error(clss->class_loader, classname->bytes); + jthrowable exn = class_get_error(m_class_loader, classname->bytes); if (exn) { - class_report_failure(clss, cp_index, exn); + class_report_failure(this, cp_index, exn); } else { assert(exn_raised()); } @@ -170,116 +182,117 @@ static Class* _resolve_class(Global_Env // referenced class should be public, // or referenced class & declaring class are the same, // or referenced class & declaring class are in the same runtime package, - // or declaring class not verified + // or declaring class not checked // (the last case is needed for certain magic classes, // eg, reflection implementation) - if(class_is_public(other_clss) - || other_clss == clss - || is_class_in_same_runtime_package( clss, other_clss ) - || clss->is_not_verified) + if(m_can_access_all + || other_clss->is_public() + || other_clss == this + || m_package == other_clss->m_package) { - clss->m_lock->_lock(); - cp_resolve_to_class(cp, cp_index, other_clss); - clss->m_lock->_unlock(); + lock(); + cp.resolve_entry(cp_index, other_clss); + unlock(); return other_clss; } // Check access control for inner classes: // access control checks is the same as for members - if(strrchr((char*)other_clss->name->bytes, '$') != NULL - && check_inner_class_access(env, other_clss, clss)) + if(strrchr(other_clss->get_name()->bytes, '$') != NULL + && can_access_inner_class(env, other_clss)) { - clss->m_lock->_lock(); - cp_resolve_to_class(cp, cp_index, other_clss); - clss->m_lock->_unlock(); + lock(); + cp.resolve_entry(cp_index, other_clss); + unlock(); return other_clss; } - CLASS_REPORT_FAILURE(clss, cp_index, "java/lang/IllegalAccessError", - "from " << clss->name->bytes << " to " << other_clss->name->bytes); + CLASS_REPORT_FAILURE(this, cp_index, "java/lang/IllegalAccessError", + "from " << get_name()->bytes << " to " << other_clss->get_name()->bytes); // IllegalAccessError return NULL; -} //_resolve_class +} // Class::_resolve_class static bool class_can_instantiate(Class* clss, bool _throw) { ASSERT_RAISE_AREA; - bool fail = class_is_abstract(clss); + bool fail = clss->is_abstract(); if(fail && _throw) { - exn_raise_by_name("java/lang/InstantiationError", clss->name->bytes); + exn_raise_by_name("java/lang/InstantiationError", clss->get_name()->bytes); } return !fail; } -Class* _resolve_class_new(Global_Env *env, Class *clss, +Class* _resolve_class_new(Global_Env* env, Class* clss, unsigned cp_index) { ASSERT_RAISE_AREA; - Class *new_clss = _resolve_class(env,clss,cp_index); + Class* new_clss = clss->_resolve_class(env, cp_index); if (!new_clss) return NULL; bool can_instantiate = class_can_instantiate(new_clss, false); - if (new_clss && !can_instantiate) { + if(new_clss && !can_instantiate) { return NULL; } return new_clss; -} //_resolve_class_new +} // _resolve_class_new // Can "other_clss" access the field or method "member"? -Boolean check_member_access(Class_Member *member, Class *other_clss) +bool Class::can_access_member(Class_Member *member) { - Class *member_clss = member->get_class(); - const char *reflect = "java/lang/reflect/"; - - // check if reflection class it has full access to all fields - if( !strncmp( other_clss->name->bytes, reflect, strlen(reflect) ) ) { - return 1; - } + Class* member_clss = member->get_class(); // check access permissions - if (member->is_public() || (other_clss == member_clss)) { + if(member->is_public() || (this == member_clss)) { // no problemo - return 1; - } else if (member->is_private()) { + return true; + } else if(member->is_private()) { // IllegalAccessError - return 0; - } else if (member->is_protected()) { - // When a member is protected, it can be accessed by classes - // in the same runtime package. - if( is_class_in_same_runtime_package( other_clss, member_clss ) ) - return 1; - // Otherwise, when other_clss is not in the same package, + return false; + } else if(member->is_protected()) { + // When a member is protected, it can be accessed by classes + // in the same runtime package + if(m_package == member_clss->m_package) + return true; + // Otherwise, when this class is not in the same package, // the class containing the member (member_clss) must be - // a superclass of other_clss. - Class *c; - for (c = other_clss->super_class; c != NULL; c = c->super_class) { - if (c == member_clss) + // a superclass of this class + // ppervov: FIXME: this can be made a method of struct Class + // smth. like: + //if(!is_extending_class(member_clss)) { + // // IllegalAccessError + // return false; + //} + //return true; + Class* c; + for(c = get_super_class(); c != NULL; c = c->get_super_class()) { + if(c == member_clss) break; } - if (c == NULL) { + if(c == NULL) { // IllegalAccessError - return 0; + return false; } - return 1; + return true; } else { - // When a member has default (or package private) access, it can only be accessed - // by classes in the same package. - if( is_class_in_same_runtime_package( other_clss, member_clss ) ) - return 1; - return 0; + // When a member has default (or package private) access, + // it can only be accessed by classes in the same package + if(m_package == member_clss->m_package) + return true; + return false; } -} //check_member_access +} // Class::can_access_member inline static bool is_class_extended_class( Class *super_clss, Class *check_clss) { - for(; super_clss != NULL; super_clss = super_clss->super_class) + for(; super_clss != NULL; super_clss = super_clss->get_super_class()) { - if( super_clss->class_loader == check_clss->class_loader - && super_clss->name == check_clss->name ) + if( super_clss->get_class_loader() == check_clss->get_class_loader() + && super_clss->get_name() == check_clss->get_name() ) { return true; } @@ -293,14 +306,14 @@ get_enclosing_class( Global_Env *env, { Class *encl_clss = NULL; - if( strrchr( (char*)klass->name->bytes, '$') != NULL ) + if( strrchr( klass->get_name()->bytes, '$') != NULL ) { // it is anonymous class // search "this$..." in fields and look for enclosing class unsigned index; Field *field; - for( index = 0, field = &klass->fields[index]; - index < klass->n_fields; - index++, field = &klass->fields[index] ) + for( index = 0, field = klass->get_field(index); + index < klass->get_number_of_fields(); + index++, field = klass->get_field(index) ) { if( strncmp( field->get_name()->bytes, "this$", 5 ) || !(field->get_access_flags() & ACC_FINAL) @@ -313,54 +326,49 @@ get_enclosing_class( Global_Env *env, // get name of enclosing class String* name = env->string_pool.lookup(&desc->bytes[1], desc->len - 2); // loading enclosing class - encl_clss = klass->class_loader->LoadVerifyAndPrepareClass(env, name); + encl_clss = klass->get_class_loader()->LoadVerifyAndPrepareClass(env, name); break; } } return encl_clss; } // get_enclosing_class -// Can "other_clss" access the "inner_clss" -Boolean -check_inner_class_access(Global_Env *env, - Class *inner_clss, - Class *other_clss) +bool Class::can_access_inner_class(Global_Env* env, Class* inner_clss) { // check access permissions - if ((inner_clss->access_flags & ACC_PUBLIC) || (other_clss == inner_clss)) { + if (inner_clss->is_public() || (this == inner_clss)) { // no problemo - return 1; - } else if (inner_clss->access_flags & ACC_PRIVATE) { + return true; + } else if (inner_clss->is_private()) { // IllegalAccessError - return 0; - } else if (inner_clss->access_flags & ACC_PROTECTED) { + return false; + } else if (inner_clss->is_protected()) { // When inner class is protected, it can be accessed by classes // in the same runtime package. - if( is_class_in_same_runtime_package( other_clss, inner_clss ) ) - return 1; + if(m_package == inner_clss->m_package) + return true; // Otherwise, when other_clss is not in the same package, // inner_clss must be a superclass of other_clss. - for( Class *decl_other_clss = other_clss; decl_other_clss != NULL; ) + for(Class *decl_other_clss = this; decl_other_clss != NULL;) { - for( Class *decl_inner_clss = inner_clss; decl_inner_clss != NULL; ) + for(Class *decl_inner_clss = inner_clss; decl_inner_clss != NULL;) { if(is_class_extended_class( decl_other_clss, decl_inner_clss ) ) { - return 1; + return true; } - if( !decl_inner_clss->declaringclass_index ) { + if( !decl_inner_clss->is_inner_class() ) { // class "decl_inner_clss" isn't inner class break; } else { // loading declaring class - if(Class* decl_inner_clss_res = _resolve_class(env, decl_inner_clss, - decl_inner_clss->declaringclass_index)) { + if(Class* decl_inner_clss_res = decl_inner_clss->resolve_declaring_class(env)) { decl_inner_clss = decl_inner_clss_res; } else { break; } } } - if( !decl_other_clss->declaringclass_index ) + if( !decl_other_clss->is_inner_class() ) { // class "decl_other_clss" isn't inner class decl_other_clss = get_enclosing_class(env, decl_other_clss); @@ -368,103 +376,98 @@ check_inner_class_access(Global_Env *env } else { // loading declaring class if(Class* decl_other_clss_res = - _resolve_class(env, decl_other_clss, decl_other_clss->declaringclass_index)) + decl_other_clss->resolve_declaring_class(env)) { - decl_other_clss = decl_other_clss_res ; + decl_other_clss = decl_other_clss_res; continue; } } break; } // IllegalAccessError - return 0; + return false; } else { // When a member has default (or package private) access, // it can only be accessed by classes in the same runtime package. - if(is_class_in_same_runtime_package(other_clss, inner_clss)) - return 1; - return 0; + if(m_package == inner_clss->m_package) + return true; + return false; } -} // check_inner_class_access +} // Class::can_access_inner_class -/** - * - */ -static Field* _resolve_field(Global_Env *env, Class *clss, unsigned cp_index) + +Field* Class::_resolve_field(Global_Env *env, unsigned cp_index) { - Const_Pool *cp = clss->const_pool; - clss->m_lock->_lock(); - if(cp_in_error(cp, cp_index)) { + lock(); + if(m_const_pool.is_entry_in_error(cp_index)) { TRACE2("resolve.testing", "Constant pool entry " << cp_index << " already contains error."); - clss->m_lock->_unlock(); + unlock(); return NULL; } - if (cp_is_resolved(cp, cp_index)) { - clss->m_lock->_unlock(); - return cp[cp_index].CONSTANT_ref.field; + if(m_const_pool.is_entry_resolved(cp_index)) { + unlock(); + return m_const_pool.get_ref_field(cp_index); } // // constant pool entry hasn't been resolved yet // - unsigned other_index = cp[cp_index].CONSTANT_ref.class_index; - clss->m_lock->_unlock(); + unsigned other_index = m_const_pool.get_ref_class_index(cp_index); + unlock(); // // check error condition from resolve class // - Class *other_clss = _resolve_class(env, clss, other_index); + Class* other_clss = _resolve_class(env, 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(m_const_pool.is_entry_in_error(other_index)) { + class_report_failure(this, cp_index, + m_const_pool.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; - - Field* field = class_lookup_field_recursive(other_clss, name, desc); - if (field == NULL) + uint16 name_and_type_index = m_const_pool.get_ref_name_and_type_index(cp_index); + String* name = m_const_pool.get_name_and_type_name(name_and_type_index); + String* desc = m_const_pool.get_name_and_type_descriptor(name_and_type_index); + Field* field = other_clss->lookup_field_recursive(name, desc); + if(field == NULL) { // // NoSuchFieldError // - CLASS_REPORT_FAILURE(clss, cp_index, "java/lang/NoSuchFieldError", - other_clss->name->bytes << "." << name->bytes + CLASS_REPORT_FAILURE(this, cp_index, "java/lang/NoSuchFieldError", + other_clss->get_name()->bytes << "." << name->bytes << " of type " << desc->bytes << " while resolving constant pool entry at index " - << cp_index << " in class " << clss->name->bytes); + << cp_index << " in class " << get_name()->bytes); return NULL; } // // check access permissions // - if (check_member_access(field, clss) == 0) + if(!can_access_member(field)) { // // IllegalAccessError // - CLASS_REPORT_FAILURE(clss, cp_index, "java/lang/IllegalAccessError", - other_clss->name->bytes << "." << name->bytes + CLASS_REPORT_FAILURE(this, cp_index, "java/lang/IllegalAccessError", + other_clss->get_name()->bytes << "." << name->bytes << " of type " << desc->bytes << " while resolving constant pool entry at index " - << cp_index << " in class " << clss->name->bytes); + << cp_index << " in class " << get_name()->bytes); return NULL; } - clss->m_lock->_lock(); - cp_resolve_to_field(cp, cp_index, field); - clss->m_lock->_unlock(); + lock(); + m_const_pool.resolve_entry(cp_index, field); + unlock(); return field; -} //_resolve_field +} // Class::_resolve_field bool field_can_link(Class* clss, Field* field, bool _static, bool putfield, bool _throw) @@ -473,21 +476,25 @@ bool field_can_link(Class* clss, Field* if(_static?(!field->is_static()):(field->is_static())) { if(_throw) { exn_raise_by_name("java/lang/IncompatibleClassChangeError", - field->get_class()->name->bytes); + field->get_class()->get_name()->bytes); } return false; } if(putfield && field->is_final()) { - for(int fn = 0; fn < clss->n_fields; fn++) { - if(&(clss->fields[fn]) == field) { + for(int fn = 0; fn < clss->get_number_of_fields(); fn++) { + if(clss->get_field(fn) == field) { return true; } } if(_throw) { - unsigned buf_size = clss->name->len + field->get_class()->name->len + field->get_name()->len + 15; + unsigned buf_size = clss->get_name()->len + + field->get_class()->get_name()->len + + field->get_name()->len + 15; char* buf = (char*)STD_ALLOCA(buf_size); memset(buf, 0, buf_size); - sprintf(buf, " from %s to %s.%s", clss->name->bytes, field->get_class()->name->bytes, field->get_name()->bytes); + sprintf(buf, " from %s to %s.%s", clss->get_name()->bytes, + field->get_class()->get_name()->bytes, + field->get_name()->bytes); jthrowable exc_object = exn_create("java/lang/IllegalAccessError", buf); exn_raise_object(exc_object); } @@ -510,126 +517,120 @@ static Field* _resolve_static_field(Glob { ASSERT_RAISE_AREA; - Field *field = _resolve_field(env,clss,cp_index); + Field *field = clss->_resolve_field(env, cp_index); if(field && !field_can_link(clss, field, CAN_LINK_FROM_STATIC, putfield, LINK_NO_THROW)) { return NULL; } return field; -} //_resolve_static_field - +} // _resolve_static_field -static Field* _resolve_nonstatic_field(Global_Env *env, - Class *clss, +static Field* _resolve_nonstatic_field(Global_Env* env, + Class* clss, unsigned cp_index, unsigned putfield) { ASSERT_RAISE_AREA; - Field *field = _resolve_field(env, clss, cp_index); + Field *field = clss->_resolve_field(env, cp_index); if(field && !field_can_link(clss, field, CAN_LINK_FROM_FIELD, putfield, LINK_NO_THROW)) { return NULL; } return field; -} //_resolve_nonstatic_field +} // _resolve_nonstatic_field -/** - * - */ -static Method* _resolve_method(Global_Env *env, Class *clss, unsigned cp_index) + +Method* Class::_resolve_method(Global_Env* env, unsigned cp_index) { - Const_Pool *cp = clss->const_pool; - clss->m_lock->_lock(); - if(cp_in_error(cp, cp_index)) { - TRACE2("resolve:testing", "Constant pool entry " << cp_index << " already contains error."); - clss->m_lock->_unlock(); + lock(); + if(m_const_pool.is_entry_in_error(cp_index)) { + TRACE2("resolve.testing", "Constant pool entry " << cp_index << " already contains error."); + unlock(); return NULL; } - if (cp_is_resolved(cp,cp_index)) { - clss->m_lock->_unlock(); - return cp[cp_index].CONSTANT_ref.method; + if(m_const_pool.is_entry_resolved(cp_index)) { + unlock(); + return m_const_pool.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; - clss->m_lock->_unlock(); + other_index = m_const_pool.get_ref_class_index(cp_index); + unlock(); // // check error condition from resolve class // - Class *other_clss = _resolve_class(env, clss, other_index); + Class* other_clss = _resolve_class(env, 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(m_const_pool.is_entry_in_error(other_index)) { + class_report_failure(this, cp_index, + m_const_pool.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 = m_const_pool.get_ref_name_and_type_index(cp_index); + String* name = m_const_pool.get_name_and_type_name(name_and_type_index); + String* desc = m_const_pool.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)) { - CLASS_REPORT_FAILURE(clss, cp_index, "java/lang/IncompatibleClassChangeError", - other_clss->name->bytes + if(m_const_pool.is_methodref(cp_index) && other_clss->is_interface()) { + CLASS_REPORT_FAILURE(this, cp_index, "java/lang/IncompatibleClassChangeError", + other_clss->get_name()->bytes << " while resolving constant pool entry " << cp_index - << " in class " << clss->name->bytes); + << " in class " << m_name->bytes); return NULL; } - if(cp_is_interfacemethodref(cp, cp_index) && !class_is_interface(other_clss)) { - CLASS_REPORT_FAILURE(clss, cp_index, "java/lang/IncompatibleClassChangeError", - other_clss->name->bytes + if(m_const_pool.is_interfacemethodref(cp_index) && !other_clss->is_interface()) { + CLASS_REPORT_FAILURE(this, cp_index, "java/lang/IncompatibleClassChangeError", + other_clss->get_name()->bytes << " while resolving constant pool entry " << cp_index - << " in class " << clss->name->bytes); + << " in class " << m_name->bytes); return NULL; } Method* method = class_lookup_method_recursive(other_clss, name, desc); - if (method == NULL) { + if(method == NULL) { // NoSuchMethodError - CLASS_REPORT_FAILURE(clss, cp_index, "java/lang/NoSuchMethodError", - other_clss->name->bytes << "." << name->bytes << desc->bytes + CLASS_REPORT_FAILURE(this, cp_index, "java/lang/NoSuchMethodError", + other_clss->get_name()->bytes << "." << name->bytes << desc->bytes << " while resolving constant pool entry at index " << cp_index - << " in class " << clss->name->bytes); + << " in class " << m_name->bytes); return NULL; } - if(method_is_abstract(method) && !class_is_abstract(other_clss)) { + if(method->is_abstract() && !other_clss->is_abstract()) { // AbstractMethodError - CLASS_REPORT_FAILURE(clss, cp_index, "java/lang/AbstractMethodError", - other_clss->name->bytes << "." << name->bytes << desc->bytes + CLASS_REPORT_FAILURE(this, cp_index, "java/lang/AbstractMethodError", + other_clss->get_name()->bytes << "." << name->bytes << desc->bytes << " while resolving constant pool entry at index " << cp_index - << " in class " << clss->name->bytes); + << " in class " << m_name->bytes); return NULL; } // // check access permissions // - if (check_member_access(method,clss) == 0) { + if(!can_access_member(method)) { // IllegalAccessError - CLASS_REPORT_FAILURE(clss, cp_index, "java/lang/IllegalAccessError", - other_clss->name->bytes << "." << name->bytes << desc->bytes + CLASS_REPORT_FAILURE(this, cp_index, "java/lang/IllegalAccessError", + other_clss->get_name()->bytes << "." << name->bytes << desc->bytes << " while resolving constant pool entry at index " << cp_index - << " in class " << clss->name->bytes); + << " in class " << m_name->bytes); return NULL; } - clss->m_lock->_lock(); - cp_resolve_to_method(cp,cp_index,method); - clss->m_lock->_unlock(); + lock(); + m_const_pool.resolve_entry(cp_index, method); + unlock(); return method; } //_resolve_method @@ -641,7 +642,7 @@ static bool method_can_link_static(Class if (!method->is_static()) { if(_throw) { exn_raise_by_name("java/lang/IncompatibleClassChangeError", - method->get_class()->name->bytes); + method->get_class()->get_name()->bytes); } return false; } @@ -654,7 +655,7 @@ static Method* _resolve_static_method(Gl { ASSERT_RAISE_AREA; - Method* method = _resolve_method(env, clss, cp_index); + Method* method = clss->_resolve_method(env, cp_index); if(method && !method_can_link_static(clss, cp_index, method, LINK_NO_THROW)) return NULL; return method; @@ -668,15 +669,15 @@ static bool method_can_link_virtual(Clas if(method->is_static()) { if(_throw) { exn_raise_by_name("java/lang/IncompatibleClassChangeError", - method->get_class()->name->bytes); + method->get_class()->get_name()->bytes); } return false; } - if(class_is_interface(method->get_class())) { + if(method->get_class()->is_interface()) { if(_throw) { - char* buf = (char*)STD_ALLOCA(clss->name->len + char* buf = (char*)STD_ALLOCA(clss->get_name()->len + method->get_name()->len + method->get_descriptor()->len + 2); - sprintf(buf, "%s.%s%s", clss->name->bytes, + sprintf(buf, "%s.%s%s", clss->get_name()->bytes, method->get_name()->bytes, method->get_descriptor()->bytes); jthrowable exc_object = exn_create("java/lang/AbstractMethodError", buf); exn_raise_object(exc_object); @@ -691,7 +692,7 @@ static Method* _resolve_virtual_method(G Class *clss, unsigned cp_index) { - Method* method = _resolve_method(env, clss, cp_index); + Method* method = clss->_resolve_method(env, cp_index); if(method && !method_can_link_virtual(clss, cp_index, method, LINK_NO_THROW)) return NULL; return method; @@ -707,7 +708,7 @@ static Method* _resolve_interface_method Class *clss, unsigned cp_index) { - Method* method = _resolve_method(env, clss, cp_index); + Method* method = clss->_resolve_method(env, cp_index); if(method && !method_can_link_interface(clss, cp_index, method, LINK_NO_THROW)) { return NULL; } @@ -719,7 +720,7 @@ Field_Handle resolve_field(Compile_Handl Class_Handle c, unsigned index) { - return _resolve_field(compile_handle_to_environment(h), c, index); + return c->_resolve_field(compile_handle_to_environment(h), index); } // resolve_field @@ -751,7 +752,7 @@ Field_Handle resolve_static_field(Compil Method_Handle resolve_method(Compile_Handle h, Class_Handle ch, unsigned idx) { - return _resolve_method(compile_handle_to_environment(h), ch, idx); + return ch->_resolve_method(compile_handle_to_environment(h), idx); } @@ -771,12 +772,13 @@ 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->get_constant_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) + && method->get_class()->get_name() != ref_class_name) { if(_throw) { exn_raise_by_name("java/lang/NoSuchMethodError", @@ -788,7 +790,7 @@ static bool method_can_link_special(Clas { if(_throw) { exn_raise_by_name("java/lang/IncompatibleClassChangeError", - method->get_class()->name->bytes); + method->get_class()->get_name()->bytes); } return false; } @@ -796,10 +798,12 @@ static bool method_can_link_special(Clas { if(_throw) { tmn_suspend_enable(); - unsigned buf_size = clss->name->len + method->get_name()->len + method->get_descriptor()->len + 5; + unsigned buf_size = clss->get_name()->len + + method->get_name()->len + method->get_descriptor()->len + 5; char* buf = (char*)STD_ALLOCA(buf_size); memset(buf, 0, buf_size); - sprintf(buf, "%s.%s%s", clss->name->bytes, method->get_name()->bytes, method->get_descriptor()->bytes); + sprintf(buf, "%s.%s%s", clss->get_name()->bytes, + method->get_name()->bytes, method->get_descriptor()->bytes); jthrowable exc_object = exn_create("java/lang/AbstractMethodError", buf); exn_raise_object(exc_object); tmn_suspend_disable(); @@ -819,18 +823,18 @@ Method_Handle resolve_special_method_env { ASSERT_RAISE_AREA; - Method* method = _resolve_method(env, curr_clss, index); + Method* method = curr_clss->_resolve_method(env, index); if(!method) { return NULL; } - if(class_is_super(curr_clss) - && is_class_extended_class(curr_clss->super_class, method->get_class()) + if(curr_clss->is_super() + && is_class_extended_class(curr_clss->get_super_class(), method->get_class()) && method->get_name() != env->Init_String) { Method* result_meth; - for(Class* clss = curr_clss->super_class; clss; clss = clss->super_class) + for(Class* clss = curr_clss->get_super_class(); clss; clss = clss->get_super_class()) { - result_meth = class_lookup_method(clss, method->get_name(), method->get_descriptor()); + result_meth = clss->lookup_method(method->get_name(), method->get_descriptor()); if(result_meth) { method = result_meth; break; @@ -910,7 +914,7 @@ Class_Handle resolve_class(Compile_Handl Class_Handle c, unsigned index) { - return _resolve_class(compile_handle_to_environment(h), c, index); + return c->_resolve_class(compile_handle_to_environment(h), index); } //resolve_class @@ -918,46 +922,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->get_constant_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: @@ -975,7 +979,7 @@ Class *resolve_class_array_of_class1(Glo { // If the element type is primitive, return one of the preloaded // classes of arrays of primitive types. - if (cc->is_primitive) { + if (cc->is_primitive()) { if (cc == env->Boolean_Class) { return env->ArrayOfBoolean_Class; } else if (cc == env->Byte_Class) { @@ -995,16 +999,16 @@ Class *resolve_class_array_of_class1(Glo } } - char *array_name = (char *)STD_MALLOC(cc->name->len + 5); - if(cc->name->bytes[0] == '[') { - sprintf(array_name, "[%s", cc->name->bytes); + char *array_name = (char *)STD_MALLOC(cc->get_name()->len + 5); + if(cc->get_name()->bytes[0] == '[') { + sprintf(array_name, "[%s", cc->get_name()->bytes); } else { - sprintf(array_name, "[L%s;", cc->name->bytes); + sprintf(array_name, "[L%s;", cc->get_name()->bytes); } String *arr_str = env->string_pool.lookup(array_name); STD_FREE(array_name); - Class* arr_clss = cc->class_loader->LoadVerifyAndPrepareClass(env, arr_str); + Class* arr_clss = cc->get_class_loader()->LoadVerifyAndPrepareClass(env, arr_str); return arr_clss; } //resolve_class_array_of_class1 @@ -1023,24 +1027,22 @@ 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->get_constant_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); + return clss->_resolve_class(env, cp_index); case CONSTANT_Fieldref: - return _resolve_field(env, clss, cp_index); + return clss->_resolve_field(env, cp_index); case CONSTANT_Methodref: - return _resolve_method(env, clss, cp_index); + return clss->_resolve_method(env, cp_index); case CONSTANT_InterfaceMethodref: - return _resolve_method(env, clss, cp_index); + return clss->_resolve_method(env, cp_index); case CONSTANT_NameAndType: // fall through case CONSTANT_Utf8: return true; @@ -1060,12 +1062,12 @@ static bool resolve_const_pool_item(Glob * Resolve whole constant pool */ int resolve_const_pool(Global_Env& env, Class *clss) { - Const_Pool *cp = clss->const_pool; + ConstantPool& cp = clss->get_constant_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 0; + 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/String_Pool.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/String_Pool.cpp index a43fc5b..e878ec8 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/String_Pool.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/String_Pool.cpp @@ -35,6 +35,7 @@ using namespace std; #include "environment.h" #include "open/hythread.h" #include "open/vm_util.h" +#include "open/gc.h" #include "atomics.h" #include "vm_strings.h" #include "vm_stats.h" @@ -290,7 +291,9 @@ ManagedObject * String_Pool::intern(Stri // Atomically update the string structure since some other thread might be trying to make the same update. // The GC won't be able to enumerate here since GC is disabled, so there are no race conditions with GC. if (VM_Global_State::loader_env->compress_references) { - COMPRESSED_REFERENCE compressed_lang_string = (COMPRESSED_REFERENCE)((POINTER_SIZE_INT)lang_string - (POINTER_SIZE_INT)Class::heap_base); + COMPRESSED_REFERENCE compressed_lang_string = + (COMPRESSED_REFERENCE)((POINTER_SIZE_INT)lang_string + - (POINTER_SIZE_INT)VM_Global_State::loader_env->heap_base); assert(is_compressed_reference(compressed_lang_string)); assert(sizeof(LONG) == sizeof(uint32)); uint32 result = apr_atomic_cas32( diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Verifier_stub.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Verifier_stub.cpp index cfc65e7..238521a 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Verifier_stub.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Verifier_stub.cpp @@ -31,101 +31,106 @@ #include "lock_manager.h" bool -class_verify(const Global_Env* env, Class *clss) +Class::verify(const Global_Env* env) { // fast path - if(clss->is_verified) + if(is_at_least_prepared() || in_error()) return true; - LMAutoUnlock aulock(clss->m_lock); - if(clss->is_verified) + LMAutoUnlock aulock(m_lock); + if(is_at_least_prepared() || m_state == ST_Error) return true; /** * Get verifier enable status */ Boolean is_forced = env->verify_all; - Boolean is_bootstrap = clss->class_loader->IsBootstrap(); + Boolean is_bootstrap = m_class_loader->IsBootstrap(); Boolean is_enabled = vm_get_boolean_property_value_with_default("vm.use_verifier"); /** * Verify class */ if(is_enabled == TRUE - && !class_is_interface(clss) - && (is_bootstrap == FALSE || is_forced == TRUE)) + && !is_interface() + && (is_bootstrap == FALSE || is_forced == TRUE)) { char *error; - Verifier_Result result = vf_verify_class((class_handler)clss, is_forced, &error ); + Verifier_Result result = vf_verify_class((class_handler)this, is_forced, &error); if( result != VER_OK ) { aulock.ForceUnlock(); - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/VerifyError", error); return false; } - clss->is_verified = 1; - } else { - clss->is_verified = 2; } + m_state = ST_BytecodesVerified; return true; -} // class_verify +} // Class::verify bool -class_verify_constraints(const Global_Env* env, Class* clss) +Class::verify_constraints(const Global_Env* env) { - if(clss->state == ST_Error) - return true; - - assert(clss->is_verified >= 1); - // fast path - if(clss->is_verified == 2) + switch(m_state) + { + case ST_ConstraintsVerified: + case ST_Initializing: + case ST_Initialized: + case ST_Error: return true; + } // lock class - clss->m_lock->_lock(); + lock(); - // check verification stage - if(clss->is_verified == 2) { - clss->m_lock->_unlock(); + // check verification stage again + switch(m_state) + { + case ST_ConstraintsVerified: + case ST_Initializing: + case ST_Initialized: + case ST_Error: + unlock(); return true; } + assert(m_state == ST_Prepared); // get verifier enable status Boolean verify_all = env->verify_all; - // unlock a class before calling of verifier - clss->m_lock->_unlock(); + // unlock a class before calling to verifier + unlock(); // check method constraints char *error; Verifier_Result result = - vf_verify_class_constraints( (class_handler)clss, verify_all, &error ); + vf_verify_class_constraints((class_handler)this, verify_all, &error); // lock class and check result - clss->m_lock->_lock(); - if( clss->state == ST_Error ) { - clss->m_lock->_unlock(); + lock(); + if(in_error()) { + unlock(); return false; } if( result != VER_OK ) { - clss->m_lock->_unlock(); + unlock(); if( result == VER_ErrorLoadClass ) { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, VM_Global_State::loader_env->JavaLangNoClassDefFoundError_String->bytes, error); } else { - REPORT_FAILED_CLASS_CLASS(clss->class_loader, clss, + REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/VerifyError", error); } return false; } - clss->is_verified = 2; + m_state = ST_ConstraintsVerified; // unlock class - clss->m_lock->_unlock(); + unlock(); return true; } // class_verify_method_constraints 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..ad089d6 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 @@ -35,7 +35,7 @@ class_get_name( class_handler klass ) { assert( klass ); Class *clss = (Class*)klass; - return clss->name->bytes; + return clss->get_name()->bytes; } // class_get_name_bytes /** @@ -46,7 +46,7 @@ class_get_class_loader( class_handler kl { assert( klass ); Class *clss = (Class*)klass; - return (classloader_handler)clss->class_loader; + return (classloader_handler)clss->get_class_loader(); } // class_get_classloader /** @@ -57,7 +57,7 @@ class_get_super_class( class_handler kla { assert( klass ); Class *clss = (Class*)klass; - return (class_handler)clss->super_class; + return (class_handler)clss->get_super_class(); } // class_get_super_class /** @@ -75,13 +75,13 @@ class_is_same_class( class_handler klass * Function checks if classes have the same package. */ unsigned -class_is_same_package( class_handler klass1, class_handler klass2 ) +class_is_same_package(class_handler klass1, class_handler klass2) { assert( klass1 ); assert( klass2 ); - Class *clss1 = (Class*)klass1; - Class *clss2 = (Class*)klass2; - return (clss1->package == clss2->package) ? 1 : 0; + Class* clss1 = (Class*)klass1; + Class* clss2 = (Class*)klass2; + return (clss1->get_package() == clss2->get_package()) ? 1 : 0; } // class_is_same_package /** @@ -93,7 +93,7 @@ class_is_interface_( class_handler klass { assert( klass ); Class *clss = (Class*)klass; - return class_is_interface( clss ) ? 1 : 0; + return clss->is_interface() ? 1 : 0; } // class_is_interface_ /** @@ -104,7 +104,7 @@ class_is_array( class_handler klass ) { assert( klass ); Class *clss = (Class*)klass; - return clss->is_array; + return clss->is_array(); } // class_is_array /** @@ -116,18 +116,18 @@ class_is_final_( class_handler klass ) { assert( klass ); Class *clss = (Class*)klass; - return class_is_final( clss ) ? 1 : 0; + return clss->is_final() ? 1 : 0; } // class_is_final_ /** * Function receives number of super interfaces of class. */ unsigned short -class_get_superinterface_number( class_handler klass ) +class_get_superinterface_number(class_handler klass) { assert( klass ); Class *clss = (Class*)klass; - return clss->n_superinterfaces; + return clss->get_number_of_superinterfaces(); } // class_get_superinterface_number /** @@ -138,8 +138,8 @@ class_get_superinterface( class_handler { assert( klass ); Class *clss = (Class*)klass; - assert( index < clss->n_superinterfaces ); - return (class_handler)clss->superinterfaces[index].clss; + assert(index < clss->get_number_of_superinterfaces()); + return (class_handler)clss->get_superinterface(index); } // class_get_superinterface /** @@ -153,8 +153,8 @@ class_get_array_element_class( class_han { assert( klass ); Class *clss = (Class*)klass; - assert( clss->is_array ); - return (class_handler)clss->array_element_class; + assert(clss->is_array()); + return (class_handler)clss->get_array_element_class(); } // class_get_array_element_class /** @@ -165,8 +165,8 @@ class_is_extending_class( class_handler { assert( klass ); assert( super_name ); - for( Class *clss = (Class*)klass; clss; clss = clss->super_class ) { - if( !strcmp( clss->name->bytes, super_name ) ) { + for( Class *clss = (Class*)klass; clss; clss = clss->get_super_class() ) { + if( !strcmp( clss->get_name()->bytes, super_name ) ) { // found class with given name return 1; } @@ -182,7 +182,7 @@ class_get_method_number( class_handler k { assert( klass ); Class *clss = (Class*)klass; - return clss->n_methods; + return clss->get_number_of_methods(); } // class_get_method_number /** @@ -193,8 +193,7 @@ class_get_method( class_handler klass, u { assert( klass ); Class *clss = (Class*)klass; - assert( index < clss->n_methods ); - return (method_handler)&clss->methods[index]; + return (method_handler)clss->get_method(index); } // class_get_method /** @@ -203,9 +202,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->get_constant_pool().get_size(); } // class_get_cp_size /** @@ -215,9 +214,8 @@ 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; + return clss->get_constant_pool().get_tag(index); } // class_get_cp_tag /** @@ -227,10 +225,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->get_constant_pool().get_class_name_index(index); } // class_get_cp_class_name_index /** @@ -241,11 +237,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->get_constant_pool().get_ref_class_index(index); } // class_get_cp_ref_class_index /** @@ -256,24 +248,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->get_constant_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->get_constant_pool().get_string_index(index); } // class_get_cp_string_index /** @@ -283,10 +269,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->get_constant_pool().get_name_and_type_name_index(index); } // class_get_cp_name_index /** @@ -296,46 +280,39 @@ 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->get_constant_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->get_constant_pool().get_utf8_chars(index); } // class_get_cp_utf8_bytes /** * Function sets verify data to a given class. */ -void -class_set_verify_data_ptr( class_handler klass, void *data ) +void class_set_verify_data_ptr(class_handler klass, void* data) { - assert( klass ); - Class *clss = (Class*)klass; - clss->verify_data = data; - return; + assert(klass); + Class* clss = (Class*)klass; + clss->set_verification_data(data); } // class_set_verify_data_ptr /** * Function returns verify data for a given class. */ -void * -class_get_verify_data_ptr( class_handler klass ) +void* class_get_verify_data_ptr(class_handler klass) { - assert( klass ); - Class *clss = (Class*)klass; - return clss->verify_data; + assert(klass); + Class* clss = (Class*)klass; + return clss->get_verification_data(); } // class_get_verify_data_ptr /** @@ -344,10 +321,10 @@ class_get_verify_data_ptr( class_handler method_handler class_resolve_method( class_handler klass, unsigned short index ) { - assert( klass ); - assert( index ); - Class *clss = (Class*)klass; - Method *method = class_resolve_method( clss, index ); + assert(klass); + assert(index); + Class* clss = (Class*)klass; + Method* method = clss->_resolve_method(VM_Global_State::loader_env, index); return (method_handler)method; } // class_resolve_method 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 d87bc16..2577f89 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp @@ -32,7 +32,6 @@ #include "exceptions.h" #include "properties.h" #include "vm_strings.h" -#include "Verifier_stub.h" #include "nogc.h" #include "bytereader.h" #include "Package.h" @@ -52,32 +51,16 @@ #include "jarfile_util.h" #include "jni_utils.h" -// -// private static variable containing the id of the next class -// access to this needs to be thread safe; also, this will have to -// change if we want to reuse class ids -// -// an id of 0 is reserved to mean null; therefore, ids start from 1 -// -// ppervov: FIXME: usage of this variable is not currently thread safe -unsigned class_next_id = 1; - unsigned ClassLoader::m_capacity = 0; unsigned ClassLoader::m_unloadedBytes = 0; unsigned ClassLoader::m_nextEntry = 0; ClassLoader** ClassLoader::m_table = NULL; Lock_Manager ClassLoader::m_tableLock; -void mark_classloader(ClassLoader* cl) -{ - if(cl->GetLoader() && cl->NotMarked()) { - TRACE2("classloader.unloading.markloader", " Marking loader " - << cl << " (" << (void*)cl->GetLoader() << " : " - << ((VTable*)(*(unsigned**)(cl->GetLoader())))->clss->name->bytes << ")"); - cl->Mark(); - } -} - +// external declaration; definition is in Class_File_Loader.cpp +const String* class_extract_name(Global_Env* env, + uint8* buffer, + unsigned offset, unsigned length); /*VMEXPORT*/ jthrowable class_get_error(ClassLoaderHandle clh, const char* name) { @@ -87,21 +70,6 @@ void mark_classloader(ClassLoader* cl) } -void class_set_error_cause(Class *clss, jthrowable exn) { - tmn_suspend_disable(); - clss->m_lock->_lock(); - clss->state = ST_Error; - clss->p_error = exn->object; - clss->m_lock->_unlock(); - tmn_suspend_enable(); -} - -jthrowable class_get_error_cause(Class *clss) { - assert(clss->p_error); - return (jthrowable) &clss->p_error; -} - - bool ClassLoader::Initialize( ManagedObject* loader ) { m_loader = loader; @@ -230,11 +198,16 @@ Class* ClassLoader::NewClass(const Globa assert(env->JavaLangClass_Class == NULL); } - clss = (Class *) Alloc(sizeof(Class)); + clss = (Class*)Alloc(sizeof(Class)); // ppervov: FIXME: should check that class is successfully allocated assert(clss); - return InitClassFields(env, clss, name); + clss->init_internals(env, name, this); + + if(clss->get_name()) + clss = AllocateAndReportInstance(env, clss); + + return clss; } ManagedObject** ClassLoader::RegisterClassInstance(const String* className, ManagedObject* instance) @@ -294,18 +267,16 @@ Class* ClassLoader::DefineClass(Global_E FailedLoadingClass(className); return NULL; } - + /* * Create a Class File Stream object */ ByteReader cfs(bytecode, offset, length); - unsigned super_class_cp_index; - assert(clss->state == ST_Start); - + /* * now parse and verify the class data */ - if(!class_parse(env, clss, &super_class_cp_index, cfs)) { + if(!clss->parse(env, cfs)) { if (NULL != redef_buf) _deallocate(redef_buf); FailedLoadingClass(className); @@ -329,22 +300,14 @@ Class* ClassLoader::DefineClass(Global_E } // XXX - //clss->class_loader = this; - if(!FinishLoadingClass(env, clss, &super_class_cp_index)) { + if(!clss->load_ancestors(env)) { FailedLoadingClass(className); return NULL; } - clss->package = ProvidePackage(env, className, NULL); - InsertClass(clss); SuccessLoadingClass(className); - //bool doNotNotifyBaseClasses = // false if class is either j/l/Object, j/io/Serializable, or j/l/Class - // (clss->name != env->JavaLangObject_String) - // && (env->java_io_Serializable_Class != NULL && clss->name != env->java_io_Serializable_Class->name) - // && (clss->name != env->JavaLangClass_String); - //if( this != env->bootstrap_class_loader || doNotNotifyBaseClasses ) if(this != env->bootstrap_class_loader || !env->InBootstrap()) { jvmti_send_class_load_event(env, clss); @@ -353,32 +316,34 @@ Class* ClassLoader::DefineClass(Global_E return clss; } - Package* ClassLoader::ProvidePackage(Global_Env* env, const String *class_name, - const char *jar) { - const char* clss = class_name->bytes; - const char* sep = strrchr(clss, '/'); - const String* package_name; - if (!sep) { - // this must be the default package... - package_name = env->string_pool.lookup(""); - } else { - package_name = env->string_pool.lookup(clss, + +Package* ClassLoader::ProvidePackage(Global_Env* env, const String* class_name, + const char* jar) +{ + const char* clss = class_name->bytes; + const char* sep = strrchr(clss, '/'); + const String* package_name; + if (!sep) { + // this must be the default package... + package_name = env->string_pool.lookup(""); + } else { + package_name = env->string_pool.lookup(clss, static_cast(sep - clss)); - } - Lock(); - Package *package = m_package_table->lookup(package_name); - if (package == NULL) { - // create a new package - void* p = apr_palloc(pool, sizeof(Package)); - const char* jar_url = jar ? - apr_pstrcat(pool, "jar:file:", jar, "!/", NULL) : NULL; - package = new (p) Package(package_name, jar_url); - m_package_table->Insert(package); - } - Unlock(); - - return package; - } + } + Lock(); + Package *package = m_package_table->lookup(package_name); + if (package == NULL) { + // create a new package + void* p = apr_palloc(pool, sizeof(Package)); + const char* jar_url = jar ? + apr_pstrcat(pool, "jar:file:", jar, "!/", NULL) : NULL; + package = new (p) Package(package_name, jar_url); + m_package_table->Insert(package); + } + Unlock(); + + return package; +} Class* ClassLoader::LoadVerifyAndPrepareClass(Global_Env* env, const String* name) { @@ -386,14 +351,8 @@ Class* ClassLoader::LoadVerifyAndPrepare Class* clss = LoadClass(env, name); if(!clss) return NULL; - - if(!class_verify(env, clss)) { - return NULL; - } - - if(!class_prepare(env, clss)) { - return NULL; - } + if(!clss->verify(env)) return NULL; + if(!clss->prepare(env)) return NULL; return clss; } @@ -419,8 +378,8 @@ void ClassLoader::ReportFailedClass(Clas assert(exn_raised()); return; // OOME } - AddFailedClass(klass->name, exn); - class_set_error_cause(klass, exn); + AddFailedClass(klass->get_name(), exn); + klass->set_error_cause(exn); } void ClassLoader::ReportFailedClass(Class* klass, const char* exnclass, std::stringstream& exnmsg) @@ -428,8 +387,8 @@ void ClassLoader::ReportFailedClass(Clas jthrowable exn = exn_create(exnclass, exnmsg.str().c_str()); // ppervov: FIXME: should throw OOME - AddFailedClass(klass->name, exn); - class_set_error_cause(klass, exn); + AddFailedClass(klass->get_name(), exn); + klass->set_error_cause(exn); } @@ -443,97 +402,6 @@ void ClassLoader::ReportFailedClass(cons AddFailedClass(klassName, exn); } -bool ClassLoader::FinishLoadingClass(Global_Env* env, Class* clss, unsigned* super_class_cp_index) -{ - clss->state = ST_LoadingAncestors; - - String* superName = clss->super_name; - - if( superName == NULL ) { - if(env->InBootstrap() || clss->name != env->JavaLangClass_String) { - // This class better be java.lang.Object - if( clss->name != env->JavaLangObject_String ) { - // ClassFormatError - std::stringstream ss; - ss << clss->name->bytes << ": class does not have superclass but the class is not java.lang.Object"; - REPORT_FAILED_CLASS_CLASS(this, clss, "java/lang/ClassFormatError", ss.str().c_str()); - return false; - } - } - } else { - // Load super class - Class* superClass; - clss->super_class = NULL; - superClass = LoadClass(env, superName); - - if(superClass == NULL) { - if(!GetClassError(clss->name->bytes)) { - // Don't report failed classes more than one time - REPORT_FAILED_CLASS_CLASS_EXN(this, clss, GetClassError(superName->bytes)); - } - return false; - } - if(class_is_interface(superClass) || class_is_final(superClass)) { - REPORT_FAILED_CLASS_CLASS(this, clss, "java/lang/IncompatibleClassChangeError", clss->name->bytes); - return false; - } - if(!class_verify(env, superClass)) return false; - if(!class_prepare(env, superClass)) return false; - - // 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 it's an interface, its superclass must be java/lang/Object - if(class_is_interface(clss)) { - if((env->JavaLangObject_Class != NULL) && (superClass != env->JavaLangObject_Class)) { - std::stringstream ss; - ss << clss->name->bytes << ": interface superclass is not java.lang.Object"; - REPORT_FAILED_CLASS_CLASS(this, clss, "java/lang/ClassFormatError", ss.str().c_str()); - return false; - } - } - - // 2003-06-18. Update the cha_first_child and cha_next_sibling fields. - clss->cha_first_child = NULL; - if (clss->super_class != NULL) - { - clss->cha_next_sibling = clss->super_class->cha_first_child; - clss->super_class->cha_first_child = clss; - } - // Notify interested JITs that the superclass has been extended. - do_jit_extended_class_callbacks( superClass, /*new_subclass*/ clss ); - } - - // - // load in super interfaces - // - for( unsigned i = 0; i < clss->n_superinterfaces; i++ ) { - String *intfc_name = clss->superinterfaces[i].name; - Class* intfc = LoadVerifyAndPrepareClass(env, intfc_name); - if( intfc == NULL ) { - if(!GetClassError(clss->name->bytes)) { - REPORT_FAILED_CLASS_CLASS_EXN(this, clss, GetClassError(intfc_name->bytes)); - } - return false; - } - if(!class_is_interface(intfc)) { - REPORT_FAILED_CLASS_CLASS(this, clss, "java/lang/IncompatibleClassChangeError", - clss->name->bytes << ": " << intfc->name->bytes << " is not an interface"); - return false; - } - - // superinterface was successfully loaded - clss->superinterfaces[i].clss = intfc; - } - // class, superclass, and superinterfaces successfully loaded - - clss->state = ST_Loaded; - - return true; -} void ClassLoader::RemoveLoadingClass(const String* className, LoadingClass* loading) { @@ -633,19 +501,19 @@ void ClassLoader::ClearMarkBits() if(m_table[i]->m_unloading) { TRACE2("classloader.unloading.debug", " Skipping \"unloaded\" classloader " << m_table[i] << " (" << m_table[i]->m_loader << " : " - << ((VTable*)(*(unsigned**)(m_table[i]->m_loader)))->clss->name->bytes << ")"); + << ((VTable*)(*(unsigned**)(m_table[i]->m_loader)))->clss->get_name()->bytes << ")"); continue; } TRACE2("classloader.unloading.debug", " Clearing mark bits in classloader " << m_table[i] << " (" << m_table[i]->m_loader << " : " - << ((VTable*)(*(unsigned**)(m_table[i]->m_loader)))->clss->name->bytes << ") and its classes"); + << ((VTable*)(*(unsigned**)(m_table[i]->m_loader)))->clss->get_name()->bytes << ") and its classes"); // clear mark bits in loader and classes m_table[i]->m_markBit = 0; for(cti = m_table[i]->m_loadedClasses->begin(); cti != m_table[i]->m_loadedClasses->end(); cti++) { - if(cti->second->class_loader == m_table[i]) { - cti->second->m_markBit = 0; + if(cti->second->get_class_loader() == m_table[i]) { + cti->second->reset_reachable(); } } } @@ -664,16 +532,16 @@ void ClassLoader::StartUnloading() if(m_table[i]->m_unloading) { TRACE2("classloader.unloading.debug", " Skipping \"unloaded\" classloader " << m_table[i] << " (" << m_table[i]->m_loader << " : " - << ((VTable*)(*(unsigned**)(m_table[i]->m_loader)))->clss->name->bytes << ")"); + << ((VTable*)(*(unsigned**)(m_table[i]->m_loader)))->clss->get_name()->bytes << ")"); continue; } TRACE2("classloader.unloading.debug", " Scanning loader " << m_table[i] << " (" << m_table[i]->m_loader << " : " - << ((VTable*)(*(unsigned**)(m_table[i]->m_loader)))->clss->name->bytes << ")"); + << ((VTable*)(*(unsigned**)(m_table[i]->m_loader)))->clss->get_name()->bytes << ")"); if(!m_table[i]->m_markBit) { TRACE2("classloader.unloading.stats", " (!) Ready to unload classloader " << m_table[i] << " (" << m_table[i]->m_loader << " : " - << ((VTable*)(*(unsigned**)(m_table[i]->m_loader)))->clss->name->bytes << ")"); + << ((VTable*)(*(unsigned**)(m_table[i]->m_loader)))->clss->get_name()->bytes << ")"); TRACE2("classloader.unloading.stats", " (!) This will free " << m_table[i]->GetFullSize() << " bytes in C heap"); m_table[i]->m_unloading = true; @@ -693,7 +561,7 @@ void ClassLoader::PrintUnloadingStats() if(m_table[i]->m_unloading) { TRACE2("classloader.unloading.stats", " Class loader " << m_table[i] << " (" << m_table[i]->m_loader << " : " - << ((VTable*)(*(unsigned**)(m_table[i]->m_loader)))->clss->name->bytes + << ((VTable*)(*(unsigned**)(m_table[i]->m_loader)))->clss->get_name()->bytes << ") contains " << m_table[i]->GetFullSize() << " bytes in C heap"); } } @@ -725,7 +593,7 @@ ClassLoader* ClassLoader::AddClassLoader ClassLoader* cl = new UserDefinedClassLoader(); TRACE2("classloader.unloading.add", "Adding class loader " << cl << " (" << loader << " : " - << ((VTable*)(*(unsigned**)(loader)))->clss->name->bytes << ")"); + << ((VTable*)(*(unsigned**)(loader)))->clss->get_name()->bytes << ")"); cl->Initialize( loader ); if( m_capacity <= m_nextEntry ) ReallocateTable( m_capacity?(2*m_capacity):32 ); @@ -774,10 +642,10 @@ Class* ClassLoader::StartLoadingClass(Gl { klass = *pklass; // class has already been loaded - if(klass->state == ST_LoadingAncestors) { + if(klass->get_state() == ST_LoadingAncestors) { // there is a circularity in the class hierarchy aulock.ForceUnlock(); - REPORT_FAILED_CLASS_CLASS(this, klass, "java/lang/ClassCircularityError", klass->name->bytes); + REPORT_FAILED_CLASS_CLASS(this, klass, "java/lang/ClassCircularityError", klass->get_name()->bytes); return NULL; } return klass; @@ -852,8 +720,8 @@ unsigned ClassLoader::GetFullSize() { for(cti = m_loadedClasses->begin(); cti != m_loadedClasses->end(); cti++) { - if(cti->second->class_loader == this) { - m_fullSize += class_calculate_size(cti->second); + if(cti->second->get_class_loader() == this) { + m_fullSize += cti->second->calculate_size(); } } return m_fullSize; @@ -917,7 +785,7 @@ Class* ClassLoader::WaitDefinition(Globa // We only have to report current error condition and do not need // to record error state in the class... std::stringstream ss; - ss << "class " << clss->name->bytes << " is defined second time"; + ss << "class " << clss->get_name()->bytes << " is defined second time"; jthrowable exn = exn_create("java/lang/LinkageError", ss.str().c_str()); exn_raise_object(exn); return NULL; @@ -1003,7 +871,7 @@ Class* ClassLoader::SetupAsArray(Global_ className); return NULL; } - ClassLoader* baseLoader = baseClass->class_loader; + ClassLoader* baseLoader = baseClass->get_class_loader(); Class* elementClass = baseClass; if(n_dimensions > 1) { elementClass = baseLoader->LoadVerifyAndPrepareClass(env, env->string_pool.lookup(&className[1])); @@ -1045,49 +913,11 @@ Class* ClassLoader::SetupAsArray(Global_ } // setup array-related fields - klass->is_array = 1; - klass->n_dimensions = (unsigned char)n_dimensions; - if(n_dimensions == 1) { - klass->is_array_of_primitives = isArrayOfPrimitives; - } else { - klass->is_array_of_primitives = false; - } - klass->array_element_class = elementClass; - klass->array_base_class = baseClass; - klass->is_verified = 2; - - assert(elementClass); - klass->array_element_type_desc = type_desc_create_from_class(elementClass); - - // insert Java field, required by spec - 'length' - klass->n_fields = 1; - klass->fields = new Field[1]; - klass->fields[0].set(klass, env->Length_String, - env->string_pool.lookup("I"), ACC_PUBLIC|ACC_FINAL); - klass->fields[0].set_field_type_desc( - type_desc_create_from_java_descriptor("I", NULL)); - klass->fields[0].set_injected(); - - klass->super_name = env->JavaLangObject_String; - - // set array access flags the same as its base class - klass->access_flags = (ACC_FINAL | ACC_ABSTRACT); - if(isArrayOfPrimitives) { - klass->access_flags |= ACC_PUBLIC; - } else { - klass->access_flags = (uint16)(klass->access_flags | (baseClass->access_flags - & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED) )); - } - klass->package = elementClass->package; - - // array classes implement two interfaces: Cloneable and Serializable - klass->superinterfaces = (Class_Superinterface*) Alloc(2 * sizeof(Class_Superinterface)); - klass->superinterfaces[0].name = env->Clonable_String; - klass->superinterfaces[1].name = env->Serializable_String; - klass->n_superinterfaces = 2; + klass->setup_as_array(env, n_dimensions, isArrayOfPrimitives, + baseClass, elementClass); } - if(!FinishLoadingClass(env, klass, NULL)) { + if(!klass->load_ancestors(env)) { FailedLoadingClass(classNameString); return NULL; } @@ -1098,24 +928,39 @@ Class* ClassLoader::SetupAsArray(Global_ return klass; } // ClassLoader::SetupAsArray + +static void set_struct_Class_field_in_java_lang_Class(const Global_Env* env, ManagedObject** jlc, Class *clss) +{ + assert(managed_object_is_java_lang_class(*jlc)); + assert(env->vm_class_offset != 0); + + Class** vm_class_ptr = (Class **)(((Byte *)(*jlc)) + env->vm_class_offset); + *vm_class_ptr = clss; +} // set_struct_Class_field_in_java_lang_Class + + /** Adds Class* pointer to m_reportedClasses HashTable. -* clss->name must not be NULL. +* clss->m_name must not be NULL. */ Class* ClassLoader::AllocateAndReportInstance(const Global_Env* env, Class* clss) { - const String* name = clss->name; + const String* name = clss->get_name(); assert(name); if (env->InBootstrap()) { - clss->class_handle = NULL; + // Make sure we are bootstrapping initial VM classes + assert((name == env->JavaLangObject_String) + || (strcmp(name->bytes, "java/io/Serializable") == 0) + || (name == env->JavaLangClass_String) + || (strcmp(name->bytes, "java/lang/reflect/AnnotatedElement") == 0) + || (strcmp(name->bytes, "java/lang/reflect/GenericDeclaration") == 0) + || (strcmp(name->bytes, "java/lang/reflect/Type") == 0)); } else { Class* root_class = env->JavaLangClass_Class; assert(root_class != NULL); tmn_suspend_disable(); // -----------------vvv - ManagedObject* new_java_lang_Class = - (ManagedObject*) vm_alloc_and_report_ti(root_class->instance_data_size, - root_class->allocation_handle, vm_get_gc_thread_local(), root_class); + ManagedObject* new_java_lang_Class = root_class->allocate_instance(); if(new_java_lang_Class == NULL) { tmn_suspend_enable(); @@ -1127,91 +972,24 @@ Class* ClassLoader::AllocateAndReportIns } // add newly created java_lang_Class to reportable collection LMAutoUnlock aulock(&m_lock); - clss->class_handle = m_reportedClasses->Insert(name, new_java_lang_Class); + clss->set_class_handle(m_reportedClasses->Insert(name, new_java_lang_Class)); aulock.ForceUnlock(); TRACE("NewClass inserting class \"" << name->bytes << "\" with key " << name << " and object " << new_java_lang_Class); - assert(new_java_lang_Class == *(clss->class_handle)); -#ifdef VM_STATS - root_class->num_allocations++; - root_class->num_bytes_allocated += root_class->instance_data_size; -#endif //VM_STATS + assert(new_java_lang_Class == *(clss->get_class_handle())); assert(env->vm_class_offset); - set_struct_Class_field_in_java_lang_Class(env, clss->class_handle, clss); + set_struct_Class_field_in_java_lang_Class(env, clss->get_class_handle(), clss); tmn_suspend_enable(); // -----------------^^^ } return clss; } -Class* ClassLoader::InitClassFields(const Global_Env* env, Class* clss, const String* name) -{ - memset(clss, 0, sizeof(Class)); - -#ifdef POINTER64 - clss->alignment = ((GC_OBJECT_ALIGNMENT<8)?8:GC_OBJECT_ALIGNMENT);; -#else - clss->alignment = GC_OBJECT_ALIGNMENT; -#endif - - clss->id = class_next_id++; - clss->name = name; - clss->class_loader = this; - clss->state = ST_Start; - - clss->m_lock = new Lock_Manager(); - - // Special case: ClassLoader.defineClass() call with null classname value. - // Calling AddToReported() only if real class name is already known. - if (clss->name != NULL) - clss = AllocateAndReportInstance(env, clss); - - return clss; -} void ClassLoader::ClassClearInternals(Class* clss) { - FieldClearInternals(clss); - - if (clss->methods != NULL) - { - for (int i = 0; i < clss->n_methods; i++){ - clss->methods[i].MethodClearInternals(); - } - 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; - } - if (clss->vtable_descriptors) - delete []clss->vtable_descriptors; - - if (clss->static_method_block) - delete []clss->static_method_block; - - if (clss->m_lock) - delete clss->m_lock; - - if (clss->array_element_type_desc) - { - delete clss->array_element_type_desc; - clss->array_element_type_desc = NULL; - } -} - -void ClassLoader::FieldClearInternals(Class* clss) -{ - if (clss->fields != NULL) - { - delete []clss->fields; - clss->fields = NULL; - } + clss->clear_internals(); } @@ -1304,7 +1082,7 @@ GenericFunctionPointer ClassLoader::Look Class* klass = method->get_class(); // get class name, method name and method descriptor - const String* class_name = klass->name; + const String* class_name = klass->get_name(); const String* method_name = method->get_name(); const String* method_desc = method->get_descriptor(); @@ -1827,10 +1605,10 @@ Class* UserDefinedClassLoader::DoLoadCla Class *exn_class = jobject_to_struct_Class(exn); INFO("Loading of " << className->bytes << " class failed due to " - << exn_class->name->bytes); + << exn_class->get_name()->bytes); while(exn_class && exn_class != NotFoundExn_class) { - exn_class = exn_class->super_class; + exn_class = exn_class->get_super_class(); } if (exn_class == NotFoundExn_class) { @@ -1870,8 +1648,8 @@ Class* UserDefinedClassLoader::DoLoadCla Class* clss = java_lang_Class_to_struct_Class(oh->object); tmn_suspend_enable(); - assert(clss->class_loader != NULL); - if(clss->class_loader != this) { + assert(clss->get_class_loader() != NULL); + if(clss->get_class_loader() != this) { // if loading of this class was delegated to some other CL // signal successful loading for our CL SuccessLoadingClass(className); @@ -1998,7 +1776,7 @@ Class* BootstrapClassLoader::LoadFromCla // define class Class* clss = DefineClass(m_env, class_name->bytes, buf, 0, buf_len); if(clss) { - clss->class_file_name = m_env->string_pool.lookup(full_name); + clss->set_class_file_name(m_env->string_pool.lookup(full_name)); } apr_pool_destroy(local_pool); @@ -2027,14 +1805,14 @@ Class* BootstrapClassLoader::LoadFromJar return NULL; } - // set class into package collection + // create package information with jar source ProvidePackage(m_env, class_name, jar_file->GetName()); // define class Class *clss = DefineClass(m_env, class_name->bytes, buffer, 0, size, NULL); if(clss) { // set class file name - clss->class_file_name = m_env->string_pool.lookup(jar_file->GetName()); + clss->set_class_file_name(m_env->string_pool.lookup(jar_file->GetName())); } return clss; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/java_type.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/java_type.cpp index 8d372bd..df32f80 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/java_type.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/java_type.cpp @@ -88,22 +88,23 @@ TypeDesc* type_desc_create_from_java_des TypeDesc* type_desc_create_from_java_class(Class* c) { - if(c->is_array) - return type_desc_create_from_java_descriptor(c->name->bytes, c->class_loader); - assert(!c->is_primitive); + const String* cname = c->get_name(); + if(c->is_array()) + return type_desc_create_from_java_descriptor(cname->bytes, c->get_class_loader()); + assert(!c->is_primitive()); - c->class_loader->LockTypesCache(); - TypeDesc** tdres = c->class_loader->GetJavaTypes()->Lookup(c->name); + c->get_class_loader()->LockTypesCache(); + TypeDesc** tdres = c->get_class_loader()->GetJavaTypes()->Lookup(cname); if (tdres) { assert (*tdres); - c->class_loader->UnlockTypesCache(); + c->get_class_loader()->UnlockTypesCache(); return *tdres; } - TypeDesc* td = new TypeDesc(K_Object, NULL, NULL, c->name, c->class_loader, NULL); + TypeDesc* td = new TypeDesc(K_Object, NULL, NULL, cname, c->get_class_loader(), NULL); assert(td); - c->class_loader->GetJavaTypes()->Insert(c->name, td); - c->class_loader->UnlockTypesCache(); + c->get_class_loader()->GetJavaTypes()->Insert(cname, td); + c->get_class_loader()->UnlockTypesCache(); return td; } 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 6021021..710b828 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 "open/vm_util.h" #include "jit_intf_cpp.h" #include "atomics.h" +#include "cci.h" #ifdef _IPF_ #include "vm_ipf.h" @@ -77,7 +78,7 @@ Class_Handle get_curr_arg_class(Arg_List n = env->string_pool.lookup(name, len); } Class* clss = ((Method *)m)->get_class(); - Class* c = clss->class_loader->LoadClass(env, n); + Class* c = clss->get_class_loader()->LoadClass(env, n); return c; } //get_curr_arg_class @@ -104,19 +105,6 @@ Arg_List_Iterator advance_arg_iterator(A return iter; } //advance_arg_iterator - -// Return the return type of this method. -VMEXPORT // temporary solution for interpreter unplug -Java_Type Method::get_return_java_type() -{ - const char *descr = get_descriptor()->bytes; - while(*descr != ')') - descr++; - return (Java_Type)*(descr + 1); -} //Method::get_return_java_type - - - Class_Handle method_get_return_type_class(Method_Handle m) { assert(hythread_is_suspend_enabled()); @@ -138,7 +126,7 @@ Class_Handle method_get_return_type_clas } Class *clss = method->get_class(); - Class *c = clss->class_loader->LoadVerifyAndPrepareClass(env, n); + Class *c = clss->get_class_loader()->LoadVerifyAndPrepareClass(env, n); return c; } //method_get_return_type_class @@ -164,24 +152,6 @@ Handler::Handler() } //Handler::Handler -VMEXPORT // temporary solution for interpreter unplug -unsigned Method::num_bc_exception_handlers() -{ - return _n_handlers; -} //Method::num_bc_exception_handlers - - - -VMEXPORT // temporary solution for interpreter unplug -Handler * -Method::get_bc_exception_handler_info(unsigned eh_number) -{ - assert(eh_number < _n_handlers); - return _handlers + eh_number; -} //Method::get_bc_exception_handler_info - - - void Method::set_num_target_exception_handlers(JIT *jit, unsigned n) { CodeChunkInfo *jit_info = get_chunk_info_mt(jit, CodeChunkInfo::main_code_chunk_id); @@ -231,20 +201,11 @@ Method::get_target_exception_handler_inf } //Method::get_target_exception_handler_info - -VMEXPORT // temporary solution for interpreter unplug -Arg_List_Iterator Method::get_argument_list() -{ - return initialize_arg_list_iterator(get_descriptor()->bytes); -} //Method::get_argument_list - - -VMEXPORT // temporary solution for interpreter unplug -unsigned Method::get_num_arg_bytes() +void Method::calculate_arguments_size() { - // Use this old scheme until we can use the new JIT interface's methods to inspect the types of - // each method argument. This requires that these methods support Java, and that - // they work during VM's bootstrapping. + // Use this old scheme until we can use the new JIT interface's methods + // to inspect the types of each method argument. This requires that these + // methods support Java, and that they work during VM's bootstrapping. unsigned nb = 0; if (!is_static()) { nb = 4; @@ -263,8 +224,8 @@ unsigned Method::get_num_arg_bytes() } iter = advance_arg_iterator(iter); } - return nb; -} //Method::get_num_arg_bytes + _arguments_size = nb; +} // Method::get_num_arg_bytes @@ -780,7 +741,7 @@ void Method::_set_nop() Byte *bc = _byte_codes; Nop_Stack_State stack_state = NS_StackEmpty; if(verbose) { - printf("=========== nop[%d]: %s.%s%s\n", len, get_class()->name->bytes, get_name()->bytes, get_descriptor()->bytes); + printf("=========== nop[%d]: %s.%s%s\n", len, get_class()->get_name()->bytes, get_name()->bytes, get_descriptor()->bytes); } for (unsigned idx = 0; idx < len; idx++) { Byte b = bc[idx]; @@ -789,7 +750,7 @@ void Method::_set_nop() } if(b == 0xb1) { // return if(verbose) { - printf("+++++++ nop: %s.%s%s\n", get_class()->name->bytes, get_name()->bytes, get_descriptor()->bytes); + printf("+++++++ nop: %s.%s%s\n", get_class()->get_name()->bytes, get_name()->bytes, get_descriptor()->bytes); } _flags.is_nop = TRUE; return; @@ -830,7 +791,7 @@ void Method::_set_nop() return; } if(verbose) { - printf("invokespecial: %s.%s%s\n", callee->get_class()->name->bytes, callee->get_name()->bytes, callee->get_descriptor()->bytes); + printf("invokespecial: %s.%s%s\n", callee->get_class()->get_name()->bytes, callee->get_name()->bytes, callee->get_descriptor()->bytes); } if(!callee->is_nop()) { return; @@ -840,7 +801,7 @@ void Method::_set_nop() return; } if(verbose) { - printf("invokespecial nop: %s.%s%s\n", callee->get_class()->name->bytes, callee->get_name()->bytes, callee->get_descriptor()->bytes); + printf("invokespecial nop: %s.%s%s\n", callee->get_class()->get_name()->bytes, callee->get_name()->bytes, callee->get_descriptor()->bytes); } } stack_state = NS_StackEmpty; 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 513688e..8e34da7 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 @@ -30,6 +30,8 @@ #include "lock_manager.h" #include "nogc.h" #include "vm_stats.h" +#include "cci.h" +#include "class_member.h" #include "method_lookup.h" @@ -268,7 +270,7 @@ void Method_Lookup_Table::print_stats() num++; printf("%8" FMT64 "u :::: %s.%s%s\n", m->num_throws, - m->get_method()->get_class()->name->bytes, + m->get_method()->get_class()->get_name()->bytes, m->get_method()->get_name()->bytes, m->get_method()->get_descriptor()->bytes); } @@ -285,7 +287,7 @@ void Method_Lookup_Table::print_stats() num++; printf("%8" FMT64 "u :::: %s.%s%s\n", m->num_catches, - m->get_method()->get_class()->name->bytes, + m->get_method()->get_class()->get_name()->bytes, m->get_method()->get_name()->bytes, m->get_method()->get_descriptor()->bytes); } @@ -302,7 +304,7 @@ void Method_Lookup_Table::print_stats() num++; printf("%8" FMT64 "u :::: %s.%s%s\n", m->num_unwind_java_frames_gc, - m->get_method()->get_class()->name->bytes, + m->get_method()->get_class()->get_name()->bytes, m->get_method()->get_name()->bytes, m->get_method()->get_descriptor()->bytes); } @@ -317,7 +319,7 @@ void Method_Lookup_Table::print_stats() num++; printf("%8" FMT64 "u :::: %s.%s%s\n", m->num_unwind_java_frames_non_gc, - m->get_method()->get_class()->name->bytes, + m->get_method()->get_class()->get_name()->bytes, m->get_method()->get_name()->bytes, m->get_method()->get_descriptor()->bytes); } diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/type.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/type.cpp index a0da049..eda8ef8 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/class_support/type.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/class_support/type.cpp @@ -163,12 +163,12 @@ TypeDesc* type_desc_create_from_class(Cl default: ABORT("Unexpected data type"); } - td = new TypeDesc(k, NULL, NULL, NULL, c->class_loader, c); + td = new TypeDesc(k, NULL, NULL, NULL, c->get_class_loader(), c); } else if (class_is_array(c)) { - td = new TypeDesc(K_Vector, NULL, NULL, NULL, c->class_loader, c); + td = new TypeDesc(K_Vector, NULL, NULL, NULL, c->get_class_loader(), c); } else { Kind k = K_Object; - td = new TypeDesc(k, NULL, NULL, NULL, c->class_loader, c); + td = new TypeDesc(k, NULL, NULL, NULL, c->get_class_loader(), c); } assert(td); return td; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp index b151622..aa92a89 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 "object_handles.h" #include "vm_arrays.h" #include "vm_strings.h" +#include "cci.h" bool exn_raised() @@ -406,7 +407,7 @@ inline void exn_jni_print_stack_trace(FI return; tmn_suspend_disable(); - const char *exceptionNameChars = exc->object->vt()->clss->name->bytes; + const char* exceptionNameChars = exc->object->vt()->clss->get_name()->bytes; tmn_suspend_enable(); const char *messageChars = GetStringUTFChars(jenv, message, false); fprintf(f, "\n%s : %s\n", exceptionNameChars, messageChars); @@ -625,7 +626,7 @@ void print_uncaught_exception_message(FI tmn_suspend_disable(); fprintf(f, "** During %s uncaught exception: %s\n", context_message, - exc->object->vt()->clss->name->bytes); + exc->object->vt()->clss->get_name()->bytes); tmn_suspend_enable(); exn_print_stack_trace(f, exc); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_impl.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_impl.cpp index 949542e..3b6faaf 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_impl.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_impl.cpp @@ -55,7 +55,7 @@ Method* lookup_exc_constructor(Class * e // Get the method for the constructor String *init_name = env->Init_String; String *init_descr = env->string_pool.lookup(signature); - Method *exc_init = class_lookup_method(exc_class, init_name, init_descr); + Method *exc_init = exc_class->lookup_method(init_name, init_descr); return exc_init; } 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 1e291e1..a84211c 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 "stack_iterator.h" #include "vm_stats.h" #include "jvmti_break_intf.h" +#include "cci.h" #ifdef _IPF_ #elif defined _EM64T_ @@ -193,7 +194,7 @@ static void exn_propagate_exception( exn_class = (*exn_obj)->vt()->clss; #ifdef VM_STATS - ((Class *) exn_class)->num_throws++; + exn_class->class_thrown(); VM_Statistics::get_vm_stats().num_exceptions++; #endif // VM_STATS @@ -527,7 +528,8 @@ NativeCodePtr exn_get_rth_throw() if (VM_Global_State::loader_env->compress_references) cs = lil_parse_onto_end(cs, "jc i0=%0i:ref,%n;" - "o0=i0;" "j %o;" ":%g;" "o0=0:ref;" ":%g;", Class::heap_base); + "o0=i0;" "j %o;" ":%g;" "o0=0:ref;" ":%g;", + VM_Global_State::loader_env->heap_base); else cs = lil_parse_onto_end(cs, "o0=i0;"); assert(cs); 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 e8facb4..6f9a33b 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..aafd70b 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 @@ -29,7 +29,9 @@ #include "vm_stats.h" #include "m2n.h" #include "open/vm_util.h" +#include "open/gc.h" #include "finalize.h" +#include "cci.h" static void vm_enumerate_interned_strings() @@ -82,24 +84,22 @@ vm_enumerate_static_fields() assert(*ppc); Class* c = jclass_to_struct_Class((jclass)ppc); - if (c->p_error) { + if(c->in_error()) { vm_enumerate_root_reference( - (void**)&c->p_error ,FALSE); + (void**)c->get_error_cause() ,FALSE); } vm_enumerate_root_reference((void**)ppc, FALSE); - Const_Pool* cp = c->m_failedResolution; + ConstPoolEntry* cp = c->get_constant_pool().get_error_chain(); while(cp) { vm_enumerate_root_reference((void**)(&(cp->error.cause)), FALSE); cp = cp->error.next; } // Finally enumerate the static fields of the class - unsigned n_fields = c->n_fields; - if((c->state == ST_Prepared) - || (c->state == ST_Initializing) - || (c->state == ST_Initialized)) { + unsigned n_fields = c->get_number_of_fields(); + if(c->is_at_least_prepared()) { // Class has been prepared, so we can iterate over all its fields. for(unsigned i = 0; i < n_fields; i++) { - Field *f = &c->fields[i]; + Field* f = c->get_field(i); if(f->is_static()) { char desc0 = f->get_descriptor()->bytes[0]; if(desc0 == 'L' || desc0 == '[') { @@ -136,9 +136,10 @@ vm_enumerate_root_reference(void **ref, ManagedObject **p_obj = (ManagedObject **)ref; ManagedObject* obj = *p_obj; assert(obj != NULL); // See the comment at the top of the procedure. - if ((void *)obj != Class::heap_base) { - assert(((POINTER_SIZE_INT)Class::heap_base <= (POINTER_SIZE_INT)obj) && ((POINTER_SIZE_INT)obj <= (POINTER_SIZE_INT)Class::heap_end)); - (obj->vt())->clss->name->bytes; + if ((void *)obj != VM_Global_State::loader_env->heap_base) { + assert(((POINTER_SIZE_INT)VM_Global_State::loader_env->heap_base <= (POINTER_SIZE_INT)obj) + && ((POINTER_SIZE_INT)obj <= (POINTER_SIZE_INT)VM_Global_State::loader_env->heap_end)); + (obj->vt())->clss->get_name()->bytes; } } #endif // _DEBUG @@ -161,11 +162,12 @@ VMEXPORT void vm_enumerate_compressed_ro COMPRESSED_REFERENCE compressed_ref = *ref; ManagedObject* obj = (ManagedObject *)uncompress_compressed_reference(compressed_ref); bool is_null = (compressed_ref == 0); - bool is_in_heap = (((POINTER_SIZE_INT)Class::heap_base <= (POINTER_SIZE_INT)obj) && ((POINTER_SIZE_INT)obj <= (POINTER_SIZE_INT)Class::heap_end)); + bool is_in_heap = (((POINTER_SIZE_INT)VM_Global_State::loader_env->heap_base <= (POINTER_SIZE_INT)obj) + && ((POINTER_SIZE_INT)obj <= (POINTER_SIZE_INT)VM_Global_State::loader_env->heap_end)); if (is_null || is_in_heap) { // Make sure the reference is valid. if (!is_null) { - (obj->vt())->clss->name->bytes; + (obj->vt())->clss->get_name()->bytes; } } else { ASSERT(0, "Bad slot pointer"); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp index c8e076b..f65fe6c 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp @@ -74,27 +74,8 @@ bool ManagedObject::_compressed = false; // begin Class ///////////////////////////////////////////////////////////////// -Field* class_resolve_field(Class* clss, unsigned cp_index) -{ - Compilation_Handle ch; - ch.env = VM_Global_State::loader_env; - ch.jit = NULL; - Field_Handle fh = resolve_field(&ch, (Class_Handle)clss, cp_index); - return (Field *)fh; -} - -Method *class_resolve_method(Class *clss, unsigned cp_index) -{ - Compilation_Handle ch; - ch.env = VM_Global_State::loader_env; - ch.jit = NULL; - Method_Handle fh = resolve_method(&ch, (Class_Handle)clss, cp_index); - return (Method *)fh; -} //class_resolve_static_field - - -Field *class_resolve_nonstatic_field(Class *clss, unsigned cp_index) +Field* class_resolve_nonstatic_field(Class* clss, unsigned cp_index) { Compilation_Handle ch; ch.env = VM_Global_State::loader_env; @@ -103,55 +84,8 @@ Field *class_resolve_nonstatic_field(Cla if(!fh || field_is_static(fh)) return NULL; return fh; -} //class_resolve_static_field - - -Class *class_resolve_class(Class *clss, unsigned cp_index) -{ - Compilation_Handle ch; - ch.env = VM_Global_State::loader_env; - ch.jit = NULL; - return resolve_class(&ch, clss, cp_index); -} //class_resolve_class - - - - -// A run-time error occurs if called for an index which does not represent -// 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)) { - case CONSTANT_String: - return JAVA_TYPE_STRING; - case CONSTANT_Integer: - return JAVA_TYPE_INT; - case CONSTANT_Float: - return JAVA_TYPE_FLOAT; - case CONSTANT_Long: - return JAVA_TYPE_LONG; - case CONSTANT_Double: - return JAVA_TYPE_DOUBLE; - case CONSTANT_Class: - return JAVA_TYPE_CLASS; - default: - DIE("non-constant type is requested from constant pool : " << cp_tag(cp, cp_index)); - } - return JAVA_TYPE_INVALID; -} //class_get_cp_const_type - - - -// 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_Pool *cp = clss->const_pool; - assert(cp_tag(cp, cp_index) != CONSTANT_String); +} // class_resolve_nonstatic_field - return (void *)(cp + cp_index); -} //class_get_addr_of_constant ///////////////////////////////////////////////////////////////// // end Class diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp index bd80b82..18fedd1 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp @@ -71,7 +71,7 @@ void vm_uninitialize_critical_sections() delete p_method_call_lock; } -Class * preload_class(Global_Env * vm_env, const char * classname) { +Class* preload_class(Global_Env * vm_env, const char * classname) { String * s = vm_env->string_pool.lookup(classname); return vm_env->LoadCoreClass(s); } @@ -84,13 +84,10 @@ static Class * preload_primitive_class(G String * s = vm_env->string_pool.lookup(classname); ClassLoader * cl = vm_env->bootstrap_class_loader; Class *clss = cl->NewClass(vm_env, s); - clss->is_primitive = 1; - clss->class_loader = cl; - clss->access_flags = ACC_ABSTRACT | ACC_FINAL | ACC_PUBLIC; - clss->is_verified = 2; + clss->setup_as_primitive(cl); cl->InsertClass(clss); - class_prepare(vm_env, clss); + clss->prepare(vm_env); return clss; } @@ -119,8 +116,8 @@ static jint lib_dependent_opts() { // and set its "vm_class" field to point back to that structure. void create_instance_for_class(Global_Env * vm_env, Class *clss) { - clss->class_loader->AllocateAndReportInstance(vm_env, clss); -} + clss->get_class_loader()->AllocateAndReportInstance(vm_env, clss); +} //create_instance_for_class /** * Loads DLLs. @@ -272,6 +269,9 @@ static void bootstrap_initial_java_class vm_env->StartVMBootstrap(); vm_env->JavaLangObject_Class = preload_class(vm_env, vm_env->JavaLangObject_String); vm_env->java_io_Serializable_Class = preload_class(vm_env, vm_env->Serializable_String); + Class* AnnotatedElement_Class = preload_class(vm_env, "java/lang/reflect/AnnotatedElement"); + Class* GenericDeclaration_Class = preload_class(vm_env, "java/lang/reflect/GenericDeclaration"); + Class* Type_Class = preload_class(vm_env, "java/lang/reflect/Type"); vm_env->JavaLangClass_Class = preload_class(vm_env, vm_env->JavaLangClass_String); vm_env->FinishVMBootstrap(); @@ -289,15 +289,10 @@ static void bootstrap_initial_java_class } jvmti_send_class_load_event(vm_env, booted); jvmti_send_class_prepare_event(booted); - } + } -#ifdef VM_STATS - // Account for the classes loaded before vm_env->JavaLangObject_Class is set. - vm_env->JavaLangObject_Class->num_allocations += num; - vm_env->JavaLangObject_Class->num_bytes_allocated += (num * vm_env->JavaLangClass_Class->instance_data_size); -#endif //VM_STATS TRACE("bootstrapping initial java classes complete"); -} +} // bootstrap_initial_java_classes /** * Loads hot classes. @@ -327,24 +322,12 @@ static jint preload_classes(Global_Env * vm_env->ArrayOfFloat_Class = preload_class(vm_env, "[F"); vm_env->ArrayOfDouble_Class = preload_class(vm_env, "[D"); -#ifndef POINTER64 - // In IA32, Arrays of Doubles need to be eight byte aligned to improve - // performance. In IPF all objects (arrays, class data structures, heap objects) - // get aligned on eight byte boundaries. So, this special code is not needed. - vm_env->ArrayOfDouble_Class->alignment = ((GC_OBJECT_ALIGNMENT < 8) ? 8: GC_OBJECT_ALIGNMENT); - // The alignment is either 4 or it is a multiple of 8. Things like 12 aren't allowed. - assert ((GC_OBJECT_ALIGNMENT == 4) || ((GC_OBJECT_ALIGNMENT % 8) == 0)); - // align doubles on 8, clear alignment field and put in 8. - set_prop_alignment_mask(vm_env->ArrayOfDouble_Class, 8); - // Set high bit in size so that gc knows there are constraints -#endif - TRACE2("init", "preloading string class"); vm_env->JavaLangString_Class = preload_class(vm_env, vm_env->JavaLangString_String); vm_env->strings_are_compressed = (class_lookup_field_recursive(vm_env->JavaLangString_Class, "bvalue", "[B") != NULL); - vm_env->JavaLangString_VTable = vm_env->JavaLangString_Class->vtable; - vm_env->JavaLangString_allocation_handle = vm_env->JavaLangString_Class->allocation_handle; + vm_env->JavaLangString_VTable = vm_env->JavaLangString_Class->get_vtable(); + vm_env->JavaLangString_allocation_handle = vm_env->JavaLangString_Class->get_allocation_handle(); TRACE2("init", "preloading exceptions"); vm_env->java_lang_Throwable_Class = @@ -484,7 +467,7 @@ static jint vm_create_jthread(jthread * assert(!hythread_is_suspend_enabled()); vm_env = jni_get_vm_env(jni_env); - + thread_class = vm_env->java_lang_Thread_Class; class_initialize(thread_class); if (exn_raised()) return TM_ERROR_INTERNAL; @@ -500,7 +483,8 @@ static jint vm_create_jthread(jthread * if (constructor == NULL) { // Initialize created thread object. - constructor = class_lookup_method_init(thread_class, descriptor); + constructor = thread_class->lookup_method(vm_env->Init_String, + vm_env->string_pool.lookup(descriptor)); if (constructor == NULL) { TRACE("Failed to find thread's constructor " << descriptor << " , exception = " << exn_get()); return JNI_ERR; @@ -642,9 +626,9 @@ int vm_init1(JavaVM_Internal * java_vm, gc_init(); // TODO: find another way to initialize the following. - Class::heap_base = (Byte *)gc_heap_base_address(); - Class::heap_end = (Byte *)gc_heap_ceiling_address(); - Class::managed_null = (vm_references_are_compressed() ? Class::heap_base : NULL); + vm_env->heap_base = (Byte *)gc_heap_base_address(); + vm_env->heap_end = (Byte *)gc_heap_ceiling_address(); + vm_env->managed_null = (vm_references_are_compressed() ? vm_env->heap_base : NULL); // 20030404 This handshaking protocol isn't quite correct. It doesn't // work at the moment because JIT has not yet been modified to support @@ -685,7 +669,6 @@ int vm_init1(JavaVM_Internal * java_vm, vm_env->popFrameException->object = class_alloc_new_object(vm_env->java_lang_Error_Class); - // Precompile StackOverflowError. class_alloc_new_object_and_run_default_constructor(vm_env->java_lang_StackOverflowError_Class); // Precompile ThreadDeathError. @@ -694,13 +677,13 @@ int vm_init1(JavaVM_Internal * java_vm, hythread_suspend_enable(); // Mark j.l.Throwable() constructor as a side effects free. - Method * m = class_lookup_method(vm_env->java_lang_Throwable_Class, + Method * m = vm_env->java_lang_Throwable_Class->lookup_method( vm_env->Init_String, vm_env->VoidVoidDescriptor_String); assert(m); m->set_side_effects(MSE_False); // Mark j.l.Throwable(j.l.String) constructor as a side effects free. - m = class_lookup_method(vm_env->java_lang_Throwable_Class, + m = vm_env->java_lang_Throwable_Class->lookup_method( vm_env->Init_String, vm_env->FromStringConstructorDescriptor_String); assert(m); m->set_side_effects(MSE_False); @@ -709,7 +692,7 @@ int vm_init1(JavaVM_Internal * java_vm, global_object_handles_init(jni_env); Class * aoObjectArray = preload_class(vm_env, "[Ljava/lang/Object;"); - cached_object_array_vtable_ptr = aoObjectArray->vtable; + cached_object_array_vtable_ptr = aoObjectArray->get_vtable(); // the following is required for creating exceptions preload_class(vm_env, "[Ljava/lang/VMClassRegistry;"); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_shutdown.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_shutdown.cpp index 6571e80..c5efbe1 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_shutdown.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_shutdown.cpp @@ -23,6 +23,7 @@ #include "open/hythread.h" #include "open/jthread.h" +#include "open/gc.h" #include "jni.h" #include "jni_direct.h" diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp index b204b6f..a3d9eb0 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp @@ -38,6 +38,8 @@ #include "stack_iterator.h" #include "interpreter.h" #include "jvmti_break_intf.h" +#include "cci.h" +#include "open/gc.h" #include "vm_stats.h" #include "dump.h" @@ -52,11 +54,23 @@ Global_Env* compile_handle_to_environmen } +int get_index_of_jit(JIT *jit) +{ + int idx; + JIT **j; + for (j = jit_compilers, idx = 0; *j; j++, idx++) { + if (*j == jit) { + return idx; + } + } + return -999; +} //get_index_of_jit + //////////////////////////////////////////////////////////////////////// // begin Forward declarations // A MethodInstrumentationProc that records calls in a call graph weighted by the call counts between methods. -void count_method_calls(CodeChunkInfo *callee); +void count_method_calls(CodeChunkInfo* callee); // end Forward declarations //////////////////////////////////////////////////////////////////////// @@ -75,7 +89,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 +99,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 +108,37 @@ CodeChunkInfo::CodeChunkInfo() #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 +193,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 +209,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 +220,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 +231,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 +239,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 +252,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 //////////////////////////////////////////////////////////////////////// @@ -292,19 +305,6 @@ void vm_initialize_all_jits() } //vm_initialize_all_jits -int get_index_of_jit(JIT *jit) -{ - int idx; - JIT **j; - for (j = jit_compilers, idx = 0; *j; j++, idx++) { - if (*j == jit) { - return idx; - } - } - return -999; -} //get_index_of_jit - - // end JIT management //////////////////////////////////////////////////////////////////////// @@ -370,10 +370,10 @@ NativeCodePtr compile_create_lil_jni_stu //***** Part 2: Initialise object handles if (is_static) { - void *jlc = &((Class*)clss)->class_handle; + void *jlc = clss->get_class_handle(); cs = lil_parse_onto_end(cs, - "ld l1,[%0i:pint];" - "ld l1,[l1+0:ref];", + //"ld l1,[%0i:pint];" + "ld l1,[%0i:ref];", jlc); assert(cs); cs = oh_gen_init_handle(cs, "l0", 0, "l1", false); @@ -447,7 +447,7 @@ NativeCodePtr compile_create_lil_jni_stu ":%g;" "o%4i=0;" ":%g;", - i, Class::managed_null, + i, VM_Global_State::loader_env->managed_null, arg_base+i, handle_offset, arg_base+i); } else { cs = lil_parse_onto_end(cs, @@ -535,7 +535,7 @@ NativeCodePtr compile_create_lil_jni_stu "jc l1!=0,done_translating_ret;" "l1=%0i:ref;" ":done_translating_ret;", - Class::managed_null); + VM_Global_State::loader_env->managed_null); } assert(cs); } @@ -596,15 +596,16 @@ NativeCodePtr compile_create_lil_jni_stu // begin Support for stub override code sequences -static int get_override_index(Method *method) +static int get_override_index(Method* method) { - const char *clss_name = &(method->get_class()->name->bytes[0]); - const char *meth_name = method->get_name()->bytes; - const char *meth_desc = method->get_descriptor()->bytes; + const char* clss_name = method->get_class()->get_name()->bytes; + const char* meth_name = method->get_name()->bytes; + const char* meth_desc = method->get_descriptor()->bytes; for (int i = 0; i < sizeof_stub_override_entries; i++) { - if ((strcmp(clss_name, stub_override_entries[i].class_name) == 0) && - (strcmp(meth_name, stub_override_entries[i].method_name) == 0) && - (strcmp(meth_desc, stub_override_entries[i].descriptor) == 0)) { + if ((strcmp(clss_name, stub_override_entries[i].class_name) == 0) + && (strcmp(meth_name, stub_override_entries[i].method_name) == 0) + && (strcmp(meth_desc, stub_override_entries[i].descriptor) == 0)) + { return i; } } @@ -658,19 +659,19 @@ static JIT_Result compile_prepare_native Class* cl = method->get_class(); NativeStubOverride nso = nso_find_method_override(VM_Global_State::loader_env, - cl->name, method->get_name(), + cl->get_name(), method->get_name(), method->get_descriptor()); NativeCodePtr stub = compile_create_jni_stub(method, func, nso); - if (!stub) return JIT_FAILURE; - cl->m_lock->_lock(); + + method->lock(); method->set_code_addr(stub); - cl->m_lock->_unlock(); + method->unlock(); return JIT_SUCCESS; -} //compile_prepare_native_method +} // compile_prepare_native_method JIT_Result compile_do_compilation_jit(Method* method, JIT* jit) @@ -796,10 +797,13 @@ static jthrowable compile_make_exception jthrowable old_exc = exn_get(); exn_clear(); - const char* c = method->get_class()->name->bytes; + const char* c = method->get_class()->get_name()->bytes; const char* m = method->get_name()->bytes; const char* d = method->get_descriptor()->bytes; - size_t sz = 25+strlen(c)+strlen(m)+strlen(d); + size_t sz = 25 + + method->get_class()->get_name()->len + + method->get_name()->len + + method->get_descriptor()->len; char* msg_raw = (char*)STD_MALLOC(sz); assert(msg_raw); sprintf(msg_raw, "Error compiling method %s.%s%s", c, m, d); 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 b60b8a9..6df06e2 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 @@ using namespace std; #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,19 +160,19 @@ 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->get_constant_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(); Class *objClass = NULL; BEGIN_RAISE_AREA; - objClass = class_resolve_class(c, cp_index); + objClass = c->_resolve_class(VM_Global_State::loader_env, cp_index); END_RAISE_AREA; hythread_suspend_disable(); @@ -253,22 +256,25 @@ static LilCodeStub* rth_gen_lil_type_tes // Null check if (null!=RTTN_NoNullCheck) { if (null==RTTN_NullMember) { - cs = lil_parse_onto_end(cs, "jc i0!=%0i:ref,null_check_faild;", Class::managed_null); + cs = lil_parse_onto_end(cs, "jc i0!=%0i:ref,null_check_faild;", + VM_Global_State::loader_env->managed_null); cs = lil_parse_onto_end(cs, (res==RTTR_ReturnOutcome ? "r=1:g4; ret;" : "r=i0; ret;")); cs = lil_parse_onto_end(cs, ":null_check_faild;"); } else { - cs = lil_parse_onto_end(cs, "jc i0=%0i:ref,failed;", Class::managed_null); + cs = lil_parse_onto_end(cs, "jc i0=%0i:ref,failed;", + VM_Global_State::loader_env->managed_null); } assert(cs); } // 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 size_t is_fast_off = Class::get_offset_of_fast_instanceof_flag(dummy); + const size_t depth_off = Class::get_offset_of_depth(dummy); const POINTER_SIZE_INT supertable_off = (POINTER_SIZE_INT)&((VTable*)NULL)->superclasses; bool do_slow = true; if (type) { - if (type->is_suitable_for_fast_instanceof) { + if(type->get_fast_instanceof_flag()) { cs = lil_parse_onto_end(cs, vm_vtable_pointers_are_compressed() ? "ld l0,[i0+%0i:g4],zx;" : "ld l0,[i0+%0i:pint];", vtable_off); @@ -276,7 +282,7 @@ static LilCodeStub* rth_gen_lil_type_tes cs = lil_parse_onto_end(cs, "ld l0,[l0+%1i:pint];" "jc l0!=%2i,failed;", - vtable_add+supertable_off+sizeof(Class*)*(type->depth-1), type); + vtable_add+supertable_off+sizeof(Class*)*(type->get_depth()-1), type); do_slow = false; assert(cs); } @@ -304,7 +310,7 @@ static LilCodeStub* rth_gen_lil_type_tes //*** Slow sequence const POINTER_SIZE_INT clss_off = (POINTER_SIZE_INT)&((VTable*)NULL)->clss; - Boolean (*p_subclass)(Class_Handle, Class_Handle) = class_is_subclass; + Boolean (*p_subclass)(Class_Handle, Class_Handle) = class_is_subtype; if (do_slow) { cs = lil_parse_onto_end(cs, ":slowpath;" @@ -348,13 +354,13 @@ static void rth_type_test_update_stats(V VM_Statistics::get_vm_stats().num_type_checks ++; if (sub->clss == super) VM_Statistics::get_vm_stats().num_type_checks_equal_type ++; - if (super->is_suitable_for_fast_instanceof) + if (super->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_type_checks_fast_decision ++; - else if (super->is_array) + else if (super->is_array()) VM_Statistics::get_vm_stats().num_type_checks_super_is_array ++; - else if (class_is_interface(super)) + else if (super->is_interface()) VM_Statistics::get_vm_stats().num_type_checks_super_is_interface ++; - else if (super->depth >= vm_max_fast_instanceof_depth()) + else if (super->get_depth() >= vm_max_fast_instanceof_depth()) VM_Statistics::get_vm_stats().num_type_checks_super_is_too_deep ++; } @@ -362,12 +368,12 @@ static void rth_type_test_update_stats(V static void rth_update_checkcast_stats(ManagedObject* o, Class* super) { VM_Statistics::get_vm_stats().num_checkcast ++; - if (o == (ManagedObject*)Class::managed_null) { + if (o == (ManagedObject*)VM_Global_State::loader_env->managed_null) { VM_Statistics::get_vm_stats().num_checkcast_null++; } else { if (o->vt()->clss == super) VM_Statistics::get_vm_stats().num_checkcast_equal_type ++; - if (super->is_suitable_for_fast_instanceof) + if (super->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_checkcast_fast_decision ++; rth_type_test_update_stats(o->vt(), super); } @@ -377,13 +383,13 @@ static void rth_update_checkcast_stats(M static void rth_update_instanceof_stats(ManagedObject* o, Class* super) { VM_Statistics::get_vm_stats().num_instanceof++; - super->num_instanceof_slow++; - if (o == (ManagedObject*)Class::managed_null) { + super->instanceof_slow_path_taken(); + if (o == (ManagedObject*)VM_Global_State::loader_env->managed_null) { VM_Statistics::get_vm_stats().num_instanceof_null++; } else { if (o->vt()->clss == super) VM_Statistics::get_vm_stats().num_instanceof_equal_type ++; - if (super->is_suitable_for_fast_instanceof) + if (super->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_instanceof_fast_decision ++; rth_type_test_update_stats(o->vt(), super); } @@ -400,7 +406,9 @@ static NativeCodePtr rth_get_lil_checkca #ifdef VM_STATS if (dyn_count) { - cs = lil_parse_onto_end(cs, "inc [%0i:pint]; in2out platform:void; call %1i;", dyn_count, rth_update_checkcast_stats); + cs = lil_parse_onto_end(cs, + "inc [%0i:pint]; in2out platform:void; call %1i;", + dyn_count, rth_update_checkcast_stats); assert(cs); } #endif @@ -453,7 +461,7 @@ static Class* rth_aastore(ManagedObject* #endif // VM_STATS Global_Env *env = VM_Global_State::loader_env; - ManagedObject* null_ref = (ManagedObject*)Class::managed_null; + ManagedObject* null_ref = (ManagedObject*)VM_Global_State::loader_env->managed_null; if (array == null_ref) { return env->java_lang_NullPointerException_Class; } else if (((uint32)idx) >= (uint32)get_vector_length(array)) { @@ -462,17 +470,17 @@ static Class* rth_aastore(ManagedObject* assert(get_vector_vtable(array)); Class* array_class = get_vector_vtable(array)->clss; assert(array_class); - assert(array_class->is_array); + assert(array_class->is_array()); #ifdef VM_STATS VTable* vt = get_vector_vtable(array); if (vt == cached_object_array_vtable_ptr) VM_Statistics::get_vm_stats().num_aastore_test_object_array++; - if (elem->vt()->clss == array_class->array_element_class) + if (elem->vt()->clss == array_class->get_array_element_class()) VM_Statistics::get_vm_stats().num_aastore_equal_type ++; - if (array_class->array_element_class->is_suitable_for_fast_instanceof) + if (array_class->get_array_element_class()->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_aastore_fast_decision ++; #endif // VM_STATS - if (class_is_subtype_fast(elem->vt(), array_class->array_element_class)) { + if (class_is_subtype_fast(elem->vt(), array_class->get_array_element_class())) { STORE_REFERENCE((ManagedObject*)array, get_vector_element_address_ref(array, idx), (ManagedObject*)elem); } else { return env->java_lang_ArrayStoreException_Class; @@ -535,7 +543,7 @@ static bool rth_aastore_test(ManagedObje VM_Statistics::get_vm_stats().num_aastore_test++; #endif // VM_STATS - ManagedObject* null_ref = (ManagedObject*)Class::managed_null; + ManagedObject* null_ref = (ManagedObject*)VM_Global_State::loader_env->managed_null; if (array == null_ref) { return false; } @@ -556,15 +564,15 @@ static bool rth_aastore_test(ManagedObje Class* array_class = vt->clss; assert(array_class); - assert(array_class->is_array); + assert(array_class->is_array()); #ifdef VM_STATS - if (elem->vt()->clss == array_class->array_element_class) + if (elem->vt()->clss == array_class->get_array_element_class()) VM_Statistics::get_vm_stats().num_aastore_test_equal_type ++; - if (array_class->array_element_class->is_suitable_for_fast_instanceof) + if (array_class->get_array_element_class()->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_aastore_test_fast_decision ++; #endif // VM_STATS - return (class_is_subtype_fast(elem->vt(), array_class->array_element_class) ? true : false); + return (class_is_subtype_fast(elem->vt(), array_class->get_array_element_class()) ? true : false); } //rth_aastore_test static NativeCodePtr rth_get_lil_aastore_test(int * dyn_count) @@ -641,37 +649,8 @@ static NativeCodePtr rth_get_lil_throw_l // Or NULL if no such interface exists for obj static void* rth_get_interface_vtable(ManagedObject* obj, Class* iid) { - assert(obj && obj->vt()); - Class* clss = obj->vt()->clss; - assert(clss); - unsigned num_intfc = clss->n_intfc_table_entries; -#ifdef VM_STATS - VM_Statistics::get_vm_stats().num_invokeinterface_calls++; - switch(num_intfc) { - case 1: VM_Statistics::get_vm_stats().num_invokeinterface_calls_size_1++; break; - case 2: VM_Statistics::get_vm_stats().num_invokeinterface_calls_size_2++; break; - default: VM_Statistics::get_vm_stats().num_invokeinterface_calls_size_many++; break; - } - if(num_intfc > VM_Statistics::get_vm_stats().invokeinterface_calls_size_max) - VM_Statistics::get_vm_stats().invokeinterface_calls_size_max = num_intfc; -#endif - for(unsigned i = 0; i < num_intfc; i++) { - Class* intfc = clss->intfc_table_descriptors[i]; - if(intfc == iid) { -#ifdef VM_STATS - switch(i) { - case 0: VM_Statistics::get_vm_stats().num_invokeinterface_calls_searched_1++; break; - case 1: VM_Statistics::get_vm_stats().num_invokeinterface_calls_searched_2++; break; - default: VM_Statistics::get_vm_stats().num_invokeinterface_calls_searched_many++; break; - } - if(i > VM_Statistics::get_vm_stats().invokeinterface_calls_searched_max) - VM_Statistics::get_vm_stats().invokeinterface_calls_searched_max = i; -#endif - unsigned char **table = clss->vtable->intfc_table->entry[i].table; - return (void *)table; - } - } - return NULL; + assert(obj && obj->vt() && obj->vt()->clss); + return obj->vt()->clss->helper_get_interface_vtable(obj, iid); } // Get interface vtable helper @@ -698,7 +677,8 @@ static NativeCodePtr rth_get_lil_get_int ":null;" "r=0;" "ret;", - Class::managed_null, p_get_ivtable, lil_npc_to_fp(exn_get_rth_throw_incompatible_class_change_exception())); + VM_Global_State::loader_env->managed_null, p_get_ivtable, + lil_npc_to_fp(exn_get_rth_throw_incompatible_class_change_exception())); assert(cs && lil_is_valid(cs)); addr = LilCodeGenerator::get_platform()->compile(cs); @@ -718,10 +698,10 @@ static POINTER_SIZE_INT is_class_initial { #ifdef VM_STATS VM_Statistics::get_vm_stats().num_is_class_initialized++; - clss->num_class_init_checks++; + clss->initialization_checked(); #endif // VM_STATS assert(!hythread_is_suspend_enabled()); - return clss->state == ST_Initialized; + return clss->is_initialized(); } //is_class_initialized void vm_rt_class_initialize(Class *clss) @@ -2042,44 +2022,34 @@ ManagedObject* vm_rt_class_alloc_new_obj } -ManagedObject *class_alloc_new_object(Class *c) +ManagedObject* class_alloc_new_object(Class* c) { ASSERT_RAISE_AREA; assert(!hythread_is_suspend_enabled()); - //hythread_suspend_disable(); - assert(strcmp(c->name->bytes, "java/lang/Class")); -#ifdef VM_STATS - VM_Statistics::get_vm_stats().num_class_alloc_new_object++; - c->num_allocations++; - c->num_bytes_allocated += get_instance_data_size(c); -#endif //VM_STATS - ManagedObject* o = (ManagedObject *) - gc_alloc(c->instance_data_size, - c->allocation_handle, vm_get_gc_thread_local()); - if (!o) { + assert(strcmp(c->get_name()->bytes, "java/lang/Class")); + + ManagedObject* obj = c->allocate_instance(); + if(!obj) { exn_raise_object( VM_Global_State::loader_env->java_lang_OutOfMemoryError); - //hythread_suspend_enable(); - return 0; // whether this return is reached or not is solved via is_unwindable state + return NULL; // whether this return is reached or not is solved via is_unwindable state } - //hythread_suspend_enable(); - return o; -} //class_alloc_new_object + return obj; +} // class_alloc_new_object ManagedObject *class_alloc_new_object_using_vtable(VTable *vtable) { ASSERT_RAISE_AREA; assert(!hythread_is_suspend_enabled()); - assert(strcmp(vtable->clss->name->bytes, "java/lang/Class")); + assert(strcmp(vtable->clss->get_name()->bytes, "java/lang/Class")); #ifdef VM_STATS VM_Statistics::get_vm_stats().num_class_alloc_new_object++; - vtable->clss->num_allocations++; - vtable->clss->num_bytes_allocated += vtable->allocated_size; + vtable->clss->instance_allocated(vtable->allocated_size); #endif //VM_STATS // From vm_types.h: this is the same as instance_data_size with the constraint bit cleared. - ManagedObject* o = (ManagedObject *) vm_alloc_and_report_ti( - vtable->allocated_size, vtable->clss->allocation_handle, - vm_get_gc_thread_local(), vtable->clss); + ManagedObject* o = (ManagedObject*) vm_alloc_and_report_ti( + vtable->allocated_size, vtable->clss->get_allocation_handle(), + vm_get_gc_thread_local(), vtable->clss); if (!o) { exn_raise_object( VM_Global_State::loader_env->java_lang_OutOfMemoryError); @@ -2088,48 +2058,42 @@ ManagedObject *class_alloc_new_object_us return o; } //class_alloc_new_object_using_vtable -ManagedObject *class_alloc_new_object_and_run_default_constructor(Class *clss) +ManagedObject* class_alloc_new_object_and_run_default_constructor(Class* clss) { return class_alloc_new_object_and_run_constructor(clss, 0, 0); -} //class_alloc_new_object_and_run_default_constructor +} // class_alloc_new_object_and_run_default_constructor -ManagedObject * -class_alloc_new_object_and_run_constructor(Class *clss, - Method *constructor, - uint8 *constructor_args) +ManagedObject* +class_alloc_new_object_and_run_constructor(Class* clss, + Method* constructor, + uint8* constructor_args) { ASSERT_RAISE_AREA; assert(!hythread_is_suspend_enabled()); - assert(strcmp(clss->name->bytes, "java/lang/Class")); - + assert(strcmp(clss->get_name()->bytes, "java/lang/Class")); + ObjectHandle obj = oh_allocate_local_handle(); - obj->object = (ManagedObject*) - gc_alloc(clss->instance_data_size, clss->allocation_handle, vm_get_gc_thread_local()); - if (!obj->object) { + obj->object = clss->allocate_instance(); + if(!obj->object) { exn_raise_object( VM_Global_State::loader_env->java_lang_OutOfMemoryError); - return 0; // should never be reached + return NULL; } -#ifdef VM_STATS - clss->num_allocations++; - clss->num_bytes_allocated += get_instance_data_size(clss); -#endif //VM_STATS if(!constructor) { // Get the default constructor - Global_Env *env = VM_Global_State::loader_env; - constructor = class_lookup_method(clss, env->Init_String, env->VoidVoidDescriptor_String); + Global_Env* env = VM_Global_State::loader_env; + constructor = clss->lookup_method(env->Init_String, env->VoidVoidDescriptor_String); assert(constructor); } - // Every argument is at least 4 bytes long int num_args_estimate = constructor->get_num_arg_bytes() / 4; - jvalue *args = (jvalue*)STD_MALLOC(num_args_estimate * sizeof(jvalue)); - args[0].l = (jobject) obj; + jvalue* args = (jvalue*)STD_MALLOC(num_args_estimate * sizeof(jvalue)); + args[0].l = (jobject)obj; int arg_num = 1; - uint8 *argp = constructor_args; + uint8* argp = constructor_args; Arg_List_Iterator iter = constructor->get_argument_list(); Java_Type typ; while((typ = curr_arg(iter)) != JAVA_TYPE_END) { @@ -2185,7 +2149,7 @@ class_alloc_new_object_and_run_construct } assert(!hythread_is_suspend_enabled()); vm_execute_java_method_array((jmethodID) constructor, 0, args); - + if (exn_raised()) { DIE("class constructor has thrown an exception"); } @@ -2208,17 +2172,17 @@ class_alloc_new_object_and_run_construct static void update_general_type_checking_stats(VTable *sub, Class *super) { #ifdef VM_STATS - VM_Statistics::get_vm_stats().num_type_checks ++; + VM_Statistics::get_vm_stats().num_type_checks++; if (sub->clss == super) - VM_Statistics::get_vm_stats().num_type_checks_equal_type ++; - if (super->is_suitable_for_fast_instanceof) - VM_Statistics::get_vm_stats().num_type_checks_fast_decision ++; - else if (super->is_array) - VM_Statistics::get_vm_stats().num_type_checks_super_is_array ++; - else if (class_is_interface(super)) - VM_Statistics::get_vm_stats().num_type_checks_super_is_interface ++; - else if (super->depth >= vm_max_fast_instanceof_depth()) - VM_Statistics::get_vm_stats().num_type_checks_super_is_too_deep ++; + VM_Statistics::get_vm_stats().num_type_checks_equal_type++; + if (super->get_fast_instanceof_flag()) + VM_Statistics::get_vm_stats().num_type_checks_fast_decision++; + else if (super->is_array()) + VM_Statistics::get_vm_stats().num_type_checks_super_is_array++; + else if (super->is_interface()) + VM_Statistics::get_vm_stats().num_type_checks_super_is_interface++; + else if (super->get_depth() >= vm_max_fast_instanceof_depth()) + VM_Statistics::get_vm_stats().num_type_checks_super_is_too_deep++; #endif // VM_STATS } @@ -2226,14 +2190,14 @@ void vm_instanceof_update_stats(ManagedO { #ifdef VM_STATS VM_Statistics::get_vm_stats().num_instanceof++; - super->num_instanceof_slow++; - if (obj == (ManagedObject *)Class::managed_null) + super->instanceof_slow_path_taken(); + if (obj == (ManagedObject*)VM_Global_State::loader_env->managed_null) VM_Statistics::get_vm_stats().num_instanceof_null++; else { if (obj->vt()->clss == super) VM_Statistics::get_vm_stats().num_instanceof_equal_type ++; - if (super->is_suitable_for_fast_instanceof) + if (super->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_instanceof_fast_decision ++; update_general_type_checking_stats(obj->vt(), super); } @@ -2244,13 +2208,13 @@ void vm_checkcast_update_stats(ManagedOb { #ifdef VM_STATS VM_Statistics::get_vm_stats().num_checkcast ++; - if (obj == (ManagedObject *)Class::managed_null) + if (obj == (ManagedObject*)VM_Global_State::loader_env->managed_null) VM_Statistics::get_vm_stats().num_checkcast_null++; else { if (obj->vt()->clss == super) VM_Statistics::get_vm_stats().num_checkcast_equal_type ++; - if (super->is_suitable_for_fast_instanceof) + if (super->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_checkcast_fast_decision ++; update_general_type_checking_stats(obj->vt(), super); } @@ -2385,12 +2349,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), + Class::get_offset_of_depth(dummy), sizeof(Class*), OFFSET(VTable, superclasses) - sizeof(Class*) + (vm_vtable_pointers_are_compressed() ? vm_get_vtable_base() : 0) ); @@ -2430,12 +2395,8 @@ static LilCodeStub* gen_lil_typecheck_fa // creates a LIL code stub for checkcast or instanceof // can be used by both IA32 and IPF code -LilCodeStub *gen_lil_typecheck_stub(bool is_checkcast) { - - // assert that some sizes are what we expect them to be - assert(SIZE(Class, is_suitable_for_fast_instanceof) == 4); - assert(SIZE(Class, depth) == 4); - +LilCodeStub *gen_lil_typecheck_stub(bool is_checkcast) +{ LilCodeStub* cs = NULL; // check if object address is NULL @@ -2446,7 +2407,7 @@ LilCodeStub *gen_lil_typecheck_stub(bool "jc i0!=%0i:ref,nonnull;" "r=i0;" // return obj if obj==NULL "ret;", - Class::managed_null); + VM_Global_State::loader_env->managed_null); } else { // args: ManagedObject *obj, Class *super; returns a boolean @@ -2455,9 +2416,10 @@ LilCodeStub *gen_lil_typecheck_stub(bool "jc i0!=%0i:ref,nonnull;" "r=0:g4;" // return FALSE if obj==NULL "ret;", - Class::managed_null); + VM_Global_State::loader_env->managed_null); } + Class* dummy = NULL; // check whether the fast or the slow path is appropriate cs = lil_parse_onto_end (cs, @@ -2466,7 +2428,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)); + Class::get_offset_of_fast_instanceof_flag(dummy)); // append the slow path right here cs = gen_lil_typecheck_slowpath(cs, is_checkcast); @@ -2506,7 +2468,7 @@ LilCodeStub *gen_lil_typecheck_stub_spec "jc i0!=%0i,nonnull;" "r=i0;" // return obj if obj==NULL "ret;", - Class::managed_null); + VM_Global_State::loader_env->managed_null); } else { // args: ManagedObject *obj, Class *super; returns a boolean @@ -2515,7 +2477,7 @@ LilCodeStub *gen_lil_typecheck_stub_spec "jc i0!=%0i,nonnull;" "r=0:g4;" // return FALSE if obj==NULL "ret;", - Class::managed_null); + VM_Global_State::loader_env->managed_null); } /* fast case; check whether @@ -2550,7 +2512,7 @@ LilCodeStub *gen_lil_typecheck_stub_spec "ld l1, [l0 + %0i: ref];" "jc l1 != %1i, failed;", OFFSET(VTable, superclasses) + (vm_vtable_pointers_are_compressed() ? vm_get_vtable_base() : 0) - + sizeof(Class*) * (superclass->depth-1), + + sizeof(Class*)*(superclass->get_depth()-1), (POINTER_SIZE_INT) superclass); if (is_checkcast) { @@ -2595,7 +2557,7 @@ void vm_aastore_test_update_stats(Manage { #ifdef VM_STATS VM_Statistics::get_vm_stats().num_aastore_test++; - if (elem == (ManagedObject *)Class::managed_null) + if(elem == (ManagedObject*)VM_Global_State::loader_env->managed_null) { VM_Statistics::get_vm_stats().num_aastore_test_null ++; return; @@ -2607,43 +2569,24 @@ void vm_aastore_test_update_stats(Manage return; } Class *array_class = vt->clss; - if (elem->vt()->clss == array_class->array_element_class) + if (elem->vt()->clss == array_class->get_array_element_class()) VM_Statistics::get_vm_stats().num_aastore_test_equal_type ++; - if (array_class->array_element_class->is_suitable_for_fast_instanceof) + if (array_class->get_array_element_class()->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_aastore_test_fast_decision ++; - update_general_type_checking_stats(elem->vt(), array_class->array_element_class); + update_general_type_checking_stats(elem->vt(), array_class->get_array_element_class()); #endif } -// Returns TRUE if "sub" represents a class that is a subtype of "super", -// according to the Java instanceof rules. -// "sub" must correspond to a non-interface type, since interfaces -// currently have a null vtable. -// -// No VM_STATS calculations are done here. Call class_is_subtype_fast -// if stats are needed. - static Boolean class_is_subtype_fast_no_stats(VTable *sub, Class *super) -{ - assert(sub != NULL); // Might happen if vtable of an interface class is accidentally taken. - if (super->is_suitable_for_fast_instanceof) - { - return sub->superclasses[super->depth-1] == super ? TRUE : FALSE; - } - return class_is_subtype(sub->clss, super); -} // class_is_subtype_fast_no_stats - - - Boolean class_is_subtype_fast(VTable *sub, Class *super) { update_general_type_checking_stats(sub, super); - return class_is_subtype_fast_no_stats(sub, super); + return sub->clss->is_instanceof(super); } // class_is_subtype_fast Boolean vm_instanceof_class(Class *s, Class *t) { - return class_is_subtype(s, t); + return s->is_instanceof(t); } @@ -2662,8 +2605,7 @@ Boolean class_is_subtype(Class *s, Class Class *object_class = env->JavaLangObject_Class; assert(object_class != NULL); - if(s->is_array) { - assert(*s->name->bytes == '['); + if(s->is_array()) { if (t == object_class) { return TRUE; } @@ -2673,26 +2615,25 @@ Boolean class_is_subtype(Class *s, Class if(t == env->java_lang_Cloneable_Class) { return TRUE; } - if(!t->is_array) { + if(!t->is_array()) { return FALSE; } - return class_is_subtype(s->array_element_class, t->array_element_class); + return class_is_subtype(s->get_array_element_class(), t->get_array_element_class()); } else { - assert(s->name->bytes[0] != '['); - if(!class_is_interface(t)) { - for(Class *c = s; c; c = c->super_class) { + if(!t->is_interface()) { + for(Class *c = s; c; c = c->get_super_class()) { if(c == t){ return TRUE; } } } else { - for(Class *c = s; c; c = c->super_class) { - unsigned n_intf = c->n_superinterfaces; + for(Class *c = s; c; c = c->get_super_class()) { + unsigned n_intf = c->get_number_of_superinterfaces(); for(unsigned i = 0; i < n_intf; i++) { - Class *intf = c->superinterfaces[i].clss; + Class* intf = c->get_superinterface(i); assert(intf); - assert(class_is_interface(intf)); + assert(intf->is_interface()); if(class_is_subtype(intf, t)) { return TRUE; } @@ -2714,10 +2655,10 @@ int __stdcall vm_instanceof(ManagedObjec #ifdef VM_STATS VM_Statistics::get_vm_stats().num_instanceof++; - c->num_instanceof_slow++; + c->instanceof_slow_path_taken(); #endif - ManagedObject *null_ref = (ManagedObject *)Class::managed_null; + ManagedObject *null_ref = (ManagedObject *)VM_Global_State::loader_env->managed_null; if (obj == null_ref) { #ifdef VM_STATS VM_Statistics::get_vm_stats().num_instanceof_null++; @@ -2728,7 +2669,7 @@ int __stdcall vm_instanceof(ManagedObjec #ifdef VM_STATS if (obj->vt()->clss == c) VM_Statistics::get_vm_stats().num_instanceof_equal_type ++; - if (c->is_suitable_for_fast_instanceof) + if (c->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_instanceof_fast_decision ++; #endif // VM_STATS return class_is_subtype_fast(obj->vt(), c); @@ -2753,7 +2694,7 @@ vm_aastore_test(ManagedObject *elem, VM_Statistics::get_vm_stats().num_aastore_test++; #endif // VM_STATS - ManagedObject *null_ref = (ManagedObject *)Class::managed_null; + ManagedObject *null_ref = (ManagedObject *)VM_Global_State::loader_env->managed_null; if (array == null_ref) { return 0; } @@ -2774,15 +2715,15 @@ vm_aastore_test(ManagedObject *elem, Class *array_class = vt->clss; assert(array_class); - assert(array_class->is_array); + assert(array_class->is_array()); #ifdef VM_STATS - if (elem->vt()->clss == array_class->array_element_class) + if (elem->vt()->clss == array_class->get_array_element_class()) VM_Statistics::get_vm_stats().num_aastore_test_equal_type ++; - if (array_class->array_element_class->is_suitable_for_fast_instanceof) + if (array_class->get_array_element_class()->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_aastore_test_fast_decision ++; #endif // VM_STATS - return class_is_subtype_fast(elem->vt(), array_class->array_element_class); + return class_is_subtype_fast(elem->vt(), array_class->get_array_element_class()); } //vm_aastore_test @@ -2796,7 +2737,7 @@ vm_rt_aastore(ManagedObject *elem, int i #endif // VM_STATS Global_Env *env = VM_Global_State::loader_env; - ManagedObject *null_ref = (ManagedObject *)Class::managed_null; + ManagedObject *null_ref = (ManagedObject *)VM_Global_State::loader_env->managed_null; if (array == null_ref) { return env->java_lang_NullPointerException_Class; } else if (((uint32)idx) >= (uint32)get_vector_length(array)) { @@ -2804,15 +2745,15 @@ vm_rt_aastore(ManagedObject *elem, int i } else if (elem != null_ref) { Class *array_class = get_vector_vtable(array)->clss; assert(array_class); - assert(array_class->is_array); + assert(array_class->is_array()); #ifdef VM_STATS // XXX - Should update VM_Statistics::get_vm_stats().num_aastore_object_array - if (elem->vt()->clss == array_class->array_element_class) + if (elem->vt()->clss == array_class->get_array_element_class()) VM_Statistics::get_vm_stats().num_aastore_equal_type ++; - if (array_class->array_element_class->is_suitable_for_fast_instanceof) + if (array_class->get_array_element_class()->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_aastore_fast_decision ++; #endif // VM_STATS - if (class_is_subtype_fast(elem->vt(), array_class->array_element_class)) { + if (class_is_subtype_fast(elem->vt(), array_class->get_array_element_class())) { STORE_REFERENCE((ManagedObject *)array, get_vector_element_address_ref(array, idx), (ManagedObject *)elem); } else { return env->java_lang_ArrayStoreException_Class; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jit/native_overrides.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jit/native_overrides.cpp index 214be94..d391c78 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jit/native_overrides.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jit/native_overrides.cpp @@ -127,15 +127,14 @@ LilCodeStub* nso_newinstance(LilCodeStub cs = lil_parse_onto_end(cs, "ld l0,[i0+%0i:pint];", (int)env->vm_class_offset); // Determine if this class supports fast allocation - size_t offset_is_fast_allocation_possible = (Byte *)&(env->Void_Class->is_fast_allocation_possible) - (Byte *)(env->Void_Class); - assert(sizeof(env->Void_Class->is_fast_allocation_possible) == 1); // else one byte ld below will fail + size_t offset_is_fast_allocation_possible = env->Void_Class->get_offset_of_fast_allocation_flag(); cs = lil_parse_onto_end(cs, "ld l1,[l0+%0i:g1];", (int)offset_is_fast_allocation_possible); cs = lil_parse_onto_end(cs, "jc l1=0,fallback;"); // Class supports fast allocation, now use frontier allocation technique size_t offset_gc_local = (Byte *)&(p_TLS_vmthread->_gc_private_information) - (Byte *)p_TLS_vmthread; - size_t offset_allocation_handle = (Byte *)&(env->Void_Class->allocation_handle) - (Byte *)(env->Void_Class); - size_t offset_instance_data_size = (Byte *)&(env->Void_Class->instance_data_size) - (Byte *)(env->Void_Class); + size_t offset_allocation_handle = env->Void_Class->get_offset_of_allocation_handle(); + size_t offset_instance_data_size = env->Void_Class->get_offset_of_instance_data_size(); current_offset += (unsigned) offset_gc_local; limit_offset += (unsigned) offset_gc_local; @@ -166,7 +165,7 @@ LilCodeStub* nso_newinstance(LilCodeStub static ManagedObject* get_class_ptr(ManagedObject* obj) { - return *(obj->vt()->clss->class_handle); + return *(obj->vt()->clss->get_class_handle()); } LilCodeStub* nso_get_class(LilCodeStub* cs, Method_Handle) @@ -336,7 +335,9 @@ LilCodeStub* nso_char_array_copy(LilCode "ld l0,[i2+%6i:pint];" "l1 = l1+i4;" "jc l0:g4ArrayOfChar_Class), + VM_Global_State::loader_env->managed_null, + VM_Global_State::loader_env->managed_null, + object_get_vtable_offset(), class_get_vtable(env->ArrayOfChar_Class), object_get_vtable_offset(), length_offset, length_offset); assert(cs); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni.cpp index 2a5e561..27366cd 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni.cpp @@ -48,7 +48,6 @@ #include "m2n.h" #include "nogc.h" #include "init.h" -#include "Verifier_stub.h" #include "jni_utils.h" #include "jit_runtime_support.h" #include "jvmti_direct.h" @@ -632,7 +631,7 @@ jclass JNICALL DefineClass(JNIEnv *jenv, bool ld_result; if(clss != NULL) - ld_result = class_verify(env, clss) && class_prepare(env, clss); + ld_result = clss->verify(env) && clss->prepare(env); if(clss && ld_result) { @@ -680,10 +679,10 @@ jclass JNICALL GetSuperclass(JNIEnv * UN assert(hythread_is_suspend_enabled()); Class* clss = jclass_to_struct_Class(clazz); if(clss) { - if(class_is_interface(clss)) { + if(clss->is_interface()) { return 0; } else { - Class *super_class = clss->super_class; + Class* super_class = clss->get_super_class(); if(super_class) { assert(hythread_is_suspend_enabled()); return struct_Class_to_jclass(super_class); @@ -922,8 +921,8 @@ jboolean JNICALL IsSameObject(JNIEnv * U ManagedObject *java_ref1 = h1->object; ManagedObject *java_ref2 = h2->object; - TRACE2("jni-same", "IsSameObject: Obj1 = " << java_ref1->vt()->clss->name->bytes << - " Obj2 = " << java_ref2->vt()->clss->name->bytes << + TRACE2("jni-same", "IsSameObject: Obj1 = " << java_ref1->vt()->clss->get_name()->bytes << + " Obj2 = " << java_ref2->vt()->clss->get_name()->bytes << " objects are " << ((java_ref1 == java_ref2) ? "same" : "different")); jboolean result = (jboolean)((java_ref1 == java_ref2) ? JNI_TRUE : JNI_FALSE); @@ -965,9 +964,9 @@ jobject JNICALL AllocObject(JNIEnv *env, assert(clazz); Class* clss = jclass_to_struct_Class(clazz); - if(class_is_interface(clss) || class_is_abstract(clss)) { + if(clss->is_interface() || clss->is_abstract()) { // Can't instantiate interfaces and abtract classes. - ThrowNew_Quick(env, "java/lang/InstantiationException", clss->name->bytes); + ThrowNew_Quick(env, "java/lang/InstantiationException", clss->get_name()->bytes); return 0; } @@ -1050,7 +1049,7 @@ jclass JNICALL GetObjectClass(JNIEnv * U assert(jlo); assert(jlo->vt()); Class *clss = jlo->vt()->clss; - TRACE2("jni", "GetObjectClass: class = " << clss->name->bytes); + TRACE2("jni", "GetObjectClass: class = " << clss->get_name()->bytes); new_handle->object= struct_Class_to_java_lang_Class(clss); tmn_suspend_enable(); //---------------------------------^ @@ -1072,7 +1071,7 @@ jboolean JNICALL IsInstanceOf(JNIEnv *en Class* clss = jclass_to_struct_Class(clazz); Class* obj_clss = jclass_to_struct_Class(obj_class); - Boolean isInstance = class_is_subtype_fast(obj_clss->vtable, clss); + Boolean isInstance = obj_clss->is_instanceof(clss); if(isInstance) { return JNI_TRUE; @@ -1271,11 +1270,11 @@ VMEXPORT void* JNICALL GetPrimitiveArray tmn_suspend_disable(); Class* array_clss = ((ObjectHandle)array)->object->vt()->clss; tmn_suspend_enable(); - assert(array_clss->name->bytes[0]=='['); + assert(array_clss->get_name()->bytes[0]=='['); TRACE2("jni.pin", "pinning array " << array->object); gc_pin_object((Managed_Object_Handle*)array); - switch (array_clss->name->bytes[1]) { + switch (array_clss->get_name()->bytes[1]) { case 'B': return GetByteArrayElements(jenv, array, isCopy); case 'C': return GetCharArrayElements(jenv, array, isCopy); case 'D': return GetDoubleArrayElements(jenv, array, isCopy); @@ -1295,8 +1294,8 @@ VMEXPORT void JNICALL ReleasePrimitiveAr tmn_suspend_disable(); Class* array_clss = ((ObjectHandle)array)->object->vt()->clss; tmn_suspend_enable(); - assert(array_clss->name->bytes[0]=='['); - switch (array_clss->name->bytes[1]) { + assert(array_clss->get_name()->bytes[0]=='['); + switch (array_clss->get_name()->bytes[1]) { case 'B': ReleaseByteArrayElements(jenv, array, (jbyte*)carray, mode); break; case 'C': ReleaseCharArrayElements(jenv, array, (jchar*)carray, mode); break; case 'D': ReleaseDoubleArrayElements(jenv, array, (jdouble*)carray, mode); break; @@ -1679,9 +1678,9 @@ static void check_for_unexpected_excepti } } -void global_object_handles_init(JNIEnv * jni_env) { - - Global_Env * vm_env = jni_get_vm_env(jni_env); +void global_object_handles_init(JNIEnv* jni_env) +{ + Global_Env* vm_env = jni_get_vm_env(jni_env); gh_jlc = oh_allocate_global_handle(); gh_jls = oh_allocate_global_handle(); @@ -1704,8 +1703,8 @@ void global_object_handles_init(JNIEnv * gh_jlfloat = oh_allocate_global_handle(); gh_jldouble = oh_allocate_global_handle(); ObjectHandle h_jlt = oh_allocate_global_handle(); - tmn_suspend_disable(); + tmn_suspend_disable(); // --------------vvv gh_jlc->object = struct_Class_to_java_lang_Class(vm_env->JavaLangClass_Class); gh_jls->object = struct_Class_to_java_lang_Class(vm_env->JavaLangString_Class); gh_jlcloneable->object = struct_Class_to_java_lang_Class(vm_env->java_lang_Cloneable_Class); @@ -1717,16 +1716,16 @@ void global_object_handles_init(JNIEnv * gh_aolong->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfLong_Class); gh_aofloat->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfFloat_Class); gh_aodouble->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfDouble_Class); - tmn_suspend_enable(); //-------------------------------------------------------^ - Class *preload_class(Global_Env* vm_env, const char *classname); - Class* jlboolean = preload_class(vm_env, "java/lang/Boolean"); - Class* jlbyte = preload_class(vm_env, "java/lang/Byte"); - Class* jlchar = preload_class(vm_env, "java/lang/Character"); - Class* jlshort = preload_class(vm_env, "java/lang/Short"); - Class* jlint = preload_class(vm_env, "java/lang/Integer"); - Class* jllong = preload_class(vm_env, "java/lang/Long"); - Class* jlfloat = preload_class(vm_env, "java/lang/Float"); - Class* jldouble = preload_class(vm_env, "java/lang/Double"); + tmn_suspend_enable(); // -------------^^^ + + Class* jlboolean = vm_env->LoadCoreClass("java/lang/Boolean"); + Class* jlbyte = vm_env->LoadCoreClass("java/lang/Byte"); + Class* jlchar = vm_env->LoadCoreClass("java/lang/Character"); + Class* jlshort = vm_env->LoadCoreClass("java/lang/Short"); + Class* jlint = vm_env->LoadCoreClass("java/lang/Integer"); + Class* jllong = vm_env->LoadCoreClass("java/lang/Long"); + Class* jlfloat = vm_env->LoadCoreClass("java/lang/Float"); + Class* jldouble = vm_env->LoadCoreClass("java/lang/Double"); tmn_suspend_disable(); gh_jlboolean->object = struct_Class_to_java_lang_Class(jlboolean); @@ -1739,6 +1738,7 @@ void global_object_handles_init(JNIEnv * gh_jldouble->object = struct_Class_to_java_lang_Class(jldouble); h_jlt->object= struct_Class_to_java_lang_Class(vm_env->java_lang_Throwable_Class); tmn_suspend_enable(); //-------------------------------------------------------^ + assert(hythread_is_suspend_enabled()); gid_throwable_traceinfo = jni_env->GetFieldID((jclass)h_jlt, "vm_stacktrace", "[J"); @@ -1758,7 +1758,7 @@ void global_object_handles_init(JNIEnv * gid_stringinit = jni_env->GetMethodID((jclass)gh_jls, "", "([C)V"); gid_string_field_value = jni_env->GetFieldID((jclass)gh_jls, "value", "[C"); - + if (vm_env->strings_are_compressed) { gid_string_field_bvalue = jni_env->GetFieldID((jclass)gh_jls, "bvalue", "[B"); } @@ -1778,6 +1778,7 @@ void global_object_handles_init(JNIEnv * assert(hythread_is_suspend_enabled()); } + void unsafe_global_object_handles_init(JNIEnv * jni_env) { assert(!hythread_is_suspend_enabled()); tmn_suspend_enable(); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_array.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_array.cpp index 0c7639f..597d1c6 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_array.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_array.cpp @@ -53,13 +53,6 @@ jsize JNICALL GetArrayLength(JNIEnv * UN } //GetArrayLength -#define BITS_PER_BYTE 8 -#define HIGH_BIT_SET_MASK (1<<((sizeof(unsigned) * BITS_PER_BYTE)-1)) -#ifndef NEXT_TO_HIGH_BIT_SET_MASK -#define NEXT_TO_HIGH_BIT_SET_MASK (1<<((sizeof(unsigned) * BITS_PER_BYTE)-2)) -#endif /* #ifndef NEXT_TO_HIGH_BIT_SET_MAS */ -#define TWO_HIGHEST_BITS_SET_MASK (HIGH_BIT_SET_MASK|NEXT_TO_HIGH_BIT_SET_MASK) - jarray JNICALL NewObjectArray(JNIEnv * UNREF env, jsize length, jclass elementClass, @@ -203,8 +196,8 @@ void JNICALL SetObjectArrayElement(JNIEn DeleteLocalRef(env, array_jclass); DeleteLocalRef(env, actual_element_jclass); - if (!class_is_subtype_fast(actual_element_class->vtable, array_class->array_element_class)) { - ThrowNew_Quick(env, "java/lang/ArrayStoreException", actual_element_class->name->bytes); + if (!actual_element_class->is_instanceof(array_class->get_array_element_class())) { + ThrowNew_Quick(env, "java/lang/ArrayStoreException", actual_element_class->get_name()->bytes); return; } } @@ -240,11 +233,12 @@ jbooleanArray JNICALL NewBooleanArray(JN assert(hythread_is_suspend_enabled()); Class *clss = VM_Global_State::loader_env->ArrayOfBoolean_Class; - unsigned sz = vm_array_size(clss->vtable, length); + unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); - Vector_Handle array = gc_alloc(sz, clss->allocation_handle, vm_get_gc_thread_local()); - if (NULL == array) + Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(), + vm_get_gc_thread_local()); + if(NULL == array) { tmn_suspend_enable(); return NULL; @@ -253,8 +247,7 @@ jbooleanArray JNICALL NewBooleanArray(JN set_vector_length(array, length); #ifdef VM_STATS - clss->num_allocations++; - clss->num_bytes_allocated += sz; + clss->instance_allocated(sz); #endif //VM_STATS h->object = (ManagedObject *)array; @@ -273,10 +266,11 @@ jbyteArray JNICALL NewByteArray(JNIEnv * Class *clss = VM_Global_State::loader_env->ArrayOfByte_Class; assert(clss); - unsigned sz = vm_array_size(clss->vtable, length); + unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); - Vector_Handle array = gc_alloc(sz, clss->allocation_handle, vm_get_gc_thread_local()); + Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(), + vm_get_gc_thread_local()); if (NULL == array) { tmn_suspend_enable(); @@ -286,8 +280,7 @@ jbyteArray JNICALL NewByteArray(JNIEnv * set_vector_length(array, length); #ifdef VM_STATS - clss->num_allocations++; - clss->num_bytes_allocated += sz; + clss->instance_allocated(sz); #endif //VM_STATS h->object = (ManagedObject *)array; @@ -305,11 +298,12 @@ jcharArray JNICALL NewCharArray(JNIEnv * assert(hythread_is_suspend_enabled()); Class *clss = VM_Global_State::loader_env->ArrayOfChar_Class; - unsigned sz = vm_array_size(clss->vtable, length); + unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); - Vector_Handle array = gc_alloc(sz, clss->allocation_handle, vm_get_gc_thread_local()); - if (NULL == array) + Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(), + vm_get_gc_thread_local()); + if(NULL == array) { tmn_suspend_enable(); return NULL; @@ -318,8 +312,7 @@ jcharArray JNICALL NewCharArray(JNIEnv * set_vector_length(array, length); #ifdef VM_STATS - clss->num_allocations++; - clss->num_bytes_allocated += sz; + clss->instance_allocated(sz); #endif //VM_STATS h->object = (ManagedObject *)array; @@ -337,11 +330,12 @@ jshortArray JNICALL NewShortArray(JNIEnv assert(hythread_is_suspend_enabled()); Class *clss = VM_Global_State::loader_env->ArrayOfShort_Class; - unsigned sz = vm_array_size(clss->vtable, length); + unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); - Vector_Handle array = gc_alloc(sz, clss->allocation_handle, vm_get_gc_thread_local()); + Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(), + vm_get_gc_thread_local()); if (NULL == array) { tmn_suspend_enable(); @@ -351,8 +345,7 @@ jshortArray JNICALL NewShortArray(JNIEnv set_vector_length(array, length); #ifdef VM_STATS - clss->num_allocations++; - clss->num_bytes_allocated += sz; + clss->instance_allocated(sz); #endif //VM_STATS h->object = (ManagedObject *)array; @@ -369,10 +362,11 @@ jintArray JNICALL NewIntArray(JNIEnv * U TRACE2("jni", "NewIntArray called"); assert(hythread_is_suspend_enabled()); Class *clss = VM_Global_State::loader_env->ArrayOfInt_Class; - unsigned sz = vm_array_size(clss->vtable, length); + unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); - Vector_Handle array = gc_alloc(sz, clss->allocation_handle, vm_get_gc_thread_local()); + Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(), + vm_get_gc_thread_local()); if (NULL == array) { tmn_suspend_enable(); @@ -382,8 +376,7 @@ jintArray JNICALL NewIntArray(JNIEnv * U set_vector_length(array, length); #ifdef VM_STATS - clss->num_allocations++; - clss->num_bytes_allocated += sz; + clss->instance_allocated(sz); #endif //VM_STATS h->object = (ManagedObject *)array; @@ -400,10 +393,11 @@ jlongArray JNICALL NewLongArray(JNIEnv * TRACE2("jni", "NewLongArray called"); assert(hythread_is_suspend_enabled()); Class *clss = VM_Global_State::loader_env->ArrayOfLong_Class; - unsigned sz = vm_array_size(clss->vtable, length); + unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); - Vector_Handle array = gc_alloc(sz, clss->allocation_handle, vm_get_gc_thread_local()); + Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(), + vm_get_gc_thread_local()); if (NULL == array) { tmn_suspend_enable(); @@ -413,8 +407,7 @@ jlongArray JNICALL NewLongArray(JNIEnv * set_vector_length(array, length); #ifdef VM_STATS - clss->num_allocations++; - clss->num_bytes_allocated += sz; + clss->instance_allocated(sz); #endif //VM_STATS h->object = (ManagedObject *)array; @@ -431,10 +424,11 @@ jfloatArray JNICALL NewFloatArray(JNIEnv TRACE2("jni", "NewFloatArray called"); assert(hythread_is_suspend_enabled()); Class *clss = VM_Global_State::loader_env->ArrayOfFloat_Class; - unsigned sz = vm_array_size(clss->vtable, length); + unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); - Vector_Handle array = gc_alloc(sz, clss->allocation_handle, vm_get_gc_thread_local()); + Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(), + vm_get_gc_thread_local()); if (NULL == array) { tmn_suspend_enable(); @@ -444,8 +438,7 @@ jfloatArray JNICALL NewFloatArray(JNIEnv set_vector_length(array, length); #ifdef VM_STATS - clss->num_allocations++; - clss->num_bytes_allocated += sz; + clss->instance_allocated(sz); #endif //VM_STATS h->object = (ManagedObject *)array; @@ -462,10 +455,11 @@ jdoubleArray JNICALL NewDoubleArray(JNIE TRACE2("jni", "NewDoubleArray called"); assert(hythread_is_suspend_enabled()); Class *clss = VM_Global_State::loader_env->ArrayOfDouble_Class; - unsigned sz = vm_array_size(clss->vtable, length); + unsigned sz = clss->calculate_array_size(length); tmn_suspend_disable(); //---------------------------------v ObjectHandle h = oh_allocate_local_handle(); - Vector_Handle array = gc_alloc(sz, clss->allocation_handle, vm_get_gc_thread_local()); + Vector_Handle array = gc_alloc(sz, clss->get_allocation_handle(), + vm_get_gc_thread_local()); if (NULL == array) { tmn_suspend_enable(); @@ -475,8 +469,7 @@ jdoubleArray JNICALL NewDoubleArray(JNIE set_vector_length(array, length); #ifdef VM_STATS - clss->num_allocations++; - clss->num_bytes_allocated += sz; + clss->instance_allocated(sz); #endif //VM_STATS h->object = (ManagedObject *)array; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_field.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_field.cpp index 96a8c94..91494a8 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_field.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_field.cpp @@ -51,7 +51,8 @@ jfieldID JNICALL GetFieldID(JNIEnv *env, ThrowNew_Quick(env, "java/lang/NoSuchFieldError", name); return 0; } - TRACE2("jni", "GetFieldID " << clss->name->bytes << "." << name << " " << sig << " = " << (jfieldID)field); + TRACE2("jni", "GetFieldID " << clss->get_name()->bytes + << "." << name << " " << sig << " = " << (jfieldID)field); assert(!field->is_static()); return (jfieldID)field; @@ -92,7 +93,8 @@ jfieldID JNICALL GetStaticFieldID(JNIEnv ThrowNew_Quick(env, "java/lang/NoSuchFieldError", name); return 0; } - TRACE2("jni", "GetStaticFieldID " << clss->name->bytes << "." << name << " " << sig << " = " << (jfieldID)field); + TRACE2("jni", "GetStaticFieldID " << clss->get_name()->bytes + << "." << name << " " << sig << " = " << (jfieldID)field); assert(field->is_static()); return (jfieldID)field; @@ -471,7 +473,7 @@ void JNICALL SetByteFieldOffset(JNIEnv * tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; - if (Class::compact_fields) + if(VM_Global_State::loader_env->compact_fields) *(jbyte *)(java_ref + offset) = value; else *(jint *)(java_ref + offset) = value; @@ -534,7 +536,7 @@ void JNICALL SetShortFieldOffset(JNIEnv tmn_suspend_disable(); //---------------------------------v Byte *java_ref = (Byte *)h->object; - if (Class::compact_fields) + if (VM_Global_State::loader_env->compact_fields) *(jshort *)(java_ref + offset) = value; else *(jint *)(java_ref + offset) = value; @@ -898,7 +900,7 @@ void JNICALL SetStaticByteField(JNIEnv * assert(f->is_static()); jbyte *field_addr = (jbyte *)f->get_address(); jint *field_addr_int = (jint *)f->get_address(); - if (Class::compact_fields) + if (VM_Global_State::loader_env->compact_fields) *field_addr = value; else *field_addr_int = value; @@ -934,7 +936,7 @@ void JNICALL SetStaticShortField(JNIEnv assert(f->is_static()); jshort *field_addr = (jshort *)f->get_address(); jint *field_addr_int = (jint *)f->get_address(); - if (Class::compact_fields) + if (VM_Global_State::loader_env->compact_fields) *field_addr = value; else *field_addr_int = value; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_method.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_method.cpp index 95fe148..904f204 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_method.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_method.cpp @@ -40,6 +40,23 @@ #include "nogc.h" +static Method* lookup_method_init(Class* clss, const char* descr) +{ + String* method_name = VM_Global_State::loader_env->Init_String; + String* method_descr = + VM_Global_State::loader_env->string_pool.lookup(descr); + + return clss->lookup_method(method_name, method_descr); +} // lookup_method_init + + +static Method* lookup_method_clinit(Class* clss) +{ + return clss->lookup_method(VM_Global_State::loader_env->Clinit_String, + VM_Global_State::loader_env->VoidVoidDescriptor_String); +} // lookup_method_clinit + + jmethodID JNICALL GetMethodID(JNIEnv *env, jclass clazz, const char *name, @@ -53,7 +70,7 @@ jmethodID JNICALL GetMethodID(JNIEnv *en Method *method; if ('<' == *name) { if (!strcmp(name + 1, "init>")) { - method = class_lookup_method_init(clss, descr); + method = lookup_method_init(clss, descr); } else { ThrowNew_Quick(env, "java/lang/NoSuchMethodError", name); return NULL; @@ -66,7 +83,8 @@ jmethodID JNICALL GetMethodID(JNIEnv *en ThrowNew_Quick(env, "java/lang/NoSuchMethodError", name); return NULL; } - TRACE2("jni", "GetMethodID " << clss->name->bytes << "." << name << " " << descr << " = " << (jmethodID)method); + TRACE2("jni", "GetMethodID " << clss->get_name()->bytes + << "." << name << " " << descr << " = " << (jmethodID)method); return (jmethodID)method; } //GetMethodID @@ -85,7 +103,7 @@ jmethodID JNICALL GetStaticMethodID(JNIE Method *method; if ('<' == *name) { if (!strcmp(name + 1, "clinit>") && !strcmp(descr, "()V")) { - method = class_lookup_method_clinit(clss); + method = lookup_method_clinit(clss); } else { ThrowNew_Quick(env, "java/lang/NoSuchMethodError", name); return NULL; @@ -98,7 +116,8 @@ jmethodID JNICALL GetStaticMethodID(JNIE ThrowNew_Quick(env, "java/lang/NoSuchMethodError", name); return NULL; } - TRACE2("jni", "GetStaticMethodID " << clss->name->bytes << "." << name << " " << descr << " = " << (jmethodID)method); + TRACE2("jni", "GetStaticMethodID " << clss->get_name()->bytes + << "." << name << " " << descr << " = " << (jmethodID)method); return (jmethodID)method; } //GetStaticMethodID @@ -341,8 +360,6 @@ jbyte JNICALL CallByteMethodA(JNIEnv *en } //CallByteMethodA - - jchar JNICALL CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { TRACE2("jni", "CallCharMethod called, id = " << methodID); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_utils.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_utils.cpp index d6e5e70..7783c8e 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_utils.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jni/jni_utils.cpp @@ -278,34 +278,34 @@ char* ParameterTypesToMethodSignature (J * GetClassSignatureLength() + 1 bytes. */ //should we care about buffer overflow and return len? -size_t GetClassSignatureLength (Class* cl) +size_t GetClassSignatureLength(Class* cl) { - assert (cl); + assert(cl); - const char* name = cl->name->bytes; + const String* name = cl->get_name(); - if (name[0] == '[') { - return strlen(name); + if (name->bytes[0] == '[') { + return name->len; } - else if (cl->is_primitive) { + else if (cl->is_primitive()) { return 1; } else { - return 2 + strlen(name); + return 2 + name->len; // 2 bytes are for L and ; } } // GetClassSignatureLength //should we care about buffer overflow and return len? -void GetClassSignature (Class* cl, char *sig) +void GetClassSignature(Class* cl, char* sig) { assert (cl); - const char* name = cl->name->bytes; + const char* name = cl->get_name()->bytes; if (name[0] == '[') { sprintf (sig, "%s",name); } - else if (cl->is_primitive) { + else if (cl->is_primitive()) { sig[0] = PrimitiveNameToSignature (name); sig[1] = '\0'; } @@ -374,7 +374,7 @@ void PrimitiveSignatureToName (const cha Field* LookupField (Class *clss, const char *name) { Field *f = 0; - for(; clss && !f; clss = clss->super_class) { + for(; clss && !f; clss = clss->get_super_class()) { if((f = LookupDeclaredField(clss, name))) return f; } @@ -382,21 +382,20 @@ Field* LookupField (Class *clss, const c return NULL; } // LookupField -Method* LookupMethod (Class *clss, const char *mname, const char *mdesc) +Method* LookupMethod(Class* clss, const char* mname, const char* mdesc) { Method* m = 0; - Class *oclss = clss; - for (; clss; clss = clss->super_class) { // for each superclass + Class* oclss = clss; + for (; clss; clss = clss->get_super_class()) { // for each superclass if((m = LookupDeclaredMethod(clss, mname, mdesc))) return m; } - Class_Superinterface *intfs = oclss->superinterfaces; - for(int i = 0; i < oclss->n_superinterfaces; i++) - if((m = LookupMethod(intfs[i].clss, mname, mdesc))) + for(int i = 0; i < oclss->get_number_of_superinterfaces(); i++) + if((m = LookupMethod(oclss->get_superinterface(i), mname, mdesc))) return m; - return (Method*)0; // method not found + return NULL; // method not found } // LookupMethod char PrimitiveNameToSignature (const char* name) @@ -523,9 +522,9 @@ Field* LookupDeclaredField (Class *clss, assert (clss); - for (unsigned i =0; i < clss->n_fields; i++) { - if (clss->fields[i].get_name() == field_name) { - return &clss->fields[i]; + for (unsigned i =0; i < clss->get_number_of_fields(); i++) { + if (clss->get_field(i)->get_name() == field_name) { + return clss->get_field(i); } } @@ -545,7 +544,7 @@ void VerifyArray (JNIEnv* env, jarray ar // Acquire handle to internal class handle (Class): Class* clss = jclass_to_struct_Class(aclazz); - if (!clss->is_array) { + if (!clss->is_array()) { ThrowNew_Quick (env, "java/lang/IllegalArgumentException", 0); return; } @@ -558,7 +557,7 @@ char GetComponentSignature (JNIEnv *env, // Acquire handle to internal class handle (Class): Class* clss = jclass_to_struct_Class(aclazz); - return clss->name->bytes[1]; // return component first character + return clss->get_name()->bytes[1]; // return component first character } @@ -568,19 +567,20 @@ Method* LookupDeclaredMethod(Class *clss size_t len = strlen (mdesc); Method *m = 0; - for (unsigned i =0; i < clss->n_methods; i++) { // for each method - m = &clss->methods[i]; + for (unsigned i =0; i < clss->get_number_of_methods(); i++) { // for each method + m = clss->get_method(i); if (m->is_fake_method()) { continue; // ignore fake methods } const char* desc = m->get_descriptor()->bytes; - if ((m->get_name() == method_name) && // if names and signatures - (strncmp (mdesc, desc, len) == 0)) { // (excluding return types) match, - return m; // return method + if ((m->get_name() == method_name) // if names and signatures + && (strncmp (mdesc, desc, len) == 0)) // (excluding return types) match + { + return m; // return method } } - return (Method*)0; // method not found + return NULL; // method not found } // LookupDeclaredMethod //Checks if the object is null. @@ -669,10 +669,6 @@ void array_copy_jni(JNIEnv* jenv, jobjec jenv->ThrowNew(tclass, "bad arrayCopy"); } -Boolean class_is_subclass(Class_Handle subclss, Class_Handle superclss) -{ - return class_is_subtype_fast(((Class*)subclss)->vtable, (Class*)superclss); -} jclass FindClass(JNIEnv* env_ext, String* name) { @@ -744,9 +740,9 @@ jobject CreateNewThrowable(JNIEnv* jenv, Method* ctor; if (message) - ctor = class_lookup_method(clazz, genv->Init_String, genv->FromStringConstructorDescriptor_String); + ctor = clazz->lookup_method(genv->Init_String, genv->FromStringConstructorDescriptor_String); else - ctor = class_lookup_method(clazz, genv->Init_String, genv->VoidVoidDescriptor_String); + ctor = clazz->lookup_method(genv->Init_String, genv->VoidVoidDescriptor_String); assert(ctor); jclass jclazz = struct_Class_to_jclass(clazz); assert(jclazz); @@ -795,14 +791,14 @@ bool ensure_initialised(JNIEnv* env, Cla ASSERT_RAISE_AREA; assert(hythread_is_suspend_enabled()); - if(clss->state != ST_Initialized) { + if(!clss->is_initialized()) { class_initialize_from_jni(clss); - if(clss->state == ST_Error) { + if(clss->in_error()) { // If exception is already raised, no need to // throw new one, just return instead - if (!exn_raised()) + if(!exn_raised()) { - env->Throw(class_get_error_cause(clss)); + env->Throw(clss->get_error_cause()); } return false; } 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 ed3144c..0f5ce26 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 "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 7da89b2..03bd482 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,8 +34,10 @@ #include "m2n.h" #include "stack_iterator.h" #include "open/bytecodes.h" -#include "jvmti_break_intf.h" +#include "cci.h" +#include "jvmti_break_intf.h" +#include "cci.h" // Forvard declarations static ConditionCode diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_class.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_class.cpp index 48f824e..ffa7bc6 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_class.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_class.cpp @@ -133,7 +133,7 @@ jvmtiGetLoadedClasses(jvmtiEnv* env, for(it = tbl->begin(); it != tbl->end(); it++) { klass = &it->second; - if ((*klass)->class_loader != classloader) + if ((*klass)->get_class_loader() != classloader) continue; count++; } @@ -176,15 +176,12 @@ jvmtiGetLoadedClasses(jvmtiEnv* env, for(it = tbl->begin(); it != tbl->end(); it++) { klass = &it->second; - if((*klass)->is_primitive) + if((*klass)->is_primitive()) continue; - if ((*klass)->class_loader != classloader) + if ((*klass)->get_class_loader() != classloader) continue; // create a new jclass handle for Class - tmn_suspend_disable(); - ObjectHandle new_handle = oh_allocate_local_handle(); - new_handle->object = struct_Class_to_java_lang_Class( *klass ); - tmn_suspend_enable(); + ObjectHandle new_handle = struct_Class_to_jclass(*klass); // set created handle into jclass handle table (*classes)[number++] = (jclass)new_handle; @@ -277,10 +274,7 @@ jvmtiGetClassLoaderClasses(jvmtiEnv* env { klass = &it->second; // create a new jclass handle for Class - tmn_suspend_disable(); - ObjectHandle new_handle = oh_allocate_local_handle(); - new_handle->object = struct_Class_to_java_lang_Class( *klass ); - tmn_suspend_enable(); + ObjectHandle new_handle = struct_Class_to_jclass(*klass); // set created handle into jclass handle table (*classes_ptr)[index++] = (jclass)new_handle; @@ -398,18 +392,18 @@ jvmtiGetClassStatus(jvmtiEnv* env, jclas } else if( class_is_array( cl ) ) { *status_ptr = JVMTI_CLASS_STATUS_ARRAY; } else { - switch( cl->state ) + switch(cl->get_state()) { case ST_Start: case ST_LoadingAncestors: - break; case ST_Loaded: + case ST_BytecodesVerified: case ST_InstanceSizeComputed: - if( cl->is_verified ) { - *status_ptr |= JVMTI_CLASS_STATUS_VERIFIED; - } break; case ST_Prepared: + *status_ptr |= JVMTI_CLASS_STATUS_PREPARED; + break; + case ST_ConstraintsVerified: case ST_Initializing: *status_ptr |= JVMTI_CLASS_STATUS_PREPARED | JVMTI_CLASS_STATUS_VERIFIED; @@ -459,20 +453,21 @@ jvmtiGetSourceFileName(jvmtiEnv* env, jc &errorCode); if( cl == NULL ) return errorCode; - if( cl->is_primitive || cl->is_array ) + if(cl->is_primitive() || cl->is_array()) { - TRACE2("jvmti.class", "GetSourceFileName called, name = " << cl->name->bytes << - " file name is absent"); + TRACE2("jvmti.class", "GetSourceFileName called, name = " + << cl->get_name()->bytes << " file name is absent"); return JVMTI_ERROR_ABSENT_INFORMATION; } - if(!cl->src_file_name) return JVMTI_ERROR_ABSENT_INFORMATION; + if(!cl->has_source_information()) return JVMTI_ERROR_ABSENT_INFORMATION; - TRACE2("jvmti.class", "GetSourceFileName called, name = " << cl->name->bytes << - " file name = " << cl->src_file_name->bytes); - errorCode = _allocate( cl->src_file_name->len + 1, (unsigned char**)res ); + TRACE2("jvmti.class", "GetSourceFileName called, name = " + << cl->get_name()->bytes << " file name = " + << cl->get_source_file_name()); + errorCode = _allocate(cl->get_source_file_name_length() + 1, (unsigned char**)res); if( errorCode != JVMTI_ERROR_NONE ) return errorCode; - strcpy( *res, cl->src_file_name->bytes ); + memcpy(*res, cl->get_source_file_name(), cl->get_source_file_name_length() + 1); return JVMTI_ERROR_NONE; } @@ -503,11 +498,11 @@ jvmtiGetClassModifiers(jvmtiEnv* env, jc if( cl == NULL ) return errorCode; *modifiers_ptr = 0; - if( class_is_public( cl ) ) *modifiers_ptr |= ACC_PUBLIC; - if( class_is_final( cl ) ) *modifiers_ptr |= ACC_FINAL; - if( class_is_super( cl ) ) *modifiers_ptr |= ACC_SUPER; - if( class_is_interface( cl ) ) *modifiers_ptr |= ACC_INTERFACE; - if( class_is_abstract( cl ) ) *modifiers_ptr |= ACC_ABSTRACT; + if(cl->is_public()) *modifiers_ptr |= ACC_PUBLIC; + if(cl->is_final()) *modifiers_ptr |= ACC_FINAL; + if(cl->is_super()) *modifiers_ptr |= ACC_SUPER; + if(cl->is_interface()) *modifiers_ptr |= ACC_INTERFACE; + if(cl->is_abstract()) *modifiers_ptr |= ACC_ABSTRACT; return JVMTI_ERROR_NONE; } @@ -542,16 +537,14 @@ jvmtiGetClassMethods(jvmtiEnv* env, jcla * Check class status. If class is not on PREPARED status, GetClassMethods(...) * function returns JVMTI_ERROR_CLASS_NOT_PREPARED */ - if ((cl->state == ST_Start) || - (cl->state == ST_LoadingAncestors) || - (cl->state == ST_Loaded) || - (cl->state == ST_InstanceSizeComputed)) + if(!cl->is_at_least_prepared()) return JVMTI_ERROR_CLASS_NOT_PREPARED; - errorCode = _allocate( cl->n_methods*sizeof(jmethodID), (unsigned char**)methods_ptr ); + errorCode = _allocate(cl->get_number_of_methods()*sizeof(jmethodID), (unsigned char**)methods_ptr ); if( errorCode != JVMTI_ERROR_NONE ) return errorCode; - *method_count_ptr = cl->n_methods; - for( short i = 0; i < cl->n_methods; i++ ) (*methods_ptr)[i] = (jmethodID)&(cl->methods[i]); + *method_count_ptr = cl->get_number_of_methods(); + for(short i = 0; i < cl->get_number_of_methods(); i++ ) + (*methods_ptr)[i] = (jmethodID)cl->get_method(i); return JVMTI_ERROR_NONE; } @@ -586,16 +579,15 @@ jvmtiGetClassFields(jvmtiEnv* env, jclas * Check class status. If class is not on PREPARED status, GetClassMethods(...) * function returns JVMTI_ERROR_CLASS_NOT_PREPARED */ - if ((cl->state == ST_Start) || - (cl->state == ST_LoadingAncestors) || - (cl->state == ST_Loaded) || - (cl->state == ST_InstanceSizeComputed)) + if(!cl->is_at_least_prepared()) return JVMTI_ERROR_CLASS_NOT_PREPARED; - errorCode = _allocate( cl->n_fields*sizeof(jfieldID), (unsigned char**)fields_ptr ); + errorCode = _allocate(cl->get_number_of_fields()*sizeof(jfieldID), + (unsigned char**)fields_ptr); if( errorCode != JVMTI_ERROR_NONE ) return errorCode; - *field_count_ptr = cl->n_fields; - for( short i = 0; i < cl->n_fields; i++ ) (*fields_ptr)[i] = (jfieldID)&(cl->fields[i]); + *field_count_ptr = cl->get_number_of_fields(); + for(short i = 0; i < cl->get_number_of_fields(); i++ ) + (*fields_ptr)[i] = (jfieldID)cl->get_field(i); return JVMTI_ERROR_NONE; } @@ -630,25 +622,19 @@ jvmtiGetImplementedInterfaces(jvmtiEnv* * Check class status. If class is not on PREPARED status, GetClassMethods(...) * function returns JVMTI_ERROR_CLASS_NOT_PREPARED */ - if ((cl->state == ST_Start) || - (cl->state == ST_LoadingAncestors) || - (cl->state == ST_Loaded) || - (cl->state == ST_InstanceSizeComputed)) + if(!cl->is_at_least_prepared()) return JVMTI_ERROR_CLASS_NOT_PREPARED; - errorCode = _allocate( cl->n_superinterfaces*sizeof(jclass), + errorCode = _allocate( cl->get_number_of_superinterfaces()*sizeof(jclass), reinterpret_cast(interfaces_ptr) ); if( errorCode != JVMTI_ERROR_NONE ) return errorCode; ObjectHandle jclss; - for( int i = 0; i < cl->n_superinterfaces; i++ ) + for( int i = 0; i < cl->get_number_of_superinterfaces(); i++ ) { - tmn_suspend_disable(); - jclss = oh_allocate_local_handle(); - jclss->object = struct_Class_to_java_lang_Class( cl->superinterfaces[i].clss ); - tmn_suspend_enable(); + jclss = struct_Class_to_jclass(cl->get_superinterface(i)); (*interfaces_ptr)[i] = (jclass)jclss; } - *interface_count_ptr = cl->n_superinterfaces; + *interface_count_ptr = cl->get_number_of_superinterfaces(); return JVMTI_ERROR_NONE; } @@ -680,8 +666,8 @@ jvmtiIsInterface(jvmtiEnv* env, jclass h if (cl == NULL) return errorCode; - TRACE2("jvmti.class", "IsInterface: class = " << cl->name->bytes); - *is_interface_ptr = (jboolean)(class_is_interface(cl) ? JNI_TRUE : JNI_FALSE); + TRACE2("jvmti.class", "IsInterface: class = " << cl->get_name()->bytes); + *is_interface_ptr = (jboolean)(cl->is_interface() ? JNI_TRUE : JNI_FALSE); return JVMTI_ERROR_NONE; } @@ -712,8 +698,8 @@ jvmtiIsArrayClass(jvmtiEnv* env, jclass if (cl == NULL) return errorCode; - TRACE2("jvmti.class", "IsArrayClass: class = " << cl->name->bytes); - *is_array_class_ptr = (jboolean)(cl->is_array ? JNI_TRUE : JNI_FALSE); + TRACE2("jvmti.class", "IsArrayClass: class = " << cl->get_name()->bytes); + *is_array_class_ptr = (jboolean)(cl->is_array() ? JNI_TRUE : JNI_FALSE); return JVMTI_ERROR_NONE; } @@ -743,7 +729,7 @@ jvmtiError JNICALL jvmtiGetClassLoader(j return errorCode; tmn_suspend_disable(); - ManagedObject* cl = clss->class_loader->GetLoader(); + ManagedObject* cl = clss->get_class_loader()->GetLoader(); if( !cl ) { *classloader_ptr = NULL; } else { @@ -782,14 +768,15 @@ jvmtiGetSourceDebugExtension(jvmtiEnv* e if (clss == NULL) return errorCode; - if( !clss->sourceDebugExtension ) return JVMTI_ERROR_ABSENT_INFORMATION; + if(!clss->has_source_debug_extension()) return JVMTI_ERROR_ABSENT_INFORMATION; - errorCode = _allocate( clss->sourceDebugExtension->len + 1, - reinterpret_cast(source_debug_extension_ptr) ); + errorCode = _allocate(clss->get_source_debug_extension_length() + 1, + reinterpret_cast(source_debug_extension_ptr)); if( errorCode != JVMTI_ERROR_NONE ) return errorCode; - strcpy( *source_debug_extension_ptr, clss->sourceDebugExtension->bytes ); + memcpy(*source_debug_extension_ptr, clss->get_source_debug_extension(), + clss->get_source_debug_extension_length() + 1); return JVMTI_ERROR_NONE; } 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 30aab0d..feee047 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 "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" @@ -455,7 +456,7 @@ void jvmti_send_compiled_method_load_eve { TRACE2("jvmti.event.cml", "Callback JVMTI_EVENT_COMPILED_METHOD_LOAD called, method = " << - method->get_class()->name->bytes << "." << method->get_name()->bytes << + method->get_class()->get_name()->bytes << "." << method->get_name()->bytes << method->get_descriptor()->bytes); for (CodeChunkInfo* cci = method->get_first_JIT_specific_info(); cci; cci = cci->_next) @@ -466,7 +467,7 @@ void jvmti_send_compiled_method_load_eve TRACE2("jvmti.event.cml", "Callback JVMTI_EVENT_COMPILED_METHOD_LOAD finished, method = " << - method->get_class()->name->bytes << "." << method->get_name()->bytes << + method->get_class()->get_name()->bytes << "." << method->get_name()->bytes << method->get_descriptor()->bytes); } } @@ -557,25 +558,23 @@ jvmtiGenerateEvents(jvmtiEnv* env, /** * Create jclass handle for classes and set in jclass table */ - classloader->Lock(); - ClassTable* tbl; - Class **klass; - ClassTable::iterator it; - tbl = classloader->GetLoadedClasses(); - for(it = tbl->begin(); it != tbl->end(); it++) - { + classloader->Lock(); + ClassTable* tbl; + Class **klass; + ClassTable::iterator it; + tbl = classloader->GetLoadedClasses(); + for(it = tbl->begin(); it != tbl->end(); it++) + { klass = &it->second; - TRACE2("jvmti.event", "Class = " << (*klass)->name->bytes); - if((*klass)->is_primitive) + TRACE2("jvmti.event", "Class = " << (*klass)->get_name()->bytes); + if((*klass)->is_primitive()) continue; - if((*klass)->class_loader != classloader) + if((*klass)->get_class_loader() != classloader) continue; - if((*klass)->state == ST_Prepared || - (*klass)->state == ST_Initializing || - (*klass)->state == ST_Initialized) - for (int jjj = 0; jjj < (*klass)->n_methods; jjj++) + if((*klass)->is_at_least_prepared()) + for (int jjj = 0; jjj < (*klass)->get_number_of_methods(); jjj++) { - Method *method = &(*klass)->methods[jjj]; + Method* method = (*klass)->get_method(jjj); TRACE2("jvmti.event", " Method = " << method->get_name()->bytes << method->get_descriptor()->bytes << (method->get_state() == Method::ST_Compiled ? " compiled" : " not compiled")); @@ -593,7 +592,7 @@ jvmtiGenerateEvents(jvmtiEnv* env, } else { break; } - } while( true ); + } while(true); ClassLoader::UnlockLoadersTable(); } @@ -1510,7 +1509,7 @@ void jvmti_send_contended_enter_or_enter void jvmti_send_class_load_event(const Global_Env* env, Class* clss) { assert(hythread_is_suspend_enabled()); - if( clss->is_array || clss->is_primitive ) { + if(clss->is_array() || clss->is_primitive()) { // array class creation and creation of a primitive class // do not generate a class load event. return; @@ -1527,11 +1526,10 @@ void jvmti_send_class_load_event(const G } JNIEnv *jni_env = p_TLS_vmthread->jni_env; - tmn_suspend_disable(); ObjectHandle hThread = oh_allocate_local_handle(); - ObjectHandle hClass = oh_allocate_local_handle(); + ObjectHandle hClass = struct_Class_to_jclass(clss); + tmn_suspend_disable(); hThread->object = (Java_java_lang_Thread *)jthread_get_java_thread(hythread_self())->object; - hClass->object = struct_Class_to_java_lang_Class(clss); tmn_suspend_enable(); TIEnv *ti_env = ti->getEnvironments(); @@ -1545,7 +1543,7 @@ void jvmti_send_class_load_event(const G { if (ti_env->global_events[JVMTI_EVENT_CLASS_LOAD - JVMTI_MIN_EVENT_TYPE_VAL]) { - TRACE2("jvmti.class.cl", "Class load event, class name = " << clss->name->bytes); + TRACE2("jvmti.class.cl", "Class load event, class name = " << clss->get_name()->bytes); // fire global event func((jvmtiEnv *)ti_env, jni_env, (jthread)hThread, (jclass)hClass); ti_env = next_env; @@ -1557,7 +1555,7 @@ void jvmti_send_class_load_event(const G ti_et != NULL; ti_et = ti_et->next ) if (ti_et->thread == hythread_self()) { - TRACE2("jvmti.class.cl", "Class load event, class name = " << clss->name->bytes); + TRACE2("jvmti.class.cl", "Class load event, class name = " << clss->get_name()->bytes); tmn_suspend_disable(); ObjectHandle hThreadLocal = oh_allocate_local_handle(); hThreadLocal->object = (Java_java_lang_Thread *)jthread_get_java_thread(ti_et->thread)->object; @@ -1654,7 +1652,7 @@ void jvmti_send_class_file_load_hook_eve void jvmti_send_class_prepare_event(Class* clss) { assert(hythread_is_suspend_enabled()); - if( clss->is_array || clss->is_primitive ) { + if(clss->is_array() || clss->is_primitive()) { // class prepare events are not generated for primitive classes // and arrays return; @@ -1671,12 +1669,11 @@ void jvmti_send_class_prepare_event(Clas } JNIEnv *jni_env = p_TLS_vmthread->jni_env; + ObjectHandle hClass = struct_Class_to_jclass(clss); tmn_suspend_disable(); // -----------vv ObjectHandle hThread = oh_allocate_local_handle(); - ObjectHandle hClass = oh_allocate_local_handle(); hThread->object = (Java_java_lang_Thread *)jthread_get_java_thread(hythread_self())->object; - hClass->object = struct_Class_to_java_lang_Class(clss); - tmn_suspend_enable(); // ------------^^ + tmn_suspend_enable(); // -----------^^ TIEnv *ti_env = ti->getEnvironments(); TIEnv *next_env; @@ -1689,10 +1686,10 @@ void jvmti_send_class_prepare_event(Clas { if (ti_env->global_events[JVMTI_EVENT_CLASS_PREPARE - JVMTI_MIN_EVENT_TYPE_VAL]) { - TRACE2("jvmti.class.cp", "Class prepare event, class name = " << clss->name->bytes); + TRACE2("jvmti.class.cp", "Class prepare event, class name = " << clss->get_name()->bytes); // fire global event func((jvmtiEnv *)ti_env, jni_env, (jthread)hThread, (jclass)hClass); - TRACE2("jvmti.class.cp", "Class prepare event exited, class name = " << clss->name->bytes); + TRACE2("jvmti.class.cp", "Class prepare event exited, class name = " << clss->get_name()->bytes); ti_env = next_env; continue; } @@ -1701,7 +1698,7 @@ void jvmti_send_class_prepare_event(Clas ti_et != NULL; ti_et = ti_et->next ) if (ti_et->thread == hythread_self()) { - TRACE2("jvmti.class.cp", "Class prepare event, class name = " << clss->name->bytes); + TRACE2("jvmti.class.cp", "Class prepare event, class name = " << clss->get_name()->bytes); tmn_suspend_disable(); // -------------------------------vv ObjectHandle hThreadLocal = oh_allocate_local_handle(); hThreadLocal->object = (Java_java_lang_Thread *)jthread_get_java_thread(hythread_self())->object; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_internal.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_internal.cpp index 92ce9e6..8d160e3 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_internal.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_internal.cpp @@ -38,8 +38,8 @@ static Boolean is_valid_instance(jobject ManagedObject *mo = h->object; // Check that reference pointer points to the heap - if (mo < (ManagedObject *)Class::heap_base || - mo > (ManagedObject *)Class::heap_end) + if (mo < (ManagedObject *)VM_Global_State::loader_env->heap_base || + mo > (ManagedObject *)VM_Global_State::loader_env->heap_end) { tmn_suspend_enable(); return false; @@ -52,8 +52,8 @@ static Boolean is_valid_instance(jobject return false; } - Class *object_clss = mo->vt()->clss; - Boolean result = class_is_subtype_fast(object_clss->vtable, clss); + Class* object_clss = mo->vt()->clss; + Boolean result = object_clss->is_instanceof(clss); tmn_suspend_enable(); //---------------------------------^ return result; 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 b82d406..a629fd6 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 "stack_iterator.h" #include "stack_trace.h" #include "jit_intf_cpp.h" +#include "cci.h" +#include "Class.h" #define jvmti_test_jenv (p_TLS_vmthread->jni_env) @@ -409,8 +411,8 @@ jvmtiSetLocalObject(jvmtiEnv* env, tmn_suspend_disable(); ManagedObject *obj = handle->object; - if (obj < (ManagedObject *)Class::heap_base || - obj > (ManagedObject *)Class::heap_end) + if (obj < (ManagedObject *)VM_Global_State::loader_env->heap_base || + obj > (ManagedObject *)VM_Global_State::loader_env->heap_end) { tmn_suspend_enable(); return JVMTI_ERROR_INVALID_OBJECT; @@ -418,6 +420,9 @@ jvmtiSetLocalObject(jvmtiEnv* env, Class *clss = obj->vt()->clss; ManagedObject *clsObj = struct_Class_to_java_lang_Class(clss); + // ppervov: FIXME: there is an assertion in the above function which + // is exactly the same as in the following if. So, this code will only + // work in release and just assert in debug. if (clsObj->vt()->clss != VM_Global_State::loader_env->JavaLangClass_Class) { tmn_suspend_enable(); return JVMTI_ERROR_INVALID_OBJECT; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_object.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_object.cpp index b4485a9..126977a 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_object.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_object.cpp @@ -67,16 +67,16 @@ jvmtiGetObjectSize(jvmtiEnv* env, ManagedObject *mo = h->object; // Check that reference pointer points to the heap - if (mo < (ManagedObject *)Class::heap_base || - mo > (ManagedObject *)Class::heap_end) + if (mo < (ManagedObject *)VM_Global_State::loader_env->heap_base || + mo > (ManagedObject *)VM_Global_State::loader_env->heap_end) { tmn_suspend_enable(); return JVMTI_ERROR_INVALID_OBJECT; } Class *object_clss = mo->vt()->clss; - if (class_is_array(object_clss)) - *size_ptr = vm_vector_size(object_clss, get_vector_length((Vector_Handle)mo)); + if(object_clss->is_array()) + *size_ptr = object_clss->calculate_array_size(get_vector_length((Vector_Handle)mo)); else *size_ptr = class_get_boxed_data_size(object_clss); @@ -119,7 +119,7 @@ jvmtiGetObjectHashCode(jvmtiEnv* env, p_obj = NULL; *hash_code_ptr = generic_hashcode(p_obj); TRACE2("jvmti-object", "Object " << - ((NULL == p_obj) ? "is null" : p_obj->vt()->clss->name->bytes) << + ((NULL == p_obj) ? "is null" : p_obj->vt()->clss->get_name()->bytes) << " hash code = " << *hash_code_ptr); tmn_suspend_enable(); 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 7c6a964..0815fa5 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 "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 6481de1..17462d0 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_iterator.h" #include "jit_intf_cpp.h" #include "thread_manager.h" +#include "cci.h" #define jvmti_test_jenv (p_TLS_vmthread->jni_env) 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 9c3f6df..316833f 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 "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" @@ -317,13 +318,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->get_constant_pool().is_entry_resolved(index)); - if( !method_is_native( klass->const_pool[index].CONSTANT_ref.method ) ) { + if(!method_is_native(klass->get_constant_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->get_constant_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 332ecae..b0d04b9 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_thread.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_thread.cpp @@ -43,6 +43,8 @@ #include "stack_iterator.h" +#include "Class.h" // FIXME: this is for Class::heap_base and Class::heap_end + #define MAX_JVMTI_ENV_NUMBER 10 #define jvmti_test_jenv (p_TLS_vmthread->jni_env) @@ -417,8 +419,8 @@ jvmtiStopThread(jvmtiEnv* env, ManagedObject *mo = h->object; // Check that reference pointer points to the heap - if (mo < (ManagedObject *)Class::heap_base || - mo > (ManagedObject *)Class::heap_end) + if (mo < (ManagedObject*)VM_Global_State::loader_env->heap_base || + mo > (ManagedObject*)VM_Global_State::loader_env->heap_end) { tmn_suspend_enable(); return JVMTI_ERROR_INVALID_OBJECT; 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 55e62de..7f2c989 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 "cxxlog.h" #include "suspend_checker.h" #include "environment.h" +#include "Class.h" #define jvmti_test_jenv (p_TLS_vmthread->jni_env) diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_watch.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_watch.cpp index 8d27296..fa755dd 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_watch.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_watch.cpp @@ -35,9 +35,9 @@ #include "Class.h" #include "vm_strings.h" #include "jvmti_direct.h" -#include "Class.h" #include "object_handles.h" #include "jvmti_utils.h" +#include "type.h" #include "cxxlog.h" #include "jvmti_interface.h" @@ -333,8 +333,8 @@ void jvmti_field_modification_callback(F if (! field->get_field_type_desc()->is_primitive() && NULL != new_value.l) { // if new_value.l is not a handle but a direct pointer to java heap - if ((ManagedObject*)new_value.l >= (ManagedObject*)Class::heap_base && - (ManagedObject*)new_value.l <= (ManagedObject*)Class::heap_end) + if ((ManagedObject*)new_value.l >= (ManagedObject*)VM_Global_State::loader_env->heap_base + && (ManagedObject*)new_value.l <= (ManagedObject*)VM_Global_State::loader_env->heap_end) { new_value.l = oh_allocate_local_handle(); new_value.l->object = (ManagedObject*)p_new_value->l; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java index 071a7b7..8a82825 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java +++ b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java @@ -337,6 +337,7 @@ public final class Class implements S * @com.intel.drl.spec_ref */ public Class getComponentType() { + if(!isArray()) return null; return VMClassRegistry.getComponentType(this); } @@ -646,7 +647,10 @@ public final class Class implements S * @com.intel.drl.spec_ref */ public boolean isArray() { - return VMClassRegistry.isArray(this); + if (reflectionData == null) { + initReflectionData(); + } + return reflectionData.isArray; } /** @@ -1169,6 +1173,8 @@ public final class Class implements S String name; int modifiers = -1; + + boolean isArray; Constructor[] declaredConstructors; @@ -1188,6 +1194,7 @@ public final class Class implements S public ReflectionData() { name = VMClassRegistry.getName(Class.this); + isArray = VMClassRegistry.isArray(Class.this); packageName = Class.getParentName(name); } diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/reflect/AccessibleObject.java b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/reflect/AccessibleObject.java index a2cb7f8..b597554 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/reflect/AccessibleObject.java +++ b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/reflect/AccessibleObject.java @@ -172,14 +172,14 @@ public class AccessibleObject implements * @throws NullPointerException if any of the arguments is null */ void appendArrayType(StringBuilder sb, Class obj) { - Class simplified = obj.getComponentType(); - if (simplified == null) { + if (!obj.isArray()) { sb.append(obj.getName()); return; } int dimensions = 1; + Class simplified = obj.getComponentType(); obj = simplified; - while ((simplified = obj.getComponentType()) != null) { + while (simplified.isArray()) { obj = simplified; dimensions++; } 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 e777843..81cc958 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 @@ -130,9 +130,9 @@ JNIEXPORT jclass JNICALL Java_java_lang_ int primitives_len = sizeof(primitives) / sizeof(Class*); for (int i = 0; i < primitives_len; i++) { - if (primitives[i] && primitives[i]->name) { - char *pname = (char*)primitives[i]->name->bytes; - if (0 == strcmp(buf, pname)) { + if (primitives[i] && primitives[i]->get_name()) { + char *pname = (char*)primitives[i]->get_name()->bytes; + if (0 == strcmp(buf, pname)) { STD_FREE(buf); return NULL; } @@ -201,7 +201,7 @@ JNIEXPORT jclass JNICALL Java_java_lang_ (JNIEnv *jenv, jclass, jclass clazz) { Class_Handle ch = jni_get_class_handle(jenv, clazz); - Class *pCompClass = ((Class*)ch)->array_element_class; + Class* pCompClass = ch->get_array_element_class(); return jni_class_from_handle(jenv, pCompClass); } @@ -323,7 +323,7 @@ JNIEXPORT jint JNICALL Java_java_lang_VM (JNIEnv *jenv, jclass, jclass clazz) { Class_Handle clss = jni_get_class_handle(jenv, clazz); - return class_get_flags(clss) & (~ACC_SUPER); + return clss->get_access_flags() & (~ACC_SUPER); } /* @@ -336,7 +336,7 @@ JNIEXPORT jstring JNICALL Java_java_lang { ASSERT_RAISE_AREA; Class* clss = jclass_to_struct_Class(clazz); - String* str = class_get_java_name(clss, VM_Global_State::loader_env); + String* str = clss->get_java_name(); return String_to_interned_jstring(str); } @@ -350,12 +350,12 @@ JNIEXPORT jclass JNICALL Java_java_lang_ { Class *clss = jni_get_class_handle(jenv, clazz); - if (class_is_interface (clss) || clss->is_primitive || !clss->super_class) { + if (clss->is_interface() || clss->is_primitive() || !clss->has_super_class()) { // Interfaces and primitive classes have no superclasses. return (jclass)0; } - return jni_class_from_handle(jenv, clss->super_class); + return jni_class_from_handle(jenv, clss->get_super_class()); } /* @@ -376,7 +376,7 @@ JNIEXPORT jobjectArray JNICALL Java_java } jclass string_class = struct_Class_to_java_lang_Class_Handle(genv->JavaLangString_Class); - static Class* aos = genv->LoadCoreClass(genv->string_pool.lookup("[Ljava/lang/String;")); + static Class* aos = genv->LoadCoreClass("[Ljava/lang/String;"); jclass string_array_class = struct_Class_to_java_lang_Class_Handle(aos); assert(string_class); assert(string_array_class); @@ -577,17 +577,17 @@ JNIEXPORT jclass JNICALL Java_java_lang_ { assert(jclazz); Class* clazz = jclass_to_struct_Class(jclazz); - unsigned idx = clazz->enclosing_class_index; + unsigned idx = clazz->get_enclosing_class_index(); if (!idx) { - idx = clazz->declaringclass_index; + idx = clazz->get_declaring_class_index(); } if (idx) { - Class* outer_clss = class_resolve_class(clazz, idx); + Class* outer_clss = clazz->_resolve_class(VM_Global_State::loader_env, idx); if (outer_clss) { - return struct_Class_to_java_lang_Class_Handle(outer_clss); + return struct_Class_to_jclass(outer_clss); } if (!exn_raised()) { - exn_raise_object(class_get_linking_error(clazz, idx)); + exn_raise_object(clazz->get_constant_pool().get_error_cause(idx)); } } return NULL; @@ -603,20 +603,20 @@ JNIEXPORT jobject JNICALL Java_java_lang { assert(jclazz); Class* clazz = jclass_to_struct_Class(jclazz); - unsigned m_idx = clazz->enclosing_method_index; - if (m_idx) { - unsigned c_idx = clazz->enclosing_class_index; + unsigned method_idx = clazz->get_enclosing_method_index(); + if (method_idx) { + unsigned c_idx = clazz->get_enclosing_class_index(); ASSERT(c_idx, "No class for enclosing method"); - Class* outer_clss = class_resolve_class(clazz, c_idx); + Class* outer_clss = clazz->_resolve_class(VM_Global_State::loader_env, 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->get_constant_pool().get_name_and_type_name(method_idx); + String* desc = clazz->get_constant_pool().get_name_and_type_descriptor(method_idx); - TRACE("Looking for enclosing method: class="<name->bytes + TRACE("Looking for enclosing method: class="<get_name()->bytes <<"; name="<bytes<<"; desc="<bytes); - Method* enclosing = class_lookup_method(outer_clss, name, desc); + Method* enclosing = outer_clss->lookup_method(name, desc); if (enclosing) { if (enclosing->is_init()) @@ -633,7 +633,7 @@ JNIEXPORT jobject JNICALL Java_java_lang "Invalid enclosing method declared"); } } else if (!exn_raised()) { - exn_raise_object(class_get_linking_error(clazz, c_idx)); + exn_raise_object(clazz->get_constant_pool().get_error_cause(c_idx)); } } return NULL; @@ -650,6 +650,6 @@ JNIEXPORT jstring JNICALL Java_java_lang ASSERT_RAISE_AREA; assert(jclazz); Class* clazz = jclass_to_struct_Class(jclazz); - String* str = class_get_simple_name(clazz, VM_Global_State::loader_env); + String* str = clazz->get_simple_name(); return str ? String_to_interned_jstring(str) : NULL; } diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.cpp index 1aba330..73df6f7 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.cpp @@ -93,11 +93,11 @@ JNIEXPORT jint JNICALL Java_java_lang_VM if(jclss) { Class* clss = jclass_to_struct_Class(jclss); - while (clss->declaringclass_index) { + while (clss->get_declaring_class_index()) { clss = class_get_declaring_class((Class_Handle)clss); } - const char* name = class_get_java_name(clss, genv)->bytes; - bool system = (((void*)clss->class_loader) == ((void*)genv->bootstrap_class_loader)); + const char* name = clss->get_java_name()->bytes; + bool system = (((void*)clss->get_class_loader()) == ((void*)genv->bootstrap_class_loader)); TRACE("check assert status for " << name << " system=" << system); if (system || !recursive) { status = reg->get_class_status(name); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_reflect_VMField.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_reflect_VMField.cpp index 3c2b944..26412d5 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_reflect_VMField.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_lang_reflect_VMField.cpp @@ -36,6 +36,7 @@ #include "exceptions.h" #include "primitives_support.h" #include "jni_utils.h" +#include "type.h" #include "java_lang_reflect_VMField.h" @@ -175,7 +176,7 @@ JNIEXPORT jobject JNICALL Java_java_lang jobject retobj = NULL; - if (field->get_field_type_desc()->is_primitive()) + if (field->get_field_type_desc()->is_primitive()) { char field_sig = field->get_descriptor()->bytes[0]; jvalue primitive_value = read_primitive(jenv, (jfieldID)field, obj, field_sig); @@ -286,7 +287,7 @@ JNIEXPORT void JNICALL Java_java_lang_re if (field->get_field_type_desc()->is_primitive()) { - char value_sig = value ? is_wrapper_class(jobject_to_struct_Class(value)->name->bytes) : 0; + char value_sig = value ? is_wrapper_class(jobject_to_struct_Class(value)->get_name()->bytes) : 0; if (!value_sig) { // the value is not primitive ThrowNew_Quick(jenv, "java/lang/IllegalArgumentException", @@ -302,7 +303,7 @@ JNIEXPORT void JNICALL Java_java_lang_re Class* value_clss = jobject_to_struct_Class(value); Class* clss = field->get_field_type_desc()->load_type_desc(); assert(clss); - if (!class_is_subtype_fast(value_clss->vtable, clss)) { + if (!value_clss->is_instanceof(clss)) { ThrowNew_Quick(jenv, "java/lang/IllegalArgumentException", "The specified value cannot be converted to the field's type type by an identity or widening conversions"); return; 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 dc01def..9f2c890 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 "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" @@ -112,7 +113,7 @@ static bool rethrow_invocation_exception jthrowable exn = exn_get(); //FIXME need better handling for lazy exceptions if (!exn) { - WARN("ATTENTION! Could not get cause exception from lazy machinery"); + WARN("ATTENTION! Could not get cause exception from lazy machinery"); } exn_clear(); //static Class* ITE_class = genv->LoadCoreClass( @@ -199,7 +200,7 @@ JNIEXPORT jobject JNICALL Java_java_lang Class* type = VM_Global_State::loader_env->java_lang_reflect_Method_Class; Method_Handle method = (Method_Handle) ((POINTER_SIZE_INT) member); - TRACE("invoke : " << method->get_class()->name->bytes << "." << method->get_name()->bytes << "()"); + TRACE("invoke : " << method->get_class()->get_name()->bytes << "." << method->get_name()->bytes << "()"); unsigned num_args = method->get_num_args(); jvalue *jvalue_args = (jvalue *)STD_ALLOCA(num_args * sizeof(jvalue)); @@ -302,7 +303,7 @@ JNIEXPORT jobject JNICALL Java_java_lang { Method_Handle method = (Method_Handle) ((POINTER_SIZE_INT) member); - TRACE("new class instance : " << method->get_class()->name->bytes); + TRACE("new class instance : " << method->get_class()->get_name()->bytes); unsigned num_args = method->get_num_args(); jvalue *jvalue_args = (jvalue *)STD_ALLOCA(num_args * sizeof(jvalue)); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_util_concurrent_Atomics.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_util_concurrent_Atomics.cpp index 38fa27d..83aa9cc 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_util_concurrent_Atomics.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_util_concurrent_Atomics.cpp @@ -39,7 +39,7 @@ JNIEXPORT jint JNICALL Java_org_apache_h (JNIEnv * env, jclass self, jclass array) { Class * clz = jclass_to_struct_Class(array); - return clz->array_element_size; + return clz->get_array_element_size(); } JNIEXPORT void JNICALL diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMGenericsAndAnnotations.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMGenericsAndAnnotations.cpp index 566acce..210f3be 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMGenericsAndAnnotations.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMGenericsAndAnnotations.cpp @@ -52,7 +52,7 @@ JNIEXPORT jstring JNICALL Java_org_apach (JNIEnv *jenv, jclass, jclass jclazz) { Class* clazz = jclass_to_struct_Class(jclazz); - String* sig = clazz->Signature; + String* sig = clazz->get_signature(); TRACE("Signature of " << clazz << " : " << sig); return sig ? NewStringUTF(jenv, sig->bytes) : NULL; } @@ -70,7 +70,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_ { Class* clazz = jclass_to_struct_Class(jclazz); TRACE("Requested annotations for class " << clazz); - return get_annotations(jenv, clazz->annotations, clazz); + return get_annotations(jenv, clazz->get_annotations(), clazz); } JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_vm_VMGenericsAndAnnotations_getParameterAnnotations @@ -81,7 +81,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_ Class* declaring_class = method->get_class(); static Class* array_class = genv->LoadCoreClass( - genv->string_pool.lookup("[Ljava/lang/annotation/Annotation;")); + "[Ljava/lang/annotation/Annotation;"); unsigned num = method->get_num_param_annotations(); TRACE("Requested parameters annotations for method " << method diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.cpp index 75e9c0a..e369556 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.cpp @@ -278,8 +278,8 @@ JNIEXPORT jobjectArray JNICALL Java_org_ jclass ste = struct_Class_to_java_lang_Class_Handle(genv->java_lang_StackTraceElement_Class); assert(ste); - static jmethodID init = (jmethodID) class_lookup_method( - genv->java_lang_StackTraceElement_Class, genv->Init_String, + static jmethodID init = (jmethodID) genv->java_lang_StackTraceElement_Class->lookup_method( + genv->Init_String, genv->string_pool.lookup("(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V")); jarray arr = jenv->NewObjectArray(size - skip, ste, NULL); @@ -314,7 +314,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_ tmn_suspend_disable(); // class name - String* className = class_get_java_name(method->get_class(), genv); + String* className = method->get_class()->get_java_name(); strClassName->object = vm_instantiate_cp_string_resolved(className); if (!strClassName->object) { tmn_suspend_enable(); @@ -391,7 +391,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_ assert(method); // skip only for main application thread if (!strcmp(method_get_name(method), "run") - && method->get_class()->name == starter_String) { + && method->get_class()->get_name() == starter_String) { size -= size < 3 ? size : 3; } @@ -399,8 +399,8 @@ JNIEXPORT jobjectArray JNICALL Java_org_ jclass ste = struct_Class_to_java_lang_Class_Handle(genv->java_lang_StackTraceElement_Class); assert(ste); - static jmethodID init = (jmethodID) class_lookup_method( - genv->java_lang_StackTraceElement_Class, genv->Init_String, + static jmethodID init = (jmethodID)genv->java_lang_StackTraceElement_Class->lookup_method( + genv->Init_String, genv->string_pool.lookup("(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V")); jarray arr = jenv->NewObjectArray(size, ste, NULL); @@ -431,8 +431,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_ tmn_suspend_disable(); // class name - String* className = class_get_java_name(method->get_class(), - VM_Global_State::loader_env); + String* className = method->get_class()->get_java_name(); strClassName->object = vm_instantiate_cp_string_resolved(className); if (!strClassName->object) { tmn_suspend_enable(); 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 2bbd48a..5c483b7 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,13 @@ #include "thread_manager.h" #include "open/types.h" #include "open/vm_util.h" +#include "vtable.h" + +#ifndef NDEBUG +// this is for managed object sanity checks +// (used in monitor enter/exit functions) +#include "Class.h" +#endif static ObjectHandlesOld* oh_allocate_object_handle(); @@ -173,8 +180,8 @@ object_is_java_lang_class(ObjectHandle o static bool managed_object_object_is_valid_unsafe(ManagedObject* p_obj) { Class* clss = p_obj->vt()->clss; - assert(clss->vtable->clss == clss); - return managed_object_is_java_lang_class_unsafe(*clss->class_handle); + assert(clss->get_vtable()->clss == clss); + return managed_object_is_java_lang_class_unsafe(*(clss->get_class_handle())); } bool @@ -352,18 +359,19 @@ VMEXPORT // temporary solution for inter ObjectHandle oh_allocate_local_handle() { assert(!hythread_is_suspend_enabled()); - // FIXME: it looks like this should be uncoment or suspend_disable added - //assert(!hythread_is_suspend_enabled()); - - - // ? 20021202 There are really 3 cases to check: - // 1) JNI transition: both LJF and LJF->local_object_handles are non-NULL. Any local handles will be cleaned up on return. - // 2) RNI/stub transition: LJF is non-NULL but LJF->local_object_handles is NULL. Although an LJF frame was pushed, - // local handles will NOT be cleaned up, so to avoid a storage leak we use the same code as case 3) below. - // 3) LJF is NULL. Native code uses Native_Local_Object_Handles, whose destructor cleans up any local handles. - - // As of 2005-03-05, RNI is not used at all, and we need local handles, - // so 2) is handled by creating new local handles. + + // There are really 3 cases to check: + // 1) JNI transition: both LJF and LJF->local_object_handles are + // non-NULL. Any local handles will be cleaned up on return. + // 2) RNI/stub transition: LJF is non-NULL but LJF->local_object_handles + // is NULL. Although an LJF frame was pushed, local handles will NOT + // be cleaned up, so to avoid a storage leak we use the same code as + // case (3) below. + // 3) LJF is NULL. Native code uses Native_Local_Object_Handles, whose + // destructor cleans up any local handles. + + // RNI is not used at all, and we need local handles, so (2) is handled by + // creating new local handles. // XXX: need to check against leaks. -salikh M2nFrame* lm2nf = m2n_get_last_frame(); @@ -526,7 +534,8 @@ LilCodeStub* oh_gen_init_handle(LilCodeS if (null_check && VM_Global_State::loader_env->compress_references) { sprintf(buf, "jc %s=%p:ref,%%n; st [%s+%d:ref],%s; j %%o; :%%g; st [%s+%d:ref],0; :%%g;", - val, Class::heap_base, base_var, offset, val, base_var, offset); + val, VM_Global_State::loader_env->heap_base, base_var, offset, + val, base_var, offset); } else { sprintf(buf, "st [%s+%d:ref],%s;", base_var, offset, val); } diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/object/vm_arrays.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/object/vm_arrays.cpp index 4a66df6..04eef18 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/object/vm_arrays.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/object/vm_arrays.cpp @@ -38,17 +38,6 @@ #include "vm_stats.h" -#define BITS_PER_BYTE 8 -#define HIGH_BIT_SET_MASK (1<<((sizeof(unsigned) * BITS_PER_BYTE)-1)) -#define HIGH_BIT_CLEAR_MASK (~HIGH_BIT_SET_MASK) -#ifndef NEXT_TO_HIGH_BIT_SET_MASK -#define NEXT_TO_HIGH_BIT_SET_MASK (1<<((sizeof(unsigned) * BITS_PER_BYTE)-2)) -#define NEXT_TO_HIGH_BIT_CLEAR_MASK (~NEXT_TO_HIGH_BIT_SET_MASK) -#endif /* #ifndef NEXT_TO_HIGH_BIT_SET_MAS */ -#define TWO_HIGHEST_BITS_SET_MASK (HIGH_BIT_SET_MASK|NEXT_TO_HIGH_BIT_SET_MASK) - - - ///////////////////////////////////////////////////////////// // begin vector access functions // @@ -81,7 +70,7 @@ static Vector_Handle vm_anewarray_resolv #endif ASSERT_RAISE_AREA; assert(!hythread_is_suspend_enabled()); - assert(!arr_clss->is_array_of_primitives); + assert(!arr_clss->is_array_of_primitives()); if (length < 0) { tmn_suspend_enable(); @@ -90,7 +79,7 @@ static Vector_Handle vm_anewarray_resolv return NULL; } - unsigned sz = vm_array_size(arr_clss->vtable, length); + unsigned sz = arr_clss->calculate_array_size(length); if ((length & TWO_HIGHEST_BITS_SET_MASK) || (sz & TWO_HIGHEST_BITS_SET_MASK)) { // VM does not support arrays of length >= MAXINT>>2 @@ -102,10 +91,10 @@ static Vector_Handle vm_anewarray_resolv return NULL; } - Vector_Handle object_array = (Vector_Handle )gc_alloc(sz, arr_clss->allocation_handle, vm_get_gc_thread_local()); + Vector_Handle object_array = (Vector_Handle )gc_alloc(sz, + arr_clss->get_allocation_handle(), vm_get_gc_thread_local()); #ifdef VM_STATS - arr_clss->num_allocations++; - arr_clss->num_bytes_allocated += sz; + arr_clss->instance_allocated(sz); #endif //VM_STATS if (NULL == object_array) { @@ -115,7 +104,7 @@ static Vector_Handle vm_anewarray_resolv } set_vector_length(object_array, length); - assert(get_vector_vtable(object_array) == arr_clss->vtable); + assert(get_vector_vtable(object_array) == arr_clss->get_vtable()); return object_array; } //vm_anewarray_resolved_array_type @@ -145,14 +134,12 @@ Vector_Handle vm_new_vector_primitive(Cl tmn_suspend_disable(); return NULL; } - assert(vector_class->is_array_of_primitives); - assert(vector_class->vtable); - unsigned sz = vm_array_size(vector_class->vtable, length); + assert(vector_class->is_array_of_primitives()); + unsigned sz = vector_class->calculate_array_size(length); Vector_Handle vector = (Vector_Handle)gc_alloc(sz, - vector_class->allocation_handle, vm_get_gc_thread_local()); + vector_class->get_allocation_handle(), vm_get_gc_thread_local()); #ifdef VM_STATS - vector_class->num_allocations++; - vector_class->num_bytes_allocated += sz; + vector_class->instance_allocated(sz); #endif //VM_STATS if (NULL == vector) { @@ -162,7 +149,7 @@ Vector_Handle vm_new_vector_primitive(Cl } set_vector_length(vector, length); - assert(get_vector_vtable(vector) == vector_class->vtable); + assert(get_vector_vtable(vector) == vector_class->get_vtable()); return vector; } @@ -172,7 +159,7 @@ Vector_Handle vm_new_vector(Class *vecto ASSERT_RAISE_AREA; Vector_Handle returned_vector; - if(vector_class->is_array_of_primitives) { + if(vector_class->is_array_of_primitives()) { returned_vector = vm_new_vector_primitive(vector_class,length); } else { returned_vector = vm_anewarray_resolved_array_type(vector_class, length); @@ -197,10 +184,9 @@ void vm_new_vector_update_stats(int leng #ifdef VM_STATS if (0 != (length&TWO_HIGHEST_BITS_SET_MASK)) return; VTable *vector_vtable = ManagedObject::allocation_handle_to_vtable(vector_handle); - unsigned sz = vm_array_size(vector_vtable, (unsigned)length); - vector_vtable->clss->num_allocations++; - vector_vtable->clss->num_bytes_allocated += sz; - if (!get_prop_non_ref_array(vector_vtable->class_properties)) + unsigned sz = vector_vtable->clss->calculate_array_size(length); + vector_vtable->clss->instance_allocated(sz); + if((vector_vtable->class_properties & CL_PROP_NON_REF_ARRAY_MASK) == 0) { VM_Statistics::get_vm_stats().num_anewarray++; } @@ -225,10 +211,9 @@ Vector_Handle vm_new_vector_using_vtable } VTable *vector_vtable = ManagedObject::allocation_handle_to_vtable(vector_handle); - unsigned sz = vm_array_size(vector_vtable, length); + unsigned sz = vector_vtable->clss->calculate_array_size(length); #ifdef VM_STATSxxx // Functionality moved into vm_new_vector_update_stats(). - vector_vtable->clss->num_allocations++; - vector_vtable->clss->num_bytes_allocated += sz; + vector_vtable->clss->instance_allocated(sz); #endif //VM_STATS assert( ! hythread_is_suspend_enabled()); Vector_Handle vector = (Vector_Handle)gc_alloc(sz, vector_handle, tp); @@ -256,21 +241,13 @@ Vector_Handle vm_new_vector_or_null_usin } VTable *vector_vtable = ManagedObject::allocation_handle_to_vtable(vector_handle); - unsigned sz = vm_array_size(vector_vtable, length); + unsigned sz = vector_vtable->clss->calculate_array_size(length); Vector_Handle vector = (Vector_Handle)gc_alloc_fast(sz, vector_handle, tp); if (vector == NULL) { return NULL; } -#ifdef VM_STATSxxx // Functionality moved into vm_new_vector_update_stats(). - vector_vtable->clss->num_allocations++; - vector_vtable->clss->num_bytes_allocated += sz; - if (!get_prop_non_ref_array(vector_vtable->class_properties)) - { - VM_Statistics::get_vm_stats().num_anewarray++; - } -#endif //VM_STATS - + set_vector_length(vector, length); assert(get_vector_vtable(vector) == vector_vtable); return vector; @@ -323,13 +300,13 @@ vm_multianewarray_recursive(Class *c, // init Class* array clss[0] = c; - assert(c->name->bytes[0] == '['); - assert(c->name->len > 1); + assert(c->get_name()->bytes[0] == '['); + assert(c->get_name()->len > 1); for(d = 1; d < dims; d++) { - c = c->array_element_class; - assert(c->name->bytes[0] == '['); - assert(c->name->len > 1); + c = c->get_array_element_class(); + assert(c->get_name()->bytes[0] == '['); + assert(c->get_name()->len > 1); clss[d] = c; } @@ -445,8 +422,8 @@ static void increment_array_copy_counter ArrayCopyResult array_copy(ManagedObject *src, int32 srcOffset, ManagedObject *dst, int32 dstOffset, int32 length) { - if (src == ((ManagedObject *)Class::managed_null) || - dst == ((ManagedObject *)Class::managed_null)) { + if (src == ((ManagedObject *)VM_Global_State::loader_env->managed_null) || + dst == ((ManagedObject *)VM_Global_State::loader_env->managed_null)) { return ACR_NullPointer; } @@ -455,12 +432,12 @@ ArrayCopyResult array_copy(ManagedObject Class *dst_class = dst->vt()->clss; assert(dst_class); - if (!(src_class->is_array && dst_class->is_array)) return ACR_TypeMismatch; - assert(src_class->name->bytes[0] == '['); - assert(dst_class->name->bytes[0] == '['); + if (!(src_class->is_array() && dst_class->is_array())) return ACR_TypeMismatch; + assert(src_class->get_name()->bytes[0] == '['); + assert(dst_class->get_name()->bytes[0] == '['); - if (src_class->name != dst_class->name - && (src_class->is_array_of_primitives || dst_class->is_array_of_primitives)) { + if (src_class->get_name() != dst_class->get_name() + && (src_class->is_array_of_primitives() || dst_class->is_array_of_primitives())) { return ACR_TypeMismatch; } @@ -476,7 +453,7 @@ ArrayCopyResult array_copy(ManagedObject if((srcOffset + length) > src_length || (dstOffset + length) > dst_length) return ACR_BadIndices; - char src_elem_type = src_class->name->bytes[1]; + char src_elem_type = src_class->get_name()->bytes[1]; switch(src_elem_type) { case 'C': @@ -591,7 +568,7 @@ ArrayCopyResult array_copy(ManagedObject #ifdef VM_STATS increment_array_copy_counter(VM_Statistics::get_vm_stats().num_arraycopy_object_different_type); #endif // VM_STATS - Class *dst_elem_clss = dst_class->array_element_class; + Class* dst_elem_clss = dst_class->get_array_element_class(); assert(dst_elem_clss); if (VM_Global_State::loader_env->compress_references) { @@ -604,8 +581,8 @@ ArrayCopyResult array_copy(ManagedObject ManagedObject *src_elem = (ManagedObject *)uncompress_compressed_reference(src_elem_offset); Class *src_elem_clss = src_elem->vt()->clss; if (src_elem_clss == dst_elem_clss) { - } else if (!class_is_subtype_fast(src_elem_clss->vtable, dst_elem_clss)) { - // note: VM_STATS values are updated when class_is_subtype_fast() is called. + } else if (!src_elem_clss->is_instanceof(dst_elem_clss)) { + // note: VM_STATS values are updated when Class::is_instanceof() is called. // Since we only flag the base do it before we throw exception gc_heap_wrote_object(dst); return ACR_TypeMismatch; @@ -621,7 +598,7 @@ ArrayCopyResult array_copy(ManagedObject if (src_body[count] != NULL) { Class *src_elem_clss = src_body[count]->vt()->clss; if (src_elem_clss == dst_elem_clss) { - } else if (!class_is_subtype_fast(src_elem_clss->vtable, dst_elem_clss)) { + } else if (!src_elem_clss->is_instanceof(dst_elem_clss)) { // note: VM_STATS values are updated when class_is_subtype_fast() is called. // Since we only flag the base do it before we throw exception gc_heap_wrote_object(dst); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/reflection/annotations.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/reflection/annotations.cpp index 97693ea..a7c76c7 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/reflection/annotations.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/reflection/annotations.cpp @@ -29,6 +29,7 @@ #include "annotations.h" #include "jni.h" #include "jni_utils.h" +#include "type.h" #include "environment.h" #include "reflection.h" #include "exceptions.h" @@ -69,7 +70,7 @@ static Class* field_descriptor_to_type(J jthrowable* cause = NULL) { Type_Info_Handle tih = (Type_Info_Handle) - type_desc_create_from_java_descriptor(desc->bytes, clss->class_loader); + type_desc_create_from_java_descriptor(desc->bytes, clss->get_class_loader()); if (tih) { Class* type = type_info_get_class(tih); if (type) { @@ -114,7 +115,7 @@ jobject resolve_annotation(JNIEnv* jenv, if (!antn_type) { return NULL; } - if (!class_is_annotation(antn_type)) { + if (!antn_type->is_annotation()) { std::stringstream ss; ss << "Non-annotation type : " << antn->type->bytes; ThrowNew_Quick(jenv, "java/lang/annotation/AnnotationFormatError", ss.str().c_str()); @@ -198,7 +199,7 @@ static jobject process_enum_value(JNIEnv } } else { std::stringstream ss; - ss << "Invalid enum type " << enum_type->name->bytes + ss << "Invalid enum type " << enum_type->get_name()->bytes << " specified for value of element \'" << name->bytes << "\'"; ThrowNew_Quick(jenv, "java/lang/annotation/AnnotationFormatError", ss.str().c_str()); } @@ -279,7 +280,7 @@ static bool process_array_element(JNIEnv // primitive value type does not match array type std::stringstream ss; ss << "Encountered value tag \'" << (char)value.tag - << "\' does not match array type " << type->name->bytes << "[]"; + << "\' does not match array type " << type->get_name()->bytes << "[]"; *cause = CreateNewThrowable(jenv, genv->java_lang_ArrayStoreException_Class, ss.str().c_str(), NULL); @@ -350,8 +351,8 @@ jobject resolve_annotation_value(JNIEnv* // of the element-defining method. Class* arr_type = NULL; unsigned i; - for (i = 0; i < antn_type->n_methods; i++) { - Method* m = antn_type->methods + i; + for (i = 0; i < antn_type->get_number_of_methods(); i++) { + Method* m = antn_type->get_method(i); if (m->get_name() == name && m->get_num_args() == 1) { Type_Info_Handle tih = method_ret_type_get_type_info( @@ -366,13 +367,13 @@ jobject resolve_annotation_value(JNIEnv* break; } } - if (!arr_type || arr_type->n_dimensions != 1) { + if (!arr_type || arr_type->get_number_of_dimensions() != 1) { std::stringstream ss; ss << "Invalid array value for element \'" << name->bytes << "\'"; ThrowNew_Quick(jenv, "java/lang/annotation/AnnotationFormatError", ss.str().c_str()); return NULL; } - arr_type = arr_type->array_element_class; + arr_type = arr_type->get_array_element_class(); jclass jarr_type = struct_Class_to_java_lang_Class_Handle(arr_type); jarray array = NewObjectArray(jenv, (jsize)value.array.length, jarr_type, NULL); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/reflection/reflection.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/reflection/reflection.cpp index 4ed27ed..bd7c5f3 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/reflection/reflection.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/reflection/reflection.cpp @@ -83,7 +83,7 @@ static jobject reflect_member(JNIEnv *je static Global_Env* genv = VM_Global_State::loader_env; static String* desc = genv->string_pool.lookup( "(JLjava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V"); - Method* member_constr = class_lookup_method(type, genv->Init_String, desc); + Method* member_constr = type->lookup_method(genv->Init_String, desc); jstring jname = String_to_interned_jstring(member->get_name()); if (jname == NULL) { @@ -308,11 +308,11 @@ bool jobjectarray_to_jvaluearray(JNIEnv { ASSERT(arg, "Cannot unwrap NULL"); Class* arg_clss = jobject_to_struct_Class(arg); - char arg_sig = is_wrapper_class(arg_clss->name->bytes); + char arg_sig = is_wrapper_class(arg_clss->get_name()->bytes); char param_sig = (char)type; ASSERT(arg_sig, "Reflection arguments mismatch: expected " - << param_sig << " but was " << arg_clss->name->bytes); + << param_sig << " but was " << arg_clss->get_name()->bytes); array[arg_number] = unwrap_primitive(jenv, arg, arg_sig); @@ -332,14 +332,14 @@ bool jobjectarray_to_jvaluearray(JNIEnv jobject reflection_get_enum_value(JNIEnv *jenv, Class* enum_type, String* name) { ASSERT(class_is_enum(enum_type), "Requested Class is not ENUM: " - << enum_type->name->bytes); + << enum_type->get_name()->bytes); - for (unsigned i=0; in_fields; i++) { - if (enum_type->fields[i].get_name() == name) { + for (unsigned i=0; iget_number_of_fields(); i++) { + if (enum_type->get_field(i)->get_name() == name) { #ifndef NDEBUG - ASSERT(enum_type->fields[i].is_enum(), "Requested field is not ENUM: " << name->bytes); - const String* type = enum_type->name; - const String* desc = enum_type->fields[i].get_descriptor(); + ASSERT(enum_type->get_field(i)->is_enum(), "Requested field is not ENUM: " << name->bytes); + const String* type = enum_type->get_name(); + const String* desc = enum_type->get_field(i)->get_descriptor(); if (desc->len != (type->len + 2) || desc->bytes[0] != 'L' || strncmp(desc->bytes + 1, type->bytes, type->len) @@ -348,7 +348,7 @@ jobject reflection_get_enum_value(JNIEnv DIE("Invalid enum field descriptor: " << desc->bytes); } #endif - return GetStaticObjectField(jenv, 0, (jfieldID)(enum_type->fields + i)); + return GetStaticObjectField(jenv, 0, (jfieldID)(enum_type->get_field(i))); } } //public EnumConstantNotPresentException(Class enumType,String constantName) 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..605d2f8 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 "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 @@ -170,19 +172,19 @@ static void st_get_java_method_info(Meth info->line = -1; info->method_name = NULL; assert(m); - if (m->get_class()->src_file_name && m->get_class()->src_file_name->bytes) { - const char* fname = m->get_class()->src_file_name->bytes; - size_t flen = strlen(fname); + if (m->get_class()->has_source_information() && m->get_class()->get_source_file_name()) { + const char* fname = m->get_class()->get_source_file_name(); + size_t flen = m->get_class()->get_source_file_name_length(); info->file_name = (char*) STD_MALLOC(flen + 1); strcpy(info->file_name, fname); } const char* mname = m->get_name()->bytes; - size_t mlen = strlen(mname); - const char* cname = m->get_class()->name->bytes; - size_t clen = strlen(cname); + size_t mlen = m->get_name()->len; + const char* cname = m->get_class()->get_name()->bytes; + size_t clen = m->get_class()->get_name()->len; const char* descr = m->get_descriptor()->bytes; - size_t dlen = strlen(descr); + size_t dlen = m->get_descriptor()->len; info->method_name = (char*) STD_MALLOC(mlen + clen + dlen + 2); memcpy(info->method_name, cname, clen); 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 96d5e35..718a94d 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 "jit_intf_cpp.h" #include "environment.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/mon_enter_exit.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/thread/mon_enter_exit.cpp index 311543a..cf350dd 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/thread/mon_enter_exit.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/thread/mon_enter_exit.cpp @@ -40,6 +40,7 @@ using namespace std; #include "stack_iterator.h" #include "Class.h" #include "jit_intf_cpp.h" +#include "cci.h" #include "mon_enter_exit.h" #include "thread_generic.h" diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/thread/object_generic.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/thread/object_generic.cpp index eeb15b8..61124b7 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/thread/object_generic.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/thread/object_generic.cpp @@ -84,8 +84,8 @@ jint default_hashcode(Managed_Object_Han set_hash_bits(p_obj); if ( *P_HASH_CONTENTION_BYTE(p_obj) & HASH_MASK) - return *P_HASH_CONTENTION_BYTE(p_obj) & HASH_MASK; - + return *P_HASH_CONTENTION_BYTE(p_obj) & HASH_MASK; + ASSERT(0, "All the possible cases are supposed to be covered before"); return 0xff; } @@ -124,14 +124,14 @@ jobject object_clone(JNIEnv *jenv, jobje ObjectHandle h = (ObjectHandle) jobj; VTable *vt = h->object->vt(); unsigned size; - if (get_prop_array(vt->class_properties)) + if((vt->class_properties & CL_PROP_ARRAY_MASK) != 0) { // clone an array int32 length = get_vector_length((Vector_Handle) h->object); - size = vm_array_size(vt, length); - result = (ManagedObject *) - vm_new_vector_using_vtable_and_thread_pointer( - length, vt->clss->allocation_handle, vm_get_gc_thread_local()); + size = vt->clss->calculate_array_size(length); + result = (ManagedObject*) + vm_new_vector_using_vtable_and_thread_pointer(length, + vt->clss->get_allocation_handle(), vm_get_gc_thread_local()); } else { @@ -144,8 +144,7 @@ jobject object_clone(JNIEnv *jenv, jobje return NULL; } size = vt->allocated_size; - result = (ManagedObject *) vm_alloc_and_report_ti(size, - vt->clss->allocation_handle, vm_get_gc_thread_local(), vt->clss); + result = vt->clss->allocate_instance(); } if (result == NULL) { tmn_suspend_enable(); 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..04c6ddf 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,13 @@ #include "dll_jit_intf.h" #include "object_generic.h" +#include "Class.h" +#include "vtable.h" +#include "environment.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/thread/thread_manager.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_manager.cpp index 3b0642d..17bf6f2 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_manager.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_manager.cpp @@ -179,7 +179,7 @@ void *vm_object_get_lockword_addr(jobjec } extern "C" char *vm_get_object_class_name(void* ptr) { - return (char*) (((ManagedObject*)ptr)->vt()->clss->name->bytes); + return (char*)(((ManagedObject*)ptr)->vt()->clss->get_name()->bytes); } void* vm_jthread_get_tm_data(jthread thread) diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/util/em64t/base/ini_em64t.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/util/em64t/base/ini_em64t.cpp index 622743a..85f665a 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/em64t/base/ini_em64t.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/em64t/base/ini_em64t.cpp @@ -211,7 +211,7 @@ void JIT_execute_method_default(JIT_Hand assert(VM_Global_State::loader_env->compress_references); // convert from native to managed NULL gr_args[gr_nargs++] = handle->object != NULL - ? (uint64) handle->object : (uint64) Class::managed_null; + ? (uint64) handle->object : (uint64) VM_Global_State::loader_env->managed_null; } Java_Type type; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/compile_IA32.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/compile_IA32.cpp index 8fb45de..66736c9 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/compile_IA32.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/compile_IA32.cpp @@ -37,6 +37,7 @@ using namespace std; #include "open/types.h" #include "Class.h" +#include "type.h" #include "environment.h" #include "method_lookup.h" #include "stack_iterator.h" @@ -59,6 +60,7 @@ using namespace std; #include "vm_synch.h" #include "vm_threads.h" #include "ini.h" +#include "type.h" #include "compile.h" #include "lil.h" @@ -156,7 +158,7 @@ char * gen_convert_managed_to_unmanaged_ unsigned stack_pointer_offset) { if (VM_Global_State::loader_env->compress_references) { ss = mov(ss, eax_opnd, M_Base_Opnd(esp_reg, stack_pointer_offset)); - ss = alu(ss, cmp_opc, eax_opnd, Imm_Opnd((int32)Class::heap_base) ); + ss = alu(ss, cmp_opc, eax_opnd, Imm_Opnd((int32)VM_Global_State::loader_env->heap_base) ); ss = branch8(ss, Condition_NE, Imm_Opnd(size_8, 0)); // not null, branch around the mov 0 char *backpatch_address__not_managed_null = ((char *)ss) - 1; ss = mov(ss, M_Base_Opnd(esp_reg, stack_pointer_offset), Imm_Opnd(0)); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/ini_iA32.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/ini_iA32.cpp index ba42123..56fb44c 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/ini_iA32.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/ini_iA32.cpp @@ -119,7 +119,7 @@ JIT_execute_method_default(JIT_Handle ji Method *method = (Method*) methodID; TRACE("enter method " - << method->get_class()->name->bytes << " " + << method->get_class()->get_name()->bytes << " " << method->get_name()->bytes << " " << method->get_descriptor()->bytes); int sz = method->get_num_arg_bytes() >> 2; @@ -247,7 +247,7 @@ JIT_execute_method_default(JIT_Handle ji } TRACE("exit method " - << method->get_class()->name->bytes << " " + << method->get_class()->get_name()->bytes << " " << method->get_name()->bytes << " " << method->get_descriptor()->bytes); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/jit_generic_rt_support_ia32.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/jit_generic_rt_support_ia32.cpp index 6474121..1bac2b4 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/jit_generic_rt_support_ia32.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/jit_generic_rt_support_ia32.cpp @@ -1010,11 +1010,11 @@ static int get_log2(int value) } //get_log2 #endif -static void vm_rt_char_arraycopy_no_exc(ManagedObject *src, - int32 srcOffset, - ManagedObject *dst, - int32 dstOffset, - int32 length) +static void vm_rt_char_arraycopy_no_exc(ManagedObject* src, + int32 srcOffset, + ManagedObject* dst, + int32 dstOffset, + int32 length) { // 20030303 Use a C loop to (hopefully) speed up short array copies. @@ -1025,10 +1025,10 @@ static void vm_rt_char_arraycopy_no_exc( assert(src_class); Class * UNUSED dst_class = dst->vt()->clss; assert(dst_class); - assert((src_class->is_array) && (dst_class->is_array)); - assert((src_class->is_array_of_primitives) && (dst_class->is_array_of_primitives)); - assert(strcmp(src_class->name->bytes, "[C") == 0); - assert(strcmp(dst_class->name->bytes, "[C") == 0); + assert(src_class->is_array() && (dst_class->is_array())); + assert(src_class->is_array_of_primitives() && dst_class->is_array_of_primitives()); + assert(strcmp(src_class->get_name()->bytes, "[C") == 0); + assert(strcmp(dst_class->get_name()->bytes, "[C") == 0); // Check the offsets assert(srcOffset >= 0); assert(dstOffset >= 0); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp index a032763..cf29f5a 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp @@ -91,7 +91,7 @@ static void update_checkcast_stats(Manag VM_Statistics::get_vm_stats().num_checkcast_null ++; if (obj != NULL && obj->vt()->clss == c) VM_Statistics::get_vm_stats().num_checkcast_equal_type ++; - if (obj != NULL && c->is_suitable_for_fast_instanceof) + if (obj != NULL && c->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_checkcast_fast_decision ++; } //update_checkcast_stats #endif @@ -130,7 +130,7 @@ static void *getaddress__vm_checkcast_na ss = mov(ss, eax_opnd, M_Base_Opnd(esp_reg, +4) ); if (VM_Global_State::loader_env->compress_references) { - ss = alu(ss, cmp_opc, eax_opnd, Imm_Opnd((unsigned)Class::heap_base)); //is eax == NULL? + ss = alu(ss, cmp_opc, eax_opnd, Imm_Opnd((unsigned)VM_Global_State::loader_env->heap_base)); //is eax == NULL? ss = branch8(ss, Condition_NZ, Imm_Opnd(size_8, 0)); } else { ss = test(ss, eax_opnd, eax_opnd); @@ -212,10 +212,10 @@ static Boolean is_class_initialized(Clas { #ifdef VM_STATS VM_Statistics::get_vm_stats().num_is_class_initialized++; - clss->num_class_init_checks++; + clss->initialization_checked(); #endif // VM_STATS assert(!hythread_is_suspend_enabled()); - return clss->state == ST_Initialized; + return clss->is_initialized(); } //is_class_initialized @@ -505,10 +505,10 @@ aastore_ia32(volatile ManagedObject *ele { if (VM_Global_State::loader_env->compress_references) { // 20030321 Convert a null reference from a managed (heap_base) to an unmanaged null (NULL/0). - if (elem == (volatile ManagedObject *)Class::heap_base) { + if (elem == (volatile ManagedObject *)VM_Global_State::loader_env->heap_base) { elem = NULL; } - if (array == (ManagedObject *)Class::heap_base) { + if (array == (ManagedObject *)VM_Global_State::loader_env->heap_base) { array = NULL; } } @@ -529,13 +529,14 @@ aastore_ia32(volatile ManagedObject *ele #ifdef VM_STATS if (vt == cached_object_array_vtable_ptr) VM_Statistics::get_vm_stats().num_aastore_object_array ++; - if (vt->clss->array_element_class->vtable == ((ManagedObject *)elem)->vt()) + if (vt->clss->get_array_element_class()->get_vtable() == ((ManagedObject *)elem)->vt()) VM_Statistics::get_vm_stats().num_aastore_equal_type ++; - if (vt->clss->array_element_class->is_suitable_for_fast_instanceof) + if (vt->clss->get_array_element_class()->get_fast_instanceof_flag()) VM_Statistics::get_vm_stats().num_aastore_fast_decision ++; #endif // VM_STATS - if(vt == cached_object_array_vtable_ptr || - class_is_subtype_fast(((ManagedObject *)elem)->vt(), vt->clss->array_element_class)) { + if(vt == cached_object_array_vtable_ptr + || class_is_subtype_fast(((ManagedObject *)elem)->vt(), vt->clss->get_array_element_class())) + { STORE_REFERENCE((ManagedObject *)array, get_vector_element_address_ref(array, idx), (ManagedObject *)elem); return 0; } @@ -1007,7 +1008,7 @@ void * getaddress__gc_write_barrier_fast if (VM_Global_State::loader_env->compress_references) { // 20030321 Convert a null reference in %ecx from a managed (heap_base) to an unmanaged null (0/NULL). - ss = test(ss, ecx_opnd, Imm_Opnd((unsigned)Class::heap_base)); + ss = test(ss, ecx_opnd, Imm_Opnd((unsigned)VM_Global_State::loader_env->heap_base)); ss = branch8(ss, Condition_NE, Imm_Opnd(size_8, 0)); // branch around mov 0 char *backpatch_address__not_managed_null = ((char *)ss) - 1; ss = mov(ss, ecx_opnd, Imm_Opnd(0)); @@ -1300,14 +1301,14 @@ VMEXPORT LilCodeStub *vm_get_rt_support_ switch (f) { case VM_RT_CHECKCAST: { - if (!clss->is_suitable_for_fast_instanceof) + if (!clss->get_fast_instanceof_flag()) return NULL; return gen_lil_typecheck_stub_specialized(true, true, clss); } case VM_RT_INSTANCEOF: { - if (!clss->is_suitable_for_fast_instanceof) + if (!clss->get_fast_instanceof_flag()) return NULL; return gen_lil_typecheck_stub_specialized(false, true, clss); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/optimize_ia32.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/optimize_ia32.cpp index 272aa88..17ccf5e 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/optimize_ia32.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/ia32/base/optimize_ia32.cpp @@ -66,7 +66,7 @@ static bool enable_fast_char_arraycopy() static ManagedObject * get_class_ptr(ManagedObject *obj) { - return *(obj->vt()->clss->class_handle); + return *(obj->vt()->clss->get_class_handle()); } // ****** Begin overrides @@ -124,16 +124,15 @@ void gen_native_newinstance(Emitter_Hand s = mov(s, ebp_opnd, M_Base_Opnd(eax_reg, (int)env->vm_class_offset)) ; // ld l0,i0+offset (add offset, ld val) // Determine if this class supports fast allocation - size_t offset_is_fast_allocation_possible = (Byte *)&(env->Void_Class->is_fast_allocation_possible) - (Byte *)(env->Void_Class); - assert(sizeof(env->Void_Class->is_fast_allocation_possible) == 1); // else one byte ld below will fail + size_t offset_is_fast_allocation_possible = env->Void_Class->get_offset_of_fast_allocation_flag(); s = movzx(s, ebx_opnd, M_Base_Opnd(ebp_reg, offset_is_fast_allocation_possible), size_8); s = test(s, ebx_opnd, ebx_opnd); // jc l1=0,fallback s = branch8(s, Condition_Z, Imm_Opnd(size_8, 50)); // Class supports fast allocation, now use frontier allocation technique size_t offset_gc_local = (Byte *)&(p_TLS_vmthread->_gc_private_information) - (Byte *)p_TLS_vmthread; - size_t offset_allocation_handle = (Byte *)&(env->Void_Class->allocation_handle) - (Byte *)(env->Void_Class); - size_t offset_instance_data_size = (Byte *)&(env->Void_Class->instance_data_size) - (Byte *)(env->Void_Class); + size_t offset_allocation_handle = env->Void_Class->get_offset_of_allocation_handle(); + size_t offset_instance_data_size = env->Void_Class->get_offset_of_instance_data_size(); current_offset += (unsigned) offset_gc_local; limit_offset += (unsigned) offset_gc_local; diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/compile_ipf.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/compile_ipf.cpp index 73cd3f3..15a2e23 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/compile_ipf.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/compile_ipf.cpp @@ -118,7 +118,7 @@ void gen_convert_unmanaged_to_managed_nu increment_stats_counter(*mce, &VM_Statistics::get_vm_stats().num_convert_null_u2m); #endif mce->ipf_cmp(icmp_eq, cmp_none, SCRATCH_PRED_REG, SCRATCH_PRED_REG2, reg, 0); - emit_mov_imm_compactor(*mce, reg, (uint64)Class::heap_base, SCRATCH_PRED_REG); + emit_mov_imm_compactor(*mce, reg, (uint64)VM_Global_State::loader_env->heap_base, SCRATCH_PRED_REG); } } //gen_convert_unmanaged_to_managed_null_ipf @@ -146,17 +146,16 @@ static void emit_newinstance_override(Em emitter.ipf_ld(int_mem_size_8, mem_ld_none, mem_none, SCRATCH_GENERAL_REG7, SCRATCH_GENERAL_REG); // Check that the argument class is instantiatable. Note: we use Void_Class here but any class will do. - // g1 = g7 + offset_is_fast_allocation_possible // address of (clss->is_fast_allocation_possible) - // g2 = [g1] // clss->is_fast_allocation_possible - // p1 = (g2 != 0) // p1 = is clss->is_fast_allocation_possible? - size_t offset_is_fast_allocation_possible = (Byte *)&(env->Void_Class->is_fast_allocation_possible) - (Byte *)(env->Void_Class); - assert(sizeof(env->Void_Class->is_fast_allocation_possible) == 1); // else one byte ld below will fail + // g1 = g7 + offset_is_fast_allocation_possible // address of (clss->m_is_fast_allocation_possible) + // g2 = [g1] // clss->m_is_fast_allocation_possible + // p1 = (g2 != 0) // p1 = is clss->m_is_fast_allocation_possible? + size_t offset_is_fast_allocation_possible = env->Void_Class->get_offset_of_fast_allocation_flag(); emitter.ipf_adds(SCRATCH_GENERAL_REG, (int)offset_is_fast_allocation_possible, SCRATCH_GENERAL_REG7); emitter.ipf_ld(int_mem_size_1, mem_ld_none, mem_none, SCRATCH_GENERAL_REG2, SCRATCH_GENERAL_REG); emitter.ipf_cmp(icmp_ne, cmp_none, SCRATCH_PRED_REG, SCRATCH_PRED_REG2, 0, SCRATCH_GENERAL_REG2); - // The following instructions are executed only if p1 (i.e., if clss->is_fast_allocation_possible). + // The following instructions are executed only if p1 (i.e., if clss->m_is_fast_allocation_possible). // This is a significantly modified version of the inline code in get_vm_rt_new_with_thread_pointer_compactor(). // Do the fast path without creating a frame. This sequence uses predicated instructions rather than branching, // although I wonder if it has become too long for this to be effective. diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/ini_ipf.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/ini_ipf.cpp index 25a647d..9cc3745 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/ini_ipf.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/ini_ipf.cpp @@ -165,7 +165,7 @@ JIT_execute_method_default(JIT_Handle jh // 20030318 We are in unmanaged code where null is represented by 0/NULL. Convert a null reference // to the representation of null in managed code (heap_base). if (i64 == 0) { - i64 = (uint64)Class::heap_base; + i64 = (uint64)VM_Global_State::loader_env->heap_base; } } arg_words[num_arg_words++] = i64; @@ -188,7 +188,7 @@ JIT_execute_method_default(JIT_Handle jh // 20030318 We are in unmanaged code where null is represented by 0/NULL. Convert a null reference // to the representation of null in managed code (heap_base). if (i64 == 0) { - i64 = (uint64)Class::heap_base; + i64 = (uint64)VM_Global_State::loader_env->heap_base; } } arg_words[num_arg_words++] = i64; @@ -196,7 +196,7 @@ JIT_execute_method_default(JIT_Handle jh #ifdef _DEBUG { if (! VM_Global_State::loader_env->compress_references || - i64 != (uint64)Class::heap_base) { + i64 != (uint64)VM_Global_State::loader_env->heap_base) { ManagedObject *object = (ManagedObject *)i64; if(object) { Class *clss = object->vt()->clss; @@ -269,7 +269,7 @@ JIT_execute_method_default(JIT_Handle jh if (VM_Global_State::loader_env->compress_references) { // 20030318 Convert a null reference in managed code (represented by heap_base) // to the representation of null in unmanaged code (0 or NULL). - if ((uint64)int_result == (uint64)Class::heap_base) { + if ((uint64)int_result == (uint64)VM_Global_State::loader_env->heap_base) { int_result = 0; } } diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp index fc397c9..73ac6e5 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp @@ -157,8 +157,7 @@ extern "C" ManagedObject *vm_rt_new_reso assert(strcmp(c->name->bytes, "java/lang/Class")); #ifdef VM_STATS VM_Statistics::get_vm_stats().num_class_alloc_new_object++; - c->num_allocations++; - c->num_bytes_allocated += get_instance_data_size(c); + c->instance_allocated(c->get_instance_data_size()); #endif //VM_STATS return (ManagedObject *)vm_malloc_with_thread_pointer(c->instance_data_size, c->allocation_handle, vm_get_gc_thread_local()); } //vm_rt_new_resolved @@ -285,8 +284,7 @@ static void update_allocation_stats(int6 #ifdef VM_STATS VTable *vt = ManagedObject::allocation_handle_to_vtable(ah); Class *c = vt->clss; - c->num_allocations++; - c->num_bytes_allocated += get_instance_data_size(c); + c->instance_allocated(get_instance_data_size(c)); #endif } @@ -651,9 +649,9 @@ static void emit_fast_type_check_without int sub_object, int super_class, int pred, bool is_instanceof, int call_label) { - // sc1 = &super_class->is_suitable_for_fast_instanceof + // sc1 = super_class->get_offset_of_fast_instanceof_flag() // sc3 = [sub_object] - // sc6 = &super_class->depth + // sc6 = super_class->get_offset_of_depth() // sc4 = offset(superclasses) - 8 // sc2 = [sc1] @@ -691,19 +689,16 @@ static void emit_fast_type_check_without const unsigned sc9 = SCRATCH_GENERAL_REG9; Class *dummy_class = NULL; - const int offset_is_suitable = (int) ((Byte*)&dummy_class->is_suitable_for_fast_instanceof - (Byte*)dummy_class); - assert(sizeof(dummy_class->is_suitable_for_fast_instanceof) == 4); - - const int offset_depth = (int) ((Byte*)&dummy_class->depth - (Byte*)dummy_class); - assert(sizeof(dummy_class->depth) == 4); + const int offset_is_suitable = (int)Class::get_offset_of_fast_instanceof_flag(dummy_class); + const int offset_depth = (int)Class::get_offset_of_depth(dummy_class); VTable *dummy_vtable = NULL; const int offset_superclasses = (int) ((Byte*)&dummy_vtable->superclasses[-1] - (Byte*)dummy_vtable); const int offset_clss = (int) ((Byte*)&dummy_vtable->clss - (Byte*)dummy_vtable); - // sc1 = &super_class->is_suitable_for_fast_instanceof + // sc1 = super_class->get_offset_of_fast_instanceof_flag() // sc3 = [sub_object] - // sc6 = &super_class->depth + // sc6 = super_class->get_offset_of_depth() // sc4 = offset(superclasses) - 8 emitter.ipf_adds(sc1, offset_is_suitable, super_class); if (vm_vtable_pointers_are_compressed()) @@ -1092,7 +1087,7 @@ static void *get_vm_rt_initialize_class_ // reg1 = [reg0] // reg1 = reg1 + 1 // [reg0] = reg1 - emitter.ipf_adds(SCRATCH_GENERAL_REG, (int)((Byte*)&dummy->num_class_init_checks-(Byte*)dummy), IN_REG0); + emitter.ipf_adds(SCRATCH_GENERAL_REG, (int)Class::get_offset_of_class_init_checks(dummy), IN_REG0); emitter.ipf_ld(int_mem_size_8, mem_ld_none, mem_none, SCRATCH_GENERAL_REG2, SCRATCH_GENERAL_REG); emitter.ipf_adds(SCRATCH_GENERAL_REG2, 1, SCRATCH_GENERAL_REG2); emitter.ipf_st(int_mem_size_8, mem_st_none, mem_none, SCRATCH_GENERAL_REG, SCRATCH_GENERAL_REG2); @@ -1132,7 +1127,7 @@ static void *get_vm_rt_initialize_class_ // 20030502 This JIT support routine expects to be called directly from managed code. static void *vm_rt_get_interface_vtable(ManagedObject *object, Class *clss) { - assert(object != (ManagedObject *)Class::managed_null); + assert(object != (ManagedObject *)VM_Global_State::loader_env->managed_null); void *vt = vm_get_interface_vtable(object, clss); return vt; } //vm_rt_get_interface_vtable diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/stub_code_utils.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/stub_code_utils.cpp index 598c11d..9164b07 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/stub_code_utils.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/ipf/base/stub_code_utils.cpp @@ -184,7 +184,7 @@ void gen_compare_to_managed_null(Merced_ { assert(VM_Global_State::loader_env->compress_references); const bool cmp4 = true; - uint32 null_low = (uint32) (uint64) Class::managed_null; + uint32 null_low = (uint32) (uint64) VM_Global_State::loader_env->managed_null; if (null_low == 0) { emitter.ipf_cmp(icmp_eq, cmp_none, predicate1, predicate2, src, 0, cmp4); diff --git a/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_stats.cpp b/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_stats.cpp index b50aab6..09a99b2 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_stats.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_stats.cpp @@ -251,10 +251,9 @@ VM_Statistics::VM_Statistics() num_monitor_exit_decr_rec_count = 0; num_monitor_exit_very_slow_path = 0; - num_monitor_enters_with_zero_headers = 0; + num_monitor_enters_with_zero_headers = 0; num_monitor_enters_with_nonzero_headers = 0; - num_monitor_enter_wait = 0; num_sleep_monitor_enter = 0; num_sleep_monitor_exit = 0; @@ -301,6 +300,17 @@ VM_Statistics::VM_Statistics() num_compileme_generated = 0; num_compileme_used = 0; + num_statics_allocations = 0; + num_nonempty_statics_allocations = 0; + num_vtable_allocations = 0; + num_hot_statics_allocations = 0; + num_hot_vtable_allocations = 0; + + total_statics_bytes = 0; + total_vtable_bytes = 0; + total_hot_statics_bytes = 0; + total_hot_vtable_bytes = 0; + // Enter the JIT RT support functions into a -> map. for (int i = 0; i < sizeof_jit_rt_function_entries; i++) { char *fn_name; @@ -340,12 +350,12 @@ static void print_classes() for (it = ct->begin(); it != ct->end(); it++) { Class *c = it->second; - if(c->num_throws) { + if(c->get_times_thrown()) { if(first_time) { first_time = false; printf("\nFollowing exceptions were thrown:\n"); } - printf("%11" FMT64 "u :::: %s\n", c->num_throws, c->name->bytes); + printf("%11" FMT64 "u :::: %s\n", c->get_times_thrown(), c->get_name()->bytes); } } if(!first_time) { @@ -356,12 +366,12 @@ static void print_classes() for (it = ct->begin(); it != ct->end(); it++) { Class *c = it->second; - if(c->num_class_init_checks) { + if(c->get_times_init_checked() != 0) { if(first_time) { first_time = false; printf("Following classes were checked for init state:\n"); } - printf("%11" FMT64 "u :::: %s\n", c->num_class_init_checks, c->name->bytes); + printf("%11" FMT64 "u :::: %s\n", c->get_times_init_checked(), c->get_name()->bytes); } } if(!first_time) { @@ -372,13 +382,14 @@ static void print_classes() for (it = ct->begin(); it != ct->end(); it++) { Class *c = it->second; - if(c->num_instanceof_slow) { + if(c->get_times_instanceof_slow_path_taken() != 0) { if(first_time) { first_time = false; printf("Following classes were used in the instanceof test:\n"); } printf("%11" FMT64 "u :::: %-50s : [intf=%d, depth=%2d]\n", - c->num_instanceof_slow, c->name->bytes, (class_is_interface(c) ? 1 : 0), c->depth); + c->get_times_instanceof_slow_path_taken(), c->get_name()->bytes, + (c->is_interface() ? 1 : 0), c->get_depth()); } } if(!first_time) { @@ -389,18 +400,18 @@ static void print_classes() for (it = ct->begin(); it != ct->end(); it++) { Class *c = it->second; - total_bytes_allocated += c->num_bytes_allocated; + total_bytes_allocated += c->get_total_bytes_allocated(); } first_time = true; for (it = ct->begin(); it != ct->end(); it++) { Class *c = it->second; - if(c->num_allocations) { + if(c->get_times_allocated() != 0) { if(first_time) { first_time = false; printf("Number of instances [and # from Class.newInstance],\nand total allocated bytes for the following classes:\n"); } - uint64 nb = c->num_bytes_allocated; + uint64 nb = c->get_total_bytes_allocated(); #if defined (__INTEL_COMPILER) #pragma warning( push ) @@ -413,21 +424,24 @@ static void print_classes() #endif if (false && nb > 1000000) { uint64 nk = (nb/1024); - if (c->is_array) { - printf(" %60s %10" FMT64 "u [%10" FMT64 "u] = %10" FMT64 "uK %3u%%\n", - c->name->bytes, c->num_allocations, c->num_allocations_from_newInstance, nk, percent); + if (c->is_array()) { + printf(" %60s %10" FMT64 "u = %10" FMT64 "uK %3u%%\n", + c->get_name()->bytes, c->get_times_allocated(), + nk, percent); } else { - printf(" %60s %10" FMT64 "u [%10" FMT64 "u] * %4u = %10" FMT64 "uK %3u%%\n", - c->name->bytes, c->num_allocations, c->num_allocations_from_newInstance, get_instance_data_size(c), nk, percent); + printf(" %60s %10" FMT64 "u * %4u = %10" FMT64 "uK %3u%%\n", + c->get_name()->bytes, c->get_times_allocated(), + c->get_instance_data_size(), nk, percent); } } else { - if (c->is_array) { - printf("%10" FMT64 "u : %10" FMT64 "u : : %10" FMT64 "u :%-60s:%2u%%\n", - c->num_allocations, c->num_allocations_from_newInstance, nb, c->name->bytes, percent); + if (c->is_array()) { + printf("%10" FMT64 "u : : %10" FMT64 "u :%-60s:%2u%%\n", + c->get_times_allocated(), + nb, c->get_name()->bytes, percent); } else { - printf("%10" FMT64 "u : %10" FMT64 "u : * %4u = : %10" FMT64 "u :%-60s:%2u%%\n", - c->num_allocations, c->num_allocations_from_newInstance, - get_instance_data_size(c), nb, c->name->bytes, percent); + printf("%10" FMT64 "u * %4u = : %10" FMT64 "u :%-60s:%2u%%\n", + c->get_times_allocated(), + c->get_instance_data_size(), nb, c->get_name()->bytes, percent); } } } @@ -449,28 +463,29 @@ static void print_classes() { Class *c = it->second; // Only print out those classes with padding bytes that also have instances allocated. - if((c->num_field_padding_bytes) && (c->num_allocations)) { + if((c->get_total_padding_bytes() != 0) && (c->get_times_allocated() != 0)) { if(first_time) { first_time = false; - if (Class::compact_fields) { + if (VM_Global_State::loader_env->compact_fields) { printf("Field alignment bytes and total allocated alignment bytes for the following classes:\n"); } else { printf("Field padding and alignment bytes and the total such bytes for the following classes:\n"); } } - if (c->is_array) { - printf("%11u :::: %s\n", (unsigned)c->num_field_padding_bytes, c->name->bytes); + if (c->is_array()) { + printf("%11u :::: %s\n", (unsigned)c->get_total_padding_bytes(), c->get_name()->bytes); } else { - uint64 bytes_allocated = (c->num_allocations * (uint64)(c->num_field_padding_bytes)); + uint64 bytes_allocated = c->get_times_allocated()*(uint64)c->get_total_padding_bytes(); total_pad_bytes_allocated += bytes_allocated; - printf("%11u : %11" FMT64 "u ::: %s\n", c->num_field_padding_bytes, bytes_allocated, c->name->bytes); + printf("%11u : %11" FMT64 "u ::: %s\n", c->get_total_padding_bytes(), + bytes_allocated, c->get_name()->bytes); } } } if(!first_time) { printf(": ----------\n"); printf(": %15" FMT64 "u\n", total_pad_bytes_allocated); - printf("\n"); + printf("\n"); } } //print_classes @@ -487,22 +502,19 @@ static void print_methods() for (it = ct->begin(); it != ct->end(); it++) { Class *c = it->second; - int n_methods = c->n_methods; + int n_methods = c->get_number_of_methods(); for(int i = 0; i < n_methods; i++) { - Method *m = &(c->methods[i]); + Method* m = c->get_method(i); if (m->is_fake_method()) { continue; // ignore fake methods } if(m->num_accesses) { - const char *cname = c->name->bytes; - const char *mname = m->get_name()->bytes; - const char *descr = m->get_descriptor()->bytes; printf("%11" FMT64 "u : %11" FMT64 "u ::: %s.%s%s\n", m->num_accesses, m->num_slow_accesses, - cname, - mname, - descr); + c->get_name()->bytes, + m->get_name()->bytes, + m->get_descriptor()->bytes); } } } @@ -839,18 +851,19 @@ void VM_Statistics::print() printf("%11" FMT64 "u ::::Number of Java yield sleeps\n", num_sleep_java_thread_yield); printf("%11" FMT64 "u ::::Number of wait for object\n", num_wait_WaitForSingleObject); printf("%11" FMT64 "u ::::Number of hashcode sleeps\n", num_sleep_hashcode); - printf("%11" FMT64 "u ::::Number of mon owner sleeps\n", num_sleep_monitor_ownership); + printf("%11" FMT64 "u ::::Number of mon owner sleeps\n", num_sleep_monitor_ownership); - // 20020923 Print total number of allocations and total number of bytes for class-related data structures. + // Print total number of allocations and total number of bytes + // for class-related data structures. printf("\nAllocations of storage for statics:\n"); - printf("%11d ::::number allocated\n", Class::num_statics_allocations); - printf("%11d ::::number nonempty allocated\n", Class::num_nonempty_statics_allocations); - printf("%11d ::::bytes allocated\n", Class::total_statics_bytes); + printf("%11d ::::number allocated\n", num_statics_allocations); + printf("%11d ::::number nonempty allocated\n", num_nonempty_statics_allocations); + printf("%11d ::::bytes allocated\n", total_statics_bytes); fflush(stdout); - + printf("\nAllocations of storage for vtables:\n"); - printf("%11d ::::number allocated\n", Class::num_vtable_allocations); - printf("%11d ::::bytes allocated\n", Class::total_vtable_bytes); + printf("%11d ::::number allocated\n", num_vtable_allocations); + printf("%11d ::::bytes allocated\n", total_vtable_bytes); printf("\n"); printf("%11" FMT64 "u ::::# times free_local_handle_2 was called\n", num_free_local_called); 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 1eca79a..163398e 100644 --- a/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp +++ b/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp @@ -243,17 +243,16 @@ static void string_create(unsigned unico clss = global_env->ArrayOfByte_Class; assert(clss); - unsigned sz = vm_array_size(clss->vtable, unicode_length); - Vector_Handle array = vm_alloc_and_report_ti(sz, clss->allocation_handle, - vm_get_gc_thread_local(), clss); - if (!array) { // OutOfMemory should be thrown + unsigned sz = clss->calculate_array_size(unicode_length); + Vector_Handle array = vm_alloc_and_report_ti(sz, clss->get_allocation_handle(), + vm_get_gc_thread_local(), clss); + if(!array) { // OutOfMemory should be thrown *str = NULL; exn_raise_object(VM_Global_State::loader_env->java_lang_OutOfMemoryError); return; } #ifdef VM_STATS - clss->num_allocations++; - clss->num_bytes_allocated += sz; + clss->instance_allocated(sz); #endif //VM_STATS set_vector_length(array, unicode_length); @@ -590,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->get_constant_pool(); + String* str = cp.get_string(cp_index); BEGIN_RAISE_AREA; result = vm_instantiate_cp_string_resolved(str);