source: webkit/trunk/JavaScriptCore/runtime/JSImmediate.h@ 43424

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

JavaScriptCore:

2009-05-02 Geoffrey Garen <[email protected]>

Reviewed by Sam Weinig.

Simplified null-ish JSValues.


Replaced calls to noValue() with calls to JSValue() (which is what
noValue() returned). Removed noValue().


Replaced almost all uses of jsImpossibleValue() with uses of JSValue().
Its one remaining use is for construction of hash table deleted values.
For that specific task, I made a new, private constructor with a special
tag. Removed jsImpossibleValue().


Removed "JSValue()" initialiazers, since default construction happens...
by default.

  • API/JSCallbackObjectFunctions.h: (JSC::::call):
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitLoad):
  • bytecompiler/BytecodeGenerator.h:
  • debugger/DebuggerCallFrame.cpp: (JSC::DebuggerCallFrame::evaluate):
  • debugger/DebuggerCallFrame.h: (JSC::DebuggerCallFrame::DebuggerCallFrame):
  • interpreter/CallFrame.h: (JSC::ExecState::clearException):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::privateExecute): (JSC::Interpreter::retrieveLastCaller):
  • interpreter/Register.h: (JSC::Register::Register):
  • jit/JITCall.cpp: (JSC::JIT::unlinkCall): (JSC::JIT::compileOpCallInitializeCallFrame): (JSC::JIT::compileOpCall):
  • jit/JITStubs.cpp: (JSC::JITStubs::cti_op_call_eval): (JSC::JITStubs::cti_vm_throw):
  • profiler/Profiler.cpp: (JSC::Profiler::willExecute): (JSC::Profiler::didExecute):
  • runtime/ArrayPrototype.cpp: (JSC::getProperty):
  • runtime/Completion.cpp: (JSC::evaluate):
  • runtime/Completion.h: (JSC::Completion::Completion):
  • runtime/GetterSetter.cpp: (JSC::GetterSetter::getPrimitiveNumber):
  • runtime/JSArray.cpp: (JSC::JSArray::putSlowCase): (JSC::JSArray::deleteProperty): (JSC::JSArray::increaseVectorLength): (JSC::JSArray::setLength): (JSC::JSArray::pop): (JSC::JSArray::sort): (JSC::JSArray::compactForSorting):
  • runtime/JSCell.cpp: (JSC::JSCell::getJSNumber):
  • runtime/JSCell.h: (JSC::JSValue::getJSNumber):
  • runtime/JSGlobalData.cpp: (JSC::JSGlobalData::JSGlobalData):
  • runtime/JSImmediate.h: (JSC::JSImmediate::fromNumberOutsideIntegerRange): (JSC::JSImmediate::from):
  • runtime/JSNumberCell.cpp: (JSC::jsNumberCell):
  • runtime/JSObject.cpp: (JSC::callDefaultValueFunction):
  • runtime/JSObject.h: (JSC::JSObject::getDirect):
  • runtime/JSPropertyNameIterator.cpp: (JSC::JSPropertyNameIterator::toPrimitive):
  • runtime/JSPropertyNameIterator.h: (JSC::JSPropertyNameIterator::next):
  • runtime/JSValue.h: (JSC::JSValue::): (JSC::JSValueHashTraits::constructDeletedValue): (JSC::JSValueHashTraits::isDeletedValue): (JSC::JSValue::JSValue):
  • runtime/JSWrapperObject.h: (JSC::JSWrapperObject::JSWrapperObject):
  • runtime/Operations.h: (JSC::resolveBase):
  • runtime/PropertySlot.h: (JSC::PropertySlot::clearBase): (JSC::PropertySlot::clearValue):

WebCore:

2009-05-02 Geoffrey Garen <[email protected]>

Reviewed by Sam Weinig.

Simplified null-ish JSValues.


Replaced calls to noValue() with calls to JSValue() (which is what
noValue() returned). Removed noValue().


