[vmkit-commits] [vmkit] r77588 - in /vmkit/trunk: include/mvm/Threads/Thread.h lib/JnJVM/Compiler/JnjvmModule.cpp lib/JnJVM/LLVMRuntime/runtime-default.ll lib/JnJVM/VMCore/JavaThread.cpp lib/JnJVM/VMCore/JavaThread.h lib/Mvm/CommonThread/ctlock.cpp lib/Mvm/CommonThread/ctthread.cpp lib/Mvm/GCMmap2/MvmGC.h lib/Mvm/GCMmap2/gc.cpp lib/Mvm/GCMmap2/gccollector.cpp lib/Mvm/GCMmap2/gcthread.cpp lib/Mvm/GCMmap2/gcthread.h lib/Mvm/Runtime/Object.cpp

Nicolas Geoffray nicolas.geoffray at lip6.fr
Thu Jul 30 02:38:40 PDT 2009


Author: geoffray
Date: Thu Jul 30 04:38:29 2009
New Revision: 77588

URL: http://llvm.org/viewvc/llvm-project?rev=77588&view=rev
Log:
Fully support a cooperative GC.


Modified:
    vmkit/trunk/include/mvm/Threads/Thread.h
    vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp
    vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll
    vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp
    vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h
    vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp
    vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp
    vmkit/trunk/lib/Mvm/GCMmap2/MvmGC.h
    vmkit/trunk/lib/Mvm/GCMmap2/gc.cpp
    vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp
    vmkit/trunk/lib/Mvm/GCMmap2/gcthread.cpp
    vmkit/trunk/lib/Mvm/GCMmap2/gcthread.h
    vmkit/trunk/lib/Mvm/Runtime/Object.cpp

Modified: vmkit/trunk/include/mvm/Threads/Thread.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Threads/Thread.h?rev=77588&r1=77587&r2=77588&view=diff

==============================================================================
--- vmkit/trunk/include/mvm/Threads/Thread.h (original)
+++ vmkit/trunk/include/mvm/Threads/Thread.h Thu Jul 30 04:38:29 2009
@@ -10,7 +10,7 @@
 #ifndef MVM_THREAD_H
 #define MVM_THREAD_H
 
-#include <sched.h>
+#include <stdlib.h>
 
 #include "types.h"
 
@@ -103,9 +103,7 @@
   
   /// yield - Yield the processor to another thread.
   ///
-  static void yield(void) {
-    sched_yield();
-  }
+  static void yield(void);
   
   /// kill - Kill the thread with the given pid by sending it a signal.
   ///
@@ -143,6 +141,15 @@
   ///
   bool doYield;
 
+  /// inGC - Flag to tell that the thread is being part of a GC.
+  ///
+  bool inGC;
+
+  /// stackScanned - Flag to tell that the thread's stack has already
+  /// been analyzed.
+  ///
+  bool stackScanned;
+
   /// get - Get the thread specific data of the current thread.
   ///
   static Thread* get() {
@@ -151,6 +158,12 @@
   
 private:
   
+  /// lastSP - If the thread is running native code that can not be
+  /// interrupted, lastSP is not null and contains the value of the
+  /// stack pointer before entering native.
+  ///
+  void* lastSP;
+ 
   /// internalThreadID - The implementation specific thread id.
   ///
   void* internalThreadID;
@@ -164,6 +177,10 @@
   ///
   virtual void internalClearException() {}
 
+  /// joinCollection - Join a collection.
+  ///
+  void joinCollection();
+
 public:
  
   /// ~Thread - Give the class a home.
@@ -174,6 +191,23 @@
   /// a tracer.
   ///
   virtual void tracer() {}
+  
+  void* getLastSP() { return lastSP; }
+  void  setLastSP(void* V) { lastSP = V; }
+
+  void enterUncooperativeCode() {
+    if (isMvmThread()) {
+      lastSP = __builtin_frame_address(0);
+      if (doYield && !inGC) joinCollection();
+    }
+  }
+
+  void leaveUncooperativeCode() {
+    if (isMvmThread()) {
+      lastSP = 0;
+      if (doYield && !inGC) joinCollection();
+    }
+  }
 
 
   /// clearException - Clear any pending exception of the current thread.
@@ -181,10 +215,23 @@
     internalClearException();
   }
 
+  bool isMvmThread() {
+    if (!baseAddr) return false;
+    else return (((uintptr_t)this) & MvmThreadMask) == baseAddr;
+  }
+
+  /// baseAddr - The base address for all threads.
+  static uintptr_t baseAddr;
+
   /// IDMask - Apply this mask to the stack pointer to get the Thread object.
   ///
   static const uint64_t IDMask = 0x7FF00000;
 
