Reviewed by Darin.

	Implementation of conservative GC, based partly on code from
	Darin. It's turned off for now, so it shouldn't have any effect on
	the normal build.

        * JavaScriptCore.pbproj/project.pbxproj:
        * kjs/collector.cpp:
        (KJS::Collector::markStackObjectsConservatively):
        (KJS::Collector::markProtectedObjects):
        (KJS::Collector::collect):
        * kjs/collector.h:
        * kjs/protect.h:
        (KJS::gcProtect):
        (KJS::gcUnprotect):
        * kjs/protected_values.cpp: Added.
        (KJS::ProtectedValues::getProtectCount):
        (KJS::ProtectedValues::increaseProtectCount):
        (KJS::ProtectedValues::insert):
        (KJS::ProtectedValues::decreaseProtectCount):
        (KJS::ProtectedValues::expand):
        (KJS::ProtectedValues::shrink):
        (KJS::ProtectedValues::rehash):
        (KJS::ProtectedValues::computeHash):
        * kjs/protected_values.h: Added.
        * kjs/value.cpp:
        (ValueImp::useConservativeMark):
        (ValueImp::mark):
        (ValueImp::marked):
        * kjs/value.h:
        (KJS::ValueImp::):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@6472 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/kjs/collector.cpp b/JavaScriptCore/kjs/collector.cpp
index ec6cfb6..09ef8ee 100644
--- a/JavaScriptCore/kjs/collector.cpp
+++ b/JavaScriptCore/kjs/collector.cpp
@@ -162,12 +162,101 @@
   return (void *)(newCell);
 }
 
+#if TEST_CONSERVATIVE_GC
+ 
+#define IS_POINTER_ALIGNED(p) (((int)(p) & (sizeof(char *) - 1)) == 0)
+
+void Collector::markStackObjectsConservatively(void *start, void *end)
+{
+  assert(((char *)end - (char *)start) < 0x1000000);
+  assert(IS_POINTER_ALIGNED(start));
+  assert(IS_POINTER_ALIGNED(end));
+  
+  char **p = (char **)start;
+  char **e = (char **)end;
+  
+  while (p != e) {
+    char *x = *p++;
+    if (IS_POINTER_ALIGNED(x)) {
+      bool good = false;
+      for (int block = 0; block < heap.usedBlocks; block++) {
+	size_t offset = x - (char *)heap.blocks[block];
+	const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1);
+	if (offset <= lastCellOffset && offset % sizeof(CollectorCell) == 0) {
+	  good = true;
+	  break;
+	}
+      }
+      
+      if (!good) {
+	int n = heap.usedOversizeCells;
+	for (int i = 0; i != n; i++) {
+	  if (x == (char *)heap.oversizeCells[i]) {
+	    good = true;
+	    break;
+	  }
+	}
+      }
+      
+      if (good && ((CollectorCell *)x)->u.freeCell.zeroIfFree != 0) {
+	ValueImp *imp = (ValueImp *)x;
+	if (!imp->marked())
+	  imp->mark();
+      }
+    }
+  }
+}
+
+void Collector::markStackObjectsConservatively()
+{
+  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));
+  markStackObjectsConservatively(stackPointer, stackBase);
+}
+
+void Collector::markProtectedObjects()
+{
+  for (int i = 0; i < ProtectedValues::_tableSize; i++) {
+    ValueImp *val = ProtectedValues::_table[i].key;
+    if (val && !val->marked()) {
+      val->mark();
+    }
+  }
+}
+
+#endif
+
 bool Collector::collect()
 {
   assert(Interpreter::lockCount() > 0);
 
   bool deleted = false;
 
+#if TEST_CONSERVATIVE_GC
+  // CONSERVATIVE MARK: mark the root set using conservative GC bit (will compare later)
+  ValueImp::useConservativeMark(true);
+
+  if (InterpreterImp::s_hook) {
+    InterpreterImp *scr = InterpreterImp::s_hook;
+    do {
+      //fprintf( stderr, "Collector marking interpreter %p\n",(void*)scr);
+      scr->mark();
+      scr = scr->next;
+    } while (scr != InterpreterImp::s_hook);
+  }
+
+  markStackObjectsConservatively();
+  markProtectedObjects();
+
+
+  ValueImp::useConservativeMark(false);
+#endif
+
   // MARK: first mark all referenced objects recursively
   // starting out from the set of root objects
   if (InterpreterImp::s_hook) {
@@ -244,7 +333,11 @@
 	  curBlock->freeList = (CollectorCell *)imp;
 
 	} else {
+#if TEST_CONSERVATIVE_GC
+	  imp->_flags &= ~(ValueImp::VI_MARKED | ValueImp::VI_CONSERVATIVE_MARKED);
+#else
 	  imp->_flags &= ~ValueImp::VI_MARKED;
+#endif
 	}
       } else {
 	minimumCellsToProcess++;