Reviewed by Geoff.
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 19 Sep 2005 06:57:28 +0000 (06:57 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 19 Sep 2005 06:57:28 +0000 (06:57 +0000)
- fixed <rdar://problem/4214783> REGRESSION: kjs_fast_malloc crash due to lack of locking on multiple threads (seen selecting volumes in the installer)

Make sure to lock using the InterpreterLock class in all places that need it
(including anything that uses the collector, the parser, the protect count hash table,
and anything that allocates via fast_malloc).

Also added assertions to ensure that the locking rules are followed for the relevant
resources.

        * Makefile.am:
        * bindings/NP_jsobject.cpp:
        (identifierFromNPIdentifier):
        (_NPN_Invoke):
        (_NPN_Evaluate):
        (_NPN_GetProperty):
        (_NPN_SetProperty):
        (_NPN_RemoveProperty):
        (_NPN_HasProperty):
        (_NPN_HasMethod):
        (_NPN_SetException):
        * bindings/jni/jni_jsobject.cpp:
        (JSObject::call):
        (JSObject::eval):
        (JSObject::getMember):
        (JSObject::setMember):
        (JSObject::removeMember):
        (JSObject::getSlot):
        (JSObject::setSlot):
        (JSObject::toString):
        (JSObject::convertJObjectToValue):
        * bindings/objc/WebScriptObject.mm:
        (-[WebScriptObject callWebScriptMethod:withArguments:]):
        (-[WebScriptObject evaluateWebScript:]):
        (-[WebScriptObject setValue:forKey:]):
        (-[WebScriptObject valueForKey:]):
        (-[WebScriptObject removeWebScriptKey:]):
        (-[WebScriptObject stringRepresentation]):
        (-[WebScriptObject webScriptValueAtIndex:]):
        (-[WebScriptObject setWebScriptValueAtIndex:value:]):
        (+[WebScriptObject _convertValueToObjcValue:KJS::originExecutionContext:Bindings::executionContext:Bindings::]):
        * bindings/runtime.cpp:
        (Instance::createRuntimeObject):
        * bindings/runtime_root.h:
        * bindings/testbindings.cpp:
        (main):
        * bindings/testbindings.mm:
        (main):
        * kjs/fast_malloc.cpp:
        (KJS::kjs_fast_malloc):
        (KJS::kjs_fast_calloc):
        (KJS::kjs_fast_free):
        (KJS::kjs_fast_realloc):
        * kjs/fast_malloc.h:
        * kjs/identifier.h:
        * kjs/internal.cpp:
        (InterpreterImp::InterpreterImp):
        (InterpreterImp::clear):
        (InterpreterImp::mark):
        (InterpreterImp::checkSyntax):
        (InterpreterImp::evaluate):
        * kjs/internal.h:
        (KJS::InterpreterImp::globalObject):
        * kjs/interpreter.cpp:
        (Interpreter::evaluate):
        * kjs/interpreter.h:
        (KJS::InterpreterLock::InterpreterLock):
        (KJS::InterpreterLock::~InterpreterLock):
        * kjs/nodes.h:
        * kjs/protect.h:
        (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_object.h:
        * kjs/protected_values.cpp:
        (KJS::ProtectedValues::getProtectCount):
        (KJS::ProtectedValues::increaseProtectCount):
        (KJS::ProtectedValues::decreaseProtectCount):
        * kjs/string_object.cpp:
        (StringObjectImp::StringObjectImp):
        * kjs/testkjs.cpp:
        (main):

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

24 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
JavaScriptCore/bindings/NP_jsobject.cpp
JavaScriptCore/bindings/jni/jni_jsobject.cpp
JavaScriptCore/bindings/objc/WebScriptObject.mm
JavaScriptCore/bindings/runtime.cpp
JavaScriptCore/bindings/runtime_root.h
JavaScriptCore/bindings/testbindings.cpp
JavaScriptCore/bindings/testbindings.mm
JavaScriptCore/kjs/fast_malloc.cpp
JavaScriptCore/kjs/identifier.h
JavaScriptCore/kjs/internal.cpp
JavaScriptCore/kjs/internal.h
JavaScriptCore/kjs/interpreter.cpp
JavaScriptCore/kjs/interpreter.h
JavaScriptCore/kjs/nodes.h
JavaScriptCore/kjs/property_map.cpp
JavaScriptCore/kjs/protect.h
JavaScriptCore/kjs/protected_object.h [deleted file]
JavaScriptCore/kjs/protected_values.cpp
JavaScriptCore/kjs/reference.h
JavaScriptCore/kjs/reference_list.cpp
JavaScriptCore/kjs/string_object.cpp
JavaScriptCore/kjs/testkjs.cpp

index a4372d0ef6670180d4a61b948aca8783f2fd5087..e527e7b90a1980b1856c5f04bbd0a568e05c61dc 100644 (file)
@@ -1,3 +1,95 @@
+2005-09-14  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Geoff.
+
+       - fixed <rdar://problem/4214783> REGRESSION: kjs_fast_malloc crash due to lack of locking on multiple threads (seen selecting volumes in the installer)
+
+       Make sure to lock using the InterpreterLock class in all places that need it
+       (including anything that uses the collector, the parser, the protect count hash table,
+       and anything that allocates via fast_malloc).
+
+       Also added assertions to ensure that the locking rules are followed for the relevant
+       resources.
+
+        * Makefile.am:
+        * bindings/NP_jsobject.cpp:
+        (identifierFromNPIdentifier):
+        (_NPN_Invoke):
+        (_NPN_Evaluate):
+        (_NPN_GetProperty):
+        (_NPN_SetProperty):
+        (_NPN_RemoveProperty):
+        (_NPN_HasProperty):
+        (_NPN_HasMethod):
+        (_NPN_SetException):
+        * bindings/jni/jni_jsobject.cpp:
+        (JSObject::call):
+        (JSObject::eval):
+        (JSObject::getMember):
+        (JSObject::setMember):
+        (JSObject::removeMember):
+        (JSObject::getSlot):
+        (JSObject::setSlot):
+        (JSObject::toString):
+        (JSObject::convertJObjectToValue):
+        * bindings/objc/WebScriptObject.mm:
+        (-[WebScriptObject callWebScriptMethod:withArguments:]):
+        (-[WebScriptObject evaluateWebScript:]):
+        (-[WebScriptObject setValue:forKey:]):
+        (-[WebScriptObject valueForKey:]):
+        (-[WebScriptObject removeWebScriptKey:]):
+        (-[WebScriptObject stringRepresentation]):
+        (-[WebScriptObject webScriptValueAtIndex:]):
+        (-[WebScriptObject setWebScriptValueAtIndex:value:]):
+        (+[WebScriptObject _convertValueToObjcValue:KJS::originExecutionContext:Bindings::executionContext:Bindings::]):
+        * bindings/runtime.cpp:
+        (Instance::createRuntimeObject):
+        * bindings/runtime_root.h:
+        * bindings/testbindings.cpp:
+        (main):
+        * bindings/testbindings.mm:
+        (main):
+        * kjs/fast_malloc.cpp:
+        (KJS::kjs_fast_malloc):
+        (KJS::kjs_fast_calloc):
+        (KJS::kjs_fast_free):
+        (KJS::kjs_fast_realloc):
+        * kjs/fast_malloc.h:
+        * kjs/identifier.h:
+        * kjs/internal.cpp:
+        (InterpreterImp::InterpreterImp):
+        (InterpreterImp::clear):
+        (InterpreterImp::mark):
+        (InterpreterImp::checkSyntax):
+        (InterpreterImp::evaluate):
+        * kjs/internal.h:
+        (KJS::InterpreterImp::globalObject):
+        * kjs/interpreter.cpp:
+        (Interpreter::evaluate):
+        * kjs/interpreter.h:
+        (KJS::InterpreterLock::InterpreterLock):
+        (KJS::InterpreterLock::~InterpreterLock):
+        * kjs/nodes.h:
+        * kjs/protect.h:
+        (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_object.h:
+        * kjs/protected_values.cpp:
+        (KJS::ProtectedValues::getProtectCount):
+        (KJS::ProtectedValues::increaseProtectCount):
+        (KJS::ProtectedValues::decreaseProtectCount):
+        * kjs/string_object.cpp:
+        (StringObjectImp::StringObjectImp):
+        * kjs/testkjs.cpp:
+        (main):
+
 2005-09-16  Adele Peterson  <adele@apple.com>
 
         Change by Darin, reviewed by me and Maciej.
index 7b2a55f1f7609739d25c76bbad2be4d4f05a3b0d..9a92e0de8f37e63f3f411be32bf40d897ee12166 100644 (file)
@@ -25,8 +25,7 @@
 /* End PBXAggregateTarget section */
 
 /* Begin PBXBuildFile section */
-               65305EAF08A58DDE00F31E73 /* protected_object.h in Headers */ = {isa = PBXBuildFile; fileRef = 65305EAE08A58DDE00F31E73 /* protected_object.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               65305EB008A58E0900F31E73 /* protected_object.h in Headers */ = {isa = PBXBuildFile; fileRef = 65305EAE08A58DDE00F31E73 /* protected_object.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               652C107F08DA7B1E0020887D /* protected_reference.h in Headers */ = {isa = PBXBuildFile; fileRef = 652C107E08DA7B1E0020887D /* protected_reference.h */; };
                65621E6D089E859700760F35 /* property_slot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65621E6B089E859700760F35 /* property_slot.cpp */; };
                65621E6E089E859700760F35 /* property_slot.h in Headers */ = {isa = PBXBuildFile; fileRef = 65621E6C089E859700760F35 /* property_slot.h */; settings = {ATTRIBUTES = (Private, ); }; };
                65621E6F089E85D300760F35 /* property_slot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65621E6B089E859700760F35 /* property_slot.cpp */; };
                651BDC78080F10CC00F10856 /* fast_malloc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fast_malloc.h; sourceTree = "<group>"; };
                651F6412039D5B5F0078395C /* dtoa.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = dtoa.cpp; sourceTree = "<group>"; };
                651F6413039D5B5F0078395C /* dtoa.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dtoa.h; sourceTree = "<group>"; };
-               65305EAE08A58DDE00F31E73 /* protected_object.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = protected_object.h; sourceTree = "<group>"; };
+               652C107E08DA7B1E0020887D /* protected_reference.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = protected_reference.h; sourceTree = "<group>"; };
                6541720E039E08B90058BFEB /* dftables.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = dftables.c; path = pcre/dftables.c; sourceTree = "<group>"; };
                6541720F039E08B90058BFEB /* pcre.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = pcre.h; path = pcre/pcre.h; sourceTree = "<group>"; };
                65417217039E0B280058BFEB /* pcre-config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = "pcre-config.h"; path = "pcre/pcre-config.h"; sourceTree = "<group>"; };
                08FB77AEFE84172EC02AAC07 /* Classes */ = {
                        isa = PBXGroup;
                        children = (
-                               65305EAE08A58DDE00F31E73 /* protected_object.h */,
                                65EF2DF408BECC80000894BB /* shared_ptr.h */,
                                65621E6B089E859700760F35 /* property_slot.cpp */,
                                65621E6C089E859700760F35 /* property_slot.h */,
                                938772E5038BFE19008635CE /* array_instance.h */,
                                650B68D80639033F009D42DE /* protected_values.cpp */,
+                               652C107E08DA7B1E0020887D /* protected_reference.h */,
                                650B68D90639033F009D42DE /* protected_values.h */,
                                65AB004806261CBA0076DE63 /* interpreter_map.cpp */,
                                65AB004906261CBA0076DE63 /* interpreter_map.h */,
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               65305EAF08A58DDE00F31E73 /* protected_object.h in Headers */,
                                932F5B400822A1C700736975 /* array_object.h in Headers */,
                                932F5B420822A1C700736975 /* collector.h in Headers */,
                                932F5B430822A1C700736975 /* date_object.h in Headers */,
                                93E26C1308B1523D00F85226 /* ucptable.c in Headers */,
                                93E26CCF08B2921900F85226 /* softlinking.h in Headers */,
                                65EF2DF508BECC80000894BB /* shared_ptr.h in Headers */,
+                               652C107F08DA7B1E0020887D /* protected_reference.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               65305EB008A58E0900F31E73 /* protected_object.h in Headers */,
                                A85D81F8087B2822006A9172 /* array_object.h in Headers */,
                                A85D81F9087B2822006A9172 /* collector.h in Headers */,
                                A85D81FA087B2822006A9172 /* date_object.h in Headers */,
index e2438fe1be9440b195f5f69a5bc6c2151425f374..d502b092bcb261a1984e4d00071edc99e53ec803 100644 (file)
@@ -73,7 +73,7 @@ static NPClass _javascriptClass = {
 
 NPClass *NPScriptObjectClass = &_javascriptClass;
 
-static Identifier identiferFromNPIdentifier(const NPUTF8 *name)
+static Identifier identifierFromNPIdentifier(const NPUTF8 *name)
 {
     NPUTF16 *methodName;
     unsigned int UTF16Length;
@@ -148,38 +148,29 @@ bool _NPN_Invoke (NPP npp, NPObject *o, NPIdentifier methodName, const NPVariant
        else {
            // Lookup the function object.
            ExecState *exec = obj->executionContext->interpreter()->globalExec();
-           Interpreter::lock();
-           ValueImp *func = obj->imp->get (exec, identiferFromNPIdentifier(i->value.string));
-           Interpreter::unlock();
+           InterpreterLock lock;
+           ValueImp *func = obj->imp->get (exec, identifierFromNPIdentifier(i->value.string));
 
            if (func->isNull()) {
                NPN_InitializeVariantAsNull(result);
                return false;
-           }
-           else if (func->isUndefined()) {
+           } else if (func->isUndefined()) {
                NPN_InitializeVariantAsUndefined(result);
                return false;
-           }
-           else {
+           } else {
                // Call the function object.
                ObjectImp *funcImp = static_cast<ObjectImp*>(func);
                ObjectImp *thisObj = const_cast<ObjectImp*>(obj->imp);
                List argList = listFromVariantArgs(exec, args, argCount);
-               Interpreter::lock();
                ValueImp *resultV = funcImp->call (exec, thisObj, argList);
-               Interpreter::unlock();
 
                // Convert and return the result of the function call.
                convertValueToNPVariant(exec, resultV, result);
                return true;
            }
        }
-    }
-    else {
-        if (o->_class->invoke) {
-            return o->_class->invoke (o, methodName, args, argCount, result);
-        }
-    }
+    } else if (o->_class->invoke)
+        return o->_class->invoke (o, methodName, args, argCount, result);
     
     return true;
 }
@@ -195,7 +186,7 @@ bool _NPN_Evaluate (NPP npp, NPObject *o, NPString *s, NPVariant *variant)
         ExecState *exec = obj->executionContext->interpreter()->globalExec();
         ValueImp *result;
         
-        Interpreter::lock();
+        InterpreterLock lock;
         NPUTF16 *scriptString;
         unsigned int UTF16Length;
         convertNPStringToUTF16 (s, &scriptString, &UTF16Length);    // requires free() of returned memory.
@@ -211,8 +202,6 @@ bool _NPN_Evaluate (NPP npp, NPObject *o, NPString *s, NPVariant *variant)
         else
             result = Undefined();
             
-        Interpreter::unlock();
-        
         free ((void *)scriptString);
         
         convertValueToNPVariant(exec, result, variant);
@@ -234,15 +223,13 @@ bool _NPN_GetProperty (NPP npp, NPObject *o, NPIdentifier propertyName, NPVarian
 
         PrivateIdentifier *i = (PrivateIdentifier *)propertyName;
         
-        Interpreter::lock();
+        InterpreterLock lock;
         ValueImp *result;
         if (i->isString) {
-            result = obj->imp->get (exec, identiferFromNPIdentifier(i->value.string));
-        }
-        else {
+            result = obj->imp->get (exec, identifierFromNPIdentifier(i->value.string));
+        } else {
             result = obj->imp->get (exec, i->value.number);
         }
-        Interpreter::unlock();
 
         if (result->isNull()) {
             NPN_InitializeVariantAsNull(variant);
@@ -278,21 +265,17 @@ bool _NPN_SetProperty (NPP npp, NPObject *o, NPIdentifier propertyName, const NP
            return false;
 
         ExecState *exec = obj->executionContext->interpreter()->globalExec();
-        Interpreter::lock();
+        InterpreterLock lock;
         PrivateIdentifier *i = (PrivateIdentifier *)propertyName;
-        if (i->isString) {
-            obj->imp->put (exec, identiferFromNPIdentifier(i->value.string), convertNPVariantToValue(exec, variant));
-        }
-        else {
-            obj->imp->put (exec, i->value.number, convertNPVariantToValue(exec, variant));
-        }
-        Interpreter::unlock();
+        if (i->isString)
+            obj->imp->put(exec, identifierFromNPIdentifier(i->value.string), convertNPVariantToValue(exec, variant));
+        else
+            obj->imp->put(exec, i->value.number, convertNPVariantToValue(exec, variant));
         
         return true;
-    }
-    else if (o->_class->setProperty) {
+    } else if (o->_class->setProperty)
         return o->_class->setProperty (o, propertyName, variant);
-    }
+
     return false;
 }
 
@@ -308,7 +291,7 @@ bool _NPN_RemoveProperty (NPP npp, NPObject *o, NPIdentifier propertyName)
 
         PrivateIdentifier *i = (PrivateIdentifier *)propertyName;
         if (i->isString) {
-            if (!obj->imp->hasProperty (exec, identiferFromNPIdentifier(i->value.string))) {
+            if (!obj->imp->hasProperty (exec, identifierFromNPIdentifier(i->value.string))) {
                 return false;
             }
         }
@@ -318,14 +301,11 @@ bool _NPN_RemoveProperty (NPP npp, NPObject *o, NPIdentifier propertyName)
             }
         }
 
-        Interpreter::lock();
-        if (i->isString) {
-            obj->imp->deleteProperty (exec, identiferFromNPIdentifier(i->value.string));
-        }
-        else {
+        InterpreterLock lock;
+        if (i->isString)
+            obj->imp->deleteProperty (exec, identifierFromNPIdentifier(i->value.string));
+        else
             obj->imp->deleteProperty (exec, i->value.number);
-        }
-        Interpreter::unlock();
         
         return true;
     }
@@ -343,24 +323,14 @@ bool _NPN_HasProperty(NPP npp, NPObject *o, NPIdentifier propertyName)
         ExecState *exec = obj->executionContext->interpreter()->globalExec();
 
         PrivateIdentifier *i = (PrivateIdentifier *)propertyName;
-        // String identifier?
-        if (i->isString) {
-            ExecState *exec = obj->executionContext->interpreter()->globalExec();
-            Interpreter::lock();
-            bool result = obj->imp->hasProperty (exec, identiferFromNPIdentifier(i->value.string));
-            Interpreter::unlock();
-            return result;
-        }
+        InterpreterLock lock;
+
+        if (i->isString)
+            return obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string));
         
-        // Numeric identifer
-        Interpreter::lock();
-        bool result = obj->imp->hasProperty (exec, i->value.number);
-        Interpreter::unlock();
-        return result;
-    }
-    else if (o->_class->hasProperty) {
+        return obj->imp->hasProperty(exec, i->value.number);
+    } else if (o->_class->hasProperty)
         return o->_class->hasProperty (o, propertyName);
