source: webkit/trunk/JavaScriptCore/kjs/internal.cpp@ 27095

Last change on this file since 27095 was 27095, checked in by darin, 18 years ago

JavaScriptCore:

Reviewed by Maciej.

Gives about 1% gain on SunSpider.

  • kjs/value.h: Added toIntegerPreserveNan, removed toUInt16. (KJS::JSValue::toInt32): Changed to call getTruncatedInt32 in a way that works with both immediate and number values. (KJS::JSValue::toUInt32): Ditto.
  • kjs/value.cpp: (KJS::JSValue::toInteger): Moved the logic from roundValue here, with a couple differences. One is that it now correctly returns 0 for NaN, and another is that there's no special case for 0 or infinity, since the general case already handles those correctly. (KJS::JSValue::toIntegerPreserveNaN): Added. Like toInteger, but without the check for NaN. (KJS::JSValue::toInt32SlowCase): Call toNumber instead of roundValue. The truncation done by the typecast already does the necessary truncation that roundValue was doing. (KJS::JSValue::toUInt32SlowCase): Ditto. (KJS::JSValue::toUInt16): Removed.
  • kjs/internal.h: Removed roundValue.
  • kjs/internal.cpp: Ditto.
  • kjs/array_object.cpp: (KJS::ArrayProtoFunc::callAsFunction): Remove unneeded code to handle NaN in Array.slice; toInteger now never returns NaN as specified.
  • kjs/date_object.cpp: (KJS::fillStructuresUsingTimeArgs): Replaced call to roundValue with a call to toNumber as specified. (KJS::DateProtoFunc::callAsFunction): In SetTime case, replaced call to roundValue with a call to toNumber and timeClip as specified. (KJS::DateObjectImp::construct): Removed unnecessary checks of numArgs in cases where the default behavior of toInt32 (returning 0) was already correct. Replaced call to roundValue with a call to toNumber as specified. (KJS::DateObjectFuncImp::callAsFunction): Ditto.
  • kjs/math_object.cpp: (MathFuncImp::callAsFunction): Removed unnecessary special cases for the pow function that the library already handles correctly.
  • kjs/number_object.cpp: (NumberProtoFunc::callAsFunction): Changed ToString to call toIntegerPreserveNaN, so we can continue to handle the NaN case differently. The real toInteger now returns 0 for NaN. Took out unneeded special case in ToFixed for undefined; was only needed because our toInteger was wrong. Same thing in ToExponential. Changed ToPrecision to call toIntegerPreserveNaN.
  • kjs/string_object.cpp: (KJS::StringProtoFunc::callAsFunction): Took out CharAt and CharCodeAt special cases for undefined that were only needed because toInteger was wrong. Same in IndexOf, and was able to remove some special cases. In LastIndexOf, used toIntegerPreserveNaN, but was able to remove some special cases there too. Changed Substr implementation to preserve correct behavior with the change to toInteger and match the specification. Also made sure we weren't converting an out of range double to an int. (KJS::StringObjectFuncImp::callAsFunction): Changed constructor to just use toUInt32, because truncating toUInt32 to 16 bits is the same thing and there's no reason to have toUInt16 as a second, less-optimized function that's only called at this one call site.
  • wtf/MathExtras.h: Added trunc function for Windows.

LayoutTests:

Reviewed by Maciej.

  • fast/js/resources/char-at.js: Updated test to expect that we get the first character if we pass NaN to charAt and charCodeAt; it's what the specification asks for and matches other browsers too.
  • fast/js/char-at-expected.txt: Updated.
  • Property svn:eol-style set to native
