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
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.
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.
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.
26 #include "Arguments.h"
28 #include "JSActivation.h"
29 #include "JSFunction.h"
30 #include "JSGlobalObject.h"
36 ASSERT_CLASS_FITS_IN_CELL(Arguments
);
38 const ClassInfo
Arguments::info
= { "Arguments", 0, 0, 0 };
40 Arguments::~Arguments()
42 if (d
->extraArguments
!= d
->extraArgumentsFixedBuffer
)
43 delete [] d
->extraArguments
;
46 void Arguments::markChildren(MarkStack
& markStack
)
48 JSObject::markChildren(markStack
);
51 markStack
.appendValues(reinterpret_cast<JSValue
*>(d
->registerArray
.get()), d
->numParameters
);
53 if (d
->extraArguments
) {
54 unsigned numExtraArguments
= d
->numArguments
- d
->numParameters
;
55 markStack
.appendValues(reinterpret_cast<JSValue
*>(d
->extraArguments
), numExtraArguments
);
58 markStack
.append(d
->callee
);
61 markStack
.append(d
->activation
);
64 void Arguments::copyToRegisters(ExecState
* exec
, Register
* buffer
, uint32_t maxSize
)
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
);
73 if (LIKELY(!d
->deletedArguments
)) {
74 unsigned parametersLength
= min(min(d
->numParameters
, d
->numArguments
), maxSize
);
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();
83 unsigned parametersLength
= min(min(d
->numParameters
, d
->numArguments
), maxSize
);
85 for (; i
< parametersLength
; ++i
) {
86 if (!d
->deletedArguments
[i
])
87 buffer
[i
] = d
->registers
[d
->firstParameterIndex
+ i
].jsValue();
89 buffer
[i
] = get(exec
, i
);
91 for (; i
< d
->numArguments
; ++i
) {
92 if (!d
->deletedArguments
[i
])
93 buffer
[i
] = d
->extraArguments
[i
- d
->numParameters
].jsValue();
95 buffer
[i
] = get(exec
, i
);
99 void Arguments::fillArgList(ExecState
* exec
, MarkedArgumentBuffer
& args
)
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
));
108 if (LIKELY(!d
->deletedArguments
)) {
109 if (LIKELY(!d
->numParameters
)) {
110 args
.initialize(d
->extraArguments
, d
->numArguments
);
114 if (d
->numParameters
== d
->numArguments
) {
115 args
.initialize(&d
->registers
[d
->firstParameterIndex
], d
->numArguments
);
119 unsigned parametersLength
= min(d
->numParameters
, d
->numArguments
);
121 for (; i
< parametersLength
; ++i
)
122 args
.append(d
->registers
[d
->firstParameterIndex
+ i
].jsValue());
123 for (; i
< d
->numArguments
; ++i
)
124 args
.append(d
->extraArguments
[i
- d
->numParameters
].jsValue());
128 unsigned parametersLength
= min(d
->numParameters
, d
->numArguments
);
130 for (; i
< parametersLength
; ++i
) {
131 if (!d
->deletedArguments
[i
])
132 args
.append(d
->registers
[d
->firstParameterIndex
+ i
].jsValue());
134 args
.append(get(exec
, i
));
136 for (; i
< d
->numArguments
; ++i
) {
137 if (!d
->deletedArguments
[i
])
138 args
.append(d
->extraArguments
[i
- d
->numParameters
].jsValue());
140 args
.append(get(exec
, i
));
144 bool Arguments::getOwnPropertySlot(ExecState
* exec
, unsigned i
, PropertySlot
& slot
)
146 if (i
< d
->numArguments
&& (!d
->deletedArguments
|| !d
->deletedArguments
[i
])) {
147 if (i
< d
->numParameters
) {
148 slot
.setRegisterSlot(&d
->registers
[d
->firstParameterIndex
+ i
]);
150 slot
.setValue(d
->extraArguments
[i
- d
->numParameters
].jsValue());
154 return JSObject::getOwnPropertySlot(exec
, Identifier(exec
, UString::from(i
)), slot
);
157 bool Arguments::getOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
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
]);
165 slot
.setValue(d
->extraArguments
[i
- d
->numParameters
].jsValue());
169 if (propertyName
== exec
->propertyNames().length
&& LIKELY(!d
->overrodeLength
)) {
170 slot
.setValue(jsNumber(exec
, d
->numArguments
));
174 if (propertyName
== exec
->propertyNames().callee
&& LIKELY(!d
->overrodeCallee
)) {
175 slot
.setValue(d
->callee
);
179 return JSObject::getOwnPropertySlot(exec
, propertyName
, slot
);
182 bool Arguments::getOwnPropertyDescriptor(ExecState
* exec
, const Identifier
& propertyName
, PropertyDescriptor
& descriptor
)
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
);
190 descriptor
.setDescriptor(d
->extraArguments
[i
- d
->numParameters
].jsValue(), DontEnum
);
194 if (propertyName
== exec
->propertyNames().length
&& LIKELY(!d
->overrodeLength
)) {
195 descriptor
.setDescriptor(jsNumber(exec
, d
->numArguments
), DontEnum
);
199 if (propertyName
== exec
->propertyNames().callee
&& LIKELY(!d
->overrodeCallee
)) {
200 descriptor
.setDescriptor(d
->callee
, DontEnum
);
204 return JSObject::getOwnPropertyDescriptor(exec
, propertyName
, descriptor
);
207 void Arguments::getOwnPropertyNames(ExecState
* exec
, PropertyNameArray
& propertyNames
, EnumerationMode mode
)
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
)));
214 propertyNames
.add(exec
->propertyNames().callee
);
215 propertyNames
.add(exec
->propertyNames().length
);
217 JSObject::getOwnPropertyNames(exec
, propertyNames
, mode
);
220 void Arguments::put(ExecState
* exec
, unsigned i
, JSValue value
, PutPropertySlot
& slot
)
222 if (i
< d
->numArguments
&& (!d
->deletedArguments
|| !d
->deletedArguments
[i
])) {
223 if (i
< d
->numParameters
)
224 d
->registers
[d
->firstParameterIndex
+ i
] = JSValue(value
);
226 d
->extraArguments
[i
- d
->numParameters
] = JSValue(value
);
230 JSObject::put(exec
, Identifier(exec
, UString::from(i
)), value
, slot
);
233 void Arguments::put(ExecState
* exec
, const Identifier
& propertyName
, JSValue value
, PutPropertySlot
& slot
)
236 unsigned i
= propertyName
.toArrayIndex(&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
);
241 d
->extraArguments
[i
- d
->numParameters
] = JSValue(value
);
245 if (propertyName
== exec
->propertyNames().length
&& !d
->overrodeLength
) {
246 d
->overrodeLength
= true;
247 putDirect(propertyName
, value
, DontEnum
);
251 if (propertyName
== exec
->propertyNames().callee
&& !d
->overrodeCallee
) {
252 d
->overrodeCallee
= true;
253 putDirect(propertyName
, value
, DontEnum
);
257 JSObject::put(exec
, propertyName
, value
, slot
);
260 bool Arguments::deleteProperty(ExecState
* exec
, unsigned i
)
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
);
267 if (!d
->deletedArguments
[i
]) {
268 d
->deletedArguments
[i
] = true;
273 return JSObject::deleteProperty(exec
, Identifier(exec
, UString::from(i
)));
276 bool Arguments::deleteProperty(ExecState
* exec
, const Identifier
& propertyName
)
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
);
285 if (!d
->deletedArguments
[i
]) {
286 d
->deletedArguments
[i
] = true;
291 if (propertyName
== exec
->propertyNames().length
&& !d
->overrodeLength
) {
292 d
->overrodeLength
= true;
296 if (propertyName
== exec
->propertyNames().callee
&& !d
->overrodeCallee
) {
297 d
->overrodeCallee
= true;
301 return JSObject::deleteProperty(exec
, propertyName
);