Removed "JSValue()" initialiazers, since default construction happens...
by default.

  • bindings/js/JSDOMBinding.cpp: (WebCore::setDOMException):
  • bindings/js/JSDOMWindowCustom.cpp: (WebCore::JSDOMWindow::open): (WebCore::JSDOMWindow::showModalDialog):
  • bindings/js/JSEventListener.cpp: (WebCore::JSEventListener::handleEvent):
  • bindings/js/JSJavaScriptCallFrameCustom.cpp: (WebCore::JSJavaScriptCallFrame::evaluate):
  • bindings/js/JSSQLResultSetRowListCustom.cpp: (WebCore::JSSQLResultSetRowList::item):
  • bindings/js/ScriptController.cpp: (WebCore::ScriptController::evaluate):
  • bindings/js/ScriptValue.h: (WebCore::ScriptValue::ScriptValue): (WebCore::ScriptValue::hasNoValue):
  • bindings/js/WorkerScriptController.cpp: (WebCore::WorkerScriptController::evaluate):
  • bridge/jni/jni_instance.cpp: (JavaInstance::invokeMethod):
  • bridge/jni/jni_runtime.cpp: (JavaField::dispatchValueFromInstance): (JavaField::dispatchSetValueToInstance):
  • bridge/runtime.h: (JSC::Bindings::Instance::invokeConstruct):

WebKit/mac:

2009-05-02 Geoffrey Garen <[email protected]>

Reviewed by Sam Weinig.

Simplified null-ish JSValues.


Replaced calls to noValue() with calls to JSValue() (which is what
noValue() returned). Removed noValue().


Removed "JSValue()" initialiazers, since default construction happens...
by default.

  • WebView/WebScriptDebugDelegate.mm: (-[WebScriptCallFrame evaluateWebScript:]):
  • Property svn:eol-style set to native
