JavaScriptCore/API/JSContextRef.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  * 1. Redistributions of source code must retain the above copyright
       
     8  *    notice, this list of conditions and the following disclaimer.
       
     9  * 2. Redistributions in binary form must reproduce the above copyright
       
    10  *    notice, this list of conditions and the following disclaimer in the
       
    11  *    documentation and/or other materials provided with the distribution.
       
    12  *
       
    13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
       
    14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
       
    17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
       
    21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
       
    24  */
       
    25 
       
    26 #include "config.h"
       
    27 #include "JSContextRef.h"
       
    28 #include "JSContextRefPrivate.h"
       
    29 
       
    30 #include "APICast.h"
       
    31 #include "InitializeThreading.h"
       
    32 #include "JSCallbackObject.h"
       
    33 #include "JSClassRef.h"
       
    34 #include "JSGlobalObject.h"
       
    35 #include "JSObject.h"
       
    36 #include <wtf/text/StringHash.h>
       
    37 
       
    38 #if OS(DARWIN)
       
    39 #include <mach-o/dyld.h>
       
    40 
       
    41 static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500; // 528.5.0
       
    42 #endif
       
    43 
       
    44 using namespace JSC;
       
    45 
       
    46 JSContextGroupRef JSContextGroupCreate()
       
    47 {
       
    48     initializeThreading();
       
    49     return toRef(JSGlobalData::createContextGroup(ThreadStackTypeSmall).releaseRef());
       
    50 }
       
    51 
       
    52 JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group)
       
    53 {
       
    54     toJS(group)->ref();
       
    55     return group;
       
    56 }
       
    57 
       
    58 void JSContextGroupRelease(JSContextGroupRef group)
       
    59 {
       
    60     toJS(group)->deref();
       
    61 }
       
    62 
       
    63 JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
       
    64 {
       
    65     initializeThreading();
       
    66 #if OS(DARWIN)
       
    67     // When running on Tiger or Leopard, or if the application was linked before JSGlobalContextCreate was changed
       
    68     // to use a unique JSGlobalData, we use a shared one for compatibility.
       
    69 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
       
    70     if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) {
       
    71 #else
       
    72     {
       
    73 #endif
       
    74         JSLock lock(LockForReal);
       
    75         return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass);
       
    76     }
       
    77 #endif // OS(DARWIN)
       
    78 
       
    79     return JSGlobalContextCreateInGroup(0, globalObjectClass);
       
    80 }
       
    81 
       
    82 JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass)
       
    83 {
       
    84     initializeThreading();
       
    85 
       
    86     JSLock lock(LockForReal);
       
    87     RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createContextGroup(ThreadStackTypeSmall);
       
    88 
       
    89     APIEntryShim entryShim(globalData.get(), false);
       
    90 
       
    91 #if ENABLE(JSC_MULTIPLE_THREADS)
       
    92     globalData->makeUsableFromMultipleThreads();
       
    93 #endif
       
    94 
       
    95     if (!globalObjectClass) {
       
    96         JSGlobalObject* globalObject = new (globalData.get()) JSGlobalObject;
       
    97         return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec()));
       
    98     }
       
    99 
       
   100     JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(globalObjectClass, JSCallbackObject<JSGlobalObject>::createStructure(jsNull()));
       
   101     ExecState* exec = globalObject->globalExec();
       
   102     JSValue prototype = globalObjectClass->prototype(exec);
       
   103     if (!prototype)
       
   104         prototype = jsNull();
       
   105     globalObject->resetPrototype(prototype);
       
   106     return JSGlobalContextRetain(toGlobalRef(exec));
       
   107 }
       
   108 
       
   109 JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx)
       
   110 {
       
   111     ExecState* exec = toJS(ctx);
       
   112     APIEntryShim entryShim(exec);
       
   113 
       
   114     JSGlobalData& globalData = exec->globalData();
       
   115     gcProtect(exec->dynamicGlobalObject());
       
   116     globalData.ref();
       
   117     return ctx;
       
   118 }
       
   119 
       
   120 void JSGlobalContextRelease(JSGlobalContextRef ctx)
       
   121 {
       
   122     ExecState* exec = toJS(ctx);
       
   123     JSLock lock(exec);
       
   124 
       
   125     JSGlobalData& globalData = exec->globalData();
       
   126     JSGlobalObject* dgo = exec->dynamicGlobalObject();
       
   127     IdentifierTable* savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable);
       
   128 
       
   129     // One reference is held by JSGlobalObject, another added by JSGlobalContextRetain().
       
   130     bool releasingContextGroup = globalData.refCount() == 2;
       
   131     bool releasingGlobalObject = Heap::heap(dgo)->unprotect(dgo);
       
   132     // If this is the last reference to a global data, it should also
       
   133     // be the only remaining reference to the global object too!
       
   134     ASSERT(!releasingContextGroup || releasingGlobalObject);
       
   135 
       
   136     // An API 'JSGlobalContextRef' retains two things - a global object and a
       
   137     // global data (or context group, in API terminology).
       
   138     // * If this is the last reference to any contexts in the given context group,
       
   139     //   call destroy on the heap (the global data is being  freed).
       
   140     // * If this was the last reference to the global object, then unprotecting
       
   141     //   it may  release a lot of GC memory - run the garbage collector now.
       
   142     // * If there are more references remaining the the global object, then do nothing
       
   143     //   (specifically that is more protects, which we assume come from other JSGlobalContextRefs).
       
   144     if (releasingContextGroup)
       
   145         globalData.heap.destroy();
       
   146     else if (releasingGlobalObject)
       
   147         globalData.heap.collectAllGarbage();
       
   148 
       
   149     globalData.deref();
       
   150 
       
   151     wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable);
       
   152 }
       
   153 
       
   154 JSObjectRef JSContextGetGlobalObject(JSContextRef ctx)
       
   155 {
       
   156     ExecState* exec = toJS(ctx);
       
   157     APIEntryShim entryShim(exec);
       
   158 
       
   159     // It is necessary to call toThisObject to get the wrapper object when used with WebCore.
       
   160     return toRef(exec->lexicalGlobalObject()->toThisObject(exec));
       
   161 }
       
   162 
       
   163 JSContextGroupRef JSContextGetGroup(JSContextRef ctx)
       
   164 {
       
   165     ExecState* exec = toJS(ctx);
       
   166     return toRef(&exec->globalData());
       
   167 }
       
   168 
       
   169 JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx)
       
   170 {
       
   171     ExecState* exec = toJS(ctx);
       
   172     APIEntryShim entryShim(exec);
       
   173 
       
   174     return toGlobalRef(exec->lexicalGlobalObject()->globalExec());
       
   175 }