2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "JSContextRef.h"
28 #include "JSContextRefPrivate.h"
31 #include "InitializeThreading.h"
32 #include <interpreter/CallFrame.h>
33 #include <interpreter/Interpreter.h>
34 #include "JSCallbackObject.h"
35 #include "JSClassRef.h"
36 #include "JSGlobalObject.h"
38 #include "UStringBuilder.h"
39 #include <wtf/text/StringHash.h>
42 #include <mach-o/dyld.h>
44 static const int32_t webkitFirstVersionWithConcurrentGlobalContexts
= 0x2100500; // 528.5.0
49 // From the API's perspective, a context group remains alive iff
50 // (a) it has been JSContextGroupRetained
52 // (b) one of its contexts has been JSContextRetained
54 JSContextGroupRef
JSContextGroupCreate()
56 initializeThreading();
57 return toRef(JSGlobalData::createContextGroup(ThreadStackTypeSmall
).leakRef());
60 JSContextGroupRef
JSContextGroupRetain(JSContextGroupRef group
)
66 void JSContextGroupRelease(JSContextGroupRef group
)
71 // From the API's perspective, a global context remains alive iff it has been JSGlobalContextRetained.
73 JSGlobalContextRef
JSGlobalContextCreate(JSClassRef globalObjectClass
)
75 initializeThreading();
78 // If the application was linked before JSGlobalContextCreate was changed to use a unique JSGlobalData,
79 // we use a shared one for backwards compatibility.
80 if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts
) {
81 return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass
);
85 return JSGlobalContextCreateInGroup(0, globalObjectClass
);
88 JSGlobalContextRef
JSGlobalContextCreateInGroup(JSContextGroupRef group
, JSClassRef globalObjectClass
)
90 initializeThreading();
92 RefPtr
<JSGlobalData
> globalData
= group
? PassRefPtr
<JSGlobalData
>(toJS(group
)) : JSGlobalData::createContextGroup(ThreadStackTypeSmall
);
94 APIEntryShim
entryShim(globalData
.get(), false);
95 globalData
->makeUsableFromMultipleThreads();
97 if (!globalObjectClass
) {
98 JSGlobalObject
* globalObject
= JSGlobalObject::create(*globalData
, JSGlobalObject::createStructure(*globalData
, jsNull()));
99 return JSGlobalContextRetain(toGlobalRef(globalObject
->globalExec()));
102 JSGlobalObject
* globalObject
= JSCallbackObject
<JSGlobalObject
>::create(*globalData
, globalObjectClass
, JSCallbackObject
<JSGlobalObject
>::createStructure(*globalData
, 0, jsNull()));
103 ExecState
* exec
= globalObject
->globalExec();
104 JSValue prototype
= globalObjectClass
->prototype(exec
);
106 prototype
= jsNull();
107 globalObject
->resetPrototype(*globalData
, prototype
);
108 return JSGlobalContextRetain(toGlobalRef(exec
));
111 JSGlobalContextRef
JSGlobalContextRetain(JSGlobalContextRef ctx
)
113 ExecState
* exec
= toJS(ctx
);
114 APIEntryShim
entryShim(exec
);
116 JSGlobalData
& globalData
= exec
->globalData();
117 gcProtect(exec
->dynamicGlobalObject());
122 void JSGlobalContextRelease(JSGlobalContextRef ctx
)
124 IdentifierTable
* savedIdentifierTable
;
125 ExecState
* exec
= toJS(ctx
);
127 JSLockHolder
lock(exec
);
129 JSGlobalData
& globalData
= exec
->globalData();
130 savedIdentifierTable
= wtfThreadData().setCurrentIdentifierTable(globalData
.identifierTable
);
132 bool protectCountIsZero
= Heap::heap(exec
->dynamicGlobalObject())->unprotect(exec
->dynamicGlobalObject());
133 if (protectCountIsZero
)
134 globalData
.heap
.reportAbandonedObjectGraph();
138 wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable
);
141 JSObjectRef
JSContextGetGlobalObject(JSContextRef ctx
)
143 ExecState
* exec
= toJS(ctx
);
144 APIEntryShim
entryShim(exec
);
146 // It is necessary to call toThisObject to get the wrapper object when used with WebCore.
147 return toRef(exec
->lexicalGlobalObject()->methodTable()->toThisObject(exec
->lexicalGlobalObject(), exec
));
150 JSContextGroupRef
JSContextGetGroup(JSContextRef ctx
)
152 ExecState
* exec
= toJS(ctx
);
153 return toRef(&exec
->globalData());
156 JSGlobalContextRef
JSContextGetGlobalContext(JSContextRef ctx
)
158 ExecState
* exec
= toJS(ctx
);
159 APIEntryShim
entryShim(exec
);
161 return toGlobalRef(exec
->lexicalGlobalObject()->globalExec());
164 JSStringRef
JSContextCreateBacktrace(JSContextRef ctx
, unsigned maxStackSize
)
166 ExecState
* exec
= toJS(ctx
);
167 JSLockHolder
lock(exec
);
170 UStringBuilder builder
;
171 CallFrame
* callFrame
= exec
;
172 UString functionName
;
173 if (exec
->callee()) {
174 if (asObject(exec
->callee())->inherits(&InternalFunction::s_info
)) {
175 functionName
= asInternalFunction(exec
->callee())->name(exec
);
176 builder
.append("#0 ");
177 builder
.append(functionName
);
178 builder
.append("() ");
184 int signedLineNumber
;
189 UString levelStr
= UString::number(count
);
191 exec
->interpreter()->retrieveLastCaller(callFrame
, signedLineNumber
, sourceID
, urlString
, function
);
194 functionName
= jsCast
<JSFunction
*>(function
)->name(exec
);
196 // Caller is unknown, but if frame is empty we should still add the frame, because
197 // something called us, and gave us arguments.
201 unsigned lineNumber
= signedLineNumber
>= 0 ? signedLineNumber
: 0;
202 if (!builder
.isEmpty())
203 builder
.append("\n");
205 builder
.append(levelStr
);
207 builder
.append(functionName
);
208 builder
.append("() at ");
209 builder
.append(urlString
);
211 builder
.append(UString::number(lineNumber
));
212 if (!function
|| ++count
== maxStackSize
)
214 callFrame
= callFrame
->callerFrame();
216 return OpaqueJSString::create(builder
.toUString()).leakRef();