Reviewed by Geoff Garen.
authorap@webkit.org <ap@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 Jul 2008 06:05:11 +0000 (06:05 +0000)
committerap@webkit.org <ap@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 Jul 2008 06:05:11 +0000 (06:05 +0000)
        Implement JSContextGroup APIs to make concurrent execution possible for
        JavaScriptCore clients.

        This changes the behavior of JSGlobalContextCreate(), so that it now uses a private context
        group for each context, making JSlock implicit locking unnecessary.

        * API/JSContextRef.h:
        * API/JSContextRef.cpp:
        (JSContextGroupCreate):
        (JSContextGroupRetain):
        (JSContextGroupRelease):
        (JSGlobalContextCreate):
        (JSGlobalContextCreateInGroup):
        (JSGlobalContextRelease):
        (JSContextGetGroup):
        Added new methods. JSGlobalContextCreate() calls JSGlobalContextCreateInGroup() now.

        * API/APICast.h: (toJS): (toRef): Added converters for JSContextGroupRef.
        * API/JSBase.cpp: (JSGarbageCollect): JSGarbageCollect(0) is now a no-op, and the passed in
        context is actually used.

        * API/JSBase.h: Aded a typedef for JSContextGroupRef. Updated documentation for
        JSGarbageCollect().

        * JavaScriptCore.exp: Removed JSGlobalData::sharedInstance().

        * kjs/JSGlobalData.cpp:
        * kjs/JSGlobalData.h:
        Removed support for JSGlobalData shared instance. JSGlobalData::isSharedInstance member
        variable still remains, to be deleted in a followup patch.

        * kjs/JSLock.cpp: (KJS::JSLock::JSLock): Disabled JSLock, to be deleted in a follow-up patch.

        * kjs/collector.cpp:
        (KJS::Heap::markOtherThreadConservatively): Removed an assertion that referenced
        JSGlobalData::sharedInstance.

        * kjs/collector.h: Made Heap destructor public, so that JSContextRelease can use it.

JavaScriptGlue:
        * JSRun.cpp:
        (JSRun::JSRun):
        * JSUtils.cpp:
        (getThreadGlobalExecState):
        Changed JavaScriptGlue to use a JSGlobalData of its own, now that there is no shared
        instance.

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

15 files changed:
JavaScriptCore/API/APICast.h
JavaScriptCore/API/JSBase.cpp
JavaScriptCore/API/JSBase.h
JavaScriptCore/API/JSContextRef.cpp
JavaScriptCore/API/JSContextRef.h
JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/kjs/JSGlobalData.cpp
JavaScriptCore/kjs/JSGlobalData.h
JavaScriptCore/kjs/JSLock.cpp
JavaScriptCore/kjs/collector.cpp
JavaScriptCore/kjs/collector.h
JavaScriptGlue/ChangeLog
JavaScriptGlue/JSRun.cpp
JavaScriptGlue/JSUtils.cpp

index 8e75acc..76947f0 100644 (file)
@@ -37,6 +37,7 @@ namespace KJS {
     class PropertyNameArray;
 }
 
+typedef const struct OpaqueJSContextGroup* JSContextGroupRef;
 typedef const struct OpaqueJSContext* JSContextRef;
 typedef struct OpaqueJSContext* JSGlobalContextRef;
 typedef struct OpaqueJSString* JSStringRef;
@@ -76,6 +77,11 @@ inline KJS::PropertyNameArray* toJS(JSPropertyNameAccumulatorRef a)
     return reinterpret_cast<KJS::PropertyNameArray*>(a);
 }
 
+inline KJS::JSGlobalData* toJS(JSContextGroupRef g)
+{
+    return reinterpret_cast<KJS::JSGlobalData*>(const_cast<OpaqueJSContextGroup*>(g));
+}
+
 inline JSValueRef toRef(KJS::JSValue* v)
 {
     return reinterpret_cast<JSValueRef>(v);
@@ -116,4 +122,9 @@ inline JSPropertyNameAccumulatorRef toRef(KJS::PropertyNameArray* l)
     return reinterpret_cast<JSPropertyNameAccumulatorRef>(l);
 }
 
+inline JSContextGroupRef toRef(KJS::JSGlobalData* g)
+{
+    return reinterpret_cast<JSContextGroupRef>(g);
+}
+
 #endif // APICast_h
