]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/Arguments.cpp
JavaScriptCore-721.26.tar.gz
[apple/javascriptcore.git] / runtime / Arguments.cpp
CommitLineData
9dae56ea
A
1/*
2 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
f9bf01c6 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
9dae56ea
A
5 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
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
40Arguments::~Arguments()
41{
42 if (d->extraArguments != d->extraArgumentsFixedBuffer)
43 delete [] d->extraArguments;
44}
45
f9bf01c6 46void Arguments::markChildren(MarkStack& markStack)
9dae56ea 47{
f9bf01c6 48 JSObject::markChildren(markStack);
9dae56ea 49
f9bf01c6
A
50 if (d->registerArray)
51 markStack.appendValues(reinterpret_cast<JSValue*>(d->registerArray.get()), d->numParameters);
9dae56ea
A
52
53 if (d->extraArguments) {
54 unsigned numExtraArguments = d->numArguments - d->numParameters;
f9bf01c6 55 markStack.appendValues(reinterpret_cast<JSValue*>(d->extraArguments), numExtraArguments);
9dae56ea
A
56 }
57
f9bf01c6 58 markStack.append(d->callee);
9dae56ea 59
f9bf01c6
A
60 if (d->activation)
61 markStack.append(d->activation);
9dae56ea
A
62}
63
ba379fdc 64void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
9dae56ea 65{
ba379fdc
A
66 if (UNLIKELY(d->overrodeLength)) {
67 unsigned length = min(get(exec, exec->propertyNames().length).toUInt32(exec), maxSize);
68 for (unsigned i = 0; i < length; i++)
69 buffer[i] = get(exec, i);
70 return;
71 }
72
73 if (LIKELY(!d->deletedArguments)) {
74 unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
75 unsigned i = 0;
76 for (; i < parametersLength; ++i)
77 buffer[i] = d->registers[d->firstParameterIndex + i].jsValue();
78 for (; i < d->numArguments; ++i)
79 buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
80 return;
81 }
82
83 unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
84 unsigned i = 0;
85 for (; i < parametersLength; ++i) {
86 if (!d->deletedArguments[i])
87 buffer[i] = d->registers[d->firstParameterIndex + i].jsValue();
88 else
89 buffer[i] = get(exec, i);
90 }
91 for (; i < d->numArguments; ++i) {
92 if (!d->deletedArguments[i])
93 buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
94 else
95 buffer[i] = get(exec, i);
96 }
97}
98
99void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
100{
101 if (UNLIKELY(d->overrodeLength)) {
102 unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec);
103 for (unsigned i = 0; i < length; i++)
104 args.append(get(exec, i));
105 return;
106 }
107
9dae56ea
A
108 if (LIKELY(!d->deletedArguments)) {
109 if (LIKELY(!d->numParameters)) {
110 args.initialize(d->extraArguments, d->numArguments);
111 return;
112 }
113
114 if (d->numParameters == d->numArguments) {
115 args.initialize(&d->registers[d->firstParameterIndex], d->numArguments);
116 return;
117 }
118
119 unsigned parametersLength = min(d->numParameters, d->numArguments);
120 unsigned i = 0;
121 for (; i < parametersLength; ++i)
ba379fdc 122 args.append(d->registers[d->firstParameterIndex + i].jsValue());
9dae56ea 123 for (; i < d->numArguments; ++i)
ba379fdc 124 args.append(d->extraArguments[i - d->numParameters].jsValue());
9dae56ea
A
125 return;
126 }
127
128 unsigned parametersLength = min(d->numParameters, d->numArguments);
129 unsigned i = 0;
130 for (; i < parametersLength; ++i) {
131 if (!d->deletedArguments[i])
ba379fdc 132 args.append(d->registers[d->firstParameterIndex + i].jsValue());
9dae56ea
A
133 else
134 args.append(get(exec, i));
135 }
136 for (; i < d->numArguments; ++i) {
137 if (!d->deletedArguments[i])
ba379fdc 138 args.append(d->extraArguments[i - d->numParameters].jsValue());
9dae56ea
A
139 else
140 args.append(get(exec, i));
141 }
142}
143
144bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
145{
146 if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
147 if (i < d->numParameters) {
148 slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
149 } else
ba379fdc 150 slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
9dae56ea
A
151 return true;
152 }
153
154 return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::from(i)), slot);
155}
156
157bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
158{
159 bool isArrayIndex;
160 unsigned i = propertyName.toArrayIndex(&isArrayIndex);
161 if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
162 if (i < d->numParameters) {
163 slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
164 } else
ba379fdc 165 slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
9dae56ea
A
166 return true;
167 }
168
169 if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
170 slot.setValue(jsNumber(exec, d->numArguments));
171 return true;
172 }
173
174 if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
175 slot.setValue(d->callee);
176 return true;
177 }
178
179 return JSObject::getOwnPropertySlot(exec, propertyName, slot);
180}
181
f9bf01c6
A
182bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
183{
184 bool isArrayIndex;
185 unsigned i = propertyName.toArrayIndex(&isArrayIndex);
186 if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
187 if (i < d->numParameters) {
188 descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].jsValue(), DontEnum);
189 } else
190 descriptor.setDescriptor(d->extraArguments[i - d->numParameters].jsValue(), DontEnum);
191 return true;
192 }
193
194 if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
195 descriptor.setDescriptor(jsNumber(exec, d->numArguments), DontEnum);
196 return true;
197 }
198
199 if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
200 descriptor.setDescriptor(d->callee, DontEnum);
201 return true;
202 }
203
204 return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
205}
206
207void Arguments::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
208{
209 if (mode == IncludeDontEnumProperties) {
210 for (unsigned i = 0; i < d->numArguments; ++i) {
211 if (!d->deletedArguments || !d->deletedArguments[i])
212 propertyNames.add(Identifier(exec, UString::from(i)));
213 }
214 propertyNames.add(exec->propertyNames().callee);
215 propertyNames.add(exec->propertyNames().length);
216 }
217 JSObject::getOwnPropertyNames(exec, propertyNames, mode);
218}
219
ba379fdc 220void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot)
9dae56ea
A
221{
222 if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
223 if (i < d->numParameters)
ba379fdc 224 d->registers[d->firstParameterIndex + i] = JSValue(value);
9dae56ea 225 else
ba379fdc 226 d->extraArguments[i - d->numParameters] = JSValue(value);
9dae56ea
A
227 return;
228 }
229
230 JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot);
231}
232
ba379fdc 233void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
9dae56ea
A
234{
235 bool isArrayIndex;
236 unsigned i = propertyName.toArrayIndex(&isArrayIndex);
237 if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
238 if (i < d->numParameters)
ba379fdc 239 d->registers[d->firstParameterIndex + i] = JSValue(value);
9dae56ea 240 else
ba379fdc 241 d->extraArguments[i - d->numParameters] = JSValue(value);
9dae56ea
A
242 return;
243 }
244
245 if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
246 d->overrodeLength = true;
247 putDirect(propertyName, value, DontEnum);
248 return;
249 }
250
251 if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
252 d->overrodeCallee = true;
253 putDirect(propertyName, value, DontEnum);
254 return;
255 }
256
257 JSObject::put(exec, propertyName, value, slot);
258}
259
260bool Arguments::deleteProperty(ExecState* exec, unsigned i)
261{
262 if (i < d->numArguments) {
263 if (!d->deletedArguments) {
264 d->deletedArguments.set(new bool[d->numArguments]);
265 memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
266 }
267 if (!d->deletedArguments[i]) {
268 d->deletedArguments[i] = true;
269 return true;
270 }
271 }
272
273 return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i)));
274}
275
276bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)
277{
278 bool isArrayIndex;
279 unsigned i = propertyName.toArrayIndex(&isArrayIndex);
280 if (isArrayIndex && i < d->numArguments) {
281 if (!d->deletedArguments) {
282 d->deletedArguments.set(new bool[d->numArguments]);
283 memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
284 }
285 if (!d->deletedArguments[i]) {
286 d->deletedArguments[i] = true;
287 return true;
288 }
289 }
290
291 if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
292 d->overrodeLength = true;
293 return true;
294 }
295
296 if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
297 d->overrodeCallee = true;
298 return true;
299 }
300
301 return JSObject::deleteProperty(exec, propertyName);
302}
303
304} // namespace JSC