X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/fb8617cde5834786bd4e4afd579883e4acf5666e..a253471d7f8e4d91bf6ebabab00155c3b387d3d0:/runtime/Arguments.h diff --git a/runtime/Arguments.h b/runtime/Arguments.h index cca3cf2..a1f36de 100644 --- a/runtime/Arguments.h +++ b/runtime/Arguments.h @@ -24,89 +24,104 @@ #ifndef Arguments_h #define Arguments_h +#include "CodeOrigin.h" #include "JSActivation.h" #include "JSFunction.h" #include "JSGlobalObject.h" #include "Interpreter.h" #include "ObjectConstructor.h" -#include "PrototypeFunction.h" namespace JSC { - struct ArgumentsData : Noncopyable { - JSActivation* activation; + struct ArgumentsData { + WTF_MAKE_NONCOPYABLE(ArgumentsData); WTF_MAKE_FAST_ALLOCATED; + public: + ArgumentsData() { } + WriteBarrier activation; - unsigned numParameters; - ptrdiff_t firstParameterIndex; unsigned numArguments; - Register* registers; - OwnArrayPtr registerArray; + WriteBarrier* registers; + OwnArrayPtr > registerArray; - Register* extraArguments; OwnArrayPtr deletedArguments; - Register extraArgumentsFixedBuffer[4]; - JSFunction* callee; + WriteBarrier 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. + typedef JSNonFinalObject Base; + + static Arguments* create(JSGlobalData& globalData, CallFrame* callFrame) + { + Arguments* arguments = new (NotNull, allocateCell(globalData.heap)) Arguments(callFrame); + arguments->finishCreation(callFrame); + return arguments; + } + enum { MaxArguments = 0x10000 }; + private: enum NoParametersType { NoParameters }; - + Arguments(CallFrame*); Arguments(CallFrame*, NoParametersType); - virtual ~Arguments(); - static const ClassInfo info; + public: + static const ClassInfo s_info; - virtual void markChildren(MarkStack&); + static void visitChildren(JSCell*, SlotVisitor&); void fillArgList(ExecState*, MarkedArgumentBuffer&); - uint32_t numProvidedArguments(ExecState* exec) const + uint32_t length(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(); + void copyToArguments(ExecState*, CallFrame*, uint32_t length); + void tearOff(CallFrame*); bool isTornOff() const { return d->registerArray; } - void setActivation(JSActivation* activation) + void didTearOffActivation(JSGlobalData& globalData, JSActivation* activation) { - d->activation = activation; + if (isTornOff()) + return; + d->activation.set(globalData, this, activation); d->registers = &activation->registerAt(0); } - static PassRefPtr createStructure(JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } protected: - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags; + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; + + void finishCreation(CallFrame*); 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 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, PutPropertySlot&); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName); - virtual bool deleteProperty(ExecState*, unsigned propertyName); - - virtual const ClassInfo* classInfo() const { return &info; } + static void destroy(JSCell*); + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); + static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); + static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); + static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); + static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); + void createStrictModeCallerIfNecessary(ExecState*); + void createStrictModeCalleeIfNecessary(ExecState*); + + WriteBarrier& argument(size_t); void init(CallFrame*); @@ -117,136 +132,46 @@ namespace JSC { inline Arguments* asArguments(JSValue value) { - ASSERT(asObject(value)->inherits(&Arguments::info)); + ASSERT(asObject(value)->inherits(&Arguments::s_info)); return static_cast(asObject(value)); } - ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc) - { - function = callFrame->callee(); - - int numParameters = function->jsExecutable()->parameterCount(); - argc = callFrame->argumentCount(); - - if (argc <= numParameters) - argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters; - else - argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc; - - argc -= 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)) { - JSFunction* callee; - ptrdiff_t firstParameterIndex; - Register* argv; - int numArguments; - getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments); - - d->numParameters = callee->jsExecutable()->parameterCount(); - d->firstParameterIndex = firstParameterIndex; - d->numArguments = numArguments; - - d->activation = 0; - d->registers = callFrame->registers(); - - Register* 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]; - else - extraArguments = d->extraArgumentsFixedBuffer; - for (unsigned i = 0; i < numExtraArguments; ++i) - extraArguments[i] = argv[d->numParameters + i]; - } - - d->extraArguments = extraArguments; - - d->callee = callee; - d->overrodeLength = false; - d->overrodeCallee = false; } 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()->jsExecutable()->parameterCount()); - - unsigned numArguments = callFrame->argumentCount() - 1; - - d->numParameters = 0; - d->numArguments = numArguments; - d->activation = 0; - - Register* extraArguments; - if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register)) - extraArguments = new Register[numArguments]; - else - extraArguments = d->extraArgumentsFixedBuffer; - - Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1; - for (unsigned i = 0; i < numArguments; ++i) - extraArguments[i] = argv[i]; - - d->extraArguments = extraArguments; - - d->callee = callFrame->callee(); - d->overrodeLength = false; - d->overrodeCallee = false; } - inline void Arguments::copyRegisters() + inline WriteBarrier& Arguments::argument(size_t i) { - ASSERT(!isTornOff()); - - if (!d->numParameters) - return; - - 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; + return d->registers[CallFrame::argumentOffset(i)]; } - // This JSActivation function is defined here so it can get at Arguments::setRegisters. - inline void JSActivation::copyRegisters(Arguments* arguments) + inline void Arguments::finishCreation(CallFrame* callFrame) { - ASSERT(!d()->registerArray); - - size_t numParametersMinusThis = d()->functionExecutable->generatedBytecode().m_numParameters - 1; - size_t numVars = d()->functionExecutable->generatedBytecode().m_numVars; - size_t numLocals = numVars + numParametersMinusThis; - - if (!numLocals) - return; + Base::finishCreation(callFrame->globalData()); + ASSERT(inherits(&s_info)); - int registerOffset = 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)->setActivation(this); - } + JSFunction* callee = jsCast(callFrame->callee()); + d->numArguments = callFrame->argumentCount(); + d->registers = reinterpret_cast*>(callFrame->registers()); + d->callee.set(callFrame->globalData(), this, callee); + d->overrodeLength = false; + d->overrodeCallee = false; + d->overrodeCaller = false; + d->isStrictMode = callFrame->codeBlock()->isStrictMode(); - ALWAYS_INLINE Arguments* Register::arguments() const - { - if (jsValue() == JSValue()) - return 0; - return asArguments(jsValue()); + // The bytecode generator omits op_tear_off_activation in cases of no + // declared parameters, so we need to tear off immediately. + if (d->isStrictMode || !callee->jsExecutable()->parameterCount()) + tearOff(callFrame); } - } // namespace JSC