[vmkit-commits] [vmkit] r70119 - in /vmkit/trunk: include/jnjvm/JnjvmModule.h include/mvm/VirtualMachine.h lib/JnJVM/Classpath/ClasspathReflect.h lib/JnJVM/Compiler/JavaJITCompiler.cpp lib/JnJVM/VMCore/JavaMetaJIT.cpp lib/JnJVM/VMCore/JavaUpcalls.cpp lib/JnJVM/VMCore/JavaUpcalls.h lib/JnJVM/VMCore/Jnjvm.cpp lib/JnJVM/VMCore/Jnjvm.h lib/Mvm/GCMmap2/gccollector.cpp lib/Mvm/Runtime/Object.cpp

Nicolas Geoffray nicolas.geoffray at lip6.fr
Sun Apr 26 02:16:53 PDT 2009


Author: geoffray
Date: Sun Apr 26 04:16:48 2009
New Revision: 70119

URL: http://llvm.org/viewvc/llvm-project?rev=70119&view=rev
Log:
Support for Weak/Soft/Phantom references in GCMmap2.


Modified:
    vmkit/trunk/include/jnjvm/JnjvmModule.h
    vmkit/trunk/include/mvm/VirtualMachine.h
    vmkit/trunk/lib/JnJVM/Classpath/ClasspathReflect.h
    vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp
    vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp
    vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.cpp
    vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.h
    vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp
    vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h
    vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp
    vmkit/trunk/lib/Mvm/Runtime/Object.cpp

Modified: vmkit/trunk/include/jnjvm/JnjvmModule.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/jnjvm/JnjvmModule.h?rev=70119&r1=70118&r2=70119&view=diff