index 70a867e..3a18178 100644 (file)
@@ -85,31 +85,22 @@ bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourc
 
 void JSGarbageCollect(JSContextRef ctx)
 {
-    // Unlikely, but it is legal to call JSGarbageCollect(0) before actually doing anything that would implicitly call initializeThreading().
-    if (!ctx)
-        initializeThreading();
-
-    // When using a shared heap, clients need to call JSGarbageCollect(0) after releasing the last reference to the context to avoid
-    // leaking protected objects. Because the function arguments were originally ignored, some clients may pass their released context here,
+    // We used to recommend passing NULL as an argument here, which caused the only heap to be collected.
+    // As there is no longer a shared heap, the previously recommended usage became a no-op (but the GC
+    // will happen when the context group is destroyed).
+    // Because the function argument was originally ignored, some clients may pass their released context here,
     // in which case there is a risk of crashing if another thread performs GC on the same heap in between.
-    if (ctx) {
-        ExecState* exec = toJS(ctx);
-        JSGlobalData& globalData = exec->globalData();
-        Heap* heap = globalData.heap;
+    if (!ctx)
+        return;
 
-        JSLock lock(globalData.isSharedInstance);
+    ExecState* exec = toJS(ctx);
+    JSGlobalData& globalData = exec->globalData();
+    Heap* heap = globalData.heap;
 
-        if (!heap->isBusy())
-            heap->collect();
-    } else {
-        JSLock lock(true);
+    JSLock lock(globalData.isSharedInstance);
 
-        if (JSGlobalData::sharedInstanceExists()) {
-            Heap* heap = JSGlobalData::sharedInstance().heap;
-            if (!heap->isBusy())
-                heap->collect();
-        }
-    }
+    if (!heap->isBusy())
+        heap->collect();
 
     // FIXME: Perhaps we should trigger a second mark and sweep
     // once the garbage collector is done if this is called when
index fdf37dd..411f20e 100644 (file)
@@ -32,6 +32,9 @@
 
 /* JavaScript engine interface */
 
+/*! @typedef JSContextGroupRef A group that associates JavaScript contexts with one another. Contexts in the same group may share and exchange JavaScript objects. */
+typedef const struct OpaqueJSContextGroup* JSContextGroupRef;
+
 /*! @typedef JSContextRef A JavaScript execution context. Holds the global object and other execution state. */
 typedef const struct OpaqueJSContext* JSContextRef;
 
@@ -108,16 +111,15 @@ JS_EXPORT bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStrin
 /*!
 @function
 @abstract Performs a JavaScript garbage collection. 
-@param ctx This parameter is currently unused. Pass NULL.
+@param ctx The execution context to use.
 @discussion JavaScript values that are on the machine stack, in a register, 
  protected by JSValueProtect, set as the global object of an execution context, 
- or reachable from any such value will not be collected. 
+ or reachable from any such value will not be collected.
+
  During JavaScript execution, you are not required to call this function; the 
- JavaScript engine will garbage collect as needed. One place you may want to call 
- this function, however, is after releasing the last reference to a JSGlobalContextRef. 
- At that point, a garbage collection can free the objects still referenced by the 
- JSGlobalContextRef's global object, along with the global object itself.
+ JavaScript engine will garbage collect as needed. JavaScript values created
+ within a context group are automatically destroyed when the last reference
+ to the context group is released.
 */
 JS_EXPORT void JSGarbageCollect(JSContextRef ctx);
 
index cc97434..a9c2924 100644 (file)
 
 using namespace KJS;
 
+JSContextGroupRef JSContextGroupCreate()
+{
+    return toRef(JSGlobalData::create().releaseRef());
+}
+
+JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group)
+{
+    toJS(group)->ref();
+    return group;
+}
+
+void JSContextGroupRelease(JSContextGroupRef group)
+{
+    toJS(group)->deref();
+}
+
 JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
 {
+    return JSGlobalContextCreateInGroup(toRef(JSGlobalData::create().get()), globalObjectClass);
+}
+
+JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass)
+{
     initializeThreading();
 
     JSLock lock(true);
 
-    JSGlobalData* sharedGlobalData = &JSGlobalData::sharedInstance();
+    JSGlobalData* globalData = toJS(group);
 
     if (!globalObjectClass) {
-        JSGlobalObject* globalObject = new (sharedGlobalData) JSGlobalObject;
+        JSGlobalObject* globalObject = new (globalData) JSGlobalObject;
         return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec()));
     }
 
