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

Last change on this file since 27695 was 27695, checked in by eseidel, 18 years ago

2007-11-10 Eric Seidel <[email protected]>

Reviewed by darin.

Add simple type inferencing to the parser, and create custom
AddNode and LessNode subclasses based on inferred types.
http://bugs.webkit.org/show_bug.cgi?id=15884

SunSpider claims this is at least a 0.5% speedup.

  • JavaScriptCore.exp:
  • kjs/grammar.y:
  • kjs/internal.cpp: (KJS::NumberImp::getPrimitiveNumber): (KJS::GetterSetterImp::getPrimitiveNumber):
  • kjs/internal.h:
  • kjs/lexer.cpp: (KJS::Lexer::lex):
  • kjs/nodes.cpp: (KJS::Node::Node): (KJS::StringNode::evaluate): (KJS::StringNode::evaluateToNumber): (KJS::StringNode::evaluateToBoolean): (KJS::RegExpNode::evaluate): (KJS::UnaryPlusNode::optimizeVariableAccess): (KJS::AddNode::evaluate): (KJS::AddNode::evaluateToNumber): (KJS::AddNumbersNode::inlineEvaluateToNumber): (KJS::AddNumbersNode::evaluate): (KJS::AddNumbersNode::evaluateToNumber): (KJS::AddStringsNode::evaluate): (KJS::AddStringLeftNode::evaluate): (KJS::AddStringRightNode::evaluate): (KJS::lessThan): (KJS::lessThanEq): (KJS::LessNumbersNode::evaluate): (KJS::LessStringsNode::evaluate):
  • kjs/nodes.h: (KJS::ExpressionNode::): (KJS::RegExpNode::): (KJS::RegExpNode::precedence): (KJS::TypeOfResolveNode::): (KJS::LocalVarTypeOfNode::): (KJS::UnaryPlusNode::): (KJS::UnaryPlusNode::precedence): (KJS::AddNode::): (KJS::AddNode::precedence): (KJS::AddNumbersNode::): (KJS::AddStringLeftNode::): (KJS::AddStringRightNode::): (KJS::AddStringsNode::): (KJS::LessNode::): (KJS::LessNode::precedence): (KJS::LessNumbersNode::): (KJS::LessStringsNode::):
  • kjs/nodes2string.cpp: (KJS::StringNode::streamTo):
  • kjs/object.cpp:
  • kjs/object.h:
  • kjs/value.h: (KJS::JSValue::getPrimitiveNumber):
  • Property svn:eol-style set to native
