source: webkit/trunk/JavaScriptCore/API/JSValueRef.cpp@ 34947

Last change on this file since 34947 was 34947, checked in by [email protected], 17 years ago

Reviewed by Darin.

Disable JSLock for per-thread contexts.

No change on SunSpider.

  • kjs/JSGlobalData.h:
  • kjs/JSGlobalData.cpp: (KJS::JSGlobalData::JSGlobalData): (KJS::JSGlobalData::sharedInstance): Added isSharedInstance as a better way to tell whether the instance is shared (legacy).
  • kjs/JSLock.cpp: (KJS::createJSLockCount): (KJS::JSLock::lockCount): (KJS::setLockCount): (KJS::JSLock::JSLock): (KJS::JSLock::lock): (KJS::JSLock::unlock): (KJS::JSLock::currentThreadIsHoldingLock): (KJS::JSLock::DropAllLocks::DropAllLocks): (KJS::JSLock::DropAllLocks::~DropAllLocks):
  • kjs/JSLock.h: (KJS::JSLock::JSLock): (KJS::JSLock::~JSLock): Made JSLock and JSLock::DropAllLocks constructors take a parameter to decide whether to actually lock a mutex, or only to increment recursion count. We cannot turn it into no-op if we want to keep existing assertions working. Made recursion count per-thread, now that locks may not lock.
  • API/JSBase.cpp: (JSEvaluateScript): Take JSLock after casting JSContextRef to ExecState* (which doesn't need locking in any case), so that a decision whether to actually lock can be made. (JSCheckScriptSyntax): Ditto. (JSGarbageCollect): Only lock while collecting the shared heap, not the per-thread one.
  • API/JSObjectRef.cpp: (JSClassCreate): Don't lock, as there is no reason to. (JSClassRetain): Ditto. (JSClassRelease): Ditto. (JSPropertyNameArrayRetain): Ditto. (JSPropertyNameArrayRelease): Only lock while deleting the array, as that may touch identifier table. (JSPropertyNameAccumulatorAddName): Adding a string also involves an identifier table lookup, and possibly modification.
  • API/JSStringRef.cpp: (JSStringCreateWithCharacters): (JSStringCreateWithUTF8CString): (JSStringRetain): (JSStringRelease): (JSStringGetUTF8CString): (JSStringIsEqual):
  • API/JSStringRefCF.cpp: (JSStringCreateWithCFString): JSStringRef operations other than releasing do not need locking.
  • VM/Machine.cpp: Don't include unused JSLock.h.
  • kjs/CollectorHeapIntrospector.cpp: (KJS::CollectorHeapIntrospector::statistics): Don't take the lock for real, as heap introspection pauses the process anyway. It seems that the existing code could cause deadlocks.
  • kjs/Shell.cpp: (functionGC): (main): (jscmain): The test tool uses a per-thread context, so no real locking is required.
  • kjs/collector.h: (KJS::Heap::setGCProtectNeedsLocking): Optionally protect m_protectedValues access with a per-heap mutex. This is only needed for WebCore Database code, which violates the "no data migration between threads" by using ProtectedPtr on a background thread. (KJS::Heap::isShared): Keep a shared flag here, as well.
  • kjs/protect.h: (KJS::::ProtectedPtr): (KJS::::~ProtectedPtr): (KJS::::operator): (KJS::operator==): (KJS::operator!=): ProtectedPtr is ony used from WebCore, so it doesn't need to take JSLock. An assertion in Heap::protect/unprotect guards agains possible future unlocked uses of ProtectedPtr in JSC.
  • kjs/collector.cpp: (KJS::Heap::Heap): Initialize m_isShared. (KJS::Heap::~Heap): No need to lock for real during destruction, but must keep assertions in sweep() working. (KJS::destroyRegisteredThread): Registered thread list is only accessed for shared heap, so locking is always needed here. (KJS::Heap::registerThread): Ditto. (KJS::Heap::markStackObjectsConservatively): Use m_isShared instead of comparing to a shared instance for a small speedup. (KJS::Heap::setGCProtectNeedsLocking): Create m_protectedValuesMutex. There is currently no way to undo this - and ideally, Database code will be fixed to lo longer require this quirk. (KJS::Heap::protect): Take m_protectedValuesMutex (if it exists) while accessing m_protectedValues. (KJS::Heap::unprotect): Ditto. (KJS::Heap::markProtectedObjects): Ditto. (KJS::Heap::protectedGlobalObjectCount): Ditto. (KJS::Heap::protectedObjectCount): Ditto. (KJS::Heap::protectedObjectTypeCounts): Ditto.
  • kjs/ustring.cpp:
  • kjs/ustring.h: Don't include JSLock.h, which is no longer used here. As a result, an explicit include had to be added to many files in JavaScriptGlue, WebCore and WebKit.
  • kjs/JSGlobalObject.cpp: (KJS::JSGlobalObject::init):
  • API/JSCallbackConstructor.cpp: (KJS::constructJSCallback):
  • API/JSCallbackFunction.cpp: (KJS::JSCallbackFunction::call):
  • API/JSCallbackObjectFunctions.h: (KJS::::init): (KJS::::getOwnPropertySlot): (KJS::::put): (KJS::::deleteProperty): (KJS::::construct): (KJS::::hasInstance): (KJS::::call): (KJS::::getPropertyNames): (KJS::::toNumber): (KJS::::toString): (KJS::::staticValueGetter): (KJS::::callbackGetter):
  • API/JSContextRef.cpp: (JSGlobalContextCreate): (JSGlobalContextRetain): (JSGlobalContextRelease):
  • API/JSValueRef.cpp: (JSValueIsEqual): (JSValueIsStrictEqual): (JSValueIsInstanceOfConstructor): (JSValueMakeNumber): (JSValueMakeString): (JSValueToNumber): (JSValueToStringCopy): (JSValueToObject): (JSValueProtect): (JSValueUnprotect):
  • JavaScriptCore.exp:
  • kjs/PropertyNameArray.h: (KJS::PropertyNameArray::globalData):
  • kjs/interpreter.cpp: (KJS::Interpreter::checkSyntax): (KJS::Interpreter::evaluate): Pass a parameter to JSLock/JSLock::DropAllLocks to decide whether the lock needs to be taken.
  • Property svn:eol-style set to native
File size: 7.3 KB
Line 
1// -*- mode: c++; c-basic-offset: 4 -*-
2/*
3 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "JSValueRef.h"
29
30#include <wtf/Platform.h>
31#include "APICast.h"
32#include "JSCallbackObject.h"
33
34#include <kjs/JSType.h>
35#include <kjs/JSGlobalObject.h>
36#include <kjs/JSString.h>
37#include <kjs/operations.h>
38#include <kjs/protect.h>
39#include <kjs/ustring.h>
40#include <kjs/JSValue.h>
41
42#include <wtf/Assertions.h>
43
44#include <algorithm> // for std::min
45
46JSType JSValueGetType(JSContextRef, JSValueRef value)
47{
48 KJS::JSValue* jsValue = toJS(value);
49 switch (jsValue->type()) {
50 case KJS::UndefinedType:
51 return kJSTypeUndefined;
52 case KJS::NullType:
53 return kJSTypeNull;
54 case KJS::BooleanType:
55 return kJSTypeBoolean;
56 case KJS::NumberType:
57 return kJSTypeNumber;
58 case KJS::StringType:
59 return kJSTypeString;
60 case KJS::ObjectType:
61 return kJSTypeObject;
62 default:
63 ASSERT(!"JSValueGetType: unknown type code.\n");
64 return kJSTypeUndefined;
65 }
66}
67
68using namespace KJS; // placed here to avoid conflict between KJS::JSType and JSType, above.
69
70bool JSValueIsUndefined(JSContextRef, JSValueRef value)
71{
72 JSValue* jsValue = toJS(value);
73 return jsValue->isUndefined();
74}
75
76bool JSValueIsNull(JSContextRef, JSValueRef value)
77{
78 JSValue* jsValue = toJS(value);
79 return jsValue->isNull();
80}
81
82bool JSValueIsBoolean(JSContextRef, JSValueRef value)
83{
84 JSValue* jsValue = toJS(value);
85 return jsValue->isBoolean();
86}
87
88bool JSValueIsNumber(JSContextRef, JSValueRef value)
89{
90 JSValue* jsValue = toJS(value);
91 return jsValue->isNumber();
92}
93
94bool JSValueIsString(JSContextRef, JSValueRef value)
95{
96 JSValue* jsValue = toJS(value);
97 return jsValue->isString();
98}
99
100bool JSValueIsObject(JSContextRef, JSValueRef value)
101{
102 JSValue* jsValue = toJS(value);
103 return jsValue->isObject();
104}
105
106bool JSValueIsObjectOfClass(JSContextRef, JSValueRef value, JSClassRef jsClass)
107{
108 JSValue* jsValue = toJS(value);
109
110 if (JSObject* o = jsValue->getObject()) {
111 if (o->inherits(&JSCallbackObject<JSGlobalObject>::info))
112 return static_cast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass);
113 else if (o->inherits(&JSCallbackObject<JSObject>::info))
114 return static_cast<JSCallbackObject<JSObject>*>(o)->inherits(jsClass);
115 }
116 return false;
117}
118
119bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception)
120{
121 ExecState* exec = toJS(ctx);
122 JSLock lock(exec);
123
124 JSValue* jsA = toJS(a);
125 JSValue* jsB = toJS(b);
126
127 bool result = equal(exec, jsA, jsB); // false if an exception is thrown
128 if (exec->hadException()) {
129 if (exception)
130 *exception = toRef(exec->exception());
131 exec->clearException();
132 }
133 return result;
134}
135
136bool JSValueIsStrictEqual(JSContextRef, JSValueRef a, JSValueRef b)
137{
138 JSValue* jsA = toJS(a);
139 JSValue* jsB = toJS(b);
140
141 bool result = strictEqual(jsA, jsB);
142 return result;
143}
144
145bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception)
146{
147 ExecState* exec = toJS(ctx);
148 JSLock lock(exec);
149
150 JSValue* jsValue = toJS(value);
151 JSObject* jsConstructor = toJS(constructor);
152 if (!jsConstructor->implementsHasInstance())
153 return false;
154 bool result = jsConstructor->hasInstance(exec, jsValue); // false if an exception is thrown
155 if (exec->hadException()) {
156 if (exception)
157 *exception = toRef(exec->exception());
158 exec->clearException();
159 }
160 return result;
161}
162
163JSValueRef JSValueMakeUndefined(JSContextRef)
164{
165 return toRef(jsUndefined());
166}
167
168JSValueRef JSValueMakeNull(JSContextRef)
169{
170 return toRef(jsNull());
171}
172
173JSValueRef JSValueMakeBoolean(JSContextRef, bool value)
174{
175 return toRef(jsBoolean(value));
176}
177
178JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
179{
180 ExecState* exec = toJS(ctx);
181 JSLock lock(exec);
182
183 return toRef(jsNumber(exec, value));
184}
185
186JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
187{
188 ExecState* exec = toJS(ctx);
189 JSLock lock(exec);
190
191 UString::Rep* rep = toJS(string);
192 return toRef(jsString(exec, UString(rep)));
193}
194
195bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
196{
197 ExecState* exec = toJS(ctx);
198 JSValue* jsValue = toJS(value);
199 return jsValue->toBoolean(exec);
200}
201
202double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
203{
204 ExecState* exec = toJS(ctx);
205 JSLock lock(exec);
206
207 JSValue* jsValue = toJS(value);
208
209 double number = jsValue->toNumber(exec);
210 if (exec->hadException()) {
211 if (exception)
212 *exception = toRef(exec->exception());
213 exec->clearException();
214 number = NaN;
215 }
216 return number;
217}
218
219JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
220{
221 ExecState* exec = toJS(ctx);
222 JSLock lock(exec);
223
224 JSValue* jsValue = toJS(value);
225
226 JSStringRef stringRef = toRef(jsValue->toString(exec).rep()->ref());
227 if (exec->hadException()) {
228 if (exception)
229 *exception = toRef(exec->exception());
230 exec->clearException();
231 stringRef = 0;
232 }
233 return stringRef;
234}
235
236JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
237{
238 ExecState* exec = toJS(ctx);
239 JSLock lock(exec);
240
241 JSValue* jsValue = toJS(value);
242
243 JSObjectRef objectRef = toRef(jsValue->toObject(exec));
244 if (exec->hadException()) {
245 if (exception)
246 *exception = toRef(exec->exception());
247 exec->clearException();
248 objectRef = 0;
249 }
250 return objectRef;
251}
252
253void JSValueProtect(JSContextRef ctx, JSValueRef value)
254{
255 ExecState* exec = toJS(ctx);
256 JSLock lock(exec);
257
258 JSValue* jsValue = toJS(value);
259 gcProtect(jsValue);
260}
261
262void JSValueUnprotect(JSContextRef ctx, JSValueRef value)
263{
264 ExecState* exec = toJS(ctx);
265 JSLock lock(exec);
266
267 JSValue* jsValue = toJS(value);
268 gcUnprotect(jsValue);
269}
Note: See TracBrowser for help on using the repository browser.