X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/9dae56ea45a0f5f8136a5c93d6f3a7f99399ca73..1df5f87f1309a8daa30dabdee855f48ae40d14ab:/runtime/Arguments.cpp diff --git a/runtime/Arguments.cpp b/runtime/Arguments.cpp index b0429a9..ec6cc8f 100644 --- a/runtime/Arguments.cpp +++ b/runtime/Arguments.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * @@ -35,7 +35,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(Arguments); -const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 }; +const ClassInfo Arguments::s_info = { "Arguments", &JSNonFinalObject::s_info, 0, 0 }; Arguments::~Arguments() { @@ -43,34 +43,71 @@ Arguments::~Arguments() delete [] d->extraArguments; } -void Arguments::mark() +void Arguments::visitChildren(SlotVisitor& visitor) { - JSObject::mark(); + ASSERT_GC_OBJECT_INHERITS(this, &s_info); + COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); + ASSERT(structure()->typeInfo().overridesVisitChildren()); + JSObject::visitChildren(visitor); - if (d->registerArray) { - for (unsigned i = 0; i < d->numParameters; ++i) { - if (!d->registerArray[i].marked()) - d->registerArray[i].mark(); - } - } + if (d->registerArray) + visitor.appendValues(d->registerArray.get(), d->numParameters); if (d->extraArguments) { unsigned numExtraArguments = d->numArguments - d->numParameters; - for (unsigned i = 0; i < numExtraArguments; ++i) { - if (!d->extraArguments[i].marked()) - d->extraArguments[i].mark(); - } + visitor.appendValues(d->extraArguments, numExtraArguments); } - if (!d->callee->marked()) - d->callee->mark(); + visitor.append(&d->callee); + + if (d->activation) + visitor.append(&d->activation); +} + +void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize) +{ + if (UNLIKELY(d->overrodeLength)) { + unsigned length = min(get(exec, exec->propertyNames().length).toUInt32(exec), maxSize); + for (unsigned i = 0; i < length; i++) + buffer[i] = get(exec, i); + return; + } - if (d->activation && !d->activation->marked()) - d->activation->mark(); + if (LIKELY(!d->deletedArguments)) { + unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize); + unsigned i = 0; + for (; i < parametersLength; ++i) + buffer[i] = d->registers[d->firstParameterIndex + i].get(); + for (; i < d->numArguments; ++i) + buffer[i] = d->extraArguments[i - d->numParameters].get(); + return; + } + + unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize); + unsigned i = 0; + for (; i < parametersLength; ++i) { + if (!d->deletedArguments[i]) + buffer[i] = d->registers[d->firstParameterIndex + i].get(); + else + buffer[i] = get(exec, i); + } + for (; i < d->numArguments; ++i) { + if (!d->deletedArguments[i]) + buffer[i] = d->extraArguments[i - d->numParameters].get(); + else + buffer[i] = get(exec, i); + } } -void Arguments::fillArgList(ExecState* exec, ArgList& args) +void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) { + if (UNLIKELY(d->overrodeLength)) { + unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec); + for (unsigned i = 0; i < length; i++) + args.append(get(exec, i)); + return; + } + if (LIKELY(!d->deletedArguments)) { if (LIKELY(!d->numParameters)) { args.initialize(d->extraArguments, d->numArguments); @@ -85,9 +122,9 @@ void Arguments::fillArgList(ExecState* exec, ArgList& args) unsigned parametersLength = min(d->numParameters, d->numArguments); unsigned i = 0; for (; i < parametersLength; ++i) - args.append(d->registers[d->firstParameterIndex + i].jsValue(exec)); + args.append(d->registers[d->firstParameterIndex + i].get()); for (; i < d->numArguments; ++i) - args.append(d->extraArguments[i - d->numParameters].jsValue(exec)); + args.append(d->extraArguments[i - d->numParameters].get()); return; } @@ -95,13 +132,13 @@ void Arguments::fillArgList(ExecState* exec, ArgList& args) unsigned i = 0; for (; i < parametersLength; ++i) { if (!d->deletedArguments[i]) - args.append(d->registers[d->firstParameterIndex + i].jsValue(exec)); + args.append(d->registers[d->firstParameterIndex + i].get()); else args.append(get(exec, i)); } for (; i < d->numArguments; ++i) { if (!d->deletedArguments[i]) - args.append(d->extraArguments[i - d->numParameters].jsValue(exec)); + args.append(d->extraArguments[i - d->numParameters].get()); else args.append(get(exec, i)); } @@ -111,77 +148,158 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& sl { if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) { - slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]); + slot.setValue(d->registers[d->firstParameterIndex + i].get()); } else - slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec)); + slot.setValue(d->extraArguments[i - d->numParameters].get()); return true; } - return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::from(i)), slot); + return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::number(i)), slot); +} + +void Arguments::createStrictModeCallerIfNecessary(ExecState* exec) +{ + if (d->overrodeCaller) + return; + + d->overrodeCaller = true; + PropertyDescriptor descriptor; + JSValue thrower = createTypeErrorFunction(exec, "Unable to access caller of strict mode function"); + descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter); + defineOwnProperty(exec, exec->propertyNames().caller, descriptor, false); +} + +void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec) +{ + if (d->overrodeCallee) + return; + + d->overrodeCallee = true; + PropertyDescriptor descriptor; + JSValue thrower = createTypeErrorFunction(exec, "Unable to access callee of strict mode function"); + descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter); + defineOwnProperty(exec, exec->propertyNames().callee, descriptor, false); } bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { bool isArrayIndex; - unsigned i = propertyName.toArrayIndex(&isArrayIndex); + unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) { - slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]); + slot.setValue(d->registers[d->firstParameterIndex + i].get()); } else - slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec)); + slot.setValue(d->extraArguments[i - d->numParameters].get()); return true; } if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) { - slot.setValue(jsNumber(exec, d->numArguments)); + slot.setValue(jsNumber(d->numArguments)); return true; } if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { - slot.setValue(d->callee); - return true; + if (!d->isStrictMode) { + slot.setValue(d->callee.get()); + return true; + } + createStrictModeCalleeIfNecessary(exec); } + if (propertyName == exec->propertyNames().caller && d->isStrictMode) + createStrictModeCallerIfNecessary(exec); + return JSObject::getOwnPropertySlot(exec, propertyName, slot); } -void Arguments::put(ExecState* exec, unsigned i, JSValuePtr value, PutPropertySlot& slot) +bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + bool isArrayIndex; + unsigned i = propertyName.toArrayIndex(isArrayIndex); + if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { + if (i < d->numParameters) { + descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].get(), DontEnum); + } else + descriptor.setDescriptor(d->extraArguments[i - d->numParameters].get(), DontEnum); + return true; + } + + if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) { + descriptor.setDescriptor(jsNumber(d->numArguments), DontEnum); + return true; + } + + if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { + if (!d->isStrictMode) { + descriptor.setDescriptor(d->callee.get(), DontEnum); + return true; + } + createStrictModeCalleeIfNecessary(exec); + } + + if (propertyName == exec->propertyNames().caller && d->isStrictMode) + createStrictModeCallerIfNecessary(exec); + + return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + +void Arguments::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + if (mode == IncludeDontEnumProperties) { + for (unsigned i = 0; i < d->numArguments; ++i) { + if (!d->deletedArguments || !d->deletedArguments[i]) + propertyNames.add(Identifier(exec, UString::number(i))); + } + propertyNames.add(exec->propertyNames().callee); + propertyNames.add(exec->propertyNames().length); + } + JSObject::getOwnPropertyNames(exec, propertyNames, mode); +} + +void Arguments::put(ExecState* exec, unsigned i, JSValue value) { if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) - d->registers[d->firstParameterIndex + i] = JSValuePtr(value); + d->registers[d->firstParameterIndex + i].set(exec->globalData(), d->activation ? static_cast(d->activation.get()) : static_cast(this), value); else - d->extraArguments[i - d->numParameters] = JSValuePtr(value); + d->extraArguments[i - d->numParameters].set(exec->globalData(), this, value); return; } - JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot); + PutPropertySlot slot; + JSObject::put(exec, Identifier(exec, UString::number(i)), value, slot); } -void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) +void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { bool isArrayIndex; - unsigned i = propertyName.toArrayIndex(&isArrayIndex); + unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { if (i < d->numParameters) - d->registers[d->firstParameterIndex + i] = JSValuePtr(value); + d->registers[d->firstParameterIndex + i].set(exec->globalData(), d->activation ? static_cast(d->activation.get()) : static_cast(this), value); else - d->extraArguments[i - d->numParameters] = JSValuePtr(value); + d->extraArguments[i - d->numParameters].set(exec->globalData(), this, value); return; } if (propertyName == exec->propertyNames().length && !d->overrodeLength) { d->overrodeLength = true; - putDirect(propertyName, value, DontEnum); + putDirect(exec->globalData(), propertyName, value, DontEnum); return; } if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) { - d->overrodeCallee = true; - putDirect(propertyName, value, DontEnum); - return; + if (!d->isStrictMode) { + d->overrodeCallee = true; + putDirect(exec->globalData(), propertyName, value, DontEnum); + return; + } + createStrictModeCalleeIfNecessary(exec); } + if (propertyName == exec->propertyNames().caller && d->isStrictMode) + createStrictModeCallerIfNecessary(exec); + JSObject::put(exec, propertyName, value, slot); } @@ -189,7 +307,7 @@ bool Arguments::deleteProperty(ExecState* exec, unsigned i) { if (i < d->numArguments) { if (!d->deletedArguments) { - d->deletedArguments.set(new bool[d->numArguments]); + d->deletedArguments = adoptArrayPtr(new bool[d->numArguments]); memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments); } if (!d->deletedArguments[i]) { @@ -198,16 +316,16 @@ bool Arguments::deleteProperty(ExecState* exec, unsigned i) } } - return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i))); + return JSObject::deleteProperty(exec, Identifier(exec, UString::number(i))); } bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) { bool isArrayIndex; - unsigned i = propertyName.toArrayIndex(&isArrayIndex); + unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < d->numArguments) { if (!d->deletedArguments) { - d->deletedArguments.set(new bool[d->numArguments]); + d->deletedArguments = adoptArrayPtr(new bool[d->numArguments]); memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments); } if (!d->deletedArguments[i]) { @@ -222,9 +340,15 @@ bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) } if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) { - d->overrodeCallee = true; - return true; + if (!d->isStrictMode) { + d->overrodeCallee = true; + return true; + } + createStrictModeCalleeIfNecessary(exec); } + + if (propertyName == exec->propertyNames().caller && !d->isStrictMode) + createStrictModeCallerIfNecessary(exec); return JSObject::deleteProperty(exec, propertyName); }