• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE 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 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.
24  */
25 
26 #ifndef JSValueInlineMethods_h
27 #define JSValueInlineMethods_h
28 
29 #include "JSValue.h"
30 
31 namespace JSC {
32 
toInt32(ExecState * exec)33     ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
34     {
35         if (isInt32())
36             return asInt32();
37         return JSC::toInt32(toNumber(exec));
38     }
39 
toUInt32(ExecState * exec)40     inline uint32_t JSValue::toUInt32(ExecState* exec) const
41     {
42         // See comment on JSC::toUInt32, above.
43         return toInt32(exec);
44     }
45 
isUInt32()46     inline bool JSValue::isUInt32() const
47     {
48         return isInt32() && asInt32() >= 0;
49     }
50 
asUInt32()51     inline uint32_t JSValue::asUInt32() const
52     {
53         ASSERT(isUInt32());
54         return asInt32();
55     }
56 
uncheckedGetNumber()57     inline double JSValue::uncheckedGetNumber() const
58     {
59         ASSERT(isNumber());
60         return isInt32() ? asInt32() : asDouble();
61     }
62 
toJSNumber(ExecState * exec)63     ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
64     {
65         return isNumber() ? asValue() : jsNumber(this->toNumber(exec));
66     }
67 
jsNaN()68     inline JSValue jsNaN()
69     {
70         return JSValue(nonInlineNaN());
71     }
72 
getNumber(double & result)73     inline bool JSValue::getNumber(double& result) const
74     {
75         if (isInt32()) {
76             result = asInt32();
77             return true;
78         }
79         if (isDouble()) {
80             result = asDouble();
81             return true;
82         }
83         return false;
84     }
85 
getBoolean(bool & v)86     inline bool JSValue::getBoolean(bool& v) const
87     {
88         if (isTrue()) {
89             v = true;
90             return true;
91         }
92         if (isFalse()) {
93             v = false;
94             return true;
95         }
96 
97         return false;
98     }
99 
JSValue(char i)100     inline JSValue::JSValue(char i)
101     {
102         *this = JSValue(static_cast<int32_t>(i));
103     }
104 
JSValue(unsigned char i)105     inline JSValue::JSValue(unsigned char i)
106     {
107         *this = JSValue(static_cast<int32_t>(i));
108     }
109 
JSValue(short i)110     inline JSValue::JSValue(short i)
111     {
112         *this = JSValue(static_cast<int32_t>(i));
113     }
114 
JSValue(unsigned short i)115     inline JSValue::JSValue(unsigned short i)
116     {
117         *this = JSValue(static_cast<int32_t>(i));
118     }
119 
JSValue(unsigned i)120     inline JSValue::JSValue(unsigned i)
121     {
122         if (static_cast<int32_t>(i) < 0) {
123             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
124             return;
125         }
126         *this = JSValue(static_cast<int32_t>(i));
127     }
128 
JSValue(long i)129     inline JSValue::JSValue(long i)
130     {
131         if (static_cast<int32_t>(i) != i) {
132             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
133             return;
134         }
135         *this = JSValue(static_cast<int32_t>(i));
136     }
137 
JSValue(unsigned long i)138     inline JSValue::JSValue(unsigned long i)
139     {
140         if (static_cast<uint32_t>(i) != i) {
141             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
142             return;
143         }
144         *this = JSValue(static_cast<uint32_t>(i));
145     }
146 
JSValue(long long i)147     inline JSValue::JSValue(long long i)
148     {
149         if (static_cast<int32_t>(i) != i) {
150             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
151             return;
152         }
153         *this = JSValue(static_cast<int32_t>(i));
154     }
155 
JSValue(unsigned long long i)156     inline JSValue::JSValue(unsigned long long i)
157     {
158         if (static_cast<uint32_t>(i) != i) {
159             *this = JSValue(EncodeAsDouble, static_cast<double>(i));
160             return;
161         }
162         *this = JSValue(static_cast<uint32_t>(i));
163     }
164 
JSValue(double d)165     inline JSValue::JSValue(double d)
166     {
167         const int32_t asInt32 = static_cast<int32_t>(d);
168         if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
169             *this = JSValue(EncodeAsDouble, d);
170             return;
171         }
172         *this = JSValue(static_cast<int32_t>(d));
173     }
174 
175 #if USE(JSVALUE32_64)
encode(JSValue value)176     inline EncodedJSValue JSValue::encode(JSValue value)
177     {
178         return value.u.asInt64;
179     }
180 
decode(EncodedJSValue encodedJSValue)181     inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
182     {
183         JSValue v;
184         v.u.asInt64 = encodedJSValue;
185         return v;
186     }
187 
JSValue()188     inline JSValue::JSValue()
189     {
190         u.asBits.tag = EmptyValueTag;
191         u.asBits.payload = 0;
192     }
193 
JSValue(JSNullTag)194     inline JSValue::JSValue(JSNullTag)
195     {
196         u.asBits.tag = NullTag;
197         u.asBits.payload = 0;
198     }
199 
JSValue(JSUndefinedTag)200     inline JSValue::JSValue(JSUndefinedTag)
201     {
202         u.asBits.tag = UndefinedTag;
203         u.asBits.payload = 0;
204     }
205 
JSValue(JSTrueTag)206     inline JSValue::JSValue(JSTrueTag)
207     {
208         u.asBits.tag = BooleanTag;
209         u.asBits.payload = 1;
210     }
211 
JSValue(JSFalseTag)212     inline JSValue::JSValue(JSFalseTag)
213     {
214         u.asBits.tag = BooleanTag;
215         u.asBits.payload = 0;
216     }
217 
JSValue(HashTableDeletedValueTag)218     inline JSValue::JSValue(HashTableDeletedValueTag)
219     {
220         u.asBits.tag = DeletedValueTag;
221         u.asBits.payload = 0;
222     }
223 
JSValue(JSCell * ptr)224     inline JSValue::JSValue(JSCell* ptr)
225     {
226         if (ptr)
227             u.asBits.tag = CellTag;
228         else
229             u.asBits.tag = EmptyValueTag;
230         u.asBits.payload = reinterpret_cast<int32_t>(ptr);
231 #if ENABLE(JSC_ZOMBIES)
232         ASSERT(!isZombie());
233 #endif
234     }
235 
JSValue(const JSCell * ptr)236     inline JSValue::JSValue(const JSCell* ptr)
237     {
238         if (ptr)
239             u.asBits.tag = CellTag;
240         else
241             u.asBits.tag = EmptyValueTag;
242         u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
243 #if ENABLE(JSC_ZOMBIES)
244         ASSERT(!isZombie());
245 #endif
246     }
247 
248     inline JSValue::operator bool() const
249     {
250         ASSERT(tag() != DeletedValueTag);
251         return tag() != EmptyValueTag;
252     }
253 
254     inline bool JSValue::operator==(const JSValue& other) const
255     {
256         return u.asInt64 == other.u.asInt64;
257     }
258 
259     inline bool JSValue::operator!=(const JSValue& other) const
260     {
261         return u.asInt64 != other.u.asInt64;
262     }
263 
isUndefined()264     inline bool JSValue::isUndefined() const
265     {
266         return tag() == UndefinedTag;
267     }
268 
isNull()269     inline bool JSValue::isNull() const
270     {
271         return tag() == NullTag;
272     }
273 
isUndefinedOrNull()274     inline bool JSValue::isUndefinedOrNull() const
275     {
276         return isUndefined() || isNull();
277     }
278 
isCell()279     inline bool JSValue::isCell() const
280     {
281         return tag() == CellTag;
282     }
283 
isInt32()284     inline bool JSValue::isInt32() const
285     {
286         return tag() == Int32Tag;
287     }
288 
isDouble()289     inline bool JSValue::isDouble() const
290     {
291         return tag() < LowestTag;
292     }
293 
isTrue()294     inline bool JSValue::isTrue() const
295     {
296         return tag() == BooleanTag && payload();
297     }
298 
isFalse()299     inline bool JSValue::isFalse() const
300     {
301         return tag() == BooleanTag && !payload();
302     }
303 
tag()304     inline uint32_t JSValue::tag() const
305     {
306         return u.asBits.tag;
307     }
308 
payload()309     inline int32_t JSValue::payload() const
310     {
311         return u.asBits.payload;
312     }
313 
asInt32()314     inline int32_t JSValue::asInt32() const
315     {
316         ASSERT(isInt32());
317         return u.asBits.payload;
318     }
319 
asDouble()320     inline double JSValue::asDouble() const
321     {
322         ASSERT(isDouble());
323         return u.asDouble;
324     }
325 
asCell()326     ALWAYS_INLINE JSCell* JSValue::asCell() const
327     {
328         ASSERT(isCell());
329         return reinterpret_cast<JSCell*>(u.asBits.payload);
330     }
331 
JSValue(EncodeAsDoubleTag,double d)332     ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
333     {
334         u.asDouble = d;
335     }
336 
JSValue(int i)337     inline JSValue::JSValue(int i)
338     {
339         u.asBits.tag = Int32Tag;
340         u.asBits.payload = i;
341     }
342 
isNumber()343     inline bool JSValue::isNumber() const
344     {
345         return isInt32() || isDouble();
346     }
347 
isBoolean()348     inline bool JSValue::isBoolean() const
349     {
350         return isTrue() || isFalse();
351     }
352 
getBoolean()353     inline bool JSValue::getBoolean() const
354     {
355         ASSERT(isBoolean());
356         return payload();
357     }
358 
359 #else // USE(JSVALUE32_64)
360 
361     // JSValue member functions.
encode(JSValue value)362     inline EncodedJSValue JSValue::encode(JSValue value)
363     {
364         return value.u.ptr;
365     }
366 
decode(EncodedJSValue ptr)367     inline JSValue JSValue::decode(EncodedJSValue ptr)
368     {
369         return JSValue(reinterpret_cast<JSCell*>(ptr));
370     }
371 
372     // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page.
JSValue()373     inline JSValue::JSValue()
374     {
375         u.asInt64 = ValueEmpty;
376     }
377 
378     // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page.
JSValue(HashTableDeletedValueTag)379     inline JSValue::JSValue(HashTableDeletedValueTag)
380     {
381         u.asInt64 = ValueDeleted;
382     }
383 
JSValue(JSCell * ptr)384     inline JSValue::JSValue(JSCell* ptr)
385     {
386         u.ptr = ptr;
387 #if ENABLE(JSC_ZOMBIES)
388         ASSERT(!isZombie());
389 #endif
390     }
391 
JSValue(const JSCell * ptr)392     inline JSValue::JSValue(const JSCell* ptr)
393     {
394         u.ptr = const_cast<JSCell*>(ptr);
395 #if ENABLE(JSC_ZOMBIES)
396         ASSERT(!isZombie());
397 #endif
398     }
399 
400     inline JSValue::operator bool() const
401     {
402         return u.ptr;
403     }
404 
405     inline bool JSValue::operator==(const JSValue& other) const
406     {
407         return u.ptr == other.u.ptr;
408     }
409 
410     inline bool JSValue::operator!=(const JSValue& other) const
411     {
412         return u.ptr != other.u.ptr;
413     }
414 
isUndefined()415     inline bool JSValue::isUndefined() const
416     {
417         return asValue() == jsUndefined();
418     }
419 
isNull()420     inline bool JSValue::isNull() const
421     {
422         return asValue() == jsNull();
423     }
424 
isTrue()425     inline bool JSValue::isTrue() const
426     {
427         return asValue() == JSValue(JSTrue);
428     }
429 
isFalse()430     inline bool JSValue::isFalse() const
431     {
432         return asValue() == JSValue(JSFalse);
433     }
434 
getBoolean()435     inline bool JSValue::getBoolean() const
436     {
437         ASSERT(asValue() == jsBoolean(true) || asValue() == jsBoolean(false));
438         return asValue() == jsBoolean(true);
439     }
440 
asInt32()441     inline int32_t JSValue::asInt32() const
442     {
443         ASSERT(isInt32());
444         return static_cast<int32_t>(u.asInt64);
445     }
446 
isDouble()447     inline bool JSValue::isDouble() const
448     {
449         return isNumber() && !isInt32();
450     }
451 
JSValue(JSNullTag)452     inline JSValue::JSValue(JSNullTag)
453     {
454         u.asInt64 = ValueNull;
455     }
456 
JSValue(JSUndefinedTag)457     inline JSValue::JSValue(JSUndefinedTag)
458     {
459         u.asInt64 = ValueUndefined;
460     }
461 
JSValue(JSTrueTag)462     inline JSValue::JSValue(JSTrueTag)
463     {
464         u.asInt64 = ValueTrue;
465     }
466 
JSValue(JSFalseTag)467     inline JSValue::JSValue(JSFalseTag)
468     {
469         u.asInt64 = ValueFalse;
470     }
471 
isUndefinedOrNull()472     inline bool JSValue::isUndefinedOrNull() const
473     {
474         // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
475         return (u.asInt64 & ~TagBitUndefined) == ValueNull;
476     }
477 
isBoolean()478     inline bool JSValue::isBoolean() const
479     {
480         return (u.asInt64 & ~1) == ValueFalse;
481     }
482 
isCell()483     inline bool JSValue::isCell() const
484     {
485         return !(u.asInt64 & TagMask);
486     }
487 
isInt32()488     inline bool JSValue::isInt32() const
489     {
490         return (u.asInt64 & TagTypeNumber) == TagTypeNumber;
491     }
492 
reinterpretDoubleToIntptr(double value)493     inline intptr_t reinterpretDoubleToIntptr(double value)
494     {
495         return bitwise_cast<intptr_t>(value);
496     }
reinterpretIntptrToDouble(intptr_t value)497     inline double reinterpretIntptrToDouble(intptr_t value)
498     {
499         return bitwise_cast<double>(value);
500     }
501 
JSValue(EncodeAsDoubleTag,double d)502     ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
503     {
504         u.asInt64 = reinterpretDoubleToIntptr(d) + DoubleEncodeOffset;
505     }
506 
JSValue(int i)507     inline JSValue::JSValue(int i)
508     {
509         u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i);
510     }
511 
asDouble()512     inline double JSValue::asDouble() const
513     {
514         return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset);
515     }
516 
isNumber()517     inline bool JSValue::isNumber() const
518     {
519         return u.asInt64 & TagTypeNumber;
520     }
521 
asCell()522     ALWAYS_INLINE JSCell* JSValue::asCell() const
523     {
524         ASSERT(isCell());
525         return u.ptr;
526     }
527 
528 #endif // USE(JSVALUE64)
529 
530 } // namespace JSC
531 
532 #endif // JSValueInlineMethods_h
533