+  /// MvmThreadMask - Apply this mask to verify that the current thread was
+  /// created by Mvm.
+  ///
+  static const uint64_t MvmThreadMask = 0xF0000000;
+
   /// OverflowMask - Apply this mask to implement overflow checks. For
   /// efficiency, we lower the available size of the stack: it can never go
   /// under 0xC0000

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

==============================================================================
--- vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp (original)
+++ vmkit/trunk/lib/JnJVM/Compiler/JnjvmModule.cpp Thu Jul 30 04:38:29 2009
@@ -199,9 +199,9 @@
   
   OffsetIsolateInThreadConstant = ConstantInt::get(Type::Int32Ty, 3);
   OffsetDoYieldInThreadConstant = ConstantInt::get(Type::Int32Ty, 6);
-  OffsetJNIInThreadConstant = ConstantInt::get(Type::Int32Ty, 9);
-  OffsetJavaExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 10);
-  OffsetCXXExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 11);
+  OffsetJNIInThreadConstant = ConstantInt::get(Type::Int32Ty, 12);
+  OffsetJavaExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 13);
+  OffsetCXXExceptionInThreadConstant = ConstantInt::get(Type::Int32Ty, 14);
   
   ClassReadyConstant = ConstantInt::get(Type::Int8Ty, ready);
   

Modified: vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll?rev=77588&r1=77587&r2=77588&view=diff

==============================================================================
--- vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll (original)
+++ vmkit/trunk/lib/JnJVM/LLVMRuntime/runtime-default.ll Thu Jul 30 04:38:29 2009
@@ -41,13 +41,16 @@
 ;;; Field 4: MyVM
 ;;; Field 5: baseSP
 ;;; Field 6: doYield
-;;; Field 7: internalThreadID
-;;; field 8: routine
-;;; field 9: jnienv
-;;; field 10: Java pendingException
-;;; field 11: CXX pendingException
-%JavaThread = type { %VT*, %JavaThread*, %JavaThread*, i8*, i8*, i8*, i1, i8*,
-                     i8*, i8*, %JavaObject*, i8* }
+;;; Field 7: inGC
+;;; Field 8: stackScanned
+;;; Field 9: lastSP
+;;; Field 10: internalThreadID
+;;; field 11: routine
+;;; field 12: jnienv
+;;; field 13: Java pendingException
+;;; field 14: CXX pendingException
+%JavaThread = type { %VT*, %JavaThread*, %JavaThread*, i8*, i8*, i8*, i1, i1,
+                     i1, i8*, i8*, i8*, i8*, %JavaObject*, i8* }
 
 
 %Attribut = type { %UTF8*, i32, i32 }

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

==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp Thu Jul 30 04:38:29 2009
@@ -103,6 +103,9 @@
   assert((addresses.size() % 2) && "Wrong stack");
   
   addresses.push_back(cur);
+
+  // Start uncooperative mode.
+  enterUncooperativeCode();
 }
 
 void JavaThread::startJava() {

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

==============================================================================
--- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h (original)
+++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h Thu Jul 30 04:38:29 2009
@@ -240,6 +240,9 @@
   
     localJNIRefs->removeJNIReferences(this, *currentAddedReferences);
     addresses.pop_back();
+   
+    // Go back to cooperative mode.
+    leaveUncooperativeCode();
   }
 
   /// endJava - Record that we are leaving Java code.

Modified: vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp?rev=77588&r1=77587&r2=77588&view=diff

==============================================================================
--- vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp (original)
+++ vmkit/trunk/lib/Mvm/CommonThread/ctlock.cpp Thu Jul 30 04:38:29 2009
@@ -63,8 +63,11 @@
 }
 
 void LockNormal::lock() {
+  Thread* th = Thread::get();
+  th->enterUncooperativeCode();
   pthread_mutex_lock((pthread_mutex_t*)&internalLock);
-  owner = mvm::Thread::get();
+  th->leaveUncooperativeCode();
+  owner = th;
 }
 
 void LockNormal::unlock() {
@@ -75,8 +78,11 @@
 
 void LockRecursive::lock() {
   if (!selfOwner()) {
+    Thread* th = Thread::get();
+    th->enterUncooperativeCode();
     pthread_mutex_lock((pthread_mutex_t*)&internalLock);
-    owner = mvm::Thread::get();
+    th->leaveUncooperativeCode();
+    owner = th;
   }
   ++n;
 }
@@ -113,8 +119,11 @@
   if (selfOwner()) {
     n += count;
   } else {
+    Thread* th = Thread::get();
+    th->enterUncooperativeCode();
     pthread_mutex_lock((pthread_mutex_t*)&internalLock);
-    owner = mvm::Thread::get();
+    th->leaveUncooperativeCode();
+    owner = th;
     n = count;
   }
 }