-    JSGlobalObject* globalObject = new (sharedGlobalData) JSCallbackObject<JSGlobalObject>(globalObjectClass);
+    JSGlobalObject* globalObject = new (globalData) JSCallbackObject<JSGlobalObject>(globalObjectClass);
     ExecState* exec = globalObject->globalExec();
     JSValue* prototype = globalObjectClass->prototype(exec);
     if (!prototype)
@@ -75,6 +96,21 @@ void JSGlobalContextRelease(JSGlobalContextRef ctx)
     JSLock lock(exec);
 
     gcUnprotect(exec->dynamicGlobalObject());
+
+    JSGlobalData& globalData = exec->globalData();
+    if (globalData.refCount() == 1) {
+        // The last reference was released, this is our last chance to collect.
+        Heap* heap = globalData.heap;
+
+        ASSERT(!heap->protectedObjectCount());
+        ASSERT(!heap->isBusy());
+
+        // Heap::destroy() will delete JSGlobalObject, which will in turn delete JSGlobalData, which will
+        // delete the heap, which would cause a crash if allowed.
+        globalData.heap = 0;
+
+        delete heap;
+    }
 }
 
 JSObjectRef JSContextGetGlobalObject(JSContextRef ctx)
@@ -85,3 +121,9 @@ JSObjectRef JSContextGetGlobalObject(JSContextRef ctx)
     // It is necessary to call toThisObject to get the wrapper object when used with WebCore.
     return toRef(exec->dynamicGlobalObject()->toThisObject(exec));
 }
+
+JSContextGroupRef JSContextGetGroup(JSContextRef ctx)
+{
+    ExecState* exec = toJS(ctx);
+    return toRef(&exec->globalData());
+}
index ef4e5f2..5e46a14 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <JavaScriptCore/JSObjectRef.h>
 #include <JavaScriptCore/JSValueRef.h>
+#include <JavaScriptCore/WebKitAvailability.h>
 
 #ifndef __cplusplus
 #include <stdbool.h>
@@ -39,9 +40,37 @@ extern "C" {
 
 /*!
 @function
+@abstract Creates a JavaScript context group.
+@discussion A JSContextGroup associates JavaScript contexts with one another.
+ Contexts in the same group may share and exchange JavaScript objects. Sharing and/or exchanging
+ JavaScript objects between contexts in different groups will produce undefined behavior.
+ When objects from the same context group are used in multiple threads, explicit
+ synchronization is required.
+@result The created JSContextGroup.
+*/
+JS_EXPORT JSContextGroupRef JSContextGroupCreate() AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
+/*!
+@function
+@abstract Retains a JavaScript context group.
+@param group The JSContextGroup to retain.
+@result A JSContextGroup that is the same as group.
+*/
+JS_EXPORT JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
+/*!
+@function
+@abstract Releases a JavaScript context group.
+@param group The JSContextGroup to release.
+*/
+JS_EXPORT void JSContextGroupRelease(JSContextGroupRef group) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
+/*!
+@function
 @abstract Creates a global JavaScript execution context.
 @discussion JSGlobalContextCreate allocates a global object and populates it with all the
  built-in JavaScript objects, such as Object, Function, String, and Array.
+ The global context is created in a unique context group.
 @param globalObjectClass The class to use when creating the global object. Pass 
  NULL to use the default object class.
 @result A JSGlobalContext with a global object of class globalObjectClass.
@@ -50,6 +79,19 @@ JS_EXPORT JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
 
 /*!
 @function
+@abstract Creates a global JavaScript execution context in the context group provided.
+@discussion JSGlobalContextCreateInGroup allocates a global object and populates it with
+ all the built-in JavaScript objects, such as Object, Function, String, and Array.
+@param globalObjectClass The class to use when creating the global object. Pass
+ NULL to use the default object class.
+@param group The context group to use. The created global context retains the group.
+@result A JSGlobalContext with a global object of class globalObjectClass and a context
+ group equal to group.
+*/
+JS_EXPORT JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
+/*!
+@function
 @abstract Retains a global JavaScript execution context.
 @param ctx The JSGlobalContext to retain.
 @result A JSGlobalContext that is the same as ctx.
@@ -71,6 +113,14 @@ JS_EXPORT void JSGlobalContextRelease(JSGlobalContextRef ctx);
 */
 JS_EXPORT JSObjectRef JSContextGetGlobalObject(JSContextRef ctx);
 
+/*!
+@function
+@abstract Gets the context group to which a JavaScript execution context belongs.
+@param ctx The JSContext whose group you want to get.
+@result ctx's group.
+*/
+JS_EXPORT JSContextGroupRef JSContextGetGroup(JSContextRef ctx) AVAILABLE_AFTER_WEBKIT_VERSION_3_1;
+
 #ifdef __cplusplus
 }
 #endif