-    }
     
     return false;
 }
@@ -379,9 +349,9 @@ bool _NPN_HasMethod(NPP npp, NPObject *o, NPIdentifier methodName)
             
         // Lookup the function object.
         ExecState *exec = obj->executionContext->interpreter()->globalExec();
-        Interpreter::lock();
-        ValueImp *func = obj->imp->get (exec, identiferFromNPIdentifier(i->value.string));
-        Interpreter::unlock();
+
+        InterpreterLock lock;
+        ValueImp *func = obj->imp->get (exec, identifierFromNPIdentifier(i->value.string));
 
         if (func->isUndefined()) {
             return false;
@@ -402,8 +372,7 @@ void _NPN_SetException(NPObject *o, const NPUTF8 *message)
     if (o->_class == NPScriptObjectClass) {
         JavaScriptObject *obj = (JavaScriptObject *)o; 
         ExecState *exec = obj->executionContext->interpreter()->globalExec();
-        Interpreter::lock();
+        InterpreterLock lock;
         throwError(exec, GeneralError, message);
-        Interpreter::unlock();
     }
 }
index ea2b2c86820c7aeb8aa308ff84e898b1ef608bb2..cdfa2f0ad06eec43d8d956b97875f76d03d7407b 100644 (file)
@@ -170,11 +170,10 @@ jobject JSObject::call(jstring methodName, jobjectArray args) const
 
     // Lookup the function object.
     ExecState *exec = _root->interpreter()->globalExec();
