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

Last change on this file since 34518 was 34518, checked in by Darin Adler, 17 years ago

2008-06-12 Darin Adler <Darin Adler>

Reviewed by Maciej.

Speeds up SunSpider by 1.1%.

Optimized code path for getting built-in properties from strings -- avoid
boxing with a string object in that case. We can make further changes to avoid
even more boxing, but this change alone is a win.

  • API/JSCallbackObjectFunctions.h: (KJS::JSCallbackObject::staticValueGetter): Use isObject instead of inherits in asssert, since the type of slotBase() is now JSValue, not JSObject. (KJS::JSCallbackObject::staticFunctionGetter): Ditto. (KJS::JSCallbackObject::callbackGetter): Ditto.
  • kjs/internal.cpp: (KJS::StringImp::getPrimitiveNumber): Updated for change of data member name. (KJS::StringImp::toBoolean): Ditto. (KJS::StringImp::toNumber): Ditto. (KJS::StringImp::toString): Ditto. (KJS::StringInstance::create): Added; avoids a bit of cut and paste code. (KJS::StringImp::toObject): Use StringInstance::create. (KJS::StringImp::toThisObject): Ditto. (KJS::StringImp::lengthGetter): Added. Replaces the getter that used to live in the StringInstance class. (KJS::StringImp::indexGetter): Ditto. (KJS::StringImp::indexNumericPropertyGetter): Ditto. (KJS::StringImp::getOwnPropertySlot): Added. Deals with built in properties of the string class without creating a StringInstance.
  • kjs/internal.h: (KJS::StringImp::getStringPropertySlot): Added. To be used by both the string and string object getOwnPropertySlot function.
  • kjs/lookup.h: (KJS::staticFunctionGetter): Updated since slotBase() is now a JSValue rather than a JSObject.
  • kjs/object.h: Removed PropertySlot::slotBase() function, which can now move back into property_slot.h where it belongs since it doesn't have to cast to JSObject*.
  • kjs/property_slot.cpp: (KJS::PropertySlot::functionGetter): Updated since slot.slotBase() is now a JSValue* instead of JSObject*. setGetterSlot still guarantees the base is a JSObject*.
  • kjs/property_slot.h: (KJS::PropertySlot::PropertySlot): Changed base to JSValue* intead of JSCell*. (KJS::PropertySlot::setStaticEntry): Ditto. (KJS::PropertySlot::setCustom): Ditto. (KJS::PropertySlot::setCustomIndex): Ditto. (KJS::PropertySlot::setCustomNumeric): Ditto. (KJS::PropertySlot::slotBase): Moved inline here since it no longer involves a downcast to JSObject*. (KJS::PropertySlot::setBase): Changed to JSValue*.
  • kjs/string_object.cpp: (KJS::StringInstance::getOwnPropertySlot): Changed to use getStringPropertySlot instead of coding the properties here. This allows sharing the code with StringImp.
  • kjs/string_object.h: Removed inlineGetOwnPropertySlot, lengthGetter, and indexGetter. Made one of the constructors protected.
  • kjs/value.h: Made getOwnPropertySlot private in the JSCell class -- this is better since it's not the real JSObject getOwnPropertySlot semantic and most callers shouldn't use it.
  • Property svn:eol-style set to native
