]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - API/JSContextRef.cpp
JavaScriptCore-1218.35.tar.gz
[apple/javascriptcore.git] / API / JSContextRef.cpp
... / ...
CommitLineData
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 <interpreter/CallFrame.h>
33#include <interpreter/Interpreter.h>
34#include "JSCallbackObject.h"
35#include "JSClassRef.h"
36#include "JSGlobalObject.h"
37#include "JSObject.h"
38#include "Operations.h"
39#include "SourceProvider.h"
40#include <wtf/text/StringBuilder.h>
41#include <wtf/text/StringHash.h>
42
43#if OS(DARWIN)
44#include <mach-o/dyld.h>
45
46static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500; // 528.5.0
47#endif
48
49using namespace JSC;
50
51// From the API's perspective, a context group remains alive iff
52// (a) it has been JSContextGroupRetained
53// OR
54// (b) one of its contexts has been JSContextRetained
55
56JSContextGroupRef JSContextGroupCreate()
57{
58 initializeThreading();
59 return toRef(VM::createContextGroup().leakRef());
60}
61
62JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group)
63{
64 toJS(group)->ref();
65 return group;
66}
67
68void JSContextGroupRelease(JSContextGroupRef group)
69{
70 IdentifierTable* savedIdentifierTable;
71 VM& vm = *toJS(group);
72
73 {
74 JSLockHolder lock(vm);
75 savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(vm.identifierTable);
76 vm.deref();
77 }
78
79 wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable);
80}
81
82static bool internalScriptTimeoutCallback(ExecState* exec, void* callbackPtr, void* callbackData)
83{
84 JSShouldTerminateCallback callback = reinterpret_cast<JSShouldTerminateCallback>(callbackPtr);
85 JSContextRef contextRef = toRef(exec);
86 ASSERT(callback);
87 return callback(contextRef, callbackData);
88}
89
90void JSContextGroupSetExecutionTimeLimit(JSContextGroupRef group, double limit, JSShouldTerminateCallback callback, void* callbackData)
91{
92 VM& vm = *toJS(group);
93 APIEntryShim entryShim(&vm);
94 Watchdog& watchdog = vm.watchdog;
95 if (callback) {
96 void* callbackPtr = reinterpret_cast<void*>(callback);
97 watchdog.setTimeLimit(vm, limit, internalScriptTimeoutCallback, callbackPtr, callbackData);
98 } else
99 watchdog.setTimeLimit(vm, limit);
100}
101
102void JSContextGroupClearExecutionTimeLimit(JSContextGroupRef group)
103{
104 VM& vm = *toJS(group);
105 APIEntryShim entryShim(&vm);
106 Watchdog& watchdog = vm.watchdog;
107 watchdog.setTimeLimit(vm, std::numeric_limits<double>::infinity());
108}
109
110// From the API's perspective, a global context remains alive iff it has been JSGlobalContextRetained.
111
112JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
113{
114 initializeThreading();
115
116#if OS(DARWIN)
117 // If the application was linked before JSGlobalContextCreate was changed to use a unique VM,
118 // we use a shared one for backwards compatibility.
119 if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) {
120 return JSGlobalContextCreateInGroup(toRef(&VM::sharedInstance()), globalObjectClass);
121 }
122#endif // OS(DARWIN)
123
124 return JSGlobalContextCreateInGroup(0, globalObjectClass);
125}
126
127JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass)
128{
129 initializeThreading();
130
131 RefPtr<VM> vm = group ? PassRefPtr<VM>(toJS(group)) : VM::createContextGroup();
132
133 APIEntryShim entryShim(vm.get(), false);
134 vm->makeUsableFromMultipleThreads();
135
136 if (!globalObjectClass) {
137 JSGlobalObject* globalObject = JSGlobalObject::create(*vm, JSGlobalObject::createStructure(*vm, jsNull()));
138 return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec()));
139 }
140
141 JSGlobalObject* globalObject = JSCallbackObject<JSGlobalObject>::create(*vm, globalObjectClass, JSCallbackObject<JSGlobalObject>::createStructure(*vm, 0, jsNull()));
142 ExecState* exec = globalObject->globalExec();
143 JSValue prototype = globalObjectClass->prototype(exec);
144 if (!prototype)
145 prototype = jsNull();
146 globalObject->resetPrototype(*vm, prototype);
147 return JSGlobalContextRetain(toGlobalRef(exec));
148}
149
150JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx)
151{
152 ExecState* exec = toJS(ctx);
153 APIEntryShim entryShim(exec);
154
155 VM& vm = exec->vm();
156 gcProtect(exec->dynamicGlobalObject());
157 vm.ref();
158 return ctx;
159}
160
161void JSGlobalContextRelease(JSGlobalContextRef ctx)
162{
163 IdentifierTable* savedIdentifierTable;
164 ExecState* exec = toJS(ctx);
165 {
166 JSLockHolder lock(exec);
167
168 VM& vm = exec->vm();
169 savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(vm.identifierTable);
170
171 bool protectCountIsZero = Heap::heap(exec->dynamicGlobalObject())->unprotect(exec->dynamicGlobalObject());
172 if (protectCountIsZero)
173 vm.heap.reportAbandonedObjectGraph();
174 vm.deref();
175 }
176
177 wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable);
178}
179
180JSObjectRef JSContextGetGlobalObject(JSContextRef ctx)
181{
182 if (!ctx) {
183 ASSERT_NOT_REACHED();
184 return 0;
185 }
186 ExecState* exec = toJS(ctx);
187 APIEntryShim entryShim(exec);
188
189 // It is necessary to call toThisObject to get the wrapper object when used with WebCore.
190 return toRef(exec->lexicalGlobalObject()->methodTable()->toThisObject(exec->lexicalGlobalObject(), exec));
191}
192
193JSContextGroupRef JSContextGetGroup(JSContextRef ctx)
194{
195 if (!ctx) {
196 ASSERT_NOT_REACHED();
197 return 0;
198 }
199 ExecState* exec = toJS(ctx);
200 return toRef(&exec->vm());
201}
202
203JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx)
204{
205 if (!ctx) {
206 ASSERT_NOT_REACHED();
207 return 0;
208 }
209 ExecState* exec = toJS(ctx);
210 APIEntryShim entryShim(exec);
211
212 return toGlobalRef(exec->lexicalGlobalObject()->globalExec());
213}
214
215JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize)
216{
217 if (!ctx) {
218 ASSERT_NOT_REACHED();
219 return 0;
220 }
221 ExecState* exec = toJS(ctx);
222 JSLockHolder lock(exec);
223 StringBuilder builder;
224 Vector<StackFrame> stackTrace;
225 Interpreter::getStackTrace(&exec->vm(), stackTrace, maxStackSize);
226
227 for (size_t i = 0; i < stackTrace.size(); i++) {
228 String urlString;
229 String functionName;
230 StackFrame& frame = stackTrace[i];
231 JSValue function = frame.callee.get();
232 if (frame.callee)
233 functionName = frame.friendlyFunctionName(exec);
234 else {
235 // Caller is unknown, but if frame is empty we should still add the frame, because
236 // something called us, and gave us arguments.
237 if (i)
238 break;
239 }
240 unsigned lineNumber;
241 unsigned column;
242 frame.computeLineAndColumn(lineNumber, column);
243 if (!builder.isEmpty())
244 builder.append('\n');
245 builder.append('#');
246 builder.appendNumber(i);
247 builder.append(' ');
248 builder.append(functionName);
249 builder.appendLiteral("() at ");
250 builder.append(urlString);
251 if (frame.codeType != StackFrameNativeCode) {
252 builder.append(':');
253 builder.appendNumber(lineNumber);
254 }
255 if (!function)
256 break;
257 }
258 return OpaqueJSString::create(builder.toString()).leakRef();
259}
260
261