source: webkit/trunk/JavaScriptCore/kjs/JSImmediate.h@ 26589

Last change on this file since 26589 was 26589, checked in by bdash, 18 years ago

2007-10-14 Kevin Ollivier <[email protected]>

Reviewed by Adam.

Add support for MSVC7, and fix cases where PLATFORM(WIN) should
be PLATFORM(WIN_OS) for other ports building on Windows.

  • dom/XMLTokenizer.cpp:
  • page/FrameTree.cpp:
  • platform/StaticConstructors.h:
  • platform/String.cpp:

2007-10-5 Kevin Ollivier <[email protected]>

Reviewed by Adam.


Add support for MSVC7, and fix cases where PLATFORM(WIN) should
be PLATFORM(WIN_OS) for other ports building on Windows.


  • kjs/DateMath.cpp: (KJS::getDSTOffsetSimple):
  • kjs/JSImmediate.h:
  • wtf/Assertions.cpp:
  • wtf/Assertions.h:
  • wtf/Platform.h:
  • wtf/StringExtras.h: (snprintf): (vsnprintf):
  • Property svn:eol-style set to native
File size: 7.4 KB
Line 
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 2003-2006 Apple Computer, Inc
4 * Copyright (C) 2006 Alexey Proskuryakov ([email protected])
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 KJS_JS_IMMEDIATE_H
24#define KJS_JS_IMMEDIATE_H
25
26#include "JSType.h"
27#include <wtf/Assertions.h>
28#include <stdarg.h>
29#include <stdint.h>
30#include <stdlib.h>
31
32namespace KJS {
33
34class ExecState;
35class JSObject;
36class JSValue;
37class UString;
38
39/*
40 * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged
41 * IEEE floating point bit pattern masquerading as a pointer). The low two bits in a JSValue* are available
42 * for type tagging because allocator alignment guarantees they will be 00 in cell pointers.
43 *
44 * For example, on a 32 bit system:
45 *
46 * JSCell*: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00
47 * [ high 30 bits: pointer address ] [ low 2 bits -- always 0 ]
48 *
49 * JSImmediate: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX TT
50 * [ high 30 bits: IEEE encoded float ] [ low 2 bits -- type tag ]
51 *
52 * The bit "payload" (the hight 30 bits) of a non-numeric immediate is its numeric equivalent. For example,
53 * the payload of null is 0.0. This makes JSValue::toNumber() a simple bitmask for all immediates.
54 *
55 * Notice that the JSType value of NullType is 4, which requires 3 bits to encode. Since we only have 2 bits
56 * available for type tagging, we tag the null immediate with UndefinedType, and JSImmediate::type() has
57 * to sort them out. Null and Undefined don't otherwise get confused because the numeric value of Undefined is
58 * NaN, not 0.0.
59 */
60
61class JSImmediate {
62public:
63 static bool isImmediate(const JSValue* v)
64 {
65 return getTag(v) != 0;
66 }
67
68 static bool isNumber(const JSValue* v)
69 {
70 return (getTag(v) == NumberType);
71 }
72
73 static bool isBoolean(const JSValue* v)
74 {
75 return (getTag(v) == BooleanType);
76 }
77
78 // Since we have room for only 3 unique tags, null and undefined have to share.
79 static bool isUndefinedOrNull(const JSValue* v)
80 {
81 return (getTag(v) == UndefinedType);
82 }
83
84 static JSValue* fromDouble(double d);
85 static double toDouble(const JSValue* v);
86 static bool toBoolean(const JSValue* v);
87 static JSObject* toObject(const JSValue*, ExecState*);
88 static UString toString(const JSValue*);
89 static JSType type(const JSValue*);
90
91 // It would nice just to use fromDouble() to create these values, but that would prevent them from
92 // turning into compile-time constants.
93 static JSValue* trueImmediate();
94 static JSValue* falseImmediate();
95 static JSValue* NaNImmediate();
96 static JSValue* undefinedImmediate();
97 static JSValue* nullImmediate();
98
99private:
100 static const uintptr_t TagMask = 3; // type tags are 2 bits long
101
102 static JSValue* tag(uintptr_t bits, uintptr_t tag)
103 {
104 return reinterpret_cast<JSValue*>(bits | tag);
105 }
106
107 static uintptr_t unTag(const JSValue* v)
108 {
109 return reinterpret_cast<uintptr_t>(v) & ~TagMask;
110 }
111
112 static uintptr_t getTag(const JSValue* v)
113 {
114 return reinterpret_cast<uintptr_t>(v) & TagMask;
115 }
116
117 // NOTE: With f-strict-aliasing enabled, unions are the only safe way to do type masquerading.
118
119 union FloatUnion {
120 uint32_t asBits;
121 float asFloat;
122 };
123
124 union DoubleUnion {
125 uint64_t asBits;
126 double asDouble;
127 };
128
129 // we support 32-bit platforms with sizes like this
130 static const bool is32bit =
131 sizeof(float) == sizeof(uint32_t) && sizeof(double) == sizeof(uint64_t) && sizeof(uintptr_t) == sizeof(uint32_t);
132
133 // we support 64-bit platforms with sizes like this
134 static const bool is64bit =
135 sizeof(float) == sizeof(uint32_t) && sizeof(double) == sizeof(uint64_t) && sizeof(uintptr_t) == sizeof(uint64_t);
136
137 template<bool for32bit, bool for64bit> struct FPBitValues {};
138};
139
140template<> struct JSImmediate::FPBitValues<true, false> {
141 static const uint32_t nanAsBits = 0x7fc00000;
142 static const uint32_t oneAsBits = 0x3f800000;
143 static const uint32_t zeroAsBits = 0x0;
144
145 static JSValue* fromDouble(double d)
146 {
147 FloatUnion floatUnion;
148 floatUnion.asFloat = static_cast<float>(d);
149
150 // check for data loss from tagging
151 if ((floatUnion.asBits & TagMask) != 0)
152 return 0;
153
154 // check for data loss from conversion to float
155 DoubleUnion doubleUnion1, doubleUnion2;
156 doubleUnion1.asDouble = floatUnion.asFloat;
157 doubleUnion2.asDouble = d;
158 if (doubleUnion1.asBits != doubleUnion2.asBits)
159 return 0;
160
161 return tag(floatUnion.asBits, NumberType);
162 }
163
164 static double toDouble(const JSValue* v)
165 {
166 ASSERT(isImmediate(v));
167
168 FloatUnion floatUnion;
169 floatUnion.asBits = static_cast<uint32_t>(unTag(v));
170 return floatUnion.asFloat;
171 }
172};
173
174template<> struct JSImmediate::FPBitValues<false, true> {
175 static const uint64_t nanAsBits = 0x7ff80000ULL << 32;
176 static const uint64_t oneAsBits = 0x3ff00000ULL << 32;
177 static const uint64_t zeroAsBits = 0x0;
178
179 static JSValue* fromDouble(double d)
180 {
181 DoubleUnion doubleUnion;
182 doubleUnion.asDouble = d;
183
184 // check for data loss from tagging
185 if ((doubleUnion.asBits & TagMask) != 0)
186 return 0;
187
188 return tag(static_cast<uintptr_t>(doubleUnion.asBits), NumberType);
189 }
190
191 static double toDouble(const JSValue* v)
192 {
193 ASSERT(isImmediate(v));
194
195 DoubleUnion doubleUnion;
196 doubleUnion.asBits = unTag(v);
197 return doubleUnion.asDouble;
198 }
199};
200
201inline JSValue* JSImmediate::trueImmediate() { return tag(FPBitValues<is32bit, is64bit>::oneAsBits, BooleanType); }
202inline JSValue* JSImmediate::falseImmediate() { return tag(FPBitValues<is32bit, is64bit>::zeroAsBits, BooleanType); }
203inline JSValue* JSImmediate::NaNImmediate() { return tag(FPBitValues<is32bit, is64bit>::nanAsBits, NumberType); }
204inline JSValue* JSImmediate::undefinedImmediate() { return tag(FPBitValues<is32bit, is64bit>::nanAsBits, UndefinedType); }
205inline JSValue* JSImmediate::nullImmediate() { return tag(FPBitValues<is32bit, is64bit>::zeroAsBits, UndefinedType); }
206
207inline bool JSImmediate::toBoolean(const JSValue* v)
208{
209 ASSERT(isImmediate(v));
210
211 uintptr_t bits = unTag(v);
212 if ((bits << 1) == 0) // -0.0 has the sign bit set
213 return false;
214
215 return bits != FPBitValues<is32bit, is64bit>::nanAsBits;
216}
217
218inline JSValue* JSImmediate::fromDouble(double d)
219{
220 return FPBitValues<is32bit, is64bit>::fromDouble(d);
221}
222
223inline double JSImmediate::toDouble(const JSValue* v)
224{
225 return FPBitValues<is32bit, is64bit>::toDouble(v);
226}
227
228} // namespace KJS
229
230#endif
Note: See TracBrowser for help on using the repository browser.