]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - API/JSContextRef.cpp
JavaScriptCore-1097.3.3.tar.gz
[apple/javascriptcore.git] / API / JSContextRef.cpp
index 9c15b22f1deb481cca7f7ea83d1983599abb7cf1..7a57287ded4e02d4b0dcc4997dda90431b6da1ab 100644 (file)
@@ -38,7 +38,6 @@
 #include "UStringBuilder.h"
 #include <wtf/text/StringHash.h>
 
-
 #if OS(DARWIN)
 #include <mach-o/dyld.h>
 
@@ -47,6 +46,11 @@ static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500;
 
 using namespace JSC;
 
+// From the API's perspective, a context group remains alive iff
+//     (a) it has been JSContextGroupRetained
+//     OR
+//     (b) one of its contexts has been JSContextRetained
+
 JSContextGroupRef JSContextGroupCreate()
 {
     initializeThreading();
@@ -64,18 +68,16 @@ void JSContextGroupRelease(JSContextGroupRef group)
     toJS(group)->deref();
 }
 
+// From the API's perspective, a global context remains alive iff it has been JSGlobalContextRetained.
+
 JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
 {
     initializeThreading();
+
 #if OS(DARWIN)
-    // When running on Tiger or Leopard, or if the application was linked before JSGlobalContextCreate was changed
-    // to use a unique JSGlobalData, we use a shared one for compatibility.
-#ifndef BUILDING_ON_LEOPARD
+    // If the application was linked before JSGlobalContextCreate was changed to use a unique JSGlobalData,
+    // we use a shared one for backwards compatibility.
     if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) {
-#else
-    {
-#endif
-        JSLock lock(LockForReal);
         return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass);
     }
 #endif // OS(DARWIN)
@@ -87,21 +89,17 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass
 {
     initializeThreading();
 
-    JSLock lock(LockForReal);
     RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createContextGroup(ThreadStackTypeSmall);
 
     APIEntryShim entryShim(globalData.get(), false);
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
     globalData->makeUsableFromMultipleThreads();
-#endif
 
     if (!globalObjectClass) {
-        JSGlobalObject* globalObject = new (globalData.get()) JSGlobalObject(*globalData, JSGlobalObject::createStructure(*globalData, jsNull()));
+        JSGlobalObject* globalObject = JSGlobalObject::create(*globalData, JSGlobalObject::createStructure(*globalData, jsNull()));
         return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec()));
     }
 
-    JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(*globalData, globalObjectClass, JSCallbackObject<JSGlobalObject>::createStructure(*globalData, jsNull()));
+    JSGlobalObject* globalObject = JSCallbackObject<JSGlobalObject>::create(*globalData, globalObjectClass, JSCallbackObject<JSGlobalObject>::createStructure(*globalData, 0, jsNull()));
     ExecState* exec = globalObject->globalExec();
     JSValue prototype = globalObjectClass->prototype(exec);
     if (!prototype)
@@ -123,38 +121,19 @@ JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx)
 
 void JSGlobalContextRelease(JSGlobalContextRef ctx)
 {
+    IdentifierTable* savedIdentifierTable;
     ExecState* exec = toJS(ctx);
-    JSLock lock(exec);
+    {
+        JSLockHolder lock(exec);
 
-    JSGlobalData& globalData = exec->globalData();
-    JSGlobalObject* dgo = exec->dynamicGlobalObject();
-    IdentifierTable* savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable);
-
-    // One reference is held by JSGlobalObject, another added by JSGlobalContextRetain().
-    bool releasingContextGroup = globalData.refCount() == 2;
-    bool releasingGlobalObject = Heap::heap(dgo)->unprotect(dgo);
-    // If this is the last reference to a global data, it should also
-    // be the only remaining reference to the global object too!
-    ASSERT(!releasingContextGroup || releasingGlobalObject);
-
-    // An API 'JSGlobalContextRef' retains two things - a global object and a
-    // global data (or context group, in API terminology).
-    // * If this is the last reference to any contexts in the given context group,
-    //   call destroy on the heap (the global data is being  freed).
-    // * If this was the last reference to the global object, then unprotecting
-    //   it may release a lot of GC memory - tickle the activity callback to
-    //   garbage collect soon.
-    // * If there are more references remaining the the global object, then do nothing
-    //   (specifically that is more protects, which we assume come from other JSGlobalContextRefs).
-    if (releasingContextGroup) {
-        globalData.clearBuiltinStructures();
-        globalData.heap.destroy();
-    } else if (releasingGlobalObject) {
-        globalData.heap.activityCallback()->synchronize();
-        (*globalData.heap.activityCallback())();
-    }
+        JSGlobalData& globalData = exec->globalData();
+        savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable);
 
-    globalData.deref();
+        bool protectCountIsZero = Heap::heap(exec->dynamicGlobalObject())->unprotect(exec->dynamicGlobalObject());
+        if (protectCountIsZero)
+            globalData.heap.reportAbandonedObjectGraph();
+        globalData.deref();
+    }
 
     wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable);
 }
@@ -165,7 +144,7 @@ JSObjectRef JSContextGetGlobalObject(JSContextRef ctx)
     APIEntryShim entryShim(exec);
 
     // It is necessary to call toThisObject to get the wrapper object when used with WebCore.
-    return toRef(exec->lexicalGlobalObject()->toThisObject(exec));
+    return toRef(exec->lexicalGlobalObject()->methodTable()->toThisObject(exec->lexicalGlobalObject(), exec));
 }
 
 JSContextGroupRef JSContextGetGroup(JSContextRef ctx)
@@ -185,7 +164,7 @@ JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx)
 JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize)
 {
     ExecState* exec = toJS(ctx);
-    JSLock lock(exec);
+    JSLockHolder lock(exec);
 
     unsigned count = 0;
     UStringBuilder builder;
@@ -212,7 +191,7 @@ JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize)
         exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function);
 
         if (function)
-            functionName = asFunction(function)->name(exec);
+            functionName = jsCast<JSFunction*>(function)->name(exec);
         else {
             // Caller is unknown, but if frame is empty we should still add the frame, because
             // something called us, and gave us arguments.