/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
* Copyright (C) 2007 Maks Orlovich
*
#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "Interpreter.h"
+#include "ObjectConstructor.h"
namespace JSC {
- struct ArgumentsData : Noncopyable {
- JSActivation* activation;
+ struct ArgumentsData {
+ WTF_MAKE_NONCOPYABLE(ArgumentsData); WTF_MAKE_FAST_ALLOCATED;
+ public:
+ ArgumentsData() { }
+ WriteBarrier<JSActivation> activation;
unsigned numParameters;
ptrdiff_t firstParameterIndex;
unsigned numArguments;
- Register* registers;
- OwnArrayPtr<Register> registerArray;
+ WriteBarrier<Unknown>* registers;
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray;
- Register* extraArguments;
+ WriteBarrier<Unknown>* extraArguments;
OwnArrayPtr<bool> deletedArguments;
- Register extraArgumentsFixedBuffer[4];
+ WriteBarrier<Unknown> extraArgumentsFixedBuffer[4];
- JSFunction* callee;
+ WriteBarrier<JSFunction> callee;
bool overrodeLength : 1;
bool overrodeCallee : 1;
+ bool overrodeCaller : 1;
+ bool isStrictMode : 1;
};
- class Arguments : public JSObject {
+ class Arguments : public JSNonFinalObject {
public:
+ // Use an enum because otherwise gcc insists on doing a memory
+ // read.
+ enum { MaxArguments = 0x10000 };
+
enum NoParametersType { NoParameters };
Arguments(CallFrame*);
Arguments(CallFrame*, NoParametersType);
virtual ~Arguments();
- static const ClassInfo info;
+ static const ClassInfo s_info;
- virtual void mark();
+ virtual void visitChildren(SlotVisitor&);
- void fillArgList(ExecState*, ArgList&);
+ void fillArgList(ExecState*, MarkedArgumentBuffer&);
- void copyRegisters();
+ uint32_t numProvidedArguments(ExecState* exec) const
+ {
+ if (UNLIKELY(d->overrodeLength))
+ return get(exec, exec->propertyNames().length).toUInt32(exec);
+ return d->numArguments;
+ }
+
+ void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize);
+ void copyRegisters(JSGlobalData&);
bool isTornOff() const { return d->registerArray; }
- void setActivation(JSActivation* activation)
+ void setActivation(JSGlobalData& globalData, JSActivation* activation)
{
- d->activation = activation;
+ ASSERT(!d->registerArray);
+ d->activation.set(globalData, this, activation);
d->registers = &activation->registerAt(0);
}
- static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
+ static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType));
+ return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
}
+ protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
+
private:
void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
- virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
- virtual void put(ExecState*, unsigned propertyName, JSValuePtr, PutPropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+ virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ virtual void put(ExecState*, unsigned propertyName, JSValue);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual bool deleteProperty(ExecState*, unsigned propertyName);
-
- virtual const ClassInfo* classInfo() const { return &info; }
+ void createStrictModeCallerIfNecessary(ExecState*);
+ void createStrictModeCalleeIfNecessary(ExecState*);
void init(CallFrame*);
OwnPtr<ArgumentsData> d;
};
- Arguments* asArguments(JSValuePtr);
+ Arguments* asArguments(JSValue);
- inline Arguments* asArguments(JSValuePtr value)
+ inline Arguments* asArguments(JSValue value)
{
- ASSERT(asObject(value)->inherits(&Arguments::info));
+ ASSERT(asObject(value)->inherits(&Arguments::s_info));
return static_cast<Arguments*>(asObject(value));
}
ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
{
- function = callFrame->callee();
-
- CodeBlock* codeBlock = &function->body()->generatedBytecode();
- int numParameters = codeBlock->m_numParameters;
- argc = callFrame->argumentCount();
+ function = asFunction(callFrame->callee());
+
+ int numParameters = function->jsExecutable()->parameterCount();
+ argc = callFrame->argumentCountIncludingThis();
if (argc <= numParameters)
- argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
+ argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
else
- argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc + 1; // + 1 to skip "this"
+ argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc;
argc -= 1; // - 1 to skip "this"
- firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
+ firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters;
}
inline Arguments::Arguments(CallFrame* callFrame)
- : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
- , d(new ArgumentsData)
+ : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
+ , d(adoptPtr(new ArgumentsData))
{
+ ASSERT(inherits(&s_info));
+
JSFunction* callee;
ptrdiff_t firstParameterIndex;
Register* argv;
int numArguments;
getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
- d->numParameters = callee->body()->parameterCount();
+ d->numParameters = callee->jsExecutable()->parameterCount();
d->firstParameterIndex = firstParameterIndex;
d->numArguments = numArguments;
- d->activation = 0;
- d->registers = callFrame->registers();
+ d->registers = reinterpret_cast<WriteBarrier<Unknown>*>(callFrame->registers());
- Register* extraArguments;
+ WriteBarrier<Unknown>* extraArguments;
if (d->numArguments <= d->numParameters)
extraArguments = 0;
else {
unsigned numExtraArguments = d->numArguments - d->numParameters;
- if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
- extraArguments = new Register[numExtraArguments];
+ if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(WriteBarrier<Unknown>))
+ extraArguments = new WriteBarrier<Unknown>[numExtraArguments];
else
extraArguments = d->extraArgumentsFixedBuffer;
for (unsigned i = 0; i < numExtraArguments; ++i)
- extraArguments[i] = argv[d->numParameters + i];
+ extraArguments[i].set(callFrame->globalData(), this, argv[d->numParameters + i].jsValue());
}
d->extraArguments = extraArguments;
- d->callee = callee;
+ d->callee.set(callFrame->globalData(), this, callee);
d->overrodeLength = false;
d->overrodeCallee = false;
+ d->overrodeCaller = false;
+ d->isStrictMode = callFrame->codeBlock()->isStrictMode();
+ if (d->isStrictMode)
+ copyRegisters(callFrame->globalData());
}
inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
- : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
- , d(new ArgumentsData)
+ : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
+ , d(adoptPtr(new ArgumentsData))
{
- ASSERT(!callFrame->callee()->body()->parameterCount());
+ ASSERT(inherits(&s_info));
+ ASSERT(!asFunction(callFrame->callee())->jsExecutable()->parameterCount());
- unsigned numArguments = callFrame->argumentCount() - 1;
+ unsigned numArguments = callFrame->argumentCount();
d->numParameters = 0;
d->numArguments = numArguments;
- d->activation = 0;
- Register* extraArguments;
+ WriteBarrier<Unknown>* extraArguments;
if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
- extraArguments = new Register[numArguments];
+ extraArguments = new WriteBarrier<Unknown>[numArguments];
else
extraArguments = d->extraArgumentsFixedBuffer;
Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1;
for (unsigned i = 0; i < numArguments; ++i)
- extraArguments[i] = argv[i];
+ extraArguments[i].set(callFrame->globalData(), this, argv[i].jsValue());
d->extraArguments = extraArguments;
- d->callee = callFrame->callee();
+ d->callee.set(callFrame->globalData(), this, asFunction(callFrame->callee()));
d->overrodeLength = false;
d->overrodeCallee = false;
+ d->overrodeCaller = false;
+ d->isStrictMode = callFrame->codeBlock()->isStrictMode();
+ if (d->isStrictMode)
+ copyRegisters(callFrame->globalData());
}
- inline void Arguments::copyRegisters()
+ inline void Arguments::copyRegisters(JSGlobalData& globalData)
{
ASSERT(!isTornOff());
int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
size_t registerArraySize = d->numParameters;
- Register* registerArray = new Register[registerArraySize];
- memcpy(registerArray, d->registers - registerOffset, registerArraySize * sizeof(Register));
- d->registerArray.set(registerArray);
- d->registers = registerArray + registerOffset;
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]);
+ for (size_t i = 0; i < registerArraySize; i++)
+ registerArray[i].set(globalData, this, d->registers[i - registerOffset].get());
+ d->registers = registerArray.get() + registerOffset;
+ d->registerArray = registerArray.release();
}
// This JSActivation function is defined here so it can get at Arguments::setRegisters.
- inline void JSActivation::copyRegisters(Arguments* arguments)
+ inline void JSActivation::copyRegisters(JSGlobalData& globalData)
{
- ASSERT(!d()->registerArray);
+ ASSERT(!m_registerArray);
- size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1;
- size_t numVars = d()->functionBody->generatedBytecode().m_numVars;
- size_t numLocals = numVars + numParametersMinusThis;
+ size_t numLocals = m_numCapturedVars + m_numParametersMinusThis;
if (!numLocals)
return;
- int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
+ int registerOffset = m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
- Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize);
- setRegisters(registerArray + registerOffset, registerArray);
- if (arguments && !arguments->isTornOff())
- static_cast<Arguments*>(arguments)->setActivation(this);
+ OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, m_registers - registerOffset, registerArraySize, m_numParametersMinusThis + 1);
+ WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset;
+ setRegisters(registers, registerArray.release());
}
} // namespace JSC