]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/Arguments.cpp
JavaScriptCore-903.5.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
14957cd0 38const ClassInfo Arguments::s_info = { "Arguments", &JSNonFinalObject::s_info, 0, 0 };
9dae56ea
A
39
40Arguments::~Arguments()
41{
42 if (d->extraArguments != d->extraArgumentsFixedBuffer)
43 delete [] d->extraArguments;
44}
45
14957cd0 46void Arguments::visitChildren(SlotVisitor& visitor)
9dae56ea 47{
14957cd0
A
48 ASSERT_GC_OBJECT_INHERITS(this, &s_info);
49 COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
50 ASSERT(structure()->typeInfo().overridesVisitChildren());
51 JSObject::visitChildren(visitor);
9dae56ea 52
f9bf01c6 53 if (d->registerArray)
14957cd0 54 visitor.appendValues(d->registerArray.get(), d->numParameters);
9dae56ea
A
55
56 if (d->extraArguments) {
57 unsigned numExtraArguments = d->numArguments - d->numParameters;
14957cd0 58 visitor.appendValues(d->extraArguments, numExtraArguments);
9dae56ea
A
59 }
60
14957cd0 61 visitor.append(&d->callee);
9dae56ea 62
f9bf01c6 63 if (d->activation)
14957cd0 64 visitor.append(&d->activation);
9dae56ea
A
65}
66
ba379fdc 67void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
9dae56ea 68{
ba379fdc
A
69 if (UNLIKELY(d->overrodeLength)) {
70 unsigned length = min(get(exec, exec->propertyNames().length).toUInt32(exec), maxSize);
71 for (unsigned i = 0; i < length; i++)
72 buffer[i] = get(exec, i);
73 return;
74 }
75
76 if (LIKELY(!d->deletedArguments)) {
77 unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
78 unsigned i = 0;
79 for (; i < parametersLength; ++i)
14957cd0 80 buffer[i] = d->registers[d->firstParameterIndex + i].get();
ba379fdc 81 for (; i < d->numArguments; ++i)
14957cd0 82 buffer[i] = d->extraArguments[i - d->numParameters].get();
ba379fdc
A
83 return;
84 }
85
86 unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
87 unsigned i = 0;
88 for (; i < parametersLength; ++i) {
89 if (!d->deletedArguments[i])
14957cd0 90 buffer[i] = d->registers[d->firstParameterIndex + i].get();
ba379fdc
A
91 else
92 buffer[i] = get(exec, i);
93 }
94 for (; i < d->numArguments; ++i) {
95 if (!d->deletedArguments[i])
14957cd0 96 buffer[i] = d->extraArguments[i - d->numParameters].get();
ba379fdc
A
97 else
98 buffer[i] = get(exec, i);
99 }
100}
101
102void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
103{
104 if (UNLIKELY(d->overrodeLength)) {
105 unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec);
106 for (unsigned i = 0; i < length; i++)
107 args.append(get(exec, i));
108 return;
109 }
110
9dae56ea
A
111 if (LIKELY(!d->deletedArguments)) {
112 if (LIKELY(!d->numParameters)) {
113 args.initialize(d->extraArguments, d->numArguments);
114 return;
115 }
116
117 if (d->numParameters == d->numArguments) {
118 args.initialize(&d->registers[d->firstParameterIndex], d->numArguments);
119 return;
120 }
121
122 unsigned parametersLength = min(d->numParameters, d->numArguments);
123 unsigned i = 0;
124 for (; i < parametersLength; ++i)
14957cd0 125 args.append(d->registers[d->firstParameterIndex + i].get());
9dae56ea 126 for (; i < d->numArguments; ++i)
14957cd0 127 args.append(d->extraArguments[i - d->numParameters].get());
9dae56ea
A
128 return;
129 }
130
131 unsigned parametersLength = min(d->numParameters, d->numArguments);
132 unsigned i = 0;
133 for (; i < parametersLength; ++i) {
134 if (!d->deletedArguments[i])
14957cd0 135 args.append(d->registers[d->firstParameterIndex + i].get());
9dae56ea
A
136 else
137 args.append(get(exec, i));
138 }
139 for (; i < d->numArguments; ++i) {
140 if (!d->deletedArguments[i])
14957cd0 141 args.append(d->extraArguments[i - d->numParameters].get());
9dae56ea
A
142 else
143 args.append(get(exec, i));
144 }
145}
146
147bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
148{
149 if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
150 if (i < d->numParameters) {
14957cd0 151 slot.setValue(d->registers[d->firstParameterIndex + i].get());
9dae56ea 152 } else
14957cd0 153 slot.setValue(d->extraArguments[i - d->numParameters].get());
9dae56ea
A
154 return true;
155 }
156
14957cd0
A
157 return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::number(i)), slot);
158}
159
160void Arguments::createStrictModeCallerIfNecessary(ExecState* exec)
161{
162 if (d->overrodeCaller)
163 return;
164
165 d->overrodeCaller = true;
166 PropertyDescriptor descriptor;
167 JSValue thrower = createTypeErrorFunction(exec, "Unable to access caller of strict mode function");
168 descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter);
169 defineOwnProperty(exec, exec->propertyNames().caller, descriptor, false);
170}
171
172void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec)
173{
174 if (d->overrodeCallee)
175 return;
176
177 d->overrodeCallee = true;
178 PropertyDescriptor descriptor;
179 JSValue thrower = createTypeErrorFunction(exec, "Unable to access callee of strict mode function");
180 descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter);
181 defineOwnProperty(exec, exec->propertyNames().callee, descriptor, false);
9dae56ea
A
182}
183
184bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
185{
186 bool isArrayIndex;
14957cd0 187 unsigned i = propertyName.toArrayIndex(isArrayIndex);
9dae56ea
A
188 if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
189 if (i < d->numParameters) {
14957cd0 190 slot.setValue(d->registers[d->firstParameterIndex + i].get());
9dae56ea 191 } else
14957cd0 192 slot.setValue(d->extraArguments[i - d->numParameters].get());
9dae56ea
A
193 return true;
194 }
195
196 if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
14957cd0 197 slot.setValue(jsNumber(d->numArguments));
9dae56ea
A
198 return true;
199 }
200
201 if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
14957cd0
A
202 if (!d->isStrictMode) {
203 slot.setValue(d->callee.get());
204 return true;
205 }
206 createStrictModeCalleeIfNecessary(exec);
9dae56ea
A
207 }
208
14957cd0
A
209 if (propertyName == exec->propertyNames().caller && d->isStrictMode)
210 createStrictModeCallerIfNecessary(exec);
211
9dae56ea
A
212 return JSObject::getOwnPropertySlot(exec, propertyName, slot);
213}
214
f9bf01c6
A
215bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
216{
217 bool isArrayIndex;
14957cd0 218 unsigned i = propertyName.toArrayIndex(isArrayIndex);
f9bf01c6
A
219 if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
220 if (i < d->numParameters) {
14957cd0 221 descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].get(), DontEnum);
f9bf01c6 222 } else
14957cd0 223 descriptor.setDescriptor(d->extraArguments[i - d->numParameters].get(), DontEnum);
f9bf01c6
A
224 return true;
225 }
226
227 if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
14957cd0 228 descriptor.setDescriptor(jsNumber(d->numArguments), DontEnum);
f9bf01c6
A
229 return true;
230 }
231
232 if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
14957cd0
A
233 if (!d->isStrictMode) {
234 descriptor.setDescriptor(d->callee.get(), DontEnum);
235 return true;
236 }
237 createStrictModeCalleeIfNecessary(exec);
f9bf01c6 238 }
14957cd0
A
239
240 if (propertyName == exec->propertyNames().caller && d->isStrictMode)
241 createStrictModeCallerIfNecessary(exec);
f9bf01c6
A
242
243 return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
244}
245
246void Arguments::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
247{
248 if (mode == IncludeDontEnumProperties) {
249 for (unsigned i = 0; i < d->numArguments; ++i) {
250 if (!d->deletedArguments || !d->deletedArguments[i])
14957cd0 251 propertyNames.add(Identifier(exec, UString::number(i)));
f9bf01c6
A
252 }
253 propertyNames.add(exec->propertyNames().callee);
254 propertyNames.add(exec->propertyNames().length);
255 }
256 JSObject::getOwnPropertyNames(exec, propertyNames, mode);
257}
258
14957cd0 259void Arguments::put(ExecState* exec, unsigned i, JSValue value)
9dae56ea
A
260{
261 if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
262 if (i < d->numParameters)
14957cd0 263 d->registers[d->firstParameterIndex + i].set(exec->globalData(), d->activation ? static_cast<JSCell*>(d->activation.get()) : static_cast<JSCell*>(this), value);
9dae56ea 264 else
14957cd0 265 d->extraArguments[i - d->numParameters].set(exec->globalData(), this, value);
9dae56ea
A
266 return;
267 }
268
14957cd0
A
269 PutPropertySlot slot;
270 JSObject::put(exec, Identifier(exec, UString::number(i)), value, slot);
9dae56ea
A
271}
272
ba379fdc 273void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
9dae56ea
A
274{
275 bool isArrayIndex;
14957cd0 276 unsigned i = propertyName.toArrayIndex(isArrayIndex);
9dae56ea
A
277 if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
278 if (i < d->numParameters)
14957cd0 279 d->registers[d->firstParameterIndex + i].set(exec->globalData(), d->activation ? static_cast<JSCell*>(d->activation.get()) : static_cast<JSCell*>(this), value);
9dae56ea 280 else
14957cd0 281 d->extraArguments[i - d->numParameters].set(exec->globalData(), this, value);
9dae56ea
A
282 return;
283 }
284
285 if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
286 d->overrodeLength = true;
14957cd0 287 putDirect(exec->globalData(), propertyName, value, DontEnum);
9dae56ea
A
288 return;
289 }
290
291 if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
14957cd0
A
292 if (!d->isStrictMode) {
293 d->overrodeCallee = true;
294 putDirect(exec->globalData(), propertyName, value, DontEnum);
295 return;
296 }
297 createStrictModeCalleeIfNecessary(exec);
9dae56ea
A
298 }
299
14957cd0
A
300 if (propertyName == exec->propertyNames().caller && d->isStrictMode)
301 createStrictModeCallerIfNecessary(exec);
302
9dae56ea
A
303 JSObject::put(exec, propertyName, value, slot);
304}
305
306bool Arguments::deleteProperty(ExecState* exec, unsigned i)
307{
308 if (i < d->numArguments) {
309 if (!d->deletedArguments) {
14957cd0 310 d->deletedArguments = adoptArrayPtr(new bool[d->numArguments]);
9dae56ea
A
311 memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
312 }
313 if (!d->deletedArguments[i]) {
314 d->deletedArguments[i] = true;
315 return true;
316 }
317 }
318
14957cd0 319 return JSObject::deleteProperty(exec, Identifier(exec, UString::number(i)));
9dae56ea
A
320}
321
322bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)
323{
324 bool isArrayIndex;
14957cd0 325 unsigned i = propertyName.toArrayIndex(isArrayIndex);
9dae56ea
A
326 if (isArrayIndex && i < d->numArguments) {
327 if (!d->deletedArguments) {
14957cd0 328 d->deletedArguments = adoptArrayPtr(new bool[d->numArguments]);
9dae56ea
A
329 memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
330 }
331 if (!d->deletedArguments[i]) {
332 d->deletedArguments[i] = true;
333 return true;
334 }
335 }
336
337 if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
338 d->overrodeLength = true;
339 return true;
340 }
341
342 if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
14957cd0
A
343 if (!d->isStrictMode) {
344 d->overrodeCallee = true;
345 return true;
346 }
347 createStrictModeCalleeIfNecessary(exec);
9dae56ea 348 }
14957cd0
A
349
350 if (propertyName == exec->propertyNames().caller && !d->isStrictMode)
351 createStrictModeCallerIfNecessary(exec);
9dae56ea
A
352
353 return JSObject::deleteProperty(exec, propertyName);
354}
355
356} // namespace JSC