source: webkit/trunk/JavaScriptCore/runtime/JSCell.h@ 57055

Last change on this file since 57055 was 57019, checked in by [email protected], 15 years ago

Inlined toThisString and toThisJSString to avoid virtual function call overhead
https://bugs.webkit.org/show_bug.cgi?id=37039

Reviewed by Oliver Hunt.

Maybe a 1% speedup on iBench JS.

  • runtime/JSCell.cpp:
  • runtime/JSCell.h:
  • runtime/JSNumberCell.cpp:
  • runtime/JSNumberCell.h:
  • runtime/JSString.cpp:
  • runtime/JSString.h:
  • runtime/JSValue.h:
  • runtime/JSZombie.h:

(JSC::JSZombie::toThisObject): Nixed the old virtual-type implementation.

  • runtime/JSObject.h:

(JSC::JSValue::toThisString):
(JSC::JSValue::toThisJSString): Added the inlined implementation.

  • Property svn:eol-style set to native
File size: 10.5 KB
Line 
1/*
2 * Copyright (C) 1999-2001 Harri Porten ([email protected])
3 * Copyright (C) 2001 Peter Kelly ([email protected])
4 * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#ifndef JSCell_h
24#define JSCell_h
25
26#include "Collector.h"
27#include "JSImmediate.h"
28#include "JSValue.h"
29#include "MarkStack.h"
30#include "Structure.h"
31#include <wtf/Noncopyable.h>
32
33namespace JSC {
34
35 class JSCell : public NoncopyableCustomAllocated {
36 friend class GetterSetter;
37 friend class Heap;
38 friend class JIT;
39 friend class JSNumberCell;
40 friend class JSObject;
41 friend class JSPropertyNameIterator;
42 friend class JSString;
43 friend class JSValue;
44 friend class JSAPIValueWrapper;
45 friend class JSZombie;
46 friend class JSGlobalData;
47
48 private:
49 explicit JSCell(Structure*);
50 virtual ~JSCell();
51
52 public:
53 static PassRefPtr<Structure> createDummyStructure()
54 {
55 return Structure::create(jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount);
56 }
57
58 // Querying the type.
59#if USE(JSVALUE32)
60 bool isNumber() const;
61#endif
62 bool isString() const;
63 bool isObject() const;
64 virtual bool isGetterSetter() const;
65 bool inherits(const ClassInfo*) const;
66 virtual bool isAPIValueWrapper() const { return false; }
67 virtual bool isPropertyNameIterator() const { return false; }
68
69 Structure* structure() const;
70
71 // Extracting the value.
72 bool getString(ExecState* exec, UString&) const;
73 UString getString(ExecState* exec) const; // null string if not a string
74 JSObject* getObject(); // NULL if not an object
75 const JSObject* getObject() const; // NULL if not an object
76
77 virtual CallType getCallData(CallData&);
78 virtual ConstructType getConstructData(ConstructData&);
79
80 // Extracting integer values.
81 // FIXME: remove these methods, can check isNumberCell in JSValue && then call asNumberCell::*.
82 virtual bool getUInt32(uint32_t&) const;
83
84 // Basic conversions.
85 virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
86 virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
87 virtual bool toBoolean(ExecState*) const;
88 virtual double toNumber(ExecState*) const;
89 virtual UString toString(ExecState*) const;
90 virtual JSObject* toObject(ExecState*) const;
91
92 // Garbage collection.
93 void* operator new(size_t, ExecState*);
94 void* operator new(size_t, JSGlobalData*);
95 void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
96
97 virtual void markChildren(MarkStack&);
98#if ENABLE(JSC_ZOMBIES)
99 virtual bool isZombie() const { return false; }
100#endif
101
102 // Object operations, with the toObject operation included.
103 virtual const ClassInfo* classInfo() const;
104 virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
105 virtual void put(ExecState*, unsigned propertyName, JSValue);
106 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
107 virtual bool deleteProperty(ExecState*, unsigned propertyName);
108
109 virtual JSObject* toThisObject(ExecState*) const;
110 virtual JSValue getJSNumber();
111 void* vptr() { return *reinterpret_cast<void**>(this); }
112 void setVPtr(void* vptr) { *reinterpret_cast<void**>(this) = vptr; }
113
114 protected:
115 static const unsigned AnonymousSlotCount = 0;
116
117 private:
118 // Base implementation; for non-object classes implements getPropertySlot.
119 bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
120 virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
121 virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
122
123 Structure* m_structure;
124 };
125
126 inline JSCell::JSCell(Structure* structure)
127 : m_structure(structure)
128 {
129 }
130
131 inline JSCell::~JSCell()
132 {
133 }
134
135#if USE(JSVALUE32)
136 inline bool JSCell::isNumber() const
137 {
138 return m_structure->typeInfo().type() == NumberType;
139 }
140#endif
141
142 inline bool JSCell::isObject() const
143 {
144 return m_structure->typeInfo().type() == ObjectType;
145 }
146
147 inline bool JSCell::isString() const
148 {
149 return m_structure->typeInfo().type() == StringType;
150 }
151
152 inline Structure* JSCell::structure() const
153 {
154 return m_structure;
155 }
156
157 inline void JSCell::markChildren(MarkStack&)
158 {
159 }
160
161 inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
162 {
163 return globalData->heap.allocate(size);
164 }
165
166 inline void* JSCell::operator new(size_t size, ExecState* exec)
167 {
168 return exec->heap()->allocate(size);
169 }
170
171 // --- JSValue inlines ----------------------------
172
173 inline bool JSValue::isString() const
174 {
175 return isCell() && asCell()->isString();
176 }
177
178 inline bool JSValue::isGetterSetter() const
179 {
180 return isCell() && asCell()->isGetterSetter();
181 }
182
183 inline bool JSValue::isObject() const
184 {
185 return isCell() && asCell()->isObject();
186 }
187
188 inline bool JSValue::getString(ExecState* exec, UString& s) const
189 {
190 return isCell() && asCell()->getString(exec, s);
191 }
192
193 inline UString JSValue::getString(ExecState* exec) const
194 {
195 return isCell() ? asCell()->getString(exec) : UString();
196 }
197
198 inline JSObject* JSValue::getObject() const
199 {
200 return isCell() ? asCell()->getObject() : 0;
201 }
202
203 inline CallType JSValue::getCallData(CallData& callData)
204 {
205 return isCell() ? asCell()->getCallData(callData) : CallTypeNone;
206 }
207
208 inline ConstructType JSValue::getConstructData(ConstructData& constructData)
209 {
210 return isCell() ? asCell()->getConstructData(constructData) : ConstructTypeNone;
211 }
212
213 ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
214 {
215 if (isInt32()) {
216 int32_t i = asInt32();
217 v = static_cast<uint32_t>(i);
218 return i >= 0;
219 }
220 if (isDouble()) {
221 double d = asDouble();
222 v = static_cast<uint32_t>(d);
223 return v == d;
224 }
225 return false;
226 }
227
228#if !USE(JSVALUE32_64)
229 ALWAYS_INLINE JSCell* JSValue::asCell() const
230 {
231 ASSERT(isCell());
232 return m_ptr;
233 }
234#endif // !USE(JSVALUE32_64)
235
236 inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
237 {
238 return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
239 }
240
241 inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
242 {
243 if (isInt32()) {
244 number = asInt32();
245 value = *this;
246 return true;
247 }
248 if (isDouble()) {
249 number = asDouble();
250 value = *this;
251 return true;
252 }
253 if (isCell())
254 return asCell()->getPrimitiveNumber(exec, number, value);
255 if (isTrue()) {
256 number = 1.0;
257 value = *this;
258 return true;
259 }
260 if (isFalse() || isNull()) {
261 number = 0.0;
262 value = *this;
263 return true;
264 }
265 ASSERT(isUndefined());
266 number = nonInlineNaN();
267 value = *this;
268 return true;
269 }
270
271 inline bool JSValue::toBoolean(ExecState* exec) const
272 {
273 if (isInt32())
274 return asInt32() != 0;
275 if (isDouble())
276 return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN
277 if (isCell())
278 return asCell()->toBoolean(exec);
279 return isTrue(); // false, null, and undefined all convert to false.
280 }
281
282 ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
283 {
284 if (isInt32())
285 return asInt32();
286 if (isDouble())
287 return asDouble();
288 if (isCell())
289 return asCell()->toNumber(exec);
290 if (isTrue())
291 return 1.0;
292 return isUndefined() ? nonInlineNaN() : 0; // null and false both convert to 0.
293 }
294
295 inline bool JSValue::needsThisConversion() const
296 {
297 if (UNLIKELY(!isCell()))
298 return true;
299 return asCell()->structure()->typeInfo().needsThisConversion();
300 }
301
302 inline JSValue JSValue::getJSNumber()
303 {
304 if (isInt32() || isDouble())
305 return *this;
306 if (isCell())
307 return asCell()->getJSNumber();
308 return JSValue();
309 }
310
311 inline JSObject* JSValue::toObject(ExecState* exec) const
312 {
313 return isCell() ? asCell()->toObject(exec) : toObjectSlowCase(exec);
314 }
315
316 inline JSObject* JSValue::toThisObject(ExecState* exec) const
317 {
318 return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec);
319 }
320
321 ALWAYS_INLINE void MarkStack::append(JSCell* cell)
322 {
323 ASSERT(!m_isCheckingForDefaultMarkViolation);
324 ASSERT(cell);
325 if (Heap::isCellMarked(cell))
326 return;
327 Heap::markCell(cell);
328 if (cell->structure()->typeInfo().type() >= CompoundType)
329 m_values.append(cell);
330 }
331
332 ALWAYS_INLINE void MarkStack::append(JSValue value)
333 {
334 ASSERT(value);
335 if (value.isCell())
336 append(value.asCell());
337 }
338
339 inline Heap* Heap::heap(JSValue v)
340 {
341 if (!v.isCell())
342 return 0;
343 return heap(v.asCell());
344 }
345
346 inline Heap* Heap::heap(JSCell* c)
347 {
348 return cellBlock(c)->heap;
349 }
350
351#if ENABLE(JSC_ZOMBIES)
352 inline bool JSValue::isZombie() const
353 {
354 return isCell() && asCell() && asCell()->isZombie();
355 }
356#endif
357} // namespace JSC
358
359#endif // JSCell_h
Note: See TracBrowser for help on using the repository browser.