Reviewed by Ken.
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Nov 2004 02:06:13 +0000 (02:06 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Nov 2004 02:06:13 +0000 (02:06 +0000)
<rdar://problem/3889696> Enable conservative garbage collection for JavaScript

* kjs/collector.cpp:
        (KJS::Collector::Thread::Thread):
        (KJS::destroyRegisteredThread):
        (KJS::initializeRegisteredThreadKey):
        (KJS::Collector::registerThread):
        (KJS::Collector::markStackObjectsConservatively):
        (KJS::Collector::markCurrentThreadConservatively):
        (KJS::Collector::markOtherThreadConservatively):
        * kjs/collector.h:
        * kjs/internal.cpp:
        (lockInterpreter):
        * kjs/value.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8067 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/kjs/collector.cpp
JavaScriptCore/kjs/collector.h
JavaScriptCore/kjs/internal.cpp
JavaScriptCore/kjs/value.h

index ad40330e1a7d5f42ce881858f9f46ec0d47fd477..249fa26955d6d0568628157ba44c3da89b98030d 100644 (file)
@@ -1,3 +1,22 @@
+2004-11-21  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Ken.
+
+       <rdar://problem/3889696> Enable conservative garbage collection for JavaScript
+        
+       * kjs/collector.cpp:
+        (KJS::Collector::Thread::Thread):
+        (KJS::destroyRegisteredThread):
+        (KJS::initializeRegisteredThreadKey):
+        (KJS::Collector::registerThread):
+        (KJS::Collector::markStackObjectsConservatively):
+        (KJS::Collector::markCurrentThreadConservatively):
+        (KJS::Collector::markOtherThreadConservatively):
+        * kjs/collector.h:
+        * kjs/internal.cpp:
+        (lockInterpreter):
+        * kjs/value.h:
+
 === Safari-172 ===
 
 2004-11-15  Richard Williamson   <rjw@apple.com>
index 048c2aecec8bbb3c798c832e651c3236847120ee..2c7113ebe4c3ca914132f289825db2af3819480a 100644 (file)
 #include <value.h>
 #include <internal.h>
 
+#if APPLE_CHANGES
+#include <pthread.h>
+#include <mach/mach_port.h>
+#include <mach/task.h>
+#include <mach/thread_act.h>
+#endif
+
 namespace KJS {
 
 // tunable parameters
@@ -168,11 +175,67 @@ void* Collector::allocate(size_t s)
 
 #if TEST_CONSERVATIVE_GC || USE_CONSERVATIVE_GC
 
+struct Collector::Thread {
+  Thread(pthread_t pthread, mach_port_t mthread) : posixThread(pthread), machThread(mthread) {}
+  Thread *next;
+  pthread_t posixThread;
+  mach_port_t machThread;
+};
+
+pthread_key_t registeredThreadKey;
+pthread_once_t registeredThreadKeyOnce = PTHREAD_ONCE_INIT;
+Collector::Thread *registeredThreads;
+  
+static void destroyRegisteredThread(void *data) 
+{
+  Collector::Thread *thread = (Collector::Thread *)data;
+
+  if (registeredThreads == thread) {
+    registeredThreads = registeredThreads->next;
+  } else {
+    Collector::Thread *last = registeredThreads;
+    for (Collector::Thread *t = registeredThreads->next; t != NULL; t = t->next) {
+      if (t == thread) {
+        last->next = t->next;
+          break;
+      }
+      last = t;
+    }
+  }
+
+  delete thread;
+}
+
+static void initializeRegisteredThreadKey()
+{
+  pthread_key_create(&registeredThreadKey, destroyRegisteredThread);
+}
+
+void Collector::registerThread()
+{
+  pthread_once(&registeredThreadKeyOnce, initializeRegisteredThreadKey);
+
+  if (!pthread_getspecific(registeredThreadKey)) {
+    pthread_t pthread = pthread_self();
+    Collector::Thread *thread = new Collector::Thread(pthread, pthread_mach_thread_np(pthread));
+    thread->next = registeredThreads;
+    registeredThreads = thread;
+    pthread_setspecific(registeredThreadKey, thread);
+  }
+}
+
+
 // cells are 8-byte aligned 
 #define IS_POINTER_ALIGNED(p) (((int)(p) & 7) == 0)
 
 void Collector::markStackObjectsConservatively(void *start, void *end)
 {
+  if (start > end) {
+    void *tmp = start;
+    start = end;
+    end = tmp;
+  }
+
   assert(((char *)end - (char *)start) < 0x1000000);
   assert(IS_POINTER_ALIGNED(start));
   assert(IS_POINTER_ALIGNED(end));
@@ -212,18 +275,68 @@ void Collector::markStackObjectsConservatively(void *start, void *end)
   }
 }
 
-void Collector::markStackObjectsConservatively()
+void Collector::markCurrentThreadConservatively()
 {
   jmp_buf registers;
   setjmp(registers);
 
   pthread_t thread = pthread_self();
   void *stackBase = pthread_get_stackaddr_np(thread);
-  void *stackPointer;
-  asm("mr %0,r1" : "=r" (stackPointer));
+  int dummy;
+  void *stackPointer = &dummy;
   markStackObjectsConservatively(stackPointer, stackBase);
 }
 
+typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit
+
+void Collector::markOtherThreadConservatively(Thread *thread)
+{
+  thread_suspend(thread->machThread);
+
+#if defined(__i386__)
+  i386_thread_state_t regs;
+  unsigned user_count = sizeof(regs)/sizeof(int);
+  thread_state_flavor_t flavor = i386_THREAD_STATE;
+#elif defined(__ppc__)
+  ppc_thread_state_t  regs;
+  unsigned user_count = PPC_THREAD_STATE_COUNT;
+  thread_state_flavor_t flavor = PPC_THREAD_STATE;
+#elif defined(__ppc64__)
+  ppc_thread_state64_t  regs;
+  unsigned user_count = PPC_THREAD_STATE64_COUNT;
+  thread_state_flavor_t flavor = PPC_THREAD_STATE64;
+#else
+#error Unknown Architecture
+#endif
+  // get the thread register state
+  thread_get_state(thread->machThread, flavor, (thread_state_t)&regs, &user_count);
+  
+  // scan the registers
+  markStackObjectsConservatively((void *)&regs, (void *)((char *)&regs + (user_count * sizeof(usword_t))));
+  
+  // scan the stack
+#if defined(__i386__)
+  markStackObjectsConservatively((void *)regs.esp, pthread_get_stackaddr_np(thread->posixThread));
+#elif defined(__ppc__) || defined(__ppc64__)
+  markStackObjectsConservatively((void *)regs.r1, pthread_get_stackaddr_np(thread->posixThread));
+#else
+#error Unknown Architecture
+#endif
+
+  thread_resume(thread->machThread);
+}
+
+void Collector::markStackObjectsConservatively()
+{
+  markCurrentThreadConservatively();
+
+  for (Thread *thread = registeredThreads; thread != NULL; thread = thread->next) {
+    if (thread->posixThread != pthread_self()) {
+      markOtherThreadConservatively(thread);
+    }
+  }
+}
+
 void Collector::markProtectedObjects()
 {
   for (int i = 0; i < ProtectedValues::_tableSize; i++) {
index aadc245cc4300b1542398c6e22bd5de3c9a1835e..2e1d259bee83b00849e15e306299a7243b380b02 100644 (file)
@@ -68,11 +68,18 @@ namespace KJS {
     static int numGCNotAllowedObjects();
     static int numReferencedObjects();
     static const void *rootObjectClasses(); // actually returns CFSetRef
+#endif
+#if TEST_CONSERVATIVE_GC | USE_CONSERVATIVE_GC
+    class Thread;
+
+    static void registerThread();
 #endif
   private:
 
 #if TEST_CONSERVATIVE_GC | USE_CONSERVATIVE_GC
     static void markProtectedObjects();
+    static void markCurrentThreadConservatively();
+    static void markOtherThreadConservatively(Thread *thread);
     static void markStackObjectsConservatively();
     static void markStackObjectsConservatively(void *start, void *end);
 #endif
index 80ec912ab4e50d60388d0db767931b8c9bde1abd..b4c8dd780a601ce85392315b8e6f979ba457ed0e 100644 (file)
@@ -94,6 +94,7 @@ static inline void lockInterpreter()
   pthread_once(&interpreterLockOnce, initializeInterpreterLock);
   pthread_mutex_lock(&interpreterLock);
   interpreterLockCount++;
+  Collector::registerThread();
 }
 
 static inline void unlockInterpreter()
index 8e5bd89afd3eb666c78db061e791a41646e71b3c..ac5186ff00ab8e82fb97f641c1ea983c5e715ce6 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef _KJS_VALUE_H_
 #define _KJS_VALUE_H_
 
-#define USE_CONSERVATIVE_GC 0
+#define USE_CONSERVATIVE_GC 1
 #define TEST_CONSERVATIVE_GC 0
 
 #ifndef NDEBUG // protection against problems if committing with KJS_VERBOSE on