1/*
2 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
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 = { .className: "Arguments", .parentClass: 0, .staticPropHashTable: 0, .classPropHashTableGetterFunction: 0 };
39
40Arguments::~Arguments()
41{
42 if (d->extraArguments != d->extraArgumentsFixedBuffer)
43 delete [] d->extraArguments;
44}
45
46void Arguments::markChildren(MarkStack& markStack)
47{
48 JSObject::markChildren(markStack);
49
50 if (d->registerArray)
51 markStack.appendValues(values: reinterpret_cast<JSValue*>(d->registerArray.get()), count: d->numParameters);
52
53 if (d->extraArguments) {
54 unsigned numExtraArguments = d->numArguments - d->numParameters;
55 markStack.appendValues(values: reinterpret_cast<JSValue*>(d->extraArguments), count: numExtraArguments);
56 }
57
58 markStack.append(cell: d->callee);
59
60 if (d->activation)
61 markStack.append(cell: d->activation);
62}
63
64void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
65{
66 if (UNLIKELY(d->overrodeLength)) {
67 unsigned length = min(a: get(exec, propertyName: exec->propertyNames().length).toUInt32(exec), b: maxSize);
68 for (unsigned i = 0; i < length; i++)
69 buffer[i] = get(exec, propertyName: i);
70 return;
71 }
72
73 if (LIKELY(!d->deletedArguments)) {
74 unsigned parametersLength = min(a: min(a: d->numParameters, b: d->numArguments), b: 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(a: min(a: d->numParameters, b: d->numArguments), b: 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, propertyName: 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, propertyName: i);
96 }
97}
98
99void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
100{
101 if (UNLIKELY(d->overrodeLength)) {
102 unsigned length = get(exec, propertyName: exec->propertyNames().length).toUInt32(exec);
103 for (unsigned i = 0; i < length; i++)
104 args.append(v: get(exec, propertyName: i));
105 return;
106 }
107
108 if (LIKELY(!d->deletedArguments)) {
109 if (LIKELY(!d->numParameters)) {
110 args.initialize(buffer: d->extraArguments, size: d->numArguments);
111 return;
112 }
113
114 if (d->numParameters == d->numArguments) {
115 args.initialize(buffer: &d->registers[d->firstParameterIndex], size: d->numArguments);
116 return;
117 }
118
119 unsigned parametersLength = min(a: d->numParameters, b: d->numArguments);
120 unsigned i = 0;
121 for (; i < parametersLength; ++i)
122 args.append(v: d->registers[d->firstParameterIndex + i].jsValue());
123 for (; i < d->numArguments; ++i)
124 args.append(v: d->extraArguments[i - d->numParameters].jsValue());
125 return;
126 }
127
128 unsigned parametersLength = min(a: d->numParameters, b: d->numArguments);
129 unsigned i = 0;
130 for (; i < parametersLength; ++i) {
131 if (!d->deletedArguments[i])
132 args.append(v: d->registers[d->firstParameterIndex + i].jsValue());
133 else
134 args.append(v: get(exec, propertyName: i));
135 }
136 for (; i < d->numArguments; ++i) {
137 if (!d->deletedArguments[i])
138 args.append(v: d->extraArguments[i - d->numParameters].jsValue());
139 else
140 args.append(v: get(exec, propertyName: 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
150 slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
151 return true;
152 }
153
154 return JSObject::getOwnPropertySlot(exec, propertyName: 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(ok: &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
165 slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
166 return true;
167 }
168
169 if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
170 slot.setValue(jsNumber(exec, i: 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
182bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
183{
184 bool isArrayIndex;
185 unsigned i = propertyName.toArrayIndex(ok: &isArrayIndex);
186 if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
187 if (i < d->numParameters) {
188 descriptor.setDescriptor(value: d->registers[d->firstParameterIndex + i].jsValue(), attributes: DontEnum);
189 } else
190 descriptor.setDescriptor(value: d->extraArguments[i - d->numParameters].jsValue(), attributes: DontEnum);
191 return true;
192 }
193
194 if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
195 descriptor.setDescriptor(value: jsNumber(exec, i: d->numArguments), attributes: DontEnum);
196 return true;
197 }
198
199 if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
200 descriptor.setDescriptor(value: d->callee, attributes: 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: Identifier(exec, UString::from(i)));
213 }
214 propertyNames.add(identifier: exec->propertyNames().callee);
215 propertyNames.add(identifier: exec->propertyNames().length);
216 }
217 JSObject::getOwnPropertyNames(exec, propertyNames, mode);
218}
219
220void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot)
221{
222 if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
223 if (i < d->numParameters)
224 d->registers[d->firstParameterIndex + i] = JSValue(value);
225 else
226 d->extraArguments[i - d->numParameters] = JSValue(value);
227 return;
228 }
229
230 JSObject::put(exec, propertyName: Identifier(exec, UString::from(i)), value, slot);
231}
232
233void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
234{
235 bool isArrayIndex;
236 unsigned i = propertyName.toArrayIndex(ok: &isArrayIndex);
237 if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
238 if (i < d->numParameters)
239 d->registers[d->firstParameterIndex + i] = JSValue(value);
240 else
241 d->extraArguments[i - d->numParameters] = JSValue(value);
242 return;
243 }
244
245 if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
246 d->overrodeLength = true;
247 putDirect(propertyName, value, attributes: DontEnum);
248 return;
249 }
250
251 if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
252 d->overrodeCallee = true;
253 putDirect(propertyName, value, attributes: 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(s: d->deletedArguments.get(), c: 0, n: 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, propertyName: Identifier(exec, UString::from(i)));
274}
275
276bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)
277{
278 bool isArrayIndex;
279 unsigned i = propertyName.toArrayIndex(ok: &isArrayIndex);
280 if (isArrayIndex && i < d->numArguments) {
281 if (!d->deletedArguments) {
282 d->deletedArguments.set(new bool[d->numArguments]);
283 memset(s: d->deletedArguments.get(), c: 0, n: 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
305

source code of qtscript/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.cpp