==============================================================================
--- vmkit/trunk/include/jnjvm/JnjvmModule.h (original)
+++ vmkit/trunk/include/jnjvm/JnjvmModule.h Sun Apr 26 04:16:48 2009
@@ -66,6 +66,7 @@
 
 
 class LLVMClassInfo : public mvm::JITInfo {
+  friend class JavaAOTCompiler;
   friend class JavaJITCompiler;
   friend class JavaLLVMCompiler;
 private:

Modified: vmkit/trunk/include/mvm/VirtualMachine.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/VirtualMachine.h?rev=70119&r1=70118&r2=70119&view=diff

==============================================================================
--- vmkit/trunk/include/mvm/VirtualMachine.h (original)
+++ vmkit/trunk/include/mvm/VirtualMachine.h Sun Apr 26 04:16:48 2009
@@ -42,13 +42,57 @@
 
 namespace mvm {
 
+class VirtualMachine;
+
+class ReferenceQueue {
+private:
+  gc** References;
+  uint32 QueueLength;
+  uint32 CurrentIndex;
+  mvm::SpinLock QueueLock;
+  uint8_t semantics;
+
+  gc* processReference(gc*, VirtualMachine*);
+public:
+
+  static const uint8_t WEAK = 1;
+  static const uint8_t SOFT = 2;
+  static const uint8_t PHANTOM = 3;
+
+  ReferenceQueue(uint8_t s) {
+    References = new gc*[INITIAL_QUEUE_SIZE];
+    QueueLength = INITIAL_QUEUE_SIZE;
+    CurrentIndex = 0;
+    semantics = s;
+  }
+ 
+  void addReference(gc* ref) {
+    QueueLock.acquire();
+    if (CurrentIndex >= QueueLength) {
+      uint32 newLength = QueueLength * GROW_FACTOR;
+      gc** newQueue = new gc*[newLength];
+      for (uint32 i = 0; i < QueueLength; ++i) newQueue[i] = References[i];
+      delete[] References;
+      References = newQueue;
+      QueueLength = newLength;
+    }
+    References[CurrentIndex++] = ref;
+    QueueLock.release();
+  }
+
+  void scan(VirtualMachine* vm);
+};
+
 /// VirtualMachine - This class is the root of virtual machine classes. It
 /// defines what a VM should be.
 ///
 class VirtualMachine : public mvm::PermanentObject {
 protected:
 
-  VirtualMachine() {
+  VirtualMachine() : 
+    WeakReferencesQueue(ReferenceQueue::WEAK),
+    SoftReferencesQueue(ReferenceQueue::SOFT), 
+    PhantomReferencesQueue(ReferenceQueue::PHANTOM) {
 #ifdef SERVICE
     memoryLimit = ~0;
     executionLimit = ~0;
@@ -64,6 +108,7 @@
     
     ToBeFinalized = new gc*[INITIAL_QUEUE_SIZE];
     ToBeFinalizedLength = INITIAL_QUEUE_SIZE;
+
   }
 public:
 
@@ -183,6 +228,18 @@
     return ToBeFinalizedLength - countFinalized();
   }
 
+  /// WeakReferencesQueue - The queue of weak references.
+  ///
+  ReferenceQueue WeakReferencesQueue;
+
+  /// SoftReferencesQueue - The queue of soft references.
+  ///
+  ReferenceQueue SoftReferencesQueue;
+
+  /// PhantomReferencesQueue - The queue of phantom references.
+  ///
+  ReferenceQueue PhantomReferencesQueue;
+
 protected:
   /// invokeFinalizer - Invoke the finalizer of the object. This may involve
   /// changing the environment, e.g. going to native to Java.
@@ -210,6 +267,60 @@
   ///
   void wakeUpFinalizers() { FinalizationCond.broadcast(); }
 
+  /// scanWeakReferencesQueue - Scan all weak references. Called by the GC
+  /// before scanning the finalization queue.
+  /// 
+  void scanWeakReferencesQueue() {
+    WeakReferencesQueue.scan(this);
+  }
+  
+  /// scanSoftReferencesQueue - Scan all soft references. Called by the GC
+  /// before scanning the finalization queue.
+  ///
+  void scanSoftReferencesQueue() {
+    SoftReferencesQueue.scan(this);
+  }
+  
+  /// scanPhantomReferencesQueue - Scan all phantom references. Called by the GC
+  /// after the finalization queue.
+  ///
+  void scanPhantomReferencesQueue() {
+    PhantomReferencesQueue.scan(this);
+  }
+  
+  /// addWeakReference - Add a weak reference to the queue.
+  ///
+  void addWeakReference(gc* ref) {
+    WeakReferencesQueue.addReference(ref);
+  }
+  
+  /// addSoftReference - Add a weak reference to the queue.
+  ///
+  void addSoftReference(gc* ref) {
+    SoftReferencesQueue.addReference(ref);
+  }
+  
+  /// addPhantomReference - Add a weak reference to the queue.
+  ///
+  void addPhantomReference(gc* ref) {
+    PhantomReferencesQueue.addReference(ref);
+  }
+
+  /// clearReferent - Clear the referent in a reference. Should be overriden
+  /// by the VM.
+  ///
+  virtual void clearReferent(gc*) {}
+
+  /// getReferent - Get the referent of the reference. Should be overriden
+  /// by the VM.
+  //
+  virtual gc* getReferent(gc*) { return 0; }
+
+  /// enqueueReference - Calls the enqueue method. Should be overriden
+  /// by the VM.
+  ///
+  virtual bool enqueueReference(gc*) { return false; }
+
 #ifdef ISOLATE
   size_t IsolateID;
 #endif

Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathReflect.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathReflect.h?rev=70119&r1=70118&r2=70119&view=diff

==============================================================================
--- vmkit/trunk/lib/JnJVM/Classpath/ClasspathReflect.h (original)
+++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathReflect.h Sun Apr 26 04:16:48 2009
@@ -148,6 +148,27 @@
   }
 };
 
+class JavaObjectReference : public JavaObject {
+private:
+  JavaObject* referent;
+  JavaObject* queue;
+  JavaObject* nextOnQueue;
+
+public:
+  void init(JavaObject* r, JavaObject* q) {
+    referent = r;
+    queue = q;
+  }
+
+  JavaObject* getReferent() const { return referent; }
+  void setReferent(JavaObject* r) { referent = r; }
+  
+  static void STATIC_TRACER(JavaObjectReference) {
+    obj->queue->MARK_AND_TRACE;
+    obj->nextOnQueue->MARK_AND_TRACE;
+  }
+};
+
 }
 
 #endif