-    Interpreter::lock();
+    InterpreterLock lock;
     
     Identifier identifier(JavaString(methodName).ustring());
     ValueImp *func = _imp->get (exec, identifier);
-    Interpreter::unlock();
     if (func->isUndefinedOrNull()) {
         // Maybe throw an exception here?
         return 0;
@@ -184,36 +183,29 @@ jobject JSObject::call(jstring methodName, jobjectArray args) const
     ObjectImp *funcImp = static_cast<ObjectImp*>(func);
     ObjectImp *thisObj = const_cast<ObjectImp*>(_imp);
     List argList = listFromJArray(args);
-    Interpreter::lock();
-    ValueImp *result = funcImp->call (exec, thisObj, argList);
-    Interpreter::unlock();
+    ValueImp *result = funcImp->call(exec, thisObj, argList);
 
-    // Convert and return the result of the function call.
-    return convertValueToJObject (result);
+    return convertValueToJObject(result);
 }
 
 jobject JSObject::eval(jstring script) const
 {
     JS_LOG ("script = %s\n", JavaString(script).UTF8String());
-
+    
     ObjectImp *thisObj = const_cast<ObjectImp*>(_imp);
     ValueImp *result;
     
-    Interpreter::lock();
-
+    InterpreterLock lock;
+    
     Completion completion = _root->interpreter()->evaluate(UString(), 0, JavaString(script).ustring(),thisObj);
     ComplType type = completion.complType();
     
     if (type == Normal) {
         result = completion.value();
-        if (!result) {
+        if (!result)
             result = Undefined();
-        }
-    }
-    else
+    } else
         result = Undefined();
-
-    Interpreter::unlock();
     
     return convertValueToJObject (result);
 }
@@ -223,21 +215,19 @@ jobject JSObject::getMember(jstring memberName) const
     JS_LOG ("(%p) memberName = %s\n", _imp, JavaString(memberName).UTF8String());
 
     ExecState *exec = _root->interpreter()->globalExec();
-
-    Interpreter::lock();
+    
+    InterpreterLock lock;
     ValueImp *result = _imp->get (exec, Identifier (JavaString(memberName).ustring()));
-    Interpreter::unlock();
 
-    return convertValueToJObject (result);
+    return convertValueToJObject(result);
 }
 
 void JSObject::setMember(jstring memberName, jobject value) const
 {
     JS_LOG ("memberName = %s, value = %p\n", JavaString(memberName).UTF8String(), value);
     ExecState *exec = _root->interpreter()->globalExec();
-    Interpreter::lock();
-    _imp->put (exec, Identifier (JavaString(memberName).ustring()), convertJObjectToValue(value));
-    Interpreter::unlock();
+    InterpreterLock lock;
+    _imp->put(exec, Identifier (JavaString(memberName).ustring()), convertJObjectToValue(value));
 }
 
 
@@ -246,9 +236,8 @@ void JSObject::removeMember(jstring memberName) const
     JS_LOG ("memberName = %s\n", JavaString(memberName).UTF8String());
 
     ExecState *exec = _root->interpreter()->globalExec();
-    Interpreter::lock();
-    _imp->deleteProperty (exec, Identifier (JavaString(memberName).ustring()));
-    Interpreter::unlock();
+    InterpreterLock lock;
+    _imp->deleteProperty(exec, Identifier (JavaString(memberName).ustring()));
 }
 
 
