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 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::mark()
50 if (d
->registerArray
) {
51 for (unsigned i
= 0; i
< d
->numParameters
; ++i
) {
52 if (!d
->registerArray
[i
].marked())
53 d
->registerArray
[i
].mark();
57 if (d
->extraArguments
) {
58 unsigned numExtraArguments
= d
->numArguments
- d
->numParameters
;
59 for (unsigned i
= 0; i
< numExtraArguments
; ++i
) {
60 if (!d
->extraArguments
[i
].marked())
61 d
->extraArguments
[i
].mark();
65 if (!d
->callee
->marked())
68 if (d
->activation
&& !d
->activation
->marked())
69 d
->activation
->mark();
72 void Arguments::copyToRegisters(ExecState
* exec
, Register
* buffer
, uint32_t maxSize
)
74 if (UNLIKELY(d
->overrodeLength
)) {
75 unsigned length
= min(get(exec
, exec
->propertyNames().length
).toUInt32(exec
), maxSize
);
76 for (unsigned i
= 0; i
< length
; i
++)
77 buffer
[i
] = get(exec
, i
);
81 if (LIKELY(!d
->deletedArguments
)) {
82 unsigned parametersLength
= min(min(d
->numParameters
, d
->numArguments
), maxSize
);
84 for (; i
< parametersLength
; ++i
)
85 buffer
[i
] = d
->registers
[d
->firstParameterIndex
+ i
].jsValue();
86 for (; i
< d
->numArguments
; ++i
)
87 buffer
[i
] = d
->extraArguments
[i
- d
->numParameters
].jsValue();
91 unsigned parametersLength
= min(min(d
->numParameters
, d
->numArguments
), maxSize
);
93 for (; i
< parametersLength
; ++i
) {
94 if (!d
->deletedArguments
[i
])
95 buffer
[i
] = d
->registers
[d
->firstParameterIndex
+ i
].jsValue();
97 buffer
[i
] = get(exec
, i
);
99 for (; i
< d
->numArguments
; ++i
) {
100 if (!d
->deletedArguments
[i
])
101 buffer
[i
] = d
->extraArguments
[i
- d
->numParameters
].jsValue();
103 buffer
[i
] = get(exec
, i
);
107 void Arguments::fillArgList(ExecState
* exec
, MarkedArgumentBuffer
& args
)
109 if (UNLIKELY(d
->overrodeLength
)) {
110 unsigned length
= get(exec
, exec
->propertyNames().length
).toUInt32(exec
);
111 for (unsigned i
= 0; i
< length
; i
++)
112 args
.append(get(exec
, i
));
116 if (LIKELY(!d
->deletedArguments
)) {
117 if (LIKELY(!d
->numParameters
)) {
118 args
.initialize(d
->extraArguments
, d
->numArguments
);
122 if (d
->numParameters
== d
->numArguments
) {
123 args
.initialize(&d
->registers
[d
->firstParameterIndex
], d
->numArguments
);
127 unsigned parametersLength
= min(d
->numParameters
, d
->numArguments
);
129 for (; i
< parametersLength
; ++i
)
130 args
.append(d
->registers
[d
->firstParameterIndex
+ i
].jsValue());
131 for (; i
< d
->numArguments
; ++i
)
132 args
.append(d
->extraArguments
[i
- d
->numParameters
].jsValue());
136 unsigned parametersLength
= min(d
->numParameters
, d
->numArguments
);
138 for (; i
< parametersLength
; ++i
) {
139 if (!d
->deletedArguments
[i
])
140 args
.append(d
->registers
[d
->firstParameterIndex
+ i
].jsValue());
142 args
.append(get(exec
, i
));
144 for (; i
< d
->numArguments
; ++i
) {
145 if (!d
->deletedArguments
[i
])
146 args
.append(d
->extraArguments
[i
- d
->numParameters
].jsValue());
148 args
.append(get(exec
, i
));
152 bool Arguments::getOwnPropertySlot(ExecState
* exec
, unsigned i
, PropertySlot
& slot
)
154 if (i
< d
->numArguments
&& (!d
->deletedArguments
|| !d
->deletedArguments
[i
])) {
155 if (i
< d
->numParameters
) {
156 slot
.setRegisterSlot(&d
->registers
[d
->firstParameterIndex
+ i
]);
158 slot
.setValue(d
->extraArguments
[i
- d
->numParameters
].jsValue());
162 return JSObject::getOwnPropertySlot(exec
, Identifier(exec
, UString::from(i
)), slot
);
165 bool Arguments::getOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
168 unsigned i
= propertyName
.toArrayIndex(&isArrayIndex
);
169 if (isArrayIndex
&& i
< d
->numArguments
&& (!d
->deletedArguments
|| !d
->deletedArguments
[i
])) {
170 if (i
< d
->numParameters
) {
171 slot
.setRegisterSlot(&d
->registers
[d
->firstParameterIndex
+ i
]);
173 slot
.setValue(d
->extraArguments
[i
- d
->numParameters
].jsValue());
177 if (propertyName
== exec
->propertyNames().length
&& LIKELY(!d
->overrodeLength
)) {
178 slot
.setValue(jsNumber(exec
, d
->numArguments
));
182 if (propertyName
== exec
->propertyNames().callee
&& LIKELY(!d
->overrodeCallee
)) {
183 slot
.setValue(d
->callee
);
187 return JSObject::getOwnPropertySlot(exec
, propertyName
, slot
);
190 void Arguments::put(ExecState
* exec
, unsigned i
, JSValue value
, PutPropertySlot
& slot
)
192 if (i
< d
->numArguments
&& (!d
->deletedArguments
|| !d
->deletedArguments
[i
])) {
193 if (i
< d
->numParameters
)
194 d
->registers
[d
->firstParameterIndex
+ i
] = JSValue(value
);
196 d
->extraArguments
[i
- d
->numParameters
] = JSValue(value
);
200 JSObject::put(exec
, Identifier(exec
, UString::from(i
)), value
, slot
);
203 void Arguments::put(ExecState
* exec
, const Identifier
& propertyName
, JSValue value
, PutPropertySlot
& slot
)
206 unsigned i
= propertyName
.toArrayIndex(&isArrayIndex
);
207 if (isArrayIndex
&& i
< d
->numArguments
&& (!d
->deletedArguments
|| !d
->deletedArguments
[i
])) {
208 if (i
< d
->numParameters
)
209 d
->registers
[d
->firstParameterIndex
+ i
] = JSValue(value
);
211 d
->extraArguments
[i
- d
->numParameters
] = JSValue(value
);
215 if (propertyName
== exec
->propertyNames().length
&& !d
->overrodeLength
) {
216 d
->overrodeLength
= true;
217 putDirect(propertyName
, value
, DontEnum
);
221 if (propertyName
== exec
->propertyNames().callee
&& !d
->overrodeCallee
) {
222 d
->overrodeCallee
= true;
223 putDirect(propertyName
, value
, DontEnum
);
227 JSObject::put(exec
, propertyName
, value
, slot
);
230 bool Arguments::deleteProperty(ExecState
* exec
, unsigned i
)
232 if (i
< d
->numArguments
) {
233 if (!d
->deletedArguments
) {
234 d
->deletedArguments
.set(new bool[d
->numArguments
]);
235 memset(d
->deletedArguments
.get(), 0, sizeof(bool) * d
->numArguments
);
237 if (!d
->deletedArguments
[i
]) {
238 d
->deletedArguments
[i
] = true;
243 return JSObject::deleteProperty(exec
, Identifier(exec
, UString::from(i
)));
246 bool Arguments::deleteProperty(ExecState
* exec
, const Identifier
& propertyName
)
249 unsigned i
= propertyName
.toArrayIndex(&isArrayIndex
);
250 if (isArrayIndex
&& i
< d
->numArguments
) {
251 if (!d
->deletedArguments
) {
252 d
->deletedArguments
.set(new bool[d
->numArguments
]);
253 memset(d
->deletedArguments
.get(), 0, sizeof(bool) * d
->numArguments
);
255 if (!d
->deletedArguments
[i
]) {
256 d
->deletedArguments
[i
] = true;
261 if (propertyName
== exec
->propertyNames().length
&& !d
->overrodeLength
) {
262 d
->overrodeLength
= true;
266 if (propertyName
== exec
->propertyNames().callee
&& !d
->overrodeCallee
) {
267 d
->overrodeCallee
= true;
271 return JSObject::deleteProperty(exec
, propertyName
);