File size: 6.8 KB
Line 
1/*
2 * Copyright (C) 1999-2002 Harri Porten ([email protected])
3 * Copyright (C) 2001 Peter Kelly ([email protected])
4 * Copyright (C) 2004, 2007 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 "internal.h"
25
26#include "array_object.h"
27#include "bool_object.h"
28#include "collector.h"
29#include "context.h"
30#include "date_object.h"
31#include "debugger.h"
32#include "error_object.h"
33#include "function_object.h"
34#include "lexer.h"
35#include "math_object.h"
36#include "nodes.h"
37#include "number_object.h"
38#include "object.h"
39#include "object_object.h"
40#include "operations.h"
41#include "regexp_object.h"
42#include "string_object.h"
43#include <math.h>
44#include <stdio.h>
45#include <wtf/Assertions.h>
46#include <wtf/HashMap.h>
47#include <wtf/HashSet.h>
48#include <wtf/Vector.h>
49
50namespace KJS {
51
52// ------------------------------ StringImp ------------------------------------
53
54JSValue* StringImp::toPrimitive(ExecState*, JSType) const
55{
56 return const_cast<StringImp*>(this);
57}
58
59bool StringImp::getPrimitiveNumber(ExecState*, double& number) const
60{
61 number = val.toDouble();
62 return false;
63}
64
65bool StringImp::toBoolean(ExecState *) const
66{
67 return (val.size() > 0);
68}
69
70double StringImp::toNumber(ExecState *) const
71{
72 return val.toDouble();
73}
74
75UString StringImp::toString(ExecState *) const
76{
77 return val;
78}
79
80JSObject* StringImp::toObject(ExecState *exec) const
81{
82 return new StringInstance(exec->lexicalInterpreter()->builtinStringPrototype(), const_cast<StringImp*>(this));
83}
84
85// ------------------------------ NumberImp ------------------------------------
86
87JSValue* NumberImp::toPrimitive(ExecState*, JSType) const
88{
89 return const_cast<NumberImp*>(this);
90}
91
92bool NumberImp::getPrimitiveNumber(ExecState*, double& number) const
93{
94 number = val;
95 return true;
96}
97
98bool NumberImp::toBoolean(ExecState *) const
99{
100 return val < 0.0 || val > 0.0; // false for NaN
101}
102
103double NumberImp::toNumber(ExecState *) const
104{
105 return val;
106}
107
108UString NumberImp::toString(ExecState *) const
109{
110 if (val == 0.0) // +0.0 or -0.0
111 return "0";
112 return UString::from(val);
113}
114
115JSObject *NumberImp::toObject(ExecState *exec) const
116{
117 List args;
118 args.append(const_cast<NumberImp*>(this));
119 return static_cast<JSObject *>(exec->lexicalInterpreter()->builtinNumber()->construct(exec,args));
120}
121
122bool NumberImp::getUInt32(uint32_t& uint32) const
123{
124 uint32 = static_cast<uint32_t>(val);
125 return uint32 == val;
126}
127
128bool NumberImp::getTruncatedInt32(int32_t& int32) const
129{
130 if (!(val >= -2147483648.0 && val < 2147483648.0))
131 return false;
132 int32 = static_cast<int32_t>(val);
133 return true;
134}
135
136bool NumberImp::getTruncatedUInt32(uint32_t& uint32) const
137{
138 if (!(val >= 0.0 && val < 4294967296.0))
139 return false;
140 uint32 = static_cast<uint32_t>(val);
141 return true;
142}
143
144// --------------------------- GetterSetterImp ---------------------------------
145void GetterSetterImp::mark()
146{
147 JSCell::mark();
148
149 if (getter && !getter->marked())
150 getter->mark();
151 if (setter && !setter->marked())
152 setter->mark();
153}
154
155JSValue* GetterSetterImp::toPrimitive(ExecState*, JSType) const
156{
157 ASSERT(false);
158 return jsNull();
159}
160
161bool GetterSetterImp::getPrimitiveNumber(ExecState*, double& number) const
162{
163 ASSERT(false);
164 number = 0;
165 return true;
166}
167
168bool GetterSetterImp::toBoolean(ExecState*) const
169{
170 ASSERT(false);
171 return false;
172}
173
174double GetterSetterImp::toNumber(ExecState *) const
175{
176 ASSERT(false);
177 return 0.0;
178}
179
180UString GetterSetterImp::toString(ExecState *) const
181{
182 ASSERT(false);
183 return UString::null();
184}
185
186JSObject *GetterSetterImp::toObject(ExecState *exec) const
187{
188 ASSERT(false);
189 return jsNull()->toObject(exec);
190}
191
192// ------------------------------ LabelStack -----------------------------------
193
194bool LabelStack::push(const Identifier &id)
195{
196 if (contains(id))
197 return false;
198
199 StackElem *newtos = new StackElem;
200 newtos->id = id;
201 newtos->prev = tos;
202 tos = newtos;
203 return true;
204}
205
206bool LabelStack::contains(const Identifier &id) const
207{
208 if (id.isEmpty())
209 return true;
210
211 for (StackElem *curr = tos; curr; curr = curr->prev)
212 if (curr->id == id)
213 return true;
214
215 return false;
216}
217
218// ------------------------------ InternalFunctionImp --------------------------
219
220const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
221
222InternalFunctionImp::InternalFunctionImp()
223{
224}
225
226InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto)
227 : JSObject(funcProto)
228{
229}
230
231InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto, const Identifier& name)
232 : JSObject(funcProto)
233 , m_name(name)
234{
235}
236
237bool InternalFunctionImp::implementsCall() const
238{
239 return true;
240}
241
242bool InternalFunctionImp::implementsHasInstance() const
243{
244 return true;
245}
246
247// ------------------------------ global functions -----------------------------
248
249#ifndef NDEBUG
250#include <stdio.h>
251void printInfo(ExecState *exec, const char *s, JSValue *o, int lineno)
252{
253 if (!o)
254 fprintf(stderr, "KJS: %s: (null)", s);
255 else {
256 JSValue *v = o;
257
258 UString name;
259 switch (v->type()) {
260 case UnspecifiedType:
261 name = "Unspecified";
262 break;
263 case UndefinedType:
264 name = "Undefined";
265 break;
266 case NullType:
267 name = "Null";
268 break;
269 case BooleanType:
270 name = "Boolean";
271 break;
272 case StringType:
273 name = "String";
274 break;
275 case NumberType:
276 name = "Number";
277 break;
278 case ObjectType:
279 name = static_cast<JSObject *>(v)->className();
280 if (name.isNull())
281 name = "(unknown class)";
282 break;
283 case GetterSetterType:
284 name = "GetterSetter";
285 break;
286 }
287 UString vString = v->toString(exec);
288 if ( vString.size() > 50 )
289 vString = vString.substr( 0, 50 ) + "...";
290 // Can't use two UString::ascii() in the same fprintf call
291 CString tempString( vString.cstring() );
292
293 fprintf(stderr, "KJS: %s: %s : %s (%p)",
294 s, tempString.c_str(), name.ascii(), (void*)v);
295
296 if (lineno >= 0)
297 fprintf(stderr, ", line %d\n",lineno);
298 else
299 fprintf(stderr, "\n");
300 }
301}
302#endif
303
304}
Note: See TracBrowser for help on using the repository browser.