@@ -136,8 +145,11 @@
 
   int n = l->unsafeUnlock();
 
+  Thread* th = Thread::get();
+  th->enterUncooperativeCode();
   int res = pthread_cond_wait((pthread_cond_t*)&internalCond,
                               (pthread_mutex_t*)&(l->internalLock));
+  th->leaveUncooperativeCode();
 
   assert(!res && "Error on wait");
   l->unsafeLock(n);
@@ -158,9 +170,12 @@
   
   int n = l->unsafeUnlock();
   
+  Thread* th = Thread::get();
+  th->enterUncooperativeCode();
   int res = pthread_cond_timedwait((pthread_cond_t*)&internalCond, 
                                    (pthread_mutex_t*)&(l->internalLock),
                                    &timeout);
+  th->leaveUncooperativeCode();
   
   assert((!res || res == ETIMEDOUT) && "Error on timed wait");
   l->unsafeLock(n);

Modified: vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp?rev=77588&r1=77587&r2=77588&view=diff

==============================================================================
--- vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp (original)
+++ vmkit/trunk/lib/Mvm/CommonThread/ctthread.cpp Thu Jul 30 04:38:29 2009
@@ -19,6 +19,7 @@
 #include <ctime>
 #include <pthread.h>
 #include <sys/mman.h>
+#include <sched.h>
 #include <unistd.h>
 
 using namespace mvm;
@@ -35,6 +36,21 @@
   pthread_exit((void*)value);
 }
 
+void Thread::yield(void) {
+  Thread* th = mvm::Thread::get();
+  if (th->isMvmThread()) {
+    if (th->doYield && !th->inGC) th->joinCollection();
+  }
+  sched_yield();
+}
+
+void Thread::joinCollection() {
+  Collector::traceStackThread();
+}
+
+
+uintptr_t Thread::baseAddr = 0;
+
 // These could be set at runtime.
 #define STACK_SIZE 0x100000
 #define NR_THREADS 255
@@ -91,6 +107,7 @@
 
     memset((void*)used, 0, NR_THREADS * sizeof(uint32));
     allocPtr = 0;