File size: 6.9 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 "ExecState.h"
27#include "array_object.h"
28#include "bool_object.h"
29#include "collector.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, JSValue*& value)
60{
61 value = this;
62 number = val.toDouble();
63 return false;
64}
65
66bool StringImp::toBoolean(ExecState *) const
67{
68 return (val.size() > 0);
69}
70
71double StringImp::toNumber(ExecState *) const
72{
73 return val.toDouble();
74}
75
76UString StringImp::toString(ExecState *) const
77{
78 return val;
79}
80
81JSObject* StringImp::toObject(ExecState *exec) const
82{
83 return new StringInstance(exec->lexicalInterpreter()->builtinStringPrototype(), const_cast<StringImp*>(this));
84}
85
86// ------------------------------ NumberImp ------------------------------------
87
88JSValue* NumberImp::toPrimitive(ExecState*, JSType) const
89{
90 return const_cast<NumberImp*>(this);
91}
92
93bool NumberImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
94{
95 number = val;
96 value = this;
97 return true;
98}
99
100bool NumberImp::toBoolean(ExecState *) const
101{
102 return val < 0.0 || val > 0.0; // false for NaN
103}
104
105double NumberImp::toNumber(ExecState *) const
106{
107 return val;
108}
109
110UString NumberImp::toString(ExecState *) const
111{
112 if (val == 0.0) // +0.0 or -0.0
113 return "0";
114 return UString::from(val);
115}
116
117JSObject *NumberImp::toObject(ExecState *exec) const
118{
119 List args;
120 args.append(const_cast<NumberImp*>(this));
121 return static_cast<JSObject *>(exec->lexicalInterpreter()->builtinNumber()->construct(exec,args));
122}
123
124bool NumberImp::getUInt32(uint32_t& uint32) const
125{
126 uint32 = static_cast<uint32_t>(val);
127 return uint32 == val;
128}
129
130bool NumberImp::getTruncatedInt32(int32_t& int32) const
131{
132 if (!(val >= -2147483648.0 && val < 2147483648.0))
133 return false;
134 int32 = static_cast<int32_t>(val);
135 return true;
136}
137
138bool NumberImp::getTruncatedUInt32(uint32_t& uint32) const
139{
140 if (!(val >= 0.0 && val < 4294967296.0))
141 return false;
142 uint32 = static_cast<uint32_t>(val);
143 return true;
144}
145
146// --------------------------- GetterSetterImp ---------------------------------
147void GetterSetterImp::mark()
148{
149 JSCell::mark();
150
151 if (getter && !getter->marked())
152 getter->mark();
153 if (setter && !setter->marked())
154 setter->mark();
155}
156
157JSValue* GetterSetterImp::toPrimitive(ExecState*, JSType) const
158{
159 ASSERT(false);
160 return jsNull();
161}
162
163bool GetterSetterImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
164{
165 ASSERT_NOT_REACHED();
166 number = 0;
167 value = 0;
168 return true;
169}
170
171bool GetterSetterImp::toBoolean(ExecState*) const
172{
173 ASSERT(false);
174 return false;
175}
176
177double GetterSetterImp::toNumber(ExecState *) const
178{
179 ASSERT(false);
180 return 0.0;
181}
182
183UString GetterSetterImp::toString(ExecState *) const
184{
185 ASSERT(false);
186 return UString::null();
187}
188
189JSObject *GetterSetterImp::toObject(ExecState *exec) const
190{
191 ASSERT(false);
192 return jsNull()->toObject(exec);
193}
194
195// ------------------------------ LabelStack -----------------------------------
196
197bool LabelStack::push(const Identifier &id)
198{
199 if (contains(id))
200 return false;
201
202 StackElem *newtos = new StackElem;
203 newtos->id = id;
204 newtos->prev = tos;
205 tos = newtos;
206 return true;
207}
208
209bool LabelStack::contains(const Identifier &id) const
210{
211 if (id.isEmpty())
212 return true;
213
214 for (StackElem *curr = tos; curr; curr = curr->prev)
215 if (curr->id == id)
216 return true;
217
218 return false;
219}
220
221// ------------------------------ InternalFunctionImp --------------------------
222
223const ClassInfo InternalFunctionImp::info = { "Function", 0, 0 };
224
225InternalFunctionImp::InternalFunctionImp()
226{
227}
228
229InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto)
230 : JSObject(funcProto)
231{
232}
233
234InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto, const Identifier& name)
235 : JSObject(funcProto)
236 , m_name(name)
237{
238}
239
240bool InternalFunctionImp::implementsCall() const
241{
242 return true;
243}
244
245bool InternalFunctionImp::implementsHasInstance() const
246{
247 return true;
248}
249
250// ------------------------------ global functions -----------------------------
251
252#ifndef NDEBUG
253#include <stdio.h>
254void printInfo(ExecState *exec, const char *s, JSValue *o, int lineno)
255{
256 if (!o)
257 fprintf(stderr, "KJS: %s: (null)", s);
258 else {
259 JSValue *v = o;
260
261 UString name;
262 switch (v->type()) {
263 case UnspecifiedType:
264 name = "Unspecified";
265 break;
266 case UndefinedType:
267 name = "Undefined";
268 break;
269 case NullType:
270 name = "Null";
271 break;
272 case BooleanType:
273 name = "Boolean";
274 break;
275 case StringType:
276 name = "String";
277 break;
278 case NumberType:
279 name = "Number";
280 break;
281 case ObjectType:
282 name = static_cast<JSObject *>(v)->className();
283 if (name.isNull())
284 name = "(unknown class)";
285 break;
286 case GetterSetterType:
287 name = "GetterSetter";
288 break;
289 }
290 UString vString = v->toString(exec);
291 if ( vString.size() > 50 )
292 vString = vString.substr( 0, 50 ) + "...";
293 // Can't use two UString::ascii() in the same fprintf call
294 CString tempString( vString.cstring() );
295
296 fprintf(stderr, "KJS: %s: %s : %s (%p)",
297 s, tempString.c_str(), name.ascii(), (void*)v);
298
299 if (lineno >= 0)
300 fprintf(stderr, ", line %d\n",lineno);
301 else
302 fprintf(stderr, "\n");
303 }
304}
305#endif
306
307}
Note: See TracBrowser for help on using the repository browser.