Modified: vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp?rev=70119&r1=70118&r2=70119&view=diff

==============================================================================
--- vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp (original)
+++ vmkit/trunk/lib/JnJVM/Compiler/JavaJITCompiler.cpp Sun Apr 26 04:16:48 2009
@@ -138,18 +138,22 @@
   assert(VT && "No VT was allocated!");
 
 #ifdef WITH_TRACER
-  if (VT->init) {
-    // So the class is vmjc'ed. Create the virtual tracer.
+  if (VT->tracer) {
+    // So the class has a tracer because either a) the class was vmjced or
+    // b) the boot sequence has set it. Create the tracer as an external
+    // function.
     Function* func = Function::Create(JnjvmModule::MarkAndTraceType,
                                       GlobalValue::ExternalLinkage,
-                                      "markAndTraceObject",
-                                      getLLVMModule());
+                                      "", getLLVMModule());
        
     uintptr_t ptr = VT->tracer;
     JnjvmModule::executionEngine->addGlobalMapping(func, (void*)ptr);
     LLVMClassInfo* LCI = getClassInfo(cl);
     LCI->virtualTracerFunction = func;
 
+  }
+  
+  if (VT->init) {
     // The VT hash already been filled by the AOT compiler so there
     // is nothing left to do!
     return;
@@ -189,11 +193,13 @@
   }
 
 #ifdef WITH_TRACER
-  Function* func = makeTracer(cl, false);
+  if (!VT->tracer) {
+    Function* func = makeTracer(cl, false);
   
-  void* codePtr = mvm::MvmModule::executionEngine->getPointerToFunction(func);
-  VT->tracer = (uintptr_t)codePtr;
-  func->deleteBody();
+    void* codePtr = mvm::MvmModule::executionEngine->getPointerToFunction(func);
+    VT->tracer = (uintptr_t)codePtr;
+    func->deleteBody();
+  }
 #endif
     
 }

Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp?rev=70119&r1=70118&r2=70119&view=diff

==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp Sun Apr 26 04:16:48 2009
@@ -633,3 +633,10 @@
   UserClass* cl = obj->getClass()->asClass();
   meth->invokeIntVirtualBuf(this, cl, obj, 0);
 }
+
+bool Jnjvm::enqueueReference(gc* _obj) {
+  JavaObject* obj = (JavaObject*)_obj;
+  JavaMethod* meth = upcalls->EnqueueReference;
+  UserClass* cl = obj->getClass()->asClass();
+  return (bool)meth->invokeIntVirtualBuf(this, cl, obj, 0);
+}

Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.cpp?rev=70119&r1=70118&r2=70119&view=diff