@@ -257,11 +246,11 @@ jobject JSObject::getSlot(jint index) const
     JS_LOG ("index = %ld\n", index);
 
     ExecState *exec = _root->interpreter()->globalExec();
-    Interpreter::lock();
+
+    InterpreterLock lock;
     ValueImp *result = _imp->get (exec, (unsigned)index);
-    Interpreter::unlock();
 
-    return convertValueToJObject (result);
+    return convertValueToJObject(result);
 }
 
 
@@ -270,25 +259,20 @@ void JSObject::setSlot(jint index, jobject value) const
     JS_LOG ("index = %ld, value = %p\n", index, value);
 
     ExecState *exec = _root->interpreter()->globalExec();
-    Interpreter::lock();
-    _imp->put (exec, (unsigned)index, convertJObjectToValue(value));
-    Interpreter::unlock();
+    InterpreterLock lock;
+    _imp->put(exec, (unsigned)index, convertJObjectToValue(value));
 }
 
 
 jstring JSObject::toString() const
 {
     JS_LOG ("\n");
-
-    Interpreter::lock();
+    
+    InterpreterLock lock;
     ObjectImp *thisObj = const_cast<ObjectImp*>(_imp);
     ExecState *exec = _root->interpreter()->globalExec();
     
-    jstring result = (jstring)convertValueToJValue (exec, thisObj, object_type, "java.lang.String").l;
-
-    Interpreter::unlock();
-    
-    return result;
+    return (jstring)convertValueToJValue (exec, thisObj, object_type, "java.lang.String").l;
 }
 
 void JSObject::finalize() const
@@ -437,9 +421,8 @@ ValueImp *JSObject::convertJObjectToValue (jobject theObject) const
         return imp;
     }
 
-    Interpreter::lock();
+    InterpreterLock lock;
     RuntimeObjectImp *newImp = new RuntimeObjectImp(new Bindings::JavaInstance (theObject, _root));
-    Interpreter::unlock();
 
     return newImp;
 }
index 65c4d8976d446d66f5bf691d75d05e27bfd199e0..49dec2e2e084d3906ac91bbf789475cc88e78cf9 100644 (file)
@@ -190,24 +190,22 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
     // Lookup the function object.
     ExecState *exec = [self _executionContext]->interpreter()->globalExec();
 
-    Interpreter::lock();
+    InterpreterLock lock;
     
     ValueImp *v = convertObjcValueToValue(exec, &name, ObjcObjectType);
     Identifier identifier(v->toString(exec));
     ValueImp *func = [self _imp]->get (exec, identifier);
-    Interpreter::unlock();
+
     if (!func || func->isUndefined()) {
         // Maybe throw an exception here?
         return 0;
     }
 
     // Call the function object.    
-    Interpreter::lock();
     ObjectImp *funcImp = static_cast<ObjectImp*>(func);
     ObjectImp *thisObj = const_cast<ObjectImp*>([self _imp]);
     List argList = listFromNSArray(exec, args);
     ValueImp *result = funcImp->call (exec, thisObj, argList);