File size: 27.5 KB
Line 
1/*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 Alexey Proskuryakov ([email protected])
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22#ifndef JSImmediate_h
23#define JSImmediate_h
24
25#include <wtf/Assertions.h>
26#include <wtf/AlwaysInline.h>
27#include <wtf/MathExtras.h>
28#include <wtf/StdLibExtras.h>
29#include "JSValue.h"
30#include <limits>
31#include <limits.h>
32#include <stdarg.h>
33#include <stdint.h>
34#include <stdlib.h>
35
36namespace JSC {
37
38 class ExecState;
39 class JSCell;
40 class JSFastMath;
41 class JSGlobalData;
42 class JSObject;
43 class UString;
44
45#if USE(ALTERNATE_JSIMMEDIATE)
46 inline intptr_t reinterpretDoubleToIntptr(double value)
47 {
48 return WTF::bitwise_cast<intptr_t>(value);
49 }
50
51 inline double reinterpretIntptrToDouble(intptr_t value)
52 {
53 return WTF::bitwise_cast<double>(value);
54 }
55#endif
56
57 /*
58 * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
59 * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging
60 * because allocator alignment guarantees they will be 00 in cell pointers.
61 *
62 * For example, on a 32 bit system:
63 *
64 * JSCell*: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00
65 * [ high 30 bits: pointer address ] [ low 2 bits -- always 0 ]
66 * JSImmediate: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX TT
67 * [ high 30 bits: 'payload' ] [ low 2 bits -- tag ]
68 *
69 * Where the bottom two bits are non-zero they either indicate that the immediate is a 31 bit signed
70 * integer, or they mark the value as being an immediate of a type other than integer, with a secondary
71 * tag used to indicate the exact type.
72 *
73 * Where the lowest bit is set (TT is equal to 01 or 11) the high 31 bits form a 31 bit signed int value.
74 * Where TT is equal to 10 this indicates this is a type of immediate other than an integer, and the next
75 * two bits will form an extended tag.
76 *
77 * 31 bit signed int: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X1
78 * [ high 30 bits of the value ] [ high bit part of value ]
79 * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY ZZ 10
80 * [ extended 'payload' ] [ extended tag ] [ tag 'other' ]
81 *
82 * Where the first bit of the extended tag is set this flags the value as being a boolean, and the following
83 * bit would flag the value as undefined. If neither bits are set, the value is null.
84 *
85 * Other: YYYYYYYYYYYYYYYYYYYYYYYYYYYY UB 10
86 * [ extended 'payload' ] [ undefined | bool ] [ tag 'other' ]
87 *
88 * For boolean value the lowest bit in the payload holds the value of the bool, all remaining bits are zero.
89 * For undefined or null immediates the payload is zero.
90 *
91 * Boolean: 000000000000000000000000000V 01 10
92 * [ boolean value ] [ bool ] [ tag 'other' ]
93 * Undefined: 0000000000000000000000000000 10 10
94 * [ zero ] [ undefined ] [ tag 'other' ]
95 * Null: 0000000000000000000000000000 00 10
96 * [ zero ] [ zero ] [ tag 'other' ]
97 */
98
99 /*
100 * On 64-bit platforms, we support an alternative encoding form for immediates, if
101 * USE(ALTERNATE_JSIMMEDIATE) is defined. When this format is used, double precision
102 * floating point values may also be encoded as JSImmediates.
103 *
104 * The encoding makes use of unused NaN space in the IEEE754 representation. Any value
105 * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values
106 * can encode a 51-bit payload. Hardware produced and C-library payloads typically
107 * have a payload of zero. We assume that non-zero payloads are available to encode
108 * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are
109 * all set represents a NaN with a non-zero payload, we can use this space in the NaN
110 * ranges to encode other values (however there are also other ranges of NaN space that
111 * could have been selected). This range of NaN space is represented by 64-bit numbers
112 * begining with the 16-bit hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no
113 * valid double-precision numbers will begin fall in these ranges.
114 *
115 * The scheme we have implemented encodes double precision values by adding 2^48 to the
116 * 64-bit integer representation of the number. After this manipulation, no encoded
117 * double-precision value will begin with the pattern 0x0000 or 0xFFFF.
118 *
119 * The top 16-bits denote the type of the encoded JSImmediate:
120 *
121 * Pointer: 0000:PPPP:PPPP:PPPP
122 * 0001:****:****:****
123 * Double:{ ...
124 * FFFE:****:****:****
125 * Integer: FFFF:0000:IIII:IIII
126 *
127 * 32-bit signed integers are marked with the 16-bit tag 0xFFFF. The tag 0x0000
128 * denotes a pointer, or another form of tagged immediate. Boolean, null and undefined
129 * values are encoded in the same manner as the default format.
130 */
131
132 class JSImmediate {
133 private:
134 friend class JIT;
135 friend class JSValue;
136 friend class JSFastMath;
137 friend JSValue jsNumber(ExecState* exec, double d);
138 friend JSValue jsNumber(ExecState*, char i);
139 friend JSValue jsNumber(ExecState*, unsigned char i);
140 friend JSValue jsNumber(ExecState*, short i);
141 friend JSValue jsNumber(ExecState*, unsigned short i);
142 friend JSValue jsNumber(ExecState* exec, int i);
143 friend JSValue jsNumber(ExecState* exec, unsigned i);
144 friend JSValue jsNumber(ExecState* exec, long i);
145 friend JSValue jsNumber(ExecState* exec, unsigned long i);
146 friend JSValue jsNumber(ExecState* exec, long long i);
147 friend JSValue jsNumber(ExecState* exec, unsigned long long i);
148 friend JSValue jsNumber(JSGlobalData* globalData, double d);
149 friend JSValue jsNumber(JSGlobalData* globalData, short i);
150 friend JSValue jsNumber(JSGlobalData* globalData, unsigned short i);
151 friend JSValue jsNumber(JSGlobalData* globalData, int i);
152 friend JSValue jsNumber(JSGlobalData* globalData, unsigned i);
153 friend JSValue jsNumber(JSGlobalData* globalData, long i);
154 friend JSValue jsNumber(JSGlobalData* globalData, unsigned long i);
155 friend JSValue jsNumber(JSGlobalData* globalData, long long i);
156 friend JSValue jsNumber(JSGlobalData* globalData, unsigned long long i);
157
158#if USE(ALTERNATE_JSIMMEDIATE)
159 // If all bits in the mask are set, this indicates an integer number,
160 // if any but not all are set this value is a double precision number.
161 static const intptr_t TagTypeNumber = 0xffff000000000000ll;
162 // This value is 2^48, used to encode doubles such that the encoded value will begin
163 // with a 16-bit pattern within the range 0x0001..0xFFFE.
164 static const intptr_t DoubleEncodeOffset = 0x1000000000000ll;
165#else
166 static const intptr_t TagTypeNumber = 0x1; // bottom bit set indicates integer, this dominates the following bit
167#endif
168 static const intptr_t TagBitTypeOther = 0x2; // second bit set indicates immediate other than an integer
169 static const intptr_t TagMask = TagTypeNumber | TagBitTypeOther;
170
171 static const intptr_t ExtendedTagMask = 0xC; // extended tag holds a further two bits
172 static const intptr_t ExtendedTagBitBool = 0x4;
173 static const intptr_t ExtendedTagBitUndefined = 0x8;
174
175 static const intptr_t FullTagTypeMask = TagMask | ExtendedTagMask;
176 static const intptr_t FullTagTypeBool = TagBitTypeOther | ExtendedTagBitBool;
177 static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined;
178 static const intptr_t FullTagTypeNull = TagBitTypeOther;
179
180#if USE(ALTERNATE_JSIMMEDIATE)
181 static const int32_t IntegerPayloadShift = 0;
182#else
183 static const int32_t IntegerPayloadShift = 1;
184#endif
185 static const int32_t ExtendedPayloadShift = 4;
186
187 static const intptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift;
188
189 static const int32_t signBit = 0x80000000;
190
191 static ALWAYS_INLINE bool isImmediate(JSValue v)
192 {
193 return rawValue(v) & TagMask;
194 }
195
196 static ALWAYS_INLINE bool isNumber(JSValue v)
197 {
198 return rawValue(v) & TagTypeNumber;
199 }
200
201 static ALWAYS_INLINE bool isIntegerNumber(JSValue v)
202 {
203#if USE(ALTERNATE_JSIMMEDIATE)
204 return (rawValue(v) & TagTypeNumber) == TagTypeNumber;
205#else
206 return isNumber(v);
207#endif
208 }
209
210#if USE(ALTERNATE_JSIMMEDIATE)
211 static ALWAYS_INLINE bool isDoubleNumber(JSValue v)
212 {
213 return isNumber(v) && !isIntegerNumber(v);
214 }
215#endif
216
217 static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValue v)
218 {
219 // A single mask to check for the sign bit and the number tag all at once.
220 return (rawValue(v) & (signBit | TagTypeNumber)) == TagTypeNumber;
221 }
222
223 static ALWAYS_INLINE bool isBoolean(JSValue v)
224 {
225 return (rawValue(v) & FullTagTypeMask) == FullTagTypeBool;
226 }
227
228 static ALWAYS_INLINE bool isUndefinedOrNull(JSValue v)
229 {
230 // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
231 return (rawValue(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull;
232 }
233
234 static JSValue from(char);
235 static JSValue from(signed char);
236 static JSValue from(unsigned char);
237 static JSValue from(short);
238 static JSValue from(unsigned short);
239 static JSValue from(int);
240 static JSValue from(unsigned);
241 static JSValue from(long);
242 static JSValue from(unsigned long);
243 static JSValue from(long long);
244 static JSValue from(unsigned long long);
245 static JSValue from(double);
246
247 static ALWAYS_INLINE bool isEitherImmediate(JSValue v1, JSValue v2)
248 {
249 return (rawValue(v1) | rawValue(v2)) & TagMask;
250 }
251
252 static ALWAYS_INLINE bool areBothImmediate(JSValue v1, JSValue v2)
253 {
254 return isImmediate(v1) & isImmediate(v2);
255 }
256
257 static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValue v1, JSValue v2)
258 {
259#if USE(ALTERNATE_JSIMMEDIATE)
260 return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber;
261#else
262 return rawValue(v1) & rawValue(v2) & TagTypeNumber;
263#endif
264 }
265
266 static double toDouble(JSValue);
267 static bool toBoolean(JSValue);
268 static JSObject* toObject(JSValue, ExecState*);
269 static JSObject* toThisObject(JSValue, ExecState*);
270 static UString toString(JSValue);
271
272 static bool getUInt32(JSValue, uint32_t&);
273 static bool getTruncatedInt32(JSValue, int32_t&);
274 static bool getTruncatedUInt32(JSValue, uint32_t&);
275
276 static int32_t getTruncatedInt32(JSValue);
277 static uint32_t getTruncatedUInt32(JSValue);
278
279 static JSValue trueImmediate();
280 static JSValue falseImmediate();
281 static JSValue undefinedImmediate();
282 static JSValue nullImmediate();
283 static JSValue zeroImmediate();
284 static JSValue oneImmediate();
285
286 static JSObject* prototype(JSValue, ExecState*);
287
288 private:
289#if USE(ALTERNATE_JSIMMEDIATE)
290 static const int minImmediateInt = ((-INT_MAX) - 1);
291 static const int maxImmediateInt = INT_MAX;
292#else
293 static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift;
294 static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift;
295#endif
296 static const unsigned maxImmediateUInt = maxImmediateInt;
297
298 static ALWAYS_INLINE JSValue makeValue(intptr_t integer)
299 {
300 return JSValue::makeImmediate(integer);
301 }
302
303 // With USE(ALTERNATE_JSIMMEDIATE) we want the argument to be zero extended, so the
304 // integer doesn't interfere with the tag bits in the upper word. In the default encoding,
305 // if intptr_t id larger then int32_t we sign extend the value through the upper word.
306#if USE(ALTERNATE_JSIMMEDIATE)
307 static ALWAYS_INLINE JSValue makeInt(uint32_t value)
308#else
309 static ALWAYS_INLINE JSValue makeInt(int32_t value)
310#endif
311 {
312 return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber);
313 }
314
315#if USE(ALTERNATE_JSIMMEDIATE)
316 static ALWAYS_INLINE JSValue makeDouble(double value)
317 {
318 return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset);
319 }
320#endif
321
322 static ALWAYS_INLINE JSValue makeBool(bool b)
323 {
324 return makeValue((static_cast<intptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool);
325 }
326
327 static ALWAYS_INLINE JSValue makeUndefined()
328 {
329 return makeValue(FullTagTypeUndefined);
330 }
331
332 static ALWAYS_INLINE JSValue makeNull()
333 {
334 return makeValue(FullTagTypeNull);
335 }
336
337 template<typename T>
338 static JSValue fromNumberOutsideIntegerRange(T);
339
340#if USE(ALTERNATE_JSIMMEDIATE)
341 static ALWAYS_INLINE double doubleValue(JSValue v)
342 {
343 return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset);
344 }
345#endif
346
347 static ALWAYS_INLINE int32_t intValue(JSValue v)
348 {
349 return static_cast<int32_t>(rawValue(v) >> IntegerPayloadShift);
350 }
351
352 static ALWAYS_INLINE uint32_t uintValue(JSValue v)
353 {
354 return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift);
355 }
356
357 static ALWAYS_INLINE bool boolValue(JSValue v)
358 {
359 return rawValue(v) & ExtendedPayloadBitBoolValue;
360 }
361
362 static ALWAYS_INLINE intptr_t rawValue(JSValue v)
363 {
364 return v.immediateValue();
365 }
366
367 static double nonInlineNaN();
368 };
369
370 ALWAYS_INLINE JSValue JSImmediate::trueImmediate() { return makeBool(true); }
371 ALWAYS_INLINE JSValue JSImmediate::falseImmediate() { return makeBool(false); }
372 ALWAYS_INLINE JSValue JSImmediate::undefinedImmediate() { return makeUndefined(); }
373 ALWAYS_INLINE JSValue JSImmediate::nullImmediate() { return makeNull(); }
374 ALWAYS_INLINE JSValue JSImmediate::zeroImmediate() { return makeInt(0); }
375 ALWAYS_INLINE JSValue JSImmediate::oneImmediate() { return makeInt(1); }
376
377#if USE(ALTERNATE_JSIMMEDIATE)
378 inline bool doubleToBoolean(double value)
379 {
380 return value < 0.0 || value > 0.0;
381 }
382
383 ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v)
384 {
385 ASSERT(isImmediate(v));
386 return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate()
387 : doubleToBoolean(doubleValue(v)) : v == trueImmediate();
388 }
389#else
390 ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v)
391 {
392 ASSERT(isImmediate(v));
393 return isIntegerNumber(v) ? v != zeroImmediate() : v == trueImmediate();
394 }
395#endif
396
397 ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValue v)
398 {
399 // FIXME: should probably be asserting isPositiveIntegerNumber here.
400 ASSERT(isIntegerNumber(v));
401 return intValue(v);
402 }
403
404#if USE(ALTERNATE_JSIMMEDIATE)
405 template<typename T>
406 inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T value)
407 {
408 return makeDouble(static_cast<double>(value));
409 }
410#else
411 template<typename T>
412 inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T)
413 {
414 return JSValue();
415 }
416#endif
417
418 ALWAYS_INLINE JSValue JSImmediate::from(char i)
419 {
420 return makeInt(i);
421 }
422
423 ALWAYS_INLINE JSValue JSImmediate::from(signed char i)
424 {
425 return makeInt(i);
426 }
427
428 ALWAYS_INLINE JSValue JSImmediate::from(unsigned char i)
429 {
430 return makeInt(i);
431 }
432
433 ALWAYS_INLINE JSValue JSImmediate::from(short i)
434 {
435 return makeInt(i);
436 }
437
438 ALWAYS_INLINE JSValue JSImmediate::from(unsigned short i)
439 {
440 return makeInt(i);
441 }
442
443 ALWAYS_INLINE JSValue JSImmediate::from(int i)
444 {
445#if !USE(ALTERNATE_JSIMMEDIATE)
446 if ((i < minImmediateInt) | (i > maxImmediateInt))
447 return fromNumberOutsideIntegerRange(i);
448#endif
449 return makeInt(i);
450 }
451
452 ALWAYS_INLINE JSValue JSImmediate::from(unsigned i)
453 {
454 if (i > maxImmediateUInt)
455 return fromNumberOutsideIntegerRange(i);
456 return makeInt(i);
457 }
458
459 ALWAYS_INLINE JSValue JSImmediate::from(long i)
460 {
461 if ((i < minImmediateInt) | (i > maxImmediateInt))
462 return fromNumberOutsideIntegerRange(i);
463 return makeInt(i);
464 }
465
466 ALWAYS_INLINE JSValue JSImmediate::from(unsigned long i)
467 {
468 if (i > maxImmediateUInt)
469 return fromNumberOutsideIntegerRange(i);
470 return makeInt(i);
471 }
472
473 ALWAYS_INLINE JSValue JSImmediate::from(long long i)
474 {
475 if ((i < minImmediateInt) | (i > maxImmediateInt))
476 return JSValue();
477 return makeInt(static_cast<intptr_t>(i));
478 }
479
480 ALWAYS_INLINE JSValue JSImmediate::from(unsigned long long i)
481 {
482 if (i > maxImmediateUInt)
483 return fromNumberOutsideIntegerRange(i);
484 return makeInt(static_cast<intptr_t>(i));
485 }
486
487 ALWAYS_INLINE JSValue JSImmediate::from(double d)
488 {
489 const int intVal = static_cast<int>(d);
490
491 // Check for data loss from conversion to int.
492 if (intVal != d || (!intVal && signbit(d)))
493 return fromNumberOutsideIntegerRange(d);
494
495 return from(intVal);
496 }
497
498 ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValue v)
499 {
500 ASSERT(isIntegerNumber(v));
501 return intValue(v);
502 }
503
504 ALWAYS_INLINE double JSImmediate::toDouble(JSValue v)
505 {
506 ASSERT(isImmediate(v));
507
508 if (isIntegerNumber(v))
509 return intValue(v);
510
511#if USE(ALTERNATE_JSIMMEDIATE)
512 if (isNumber(v)) {
513 ASSERT(isDoubleNumber(v));
514 return doubleValue(v);
515 }
516#else
517 ASSERT(!isNumber(v));
518#endif
519
520 if (rawValue(v) == FullTagTypeUndefined)
521 return nonInlineNaN();
522
523 ASSERT(JSImmediate::isBoolean(v) || (v == JSImmediate::nullImmediate()));
524 return rawValue(v) >> ExtendedPayloadShift;
525 }
526
527 ALWAYS_INLINE bool JSImmediate::getUInt32(JSValue v, uint32_t& i)
528 {
529 i = uintValue(v);
530 return isPositiveIntegerNumber(v);
531 }
532
533 ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValue v, int32_t& i)
534 {
535 i = intValue(v);
536 return isIntegerNumber(v);
537 }
538
539 ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValue v, uint32_t& i)
540 {
541 return getUInt32(v, i);
542 }
543
544 // These are identical logic to the JSValue functions above, and faster than jsNumber(number).toInt32().
545 int32_t toInt32(double);
546 uint32_t toUInt32(double);
547 int32_t toInt32SlowCase(double, bool& ok);
548 uint32_t toUInt32SlowCase(double, bool& ok);
549
550 inline JSValue::JSValue(JSNullTag)
551 {
552 *this = JSImmediate::nullImmediate();
553 }
554
555 inline JSValue::JSValue(JSUndefinedTag)
556 {
557 *this = JSImmediate::undefinedImmediate();
558 }
559
560 inline JSValue::JSValue(JSTrueTag)
561 {
562 *this = JSImmediate::trueImmediate();
563 }
564
565 inline JSValue::JSValue(JSFalseTag)
566 {
567 *this = JSImmediate::falseImmediate();
568 }
569
570 inline bool JSValue::isUndefinedOrNull() const
571 {
572 return JSImmediate::isUndefinedOrNull(asValue());
573 }
574
575 inline bool JSValue::isBoolean() const
576 {
577 return JSImmediate::isBoolean(asValue());
578 }
579
580 inline bool JSValue::getBoolean(bool& v) const
581 {
582 if (JSImmediate::isBoolean(asValue())) {
583 v = JSImmediate::toBoolean(asValue());
584 return true;
585 }
586
587 return false;
588 }
589
590 inline bool JSValue::getBoolean() const
591 {
592 return asValue() == jsBoolean(true);
593 }
594
595 ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
596 {
597 int32_t i;
598 if (getTruncatedInt32(i))
599 return i;
600 bool ignored;
601 return toInt32SlowCase(toNumber(exec), ignored);
602 }
603
604 inline uint32_t JSValue::toUInt32(ExecState* exec) const
605 {
606 uint32_t i;
607 if (getTruncatedUInt32(i))
608 return i;
609 bool ignored;
610 return toUInt32SlowCase(toNumber(exec), ignored);
611 }
612
613 inline int32_t toInt32(double val)
614 {
615 if (!(val >= -2147483648.0 && val < 2147483648.0)) {
616 bool ignored;
617 return toInt32SlowCase(val, ignored);
618 }
619 return static_cast<int32_t>(val);
620 }
621
622 inline uint32_t toUInt32(double val)
623 {
624 if (!(val >= 0.0 && val < 4294967296.0)) {
625 bool ignored;
626 return toUInt32SlowCase(val, ignored);
627 }
628 return static_cast<uint32_t>(val);
629 }
630
631 inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
632 {
633 int32_t i;
634 if (getTruncatedInt32(i)) {
635 ok = true;
636 return i;
637 }
638 return toInt32SlowCase(toNumber(exec), ok);
639 }
640
641 inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
642 {
643 uint32_t i;
644 if (getTruncatedUInt32(i)) {
645 ok = true;
646 return i;
647 }
648 return toUInt32SlowCase(toNumber(exec), ok);
649 }
650
651 inline bool JSValue::isCell() const
652 {
653 return !JSImmediate::isImmediate(asValue());
654 }
655
656 inline bool JSValue::isInt32Fast() const
657 {
658 return JSImmediate::isIntegerNumber(asValue());
659 }
660
661 inline int32_t JSValue::getInt32Fast() const
662 {
663 ASSERT(isInt32Fast());
664 return JSImmediate::getTruncatedInt32(asValue());
665 }
666
667 inline bool JSValue::isUInt32Fast() const
668 {
669 return JSImmediate::isPositiveIntegerNumber(asValue());
670 }
671
672 inline uint32_t JSValue::getUInt32Fast() const
673 {
674 ASSERT(isUInt32Fast());
675 return JSImmediate::getTruncatedUInt32(asValue());
676 }
677
678 inline JSValue JSValue::makeInt32Fast(int32_t i)
679 {
680 return JSImmediate::from(i);
681 }
682
683 inline bool JSValue::areBothInt32Fast(JSValue v1, JSValue v2)
684 {
685 return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
686 }
687
688 class JSFastMath {
689 public:
690 static ALWAYS_INLINE bool canDoFastBitwiseOperations(JSValue v1, JSValue v2)
691 {
692 return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
693 }
694
695 static ALWAYS_INLINE JSValue equal(JSValue v1, JSValue v2)
696 {
697 ASSERT(canDoFastBitwiseOperations(v1, v2));
698 return jsBoolean(v1 == v2);
699 }
700
701 static ALWAYS_INLINE JSValue notEqual(JSValue v1, JSValue v2)
702 {
703 ASSERT(canDoFastBitwiseOperations(v1, v2));
704 return jsBoolean(v1 != v2);
705 }
706
707 static ALWAYS_INLINE JSValue andImmediateNumbers(JSValue v1, JSValue v2)
708 {
709 ASSERT(canDoFastBitwiseOperations(v1, v2));
710 return JSImmediate::makeValue(JSImmediate::rawValue(v1) & JSImmediate::rawValue(v2));
711 }
712
713 static ALWAYS_INLINE JSValue xorImmediateNumbers(JSValue v1, JSValue v2)
714 {
715 ASSERT(canDoFastBitwiseOperations(v1, v2));
716 return JSImmediate::makeValue((JSImmediate::rawValue(v1) ^ JSImmediate::rawValue(v2)) | JSImmediate::TagTypeNumber);
717 }
718
719 static ALWAYS_INLINE JSValue orImmediateNumbers(JSValue v1, JSValue v2)
720 {
721 ASSERT(canDoFastBitwiseOperations(v1, v2));
722 return JSImmediate::makeValue(JSImmediate::rawValue(v1) | JSImmediate::rawValue(v2));
723 }
724
725 static ALWAYS_INLINE bool canDoFastRshift(JSValue v1, JSValue v2)
726 {
727 return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
728 }
729
730 static ALWAYS_INLINE bool canDoFastUrshift(JSValue v1, JSValue v2)
731 {
732 return JSImmediate::areBothImmediateIntegerNumbers(v1, v2) && !(JSImmediate::rawValue(v1) & JSImmediate::signBit);
733 }
734
735 static ALWAYS_INLINE JSValue rightShiftImmediateNumbers(JSValue val, JSValue shift)
736 {
737 ASSERT(canDoFastRshift(val, shift) || canDoFastUrshift(val, shift));
738#if USE(ALTERNATE_JSIMMEDIATE)
739 return JSImmediate::makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(JSImmediate::rawValue(val)) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f))) | JSImmediate::TagTypeNumber);
740#else
741 return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeNumber);
742#endif
743 }
744
745 static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue v)
746 {
747 // Number is non-negative and an operation involving two of these can't overflow.
748 // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
749 return (JSImmediate::rawValue(v) & (JSImmediate::TagTypeNumber + (JSImmediate::signBit | (JSImmediate::signBit >> 1)))) == JSImmediate::TagTypeNumber;
750 }
751
752 static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue v1, JSValue v2)
753 {
754 // Number is non-negative and an operation involving two of these can't overflow.
755 // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
756 return canDoFastAdditiveOperations(v1) && canDoFastAdditiveOperations(v2);
757 }
758
759 static ALWAYS_INLINE JSValue addImmediateNumbers(JSValue v1, JSValue v2)
760 {
761 ASSERT(canDoFastAdditiveOperations(v1, v2));
762 return JSImmediate::makeValue(JSImmediate::rawValue(v1) + JSImmediate::rawValue(v2) - JSImmediate::TagTypeNumber);
763 }
764
765 static ALWAYS_INLINE JSValue subImmediateNumbers(JSValue v1, JSValue v2)
766 {
767 ASSERT(canDoFastAdditiveOperations(v1, v2));
768 return JSImmediate::makeValue(JSImmediate::rawValue(v1) - JSImmediate::rawValue(v2) + JSImmediate::TagTypeNumber);
769 }
770
771 static ALWAYS_INLINE JSValue incImmediateNumber(JSValue v)
772 {
773 ASSERT(canDoFastAdditiveOperations(v));
774 return JSImmediate::makeValue(JSImmediate::rawValue(v) + (1 << JSImmediate::IntegerPayloadShift));
775 }
776
777 static ALWAYS_INLINE JSValue decImmediateNumber(JSValue v)
778 {
779 ASSERT(canDoFastAdditiveOperations(v));
780 return JSImmediate::makeValue(JSImmediate::rawValue(v) - (1 << JSImmediate::IntegerPayloadShift));
781 }
782 };
783
784} // namespace JSC
785
786#endif // JSImmediate_h
Note: See TracBrowser for help on using the repository browser.