]>
Commit | Line | Data |
---|---|---|
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 | ||
81345200 | 28 | #include "CopyVisitorInlines.h" |
9dae56ea | 29 | #include "JSActivation.h" |
81345200 | 30 | #include "JSArgumentsIterator.h" |
9dae56ea A |
31 | #include "JSFunction.h" |
32 | #include "JSGlobalObject.h" | |
81345200 | 33 | #include "JSCInlines.h" |
9dae56ea A |
34 | |
35 | using namespace std; | |
36 | ||
37 | namespace JSC { | |
38 | ||
81345200 A |
39 | STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(Arguments); |
40 | ||
93a37866 | 41 | const ClassInfo Arguments::s_info = { "Arguments", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Arguments) }; |
9dae56ea | 42 | |
6fe7ccc8 | 43 | void Arguments::visitChildren(JSCell* cell, SlotVisitor& visitor) |
9dae56ea | 44 | { |
6fe7ccc8 | 45 | Arguments* thisObject = jsCast<Arguments*>(cell); |
81345200 | 46 | ASSERT_GC_OBJECT_INHERITS(thisObject, info()); |
6fe7ccc8 A |
47 | COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); |
48 | ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); | |
49 | JSObject::visitChildren(thisObject, visitor); | |
50 | ||
81345200 A |
51 | if (thisObject->m_registerArray) { |
52 | visitor.copyLater(thisObject, ArgumentsRegisterArrayCopyToken, | |
53 | thisObject->m_registerArray.get(), thisObject->registerArraySizeInBytes()); | |
93a37866 | 54 | visitor.appendValues(thisObject->m_registerArray.get(), thisObject->m_numArguments); |
81345200 A |
55 | } |
56 | if (thisObject->m_slowArgumentData) { | |
57 | visitor.copyLater(thisObject, ArgumentsSlowArgumentDataCopyToken, | |
58 | thisObject->m_slowArgumentData.get(), SlowArgumentData::sizeForNumArguments(thisObject->m_numArguments)); | |
59 | } | |
93a37866 A |
60 | visitor.append(&thisObject->m_callee); |
61 | visitor.append(&thisObject->m_activation); | |
9dae56ea A |
62 | } |
63 | ||
81345200 | 64 | void Arguments::copyBackingStore(JSCell* cell, CopyVisitor& visitor, CopyToken token) |
9dae56ea | 65 | { |
81345200 A |
66 | Arguments* thisObject = jsCast<Arguments*>(cell); |
67 | ASSERT_GC_OBJECT_INHERITS(thisObject, info()); | |
68 | ||
69 | ||
70 | switch (token) { | |
71 | case ArgumentsRegisterArrayCopyToken: { | |
72 | WriteBarrier<Unknown>* registerArray = thisObject->m_registerArray.get(); | |
73 | if (!registerArray) | |
74 | return; | |
75 | ||
76 | if (visitor.checkIfShouldCopy(registerArray)) { | |
77 | size_t bytes = thisObject->registerArraySizeInBytes(); | |
78 | WriteBarrier<Unknown>* newRegisterArray = static_cast<WriteBarrier<Unknown>*>(visitor.allocateNewSpace(bytes)); | |
79 | memcpy(newRegisterArray, registerArray, bytes); | |
80 | thisObject->m_registerArray.setWithoutWriteBarrier(newRegisterArray); | |
81 | thisObject->m_registers = newRegisterArray - CallFrame::offsetFor(1) - 1; | |
82 | visitor.didCopy(registerArray, bytes); | |
83 | } | |
84 | return; | |
85 | } | |
86 | ||
87 | case ArgumentsSlowArgumentDataCopyToken: { | |
88 | SlowArgumentData* slowArgumentData = thisObject->m_slowArgumentData.get(); | |
89 | if (!slowArgumentData) | |
90 | return; | |
91 | ||
92 | if (visitor.checkIfShouldCopy(slowArgumentData)) { | |
93 | size_t bytes = SlowArgumentData::sizeForNumArguments(thisObject->m_numArguments); | |
94 | SlowArgumentData* newSlowArgumentData = static_cast<SlowArgumentData*>(visitor.allocateNewSpace(bytes)); | |
95 | memcpy(newSlowArgumentData, slowArgumentData, bytes); | |
96 | thisObject->m_slowArgumentData.setWithoutWriteBarrier(newSlowArgumentData); | |
97 | visitor.didCopy(slowArgumentData, bytes); | |
98 | } | |
99 | return; | |
100 | } | |
101 | ||
102 | default: | |
103 | return; | |
104 | } | |
9dae56ea | 105 | } |
81345200 A |
106 | |
107 | static EncodedJSValue JSC_HOST_CALL argumentsFuncIterator(ExecState*); | |
9dae56ea | 108 | |
81345200 | 109 | void Arguments::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t copyLength, int32_t firstVarArgOffset) |
9dae56ea | 110 | { |
81345200 A |
111 | uint32_t length = copyLength + firstVarArgOffset; |
112 | ||
93a37866 | 113 | if (UNLIKELY(m_overrodeLength)) { |
6fe7ccc8 | 114 | length = min(get(exec, exec->propertyNames().length).toUInt32(exec), length); |
81345200 | 115 | for (unsigned i = firstVarArgOffset; i < length; i++) |
6fe7ccc8 | 116 | callFrame->setArgument(i, get(exec, i)); |
ba379fdc A |
117 | return; |
118 | } | |
6fe7ccc8 | 119 | ASSERT(length == this->length(exec)); |
81345200 | 120 | for (size_t i = firstVarArgOffset; i < length; ++i) { |
93a37866 | 121 | if (JSValue value = tryGetArgument(i)) |
81345200 | 122 | callFrame->setArgument(i - firstVarArgOffset, value); |
ba379fdc | 123 | else |
81345200 | 124 | callFrame->setArgument(i - firstVarArgOffset, get(exec, i)); |
ba379fdc A |
125 | } |
126 | } | |
127 | ||
128 | void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) | |
129 | { | |
93a37866 | 130 | if (UNLIKELY(m_overrodeLength)) { |
ba379fdc A |
131 | unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec); |
132 | for (unsigned i = 0; i < length; i++) | |
133 | args.append(get(exec, i)); | |
134 | return; | |
135 | } | |
6fe7ccc8 A |
136 | uint32_t length = this->length(exec); |
137 | for (size_t i = 0; i < length; ++i) { | |
93a37866 A |
138 | if (JSValue value = tryGetArgument(i)) |
139 | args.append(value); | |
9dae56ea A |
140 | else |
141 | args.append(get(exec, i)); | |
142 | } | |
143 | } | |
144 | ||
81345200 | 145 | bool Arguments::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned i, PropertySlot& slot) |
9dae56ea | 146 | { |
81345200 | 147 | Arguments* thisObject = jsCast<Arguments*>(object); |
93a37866 | 148 | if (JSValue value = thisObject->tryGetArgument(i)) { |
81345200 | 149 | slot.setValue(thisObject, None, value); |
9dae56ea A |
150 | return true; |
151 | } | |
152 | ||
81345200 | 153 | return JSObject::getOwnPropertySlot(thisObject, exec, Identifier::from(exec, i), slot); |
14957cd0 A |
154 | } |
155 | ||
156 | void Arguments::createStrictModeCallerIfNecessary(ExecState* exec) | |
157 | { | |
93a37866 | 158 | if (m_overrodeCaller) |
14957cd0 A |
159 | return; |
160 | ||
81345200 | 161 | VM& vm = exec->vm(); |
93a37866 | 162 | m_overrodeCaller = true; |
14957cd0 | 163 | PropertyDescriptor descriptor; |
81345200 A |
164 | descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(vm), DontEnum | DontDelete | Accessor); |
165 | methodTable(exec->vm())->defineOwnProperty(this, exec, vm.propertyNames->caller, descriptor, false); | |
14957cd0 A |
166 | } |
167 | ||
168 | void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec) | |
169 | { | |
93a37866 | 170 | if (m_overrodeCallee) |
14957cd0 | 171 | return; |
81345200 A |
172 | |
173 | VM& vm = exec->vm(); | |
93a37866 | 174 | m_overrodeCallee = true; |
14957cd0 | 175 | PropertyDescriptor descriptor; |
81345200 A |
176 | descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(vm), DontEnum | DontDelete | Accessor); |
177 | methodTable(exec->vm())->defineOwnProperty(this, exec, vm.propertyNames->callee, descriptor, false); | |
9dae56ea A |
178 | } |
179 | ||
81345200 | 180 | bool Arguments::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) |
9dae56ea | 181 | { |
81345200 | 182 | Arguments* thisObject = jsCast<Arguments*>(object); |
93a37866 A |
183 | unsigned i = propertyName.asIndex(); |
184 | if (JSValue value = thisObject->tryGetArgument(i)) { | |
185 | RELEASE_ASSERT(i < PropertyName::NotAnIndex); | |
81345200 | 186 | slot.setValue(thisObject, None, value); |
9dae56ea A |
187 | return true; |
188 | } | |
189 | ||
93a37866 | 190 | if (propertyName == exec->propertyNames().length && LIKELY(!thisObject->m_overrodeLength)) { |
81345200 | 191 | slot.setValue(thisObject, DontEnum, jsNumber(thisObject->m_numArguments)); |
9dae56ea A |
192 | return true; |
193 | } | |
194 | ||
93a37866 A |
195 | if (propertyName == exec->propertyNames().callee && LIKELY(!thisObject->m_overrodeCallee)) { |
196 | if (!thisObject->m_isStrictMode) { | |
81345200 | 197 | slot.setValue(thisObject, DontEnum, thisObject->m_callee.get()); |
14957cd0 A |
198 | return true; |
199 | } | |
6fe7ccc8 | 200 | thisObject->createStrictModeCalleeIfNecessary(exec); |
9dae56ea A |
201 | } |
202 | ||
93a37866 | 203 | if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) |
6fe7ccc8 | 204 | thisObject->createStrictModeCallerIfNecessary(exec); |
14957cd0 | 205 | |
81345200 | 206 | if (JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot)) |
f9bf01c6 | 207 | return true; |
81345200 A |
208 | if (propertyName == exec->propertyNames().iteratorPrivateName) { |
209 | VM& vm = exec->vm(); | |
210 | JSGlobalObject* globalObject = exec->lexicalGlobalObject(); | |
211 | thisObject->JSC_NATIVE_FUNCTION(exec->propertyNames().iteratorPrivateName, argumentsFuncIterator, DontEnum, 0); | |
212 | if (JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot)) | |
14957cd0 | 213 | return true; |
f9bf01c6 | 214 | } |
81345200 | 215 | return false; |
f9bf01c6 A |
216 | } |
217 | ||
6fe7ccc8 | 218 | void Arguments::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) |
f9bf01c6 | 219 | { |
6fe7ccc8 | 220 | Arguments* thisObject = jsCast<Arguments*>(object); |
93a37866 A |
221 | for (unsigned i = 0; i < thisObject->m_numArguments; ++i) { |
222 | if (!thisObject->isArgument(i)) | |
223 | continue; | |
81345200 | 224 | propertyNames.add(Identifier::from(exec, i)); |
6fe7ccc8 | 225 | } |
f9bf01c6 | 226 | if (mode == IncludeDontEnumProperties) { |
f9bf01c6 A |
227 | propertyNames.add(exec->propertyNames().callee); |
228 | propertyNames.add(exec->propertyNames().length); | |
229 | } | |
6fe7ccc8 | 230 | JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode); |
f9bf01c6 A |
231 | } |
232 | ||
6fe7ccc8 | 233 | void Arguments::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value, bool shouldThrow) |
9dae56ea | 234 | { |
6fe7ccc8 | 235 | Arguments* thisObject = jsCast<Arguments*>(cell); |
93a37866 | 236 | if (thisObject->trySetArgument(exec->vm(), i, value)) |
9dae56ea | 237 | return; |
9dae56ea | 238 | |
81345200 A |
239 | PutPropertySlot slot(thisObject, shouldThrow); |
240 | JSObject::put(thisObject, exec, Identifier::from(exec, i), value, slot); | |
9dae56ea A |
241 | } |
242 | ||
93a37866 | 243 | void Arguments::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) |
9dae56ea | 244 | { |
6fe7ccc8 | 245 | Arguments* thisObject = jsCast<Arguments*>(cell); |
93a37866 A |
246 | unsigned i = propertyName.asIndex(); |
247 | if (thisObject->trySetArgument(exec->vm(), i, value)) | |
9dae56ea | 248 | return; |
9dae56ea | 249 | |
93a37866 A |
250 | if (propertyName == exec->propertyNames().length && !thisObject->m_overrodeLength) { |
251 | thisObject->m_overrodeLength = true; | |
252 | thisObject->putDirect(exec->vm(), propertyName, value, DontEnum); | |
9dae56ea A |
253 | return; |
254 | } | |
255 | ||
93a37866 A |
256 | if (propertyName == exec->propertyNames().callee && !thisObject->m_overrodeCallee) { |
257 | if (!thisObject->m_isStrictMode) { | |
258 | thisObject->m_overrodeCallee = true; | |
259 | thisObject->putDirect(exec->vm(), propertyName, value, DontEnum); | |
14957cd0 A |
260 | return; |
261 | } | |
6fe7ccc8 | 262 | thisObject->createStrictModeCalleeIfNecessary(exec); |
9dae56ea A |
263 | } |
264 | ||
93a37866 | 265 | if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) |
6fe7ccc8 | 266 | thisObject->createStrictModeCallerIfNecessary(exec); |
14957cd0 | 267 | |
6fe7ccc8 | 268 | JSObject::put(thisObject, exec, propertyName, value, slot); |
9dae56ea A |
269 | } |
270 | ||
6fe7ccc8 | 271 | bool Arguments::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) |
9dae56ea | 272 | { |
6fe7ccc8 | 273 | Arguments* thisObject = jsCast<Arguments*>(cell); |
93a37866 | 274 | if (i < thisObject->m_numArguments) { |
6fe7ccc8 A |
275 | if (!Base::deletePropertyByIndex(cell, exec, i)) |
276 | return false; | |
81345200 | 277 | if (thisObject->tryDeleteArgument(exec->vm(), i)) |
9dae56ea | 278 | return true; |
9dae56ea | 279 | } |
93a37866 | 280 | return JSObject::deletePropertyByIndex(thisObject, exec, i); |
9dae56ea A |
281 | } |
282 | ||
93a37866 | 283 | bool Arguments::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) |
9dae56ea | 284 | { |
93a37866 | 285 | if (exec->vm().isInDefineOwnProperty()) |
6fe7ccc8 A |
286 | return Base::deleteProperty(cell, exec, propertyName); |
287 | ||
288 | Arguments* thisObject = jsCast<Arguments*>(cell); | |
93a37866 A |
289 | unsigned i = propertyName.asIndex(); |
290 | if (i < thisObject->m_numArguments) { | |
291 | RELEASE_ASSERT(i < PropertyName::NotAnIndex); | |
6fe7ccc8 A |
292 | if (!Base::deleteProperty(cell, exec, propertyName)) |
293 | return false; | |
81345200 | 294 | if (thisObject->tryDeleteArgument(exec->vm(), i)) |
9dae56ea | 295 | return true; |
9dae56ea A |
296 | } |
297 | ||
93a37866 A |
298 | if (propertyName == exec->propertyNames().length && !thisObject->m_overrodeLength) { |
299 | thisObject->m_overrodeLength = true; | |
9dae56ea A |
300 | return true; |
301 | } | |
302 | ||
93a37866 A |
303 | if (propertyName == exec->propertyNames().callee && !thisObject->m_overrodeCallee) { |
304 | if (!thisObject->m_isStrictMode) { | |
305 | thisObject->m_overrodeCallee = true; | |
14957cd0 A |
306 | return true; |
307 | } | |
6fe7ccc8 | 308 | thisObject->createStrictModeCalleeIfNecessary(exec); |
9dae56ea | 309 | } |
14957cd0 | 310 | |
93a37866 | 311 | if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) |
6fe7ccc8 A |
312 | thisObject->createStrictModeCallerIfNecessary(exec); |
313 | ||
314 | return JSObject::deleteProperty(thisObject, exec, propertyName); | |
315 | } | |
316 | ||
81345200 | 317 | bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) |
6fe7ccc8 A |
318 | { |
319 | Arguments* thisObject = jsCast<Arguments*>(object); | |
93a37866 A |
320 | unsigned i = propertyName.asIndex(); |
321 | if (i < thisObject->m_numArguments) { | |
322 | RELEASE_ASSERT(i < PropertyName::NotAnIndex); | |
6fe7ccc8 | 323 | // If the property is not yet present on the object, and is not yet marked as deleted, then add it now. |
81345200 | 324 | PropertySlot slot(thisObject); |
93a37866 A |
325 | if (!thisObject->isDeletedArgument(i) && !JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot)) { |
326 | JSValue value = thisObject->tryGetArgument(i); | |
327 | ASSERT(value); | |
328 | object->putDirectMayBeIndex(exec, propertyName, value); | |
329 | } | |
6fe7ccc8 A |
330 | if (!Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow)) |
331 | return false; | |
332 | ||
6fe7ccc8 A |
333 | // From ES 5.1, 10.6 Arguments Object |
334 | // 5. If the value of isMapped is not undefined, then | |
93a37866 | 335 | if (thisObject->isArgument(i)) { |
6fe7ccc8 A |
336 | // a. If IsAccessorDescriptor(Desc) is true, then |
337 | if (descriptor.isAccessorDescriptor()) { | |
338 | // i. Call the [[Delete]] internal method of map passing P, and false as the arguments. | |
81345200 | 339 | thisObject->tryDeleteArgument(exec->vm(), i); |
6fe7ccc8 A |
340 | } else { // b. Else |
341 | // i. If Desc.[[Value]] is present, then | |
342 | // 1. Call the [[Put]] internal method of map passing P, Desc.[[Value]], and Throw as the arguments. | |
343 | if (descriptor.value()) | |
93a37866 | 344 | thisObject->trySetArgument(exec->vm(), i, descriptor.value()); |
6fe7ccc8 A |
345 | // ii. If Desc.[[Writable]] is present and its value is false, then |
346 | // 1. Call the [[Delete]] internal method of map passing P and false as arguments. | |
347 | if (descriptor.writablePresent() && !descriptor.writable()) | |
81345200 | 348 | thisObject->tryDeleteArgument(exec->vm(), i); |
6fe7ccc8 A |
349 | } |
350 | } | |
351 | return true; | |
352 | } | |
9dae56ea | 353 | |
93a37866 A |
354 | if (propertyName == exec->propertyNames().length && !thisObject->m_overrodeLength) { |
355 | thisObject->putDirect(exec->vm(), propertyName, jsNumber(thisObject->m_numArguments), DontEnum); | |
356 | thisObject->m_overrodeLength = true; | |
357 | } else if (propertyName == exec->propertyNames().callee && !thisObject->m_overrodeCallee) { | |
358 | thisObject->putDirect(exec->vm(), propertyName, thisObject->m_callee.get(), DontEnum); | |
359 | thisObject->m_overrodeCallee = true; | |
360 | } else if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) | |
6fe7ccc8 A |
361 | thisObject->createStrictModeCallerIfNecessary(exec); |
362 | ||
363 | return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow); | |
364 | } | |
365 | ||
81345200 A |
366 | void Arguments::allocateRegisterArray(VM& vm) |
367 | { | |
368 | ASSERT(!m_registerArray); | |
369 | void* backingStore; | |
370 | if (!vm.heap.tryAllocateStorage(this, registerArraySizeInBytes(), &backingStore)) | |
371 | RELEASE_ASSERT_NOT_REACHED(); | |
372 | m_registerArray.set(vm, this, static_cast<WriteBarrier<Unknown>*>(backingStore)); | |
373 | } | |
374 | ||
6fe7ccc8 A |
375 | void Arguments::tearOff(CallFrame* callFrame) |
376 | { | |
377 | if (isTornOff()) | |
378 | return; | |
379 | ||
93a37866 | 380 | if (!m_numArguments) |
6fe7ccc8 A |
381 | return; |
382 | ||
93a37866 A |
383 | // Must be called for the same call frame from which it was created. |
384 | ASSERT(bitwise_cast<WriteBarrier<Unknown>*>(callFrame) == m_registers); | |
385 | ||
81345200 A |
386 | allocateRegisterArray(callFrame->vm()); |
387 | m_registers = m_registerArray.get() - CallFrame::offsetFor(1) - 1; | |
93a37866 A |
388 | |
389 | // If we have a captured argument that logically aliases activation storage, | |
390 | // but we optimize away the activation, the argument needs to tear off into | |
391 | // our storage. The simplest way to do this is to revert it to Normal status. | |
81345200 | 392 | if (m_slowArgumentData && !m_activation) { |
93a37866 | 393 | for (size_t i = 0; i < m_numArguments; ++i) { |
81345200 | 394 | if (m_slowArgumentData->slowArguments()[i].status != SlowArgument::Captured) |
93a37866 | 395 | continue; |
81345200 A |
396 | m_slowArgumentData->slowArguments()[i].status = SlowArgument::Normal; |
397 | m_slowArgumentData->slowArguments()[i].index = CallFrame::argumentOffset(i); | |
93a37866 A |
398 | } |
399 | } | |
6fe7ccc8 | 400 | |
81345200 A |
401 | for (size_t i = 0; i < m_numArguments; ++i) |
402 | trySetArgument(callFrame->vm(), i, callFrame->argumentAfterCapture(i)); | |
93a37866 A |
403 | } |
404 | ||
405 | void Arguments::didTearOffActivation(ExecState* exec, JSActivation* activation) | |
406 | { | |
407 | RELEASE_ASSERT(activation); | |
408 | if (isTornOff()) | |
409 | return; | |
410 | ||
411 | if (!m_numArguments) | |
412 | return; | |
413 | ||
414 | m_activation.set(exec->vm(), this, activation); | |
415 | tearOff(exec); | |
416 | } | |
417 | ||
418 | void Arguments::tearOff(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) | |
419 | { | |
420 | if (isTornOff()) | |
421 | return; | |
422 | ||
423 | if (!m_numArguments) | |
424 | return; | |
425 | ||
81345200 A |
426 | allocateRegisterArray(callFrame->vm()); |
427 | m_registers = m_registerArray.get() - CallFrame::offsetFor(1) - 1; | |
93a37866 | 428 | |
93a37866 | 429 | for (size_t i = 0; i < m_numArguments; ++i) { |
6fe7ccc8 | 430 | ValueRecovery& recovery = inlineCallFrame->arguments[i + 1]; |
81345200 | 431 | trySetArgument(callFrame->vm(), i, recovery.recover(callFrame)); |
6fe7ccc8 | 432 | } |
9dae56ea | 433 | } |
81345200 A |
434 | |
435 | EncodedJSValue JSC_HOST_CALL argumentsFuncIterator(ExecState* exec) | |
436 | { | |
437 | JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); | |
438 | Arguments* arguments = jsDynamicCast<Arguments*>(thisObj); | |
439 | if (!arguments) | |
440 | return JSValue::encode(throwTypeError(exec, "Attempted to use Arguments iterator on non-Arguments object")); | |
441 | return JSValue::encode(JSArgumentsIterator::create(exec->vm(), exec->callee()->globalObject()->argumentsIteratorStructure(), arguments)); | |
442 | } | |
443 | ||
9dae56ea A |
444 | |
445 | } // namespace JSC |