==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.cpp (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.cpp Sun Apr 26 04:16:48 2009
@@ -208,6 +208,9 @@
 JavaField* Classpath::fieldClass;
 JavaField* Classpath::constructorClass;
 
+JavaMethod* Classpath::EnqueueReference;
+Class*      Classpath::newReference;
+
 #endif
 
 void Classpath::CreateJavaThread(Jnjvm* vm, JavaThread* myth,
@@ -336,6 +339,44 @@
 extern "C" void nativePropertiesPostInit(JavaObject* prop);
 
 
+extern "C" void nativeInitWeakReference(JavaObjectReference* reference,
+                                        JavaObject* referent) {
+  reference->init(referent, 0);
+  JavaThread::get()->getJVM()->addWeakReference(reference);
+
+}
+
+extern "C" void nativeInitWeakReferenceQ(JavaObjectReference* reference,
+                                         JavaObject* referent,
+                                         JavaObject* queue) {
+  reference->init(referent, queue);
+  JavaThread::get()->getJVM()->addWeakReference(reference);
+
+}
+
+extern "C" void nativeInitSoftReference(JavaObjectReference* reference,
+                                        JavaObject* referent) {
+  reference->init(referent, 0);
+  JavaThread::get()->getJVM()->addSoftReference(reference);
+
+}
+
+extern "C" void nativeInitSoftReferenceQ(JavaObjectReference* reference,
+                                         JavaObject* referent,
+                                         JavaObject* queue) {
+  reference->init(referent, queue);
+  JavaThread::get()->getJVM()->addSoftReference(reference);
+
+}
+
+extern "C" void nativeInitPhantomReferenceQ(JavaObjectReference* reference,
+                                            JavaObject* referent,
+                                            JavaObject* queue) {
+  reference->init(referent, queue);
+  JavaThread::get()->getJVM()->addPhantomReference(reference);
+
+}
+
 void Classpath::initialiseClasspath(JnjvmClassLoader* loader) {
 
   newClassLoader = 
@@ -745,5 +786,64 @@
                   ACC_VIRTUAL);
   getAnnotations->setCompiledPtr((void*)(intptr_t)nativeGetDeclaredAnnotations,
                                  "nativeGetDeclaredAnnotations");
+
+  newReference =
+    loader->loadName(loader->asciizConstructUTF8("java/lang/ref/Reference"),
+                     false, false);
+    
+  assert(!newReference->isResolved() && "Reference class already resolved");
+  JavaVirtualTable* ptr = newReference->getVirtualVT();
+  ptr->tracer = (uintptr_t)JavaObjectReference::staticTracer;
+  
+  EnqueueReference = 
+    UPCALL_METHOD(loader, "java/lang/ref/Reference",  "enqueue", "()Z",
+                  ACC_VIRTUAL);
+ 
+  JavaMethod* initWeakReference =
+    UPCALL_METHOD(loader, "java/lang/ref/WeakReference", "<init>",
+                  "(Ljava/lang/Object;)V",
+                  ACC_VIRTUAL);
+  initWeakReference->setCompiledPtr((void*)(intptr_t)nativeInitWeakReference,
+                                    "nativeInitWeakReference");
+  
+  initWeakReference =
+    UPCALL_METHOD(loader, "java/lang/ref/WeakReference", "<init>",
+                  "(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V",
+                  ACC_VIRTUAL);
+  initWeakReference->setCompiledPtr((void*)(intptr_t)nativeInitWeakReferenceQ,
+                                    "nativeInitWeakReferenceQ");
+  
+  JavaMethod* initSoftReference =
+    UPCALL_METHOD(loader, "java/lang/ref/SoftReference", "<init>",
+                  "(Ljava/lang/Object;)V",
+                  ACC_VIRTUAL);
+  initSoftReference->setCompiledPtr((void*)(intptr_t)nativeInitSoftReference,
+                                    "nativeInitSoftReference");
+  
+  initSoftReference =
+    UPCALL_METHOD(loader, "java/lang/ref/WeakReference", "<init>",
+                  "(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V",
+                  ACC_VIRTUAL);
+  initSoftReference->setCompiledPtr((void*)(intptr_t)nativeInitSoftReferenceQ,
+                                    "nativeInitSoftReferenceQ");
+  
+  JavaMethod* initPhantomReference =
+    UPCALL_METHOD(loader, "java/lang/ref/PhantomReference", "<init>",
+                  "(Ljava/lang/Object;Ljava/lang/ref/ReferenceQueue;)V",
+                  ACC_VIRTUAL);
+  initPhantomReference->setCompiledPtr(
+      (void*)(intptr_t)nativeInitPhantomReferenceQ,
+      "nativeInitPhantomReferenceQ");
+  
+
+}
+
+gc* Jnjvm::getReferent(gc* _obj) {
+  JavaObjectReference* obj = (JavaObjectReference*)_obj;
+  return obj->getReferent();
 }
 
+void Jnjvm::clearReferent(gc* _obj) {
+  JavaObjectReference* obj = (JavaObjectReference*)_obj;
+  obj->setReferent(0);
+}

Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.h?rev=70119&r1=70118&r2=70119&view=diff

==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.h (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.h Sun Apr 26 04:16:48 2009
@@ -242,6 +242,9 @@
   ISOLATE_STATIC JavaField* methodClass;
   ISOLATE_STATIC JavaField* fieldClass;
   ISOLATE_STATIC JavaField* constructorClass;
+
+  ISOLATE_STATIC JavaMethod* EnqueueReference;
+  ISOLATE_STATIC Class*      newReference;
   
 private:
   ISOLATE_STATIC void CreateJavaThread(Jnjvm* vm, JavaThread* myth,

Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp?rev=70119&r1=70118&r2=70119&view=diff

==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Sun Apr 26 04:16:48 2009
@@ -845,7 +845,7 @@
   LOAD_CLASS(upcalls->newVMThread);
   ptr = ((uintptr_t*)upcalls->newVMThread->getVirtualVT());
   ptr[VT_DESTRUCTOR_OFFSET] = (uintptr_t)JavaObjectVMThread::staticDestructor;
-
+   
 #ifdef SERVICE
   if (!IsolateID)
 #endif

Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h?rev=70119&r1=70118&r2=70119&view=diff

==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h Sun Apr 26 04:16:48 2009
@@ -363,6 +363,10 @@
 protected:
   virtual void invokeFinalizer(gc*);
 
+public:
+  virtual void clearReferent(gc*);
+  virtual gc* getReferent(gc*);
+  virtual bool enqueueReference(gc*);
 
 };
 

Modified: vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp?rev=70119&r1=70118&r2=70119&view=diff

==============================================================================
--- vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp (original)
+++ vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp Sun Apr 26 04:16:48 2009
@@ -78,7 +78,17 @@
   threads->collectionFinished();
 #endif
 
-  Thread::get()->MyVM->scanFinalizationQueue();
+  VirtualMachine* vm = Thread::get()->MyVM;
+  
+  // Scan soft and weak reference queues.
+  vm->scanWeakReferencesQueue();
+  vm->scanSoftReferencesQueue();
+
+  // Scan finalization queue.
+  vm->scanFinalizationQueue();
+
+  // Now that the finalization queue has been scanned, scan the phantom queue.
+  vm->scanPhantomReferencesQueue();
   
   /* finalize */
   GCChunkNode  finalizable;
@@ -92,7 +102,8 @@
     allocator->reject_chunk(cur);
   }
   status = stat_alloc;
-  
+ 
+  // Collection finished. Wake up the finalizers if they are waiting.
   Thread::get()->MyVM->wakeUpFinalizers();
 
 

Modified: vmkit/trunk/lib/Mvm/Runtime/Object.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/Runtime/Object.cpp?rev=70119&r1=70118&r2=70119&view=diff

==============================================================================
--- vmkit/trunk/lib/Mvm/Runtime/Object.cpp (original)
+++ vmkit/trunk/lib/Mvm/Runtime/Object.cpp Sun Apr 26 04:16:48 2009
@@ -218,3 +218,44 @@
   FinalizationQueueLock.release();
 
 }
+
+gc* ReferenceQueue::processReference(gc* reference, VirtualMachine* vm) {
+  if (!Collector::isLive(reference)) {
+    vm->clearReferent(reference);
+    return 0;
+  }
+
+  gc* referent = vm->getReferent(reference);
+
+  if (!referent) return 0;
+
+  if (semantics == SOFT) {
+    // TODO: are we are out of memory? Consider that we always are for now.
+    if (false) {
+      referent->markAndTrace();
+    }
+  } else if (semantics == PHANTOM) {
+    // Nothing to do.
+  }
+
+  if (Collector::isLive(referent)) {
+    return reference;
+  } else {
+    vm->clearReferent(reference);
+    vm->enqueueReference(reference);
+    return 0;
+  }
+}
+
+
+void ReferenceQueue::scan(VirtualMachine* vm) {
+  uint32 NewIndex = 0;
+
+  for (uint32 i = 0; i < CurrentIndex; ++i) {
+    gc* obj = References[i];
+    processReference(obj, vm);
+  }
+
+  CurrentIndex = NewIndex;
+
+}





More information about the vmkit-commits mailing list