Changeset 34947 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Jul 2, 2008, 12:00:53 AM (17 years ago)
Author:
[email protected]
Message:

Reviewed by Darin.

Disable JSLock for per-thread contexts.

No change on SunSpider.

  • kjs/JSGlobalData.h:
  • kjs/JSGlobalData.cpp: (KJS::JSGlobalData::JSGlobalData): (KJS::JSGlobalData::sharedInstance): Added isSharedInstance as a better way to tell whether the instance is shared (legacy).
  • kjs/JSLock.cpp: (KJS::createJSLockCount): (KJS::JSLock::lockCount): (KJS::setLockCount): (KJS::JSLock::JSLock): (KJS::JSLock::lock): (KJS::JSLock::unlock): (KJS::JSLock::currentThreadIsHoldingLock): (KJS::JSLock::DropAllLocks::DropAllLocks): (KJS::JSLock::DropAllLocks::~DropAllLocks):
  • kjs/JSLock.h: (KJS::JSLock::JSLock): (KJS::JSLock::~JSLock): Made JSLock and JSLock::DropAllLocks constructors take a parameter to decide whether to actually lock a mutex, or only to increment recursion count. We cannot turn it into no-op if we want to keep existing assertions working. Made recursion count per-thread, now that locks may not lock.
  • API/JSBase.cpp: (JSEvaluateScript): Take JSLock after casting JSContextRef to ExecState* (which doesn't need locking in any case), so that a decision whether to actually lock can be made. (JSCheckScriptSyntax): Ditto. (JSGarbageCollect): Only lock while collecting the shared heap, not the per-thread one.
  • API/JSObjectRef.cpp: (JSClassCreate): Don't lock, as there is no reason to. (JSClassRetain): Ditto. (JSClassRelease): Ditto. (JSPropertyNameArrayRetain): Ditto. (JSPropertyNameArrayRelease): Only lock while deleting the array, as that may touch identifier table. (JSPropertyNameAccumulatorAddName): Adding a string also involves an identifier table lookup, and possibly modification.
  • API/JSStringRef.cpp: (JSStringCreateWithCharacters): (JSStringCreateWithUTF8CString): (JSStringRetain): (JSStringRelease): (JSStringGetUTF8CString): (JSStringIsEqual):
  • API/JSStringRefCF.cpp: (JSStringCreateWithCFString): JSStringRef operations other than releasing do not need locking.
  • VM/Machine.cpp: Don't include unused JSLock.h.
  • kjs/CollectorHeapIntrospector.cpp: (KJS::CollectorHeapIntrospector::statistics): Don't take the lock for real, as heap introspection pauses the process anyway. It seems that the existing code could cause deadlocks.
  • kjs/Shell.cpp: (functionGC): (main): (jscmain): The test tool uses a per-thread context, so no real locking is required.
  • kjs/collector.h: (KJS::Heap::setGCProtectNeedsLocking): Optionally protect m_protectedValues access with a per-heap mutex. This is only needed for WebCore Database code, which violates the "no data migration between threads" by using ProtectedPtr on a background thread. (KJS::Heap::isShared): Keep a shared flag here, as well.
  • kjs/protect.h: (KJS::::ProtectedPtr): (KJS::::~ProtectedPtr): (KJS::::operator): (KJS::operator==): (KJS::operator!=): ProtectedPtr is ony used from WebCore, so it doesn't need to take JSLock. An assertion in Heap::protect/unprotect guards agains possible future unlocked uses of ProtectedPtr in JSC.
  • kjs/collector.cpp: (KJS::Heap::Heap): Initialize m_isShared. (KJS::Heap::~Heap): No need to lock for real during destruction, but must keep assertions in sweep() working. (KJS::destroyRegisteredThread): Registered thread list is only accessed for shared heap, so locking is always needed here. (KJS::Heap::registerThread): Ditto. (KJS::Heap::markStackObjectsConservatively): Use m_isShared instead of comparing to a shared instance for a small speedup. (KJS::Heap::setGCProtectNeedsLocking): Create m_protectedValuesMutex. There is currently no way to undo this - and ideally, Database code will be fixed to lo longer require this quirk. (KJS::Heap::protect): Take m_protectedValuesMutex (if it exists) while accessing m_protectedValues. (KJS::Heap::unprotect): Ditto. (KJS::Heap::markProtectedObjects): Ditto. (KJS::Heap::protectedGlobalObjectCount): Ditto. (KJS::Heap::protectedObjectCount): Ditto. (KJS::Heap::protectedObjectTypeCounts): Ditto.
  • kjs/ustring.cpp:
  • kjs/ustring.h: Don't include JSLock.h, which is no longer used here. As a result, an explicit include had to be added to many files in JavaScriptGlue, WebCore and WebKit.
  • kjs/JSGlobalObject.cpp: (KJS::JSGlobalObject::init):
  • API/JSCallbackConstructor.cpp: (KJS::constructJSCallback):
  • API/JSCallbackFunction.cpp: (KJS::JSCallbackFunction::call):
  • API/JSCallbackObjectFunctions.h: (KJS::::init): (KJS::::getOwnPropertySlot): (KJS::::put): (KJS::::deleteProperty): (KJS::::construct): (KJS::::hasInstance): (KJS::::call): (KJS::::getPropertyNames): (KJS::::toNumber): (KJS::::toString): (KJS::::staticValueGetter): (KJS::::callbackGetter):
  • API/JSContextRef.cpp: (JSGlobalContextCreate): (JSGlobalContextRetain): (JSGlobalContextRelease):
  • API/JSValueRef.cpp: (JSValueIsEqual): (JSValueIsStrictEqual): (JSValueIsInstanceOfConstructor): (JSValueMakeNumber): (JSValueMakeString): (JSValueToNumber): (JSValueToStringCopy): (JSValueToObject): (JSValueProtect): (JSValueUnprotect):
  • JavaScriptCore.exp:
  • kjs/PropertyNameArray.h: (KJS::PropertyNameArray::globalData):
  • kjs/interpreter.cpp: (KJS::Interpreter::checkSyntax): (KJS::Interpreter::evaluate): Pass a parameter to JSLock/JSLock::DropAllLocks to decide whether the lock needs to be taken.
Location:
trunk/JavaScriptCore
Files:
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/API/JSBase.cpp

    r34659 r34947  
    4141JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef thisObject, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
    4242{
    43     JSLock lock;
    4443    ExecState* exec = toJS(ctx);
     44    JSLock lock(exec);
    4545    JSObject* jsThisObject = toJS(thisObject);
    4646    UString::Rep* scriptRep = toJS(script);
     
    6666bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
    6767{
    68     JSLock lock;
    69 
    7068    ExecState* exec = toJS(ctx);
     69    JSLock lock(exec);
    7170    UString::Rep* scriptRep = toJS(script);
    7271    UString::Rep* sourceURLRep = sourceURL ? toJS(sourceURL) : &UString::Rep::null;
     
    9089    // and it may actually be garbage for some clients (most likely, because of JSGarbageCollect being called after releasing the context).
    9190
    92     JSLock lock;
    93 
    9491    // FIXME: It would be good to avoid creating a JSGlobalData instance if it didn't exist for this thread yet.
    9592    Heap* heap = JSGlobalData::threadInstance().heap;
    9693    if (!heap->isBusy())
    9794        heap->collect();
     95
     96    JSLock lock(true);
    9897
    9998    // FIXME: Similarly, we shouldn't create a shared instance here.
  • trunk/JavaScriptCore/API/JSCallbackConstructor.cpp

    r34854 r34947  
    3030#include "APICast.h"
    3131#include <kjs/JSGlobalObject.h>
     32#include <kjs/JSLock.h>
    3233#include <kjs/ObjectPrototype.h>
    3334#include <wtf/Vector.h>
     
    6970            arguments[i] = toRef(args[i]);
    7071           
    71         JSLock::DropAllLocks dropAllLocks;
     72        JSLock::DropAllLocks dropAllLocks(exec);
    7273        return toJS(callback(ctx, constructorRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
    7374    }
  • trunk/JavaScriptCore/API/JSCallbackFunction.cpp

    r34754 r34947  
    3333#include "FunctionPrototype.h"
    3434#include <kjs/JSGlobalObject.h>
     35#include <kjs/JSLock.h>
    3536#include <wtf/Vector.h>
    3637
     
    6364        arguments[i] = toRef(args[i]);
    6465
    65     JSLock::DropAllLocks dropAllLocks;
     66    JSLock::DropAllLocks dropAllLocks(exec);
    6667    return toJS(static_cast<JSCallbackFunction*>(functionObject)->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
    6768}
  • trunk/JavaScriptCore/API/JSCallbackObjectFunctions.h

    r34754 r34947  
    3030#include "JSClassRef.h"
    3131#include "JSGlobalObject.h"
     32#include "JSLock.h"
    3233#include "JSObjectRef.h"
    3334#include "JSString.h"
     
    7273    // initialize from base to derived
    7374    for (int i = static_cast<int>(initRoutines.size()) - 1; i >= 0; i--) {
    74         JSLock::DropAllLocks dropAllLocks;
     75        JSLock::DropAllLocks dropAllLocks(exec);
    7576        JSObjectInitializeCallback initialize = initRoutines[i];
    7677        initialize(toRef(exec), toRef(this));
     
    110111        // optional optimization to bypass getProperty in cases when we only need to know if the property exists
    111112        if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
    112             JSLock::DropAllLocks dropAllLocks;
     113            JSLock::DropAllLocks dropAllLocks(exec);
    113114            if (hasProperty(ctx, thisRef, propertyNameRef)) {
    114115                slot.setCustom(this, callbackGetter);
     
    116117            }
    117118        } else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
    118             JSLock::DropAllLocks dropAllLocks;
     119            JSLock::DropAllLocks dropAllLocks(exec);
    119120            if (JSValueRef value = getProperty(ctx, thisRef, propertyNameRef, toRef(exec->exceptionSlot()))) {
    120121                // cache the value so we don't have to compute it again
     
    160161    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    161162        if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
    162             JSLock::DropAllLocks dropAllLocks;
     163            JSLock::DropAllLocks dropAllLocks(exec);
    163164            if (setProperty(ctx, thisRef, propertyNameRef, valueRef, toRef(exec->exceptionSlot())))
    164165                return;
     
    170171                    return;
    171172                if (JSObjectSetPropertyCallback setProperty = entry->setProperty) {
    172                     JSLock::DropAllLocks dropAllLocks;
     173                    JSLock::DropAllLocks dropAllLocks(exec);
    173174                    if (setProperty(ctx, thisRef, propertyNameRef, valueRef, toRef(exec->exceptionSlot())))
    174175                        return;
     
    206207    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    207208        if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) {
    208             JSLock::DropAllLocks dropAllLocks;
     209            JSLock::DropAllLocks dropAllLocks(exec);
    209210            if (deleteProperty(ctx, thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
    210211                return true;
     
    261262            for (int i = 0; i < argumentCount; i++)
    262263                arguments[i] = toRef(args[i]);
    263             JSLock::DropAllLocks dropAllLocks;
     264            JSLock::DropAllLocks dropAllLocks(exec);
    264265            return toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
    265266        }
     
    288289    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    289290        if (JSObjectHasInstanceCallback hasInstance = jsClass->hasInstance) {
    290             JSLock::DropAllLocks dropAllLocks;
     291            JSLock::DropAllLocks dropAllLocks(exec);
    291292            return hasInstance(execRef, thisRef, toRef(value), toRef(exec->exceptionSlot()));
    292293        }
     
    321322            for (int i = 0; i < argumentCount; i++)
    322323                arguments[i] = toRef(args[i]);
    323             JSLock::DropAllLocks dropAllLocks;
     324            JSLock::DropAllLocks dropAllLocks(exec);
    324325            return toJS(callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), toRef(exec->exceptionSlot())));
    325326        }
     
    338339    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass) {
    339340        if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) {
    340             JSLock::DropAllLocks dropAllLocks;
     341            JSLock::DropAllLocks dropAllLocks(exec);
    341342            getPropertyNames(execRef, thisRef, toRef(&propertyNames));
    342343        }
     
    381382    for (JSClassRef jsClass = m_class; jsClass; jsClass = jsClass->parentClass)
    382383        if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) {
    383             JSLock::DropAllLocks dropAllLocks;
     384            JSLock::DropAllLocks dropAllLocks(exec);
    384385            if (JSValueRef value = convertToType(ctx, thisRef, kJSTypeNumber, toRef(exec->exceptionSlot())))
    385386                return toJS(value)->getNumber();
     
    399400            JSValueRef value;
    400401            {
    401                 JSLock::DropAllLocks dropAllLocks;
     402                JSLock::DropAllLocks dropAllLocks(exec);
    402403                value = convertToType(ctx, thisRef, kJSTypeString, toRef(exec->exceptionSlot()));
    403404            }
     
    452453            if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep()))
    453454                if (JSObjectGetPropertyCallback getProperty = entry->getProperty) {
    454                     JSLock::DropAllLocks dropAllLocks;
     455                    JSLock::DropAllLocks dropAllLocks(exec);
    455456                    if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
    456457                        return toJS(value);
     
    497498    for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass)
    498499        if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
    499             JSLock::DropAllLocks dropAllLocks;
     500            JSLock::DropAllLocks dropAllLocks(exec);
    500501            if (JSValueRef value = getProperty(toRef(exec), thisRef, propertyNameRef, toRef(exec->exceptionSlot())))
    501502                return toJS(value);
  • trunk/JavaScriptCore/API/JSContextRef.cpp

    r34659 r34947  
    4242    initializeThreading();
    4343
    44     JSLock lock;
     44    JSLock lock(true);
    4545
    4646    if (!globalObjectClass) {
     
    6060JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx)
    6161{
    62     JSLock lock;
    6362    ExecState* exec = toJS(ctx);
     63    JSLock lock(exec);
    6464    gcProtect(exec->dynamicGlobalObject());
    6565    return ctx;
     
    6868void JSGlobalContextRelease(JSGlobalContextRef ctx)
    6969{
    70     JSLock lock;
    7170    ExecState* exec = toJS(ctx);
     71    JSLock lock(exec);
    7272    gcUnprotect(exec->dynamicGlobalObject());
    7373}
  • trunk/JavaScriptCore/API/JSObjectRef.cpp

    r34854 r34947  
    4848JSClassRef JSClassCreate(const JSClassDefinition* definition)
    4949{
    50     JSLock lock;
    5150    RefPtr<OpaqueJSClass> jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype)
    5251        ? OpaqueJSClass::createNoAutomaticPrototype(definition)
     
    5857JSClassRef JSClassRetain(JSClassRef jsClass)
    5958{
    60     JSLock lock;
    6159    jsClass->ref();
    6260    return jsClass;
     
    6563void JSClassRelease(JSClassRef jsClass)
    6664{
    67     JSLock lock;
    6865    jsClass->deref();
    6966}
     
    7168JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
    7269{
    73     JSLock lock;
    74     ExecState* exec = toJS(ctx);
     70    ExecState* exec = toJS(ctx);
     71    JSLock lock(exec);
    7572
    7673    if (!jsClass)
     
    8683JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
    8784{
    88     JSLock lock;
    89     ExecState* exec = toJS(ctx);
     85    ExecState* exec = toJS(ctx);
     86    JSLock lock(exec);
    9087    Identifier nameID = name ? Identifier(exec, toJS(name)) : Identifier(exec, "anonymous");
    9188   
     
    9592JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
    9693{
    97     JSLock lock;
    98     ExecState* exec = toJS(ctx);
     94    ExecState* exec = toJS(ctx);
     95    JSLock lock(exec);
    9996   
    10097    JSValue* jsPrototype = jsClass
     
    109106JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
    110107{
    111     JSLock lock;
    112    
    113     ExecState* exec = toJS(ctx);
     108    ExecState* exec = toJS(ctx);
     109    JSLock lock(exec);
     110
    114111    UString::Rep* bodyRep = toJS(body);
    115112    UString::Rep* sourceURLRep = sourceURL ? toJS(sourceURL) : &UString::Rep::null;
     
    148145bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
    149146{
    150     JSLock lock;
    151     ExecState* exec = toJS(ctx);
     147    ExecState* exec = toJS(ctx);
     148    JSLock lock(exec);
    152149    JSObject* jsObject = toJS(object);
    153150    UString::Rep* nameRep = toJS(propertyName);
     
    158155JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
    159156{
    160     JSLock lock;
    161     ExecState* exec = toJS(ctx);
     157    ExecState* exec = toJS(ctx);
     158    JSLock lock(exec);
    162159    JSObject* jsObject = toJS(object);
    163160    UString::Rep* nameRep = toJS(propertyName);
     
    174171void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
    175172{
    176     JSLock lock;
    177     ExecState* exec = toJS(ctx);
     173    ExecState* exec = toJS(ctx);
     174    JSLock lock(exec);
    178175    JSObject* jsObject = toJS(object);
    179176    Identifier name(exec, toJS(propertyName));
     
    194191JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
    195192{
    196     JSLock lock;
    197     ExecState* exec = toJS(ctx);
     193    ExecState* exec = toJS(ctx);
     194    JSLock lock(exec);
    198195    JSObject* jsObject = toJS(object);
    199196
     
    210207void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
    211208{
    212     JSLock lock;
    213     ExecState* exec = toJS(ctx);
     209    ExecState* exec = toJS(ctx);
     210    JSLock lock(exec);
    214211    JSObject* jsObject = toJS(object);
    215212    JSValue* jsValue = toJS(value);
     
    225222bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
    226223{
    227     JSLock lock;
    228     ExecState* exec = toJS(ctx);
     224    ExecState* exec = toJS(ctx);
     225    JSLock lock(exec);
    229226    JSObject* jsObject = toJS(object);
    230227    UString::Rep* nameRep = toJS(propertyName);
     
    274271JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
    275272{
    276     JSLock lock;
    277     ExecState* exec = toJS(ctx);
     273    ExecState* exec = toJS(ctx);
     274    JSLock lock(exec);
    278275    JSObject* jsObject = toJS(object);
    279276    JSObject* jsThisObject = toJS(thisObject);
     
    310307JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
    311308{
    312     JSLock lock;
    313     ExecState* exec = toJS(ctx);
     309    ExecState* exec = toJS(ctx);
     310    JSLock lock(exec);
    314311    JSObject* jsObject = toJS(object);
    315312
     
    344341JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object)
    345342{
    346     JSLock lock;
    347     JSObject* jsObject = toJS(object);
    348     ExecState* exec = toJS(ctx);
     343    JSObject* jsObject = toJS(object);
     344    ExecState* exec = toJS(ctx);
     345    JSLock lock(exec);
    349346   
    350347    JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(&exec->globalData());
     
    356353JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
    357354{
    358     JSLock lock;
    359355    ++array->refCount;
    360356    return array;
     
    363359void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
    364360{
    365     JSLock lock;
    366     if (--array->refCount == 0)
     361    if (--array->refCount == 0) {
     362        JSLock lock(array->array.globalData()->isSharedInstance);
    367363        delete array;
     364    }
    368365}
    369366
     
    380377void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
    381378{
    382     JSLock lock;
    383379    PropertyNameArray* propertyNames = toJS(array);
    384380    UString::Rep* rep = toJS(propertyName);
     381
     382    JSLock lock(propertyNames->globalData()->isSharedInstance);
    385383    propertyNames->add(rep);
    386384}
  • trunk/JavaScriptCore/API/JSStringRef.cpp

    r34581 r34947  
    4444JSStringRef JSStringCreateWithCharacters(const JSChar* chars, size_t numChars)
    4545{
    46     JSLock lock;
    4746    return toRef(UString(chars, static_cast<int>(numChars)).rep()->ref());
    4847}
     
    5049JSStringRef JSStringCreateWithUTF8CString(const char* string)
    5150{
    52     JSLock lock;
    53 
    5451    RefPtr<UString::Rep> result = UString::Rep::createFromUTF8(string);
    5552    if (result.get() == &UString::Rep::null)
     
    6158JSStringRef JSStringRetain(JSStringRef string)
    6259{
    63     JSLock lock;
    6460    UString::Rep* rep = toJS(string);
    6561    return toRef(rep->ref());
     
    6864void JSStringRelease(JSStringRef string)
    6965{
    70     JSLock lock;
    7166    UString::Rep* rep = toJS(string);
    72     rep->deref();
     67    bool needsLocking = rep->identifierTable;
     68    if (needsLocking) {
     69        // It is wasteful to take the lock for per-thread contexts, but we don't have a good way
     70        // to determine what the context is.
     71        JSLock lock(true);
     72        rep->deref();
     73    } else
     74        rep->deref();
    7375}
    7476
     
    9597size_t JSStringGetUTF8CString(JSStringRef string, char* buffer, size_t bufferSize)
    9698{
    97     JSLock lock;
    9899    UString::Rep* rep = toJS(string);
    99100    CString cString = UString(rep).UTF8String();
     
    106107bool JSStringIsEqual(JSStringRef a, JSStringRef b)
    107108{
    108     JSLock lock;
    109 
    110109    UString::Rep* aRep = toJS(a);
    111110    UString::Rep* bRep = toJS(b);
  • trunk/JavaScriptCore/API/JSStringRefCF.cpp

    r34581 r34947  
    3838JSStringRef JSStringCreateWithCFString(CFStringRef string)
    3939{
    40     JSLock lock;
    4140    CFIndex length = CFStringGetLength(string);
    4241    UString::Rep* rep;
  • trunk/JavaScriptCore/API/JSValueRef.cpp

    r34659 r34947  
    119119bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception)
    120120{
    121     JSLock lock;
    122     ExecState* exec = toJS(ctx);
     121    ExecState* exec = toJS(ctx);
     122    JSLock lock(exec);
     123
    123124    JSValue* jsA = toJS(a);
    124125    JSValue* jsB = toJS(b);
     
    133134}
    134135
    135 bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b)
    136 {
    137     UNUSED_PARAM(ctx);
    138 
    139     JSLock lock;
     136bool JSValueIsStrictEqual(JSContextRef, JSValueRef a, JSValueRef b)
     137{
    140138    JSValue* jsA = toJS(a);
    141139    JSValue* jsB = toJS(b);
     
    147145bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception)
    148146{
    149     JSLock lock;
    150     ExecState* exec = toJS(ctx);
     147    ExecState* exec = toJS(ctx);
     148    JSLock lock(exec);
     149
    151150    JSValue* jsValue = toJS(value);
    152151    JSObject* jsConstructor = toJS(constructor);
     
    179178JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
    180179{
    181     JSLock lock;
    182     return toRef(jsNumber(toJS(ctx), value));
     180    ExecState* exec = toJS(ctx);
     181    JSLock lock(exec);
     182
     183    return toRef(jsNumber(exec, value));
    183184}
    184185
    185186JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
    186187{
    187     JSLock lock;
     188    ExecState* exec = toJS(ctx);
     189    JSLock lock(exec);
     190
    188191    UString::Rep* rep = toJS(string);
    189     return toRef(jsString(toJS(ctx), UString(rep)));
     192    return toRef(jsString(exec, UString(rep)));
    190193}
    191194
     
    199202double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
    200203{
    201     JSLock lock;
    202     JSValue* jsValue = toJS(value);
    203     ExecState* exec = toJS(ctx);
     204    ExecState* exec = toJS(ctx);
     205    JSLock lock(exec);
     206
     207    JSValue* jsValue = toJS(value);
    204208
    205209    double number = jsValue->toNumber(exec);
     
    215219JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
    216220{
    217     JSLock lock;
    218     JSValue* jsValue = toJS(value);
    219     ExecState* exec = toJS(ctx);
     221    ExecState* exec = toJS(ctx);
     222    JSLock lock(exec);
     223
     224    JSValue* jsValue = toJS(value);
    220225   
    221226    JSStringRef stringRef = toRef(jsValue->toString(exec).rep()->ref());
     
    231236JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
    232237{
    233     JSLock lock;
    234     ExecState* exec = toJS(ctx);
     238    ExecState* exec = toJS(ctx);
     239    JSLock lock(exec);
     240
    235241    JSValue* jsValue = toJS(value);
    236242   
     
    245251}   
    246252
    247 void JSValueProtect(JSContextRef, JSValueRef value)
    248 {
    249     JSLock lock;
     253void JSValueProtect(JSContextRef ctx, JSValueRef value)
     254{
     255    ExecState* exec = toJS(ctx);
     256    JSLock lock(exec);
     257
    250258    JSValue* jsValue = toJS(value);
    251259    gcProtect(jsValue);
    252260}
    253261
    254 void JSValueUnprotect(JSContextRef, JSValueRef value)
    255 {
    256     JSLock lock;
     262void JSValueUnprotect(JSContextRef ctx, JSValueRef value)
     263{
     264    ExecState* exec = toJS(ctx);
     265    JSLock lock(exec);
     266
    257267    JSValue* jsValue = toJS(value);
    258268    gcUnprotect(jsValue);
  • trunk/JavaScriptCore/ChangeLog

    r34946 r34947  
     12008-06-30  Alexey Proskuryakov  <[email protected]>
     2
     3        Reviewed by Darin.
     4
     5        Disable JSLock for per-thread contexts.
     6
     7        No change on SunSpider.
     8
     9        * kjs/JSGlobalData.h:
     10        * kjs/JSGlobalData.cpp:
     11        (KJS::JSGlobalData::JSGlobalData):
     12        (KJS::JSGlobalData::sharedInstance):
     13        Added isSharedInstance as a better way to tell whether the instance is shared (legacy).
     14
     15        * kjs/JSLock.cpp:
     16        (KJS::createJSLockCount):
     17        (KJS::JSLock::lockCount):
     18        (KJS::setLockCount):
     19        (KJS::JSLock::JSLock):
     20        (KJS::JSLock::lock):
     21        (KJS::JSLock::unlock):
     22        (KJS::JSLock::currentThreadIsHoldingLock):
     23        (KJS::JSLock::DropAllLocks::DropAllLocks):
     24        (KJS::JSLock::DropAllLocks::~DropAllLocks):
     25        * kjs/JSLock.h:
     26        (KJS::JSLock::JSLock):
     27        (KJS::JSLock::~JSLock):
     28        Made JSLock and JSLock::DropAllLocks constructors take a parameter to decide whether to
     29        actually lock a mutex, or only to increment recursion count. We cannot turn it into no-op
     30        if we want to keep existing assertions working.
     31        Made recursion count per-thread, now that locks may not lock.
     32
     33        * API/JSBase.cpp:
     34        (JSEvaluateScript): Take JSLock after casting JSContextRef to ExecState* (which doesn't need
     35        locking in any case), so that a decision whether to actually lock can be made.
     36        (JSCheckScriptSyntax): Ditto.
     37        (JSGarbageCollect): Only lock while collecting the shared heap, not the per-thread one.
     38
     39        * API/JSObjectRef.cpp:
     40        (JSClassCreate): Don't lock, as there is no reason to.
     41        (JSClassRetain): Ditto.
     42        (JSClassRelease): Ditto.
     43        (JSPropertyNameArrayRetain): Ditto.
     44        (JSPropertyNameArrayRelease): Only lock while deleting the array, as that may touch
     45        identifier table.
     46        (JSPropertyNameAccumulatorAddName): Adding a string also involves an identifier table
     47        lookup, and possibly modification.
     48
     49        * API/JSStringRef.cpp:
     50        (JSStringCreateWithCharacters):
     51        (JSStringCreateWithUTF8CString):
     52        (JSStringRetain):
     53        (JSStringRelease):
     54        (JSStringGetUTF8CString):
     55        (JSStringIsEqual):
     56        * API/JSStringRefCF.cpp:
     57        (JSStringCreateWithCFString):
     58        JSStringRef operations other than releasing do not need locking.
     59
     60        * VM/Machine.cpp: Don't include unused JSLock.h.
     61
     62        * kjs/CollectorHeapIntrospector.cpp: (KJS::CollectorHeapIntrospector::statistics):
     63        Don't take the lock for real, as heap introspection pauses the process anyway. It seems that
     64        the existing code could cause deadlocks.
     65
     66        * kjs/Shell.cpp:
     67        (functionGC):
     68        (main):
     69        (jscmain):
     70        The test tool uses a per-thread context, so no real locking is required.
     71
     72        * kjs/collector.h:
     73        (KJS::Heap::setGCProtectNeedsLocking): Optionally protect m_protectedValues access with a
     74        per-heap mutex. This is only needed for WebCore Database code, which violates the "no data
     75        migration between threads" by using ProtectedPtr on a background thread.
     76        (KJS::Heap::isShared): Keep a shared flag here, as well.
     77
     78        * kjs/protect.h:
     79        (KJS::::ProtectedPtr):
     80        (KJS::::~ProtectedPtr):
     81        (KJS::::operator):
     82        (KJS::operator==):
     83        (KJS::operator!=):
     84        ProtectedPtr is ony used from WebCore, so it doesn't need to take JSLock. An assertion in
     85        Heap::protect/unprotect guards agains possible future unlocked uses of ProtectedPtr in JSC.
     86
     87        * kjs/collector.cpp:
     88        (KJS::Heap::Heap): Initialize m_isShared.
     89        (KJS::Heap::~Heap): No need to lock for real during destruction, but must keep assertions
     90        in sweep() working.
     91        (KJS::destroyRegisteredThread): Registered thread list is only accessed for shared heap,
     92        so locking is always needed here.
     93        (KJS::Heap::registerThread): Ditto.
     94        (KJS::Heap::markStackObjectsConservatively): Use m_isShared instead of comparing to a shared
     95        instance for a small speedup.
     96        (KJS::Heap::setGCProtectNeedsLocking): Create m_protectedValuesMutex. There is currently no
     97        way to undo this - and ideally, Database code will be fixed to lo longer require this quirk.
     98        (KJS::Heap::protect): Take m_protectedValuesMutex (if it exists) while accessing
     99        m_protectedValues.
     100        (KJS::Heap::unprotect): Ditto.
     101        (KJS::Heap::markProtectedObjects): Ditto.
     102        (KJS::Heap::protectedGlobalObjectCount): Ditto.
     103        (KJS::Heap::protectedObjectCount): Ditto.
     104        (KJS::Heap::protectedObjectTypeCounts): Ditto.
     105
     106        * kjs/ustring.cpp:
     107        * kjs/ustring.h:
     108        Don't include JSLock.h, which is no longer used here. As a result, an explicit include had
     109        to be added to many files in JavaScriptGlue, WebCore and WebKit.
     110
     111        * kjs/JSGlobalObject.cpp:
     112        (KJS::JSGlobalObject::init):
     113        * API/JSCallbackConstructor.cpp:
     114        (KJS::constructJSCallback):
     115        * API/JSCallbackFunction.cpp:
     116        (KJS::JSCallbackFunction::call):
     117        * API/JSCallbackObjectFunctions.h:
     118        (KJS::::init):
     119        (KJS::::getOwnPropertySlot):
     120        (KJS::::put):
     121        (KJS::::deleteProperty):
     122        (KJS::::construct):
     123        (KJS::::hasInstance):
     124        (KJS::::call):
     125        (KJS::::getPropertyNames):
     126        (KJS::::toNumber):
     127        (KJS::::toString):
     128        (KJS::::staticValueGetter):
     129        (KJS::::callbackGetter):
     130        * API/JSContextRef.cpp:
     131        (JSGlobalContextCreate):
     132        (JSGlobalContextRetain):
     133        (JSGlobalContextRelease):
     134        * API/JSValueRef.cpp:
     135        (JSValueIsEqual):
     136        (JSValueIsStrictEqual):
     137        (JSValueIsInstanceOfConstructor):
     138        (JSValueMakeNumber):
     139        (JSValueMakeString):
     140        (JSValueToNumber):
     141        (JSValueToStringCopy):
     142        (JSValueToObject):
     143        (JSValueProtect):
     144        (JSValueUnprotect):
     145        * JavaScriptCore.exp:
     146        * kjs/PropertyNameArray.h:
     147        (KJS::PropertyNameArray::globalData):
     148        * kjs/interpreter.cpp:
     149        (KJS::Interpreter::checkSyntax):
     150        (KJS::Interpreter::evaluate):
     151        Pass a parameter to JSLock/JSLock::DropAllLocks to decide whether the lock needs to be taken.
     152
    11532008-07-01  Alexey Proskuryakov  <[email protected]>
    2154
     
    306458        (WTF::): Updated HashTraits for HashTable change.
    307459
    308 2008-06-30  Alexey Proskuryakov  <[email protected]>
     4602008-07-01  Alexey Proskuryakov  <[email protected]>
    309461
    310462        Reviewed by Cameron Zwarich.
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r34933 r34947  
    148148__ZN3KJS4Heap17globalObjectCountEv
    149149__ZN3KJS4Heap20protectedObjectCountEv
     150__ZN3KJS4Heap24setGCProtectNeedsLockingEv
    150151__ZN3KJS4Heap25protectedObjectTypeCountsEv
    151152__ZN3KJS4Heap26protectedGlobalObjectCountEv
     
    170171__ZN3KJS6JSCell9getObjectEv
    171172__ZN3KJS6JSCellnwEmPNS_9ExecStateE
    172 __ZN3KJS6JSLock12DropAllLocksC1Ev
     173__ZN3KJS6JSLock12DropAllLocksC1Eb
     174__ZN3KJS6JSLock12DropAllLocksC1EPNS_9ExecStateE
    173175__ZN3KJS6JSLock12DropAllLocksD1Ev
    174176__ZN3KJS6JSLock14registerThreadEv
    175 __ZN3KJS6JSLock4lockEv
    176 __ZN3KJS6JSLock6unlockEv
     177__ZN3KJS6JSLock4lockEb
     178__ZN3KJS6JSLock6unlockEb
    177179__ZN3KJS6JSLock9lockCountEv
     180__ZN3KJS6JSLockC1EPNS_9ExecStateE
    178181__ZN3KJS6Parser5parseEPNS_9ExecStateERKNS_7UStringEiN3WTF10PassRefPtrINS_14SourceProviderEEEPiSA_PS3_
    179182__ZN3KJS6strtodEPKcPPc
  • trunk/JavaScriptCore/VM/Machine.cpp

    r34945 r34947  
    3838#include "JSArray.h"
    3939#include "JSFunction.h"
    40 #include "JSLock.h"
    4140#include "JSPropertyNameIterator.h"
    4241#include "JSString.h"
  • trunk/JavaScriptCore/kjs/CollectorHeapIntrospector.cpp

    r34824 r34947  
    9696void CollectorHeapIntrospector::statistics(malloc_zone_t* zone, malloc_statistics_t* stats)
    9797{
    98     JSLock lock;
     98    JSLock lock(false);
    9999    CollectorHeapIntrospector* introspector = reinterpret_cast<CollectorHeapIntrospector*>(zone);
    100100    CollectorHeap* primaryHeap = introspector->m_primaryHeap;
  • trunk/JavaScriptCore/kjs/JSGlobalData.cpp

    r34907 r34947  
    5757
    5858
    59 JSGlobalData::JSGlobalData()
     59JSGlobalData::JSGlobalData(bool isShared)
    6060    : machine(new Machine)
    61     , heap(new Heap)
     61    , heap(new Heap(isShared))
    6262#if USE(MULTIPLE_THREADS)
    6363    , arrayTable(new HashTable(KJS::arrayTable))
     
    8484    , parser(new Parser)
    8585    , head(0)
     86    , isSharedInstance(isShared)
    8687{
    8788}
     
    133134{
    134135#if USE(MULTIPLE_THREADS)
    135     AtomicallyInitializedStatic(JSGlobalData, sharedInstance);
    136 #else
    137     static JSGlobalData sharedInstance;
     136    MutexLocker locker(*atomicallyInitializedStaticMutex);
    138137#endif
    139     return sharedInstance;
     138    static JSGlobalData* sharedInstance;
     139    if (!sharedInstance)
     140        sharedInstance = new JSGlobalData(true);
     141    return *sharedInstance;
    140142}
    141143
  • trunk/JavaScriptCore/kjs/JSGlobalData.h

    r34838 r34947  
    8282        JSGlobalObject* head;
    8383
     84        bool isSharedInstance;
     85
    8486    private:
    8587        friend class WTF::ThreadSpecific<JSGlobalData>;
    8688
    87         JSGlobalData();
     89        JSGlobalData(bool isShared = false);
    8890        ~JSGlobalData();
    8991    };
  • trunk/JavaScriptCore/kjs/JSGlobalObject.cpp

    r34946 r34947  
    102102    ASSERT(JSLock::currentThreadIsHoldingLock());
    103103
    104     d()->globalData = (Heap::heap(this) == JSGlobalData::sharedInstance().heap) ? &JSGlobalData::sharedInstance() : &JSGlobalData::threadInstance();
     104    d()->globalData = Heap::heap(this)->isShared() ? &JSGlobalData::sharedInstance() : &JSGlobalData::threadInstance();
    105105
    106106    if (JSGlobalObject*& headObject = head()) {
  • trunk/JavaScriptCore/kjs/JSLock.cpp

    r34659 r34947  
    2525
    2626#include "collector.h"
     27#include "ExecState.h"
     28
    2729#if USE(MULTIPLE_THREADS)
    2830#include <pthread.h>
     
    3638static pthread_mutex_t JSMutex = PTHREAD_MUTEX_INITIALIZER;
    3739
    38 // Thread-specific key that tells whether a thread holds the JSMutex.
    39 pthread_key_t didLockJSMutex;
     40// Thread-specific key that tells whether a thread holds the JSMutex, and how many times it was taken recursively.
     41pthread_key_t JSLockCount;
     42
     43static void createJSLockCount()
     44{
     45    pthread_key_create(&JSLockCount, 0);
     46}
     47
     48pthread_once_t createJSLockCountOnce = PTHREAD_ONCE_INIT;
    4049
    4150// Lock nesting count.
    42 static int JSLockCount;
     51int JSLock::lockCount()
     52{
     53    pthread_once(&createJSLockCountOnce, createJSLockCount);
    4354
    44 static void createDidLockJSMutex()
     55    return reinterpret_cast<int>(pthread_getspecific(JSLockCount));
     56}
     57
     58static void setLockCount(int count)
    4559{
    46     pthread_key_create(&didLockJSMutex, 0);
     60    pthread_setspecific(JSLockCount, reinterpret_cast<void*>(count));
    4761}
    48 pthread_once_t createDidLockJSMutexOnce = PTHREAD_ONCE_INIT;
    4962
    50 void JSLock::lock()
     63JSLock::JSLock(ExecState* exec)
     64    : m_lockingForReal(exec->globalData().isSharedInstance)
    5165{
    52     pthread_once(&createDidLockJSMutexOnce, createDidLockJSMutex);
     66    lock(m_lockingForReal);
     67    if (m_lockingForReal)
     68        registerThread();
     69}
    5370
    54     if (!pthread_getspecific(didLockJSMutex)) {
     71void JSLock::lock(bool lockForReal)
     72{
     73#ifdef NDEBUG
     74    // For per-thread contexts, locking is a debug-only feature.
     75    if (!lockForReal)
     76        return;
     77#endif
     78
     79    pthread_once(&createJSLockCountOnce, createJSLockCount);
     80
     81    int currentLockCount = lockCount();
     82    if (!currentLockCount && lockForReal) {
    5583        int result;
    5684        result = pthread_mutex_lock(&JSMutex);
    5785        ASSERT(!result);
    58         pthread_setspecific(didLockJSMutex, &didLockJSMutex);
    5986    }
    60     ++JSLockCount;
     87    setLockCount(currentLockCount + 1);
    6188}
    6289
    63 void JSLock::unlock()
     90void JSLock::unlock(bool lockForReal)
    6491{
    65     ASSERT(JSLockCount);
    66     ASSERT(!!pthread_getspecific(didLockJSMutex));
     92    ASSERT(lockCount());
    6793
    68     --JSLockCount;
    69     if (!JSLockCount) {
    70         pthread_setspecific(didLockJSMutex, 0);
     94#ifdef NDEBUG
     95    // For per-thread contexts, locking is a debug-only feature.
     96    if (!lockForReal)
     97        return;
     98#endif
     99
     100    int newLockCount = lockCount() - 1;
     101    setLockCount(newLockCount);
     102    if (!newLockCount && lockForReal) {
    71103        int result;
    72104        result = pthread_mutex_unlock(&JSMutex);
     
    75107}
    76108
     109void JSLock::lock(ExecState* exec)
     110{
     111    lock(exec->globalData().isSharedInstance);
     112}
     113
     114void JSLock::unlock(ExecState* exec)
     115{
     116    unlock(exec->globalData().isSharedInstance);
     117}
     118
    77119bool JSLock::currentThreadIsHoldingLock()
    78120{
    79     pthread_once(&createDidLockJSMutexOnce, createDidLockJSMutex);
    80     return !!pthread_getspecific(didLockJSMutex);
     121    pthread_once(&createJSLockCountOnce, createJSLockCount);
     122    return !!pthread_getspecific(JSLockCount);
    81123}
    82124
     
    86128}
    87129
    88 JSLock::DropAllLocks::DropAllLocks()
    89     : m_lockCount(0)
     130JSLock::DropAllLocks::DropAllLocks(ExecState* exec)
     131    : m_lockingForReal(exec->globalData().isSharedInstance)
    90132{
    91     pthread_once(&createDidLockJSMutexOnce, createDidLockJSMutex);
     133    pthread_once(&createJSLockCountOnce, createJSLockCount);
    92134
    93     m_lockCount = !!pthread_getspecific(didLockJSMutex) ? JSLock::lockCount() : 0;
     135    m_lockCount = JSLock::lockCount();
    94136    for (int i = 0; i < m_lockCount; i++)
    95         JSLock::unlock();
     137        JSLock::unlock(m_lockingForReal);
     138}
     139
     140JSLock::DropAllLocks::DropAllLocks(bool lockingForReal)
     141    : m_lockingForReal(lockingForReal)
     142{
     143    pthread_once(&createJSLockCountOnce, createJSLockCount);
     144
     145    // It is necessary to drop even "unreal" locks, because having a non-zero lock count
     146    // will prevent a real lock from being taken.
     147
     148    m_lockCount = JSLock::lockCount();
     149    for (int i = 0; i < m_lockCount; i++)
     150        JSLock::unlock(m_lockingForReal);
    96151}
    97152
     
    99154{
    100155    for (int i = 0; i < m_lockCount; i++)
    101         JSLock::lock();
    102     m_lockCount = 0;
     156        JSLock::lock(m_lockingForReal);
    103157}
    104158
     
    107161// If threading support is off, set the lock count to a constant value of 1 so assertions
    108162// that the lock is held don't fail
    109 const int JSLockCount = 1;
     163int JSLock::lockCount()
     164{
     165    return 1;
     166}
    110167
    111168bool JSLock::currentThreadIsHoldingLock()
     
    136193#endif // USE(MULTIPLE_THREADS)
    137194
    138 int JSLock::lockCount()
    139 {
    140     return JSLockCount;
    141195}
    142 
    143 }
  • trunk/JavaScriptCore/kjs/JSLock.h

    r33038 r34947  
    4747    // thread acquired it to begin with.
    4848
     49    // For per-thread contexts, JSLock doesn't do any locking, but we
     50    // still need to perform all the counting in order to keep debug
     51    // assertions working, so that clients that use a shared context don't break.
     52
     53    class ExecState;
     54
    4955    class JSLock : Noncopyable {
    5056    public:
    51         JSLock()
     57        JSLock(ExecState* exec);
     58
     59        JSLock(bool lockingForReal)
     60            : m_lockingForReal(lockingForReal)
    5261        {
    53             lock();
    54             registerThread();
     62#ifdef NDEBUG
     63            // For per-thread contexts, locking is a debug-only feature.
     64            if (!lockingForReal)
     65                return;
     66#endif
     67            lock(lockingForReal);
     68            if (lockingForReal)
     69                registerThread();
    5570        }
    5671
    57         ~JSLock() 
     72        ~JSLock()
    5873        {
    59             unlock();
     74#ifdef NDEBUG
     75            // For per-thread contexts, locking is a debug-only feature.
     76            if (!m_lockingForReal)
     77                return;
     78#endif
     79            unlock(m_lockingForReal);
    6080        }
    6181       
    62         static void lock();
    63         static void unlock();
     82        static void lock(bool);
     83        static void unlock(bool);
     84        static void lock(ExecState*);
     85        static void unlock(ExecState*);
     86
    6487        static int lockCount();
    6588        static bool currentThreadIsHoldingLock();
     
    6790        static void registerThread();
    6891
     92        bool m_lockingForReal;
     93
    6994        class DropAllLocks : Noncopyable {
    7095        public:
    71             DropAllLocks();
     96            DropAllLocks(ExecState* exec);
     97            DropAllLocks(bool);
    7298            ~DropAllLocks();
    7399           
    74100        private:
    75101            int m_lockCount;
     102            bool m_lockingForReal;
    76103        };
    77104    };
  • trunk/JavaScriptCore/kjs/PropertyNameArray.h

    r34611 r34947  
    3838        PropertyNameArray(ExecState* exec) : m_globalData(&exec->globalData()) {}
    3939
     40        JSGlobalData* globalData() { return m_globalData; }
     41
    4042        void add(const Identifier& identifier) { add(identifier.ustring().rep()); }
    4143        void add(UString::Rep*);
  • trunk/JavaScriptCore/kjs/Shell.cpp

    r34854 r34947  
    207207JSValue* functionGC(ExecState* exec, JSObject*, JSValue*, const ArgList&)
    208208{
    209     JSLock lock;
     209    JSLock lock(false);
    210210    exec->heap()->collect();
    211211    return jsUndefined();
     
    302302        res = jscmain(argc, argv);
    303303#ifndef NDEBUG
    304         JSLock::lock();
     304        JSLock::lock(false);
    305305        JSGlobalData::threadInstance().heap->collect();
    306         JSLock::unlock();
     306        JSLock::unlock(false);
    307307#endif
    308308    EXCEPT(res = 3)
     
    448448int jscmain(int argc, char** argv)
    449449{
    450     initializeThreading();
    451 
    452     JSLock lock;
     450    KJS::initializeThreading();
     451
     452    JSLock lock(false);
    453453
    454454    Options options;
  • trunk/JavaScriptCore/kjs/collector.cpp

    r34907 r34947  
    2424#include "ExecState.h"
    2525#include "JSGlobalObject.h"
     26#include "JSLock.h"
    2627#include "JSString.h"
    2728#include "JSValue.h"
     
    9192static void freeHeap(CollectorHeap*);
    9293
    93 Heap::Heap()
     94Heap::Heap(bool isShared)
    9495    : m_markListSet(0)
     96    , m_isShared(isShared)
    9597{
    9698    memset(&primaryHeap, 0, sizeof(CollectorHeap));
     
    100102Heap::~Heap()
    101103{
    102     JSLock lock;
     104    JSLock lock(false);
    103105
    104106    delete m_markListSet;
     
    439441    // Can't use JSLock convenience object here because we don't want to re-register
    440442    // an exiting thread.
    441     JSLock::lock();
     443    // JSLock is only used for code simplicity here, as we only need to protect registeredThreads
     444    // list manipulation, not JS data structures.
     445    JSLock::lock(true);
    442446
    443447    if (registeredThreads == thread) {
     
    456460    }
    457461
    458     JSLock::unlock();
     462    JSLock::unlock(true);
    459463
    460464    delete thread;
     
    468472void Heap::registerThread()
    469473{
     474    // Since registerThread() is only called when using a shared heap, these locks will be real.
    470475    ASSERT(JSLock::lockCount() > 0);
    471476    ASSERT(JSLock::currentThreadIsHoldingLock());
     
    729734#if USE(MULTIPLE_THREADS)
    730735
    731     if (this == JSGlobalData::sharedInstance().heap) {
     736    if (m_isShared) {
    732737
    733738#ifndef NDEBUG
     
    737742        fastMallocForbid();
    738743#endif
     744        // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held,
     745        // and since this is a shared heap, they are real locks.
    739746        for (Thread* thread = registeredThreads; thread != NULL; thread = thread->next) {
    740747            if (!pthread_equal(thread->posixThread, pthread_self()))
     
    748755}
    749756
     757void Heap::setGCProtectNeedsLocking()
     758{
     759    // Most clients do not need to call this, with the notable exception of WebCore.
     760    // Clients that use shared heap have JSLock protection, while others are not supposed
     761    // to migrate JS objects between threads. WebCore violates this contract in Database code,
     762    // which calls gcUnprotect from a secondary thread.
     763    if (!m_protectedValuesMutex)
     764        m_protectedValuesMutex.set(new Mutex);
     765}
     766
    750767void Heap::protect(JSValue* k)
    751768{
    752769    ASSERT(k);
    753     ASSERT(JSLock::lockCount() > 0);
    754     ASSERT(JSLock::currentThreadIsHoldingLock());
     770    ASSERT(JSLock::currentThreadIsHoldingLock() || !m_isShared);
    755771
    756772    if (JSImmediate::isImmediate(k))
    757773        return;
    758774
    759     protectedValues.add(k->asCell());
     775    if (m_protectedValuesMutex)
     776        m_protectedValuesMutex->lock();
     777
     778    m_protectedValues.add(k->asCell());
     779
     780    if (m_protectedValuesMutex)
     781        m_protectedValuesMutex->unlock();
    760782}
    761783
     
    763785{
    764786    ASSERT(k);
    765     ASSERT(JSLock::lockCount() > 0);
    766     ASSERT(JSLock::currentThreadIsHoldingLock());
     787    ASSERT(JSLock::currentThreadIsHoldingLock() || !m_isShared);
    767788
    768789    if (JSImmediate::isImmediate(k))
    769790        return;
    770791
    771     protectedValues.remove(k->asCell());
     792    if (m_protectedValuesMutex)
     793        m_protectedValuesMutex->lock();
     794
     795    m_protectedValues.remove(k->asCell());
     796
     797    if (m_protectedValuesMutex)
     798        m_protectedValuesMutex->unlock();
    772799}
    773800
     
    781808void Heap::markProtectedObjects()
    782809{
    783     ProtectCountSet::iterator end = protectedValues.end();
    784     for (ProtectCountSet::iterator it = protectedValues.begin(); it != end; ++it) {
     810    if (m_protectedValuesMutex)
     811        m_protectedValuesMutex->lock();
     812
     813    ProtectCountSet::iterator end = m_protectedValues.end();
     814    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
    785815        JSCell* val = it->first;
    786816        if (!val->marked())
    787817            val->mark();
    788818    }
     819
     820    if (m_protectedValuesMutex)
     821        m_protectedValuesMutex->unlock();
    789822}
    790823
     
    941974size_t Heap::protectedGlobalObjectCount()
    942975{
     976    if (m_protectedValuesMutex)
     977        m_protectedValuesMutex->lock();
     978
    943979    size_t count = 0;
    944980    if (JSGlobalObject* head = JSGlobalData::threadInstance().head) {
    945981        JSGlobalObject* o = head;
    946982        do {
    947             if (protectedValues.contains(o))
     983            if (m_protectedValues.contains(o))
    948984                ++count;
    949985            o = o->next();
    950986        } while (o != head);
    951987    }
     988
     989    if (m_protectedValuesMutex)
     990        m_protectedValuesMutex->unlock();
     991
    952992    return count;
    953993}
     
    955995size_t Heap::protectedObjectCount()
    956996{
    957     return protectedValues.size();
     997    if (m_protectedValuesMutex)
     998        m_protectedValuesMutex->lock();
     999
     1000    size_t result = m_protectedValues.size();
     1001
     1002    if (m_protectedValuesMutex)
     1003        m_protectedValuesMutex->unlock();
     1004
     1005    return result;
    9581006}
    9591007
     
    9951043    HashCountedSet<const char*>* counts = new HashCountedSet<const char*>;
    9961044
    997     ProtectCountSet::iterator end = protectedValues.end();
    998     for (ProtectCountSet::iterator it = protectedValues.begin(); it != end; ++it)
     1045    if (m_protectedValuesMutex)
     1046        m_protectedValuesMutex->lock();
     1047
     1048    ProtectCountSet::iterator end = m_protectedValues.end();
     1049    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
    9991050        counts->add(typeName(it->first));
    10001051
     1052    if (m_protectedValuesMutex)
     1053        m_protectedValuesMutex->unlock();
     1054
    10011055    return counts;
    10021056}
  • trunk/JavaScriptCore/kjs/collector.h

    r34907 r34947  
    2727#include <wtf/HashSet.h>
    2828#include <wtf/Noncopyable.h>
     29#include <wtf/OwnPtr.h>
     30#include <wtf/Threading.h>
    2931
    3032namespace KJS {
     
    7678        size_t size();
    7779
     80        void setGCProtectNeedsLocking();
    7881        void protect(JSValue*);
    7982        void unprotect(JSValue*);
     
    98101
    99102        HashSet<ArgList*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<ArgList*>; return *m_markListSet; }
     103
     104        bool isShared() const { return m_isShared; }
    100105
    101106    private:
     
    106111        static size_t cellOffset(const JSCell*);
    107112
    108         friend class Machine;
    109113        friend class JSGlobalData;
    110         Heap();
     114        Heap(bool isShared);
    111115        ~Heap();
    112116
     
    122126        CollectorHeap primaryHeap;
    123127        CollectorHeap numberHeap;
    124         ProtectCountSet protectedValues;
     128
     129        OwnPtr<Mutex> m_protectedValuesMutex; // Only non-null if the client explicitly requested it via setGCPrtotectNeedsLocking().
     130        ProtectCountSet m_protectedValues;
     131
    125132        HashSet<ArgList*>* m_markListSet;
     133
     134        bool m_isShared;
    126135    };
    127136
  • trunk/JavaScriptCore/kjs/interpreter.cpp

    r34842 r34947  
    4646Completion Interpreter::checkSyntax(ExecState* exec, const UString& sourceURL, int startingLineNumber, PassRefPtr<SourceProvider> source)
    4747{
    48     JSLock lock;
     48    JSLock lock(exec);
    4949
    5050    int errLine;
     
    6464Completion Interpreter::evaluate(ExecState* exec, ScopeChain& scopeChain, const UString& sourceURL, int startingLineNumber, PassRefPtr<SourceProvider> source, JSValue* thisValue)
    6565{
    66     JSLock lock;
     66    JSLock lock(exec);
    6767   
    6868    // parse the source code
  • trunk/JavaScriptCore/kjs/protect.h

    r34659 r34947  
    2727#include "JSValue.h"
    2828#include "collector.h"
    29 #include "JSLock.h"
    3029
    3130namespace KJS {
     
    6362        ProtectedPtr() : m_ptr(NULL) { }
    6463        ProtectedPtr(T *ptr);
    65         ProtectedPtr(const ProtectedPtr &);
     64        ProtectedPtr(const ProtectedPtr&);
    6665        ~ProtectedPtr();
    6766
    68         template <class U> ProtectedPtr(const ProtectedPtr<U> &);
     67        template <class U> ProtectedPtr(const ProtectedPtr<U>&);
    6968       
    7069        T *get() const { return m_ptr; }
     
    7473        bool operator!() const { return m_ptr == NULL; }
    7574
    76         ProtectedPtr &operator=(const ProtectedPtr &);
    77         ProtectedPtr &operator=(T *);
     75        ProtectedPtr& operator=(const ProtectedPtr&);
     76        ProtectedPtr& operator=(T*);
    7877       
    7978    private:
     
    8483        : m_ptr(ptr)
    8584    {
    86         if (ptr) {
    87             JSLock lock;
     85        if (ptr)
    8886            gcProtect(ptr);
    89         }
    9087    }
    9188
    92     template <class T> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr &o)
     89    template <class T> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr& o)
    9390        : m_ptr(o.get())
    9491    {
    95         if (T *ptr = m_ptr) {
    96             JSLock lock;
     92        if (T *ptr = m_ptr)
    9793            gcProtect(ptr);
    98         }
    9994    }
    10095
    10196    template <class T> ProtectedPtr<T>::~ProtectedPtr()
    10297    {
    103         if (T *ptr = m_ptr) {
    104             JSLock lock;
     98        if (T *ptr = m_ptr)
    10599            gcUnprotect(ptr);
    106         }
    107100    }
    108101
    109     template <class T> template <class U> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr<U> &o)
     102    template <class T> template <class U> ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr<U>& o)
    110103        : m_ptr(o.get())
    111104    {
    112         if (T *ptr = m_ptr) {
    113             JSLock lock;
     105        if (T *ptr = m_ptr)
    114106            gcProtect(ptr);
    115         }
    116107    }
    117108
    118     template <class T> ProtectedPtr<T> &ProtectedPtr<T>::operator=(const ProtectedPtr<T> &o)
     109    template <class T> ProtectedPtr<T>& ProtectedPtr<T>::operator=(const ProtectedPtr<T>& o)
    119110    {
    120         JSLock lock;
    121111        T *optr = o.m_ptr;
    122112        gcProtectNullTolerant(optr);
     
    126116     }
    127117
    128     template <class T> inline ProtectedPtr<T> &ProtectedPtr<T>::operator=(T *optr)
     118    template <class T> inline ProtectedPtr<T>& ProtectedPtr<T>::operator=(T* optr)
    129119    {
    130         JSLock lock;
    131120        gcProtectNullTolerant(optr);
    132121        gcUnprotectNullTolerant(m_ptr);
     
    135124    }
    136125
    137     template <class T> inline bool operator==(const ProtectedPtr<T> &a, const ProtectedPtr<T> &b) { return a.get() == b.get(); }
    138     template <class T> inline bool operator==(const ProtectedPtr<T> &a, const T *b) { return a.get() == b; }
    139     template <class T> inline bool operator==(const T *a, const ProtectedPtr<T> &b) { return a == b.get(); }
     126    template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() == b.get(); }
     127    template <class T> inline bool operator==(const ProtectedPtr<T>& a, const T* b) { return a.get() == b; }
     128    template <class T> inline bool operator==(const T* a, const ProtectedPtr<T>& b) { return a == b.get(); }
    140129
    141     template <class T> inline bool operator!=(const ProtectedPtr<T> &a, const ProtectedPtr<T> &b) { return a.get() != b.get(); }
    142     template <class T> inline bool operator!=(const ProtectedPtr<T> &a, const T *b) { return a.get() != b; }
    143     template <class T> inline bool operator!=(const T *a, const ProtectedPtr<T> &b) { return a != b.get(); }
     130    template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() != b.get(); }
     131    template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const T* b) { return a.get() != b; }
     132    template <class T> inline bool operator!=(const T* a, const ProtectedPtr<T>& b) { return a != b.get(); }
    144133 
    145134} // namespace
  • trunk/JavaScriptCore/kjs/ustring.cpp

    r34821 r34947  
    2525#include "ustring.h"
    2626
    27 #include "JSLock.h"
    2827#include "collector.h"
    2928#include "dtoa.h"
  • trunk/JavaScriptCore/kjs/ustring.h

    r34821 r34947  
    2424#define _KJS_USTRING_H_
    2525
    26 #include "JSLock.h"
    2726#include "collector.h"
    2827#include <stdint.h>
Note: See TracChangeset for help on using the changeset viewer.