+    mvm::Thread::baseAddr = baseAddr;
   }
 
   uintptr_t allocate() {

Modified: vmkit/trunk/lib/Mvm/GCMmap2/MvmGC.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/GCMmap2/MvmGC.h?rev=77588&r1=77587&r2=77588&view=diff

==============================================================================
--- vmkit/trunk/lib/Mvm/GCMmap2/MvmGC.h (original)
+++ vmkit/trunk/lib/Mvm/GCMmap2/MvmGC.h Thu Jul 30 04:38:29 2009
@@ -81,6 +81,8 @@
   static inline size_t real_nbb(GCChunkNode *n) { 
     return n->nbb() - sizeof(gcRoot);
   }
+  
+  static void traceForeignThreadStack(mvm::Thread* th, void* endPtr);
 
 public:
   static GCThread *threads;        /* le gestionnaire de thread et de synchro */
@@ -98,6 +100,10 @@
 
   static int siggc();
 
+  static void traceStackThread() {
+    siggc_handler(0);
+  }
+
   static void inject_my_thread(mvm::Thread* th);
   static inline void  remove_my_thread(mvm::Thread* th) {
     threads->remove(th);

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

==============================================================================
--- vmkit/trunk/lib/Mvm/GCMmap2/gc.cpp (original)
+++ vmkit/trunk/lib/Mvm/GCMmap2/gc.cpp Thu Jul 30 04:38:29 2009
@@ -39,16 +39,63 @@
 
 void Collector::siggc_handler(int) {
   mvm::Thread* th = mvm::Thread::get();
+  th->inGC = true;
 
-  jmp_buf buf;
-  setjmp(buf);
   
   Collector::threads->stackLock();
+
+  if (Collector::threads->cooperative && !th->doYield) {
+    // I was previously blocked, and I'm running late: someone else collected
+    // my stack, and the GC has finished already. Just unlock and return.
+    Collector::threads->stackUnlock();
+    th->inGC = false;
+    return;
+  }
+ 
+  // I woke up while a GC was happening, and no-one has collected my stack yet.
+  // Do it now.
+  if (!th->stackScanned) {
+    jmp_buf buf;
+    setjmp(buf);
   
-  if(!th) /* The thread is being destroyed */
-    Collector::threads->another_mark();
-  else {
-    register unsigned int  **cur = (unsigned int**)(void*)&buf;
+    if(!th) /* The thread is being destroyed */
+      Collector::threads->another_mark();
+    else {
+      register unsigned int  **cur = (unsigned int**)(void*)&buf;
+      register unsigned int  **max = (unsigned int**)th->baseSP;
+    
+      GCChunkNode *node;
+    
+      for(; cur<max; cur++) {
+        if((node = o2node(*cur)) && (!Collector::isMarked(node))) {
+          node->remove();
+          node->append(Collector::used_nodes);
+          Collector::mark(node);
+        }
+      }
+    
+      Collector::threads->another_mark();
+    }
+    th->stackScanned = true;
+  }
+
+  // Wait for the collection to finish.
+  Collector::threads->waitCollection();
+  Collector::threads->stackUnlock();
+  
+  // If the current thread is not the collector thread, this means that the
+  // collection is finished. Set inGC to false.
+  if(th != threads->getCurrentCollector())
+    th->inGC = false;
+}
+
+void Collector::traceForeignThreadStack(mvm::Thread* th, void* endPtr) {
+  Collector::threads->stackLock();
+ 
+  // The thread may have waken up during this GC. In this case, it may also
+  // have collected its stack. Don't scan it then.
+  if (!th->stackScanned) {
+    register unsigned int  **cur = (unsigned int**)endPtr;
     register unsigned int  **max = (unsigned int**)th->baseSP;
     
     GCChunkNode *node;
@@ -60,9 +107,13 @@
         Collector::mark(node);
       }
     }
-    
     Collector::threads->another_mark();
-    Collector::threads->waitCollection();
+    th->stackScanned = true;
   }
+
   Collector::threads->stackUnlock();
 }
+
+extern "C" void conditionalSafePoint() {
+  Collector::traceStackThread();  
+}

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

==============================================================================
--- vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp (original)
+++ vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp Thu Jul 30 04:38:29 2009
@@ -46,6 +46,7 @@
 
   mvm::Thread* th = mvm::Thread::get();
   th->MyVM->startCollection();
+  th->inGC = true;
 
   threads->synchronize();
 
@@ -103,6 +104,7 @@
     next = cur->next();
     allocator->reject_chunk(cur);
   }
+  th->inGC = false;
 
 }
 

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

==============================================================================
--- vmkit/trunk/lib/Mvm/GCMmap2/gcthread.cpp (original)
+++ vmkit/trunk/lib/Mvm/GCMmap2/gcthread.cpp Thu Jul 30 04:38:29 2009
@@ -20,18 +20,58 @@
 }
 
 void GCThread::synchronize() {
-	int signo = Collector::siggc();
-  mvm::Thread* self = mvm::Thread::get();
-  assert(self && "No thread local data for this thread");
-	current_collector = self;
-	_nb_collected = 0;
-
- 	for(mvm::Thread* cur = (mvm::Thread*)self->next(); cur != self; 
-      cur = (mvm::Thread*)cur->next()) {
-    cur->kill(signo);
-	}
+	
+  if (cooperative) {
+    mvm::Thread* self = mvm::Thread::get();
+    assert(self && "No thread local data for this thread");
+	  current_collector = self;
+	  _nb_collected = 0;
+ 	 
+    // Lock stacks. Changes on the doYield flag of threads must be
+    // protected, as threads may wake up after being blocked in native code
+    // and join the collection.
+    stackLock();
+
+    mvm::Thread* cur = self;
+    do {
+      cur->stackScanned = false;
+      cur->doYield = true;
+      cur = (mvm::Thread*)cur->next();
+    } while (cur != self);
+    
+    // Unlock now. Each running thread will scan its stack.
+    stackUnlock();
+
+    // Scan the stacks of currently blocked threads.
+ 	  for (mvm::Thread* cur = (mvm::Thread*)self->next(); cur != self; 
+         cur = (mvm::Thread*)cur->next()) {
+      void* val = cur->getLastSP();
+      // If val is null, this means that the thread woke up, and is
+      // joining the collection. We are sure the thread will scan its stack.
+      if (val) Collector::traceForeignThreadStack(cur, val);
+	  }
+
+    // Finally, scan my stack too!
+	  Collector::siggc_handler(0);
+
+    // And wait for other threads to finish.
+    waitStacks();
+  } else {
+    int signo = Collector::siggc();
+    mvm::Thread* self = mvm::Thread::get();
+    self->stackScanned = false;
+    assert(self && "No thread local data for this thread");
+	  current_collector = self;
+	  _nb_collected = 0;
+
+ 	  for (mvm::Thread* cur = (mvm::Thread*)self->next(); cur != self; 
+         cur = (mvm::Thread*)cur->next()) {
+      cur->stackScanned = false;
+      cur->kill(signo);
+	  }
 
-	Collector::siggc_handler(signo);
+	  Collector::siggc_handler(signo);
 	
-  waitStacks();
+    waitStacks();
+  }
 }

