source: webkit/trunk/JavaScriptCore/runtime/JSNumberCell.h@ 47267

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

Devirtualise marking
https://bugs.webkit.org/show_bug.cgi?id=28294

Reviewed by Maciej Stachowiak.

Add a bit to TypeInfo to indicate that an object uses the standard
JSObject::markChildren method. This allows us to devirtualise marking
of most objects (though a branch is still needed). We also add a branch
to identify arrays thus devirtualising marking in that case as well.

In order to make the best use of this devirtualisation I've also reworked
the MarkStack::drain() logic to make the iteration more efficient.

  • Property svn:eol-style set to native
File size: 9.1 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 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 JSNumberCell_h
24#define JSNumberCell_h
25
26#include "CallFrame.h"
27#include "JSCell.h"
28#include "JSImmediate.h"
29#include "Collector.h"
30#include "UString.h"
31#include <stddef.h> // for size_t
32
33namespace JSC {
34
35 extern const double NaN;
36 extern const double Inf;
37
38#if USE(JSVALUE32)
39 JSValue jsNumberCell(ExecState*, double);
40
41 class Identifier;
42 class JSCell;
43 class JSObject;
44 class JSString;
45 class PropertySlot;
46
47 struct ClassInfo;
48 struct Instruction;
49
50 class JSNumberCell : public JSCell {
51 friend class JIT;
52 friend JSValue jsNumberCell(JSGlobalData*, double);
53 friend JSValue jsNumberCell(ExecState*, double);
54
55 public:
56 double value() const { return m_value; }
57
58 virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
59 virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
60 virtual bool toBoolean(ExecState*) const;
61 virtual double toNumber(ExecState*) const;
62 virtual UString toString(ExecState*) const;
63 virtual JSObject* toObject(ExecState*) const;
64
65 virtual UString toThisString(ExecState*) const;
66 virtual JSObject* toThisObject(ExecState*) const;
67 virtual JSValue getJSNumber();
68
69 void* operator new(size_t size, ExecState* exec)
70 {
71 #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
72 return exec->heap()->inlineAllocateNumber(size);
73 #else
74 return exec->heap()->allocateNumber(size);
75 #endif
76 }
77
78 void* operator new(size_t size, JSGlobalData* globalData)
79 {
80 #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE
81 return globalData->heap.inlineAllocateNumber(size);
82 #else
83 return globalData->heap.allocateNumber(size);
84 #endif
85 }
86
87 static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion | HasDefaultMark)); }
88
89 private:
90 JSNumberCell(JSGlobalData* globalData, double value)
91 : JSCell(globalData->numberStructure.get())
92 , m_value(value)
93 {
94 }
95
96 JSNumberCell(ExecState* exec, double value)
97 : JSCell(exec->globalData().numberStructure.get())
98 , m_value(value)
99 {
100 }
101
102 virtual bool getUInt32(uint32_t&) const;
103
104 double m_value;
105 };
106
107 JSValue jsNumberCell(JSGlobalData*, double);
108
109 inline bool isNumberCell(JSValue v)
110 {
111 return v.isCell() && v.asCell()->isNumber();
112 }
113
114 inline JSNumberCell* asNumberCell(JSValue v)
115 {
116 ASSERT(isNumberCell(v));
117 return static_cast<JSNumberCell*>(v.asCell());
118 }
119
120 inline JSValue::JSValue(ExecState* exec, double d)
121 {
122 JSValue v = JSImmediate::from(d);
123 *this = v ? v : jsNumberCell(exec, d);
124 }
125
126 inline JSValue::JSValue(ExecState* exec, int i)
127 {
128 JSValue v = JSImmediate::from(i);
129 *this = v ? v : jsNumberCell(exec, i);
130 }
131
132 inline JSValue::JSValue(ExecState* exec, unsigned i)
133 {
134 JSValue v = JSImmediate::from(i);
135 *this = v ? v : jsNumberCell(exec, i);
136 }
137
138 inline JSValue::JSValue(ExecState* exec, long i)
139 {
140 JSValue v = JSImmediate::from(i);
141 *this = v ? v : jsNumberCell(exec, i);
142 }
143
144 inline JSValue::JSValue(ExecState* exec, unsigned long i)
145 {
146 JSValue v = JSImmediate::from(i);
147 *this = v ? v : jsNumberCell(exec, i);
148 }
149
150 inline JSValue::JSValue(ExecState* exec, long long i)
151 {
152 JSValue v = JSImmediate::from(i);
153 *this = v ? v : jsNumberCell(exec, static_cast<double>(i));
154 }
155
156 inline JSValue::JSValue(ExecState* exec, unsigned long long i)
157 {
158 JSValue v = JSImmediate::from(i);
159 *this = v ? v : jsNumberCell(exec, static_cast<double>(i));
160 }
161
162 inline JSValue::JSValue(JSGlobalData* globalData, double d)
163 {
164 JSValue v = JSImmediate::from(d);
165 *this = v ? v : jsNumberCell(globalData, d);
166 }
167
168 inline JSValue::JSValue(JSGlobalData* globalData, int i)
169 {
170 JSValue v = JSImmediate::from(i);
171 *this = v ? v : jsNumberCell(globalData, i);
172 }
173
174 inline JSValue::JSValue(JSGlobalData* globalData, unsigned i)
175 {
176 JSValue v = JSImmediate::from(i);
177 *this = v ? v : jsNumberCell(globalData, i);
178 }
179
180 inline bool JSValue::isDouble() const
181 {
182 return isNumberCell(asValue());
183 }
184
185 inline double JSValue::asDouble() const
186 {
187 return asNumberCell(asValue())->value();
188 }
189
190 inline bool JSValue::isNumber() const
191 {
192 return JSImmediate::isNumber(asValue()) || isDouble();
193 }
194
195 inline double JSValue::uncheckedGetNumber() const
196 {
197 ASSERT(isNumber());
198 return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asDouble();
199 }
200
201#endif // USE(JSVALUE32)
202
203#if USE(JSVALUE64)
204 inline JSValue::JSValue(ExecState*, double d)
205 {
206 JSValue v = JSImmediate::from(d);
207 ASSERT(v);
208 *this = v;
209 }
210
211 inline JSValue::JSValue(ExecState*, int i)
212 {
213 JSValue v = JSImmediate::from(i);
214 ASSERT(v);
215 *this = v;
216 }
217
218 inline JSValue::JSValue(ExecState*, unsigned i)
219 {
220 JSValue v = JSImmediate::from(i);
221 ASSERT(v);
222 *this = v;
223 }
224
225 inline JSValue::JSValue(ExecState*, long i)
226 {
227 JSValue v = JSImmediate::from(i);
228 ASSERT(v);
229 *this = v;
230 }
231
232 inline JSValue::JSValue(ExecState*, unsigned long i)
233 {
234 JSValue v = JSImmediate::from(i);
235 ASSERT(v);
236 *this = v;
237 }
238
239 inline JSValue::JSValue(ExecState*, long long i)
240 {
241 JSValue v = JSImmediate::from(static_cast<double>(i));
242 ASSERT(v);
243 *this = v;
244 }
245
246 inline JSValue::JSValue(ExecState*, unsigned long long i)
247 {
248 JSValue v = JSImmediate::from(static_cast<double>(i));
249 ASSERT(v);
250 *this = v;
251 }
252
253 inline JSValue::JSValue(JSGlobalData*, double d)
254 {
255 JSValue v = JSImmediate::from(d);
256 ASSERT(v);
257 *this = v;
258 }
259
260 inline JSValue::JSValue(JSGlobalData*, int i)
261 {
262 JSValue v = JSImmediate::from(i);
263 ASSERT(v);
264 *this = v;
265 }
266
267 inline JSValue::JSValue(JSGlobalData*, unsigned i)
268 {
269 JSValue v = JSImmediate::from(i);
270 ASSERT(v);
271 *this = v;
272 }
273
274 inline bool JSValue::isDouble() const
275 {
276 return JSImmediate::isDouble(asValue());
277 }
278
279 inline double JSValue::asDouble() const
280 {
281 return JSImmediate::doubleValue(asValue());
282 }
283
284 inline bool JSValue::isNumber() const
285 {
286 return JSImmediate::isNumber(asValue());
287 }
288
289 inline double JSValue::uncheckedGetNumber() const
290 {
291 ASSERT(isNumber());
292 return JSImmediate::toDouble(asValue());
293 }
294
295#endif // USE(JSVALUE64)
296
297#if USE(JSVALUE32) || USE(JSVALUE64)
298
299 inline JSValue::JSValue(ExecState*, char i)
300 {
301 ASSERT(JSImmediate::from(i));
302 *this = JSImmediate::from(i);
303 }
304
305 inline JSValue::JSValue(ExecState*, unsigned char i)
306 {
307 ASSERT(JSImmediate::from(i));
308 *this = JSImmediate::from(i);
309 }
310
311 inline JSValue::JSValue(ExecState*, short i)
312 {
313 ASSERT(JSImmediate::from(i));
314 *this = JSImmediate::from(i);
315 }
316
317 inline JSValue::JSValue(ExecState*, unsigned short i)
318 {
319 ASSERT(JSImmediate::from(i));
320 *this = JSImmediate::from(i);
321 }
322
323 inline JSValue jsNaN(ExecState* exec)
324 {
325 return jsNumber(exec, NaN);
326 }
327
328 inline JSValue jsNaN(JSGlobalData* globalData)
329 {
330 return jsNumber(globalData, NaN);
331 }
332
333 // --- JSValue inlines ----------------------------
334
335 ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
336 {
337 return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec));
338 }
339
340 inline bool JSValue::getNumber(double &result) const
341 {
342 if (isInt32())
343 result = asInt32();
344 else if (LIKELY(isDouble()))
345 result = asDouble();
346 else {
347 ASSERT(!isNumber());
348 return false;
349 }
350 return true;
351 }
352
353#endif // USE(JSVALUE32) || USE(JSVALUE64)
354
355} // namespace JSC
356
357#endif // JSNumberCell_h
Note: See TracBrowser for help on using the repository browser.