index b39d615..84cd9f0 100644 (file)
@@ -2,6 +2,49 @@
 
         Reviewed by Geoff Garen.
 
+        Implement JSContextGroup APIs to make concurrent execution possible for
+        JavaScriptCore clients.
+
+        This changes the behavior of JSGlobalContextCreate(), so that it now uses a private context
+        group for each context, making JSlock implicit locking unnecessary.
+
+        * API/JSContextRef.h:
+        * API/JSContextRef.cpp:
+        (JSContextGroupCreate):
+        (JSContextGroupRetain):
+        (JSContextGroupRelease):
+        (JSGlobalContextCreate):
+        (JSGlobalContextCreateInGroup):
+        (JSGlobalContextRelease):
+        (JSContextGetGroup):
+        Added new methods. JSGlobalContextCreate() calls JSGlobalContextCreateInGroup() now.
+
+        * API/APICast.h: (toJS): (toRef): Added converters for JSContextGroupRef.
+        * API/JSBase.cpp: (JSGarbageCollect): JSGarbageCollect(0) is now a no-op, and the passed in
+        context is actually used.
+
+        * API/JSBase.h: Aded a typedef for JSContextGroupRef. Updated documentation for
+        JSGarbageCollect().
+
+        * JavaScriptCore.exp: Removed JSGlobalData::sharedInstance().
+
+        * kjs/JSGlobalData.cpp:
+        * kjs/JSGlobalData.h:
+        Removed support for JSGlobalData shared instance. JSGlobalData::isSharedInstance member
+        variable still remains, to be deleted in a followup patch.
+
+        * kjs/JSLock.cpp: (KJS::JSLock::JSLock): Disabled JSLock, to be deleted in a follow-up patch.
+        
+        * kjs/collector.cpp:
+        (KJS::Heap::markOtherThreadConservatively): Removed an assertion that referenced
+        JSGlobalData::sharedInstance.
+
+        * kjs/collector.h: Made Heap destructor public, so that JSContextRelease can use it.
+
+2008-07-29  Alexey Proskuryakov  <ap@webkit.org>
+
+        Reviewed by Geoff Garen.
+
         Fix a leak of ThreadRegistrar objects.
 
         As the heap is usually deleted when registered threads still exist, ThreadSpecific doesn't
index a8bd087..68b3987 100644 (file)
@@ -98,7 +98,6 @@ __ZN3KJS11PropertyMap11getLocationERKNS_10IdentifierERb
 __ZN3KJS11PropertyMap3putERKNS_10IdentifierEPNS_7JSValueEjb
 __ZN3KJS11PropertyMapD1Ev
 __ZN3KJS12DateInstance4infoE
-__ZN3KJS12JSGlobalData14sharedInstanceEv
 __ZN3KJS12JSGlobalData6createEv
 __ZN3KJS12JSGlobalDataD1Ev
 __ZN3KJS12PropertySlot15undefinedGetterEPNS_9ExecStateERKNS_10IdentifierERKS0_
index 598c292..2a608f6 100644 (file)
@@ -56,7 +56,7 @@ extern const HashTable regExpTable;
 extern const HashTable regExpConstructorTable;
 extern const HashTable stringTable;
 
-JSGlobalData::JSGlobalData(bool isShared)
+JSGlobalData::JSGlobalData()
     : machine(new Machine)
     , heap(new Heap(this))
 #if USE(MULTIPLE_THREADS)
@@ -85,7 +85,7 @@ JSGlobalData::JSGlobalData(bool isShared)
     , lexer(new Lexer(this))
     , parser(new Parser)
     , head(0)
-    , isSharedInstance(isShared)
+    , isSharedInstance(false)
 {
 }
 
@@ -131,24 +131,4 @@ PassRefPtr<JSGlobalData> JSGlobalData::create()
     return adoptRef(new JSGlobalData);
 }
 