Modified: vmkit/trunk/lib/Mvm/GCMmap2/gcthread.h
URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/GCMmap2/gcthread.h?rev=77588&r1=77587&r2=77588&view=diff

==============================================================================
--- vmkit/trunk/lib/Mvm/GCMmap2/gcthread.h (original)
+++ vmkit/trunk/lib/Mvm/GCMmap2/gcthread.h Thu Jul 30 04:38:29 2009
@@ -42,12 +42,18 @@
   
 public:
   mvm::Thread* base;
-  
+  bool cooperative;
+ 
+  mvm::Thread* getCurrentCollector() {
+    return current_collector;
+  }
+
   GCThread() {
     _nb_threads = 0;
     _nb_collected = 0;
     current_collector = 0;
     base = 0;
+    cooperative = false;
   }
   
   inline unsigned int get_nb_threads() {
@@ -61,7 +67,25 @@
 
   void        waitStacks();
   void        waitCollection();
-  inline void collectionFinished() { _collectionCond.broadcast(); }
+ 
+  inline void collectionFinished() {
+    if (cooperative) {
+      // We lock here to make sure no previously blocked in native threads
+      // will join the collection and never go back to running code.
+      stackLock();
+      mvm::Thread* cur = current_collector;
+      do {
+        cur->doYield = false;
+        cur = (mvm::Thread*)cur->next();
+      } while (cur != current_collector);
+      _collectionCond.broadcast();
+      stackUnlock();
+    } else {
+      _collectionCond.broadcast();
+    }
+    current_collector->inGC = false;
+  }
+  
   inline void collectorGo() { _stackCond.broadcast(); }
 
   inline void cancel() {

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

==============================================================================
--- vmkit/trunk/lib/Mvm/Runtime/Object.cpp (original)
+++ vmkit/trunk/lib/Mvm/Runtime/Object.cpp Thu Jul 30 04:38:29 2009
@@ -119,6 +119,8 @@
 
 void VirtualMachine::finalizerStart(mvm::Thread* th) {
   VirtualMachine* vm = th->MyVM;
+  gc* res = 0;
+  llvm_gcroot(res, 0);
 
   while (true) {
     vm->FinalizationLock.lock();
@@ -129,7 +131,6 @@
 
     while (true) {
       vm->FinalizationQueueLock.acquire();
-      gc* res = 0;
       if (vm->CurrentFinalizedIndex != 0) {
         res = vm->ToBeFinalized[--vm->CurrentFinalizedIndex];
       }
@@ -146,6 +147,7 @@
         }
       } catch(...) {
       }
+      res = 0;
       th->clearException();
     }
   }
@@ -153,6 +155,8 @@
 
 void VirtualMachine::enqueueStart(mvm::Thread* th) {
   VirtualMachine* vm = th->MyVM;
+  gc* res = 0;
+  llvm_gcroot(res, 0);
 
   while (true) {
     vm->EnqueueLock.lock();
@@ -163,7 +167,6 @@
 
     while (true) {
       vm->ToEnqueueLock.acquire();
-      gc* res = 0;
       if (vm->ToEnqueueIndex != 0) {
         res = vm->ToEnqueue[--vm->ToEnqueueIndex];
       }
@@ -174,6 +177,7 @@
         vm->enqueueReference(res);
       } catch(...) {
       }
+      res = 0;
       th->clearException();
     }
   }
@@ -307,9 +311,3 @@
 void Allocator::freeTemporaryMemory(void* obj) {
   return free(obj); 
 }
-
-
-
-extern "C" void conditionalSafePoint() {
-  abort();
-}





More information about the vmkit-commits mailing list