Index: vm/include/jit_import_rt.h =================================================================== --- vm/include/jit_import_rt.h (revision 534759) +++ vm/include/jit_import_rt.h (working copy) @@ -40,6 +40,12 @@ */ VMEXPORT void vm_enumerate_root_reference(Managed_Object_Handle *ref, Boolean is_pinned); +// Enumerate a weak root entry. The argument is a pointer to the memory +// location that contains a managed reference. The GC may update +// this location if the object pointed to has been moved during +// collection. +VMEXPORT void vm_enumerate_weak_root_reference(Managed_Object_Handle *ref, Boolean is_pinned); + /** * Resembles vm_enumerate_root_reference(), but is passed the * address of a slot containing a compressed reference. Index: vm/vmcore/include/classloader.h =================================================================== --- vm/vmcore/include/classloader.h (revision 534759) +++ vm/vmcore/include/classloader.h (working copy) @@ -147,7 +147,7 @@ private: class LoadingClasses : public MapEx {}; - class ReportedClasses : public MapEx {}; + class ReportedClasses : public MapEx {}; class JavaTypes : public MapEx {}; @@ -173,11 +173,12 @@ klass = m_initiatedClasses->Lookup(name); return klass?*klass:NULL; } - void InsertClass(Class* clss) { - LMAutoUnlock aulock(&m_lock); - m_loadedClasses->Insert(clss->get_name(), clss); - m_initiatedClasses->Insert(clss->get_name(), clss); + void RemoveFromReported(const String* name){ + if(m_reportedClasses->Lookup(name)) { + m_reportedClasses->Remove(name); + } } + bool InsertClass(Class* clss); Class* AllocateAndReportInstance(const Global_Env* env, Class* klass); Class* NewClass(const Global_Env* env, const String* name); Package* ProvidePackage(Global_Env* env, const String *class_name, const char *jar); Index: vm/vmcore/src/gc/root_set_enum_common.cpp =================================================================== --- vm/vmcore/src/gc/root_set_enum_common.cpp (revision 534759) +++ vm/vmcore/src/gc/root_set_enum_common.cpp (working copy) @@ -66,81 +66,123 @@ // Enumerate all globally visible classes and their static fields. +static void vm_enumerate_jlc(Class* c, bool b_weak = false) +{ + assert (*c->get_class_handle()); + if (!b_weak) { + vm_enumerate_root_reference((void**)c->get_class_handle(), FALSE); + } + else { + vm_enumerate_weak_root_reference((void**)c->get_class_handle(), FALSE); + } +} + +static void vm_enumerate_class_static(Class* c) +{ + Global_Env *global_env = VM_Global_State::loader_env; + assert (c); + 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->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->get_field(i); + if(f->is_static()) { + if(field_is_enumerable_reference(f)){ + // The field is static and it is a reference. + if (global_env->compress_references) { + vm_enumerate_compressed_root_reference((uint32 *)f->get_address(), FALSE); + } else { + vm_enumerate_root_reference((void **)f->get_address(), FALSE); + } + } + } + } + } +} + void vm_enumerate_static_fields() { TRACE2("enumeration", "vm_enumerate_static_fields()"); - Global_Env *global_env = VM_Global_State::loader_env; - ManagedObject** ppc; GlobalClassLoaderIterator ClIterator; ClassLoader *cl = ClIterator.first(); while(cl) { GlobalClassLoaderIterator::ClassIterator itc; GlobalClassLoaderIterator::ReportedClasses RepClasses = cl->GetReportedClasses(); + Class* c; for (itc = RepClasses->begin(); itc != RepClasses->end(); itc++) { - ppc = &itc->second; - assert(*ppc); - Class* c = jclass_to_struct_Class((jclass)ppc); - - vm_enumerate_root_reference((void**)ppc, FALSE); - ConstPoolEntry* cp = c->get_constant_pool().get_error_chain(); - while(cp) { - vm_enumerate_root_reference((void**)(&(cp->error.cause)), FALSE); - cp = cp->error.next; + c = itc->second; + assert(c); + vm_enumerate_jlc(c); + vm_enumerate_class_static(c); + } + ClassTable::iterator itl; + ClassTable* p_loadedClasses = cl->GetLoadedClasses(); + for (itl = p_loadedClasses->begin(); itl != p_loadedClasses->end(); itl++) + { + c = itl->second; + assert(c); + if (!cl->IsBootstrap()) + { + vm_enumerate_jlc(c, true/*enum as weak root*/); + vm_enumerate_class_static(c); } - // Finally enumerate the static fields of the class - 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->get_field(i); - if(f->is_static()) { - if(field_is_enumerable_reference(f)){ - // The field is static and it is a reference. - if (global_env->compress_references) { - vm_enumerate_compressed_root_reference((uint32 *)f->get_address(), FALSE); - } else { - vm_enumerate_root_reference((void **)f->get_address(), FALSE); - } - } - } - } - } } cl = ClIterator.next(); - } -} //vm_enumerate_static_fields + } + } //vm_enumerate_static_fields - - // This is the main function used to enumerate Java references by the VM and the JITs. // It is part of the JIT-VM interface. // 20030405 Note: When compressing references, vm_enumerate_root_reference() expects to be called with slots // containing *managed* refs (represented by heap_base if null, not 0/NULL), so those refs must not be NULL. +static void check_ref(void** ref) +{ + if (VM_Global_State::loader_env->compress_references) { + // 20030324 DEBUG: verify the slot whose reference is being passed. + ManagedObject **p_obj = (ManagedObject **)ref; + ManagedObject* obj = *p_obj; + assert(obj != NULL); // See the comment at the top of the procedure. + 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)); + } + } +} + void vm_enumerate_root_reference(void **ref, Boolean is_pinned) { TRACE2("vm.enum", "vm_enumerate_root_reference(" << ref << " -> " << *ref << ")"); #if _DEBUG - if (VM_Global_State::loader_env->compress_references) { - // 20030324 DEBUG: verify the slot whose reference is being passed. - ManagedObject **p_obj = (ManagedObject **)ref; - ManagedObject* obj = *p_obj; - assert(obj != NULL); // See the comment at the top of the procedure. - 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)); - } - } + check_ref(ref); #endif // _DEBUG gc_add_root_set_entry((Managed_Object_Handle *)ref, is_pinned); } //vm_enumerate_root_reference +void +vm_enumerate_weak_root_reference(void **ref, Boolean is_pinned) +{ + TRACE2("vm.enum", "vm_enumerate_weak_root_reference(" + << ref << " -> " << *ref << ")"); +#if _DEBUG + check_ref(ref); +#endif // _DEBUG + gc_add_weak_root_set_entry((Managed_Object_Handle *)ref, is_pinned, FALSE); +} //vm_enumerate_weak_root_reference + + // Resembles vm_enumerate_root_reference() but is passed the address of a uint32 slot containing a compressed reference. VMEXPORT void vm_enumerate_compressed_root_reference(uint32 *ref, Boolean is_pinned) { Index: vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java =================================================================== --- vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java (revision 534759) +++ vm/vmcore/src/kernel_classes/javasrc/java/lang/Class.java (working copy) @@ -1160,6 +1160,7 @@ return VMClassRegistry.getSimpleName(this); } + protected ClassLoader definingLoader; private final class ReflectionData { Index: vm/vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java =================================================================== --- vm/vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java (revision 534759) +++ vm/vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java (working copy) @@ -106,6 +106,12 @@ */ private final HashMap definedPackages; + /* + * The following mapping is used , where binaryClassName - class name, + * clazz - corresponding class. + */ + Hashtable loadedClasses = new Hashtable(); + /** * package private to access from the java.lang.Class class. The following * mapping is used , where name - @@ -373,6 +379,15 @@ /** * @com.intel.drl.spec_ref */ + public void addToLoadedClasses(String name, Class clazz) { + synchronized (loadedClasses){ + loadedClasses.put(name, clazz); + } + } + + /** + * @com.intel.drl.spec_ref + */ protected final Class defineClass(String name, ByteBuffer b, ProtectionDomain protectionDomain) throws ClassFormatError { byte[] data = b.array(); @@ -415,6 +430,7 @@ certs = getCertificates(packageName, domain.getCodeSource()); } Class clazz = defineClass0(name, data, offset, len); + clazz.definingLoader = this; clazz.setProtectionDomain(domain); if (certs != null) { packageCertificates.put(packageName, certs); Index: vm/vmcore/src/class_support/classloader.cpp =================================================================== --- vm/vmcore/src/class_support/classloader.cpp (revision 534759) +++ vm/vmcore/src/class_support/classloader.cpp (working copy) @@ -314,7 +314,11 @@ return NULL; } - InsertClass(clss); + if (!InsertClass(clss)){ + FailedLoadingClass(className); + return NULL; + } + SuccessLoadingClass(className); if(this != env->bootstrap_class_loader || !env->InBootstrap()) @@ -628,9 +632,7 @@ lc->SignalLoading(); RemoveLoadingClass(className, lc); } - if(m_reportedClasses->Lookup(className)) { - m_reportedClasses->Remove(className); - } + RemoveFromReported(className); } @@ -811,7 +813,10 @@ return NULL; } - InsertClass(klass); + if (!InsertClass(klass)){ + FailedLoadingClass(classNameString); + return NULL; + } SuccessLoadingClass(classNameString); return klass; @@ -862,7 +867,11 @@ } // add newly created java_lang_Class to reportable collection LMAutoUnlock aulock(&m_lock); - clss->set_class_handle(m_reportedClasses->Insert(name, new_java_lang_Class)); + ManagedObject** ch = (ManagedObject**)Alloc(sizeof(ManagedObject*)); + *ch = new_java_lang_Class; + m_reportedClasses->Insert(name, clss); + clss->set_class_handle(ch); + aulock.ForceUnlock(); TRACE("NewClass inserting class \"" << name->bytes << "\" with key " << name << " and object " << new_java_lang_Class); @@ -1585,6 +1594,69 @@ return clss; } // UserDefinedClassLoader::DoLoadClass +bool ClassLoader::InsertClass(Class* clss) { + tmn_suspend_disable(); + if (!IsBootstrap()) // skip BS classes + { + Global_Env* env = VM_Global_State::loader_env; + jvalue args[3]; + ManagedObject* jstr; + + if (env->compress_references) { + jstr = uncompress_compressed_reference(clss->get_name()->intern.compressed_ref); + } else { + jstr = clss->get_name()->intern.raw_ref; + } + ObjectHandle h = oh_allocate_local_handle(); + if (jstr != NULL) { + h->object = jstr; + } else { + h->object = vm_instantiate_cp_string_resolved((String*)clss->get_name()); + } + args[1].l = h; + + if (exn_raised()) { + TRACE2("classloader", "OutOfMemoryError on class registering " << clss->get_name()->bytes); + assert (false); + tmn_suspend_enable(); + return false; + } + + // this parameter + ObjectHandle hl = oh_allocate_local_handle(); + hl->object = m_loader; + args[0].l = hl; + + // jlc parameter + ObjectHandle chl = oh_allocate_local_handle(); + chl->object = *clss->get_class_handle(); + args[2].l = chl; + + static String* acr_func_name = env->string_pool.lookup("addToLoadedClasses"); + static String* acr_func_desc = env->string_pool.lookup("(Ljava/lang/String;Ljava/lang/Class;)V"); + + Method* method = class_lookup_method_recursive(m_loader->vt()->clss, acr_func_name, acr_func_desc); + assert(method); + + jvalue res; + vm_execute_java_method_array((jmethodID) method, &res, args); + + if(exn_raised()) { + tmn_suspend_enable(); + return false; + } + } + + LMAutoUnlock aulock(&m_lock); + m_loadedClasses->Insert(clss->get_name(), clss); + if (!IsBootstrap()){ + RemoveFromReported(clss->get_name()); + } + tmn_suspend_enable(); + m_initiatedClasses->Insert(clss->get_name(), clss); + return true; +} + void BootstrapClassLoader::ReportAndExit(const char* exnclass, std::stringstream& exnmsg) { std::stringstream ss;