-    Interpreter::unlock();
 
     if (exec->hadException()) {
         LOG_EXCEPTION (exec);
@@ -226,15 +224,14 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
 {
     if (![self _executionContext])
         return nil;
-
+    
     if (![self _isSafeScript])
        return nil;
-
+    
     ExecState *exec = [self _executionContext]->interpreter()->globalExec();
-
     ValueImp *result;
     
-    Interpreter::lock();
+    InterpreterLock lock;
     
     ValueImp *v = convertObjcValueToValue(exec, &script, ObjcObjectType);
     Completion completion = [self _executionContext]->interpreter()->evaluate(UString(), 0, v->toString(exec));
@@ -242,22 +239,18 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
     
     if (type == Normal) {
         result = completion.value();
-        if (!result) {
+        if (!result)
             result = Undefined();
-        }
-    }
-    else
+    } else
         result = Undefined();
-
-    Interpreter::unlock();
     
     if (exec->hadException()) {
         LOG_EXCEPTION (exec);
         result = Undefined();
     }
-
+    
     id resultObj = [WebScriptObject _convertValueToObjcValue:result originExecutionContext:[self _originExecutionContext] executionContext:[self _executionContext]];
-
+    
     _didExecute(self);
     
     return resultObj;
@@ -273,10 +266,9 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
 
     ExecState *exec = [self _executionContext]->interpreter()->globalExec();
 
-    Interpreter::lock();
+    InterpreterLock lock;
     ValueImp *v = convertObjcValueToValue(exec, &key, ObjcObjectType);
     [self _imp]->put (exec, Identifier (v->toString(exec)), (convertObjcValueToValue(exec, &value, ObjcObjectType)));
-    Interpreter::unlock();
 
     if (exec->hadException()) {
         LOG_EXCEPTION (exec);
@@ -295,10 +287,9 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
 
     ExecState *exec = [self _executionContext]->interpreter()->globalExec();
 
-    Interpreter::lock();
+    InterpreterLock lock;
     ValueImp *v = convertObjcValueToValue(exec, &key, ObjcObjectType);
     ValueImp *result = [self _imp]->get (exec, Identifier (v->toString(exec)));
-    Interpreter::unlock();
     
     if (exec->hadException()) {
         LOG_EXCEPTION (exec);
@@ -322,10 +313,9 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
 
     ExecState *exec = [self _executionContext]->interpreter()->globalExec();
 
-    Interpreter::lock();
+    InterpreterLock lock;
     ValueImp *v = convertObjcValueToValue(exec, &key, ObjcObjectType);
     [self _imp]->deleteProperty (exec, Identifier (v->toString(exec)));
-    Interpreter::unlock();
 
     if (exec->hadException()) {
         LOG_EXCEPTION (exec);
@@ -340,14 +330,12 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
         // This is a workaround for a gcc 3.3 internal compiler error.
        return @"Undefined";
 
-    Interpreter::lock();
+    InterpreterLock lock;
     ObjectImp *thisObj = const_cast<ObjectImp*>([self _imp]);
     ExecState *exec = [self _executionContext]->interpreter()->globalExec();
     
     id result = convertValueToObjcValue(exec, thisObj, ObjcObjectType).objectValue;
 
-    Interpreter::unlock();
-    
     id resultObj = [result description];
 
     _didExecute(self);
@@ -364,9 +352,8 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
        return nil;
 
     ExecState *exec = [self _executionContext]->interpreter()->globalExec();
-    Interpreter::lock();
+    InterpreterLock lock;
     ValueImp *result = [self _imp]->get (exec, (unsigned)index);
-    Interpreter::unlock();
 
     if (exec->hadException()) {
         LOG_EXCEPTION (exec);
@@ -389,9 +376,8 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
        return;
 
     ExecState *exec = [self _executionContext]->interpreter()->globalExec();
-    Interpreter::lock();
+    InterpreterLock lock;
     [self _imp]->put (exec, (unsigned)index, (convertObjcValueToValue(exec, &value, ObjcObjectType)));
-    Interpreter::unlock();
 
     if (exec->hadException()) {
         LOG_EXCEPTION (exec);
@@ -408,62 +394,46 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
 
 + (id)_convertValueToObjcValue:(ValueImp *)value originExecutionContext:(const RootObject *)originExecutionContext executionContext:(const RootObject *)executionContext
 {
-    id result = 0;
-
     // First see if we have a ObjC instance.
     if (value->isObject()) {
         ObjectImp *objectImp = static_cast<ObjectImp*>(value);
        Interpreter *intepreter = executionContext->interpreter();
        ExecState *exec = intepreter->globalExec();
-        Interpreter::lock();
+        InterpreterLock lock;
        
         if (objectImp->classInfo() != &RuntimeObjectImp::info) {
            ValueImp *runtimeObject = objectImp->get(exec, "__apple_runtime_object");
            if (runtimeObject && runtimeObject->isObject())
                objectImp = static_cast<RuntimeObjectImp*>(runtimeObject);
        }
-        
-        Interpreter::unlock();
 
         if (objectImp->classInfo() == &RuntimeObjectImp::info) {
             RuntimeObjectImp *imp = static_cast<RuntimeObjectImp *>(objectImp);
             ObjcInstance *instance = static_cast<ObjcInstance*>(imp->getInternalInstance());
             if (instance)
-                result = instance->getObject();
-        }
-        // Convert to a WebScriptObject
-        else {
-           result = (id)intepreter->createLanguageInstanceForValue (exec, Instance::ObjectiveCLanguage, value->toObject(exec), originExecutionContext, executionContext);
-        }
-    }
-    
-    // Convert JavaScript String value to NSString?
-    else if (value->isString()) {
+                return instance->getObject();
+        } else
+            // JS Object --> WebScriptObject
+           return (id)intepreter->createLanguageInstanceForValue (exec, Instance::ObjectiveCLanguage, value->toObject(exec), originExecutionContext, executionContext);
+    } else if (value->isString()) {
+        // JS String --> NSString
         StringImp *s = static_cast<StringImp*>(value);
         UString u = s->value();
         
         NSString *string = [NSString stringWithCharacters:(const unichar*)u.data() length:u.size()];
-        result = string;
-    }
-    
-    // Convert JavaScript Number value to NSNumber?
-    else if (value->isNumber()) {
-        result = [NSNumber numberWithDouble:value->getNumber()];
-    }
-    
-    else if (value->isBoolean()) {
-        BooleanImp *b = static_cast<BooleanImp*>(value);
-        result = [NSNumber numberWithBool:b->value()];
-    }
-    
-    // Convert JavaScript Undefined types to WebUndefined
-    else if (value->isUndefined()) {
-        result = [WebUndefined undefined];
-    }
+        return string;
+    } else if (value->isNumber())
+        // JS Number --> NSNumber
+        return [NSNumber numberWithDouble:value->getNumber()];
+    else if (value->isBoolean())
+        // JS Boolean --> NSNumber
+        return [NSNumber numberWithBool:static_cast<BooleanImp*>(value)->value()];
+    else if (value->isUndefined())
+        // JS Undefined --> WebUndefined
+        return [WebUndefined undefined];
     
     // Other types (UnspecifiedType and NullType) converted to 0.
-    
-    return result;
+    return 0;
 }
 
 @end
index 8628f4d832c96bf5b42aabcbd4e77a2e647700a8..5f565ca0c1b068f3ab90acec22a1ef03cff6c20c 100644 (file)
@@ -128,13 +128,10 @@ Instance *Instance::createBindingForLanguageInstance (BindingLanguage language,
 
 ObjectImp *Instance::createRuntimeObject (BindingLanguage language, void *nativeInstance, const RootObject *executionContext)
 {
-    Instance *interfaceObject = Instance::createBindingForLanguageInstance (language, (void *)nativeInstance, executionContext);
+    Instance *interfaceObject = Instance::createBindingForLanguageInstance(language, (void *)nativeInstance, executionContext);
     
-    Interpreter::lock();
-    ObjectImp *theObject(new RuntimeObjectImp(interfaceObject,true));
-    Interpreter::unlock();
-    
-    return theObject;
+    InterpreterLock lock;
+    return new RuntimeObjectImp(interfaceObject,true);
 }
 
 void *Instance::createLanguageInstanceForValue (ExecState *exec, BindingLanguage language, ObjectImp *value, const RootObject *origin, const RootObject *current)
index f23da13df259f4c29ef0a708aef6c1fe4f007a95..b1122a5f965f0b134a542a68d7399f84b9c95082 100644 (file)
@@ -29,6 +29,7 @@
 #include <JavaScriptCore/object.h>
 #include <JavaScriptCore/protect.h>
 #include <JavaScriptCore/jni_jsobject.h>
+#include <JavaScriptCore/protect.h>
 
 namespace KJS {
 
index ea35bfc920f56a475526cf2b5abf8fd59063bcc3..fd5c449e1dfacaaee0686a322f6fb280508489fa 100644 (file)
@@ -372,7 +372,7 @@ int main(int argc, char **argv)
     
     bool ret = true;
     {
-        Interpreter::lock();
+        InterpreterLock lock;
         
         // create interpreter w/ global object
         Object global(new GlobalImp());
@@ -414,8 +414,6 @@ int main(int argc, char **argv)
                 
         NPN_ReleaseObject ((NPObject *)myObject);
         
-        Interpreter::unlock();
-        
     } // end block, so that Interpreter and global get deleted
     
     return ret ? 0 : 3;
index 8a9d4b3a7794207afeaf26b5207c4b7ebcd3f529..bcf5c2e4657cdf7781a1d425e0642687a8de2006 100644 (file)
@@ -239,7 +239,7 @@ int main(int argc, char **argv)
     {
         NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
         
-        Interpreter::lock();
+        InterpreterLock lock;
         
         // create interpreter w/ global object
         Object global(new GlobalImp());
@@ -281,8 +281,6 @@ int main(int argc, char **argv)
         
         [myInterface release];
         
-        Interpreter::unlock();
-        
 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_3
         [pool release];
 #else
index df9fdc26c491e87fbf407d92af51180a270a846c..e9b4f0cfcc854685388b5d103472916453fcb2f8 100644 (file)
 #define MORECORE_CANNOT_TRIM 1
 #endif
 
+#include "internal.h"
+
 namespace KJS {
 
 #ifndef NDEBUG
@@ -244,21 +246,25 @@ namespace KJS {
 
 void *kjs_fast_malloc(size_t n)
 {
+    assert(InterpreterImp::lockCount() > 0);
     return malloc(n);
 }
 
 void *kjs_fast_calloc(size_t n_elements, size_t element_size)
 {
+    assert(InterpreterImp::lockCount() > 0);
     return calloc(n_elements, element_size);
 }
 
 void kjs_fast_free(void* p)
 {
+    assert(InterpreterImp::lockCount() > 0);
     free(p);
 }
 
 void *kjs_fast_realloc(void* p, size_t n)
 {
+    assert(InterpreterImp::lockCount() > 0);
     return realloc(p, n);
 }
 
@@ -5457,7 +5463,7 @@ static int cpuinfo (int whole, CHUNK_SIZE_T  *kernel, CHUNK_SIZE_T  *user) {
 
 #endif /* WIN32 */
 
-#endif
+#endif // NDEBUG
 
 }  /* end of namespace KJS */
 
index afd16eed9a583639debd3d386ce2bc1bf28af666..4b4bba430fc38c7f98b4c75dbcc2c127fd286aec 100644 (file)
@@ -114,6 +114,7 @@ namespace KJS {
         macro(arguments) \
         macro(callee) \
         macro(constructor) \
+        macro(fromCharCode) \
         macro(length) \
         macro(message) \
         macro(name) \
index c1873460678d85a03a3f2fed706f99dc4d256f84..453f40c6d21cbd8240926ccbafb972785ade4273 100644 (file)
@@ -1,4 +1,3 @@
-// -*- c-basic-offset: 2 -*-
 /*
  *  This file is part of the KDE libraries
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
@@ -451,7 +450,8 @@ InterpreterImp::InterpreterImp(Interpreter *interp, ObjectImp *glob)
 {
   // add this interpreter to the global chain
   // as a root set for garbage collection
-  lockInterpreter();
+  InterpreterLock lock;
+
   m_interpreter = interp;
   if (s_hook) {
     prev = s_hook;
@@ -474,7 +474,6 @@ InterpreterImp::InterpreterImp(Interpreter *interp, ObjectImp *glob)
   initGlobalObject();
 
   recursion = 0;
-  unlockInterpreter();
 }
 
 void InterpreterImp::lock()
@@ -622,9 +621,8 @@ void InterpreterImp::clear()
 {
   //fprintf(stderr,"InterpreterImp::clear\n");
   // remove from global chain (see init())
-#if APPLE_CHANGES
-  lockInterpreter();
-#endif
+  InterpreterLock lock;
+
   next->prev = prev;
   prev->next = next;
   s_hook = next;
@@ -635,10 +633,6 @@ void InterpreterImp::clear()
     globalClear();
   }
   InterpreterMap::removeInterpreterForGlobalObject(global);
-
-#if APPLE_CHANGES
-  unlockInterpreter();
-#endif
 }
 
 void InterpreterImp::mark()
@@ -648,10 +642,16 @@ void InterpreterImp::mark()
     m_interpreter->mark();
   if (_context)
     _context->mark();
+  if (global)
+      global->mark();
+  if (globExec._exception)
+      globExec._exception->mark();
 }
 
 bool InterpreterImp::checkSyntax(const UString &code)
 {
+  InterpreterLock lock;
+
   // Parser::parse() returns 0 in a syntax error occurs, so we just check for that
   SharedPtr<ProgramNode> progNode = Parser::parse(UString(), 0, code.data(),code.size(),0,0,0);
   return progNode;
@@ -659,20 +659,18 @@ bool InterpreterImp::checkSyntax(const UString &code)
 
 Completion InterpreterImp::evaluate(const UString &code, ValueImp *thisV, const UString &sourceURL, int startingLineNumber)
 {
-#if APPLE_CHANGES
-  lockInterpreter();
-#endif
+  InterpreterLock lock;
+
   // prevent against infinite recursion
   if (recursion >= 20) {
 #if APPLE_CHANGES
     Completion result = Completion(Throw, Error::create(&globExec, GeneralError, "Recursion too deep"));
-    unlockInterpreter();
     return result;
 #else
     return Completion(Throw,Error::create(&globExec, GeneralError, "Recursion too deep"));
 #endif
   }
-  
+
   // parse the source code
   int sid;
   int errLine;
@@ -683,22 +681,12 @@ Completion InterpreterImp::evaluate(const UString &code, ValueImp *thisV, const
   if (dbg) {
     bool cont = dbg->sourceParsed(&globExec, sid, sourceURL, code, errLine);
     if (!cont)
-#if APPLE_CHANGES
-      {
-       unlockInterpreter();
-       return Completion(Break);
-      }
-#else
       return Completion(Break);
-#endif
   }
   
   // no program node means a syntax error occurred
   if (!progNode) {
     ObjectImp *err = Error::create(&globExec, SyntaxError, errMsg, errLine, sid, &sourceURL);
-#if APPLE_CHANGES
-    unlockInterpreter();
-#endif
     return Completion(Throw,err);
   }
 
@@ -727,16 +715,13 @@ Completion InterpreterImp::evaluate(const UString &code, ValueImp *thisV, const
   else {
     // execute the code
     ContextImp ctx(globalObj, this, thisObj);
-    ExecState newExec(m_interpreter,&ctx);
+    ExecState newExec(m_interpreter, &ctx);
     progNode->processVarDecls(&newExec);
     res = progNode->execute(&newExec);
   }
 
   recursion--;
 
-#if APPLE_CHANGES
-  unlockInterpreter();
-#endif
   return res;
 }
 
index 6c88028425d34cb98ec34757a87f42fbbcfc505d..163b3e968480d1fa112de241be06b28510ac4354 100644 (file)
@@ -28,7 +28,7 @@
 #include "ustring.h"
 #include "value.h"
 #include "object.h"
-#include "protected_object.h"
+#include "protect.h"
 #include "types.h"
 #include "interpreter.h"
 #include "scope_chain.h"
@@ -215,39 +215,39 @@ namespace KJS {
   class SavedBuiltinsInternal {
     friend class InterpreterImp;
   private:
-    ProtectedObject b_Object;
-    ProtectedObject b_Function;
-    ProtectedObject b_Array;
-    ProtectedObject b_Boolean;
-    ProtectedObject b_String;
-    ProtectedObject b_Number;
-    ProtectedObject b_Date;
-    ProtectedObject b_RegExp;
-    ProtectedObject b_Error;
-
-    ProtectedObject b_ObjectPrototype;
-    ProtectedObject b_FunctionPrototype;
-    ProtectedObject b_ArrayPrototype;
-    ProtectedObject b_BooleanPrototype;
-    ProtectedObject b_StringPrototype;
-    ProtectedObject b_NumberPrototype;
-    ProtectedObject b_DatePrototype;
-    ProtectedObject b_RegExpPrototype;
-    ProtectedObject b_ErrorPrototype;
-
-    ProtectedObject b_evalError;
-    ProtectedObject b_rangeError;
-    ProtectedObject b_referenceError;
-    ProtectedObject b_syntaxError;
-    ProtectedObject b_typeError;
-    ProtectedObject b_uriError;
-
-    ProtectedObject b_evalErrorPrototype;
-    ProtectedObject b_rangeErrorPrototype;
-    ProtectedObject b_referenceErrorPrototype;
-    ProtectedObject b_syntaxErrorPrototype;
-    ProtectedObject b_typeErrorPrototype;
-    ProtectedObject b_uriErrorPrototype;
+    ProtectedPtr<ObjectImp> b_Object;
+    ProtectedPtr<ObjectImp> b_Function;
+    ProtectedPtr<ObjectImp> b_Array;
+    ProtectedPtr<ObjectImp> b_Boolean;
+    ProtectedPtr<ObjectImp> b_String;
+    ProtectedPtr<ObjectImp> b_Number;
+    ProtectedPtr<ObjectImp> b_Date;
+    ProtectedPtr<ObjectImp> b_RegExp;
+    ProtectedPtr<ObjectImp> b_Error;
+
+    ProtectedPtr<ObjectImp> b_ObjectPrototype;
+    ProtectedPtr<ObjectImp> b_FunctionPrototype;
+    ProtectedPtr<ObjectImp> b_ArrayPrototype;
+    ProtectedPtr<ObjectImp> b_BooleanPrototype;
+    ProtectedPtr<ObjectImp> b_StringPrototype;
+    ProtectedPtr<ObjectImp> b_NumberPrototype;
+    ProtectedPtr<ObjectImp> b_DatePrototype;
+    ProtectedPtr<ObjectImp> b_RegExpPrototype;
+    ProtectedPtr<ObjectImp> b_ErrorPrototype;
+
+    ProtectedPtr<ObjectImp> b_evalError;
+    ProtectedPtr<ObjectImp> b_rangeError;
+    ProtectedPtr<ObjectImp> b_referenceError;
+    ProtectedPtr<ObjectImp> b_syntaxError;
+    ProtectedPtr<ObjectImp> b_typeError;
+    ProtectedPtr<ObjectImp> b_uriError;
+
+    ProtectedPtr<ObjectImp> b_evalErrorPrototype;
+    ProtectedPtr<ObjectImp> b_rangeErrorPrototype;
+    ProtectedPtr<ObjectImp> b_referenceErrorPrototype;
+    ProtectedPtr<ObjectImp> b_syntaxErrorPrototype;
+    ProtectedPtr<ObjectImp> b_typeErrorPrototype;
+    ProtectedPtr<ObjectImp> b_uriErrorPrototype;
   };
 
   class InterpreterImp {
@@ -259,8 +259,8 @@ namespace KJS {
     InterpreterImp(Interpreter *interp, ObjectImp *glob);
     ~InterpreterImp();
 
-    ProtectedObject &globalObject() const { return const_cast<ProtectedObject &>(global); }
-    Interpreterinterpreter() const { return m_interpreter; }
+    ObjectImp *globalObject() { return global; }
+    Interpreter *interpreter() const { return m_interpreter; }
 
     void initGlobalObject();
     static void lock();
@@ -328,46 +328,46 @@ namespace KJS {
   private:
     void clear();
     Interpreter *m_interpreter;
-    ProtectedObject global;
+    ObjectImp *global;
     Debugger *dbg;
 
     // Built-in properties of the object prototype. These are accessible
     // from here even if they are replaced by js code (e.g. assigning to
     // Array.prototype)
 
-    ProtectedObject b_Object;
-    ProtectedObject b_Function;
-    ProtectedObject b_Array;
-    ProtectedObject b_Boolean;
-    ProtectedObject b_String;
-    ProtectedObject b_Number;
-    ProtectedObject b_Date;
-    ProtectedObject b_RegExp;
-    ProtectedObject b_Error;
-
-    ProtectedObject b_ObjectPrototype;
-    ProtectedObject b_FunctionPrototype;
-    ProtectedObject b_ArrayPrototype;
-    ProtectedObject b_BooleanPrototype;
-    ProtectedObject b_StringPrototype;
-    ProtectedObject b_NumberPrototype;
-    ProtectedObject b_DatePrototype;
-    ProtectedObject b_RegExpPrototype;
-    ProtectedObject b_ErrorPrototype;
-
-    ProtectedObject b_evalError;
-    ProtectedObject b_rangeError;
-    ProtectedObject b_referenceError;
-    ProtectedObject b_syntaxError;
-    ProtectedObject b_typeError;
-    ProtectedObject b_uriError;
-
-    ProtectedObject b_evalErrorPrototype;
-    ProtectedObject b_rangeErrorPrototype;
-    ProtectedObject b_referenceErrorPrototype;
-    ProtectedObject b_syntaxErrorPrototype;
-    ProtectedObject b_typeErrorPrototype;
-    ProtectedObject b_uriErrorPrototype;
+    ProtectedPtr<ObjectImp> b_Object;
+    ProtectedPtr<ObjectImp> b_Function;
+    ProtectedPtr<ObjectImp> b_Array;
+    ProtectedPtr<ObjectImp> b_Boolean;
+    ProtectedPtr<ObjectImp> b_String;
+    ProtectedPtr<ObjectImp> b_Number;
+    ProtectedPtr<ObjectImp> b_Date;
+    ProtectedPtr<ObjectImp> b_RegExp;
+    ProtectedPtr<ObjectImp> b_Error;
+
+    ProtectedPtr<ObjectImp> b_ObjectPrototype;
+    ProtectedPtr<ObjectImp> b_FunctionPrototype;
+    ProtectedPtr<ObjectImp> b_ArrayPrototype;
+    ProtectedPtr<ObjectImp> b_BooleanPrototype;
+    ProtectedPtr<ObjectImp> b_StringPrototype;
+    ProtectedPtr<ObjectImp> b_NumberPrototype;
+    ProtectedPtr<ObjectImp> b_DatePrototype;
+    ProtectedPtr<ObjectImp> b_RegExpPrototype;
+    ProtectedPtr<ObjectImp> b_ErrorPrototype;
+
+    ProtectedPtr<ObjectImp> b_evalError;
+    ProtectedPtr<ObjectImp> b_rangeError;
+    ProtectedPtr<ObjectImp> b_referenceError;
+    ProtectedPtr<ObjectImp> b_syntaxError;
+    ProtectedPtr<ObjectImp> b_typeError;
+    ProtectedPtr<ObjectImp> b_uriError;
+
+    ProtectedPtr<ObjectImp> b_evalErrorPrototype;
+    ProtectedPtr<ObjectImp> b_rangeErrorPrototype;
+    ProtectedPtr<ObjectImp> b_referenceErrorPrototype;
+    ProtectedPtr<ObjectImp> b_syntaxErrorPrototype;
+    ProtectedPtr<ObjectImp> b_typeErrorPrototype;
+    ProtectedPtr<ObjectImp> b_uriErrorPrototype;
 
     ExecState globExec;
     Interpreter::CompatMode m_compatMode;
index d8ba0a01e616d3aa55d799a70b5b557cf2d8a057..e91dc0b403fcac9f18713f60e8b6f3114b1948a0 100644 (file)
@@ -134,14 +134,13 @@ Completion Interpreter::evaluate(const UString &sourceURL, int startingLineNumbe
 
 #if APPLE_CHANGES
   if (shouldPrintExceptions() && comp.complType() == Throw) {
-    lock();
+    InterpreterLock lock;
     ExecState *exec = rep->globalExec();
     char *f = strdup(sourceURL.ascii());
     const char *message = comp.value()->toObject(exec)->toString(exec).ascii();
     printf("[%d] %s:%s\n", getpid(), f, message);
 
     free(f);
-    unlock();
   }
 #endif
 
index 3ae56ab21746e22ccf441d6009e92887d6028afe..20e4f520d1e91740c983a55392315792719ddedb 100644 (file)
@@ -1,4 +1,3 @@
-// -*- c-basic-offset: 2 -*-
 /*
  *  This file is part of the KDE libraries
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
@@ -483,6 +482,16 @@ namespace KJS {
     ValueImp *_exception;
   };
 
+    class InterpreterLock
+    {
+    public:
+        InterpreterLock() { Interpreter::lock(); }
+        ~InterpreterLock() { Interpreter::unlock(); }
+    private:
+        InterpreterLock(const InterpreterLock &);
+        InterpreterLock &operator =(const InterpreterLock &);
+    };
+
 } // namespace
 
 #endif // _KJS_INTERPRETER_H_
index 58f4d352cafd67e66a66454a48d7f16cc6391b40..7aac71fcf0a33ab0d9d76ec44f6e933d233a9617 100644 (file)
 
 namespace KJS {
 
+  class ProgramNode;
+  class PropertyNode;
+  class PropertyValueNode;
+  class Reference;
   class RegExp;
   class SourceElementsNode;
-  class ProgramNode;
   class SourceStream;
-  class PropertyValueNode;
-  class PropertyNode;
 
   enum Operator { OpEqual,
                  OpEqEq,
index 463db59b2a6e6eafa9a600e936574aeb487ec4e1..280e5f25a34d03f58dc2bc864ecb9869a1c878ba 100644 (file)
@@ -89,7 +89,7 @@ struct PropertyMapHashTable
 class SavedProperty {
 public:
     Identifier key;
-    ProtectedValue value;
+    ProtectedPtr<ValueImp> value;
     int attributes;
 };
 
index a220530ef4ce5a35cbbc8cc5b880a1f05e901d65..30897d6145763a0543f856b20c882f6fc562f6de 100644 (file)
 #include "reference.h"
 #include "value.h"
 #include "protected_values.h"
+#include "interpreter.h"
 
 namespace KJS {
 
     inline void gcProtect(ValueImp *val) 
-      
+    { 
        ProtectedValues::increaseProtectCount(val);
-      }
+    }
+
     inline void gcUnprotect(ValueImp *val)
-      
+    { 
        ProtectedValues::decreaseProtectCount(val);
-      }
+    }
 
     inline void gcProtectNullTolerant(ValueImp *val) 
-      {
+    {
        if (val) gcProtect(val);
-      }
+    }
 
     inline void gcUnprotectNullTolerant(ValueImp *val) 
-      {
+    {
        if (val) gcUnprotect(val);
-      }
+    }
     
-class ProtectedValue {
-public:
-    ProtectedValue() : m_value(0) { }
-    ProtectedValue(ValueImp *v) : m_value(v) { gcProtectNullTolerant(v); }
-    ProtectedValue(const ProtectedValue& v) : m_value(v.m_value) { gcProtectNullTolerant(m_value); }
-    ~ProtectedValue() { gcUnprotectNullTolerant(m_value); }
-    ProtectedValue& operator=(ValueImp *v)
+    // FIXME: Share more code with SharedPtr template? The only difference is the ref/deref operation.
+    template <class T> class ProtectedPtr {
+    public:
+        ProtectedPtr() : m_ptr(NULL) { }
+        ProtectedPtr(T *ptr);
+        ProtectedPtr(const ProtectedPtr &);
+        ~ProtectedPtr();
+
+        template <class U> ProtectedPtr(const ProtectedPtr<U> &);
+        
+        T *get() const { return m_ptr; }
+        operator T *() const { return m_ptr; }
+        T *operator->() const { return m_ptr; }
+        
+        bool operator!() const { return m_ptr == NULL; }
+        operator bool() const { return m_ptr != NULL; }
+        
+        ProtectedPtr &operator=(const ProtectedPtr &);
+        ProtectedPtr &operator=(T *);
+        
+    private:
+        T *m_ptr;
+        
+        operator int() const; // deliberately not implemented; helps prevent operator bool from converting to int accidentally
+    };
+
+    template <class T> ProtectedPtr<T>::ProtectedPtr(T *ptr)
+        : m_ptr(ptr)
+    {
+        if (ptr) {
+            InterpreterLock lock;
+            gcProtect(ptr);
+        }
+    }
+
+    template <class T> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr &o)
+        : m_ptr(o.get())
     {
-        gcProtectNullTolerant(v);
-        gcUnprotectNullTolerant(m_value);
-        m_value = v;
+        if (T *ptr = m_ptr) {
+            InterpreterLock lock;
+            gcProtect(ptr);
+        }
+    }
+
+    template <class T> ProtectedPtr<T>::~ProtectedPtr()
+    {
+        if (T *ptr = m_ptr) {
+            InterpreterLock lock;
+            gcUnprotect(ptr);
+        }
+    }
+
+    template <class T> template <class U> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr<U> &o)
+        : m_ptr(o.get())
+    {
+        if (T *ptr = m_ptr) {
+            InterpreterLock lock;
+            gcProtect(ptr);
+        }
+    }
+
+    template <class T> ProtectedPtr<T> &ProtectedPtr<T>::operator=(const ProtectedPtr<T> &o) 
+    {
+        InterpreterLock lock;
+        T *optr = o.m_ptr;
+        gcProtectNullTolerant(optr);
+        gcUnprotectNullTolerant(m_ptr);
+        m_ptr = optr;
+         return *this;
+     }
+
+    template <class T> inline ProtectedPtr<T> &ProtectedPtr<T>::operator=(T *optr)
+    {
+        InterpreterLock lock;
+        gcProtectNullTolerant(optr);
+        gcUnprotectNullTolerant(m_ptr);
+        m_ptr = optr;
         return *this;
     }
-    ProtectedValue& operator=(const ProtectedValue& v) { return *this = v.m_value; }
-    operator ValueImp *() const { return m_value; }
-    ValueImp *operator->() const { return m_value; }
-protected:
-    ValueImp *m_value;
-};
 
+    template <class T> inline bool operator==(const ProtectedPtr<T> &a, const ProtectedPtr<T> &b) { return a.get() == b.get(); }
+    template <class T> inline bool operator==(const ProtectedPtr<T> &a, const T *b) { return a.get() == b; }
+    template <class T> inline bool operator==(const T *a, const ProtectedPtr<T> &b) { return a == b.get(); }
+
+    template <class T> inline bool operator!=(const ProtectedPtr<T> &a, const ProtectedPtr<T> &b) { return a.get() != b.get(); }
+    template <class T> inline bool operator!=(const ProtectedPtr<T> &a, const T *b) { return a.get() != b; }
+    template <class T> inline bool operator!=(const T *a, const ProtectedPtr<T> &b) { return a != b.get(); }
 } // namespace
 
 #endif
diff --git a/JavaScriptCore/kjs/protected_object.h b/JavaScriptCore/kjs/protected_object.h
deleted file mode 100644 (file)
index fdb45ac..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *  This file is part of the KDE libraries
- *  Copyright (C) 2004 Apple Computer, Inc.
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef KJS_PROTECTED_OBJECT_H
-#define KJS_PROTECTED_OBJECT_H
-
-#include "protect.h"
-#include "object.h"
-#include "reference.h"
-
-namespace KJS {
-
-class ProtectedObject : private ProtectedValue {
-public:
-    ProtectedObject() { }
-    ProtectedObject(ObjectImp *v) : ProtectedValue(v) { }
-    ProtectedObject(const ProtectedObject& v) : ProtectedValue(v) { }
-    ProtectedObject& operator=(ObjectImp *v) { ProtectedValue::operator=(v); return *this; }
-    ProtectedObject& operator=(const ProtectedObject& v) { ProtectedValue::operator=(v); return *this; }
-    operator ValueImp *() const { return m_value; }
-    operator ObjectImp *() const { return static_cast<ObjectImp *>(m_value); }
-    ObjectImp *operator->() const { return static_cast<ObjectImp *>(m_value); }
-};
-
-    class ProtectedReference : public Reference {
-    public:
-      ProtectedReference(const Reference& r) : Reference(r) { gcProtectNullTolerant(r.base); };
-      ~ProtectedReference() { gcUnprotectNullTolerant(base);}
-      ProtectedReference& operator=(const Reference &r)
-       { 
-         ValueImp *old = base;
-         Reference::operator=(r); 
-         gcProtectNullTolerant(r.base);
-         gcUnprotectNullTolerant(old); 
-         return *this;
-       }
-    private:
-      ProtectedReference();
-      ProtectedReference(ObjectImp *b, const Identifier& p);
-      ProtectedReference(ObjectImp *b, unsigned p);
-      ProtectedReference(const Identifier& p);
-      ProtectedReference(unsigned p);
-    };
-
-} // namespace
-
-#endif
index c7ca6c9ef1cd507fe98c9cd58f1417f1be0109b7..bfc1d74f4e6bcac1c3bc77ece63e7a4dcfa614a0 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "pointer_hash.h"
 #include "simple_number.h"
+#include "internal.h"
 #include <stdint.h>
 #include "value.h"
 
@@ -38,6 +39,9 @@ int ProtectedValues::_keyCount;
 
 int ProtectedValues::getProtectCount(ValueImp *k)
 {
+    assert(k);
+    assert(InterpreterImp::lockCount() > 0);
+
     if (!_table)
        return 0;
 
@@ -65,6 +69,7 @@ int ProtectedValues::getProtectCount(ValueImp *k)
 void ProtectedValues::increaseProtectCount(ValueImp *k)
 {
     assert(k);
+    assert(InterpreterImp::lockCount() > 0);
 
     if (SimpleNumber::is(k))
       return;
@@ -114,6 +119,7 @@ inline void ProtectedValues::insert(AllocatedValueImp *k, int v)
 void ProtectedValues::decreaseProtectCount(ValueImp *k)
 {
     assert(k);
+    assert(InterpreterImp::lockCount() > 0);
 
     if (SimpleNumber::is(k))
       return;
index 6765614cd4969aa531dec7c4e020b04315dec5fd..ca0dec18791a66d88545a89657e2f6cac91754c7 100644 (file)
@@ -33,7 +33,6 @@ namespace KJS {
   class Reference {
     friend class ReferenceList;
     friend class ReferenceListIterator;
-    friend class ProtectedReference;
   public:
     Reference(ObjectImp *b, const Identifier& p);
     Reference(ObjectImp *b, unsigned p);
@@ -70,10 +69,12 @@ namespace KJS {
 
     ValueImp *baseIfMutable() const { return baseIsValue ? 0 : base; }
 
+  protected:
+    ValueImp *base;
+
   private:
     Reference() { }
 
-    ValueImp *base;
     unsigned propertyNameAsNumber;
     bool baseIsValue;
     bool propertyNameIsNumber;
index 6d0b276224d910664a26320c849014d7ef095bd1..94ff983388ff5319c05d98d3904a1643048a0f4a 100644 (file)
@@ -21,8 +21,7 @@
  */
 
 #include "reference_list.h"
-
-#include "protected_object.h"
+#include "protected_reference.h"
 
 namespace KJS {
   class ReferenceListNode {
index cea953bb5ff92327c41d9b99d9af1ce06dadb41e..a25824f52407acdd4468c9494756723276186c30 100644 (file)
@@ -710,8 +710,7 @@ StringObjectImp::StringObjectImp(ExecState *exec,
   // ECMA 15.5.3.1 String.prototype
   putDirect(prototypePropertyName, stringProto, DontEnum|DontDelete|ReadOnly);
 
-  static Identifier fromCharCode("fromCharCode");
-  putDirect(fromCharCode, new StringObjectFuncImp(exec,funcProto), DontEnum);
+  putDirect(fromCharCodePropertyName, new StringObjectFuncImp(exec, funcProto), DontEnum);
 
   // no. of arguments for constructor
   putDirect(lengthPropertyName, jsOne(), ReadOnly|DontDelete|DontEnum);
index 5c7106ed7229726ed54525cbb27b5a39acbcb258..d9bd4496d183372cda00e7e359cb21eac5dc2380 100644 (file)
@@ -101,7 +101,7 @@ int main(int argc, char **argv)
 
   bool ret = true;
   {
-    Interpreter::lock();
+    InterpreterLock lock;
 
     ObjectImp *global(new GlobalImp());
 
@@ -171,9 +171,7 @@ int main(int argc, char **argv)
 
       free(code);
     }
-
-    Interpreter::unlock();
-  } // end block, so that Interpreter and global get deleted
+  } // end block, so that interpreter gets deleted
 
   if (ret)
     fprintf(stderr, "OK.\n");