-bool JSGlobalData::sharedInstanceExists()
-{
-    return sharedInstanceInternal();
-}
-
-JSGlobalData& JSGlobalData::sharedInstance()
-{
-    JSGlobalData*& instance = sharedInstanceInternal();
-    if (!instance)
-        instance = new JSGlobalData(true);
-    return *instance;
-}
-
-JSGlobalData*& JSGlobalData::sharedInstanceInternal()
-{
-    ASSERT(JSLock::currentThreadIsHoldingLock());
-    static JSGlobalData* sharedInstance;
-    return sharedInstance;
-}
-
 }
index 95d25bd..355f3cd 100644 (file)
@@ -53,9 +53,6 @@ namespace KJS {
     struct HashTable;
 
     struct JSGlobalData : public RefCounted<JSGlobalData> {
-        static bool sharedInstanceExists();
-        static JSGlobalData& sharedInstance();
-
         static PassRefPtr<JSGlobalData> create();
         ~JSGlobalData();
 
@@ -87,9 +84,7 @@ namespace KJS {
         bool isSharedInstance;
 
     private:
-        JSGlobalData(bool isShared = false);
-
-        static JSGlobalData*& sharedInstanceInternal();
+        JSGlobalData();
 
         struct DataInstance {
             DataInstance() : m_data(0) { }
index 9c9ca9a..5b949ac 100644 (file)
 
 namespace KJS {
 
-#if USE(MULTIPLE_THREADS)
-
-// Acquire this mutex before accessing lock-related data.
-static pthread_mutex_t JSMutex = PTHREAD_MUTEX_INITIALIZER;
-
-// Thread-specific key that tells whether a thread holds the JSMutex, and how many times it was taken recursively.
-pthread_key_t JSLockCount;
-
-static void createJSLockCount()
-{
-    pthread_key_create(&JSLockCount, 0);
-}
-
-pthread_once_t createJSLockCountOnce = PTHREAD_ONCE_INIT;
-
-// Lock nesting count.
-intptr_t JSLock::lockCount()
-{
-    pthread_once(&createJSLockCountOnce, createJSLockCount);
-
-    return reinterpret_cast<intptr_t>(pthread_getspecific(JSLockCount));
-}
-
-static void setLockCount(intptr_t count)
-{
-    ASSERT(count >= 0);
-    pthread_setspecific(JSLockCount, reinterpret_cast<void*>(count));
-}
-
-JSLock::JSLock(ExecState* exec)
-    : m_lockingForReal(exec->globalData().isSharedInstance)
-{
-    lock(m_lockingForReal);
-}
-
-void JSLock::lock(bool lockForReal)
-{
-#ifdef NDEBUG
-    // Locking "not for real" is a debug-only feature.
-    if (!lockForReal)
-        return;
-#endif
-
-    pthread_once(&createJSLockCountOnce, createJSLockCount);
-
-    intptr_t currentLockCount = lockCount();
-    if (!currentLockCount && lockForReal) {
-        int result;
-        result = pthread_mutex_lock(&JSMutex);
-        ASSERT(!result);
-    }
-    setLockCount(currentLockCount + 1);
-}
-
-void JSLock::unlock(bool lockForReal)
-{
-    ASSERT(lockCount());
-
-#ifdef NDEBUG
-    // Locking "not for real" is a debug-only feature.
-    if (!lockForReal)
-        return;
-#endif
-
-    intptr_t newLockCount = lockCount() - 1;
-    setLockCount(newLockCount);
-    if (!newLockCount && lockForReal) {
-        int result;
-        result = pthread_mutex_unlock(&JSMutex);
-        ASSERT(!result);
-    }
-}
-
-void JSLock::lock(ExecState* exec)
-{
-    lock(exec->globalData().isSharedInstance);
-}
-
-void JSLock::unlock(ExecState* exec)
-{
-    unlock(exec->globalData().isSharedInstance);
-}
-
-bool JSLock::currentThreadIsHoldingLock()
-{
-    pthread_once(&createJSLockCountOnce, createJSLockCount);
-    return !!pthread_getspecific(JSLockCount);
-}
-
-JSLock::DropAllLocks::DropAllLocks(ExecState* exec)
-    : m_lockingForReal(exec->globalData().isSharedInstance)
-{
-    pthread_once(&createJSLockCountOnce, createJSLockCount);
-
-    m_lockCount = JSLock::lockCount();
-    for (intptr_t i = 0; i < m_lockCount; i++)
-        JSLock::unlock(m_lockingForReal);
-}
-
-JSLock::DropAllLocks::DropAllLocks(bool lockingForReal)
-    : m_lockingForReal(lockingForReal)
-{
-    pthread_once(&createJSLockCountOnce, createJSLockCount);
-
-    // It is necessary to drop even "unreal" locks, because having a non-zero lock count
-    // will prevent a real lock from being taken.
-
-    m_lockCount = JSLock::lockCount();
-    for (intptr_t i = 0; i < m_lockCount; i++)
-        JSLock::unlock(m_lockingForReal);
-}
-
-JSLock::DropAllLocks::~DropAllLocks()
-{
-    for (intptr_t i = 0; i < m_lockCount; i++)
-        JSLock::lock(m_lockingForReal);
-}
-
-#else
-
-JSLock::JSLock(ExecState* exec)
+JSLock::JSLock(ExecState*)
     : m_lockingForReal(false)
 {
 }
@@ -195,6 +75,4 @@ JSLock::DropAllLocks::~DropAllLocks()
 {
 }
 
-#endif // USE(MULTIPLE_THREADS)
-
 } // namespace KJS
index 8890a74..3b4c178 100644 (file)
@@ -725,8 +725,6 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
 
 void Heap::markOtherThreadConservatively(Thread* thread)
 {
-    ASSERT(this == JSGlobalData::sharedInstance().heap);
-
     suspendThread(thread->platformThread);
 
     PlatformThreadRegisters regs;
index 13b6689..788caca 100644 (file)
@@ -74,6 +74,8 @@ namespace KJS {
         bool collect();
         bool isBusy(); // true if an allocation or collection is in progress
 
+        ~Heap();
+
         static const size_t minExtraCostSize = 256;
 
         void reportExtraMemoryCost(size_t cost);
@@ -111,7 +113,6 @@ namespace KJS {
 
         friend class JSGlobalData;
         Heap(JSGlobalData*);
-        ~Heap();
 
         void recordExtraCost(size_t);
         void markProtectedObjects();
index 9fd1905..47b207f 100644 (file)
@@ -1,3 +1,17 @@
+2008-07-29  Alexey Proskuryakov  <ap@webkit.org>
+
+        Reviewed by Geoff Garen.
+
+        Implement JSContextGroup APIs to make concurrent execution possible for
+        JavaScriptCore clients.
+
+        * JSRun.cpp:
+        (JSRun::JSRun):
+        * JSUtils.cpp:
+        (getThreadGlobalExecState):
+        Changed JavaScriptGlue to use a JSGlobalData of its own, now that there is no shared
+        instance.
+
 2008-07-23  Alexey Proskuryakov  <ap@webkit.org>
 
         Reviewed by Geoff Garen.
index 6290e18..71a7a06 100644 (file)
@@ -34,7 +34,7 @@
 JSRun::JSRun(CFStringRef source, JSFlags inFlags)
     :   JSBase(kJSRunTypeID),
         fSource(CFStringToUString(source)),
-        fGlobalObject(new (&JSGlobalData::sharedInstance()) JSGlueGlobalObject(inFlags)),
+        fGlobalObject(new (&getThreadGlobalExecState()->globalData()) JSGlueGlobalObject(inFlags)),
         fFlags(inFlags)
 {
 }
index 76ed944..fe01255 100644 (file)
@@ -396,6 +396,7 @@ CFTypeRef GetCFNull(void)
 
 static pthread_key_t globalObjectKey;
 static pthread_once_t globalObjectKeyOnce = PTHREAD_ONCE_INIT;
+JSGlobalData* sharedGlobalData;
 
 static void unprotectGlobalObject(void* data) 
 {
@@ -405,6 +406,7 @@ static void unprotectGlobalObject(void* data)
 
 static void initializeGlobalObjectKey()
 {
+    sharedGlobalData = JSGlobalData::create().releaseRef();
     pthread_key_create(&globalObjectKey, unprotectGlobalObject);
 }
 
@@ -413,7 +415,7 @@ ExecState* getThreadGlobalExecState()
     pthread_once(&globalObjectKeyOnce, initializeGlobalObjectKey);
     JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(pthread_getspecific(globalObjectKey));
     if (!globalObject) {
-        globalObject = new (&JSGlobalData::sharedInstance()) JSGlueGlobalObject;
+        globalObject = new (JSGlobalData::create().get()) JSGlueGlobalObject;
         gcProtect(globalObject);
         pthread_setspecific(globalObjectKey, globalObject);
     }