File size: 8.3 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, 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 "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 = m_value.toDouble();
63 return false;
64}
65
66bool StringImp::toBoolean(ExecState*) const
67{
68 return !m_value.isEmpty();
69}
70
71double StringImp::toNumber(ExecState*) const
72{
73 return m_value.toDouble();
74}
75
76UString StringImp::toString(ExecState*) const
77{
78 return m_value;
79}
80
81inline StringInstance* StringInstance::create(ExecState* exec, StringImp* string)
82{
83 return new StringInstance(exec->lexicalGlobalObject()->stringPrototype(), string);
84}
85
86JSObject* StringImp::toObject(ExecState* exec) const
87{
88 return StringInstance::create(exec, const_cast<StringImp*>(this));
89}
90
91JSObject* StringImp::toThisObject(ExecState* exec) const
92{
93 return StringInstance::create(exec, const_cast<StringImp*>(this));
94}
95
96JSValue* StringImp::lengthGetter(ExecState*, const Identifier&, const PropertySlot& slot)
97{
98 return jsNumber(static_cast<StringImp*>(slot.slotBase())->value().size());
99}
100
101JSValue* StringImp::indexGetter(ExecState*, const Identifier&, const PropertySlot& slot)
102{
103 return jsString(static_cast<StringImp*>(slot.slotBase())->value().substr(slot.index(), 1));
104}
105
106JSValue* StringImp::indexNumericPropertyGetter(ExecState*, unsigned index, const PropertySlot& slot)
107{
108 return jsString(static_cast<StringImp*>(slot.slotBase())->value().substr(index, 1));
109}
110
111bool StringImp::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
112{
113 // The semantics here are really getPropertySlot, not getOwnPropertySlot.
114 // This function should only be called by JSValue::get.
115 if (getStringPropertySlot(exec, propertyName, slot))
116 return true;
117 JSObject* object = StringInstance::create(exec, this);
118 slot.setBase(object);
119 if (object->JSObject::getOwnPropertySlot(exec, propertyName, slot))
120 return true;
121 while (true) {
122 JSValue* proto = object->prototype();
123 if (!proto->isObject()) {
124 slot.setUndefined();
125 return true;
126 }
127 object = static_cast<JSObject*>(proto);
128 if (object->getOwnPropertySlot(exec, propertyName, slot))
129 return true;
130 }
131}
132
133bool StringImp::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
134{
135 // The semantics here are really getPropertySlot, not getOwnPropertySlot.
136 // This function should only be called by JSValue::get.
137 if (getStringPropertySlot(propertyName, slot))
138 return true;
139 return StringImp::getOwnPropertySlot(exec, Identifier::from(propertyName), slot);
140}
141
142// ------------------------------ NumberImp ------------------------------------
143
144JSType NumberImp::type() const
145{
146 return NumberType;
147}
148
149JSValue* NumberImp::toPrimitive(ExecState*, JSType) const
150{
151 return const_cast<NumberImp*>(this);
152}
153
154bool NumberImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
155{
156 number = val;
157 value = this;
158 return true;
159}
160
161bool NumberImp::toBoolean(ExecState *) const
162{
163 return val < 0.0 || val > 0.0; // false for NaN
164}
165
166double NumberImp::toNumber(ExecState *) const
167{
168 return val;
169}
170
171UString NumberImp::toString(ExecState *) const
172{
173 if (val == 0.0) // +0.0 or -0.0
174 return "0";
175 return UString::from(val);
176}
177
178JSObject *NumberImp::toObject(ExecState *exec) const
179{
180 List args;
181 args.append(const_cast<NumberImp*>(this));
182 return static_cast<JSObject *>(exec->lexicalGlobalObject()->numberConstructor()->construct(exec,args));
183}
184
185JSObject* NumberImp::toThisObject(ExecState* exec) const
186{
187 List args;
188 args.append(const_cast<NumberImp*>(this));
189 return static_cast<JSObject*>(exec->lexicalGlobalObject()->numberConstructor()->construct(exec, args));
190}
191
192bool NumberImp::getUInt32(uint32_t& uint32) const
193{
194 uint32 = static_cast<uint32_t>(val);
195 return uint32 == val;
196}
197
198bool NumberImp::getTruncatedInt32(int32_t& int32) const
199{
200 if (!(val >= -2147483648.0 && val < 2147483648.0))
201 return false;
202 int32 = static_cast<int32_t>(val);
203 return true;
204}
205
206bool NumberImp::getTruncatedUInt32(uint32_t& uint32) const
207{
208 if (!(val >= 0.0 && val < 4294967296.0))
209 return false;
210 uint32 = static_cast<uint32_t>(val);
211 return true;
212}
213
214// --------------------------- GetterSetterImp ---------------------------------
215void GetterSetterImp::mark()
216{
217 JSCell::mark();
218
219 if (getter && !getter->marked())
220 getter->mark();
221 if (setter && !setter->marked())
222 setter->mark();
223}
224
225JSValue* GetterSetterImp::toPrimitive(ExecState*, JSType) const
226{
227 ASSERT(false);
228 return jsNull();
229}
230
231bool GetterSetterImp::getPrimitiveNumber(ExecState*, double& number, JSValue*& value)
232{
233 ASSERT_NOT_REACHED();
234 number = 0;
235 value = 0;
236 return true;
237}
238
239bool GetterSetterImp::toBoolean(ExecState*) const
240{
241 ASSERT(false);
242 return false;
243}
244
245double GetterSetterImp::toNumber(ExecState *) const
246{
247 ASSERT(false);
248 return 0.0;
249}
250
251UString GetterSetterImp::toString(ExecState *) const
252{
253 ASSERT(false);
254 return UString::null();
255}
256
257JSObject *GetterSetterImp::toObject(ExecState *exec) const
258{
259 ASSERT(false);
260 return jsNull()->toObject(exec);
261}
262
263bool GetterSetterImp::getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&)
264{
265 ASSERT_NOT_REACHED();
266 return false;
267}
268
269bool GetterSetterImp::getOwnPropertySlot(ExecState*, unsigned, PropertySlot&)
270{
271 ASSERT_NOT_REACHED();
272 return false;
273}
274
275void GetterSetterImp::put(ExecState*, const Identifier&, JSValue*)
276{
277 ASSERT_NOT_REACHED();
278}
279
280void GetterSetterImp::put(ExecState*, unsigned, JSValue*)
281{
282 ASSERT_NOT_REACHED();
283}
284
285JSObject* GetterSetterImp::toThisObject(ExecState*) const
286{
287 ASSERT_NOT_REACHED();
288 return 0;
289}
290
291// ------------------------------ LabelStack -----------------------------------
292
293bool LabelStack::push(const Identifier &id)
294{
295 if (contains(id))
296 return false;
297
298 StackElem *newtos = new StackElem;
299 newtos->id = id;
300 newtos->prev = tos;
301 tos = newtos;
302 return true;
303}
304
305bool LabelStack::contains(const Identifier &id) const
306{
307 if (id.isEmpty())
308 return true;
309
310 for (StackElem *curr = tos; curr; curr = curr->prev)
311 if (curr->id == id)
312 return true;
313
314 return false;
315}
316
317// ------------------------------ InternalFunctionImp --------------------------
318
319const ClassInfo InternalFunctionImp::info = { "Function", 0, 0, 0 };
320
321InternalFunctionImp::InternalFunctionImp()
322{
323}
324
325InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto, const Identifier& name)
326 : JSObject(funcProto)
327 , m_name(name)
328{
329}
330
331CallType InternalFunctionImp::getCallData(CallData&)
332{
333 return CallTypeNative;
334}
335
336bool InternalFunctionImp::implementsHasInstance() const
337{
338 return true;
339}
340
341}
Note: See TracBrowser for help on using the repository browser.