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 "Operations.h"
39 #include "SourceProvider.h"
40 #include <wtf/text/StringBuilder.h>
41 #include <wtf/text/StringHash.h>
44 #include <mach-o/dyld.h>
46 static const int32_t webkitFirstVersionWithConcurrentGlobalContexts
= 0x2100500; // 528.5.0
51 // From the API's perspective, a context group remains alive iff
52 // (a) it has been JSContextGroupRetained
54 // (b) one of its contexts has been JSContextRetained
56 JSContextGroupRef
JSContextGroupCreate()
58 initializeThreading();
59 return toRef(VM::createContextGroup().leakRef());
62 JSContextGroupRef
JSContextGroupRetain(JSContextGroupRef group
)
68 void JSContextGroupRelease(JSContextGroupRef group
)
70 IdentifierTable
* savedIdentifierTable
;
71 VM
& vm
= *toJS(group
);
74 JSLockHolder
lock(vm
);
75 savedIdentifierTable
= wtfThreadData().setCurrentIdentifierTable(vm
.identifierTable
);
79 wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable
);
82 static bool internalScriptTimeoutCallback(ExecState
* exec
, void* callbackPtr
, void* callbackData
)
84 JSShouldTerminateCallback callback
= reinterpret_cast<JSShouldTerminateCallback
>(callbackPtr
);
85 JSContextRef contextRef
= toRef(exec
);
87 return callback(contextRef
, callbackData
);
90 void JSContextGroupSetExecutionTimeLimit(JSContextGroupRef group
, double limit
, JSShouldTerminateCallback callback
, void* callbackData
)
92 VM
& vm
= *toJS(group
);
93 APIEntryShim
entryShim(&vm
);
94 Watchdog
& watchdog
= vm
.watchdog
;
96 void* callbackPtr
= reinterpret_cast<void*>(callback
);
97 watchdog
.setTimeLimit(vm
, limit
, internalScriptTimeoutCallback
, callbackPtr
, callbackData
);
99 watchdog
.setTimeLimit(vm
, limit
);
102 void JSContextGroupClearExecutionTimeLimit(JSContextGroupRef group
)
104 VM
& vm
= *toJS(group
);
105 APIEntryShim
entryShim(&vm
);
106 Watchdog
& watchdog
= vm
.watchdog
;
107 watchdog
.setTimeLimit(vm
, std::numeric_limits
<double>::infinity());
110 // From the API's perspective, a global context remains alive iff it has been JSGlobalContextRetained.
112 JSGlobalContextRef
JSGlobalContextCreate(JSClassRef globalObjectClass
)
114 initializeThreading();
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
);
124 return JSGlobalContextCreateInGroup(0, globalObjectClass
);
127 JSGlobalContextRef
JSGlobalContextCreateInGroup(JSContextGroupRef group
, JSClassRef globalObjectClass
)
129 initializeThreading();
131 RefPtr
<VM
> vm
= group
? PassRefPtr
<VM
>(toJS(group
)) : VM::createContextGroup();
133 APIEntryShim
entryShim(vm
.get(), false);
134 vm
->makeUsableFromMultipleThreads();
136 if (!globalObjectClass
) {
137 JSGlobalObject
* globalObject
= JSGlobalObject::create(*vm
, JSGlobalObject::createStructure(*vm
, jsNull()));
138 return JSGlobalContextRetain(toGlobalRef(globalObject
->globalExec()));
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
);
145 prototype
= jsNull();
146 globalObject
->resetPrototype(*vm
, prototype
);
147 return JSGlobalContextRetain(toGlobalRef(exec
));
150 JSGlobalContextRef
JSGlobalContextRetain(JSGlobalContextRef ctx
)
152 ExecState
* exec
= toJS(ctx
);
153 APIEntryShim
entryShim(exec
);
156 gcProtect(exec
->dynamicGlobalObject());
161 void JSGlobalContextRelease(JSGlobalContextRef ctx
)
163 IdentifierTable
* savedIdentifierTable
;
164 ExecState
* exec
= toJS(ctx
);
166 JSLockHolder
lock(exec
);
169 savedIdentifierTable
= wtfThreadData().setCurrentIdentifierTable(vm
.identifierTable
);
171 bool protectCountIsZero
= Heap::heap(exec
->dynamicGlobalObject())->unprotect(exec
->dynamicGlobalObject());
172 if (protectCountIsZero
)
173 vm
.heap
.reportAbandonedObjectGraph();
177 wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable
);
180 JSObjectRef
JSContextGetGlobalObject(JSContextRef ctx
)
183 ASSERT_NOT_REACHED();
186 ExecState
* exec
= toJS(ctx
);
187 APIEntryShim
entryShim(exec
);
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
));
193 JSContextGroupRef
JSContextGetGroup(JSContextRef ctx
)
196 ASSERT_NOT_REACHED();
199 ExecState
* exec
= toJS(ctx
);
200 return toRef(&exec
->vm());
203 JSGlobalContextRef
JSContextGetGlobalContext(JSContextRef ctx
)
206 ASSERT_NOT_REACHED();
209 ExecState
* exec
= toJS(ctx
);
210 APIEntryShim
entryShim(exec
);
212 return toGlobalRef(exec
->lexicalGlobalObject()->globalExec());
215 JSStringRef
JSContextCreateBacktrace(JSContextRef ctx
, unsigned maxStackSize
)
218 ASSERT_NOT_REACHED();
221 ExecState
* exec
= toJS(ctx
);
222 JSLockHolder
lock(exec
);
223 StringBuilder builder
;
224 Vector
<StackFrame
> stackTrace
;
225 Interpreter::getStackTrace(&exec
->vm(), stackTrace
, maxStackSize
);
227 for (size_t i
= 0; i
< stackTrace
.size(); i
++) {
230 StackFrame
& frame
= stackTrace
[i
];
231 JSValue function
= frame
.callee
.get();
233 functionName
= frame
.friendlyFunctionName(exec
);
235 // Caller is unknown, but if frame is empty we should still add the frame, because
236 // something called us, and gave us arguments.
242 frame
.computeLineAndColumn(lineNumber
, column
);
243 if (!builder
.isEmpty())
244 builder
.append('\n');
246 builder
.appendNumber(i
);
248 builder
.append(functionName
);
249 builder
.appendLiteral("() at ");
250 builder
.append(urlString
);
251 if (frame
.codeType
!= StackFrameNativeCode
) {
253 builder
.appendNumber(lineNumber
);
258 return OpaqueJSString::create(builder
.toString()).leakRef();