]> git.saurik.com Git - apple/javascriptcore.git/blame - kjs/value.cpp
JavaScriptCore-466.1.3.tar.gz
[apple/javascriptcore.git] / kjs / value.cpp
CommitLineData
b37bf2e1
A
1/*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 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#include "config.h"
24#include "value.h"
25
26#include "error_object.h"
27#include "nodes.h"
28#include <stdio.h>
29#include <string.h>
30#include <wtf/MathExtras.h>
31
32namespace KJS {
33
34#if defined NAN && defined INFINITY
35
36extern const double NaN = NAN;
37extern const double Inf = INFINITY;
38
39#else // !(defined NAN && defined INFINITY)
40
41// The trick is to define the NaN and Inf globals with a different type than the declaration.
42// This trick works because the mangled name of the globals does not include the type, although
43// I'm not sure that's guaranteed. There could be alignment issues with this, since arrays of
44// characters don't necessarily need the same alignment doubles do, but for now it seems to work.
45// It would be good to figure out a 100% clean way that still avoids code that runs at init time.
46
47// Note, we have to use union to ensure alignment. Otherwise, NaN_Bytes can start anywhere,
48// while NaN_double has to be 4-byte aligned for 32-bits.
49// With -fstrict-aliasing enabled, unions are the only safe way to do type masquerading.
50
51static const union {
52 struct {
53 unsigned char NaN_Bytes[8];
54 unsigned char Inf_Bytes[8];
55 } bytes;
56
57 struct {
58 double NaN_Double;
59 double Inf_Double;
60 } doubles;
61
62} NaNInf = { {
63#if PLATFORM(BIG_ENDIAN)
64 { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 },
65 { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
66#elif PLATFORM(MIDDLE_ENDIAN)
67 { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 },
68 { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 }
69#else
70 { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f },
71 { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }
72#endif
73} } ;
74
75extern const double NaN = NaNInf.doubles.NaN_Double;
76extern const double Inf = NaNInf.doubles.Inf_Double;
77
78#endif // !(defined NAN && defined INFINITY)
79
80static const double D16 = 65536.0;
81static const double D32 = 4294967296.0;
82
83void *JSCell::operator new(size_t size)
84{
85 return Collector::allocate(size);
86}
87
88bool JSCell::getUInt32(uint32_t&) const
89{
90 return false;
91}
92
93bool JSCell::getTruncatedInt32(int32_t&) const
94{
95 return false;
96}
97
98bool JSCell::getTruncatedUInt32(uint32_t&) const
99{
100 return false;
101}
102
103// ECMA 9.4
104double JSValue::toInteger(ExecState *exec) const
105{
106 int32_t i;
107 if (getTruncatedInt32(i))
108 return i;
109 double d = toNumber(exec);
110 return isnan(d) ? 0.0 : trunc(d);
111}
112
113double JSValue::toIntegerPreserveNaN(ExecState *exec) const
114{
115 int32_t i;
116 if (getTruncatedInt32(i))
117 return i;
118 return trunc(toNumber(exec));
119}
120
121int32_t JSValue::toInt32SlowCase(double d, bool& ok)
122{
123 ok = true;
124
125 if (d >= -D32 / 2 && d < D32 / 2)
126 return static_cast<int32_t>(d);
127
128 if (isnan(d) || isinf(d)) {
129 ok = false;
130 return 0;
131 }
132
133 double d32 = fmod(trunc(d), D32);
134 if (d32 >= D32 / 2)
135 d32 -= D32;
136 else if (d32 < -D32 / 2)
137 d32 += D32;
138 return static_cast<int32_t>(d32);
139}
140
141int32_t JSValue::toInt32SlowCase(ExecState* exec, bool& ok) const
142{
143 return JSValue::toInt32SlowCase(toNumber(exec), ok);
144}
145
146uint32_t JSValue::toUInt32SlowCase(double d, bool& ok)
147{
148 ok = true;
149
150 if (d >= 0.0 && d < D32)
151 return static_cast<uint32_t>(d);
152
153 if (isnan(d) || isinf(d)) {
154 ok = false;
155 return 0;
156 }
157
158 double d32 = fmod(trunc(d), D32);
159 if (d32 < 0)
160 d32 += D32;
161 return static_cast<uint32_t>(d32);
162}
163
164uint32_t JSValue::toUInt32SlowCase(ExecState* exec, bool& ok) const
165{
166 return JSValue::toUInt32SlowCase(toNumber(exec), ok);
167}
168
169float JSValue::toFloat(ExecState* exec) const
170{
171 return static_cast<float>(toNumber(exec));
172}
173
174bool JSCell::getNumber(double &numericValue) const
175{
176 if (!isNumber())
177 return false;
178 numericValue = static_cast<const NumberImp *>(this)->value();
179 return true;
180}
181
182double JSCell::getNumber() const
183{
184 return isNumber() ? static_cast<const NumberImp *>(this)->value() : NaN;
185}
186
187bool JSCell::getString(UString &stringValue) const
188{
189 if (!isString())
190 return false;
191 stringValue = static_cast<const StringImp *>(this)->value();
192 return true;
193}
194
195UString JSCell::getString() const
196{
197 return isString() ? static_cast<const StringImp *>(this)->value() : UString();
198}
199
200JSObject *JSCell::getObject()
201{
202 return isObject() ? static_cast<JSObject *>(this) : 0;
203}
204
205const JSObject *JSCell::getObject() const
206{
207 return isObject() ? static_cast<const JSObject *>(this) : 0;
208}
209
210JSCell* jsString(const char* s)
211{
212 return new StringImp(s ? s : "");
213}
214
215JSCell* jsString(const UString& s)
216{
217 return s.isNull() ? new StringImp("") : new StringImp(s);
218}
219
220JSCell* jsOwnedString(const UString& s)
221{
222 return s.isNull() ? new StringImp("", StringImp::HasOtherOwner) : new StringImp(s, StringImp::HasOtherOwner);
223}
224
225// This method includes a PIC branch to set up the NumberImp's vtable, so we quarantine
226// it in a separate function to keep the normal case speedy.
227JSValue *jsNumberCell(double d)
228{
229 return new NumberImp(d);
230}
231
232} // namespace KJS