JavaScriptCore:
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 May 2004 06:41:06 +0000 (06:41 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 May 2004 06:41:06 +0000 (06:41 +0000)
        Reviewed by Darin.

Enable full conservative GC mode in addition to test mode. When
conservative GC is enabled, we now get an 11% speed improvement on
the iBench. Also fix some spots I missed before.

Specific noteworth changes:

        * kjs/collector.cpp:
(KJS::Collector::markStackObjectsConservatively): Check possible
cell pointers for 8-byte aligment and verify they are not 0.

        * kjs/protected_values.cpp:
        (KJS::ProtectedValues::increaseProtectCount): Move null-tolerance from here...
        (KJS::ProtectedValues::decreaseProtectCount): ...and here...
        * kjs/protect.h:
        (KJS::gcProtectNullTolerant): ...to here...
        (KJS::gcUnprotectNullTolerant): ...and here, because not all callers need the null
tolerance, and doing the check is expensive.

        * kjs/protected_values.cpp:
        (KJS::ProtectedValues::computeHash): Replace hash function with a much faster one
that is still very good.

        * kjs/protect.h:
        (KJS::gcProtect):
        (KJS::gcUnprotect):
        (KJS::ProtectedValue::ProtectedValue):
        (KJS::ProtectedValue::~ProtectedValue):
        (KJS::ProtectedValue::operator=):
        (KJS::ProtectedObject::ProtectedObject):
        (KJS::ProtectedObject::~ProtectedObject):
        (KJS::ProtectedObject::operator=):
        (KJS::ProtectedReference::ProtectedReference):
        (KJS::ProtectedReference::~ProtectedReference):
        (KJS::ProtectedReference::operator=):
        * kjs/protected_values.cpp:
        (KJS::ProtectedValues::getProtectCount):
        (KJS::ProtectedValues::increaseProtectCount):
        (KJS::ProtectedValues::decreaseProtectCount):
        (KJS::ProtectedValues::computeHash):
        * bindings/runtime_root.cpp:
        (KJS::Bindings::addNativeReference):
        (KJS::Bindings::removeNativeReference):
        (RootObject::removeAllNativeReferences):
        * bindings/runtime_root.h:
        (KJS::Bindings::RootObject::~RootObject):
        (KJS::Bindings::RootObject::setRootObjectImp):
        * kjs/collector.cpp:
        (KJS::Collector::allocate):
        (KJS::Collector::collect):
        * kjs/collector.h:
        * kjs/internal.cpp:
        (NumberImp::create):
        (InterpreterImp::globalInit):
        (InterpreterImp::globalClear):
        (InterpreterImp::mark):
        * kjs/list.cpp:
        (KJS::List::derefValues):
        (KJS::List::refValues):
        (KJS::List::append):
        * kjs/object.cpp:
        (KJS::ObjectImp::setInternalValue):
        (KJS::ObjectImp::putDirect):
        * kjs/value.cpp:
        (ValueImp::mark):
        (ValueImp::marked):
        * kjs/value.h:
        (KJS::ValueImp::ValueImp):
        (KJS::ValueImp::~ValueImp):
        (KJS::ValueImp::):
        (KJS::Value::Value):
        (KJS::Value::~Value):
        (KJS::Value::operator=):

WebCore:

        Reviewed by Darin.

        * khtml/ecma/kjs_events.cpp:
        (JSLazyEventListener::parseCode): Make sure to protect the
permanent "event" string object.

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

14 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/bindings/runtime_root.cpp
JavaScriptCore/bindings/runtime_root.h
JavaScriptCore/kjs/collector.cpp
JavaScriptCore/kjs/collector.h
JavaScriptCore/kjs/internal.cpp
JavaScriptCore/kjs/list.cpp
JavaScriptCore/kjs/object.cpp
JavaScriptCore/kjs/protect.h
JavaScriptCore/kjs/protected_values.cpp
JavaScriptCore/kjs/value.cpp
JavaScriptCore/kjs/value.h
WebCore/ChangeLog-2005-08-23
WebCore/khtml/ecma/kjs_events.cpp

index 303ed78..1a7959a 100644 (file)
@@ -1,3 +1,80 @@
+2004-04-25  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+       Enable full conservative GC mode in addition to test mode. When
+       conservative GC is enabled, we now get an 11% speed improvement on
+       the iBench. Also fix some spots I missed before.
+
+       Specific noteworth changes:
+       
+        * kjs/collector.cpp:
+       (KJS::Collector::markStackObjectsConservatively): Check possible
+       cell pointers for 8-byte aligment and verify they are not 0.
+
+        * kjs/protected_values.cpp:
+        (KJS::ProtectedValues::increaseProtectCount): Move null-tolerance from here...
+        (KJS::ProtectedValues::decreaseProtectCount): ...and here...
+        * kjs/protect.h:
+        (KJS::gcProtectNullTolerant): ...to here...
+        (KJS::gcUnprotectNullTolerant): ...and here, because not all callers need the null
+       tolerance, and doing the check is expensive.
+
+        * kjs/protected_values.cpp:
+        (KJS::ProtectedValues::computeHash): Replace hash function with a much faster one
+       that is still very good.
+
+        * kjs/protect.h:
+        (KJS::gcProtect):
+        (KJS::gcUnprotect):
+        (KJS::ProtectedValue::ProtectedValue):
+        (KJS::ProtectedValue::~ProtectedValue):
+        (KJS::ProtectedValue::operator=):
+        (KJS::ProtectedObject::ProtectedObject):
+        (KJS::ProtectedObject::~ProtectedObject):
+        (KJS::ProtectedObject::operator=):
+        (KJS::ProtectedReference::ProtectedReference):
+        (KJS::ProtectedReference::~ProtectedReference):
+        (KJS::ProtectedReference::operator=):
+        * kjs/protected_values.cpp:
+        (KJS::ProtectedValues::getProtectCount):
+        (KJS::ProtectedValues::increaseProtectCount):
+        (KJS::ProtectedValues::decreaseProtectCount):
+        (KJS::ProtectedValues::computeHash):
+        * bindings/runtime_root.cpp:
+        (KJS::Bindings::addNativeReference):
+        (KJS::Bindings::removeNativeReference):
+        (RootObject::removeAllNativeReferences):
+        * bindings/runtime_root.h:
+        (KJS::Bindings::RootObject::~RootObject):
+        (KJS::Bindings::RootObject::setRootObjectImp):
+        * kjs/collector.cpp:
+        (KJS::Collector::allocate):
+        (KJS::Collector::collect):
+        * kjs/collector.h:
+        * kjs/internal.cpp:
+        (NumberImp::create):
+        (InterpreterImp::globalInit):
+        (InterpreterImp::globalClear):
+        (InterpreterImp::mark):
+        * kjs/list.cpp:
+        (KJS::List::derefValues):
+        (KJS::List::refValues):
+        (KJS::List::append):
+        * kjs/object.cpp:
+        (KJS::ObjectImp::setInternalValue):
+        (KJS::ObjectImp::putDirect):
+        * kjs/value.cpp:
+        (ValueImp::mark):
+        (ValueImp::marked):
+        * kjs/value.h:
+        (KJS::ValueImp::ValueImp):
+        (KJS::ValueImp::~ValueImp):
+        (KJS::ValueImp::):
+        (KJS::Value::Value):
+        (KJS::Value::~Value):
+        (KJS::Value::operator=):
+
 2004-04-30  Richard Williamson   <rjw@apple.com>
 
        Asking an NSInvocation for it's return value when return type
index 6287604..24a3655 100644 (file)
@@ -158,7 +158,12 @@ void KJS::Bindings::addNativeReference (const Bindings::RootObject *root, Object
         
         unsigned int numReferences = (unsigned int)CFDictionaryGetValue (referencesDictionary, imp);
         if (numReferences == 0) {
-            imp->ref();
+#if !USE_CONSERVATIVE_GC
+           imp->ref();
+#endif
+#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
+           gcProtect(imp);
+#endif 
             CFDictionaryAddValue (referencesDictionary, imp,  (const void *)1);
         }
         else {
@@ -170,11 +175,16 @@ void KJS::Bindings::addNativeReference (const Bindings::RootObject *root, Object
 void KJS::Bindings::removeNativeReference (ObjectImp *imp)
 {
     CFMutableDictionaryRef referencesDictionary = findReferenceDictionary (imp);
-    
+
     if (referencesDictionary) {
         unsigned int numReferences = (unsigned int)CFDictionaryGetValue (referencesDictionary, imp);
         if (numReferences == 1) {
-            imp->deref();
+#if !USE_CONSERVATIVE_GC
+           imp->deref();
+#endif
+#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
+           gcUnprotect(imp);
+#endif 
             CFDictionaryRemoveValue (referencesDictionary, imp);
         }
         else {
@@ -321,7 +331,12 @@ void RootObject::removeAllNativeReferences ()
         CFDictionaryGetKeysAndValues (referencesDictionary, (const void **)allImps, NULL);
         for(i = 0; i < count; i++) {
             ObjectImp *anImp = static_cast<ObjectImp*>(allImps[i]);
+#if !USE_CONSERVATIVE_GC
             anImp->deref();
+#endif
+#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
+           gcUnprotect(anImp);
+#endif
         }
         free ((void *)allImps);
         CFDictionaryRemoveAllValues (referencesDictionary);
index 3f74324..406276f 100644 (file)
@@ -49,12 +49,23 @@ friend class JSObject;
 public:
     RootObject (const void *nativeHandle) : _nativeHandle(nativeHandle), _imp(0), _interpreter(0) {}
     ~RootObject (){
+#if !USE_CONSERVATIVE_GC
         _imp->deref();
+#endif
+#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
+       gcUnprotect(_imp);
+#endif
     }
     
     void setRootObjectImp (KJS::ObjectImp *i) { 
         _imp = i;
+#if !USE_CONSERVATIVE_GC
         _imp->ref();
+
+#endif
+#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
+       gcProtect(_imp);
+#endif
     }
     
     KJS::ObjectImp *rootObjectImp() const { return _imp; }
index 09ef8ee..048c2ae 100644 (file)
@@ -110,7 +110,9 @@ void* Collector::allocate(size_t s)
     heap.usedOversizeCells++;
     heap.numLiveObjects++;
 
+#if !USE_CONSERVATIVE_GC
     ((ValueImp *)(newCell))->_flags = 0;
+#endif
     return newCell;
   }
   
@@ -158,13 +160,16 @@ void* Collector::allocate(size_t s)
   targetBlock->usedCells++;
   heap.numLiveObjects++;
 
+#if !USE_CONSERVATIVE_GC
   ((ValueImp *)(newCell))->_flags = 0;
+#endif
   return (void *)(newCell);
 }
 
-#if TEST_CONSERVATIVE_GC
-#define IS_POINTER_ALIGNED(p) (((int)(p) & (sizeof(char *) - 1)) == 0)
+#if TEST_CONSERVATIVE_GC || USE_CONSERVATIVE_GC
+
+// cells are 8-byte aligned 
+#define IS_POINTER_ALIGNED(p) (((int)(p) & 7) == 0)
 
 void Collector::markStackObjectsConservatively(void *start, void *end)
 {
@@ -177,7 +182,7 @@ void Collector::markStackObjectsConservatively(void *start, void *end)
   
   while (p != e) {
     char *x = *p++;
-    if (IS_POINTER_ALIGNED(x)) {
+    if (IS_POINTER_ALIGNED(x) && x) {
       bool good = false;
       for (int block = 0; block < heap.usedBlocks; block++) {
        size_t offset = x - (char *)heap.blocks[block];
@@ -240,7 +245,9 @@ bool Collector::collect()
 #if TEST_CONSERVATIVE_GC
   // CONSERVATIVE MARK: mark the root set using conservative GC bit (will compare later)
   ValueImp::useConservativeMark(true);
+#endif
 
+#if USE_CONSERVATIVE_GC || TEST_CONSERVATIVE_GC
   if (InterpreterImp::s_hook) {
     InterpreterImp *scr = InterpreterImp::s_hook;
     do {
@@ -252,11 +259,13 @@ bool Collector::collect()
 
   markStackObjectsConservatively();
   markProtectedObjects();
+#endif
 
-
+#if TEST_CONSERVATIVE_GC
   ValueImp::useConservativeMark(false);
 #endif
 
+#if !USE_CONSERVATIVE_GC
   // MARK: first mark all referenced objects recursively
   // starting out from the set of root objects
   if (InterpreterImp::s_hook) {
@@ -301,6 +310,7 @@ bool Collector::collect()
       imp->mark();
     }
   }
+#endif
 
   // SWEEP: delete everything with a zero refcount (garbage) and unmark everything else
   
@@ -319,7 +329,12 @@ bool Collector::collect()
       ValueImp *imp = (ValueImp *)(curBlock->cells + cell);
 
       if (((CollectorCell *)imp)->u.freeCell.zeroIfFree != 0) {
-       if (!imp->refcount && imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED)) {
+#if USE_CONSERVATIVE_GC
+       if (!imp->_marked)
+#else
+       if (!imp->refcount && imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED))
+#endif
+       {
          //fprintf( stderr, "Collector::deleting ValueImp %p (%s)\n", (void*)imp, typeid(*imp).name());
          // emulate destructing part of 'operator delete()'
          imp->~ValueImp();
@@ -333,7 +348,9 @@ bool Collector::collect()
          curBlock->freeList = (CollectorCell *)imp;
 
        } else {
-#if TEST_CONSERVATIVE_GC
+#if USE_CONSERVATIVE_GC
+         imp->_marked = 0;
+#elif TEST_CONSERVATIVE_GC
          imp->_flags &= ~(ValueImp::VI_MARKED | ValueImp::VI_CONSERVATIVE_MARKED);
 #else
          imp->_flags &= ~ValueImp::VI_MARKED;
@@ -373,9 +390,13 @@ bool Collector::collect()
   while (cell < heap.usedOversizeCells) {
     ValueImp *imp = (ValueImp *)heap.oversizeCells[cell];
     
+#if USE_CONSERVATIVE_GC
+    if (!imp->_marked) {
+#else
     if (!imp->refcount && 
        imp->_flags == (ValueImp::VI_GCALLOWED | ValueImp::VI_CREATED)) {
-      
+#endif
+
       imp->~ValueImp();
 #if DEBUG_COLLECTOR
       heap.oversizeCells[cell]->u.freeCell.zeroIfFree = 0;
@@ -396,7 +417,13 @@ bool Collector::collect()
       }
 
     } else {
+#if USE_CONSERVATIVE_GC
+      imp->_marked = 0;
+#elif TEST_CONSERVATIVE_GC
+      imp->_flags &= ~(ValueImp::VI_MARKED | ValueImp::VI_CONSERVATIVE_MARKED);
+#else
       imp->_flags &= ~ValueImp::VI_MARKED;
+#endif
       cell++;
     }
   }
@@ -437,6 +464,7 @@ int Collector::numInterpreters()
 int Collector::numGCNotAllowedObjects()
 {
   int count = 0;
+#if !USE_CONSERVATIVE_GC
   for (int block = 0; block < heap.usedBlocks; block++) {
     CollectorBlock *curBlock = heap.blocks[block];
 
@@ -456,6 +484,7 @@ int Collector::numGCNotAllowedObjects()
       ++count;
     }
   }
+#endif
 
   return count;
 }
@@ -463,6 +492,17 @@ int Collector::numGCNotAllowedObjects()
 int Collector::numReferencedObjects()
 {
   int count = 0;
+
+#if USE_CONSERVATIVE_GC
+  for (int i = 0; i < ProtectedValues::_tableSize; i++) {
+    ValueImp *val = ProtectedValues::_table[i].key;
+    if (val) {
+      ++count;
+    }
+  }
+
+#else
+
   for (int block = 0; block < heap.usedBlocks; block++) {
     CollectorBlock *curBlock = heap.blocks[block];
 
@@ -482,6 +522,7 @@ int Collector::numReferencedObjects()
         ++count;
       }
   }
+#endif
 
   return count;
 }
@@ -489,7 +530,22 @@ int Collector::numReferencedObjects()
 const void *Collector::rootObjectClasses()
 {
   CFMutableSetRef classes = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
-  
+
+#if USE_CONSERVATIVE_GC
+  for (int i = 0; i < ProtectedValues::_tableSize; i++) {
+    ValueImp *val = ProtectedValues::_table[i].key;
+    if (val) {
+      const char *mangled_name = typeid(*val).name();
+      int status;
+      char *demangled_name = __cxxabiv1::__cxa_demangle (mangled_name, NULL, NULL, &status);
+      
+      CFStringRef className = CFStringCreateWithCString(NULL, demangled_name, kCFStringEncodingASCII);
+      free(demangled_name);
+      CFSetAddValue(classes, className);
+      CFRelease(className);
+    }
+  }
+#else
   for (int block = 0; block < heap.usedBlocks; block++) {
     CollectorBlock *curBlock = heap.blocks[block];
     for (int cell = 0; cell < CELLS_PER_BLOCK; cell++) {
@@ -523,6 +579,7 @@ const void *Collector::rootObjectClasses()
       CFRelease(className);
     }
   }
+#endif
   
   return classes;
 }
index be5bba3..aadc245 100644 (file)
@@ -71,7 +71,7 @@ namespace KJS {
 #endif
   private:
 
-#if TEST_CONSERVATIVE_GC
+#if TEST_CONSERVATIVE_GC | USE_CONSERVATIVE_GC
     static void markProtectedObjects();
     static void markStackObjectsConservatively();
     static void markStackObjectsConservatively(void *start, void *end);
index ee81761..c95a035 100644 (file)
@@ -236,7 +236,9 @@ ValueImp *NumberImp::create(int i)
     if (SimpleNumber::fits(i))
         return SimpleNumber::make(i);
     NumberImp *imp = new NumberImp(static_cast<double>(i));
+#if !USE_CONSERVATIVE_GC
     imp->setGcAllowedFast();
+#endif
     return imp;
 }
 
@@ -247,7 +249,9 @@ ValueImp *NumberImp::create(double d)
     if (isNaN(d))
         return staticNaN;
     NumberImp *imp = new NumberImp(d);
+#if !USE_CONSERVATIVE_GC
     imp->setGcAllowedFast();
+#endif
     return imp;
 }
 
@@ -479,34 +483,54 @@ void InterpreterImp::globalInit()
 {
   //fprintf( stderr, "InterpreterImp::globalInit()\n" );
   UndefinedImp::staticUndefined = new UndefinedImp();
+#if !USE_CONSERVATIVE_GC
   UndefinedImp::staticUndefined->ref();
+#endif
   NullImp::staticNull = new NullImp();
+#if !USE_CONSERVATIVE_GC
   NullImp::staticNull->ref();
+#endif
   BooleanImp::staticTrue = new BooleanImp(true);
+#if !USE_CONSERVATIVE_GC
   BooleanImp::staticTrue->ref();
+#endif
   BooleanImp::staticFalse = new BooleanImp(false);
+#if !USE_CONSERVATIVE_GC
   BooleanImp::staticFalse->ref();
+#endif
   NumberImp::staticNaN = new NumberImp(NaN);
+#if !USE_CONSERVATIVE_GC
   NumberImp::staticNaN->ref();
+#endif
 }
 
 void InterpreterImp::globalClear()
 {
   //fprintf( stderr, "InterpreterImp::globalClear()\n" );
+#if !USE_CONSERVATIVE_GC
   UndefinedImp::staticUndefined->deref();
   UndefinedImp::staticUndefined->setGcAllowed();
+#endif
   UndefinedImp::staticUndefined = 0L;
+#if !USE_CONSERVATIVE_GC
   NullImp::staticNull->deref();
   NullImp::staticNull->setGcAllowed();
+#endif
   NullImp::staticNull = 0L;
+#if !USE_CONSERVATIVE_GC
   BooleanImp::staticTrue->deref();
   BooleanImp::staticTrue->setGcAllowed();
+#endif
   BooleanImp::staticTrue = 0L;
+#if !USE_CONSERVATIVE_GC
   BooleanImp::staticFalse->deref();
   BooleanImp::staticFalse->setGcAllowed();
+#endif
   BooleanImp::staticFalse = 0L;
+#if !USE_CONSERVATIVE_GC
   NumberImp::staticNaN->deref();
   NumberImp::staticNaN->setGcAllowed();
+#endif
   NumberImp::staticNaN = 0;
 }
 
@@ -729,8 +753,6 @@ void InterpreterImp::mark()
   if (BooleanImp::staticFalse && !BooleanImp::staticFalse->marked())
     BooleanImp::staticFalse->mark();
   //fprintf( stderr, "InterpreterImp::mark this=%p global.imp()=%p\n", this, global.imp() );
-  if (global.imp())
-    global.imp()->mark();
   if (m_interpreter)
     m_interpreter->mark();
   if (_context)
index ebf9510..faa0bce 100644 (file)
@@ -158,13 +158,27 @@ void List::derefValues()
     int size = imp->size;
     
     int inlineSize = MIN(size, inlineValuesSize);
+#if !USE_CONSERVATIVE_GC
     for (int i = 0; i != inlineSize; ++i)
         imp->values[i]->deref();
+#endif
+
+#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
+    for (int i = 0; i != inlineSize; ++i)
+        gcUnprotect(imp->values[i]);
+#endif
     
     int overflowSize = size - inlineSize;
     ValueImp **overflow = imp->overflow;
+#if !USE_CONSERVATIVE_GC
     for (int i = 0; i != overflowSize; ++i)
         overflow[i]->deref();
+#endif
+
+#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
+    for (int i = 0; i != overflowSize; ++i)
+        gcUnprotect(overflow[i]);
+#endif
 }
 
 void List::refValues()
@@ -174,13 +188,25 @@ void List::refValues()
     int size = imp->size;
     
     int inlineSize = MIN(size, inlineValuesSize);
+#if !USE_CONSERVATIVE_GC
     for (int i = 0; i != inlineSize; ++i)
         imp->values[i]->ref();
+#endif
+#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
+    for (int i = 0; i != inlineSize; ++i)
+        gcProtect(imp->values[i]);
+#endif
     
     int overflowSize = size - inlineSize;
     ValueImp **overflow = imp->overflow;
+#if !USE_CONSERVATIVE_GC
     for (int i = 0; i != overflowSize; ++i)
         overflow[i]->ref();
+#endif
+#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
+    for (int i = 0; i != overflowSize; ++i)
+        gcProtect(overflow[i]);
+#endif
 }
 
 void List::markValues()
@@ -251,7 +277,12 @@ void List::append(ValueImp *v)
 #endif
 
     if (imp->valueRefCount > 0) {
+#if !USE_CONSERVATIVE_GC
        v->ref();
+#endif
+#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
+       gcProtect(v);
+#endif
     }
     
     if (i < inlineValuesSize) {
index f6c01fc..a4ebd17 100644 (file)
@@ -427,7 +427,9 @@ void ObjectImp::setInternalValue(const Value &v)
 
 void ObjectImp::setInternalValue(ValueImp *v)
 {
+#if !USE_CONSERVATIVE_GC
   v->setGcAllowed();
+#endif
   _internalValue = v;
 }
 
@@ -464,7 +466,9 @@ Object ObjectImp::toObject(ExecState */*exec*/) const
 
 void ObjectImp::putDirect(const Identifier &propertyName, ValueImp *value, int attr)
 {
+#if !USE_CONSERVATIVE_GC
     value->setGcAllowed();
+#endif
     _prop.put(propertyName, value, attr);
 }
 
index 1bf2a61..3f3ee9d 100644 (file)
@@ -33,28 +33,39 @@ namespace KJS {
 
     inline void gcProtect(ValueImp *val) 
       { 
-#if TEST_CONSERVATIVE_GC
+#if TEST_CONSERVATIVE_GC | USE_CONSERVATIVE_GC
        ProtectedValues::increaseProtectCount(val);
 #endif
       }
     inline void gcUnprotect(ValueImp *val)
       { 
-#if TEST_CONSERVATIVE_GC
+#if TEST_CONSERVATIVE_GC | USE_CONSERVATIVE_GC
        ProtectedValues::decreaseProtectCount(val);
 #endif
       }
+
+    inline void gcProtectNullTolerant(ValueImp *val) 
+      {
+       if (val) gcProtect(val);
+      }
+
+    inline void gcUnprotectNullTolerant(ValueImp *val) 
+      {
+       if (val) gcUnprotect(val);
+      }
+
     
     class ProtectedValue : public Value {
     public:
       ProtectedValue() : Value() {}
-      ProtectedValue(const Value&v)  : Value(v) { gcProtect(v.imp()); };
-      ~ProtectedValue() { gcUnprotect(imp());}
+      ProtectedValue(const Value&v)  : Value(v) { gcProtectNullTolerant(v.imp()); };
+      ~ProtectedValue() { gcUnprotectNullTolerant(imp());}
       ProtectedValue& operator=(const Value &v)
        { 
          ValueImp *old = imp();
          Value::operator=(v); 
-         gcProtect(v.imp());
-         gcUnprotect(old); 
+         gcProtectNullTolerant(v.imp());
+         gcUnprotectNullTolerant(old); 
          return *this;
        }
     private:
@@ -65,14 +76,14 @@ namespace KJS {
     class ProtectedObject : public Object {
     public:
       ProtectedObject() : Object() {}
-      ProtectedObject(const Object&o)  : Object(o) { gcProtect(o.imp()); };
-      ~ProtectedObject() { gcUnprotect(imp());}
+      ProtectedObject(const Object&o)  : Object(o) { gcProtectNullTolerant(o.imp()); };
+      ~ProtectedObject() { gcUnprotectNullTolerant(imp());}
       ProtectedObject& operator=(const Object &o)
        { 
          ValueImp *old = imp();
          Object::operator=(o); 
-         gcProtect(o.imp());
-         gcUnprotect(old); 
+         gcProtectNullTolerant(o.imp());
+         gcUnprotectNullTolerant(old); 
          return *this;
        }
     private:
@@ -82,14 +93,14 @@ namespace KJS {
 
     class ProtectedReference : public Reference {
     public:
-      ProtectedReference(const Reference&r)  : Reference(r) { gcProtect(r.base.imp()); };
-      ~ProtectedReference() { gcUnprotect(base.imp());}
+      ProtectedReference(const Reference&r)  : Reference(r) { gcProtectNullTolerant(r.base.imp()); };
+      ~ProtectedReference() { gcUnprotectNullTolerant(base.imp());}
       ProtectedReference& operator=(const Reference &r)
        { 
          ValueImp *old = base.imp();
          Reference::operator=(r); 
-         gcProtect(r.base.imp());
-         gcUnprotect(old); 
+         gcProtectNullTolerant(r.base.imp());
+         gcUnprotectNullTolerant(old); 
          return *this;
        }
     private:
index fe6df1e..9bb578a 100644 (file)
@@ -33,9 +33,6 @@ int ProtectedValues::_keyCount;
 
 int ProtectedValues::getProtectCount(ValueImp *k)
 {
-    if (!k)
-       return 0;
-
     if (!_table)
        return 0;
 
@@ -59,8 +56,7 @@ int ProtectedValues::getProtectCount(ValueImp *k)
 
 void ProtectedValues::increaseProtectCount(ValueImp *k)
 {
-    if (!k)
-       return;
+    assert(k);
 
     if (!_table)
         expand();
@@ -106,8 +102,7 @@ inline void ProtectedValues::insert(ValueImp *k, int v)
 
 void ProtectedValues::decreaseProtectCount(ValueImp *k)
 {
-    if (!k)
-       return;
+    assert(k);
 
     unsigned hash = computeHash(k);
     
@@ -182,36 +177,53 @@ void ProtectedValues::rehash(int newTableSize)
 // or anything like that.
 const unsigned PHI = 0x9e3779b9U;
 
+template <int size> static unsigned hash(ValueImp *pointer);
+
+template <> static inline unsigned hash<4>(ValueImp *pointer) 
+{
+  int a = (int)PHI;
+  int b = (int)pointer;
+  int c = 0;
+
+  a -= b; a -= c; a ^= (c>>13);
+  b -= c; b -= a; b ^= (a<<8); 
+  c -= a; c -= b; c ^= (b>>13);
+  a -= b; a -= c; a ^= (c>>12);
+  b -= c; b -= a; b ^= (a<<16);
+  c -= a; c -= b; c ^= (b>>5);
+  a -= b; a -= c; a ^= (c>>3);
+  b -= c; b -= a; b ^= (a<<10);
+  c -= a; c -= b; c ^= (b>>15);
+  
+  return (unsigned)c;
+}
+
+template <> static inline unsigned hash<8>(ValueImp *pointer)
+{
+  int a = (int)PHI;
+  int b = (int)(long)pointer;
+  int c = (int)(((long)pointer >> 16) >> 16);
+
+  a -= b; a -= c; a ^= (c>>13);
+  b -= c; b -= a; b ^= (a<<8); 
+  c -= a; c -= b; c ^= (b>>13);
+  a -= b; a -= c; a ^= (c>>12);
+  b -= c; b -= a; b ^= (a<<16);
+  c -= a; c -= b; c ^= (b>>5);
+  a -= b; a -= c; a ^= (c>>3);
+  b -= c; b -= a; b ^= (a<<10);
+  c -= a; c -= b; c ^= (b>>15);
+  
+  return (unsigned)c;
+}
+
+
 // This hash algorithm comes from:
 // http://burtleburtle.net/bob/hash/hashfaq.html
 // http://burtleburtle.net/bob/hash/doobs.html
 unsigned ProtectedValues::computeHash(ValueImp *pointer)
 {
-    int length = sizeof(ValueImp *);
-    char s[sizeof(ValueImp *)];
-               
-    memcpy((void *)s, (void *)&pointer, sizeof(ValueImp *));
-
-    unsigned h = PHI;
-    h += length;
-    h += (h << 10); 
-    h ^= (h << 6); 
-
-    for (int i = 0; i < length; i++) {
-        h += (unsigned char)s[i];
-       h += (h << 10); 
-       h ^= (h << 6); 
-    }
-
-    h += (h << 3);
-    h ^= (h >> 11);
-    h += (h << 15);
-
-    if (h == 0)
-        h = 0x80000000;
-
-    return h;
+  return hash<sizeof(ValueImp *)>(pointer);
 }
 
-
 } // namespace
index 88913da..2267608 100644 (file)
@@ -43,6 +43,7 @@ using namespace KJS;
 
 // ----------------------------- ValueImp -------------------------------------
 
+#if !USE_CONSERVATIVE_GC
 ValueImp::ValueImp() :
   refcount(0),
   // Tell the garbage collector that this memory block corresponds to a real object now
@@ -55,6 +56,7 @@ ValueImp::~ValueImp()
 {
   //fprintf(stderr,"ValueImp::~ValueImp %p\n",(void*)this);
 }
+#endif
 
 #if TEST_CONSERVATIVE_GC
 static bool conservativeMark = false;
@@ -68,7 +70,9 @@ void ValueImp::useConservativeMark(bool use)
 void ValueImp::mark()
 {
   //fprintf(stderr,"ValueImp::mark %p\n",(void*)this);
-#if TEST_CONSERVATIVE_GC
+#if USE_CONSERVATIVE_GC
+  _marked = true;
+#elif TEST_CONSERVATIVE_GC
   if (conservativeMark) {
     _flags |= VI_CONSERVATIVE_MARKED;
   } else {
@@ -85,7 +89,9 @@ void ValueImp::mark()
 bool ValueImp::marked() const
 {
   // Simple numbers are always considered marked.
-#if TEST_CONSERVATIVE_GC
+#if USE_CONSERVATIVE_GC
+  return SimpleNumber::is(this) || _marked;
+#elif TEST_CONSERVATIVE_GC
   if (conservativeMark) {
     return SimpleNumber::is(this) || (_flags & VI_CONSERVATIVE_MARKED);
   } else {
@@ -96,6 +102,7 @@ bool ValueImp::marked() const
 #endif
 }
 
+#if !USE_CONSERVATIVE_GC
 void ValueImp::setGcAllowed()
 {
   //fprintf(stderr,"ValueImp::setGcAllowed %p\n",(void*)this);
@@ -104,6 +111,7 @@ void ValueImp::setGcAllowed()
   if (!SimpleNumber::is(this))
     _flags |= VI_GCALLOWED;
 }
+#endif
 
 void* ValueImp::operator new(size_t s)
 {
@@ -241,6 +249,8 @@ bool ValueImp::dispatchToUInt32(uint32_t& result) const
 
 // ------------------------------ Value ----------------------------------------
 
+#if !USE_CONSERVATIVE_GC
+
 Value::Value(ValueImp *v)
 {
   rep = v;
@@ -293,6 +303,7 @@ Value& Value::operator=(const Value &v)
   }
   return *this;
 }
+#endif
 
 // ------------------------------ Undefined ------------------------------------
 
index c225352..8e5bd89 100644 (file)
@@ -25,6 +25,7 @@
 #ifndef _KJS_VALUE_H_
 #define _KJS_VALUE_H_
 
+#define USE_CONSERVATIVE_GC 0
 #define TEST_CONSERVATIVE_GC 0
 
 #ifndef NDEBUG // protection against problems if committing with KJS_VERBOSE on
@@ -94,17 +95,25 @@ namespace KJS {
     friend class Value;
     friend class ContextImp;
   public:
+#if USE_CONSERVATIVE_GC
+    ValueImp() : _marked(0) {}
+    virtual ~ValueImp() {}
+#else
     ValueImp();
     virtual ~ValueImp();
+#endif
 
+#if !USE_CONSERVATIVE_GC
     ValueImp* ref() { if (!SimpleNumber::is(this)) refcount++; return this; }
     bool deref() { if (SimpleNumber::is(this)) return false; else return (!--refcount); }
+#endif
 
     virtual void mark();
     bool marked() const;
     void* operator new(size_t);
     void operator delete(void*);
 
+#if !USE_CONSERVATIVE_GC
     /**
      * @internal
      *
@@ -114,6 +123,7 @@ namespace KJS {
     
     // Will crash if called on a simple number.
     void setGcAllowedFast() { _flags |= VI_GCALLOWED; }
+#endif
 
     double toInteger(ExecState *exec) const;
     int32_t toInt32(ExecState *exec) const;
@@ -130,11 +140,11 @@ namespace KJS {
     bool dispatchToUInt32(uint32_t&) const;
     Object dispatchToObject(ExecState *exec) const;
 
+#if !USE_CONSERVATIVE_GC
     unsigned short int refcount;
+#endif
 
   private:
-    unsigned short int _flags;
-
     virtual Type type() const = 0;
 
     // The conversion operations
@@ -146,14 +156,20 @@ namespace KJS {
     virtual Object toObject(ExecState *exec) const = 0;
     virtual bool toUInt32(unsigned&) const;
 
+#if USE_CONSERVATIVE_GC
+    bool _marked;
+#else
+    unsigned short int _flags;
+
     enum {
       VI_MARKED = 1,
       VI_GCALLOWED = 2,
       VI_CREATED = 4
 #if TEST_CONSERVATIVE_GC
       , VI_CONSERVATIVE_MARKED = 8
-#endif
+#endif // TEST_CONSERVATIVE_GC
     }; // VI means VALUEIMPL
+#endif // USE_CONSERVATIVE_GC
 
     // Give a compile time error if we try to copy one of these.
     ValueImp(const ValueImp&);
@@ -182,11 +198,18 @@ namespace KJS {
   class Value {
   public:
     Value() : rep(0) { }
+#if USE_CONSERVATIVE_GC
+    explicit Value(ValueImp *v) : rep(v) {}
+    Value(const Value &v) : rep (v.rep) {}
+    ~Value() {}
+    Value& operator=(const Value &v) { rep = v.rep; return *this; } 
+#else
     explicit Value(ValueImp *v);
     Value(const Value &v);
     ~Value();
-
     Value& operator=(const Value &v);
+#endif
+
     bool isNull() const { return rep == 0; }
     ValueImp *imp() const { return rep; }
 
index 19a2b8c..4282d89 100644 (file)
@@ -1,3 +1,11 @@
+2004-04-25  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+        * khtml/ecma/kjs_events.cpp:
+        (JSLazyEventListener::parseCode): Make sure to protect the
+       permanent "event" string object.
+
 2004-05-05  David Hyatt  <hyatt@apple.com>
 
        Fixes for 3637924, 3643356, and 3558513, all crashes in recalcStyle.  Make sure the tree is always in a
index 07fb673..b7a14de 100644 (file)
@@ -188,7 +188,7 @@ void JSLazyEventListener::parseCode() const
       KJS::Object constr = interpreter->builtinFunction();
       KJS::List args;
 
-      static KJS::String eventString("event");
+      static ProtectedValue eventString = KJS::String("event");
 
       args.append(eventString);
       args.append(KJS::String(code));