source: webkit/trunk/JavaScriptCore/kjs/Arguments.cpp@ 36804

Last change on this file since 36804 was 36804, checked in by [email protected], 17 years ago

2008-09-23 Cameron Zwarich <[email protected]>

Reviewed by Oliver Hunt.

Bug 20989: Aguments constructor should put 'callee' and 'length' properties in a more efficient way
<https://bugs.webkit.org/show_bug.cgi?id=20989>

Make special cases for the 'callee' and 'length' properties in the
Arguments object.

This is somewhere between a 7.8% speedup and a 10% speedup on the V8
Raytrace benchmark, depending on whether it is run alone or with the
other V8 benchmarks.

  • kjs/Arguments.cpp: (JSC::ArgumentsData::ArgumentsData): (JSC::Arguments::Arguments): (JSC::Arguments::mark): (JSC::Arguments::getOwnPropertySlot): (JSC::Arguments::put): (JSC::Arguments::deleteProperty):
  • Property svn:eol-style set to native
File size: 8.9 KB
Line 
1/*
2 * Copyright (C) 1999-2002 Harri Porten ([email protected])
3 * Copyright (C) 2001 Peter Kelly ([email protected])
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 * Copyright (C) 2007 Cameron Zwarich ([email protected])
6 * Copyright (C) 2007 Maks Orlovich
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#include "config.h"
26#include "Arguments.h"
27
28#include "JSActivation.h"
29#include "JSFunction.h"
30#include "JSGlobalObject.h"
31
32using namespace std;
33
34namespace JSC {
35
36ASSERT_CLASS_FITS_IN_CELL(Arguments);
37
38const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };
39
40struct ArgumentsData : Noncopyable {
41 ArgumentsData(JSActivation* activation, unsigned numParameters, unsigned firstArgumentIndex, unsigned numArguments, JSFunction* callee)
42 : activation(activation)
43 , numParameters(numParameters)
44 , firstArgumentIndex(firstArgumentIndex)
45 , numArguments(numArguments)
46 , extraArguments(0)
47 , callee(callee)
48 , overrodeLength(false)
49 , overrodeCallee(false)
50 {
51 }
52
53 JSActivation* activation;
54
55 unsigned numParameters;
56 unsigned firstArgumentIndex;
57 unsigned numArguments;
58 Register* extraArguments;
59 OwnArrayPtr<bool> deletedArguments;
60 Register extraArgumentsFixedBuffer[4];
61
62 JSFunction* callee;
63 bool overrodeLength : 1;
64 bool overrodeCallee : 1;
65};
66
67// ECMA 10.1.8
68Arguments::Arguments(ExecState* exec, JSFunction* function, JSActivation* activation, int firstArgumentIndex, Register* argv, int argc)
69 : JSObject(exec->lexicalGlobalObject()->argumentsStructure())
70 , d(new ArgumentsData(activation, function->numParameters(), firstArgumentIndex, argc, function))
71{
72 ASSERT(activation);
73
74 if (d->numArguments > d->numParameters) {
75 unsigned numExtraArguments = d->numArguments - d->numParameters;
76 Register* extraArguments;
77 if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
78 extraArguments = new Register[numExtraArguments];
79 else
80 extraArguments = d->extraArgumentsFixedBuffer;
81 for (unsigned i = 0; i < numExtraArguments; ++i)
82 extraArguments[i] = argv[d->numParameters + i];
83 d->extraArguments = extraArguments;
84 }
85}
86
87Arguments::~Arguments()
88{
89 if (d->extraArguments != d->extraArgumentsFixedBuffer)
90 delete [] d->extraArguments;
91}
92
93void Arguments::mark()
94{
95 JSObject::mark();
96
97 if (d->extraArguments) {
98 unsigned numExtraArguments = d->numArguments - d->numParameters;
99 for (unsigned i = 0; i < numExtraArguments; ++i) {
100 if (!d->extraArguments[i].marked())
101 d->extraArguments[i].mark();
102 }
103 }
104
105 if (!d->callee->marked())
106 d->callee->mark();
107
108 if (!d->activation->marked())
109 d->activation->mark();
110}
111
112void Arguments::fillArgList(ExecState* exec, ArgList& args)
113{
114 if (LIKELY(!d->deletedArguments)) {
115 if (LIKELY(!d->numParameters)) {
116 args.initialize(d->extraArguments, d->numArguments);
117 return;
118 }
119
120 if (d->numParameters == d->numArguments) {
121 args.initialize(&d->activation->registerAt(d->firstArgumentIndex), d->numArguments);
122 return;
123 }
124
125 unsigned parametersLength = min(d->numParameters, d->numArguments);
126 unsigned i = 0;
127 for (; i < parametersLength; ++i)
128 args.append(d->activation->uncheckedSymbolTableGetValue(d->firstArgumentIndex + i));
129 for (; i < d->numArguments; ++i)
130 args.append(d->extraArguments[i - d->numParameters].getJSValue());
131 return;
132 }
133
134 unsigned parametersLength = min(d->numParameters, d->numArguments);
135 unsigned i = 0;
136 for (; i < parametersLength; ++i) {
137 if (!d->deletedArguments[i])
138 args.append(d->activation->uncheckedSymbolTableGetValue(d->firstArgumentIndex + i));
139 else
140 args.append(get(exec, i));
141 }
142 for (; i < d->numArguments; ++i) {
143 if (!d->deletedArguments[i])
144 args.append(d->extraArguments[i - d->numParameters].getJSValue());
145 else
146 args.append(get(exec, i));
147 }
148}
149
150bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
151{
152 if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
153 if (i < d->numParameters)
154 d->activation->uncheckedSymbolTableGet(d->firstArgumentIndex + i, slot);
155 else
156 slot.setValue(d->extraArguments[i - d->numParameters].getJSValue());
157 return true;
158 }
159
160 return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::from(i)), slot);
161}
162
163bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
164{
165 bool isArrayIndex;
166 unsigned i = propertyName.toArrayIndex(&isArrayIndex);
167 if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
168 if (i < d->numParameters)
169 d->activation->uncheckedSymbolTableGet(d->firstArgumentIndex + i, slot);
170 else
171 slot.setValue(d->extraArguments[i - d->numParameters].getJSValue());
172 return true;
173 }
174
175 if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
176 slot.setValue(jsNumber(exec, d->numArguments));
177 return true;
178 }
179
180 if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
181 slot.setValue(d->callee);
182 return true;
183 }
184
185 return JSObject::getOwnPropertySlot(exec, propertyName, slot);
186}
187
188void Arguments::put(ExecState* exec, unsigned i, JSValue* value, PutPropertySlot& slot)
189{
190 if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
191 if (i < d->numParameters)
192 d->activation->uncheckedSymbolTablePut(d->firstArgumentIndex + i, value);
193 else
194 d->extraArguments[i - d->numParameters] = value;
195 return;
196 }
197
198 JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot);
199}
200
201void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
202{
203 bool isArrayIndex;
204 unsigned i = propertyName.toArrayIndex(&isArrayIndex);
205 if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
206 if (i < d->numParameters)
207 d->activation->uncheckedSymbolTablePut(d->firstArgumentIndex + i, value);
208 else
209 d->extraArguments[i - d->numParameters] = value;
210 return;
211 }
212
213 if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
214 d->overrodeLength = true;
215 putDirect(propertyName, value, DontEnum);
216 return;
217 }
218
219 if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
220 d->overrodeCallee = true;
221 putDirect(propertyName, value, DontEnum);
222 return;
223 }
224
225 JSObject::put(exec, propertyName, value, slot);
226}
227
228bool Arguments::deleteProperty(ExecState* exec, unsigned i)
229{
230 if (i < d->numArguments) {
231 if (!d->deletedArguments) {
232 d->deletedArguments.set(new bool[d->numArguments]);
233 memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
234 }
235 if (!d->deletedArguments[i]) {
236 d->deletedArguments[i] = true;
237 return true;
238 }
239 }
240
241 return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i)));
242}
243
244bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)
245{
246 bool isArrayIndex;
247 unsigned i = propertyName.toArrayIndex(&isArrayIndex);
248 if (isArrayIndex && i < d->numArguments) {
249 if (!d->deletedArguments) {
250 d->deletedArguments.set(new bool[d->numArguments]);
251 memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
252 }
253 if (!d->deletedArguments[i]) {
254 d->deletedArguments[i] = true;
255 return true;
256 }
257 }
258
259 if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
260 d->overrodeLength = true;
261 return true;
262 }
263
264 if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
265 d->overrodeCallee = true;
266 return true;
267 }
268
269 return JSObject::deleteProperty(exec, propertyName);
270}
271
272} // namespace JSC
Note: See TracBrowser for help on using the repository browser.