X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4be4e30906bcb8ee30b4d189205cb70bad6707ce..81345200c95645a1b0d2635520f96ad55dfde63f:/runtime/Arguments.h diff --git a/runtime/Arguments.h b/runtime/Arguments.h index 58ac782..6970cb8 100644 --- a/runtime/Arguments.h +++ b/runtime/Arguments.h @@ -26,19 +26,20 @@ #include "CodeOrigin.h" #include "JSActivation.h" -#include "JSDestructibleObject.h" #include "JSFunction.h" #include "JSGlobalObject.h" #include "Interpreter.h" #include "ObjectConstructor.h" +#include "WriteBarrierInlines.h" +#include namespace JSC { -class Arguments : public JSDestructibleObject { +class Arguments : public JSNonFinalObject { friend class JIT; - friend class DFG::SpeculativeJIT; + friend class JSArgumentsIterator; public: - typedef JSDestructibleObject Base; + typedef JSNonFinalObject Base; static Arguments* create(VM& vm, CallFrame* callFrame) { @@ -62,12 +63,11 @@ private: Arguments(CallFrame*); Arguments(CallFrame*, NoParametersType); - void tearOffForInlineCallFrame(VM& vm, Register*, InlineCallFrame*); - public: - static const ClassInfo s_info; + DECLARE_INFO; static void visitChildren(JSCell*, SlotVisitor&); + static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken); void fillArgList(ExecState*, MarkedArgumentBuffer&); @@ -78,17 +78,32 @@ public: return m_numArguments; } - void copyToArguments(ExecState*, CallFrame*, uint32_t length); + void copyToArguments(ExecState*, CallFrame*, uint32_t copyLength, int32_t firstArgumentOffset); void tearOff(CallFrame*); void tearOff(CallFrame*, InlineCallFrame*); - bool isTornOff() const { return m_registerArray; } + bool isTornOff() const { return m_registerArray.get(); } void didTearOffActivation(ExecState*, JSActivation*); static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + return Structure::create(vm, globalObject, prototype, TypeInfo(ArgumentsType, StructureFlags), info()); } - + + static ptrdiff_t offsetOfActivation() { return OBJECT_OFFSETOF(Arguments, m_activation); } + static ptrdiff_t offsetOfNumArguments() { return OBJECT_OFFSETOF(Arguments, m_numArguments); } + static ptrdiff_t offsetOfOverrodeLength() { return OBJECT_OFFSETOF(Arguments, m_overrodeLength); } + static ptrdiff_t offsetOfIsStrictMode() { return OBJECT_OFFSETOF(Arguments, m_isStrictMode); } + static ptrdiff_t offsetOfRegisters() { return OBJECT_OFFSETOF(Arguments, m_registers); } + static ptrdiff_t offsetOfRegisterArray() { return OBJECT_OFFSETOF(Arguments, m_registerArray); } + static ptrdiff_t offsetOfSlowArgumentData() { return OBJECT_OFFSETOF(Arguments, m_slowArgumentData); } + static ptrdiff_t offsetOfCallee() { return OBJECT_OFFSETOF(Arguments, m_callee); } + + static size_t allocationSize(size_t inlineCapacity) + { + ASSERT_UNUSED(inlineCapacity, !inlineCapacity); + return sizeof(Arguments); + } + protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; @@ -96,26 +111,26 @@ protected: void finishCreation(CallFrame*, InlineCallFrame*); private: - static void destroy(JSCell*); - static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); - static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); + static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); + static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&); static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); static bool deleteProperty(JSCell*, ExecState*, PropertyName); static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); - static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow); + static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow); void createStrictModeCallerIfNecessary(ExecState*); void createStrictModeCalleeIfNecessary(ExecState*); + size_t registerArraySizeInBytes() const { return sizeof(WriteBarrier) * m_numArguments; } + void allocateRegisterArray(VM&); bool isArgument(size_t); bool trySetArgument(VM&, size_t argument, JSValue); JSValue tryGetArgument(size_t argument); bool isDeletedArgument(size_t); - bool tryDeleteArgument(size_t); + bool tryDeleteArgument(VM&, size_t); WriteBarrierBase& argument(size_t); - void allocateSlowArguments(); + void allocateSlowArguments(VM&); void init(CallFrame*); @@ -132,9 +147,35 @@ private: bool m_isStrictMode; WriteBarrierBase* m_registers; - OwnArrayPtr > m_registerArray; + CopyWriteBarrier> m_registerArray; - OwnArrayPtr m_slowArguments; +public: + struct SlowArgumentData { + public: + SlowArgumentData() + : m_bytecodeToMachineCaptureOffset(0) + { + } + + SlowArgument* slowArguments() + { + return reinterpret_cast(WTF::roundUpToMultipleOf<8>(reinterpret_cast(this + 1))); + } + + int bytecodeToMachineCaptureOffset() const { return m_bytecodeToMachineCaptureOffset; } + void setBytecodeToMachineCaptureOffset(int newOffset) { m_bytecodeToMachineCaptureOffset = newOffset; } + + static size_t sizeForNumArguments(unsigned numArguments) + { + return WTF::roundUpToMultipleOf<8>(sizeof(SlowArgumentData)) + sizeof(SlowArgument) * numArguments; + } + + private: + int m_bytecodeToMachineCaptureOffset; // Add this if you have a bytecode offset into captured registers and you want the machine offset instead. Subtract if you want to do the opposite. + }; + +private: + CopyWriteBarrier m_slowArgumentData; WriteBarrier m_callee; }; @@ -143,37 +184,42 @@ Arguments* asArguments(JSValue); inline Arguments* asArguments(JSValue value) { - ASSERT(asObject(value)->inherits(&Arguments::s_info)); + ASSERT(asObject(value)->inherits(Arguments::info())); return static_cast(asObject(value)); } inline Arguments::Arguments(CallFrame* callFrame) - : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure()) + : Base(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure()) { } inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) - : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure()) + : Base(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure()) { } -inline void Arguments::allocateSlowArguments() +inline void Arguments::allocateSlowArguments(VM& vm) { - if (m_slowArguments) + if (!!m_slowArgumentData) return; - m_slowArguments = adoptArrayPtr(new SlowArgument[m_numArguments]); + + void* backingStore; + if (!vm.heap.tryAllocateStorage(this, SlowArgumentData::sizeForNumArguments(m_numArguments), &backingStore)) + RELEASE_ASSERT_NOT_REACHED(); + m_slowArgumentData.set(vm, this, static_cast(backingStore)); + for (size_t i = 0; i < m_numArguments; ++i) { - ASSERT(m_slowArguments[i].status == SlowArgument::Normal); - m_slowArguments[i].index = CallFrame::argumentOffset(i); + ASSERT(m_slowArgumentData->slowArguments()[i].status == SlowArgument::Normal); + m_slowArgumentData->slowArguments()[i].index = CallFrame::argumentOffset(i); } } -inline bool Arguments::tryDeleteArgument(size_t argument) +inline bool Arguments::tryDeleteArgument(VM& vm, size_t argument) { if (!isArgument(argument)) return false; - allocateSlowArguments(); - m_slowArguments[argument].status = SlowArgument::Deleted; + allocateSlowArguments(vm); + m_slowArgumentData->slowArguments()[argument].status = SlowArgument::Deleted; return true; } @@ -196,9 +242,9 @@ inline bool Arguments::isDeletedArgument(size_t argument) { if (argument >= m_numArguments) return false; - if (!m_slowArguments) + if (!m_slowArgumentData) return false; - if (m_slowArguments[argument].status != SlowArgument::Deleted) + if (m_slowArgumentData->slowArguments()[argument].status != SlowArgument::Deleted) return false; return true; } @@ -207,7 +253,7 @@ inline bool Arguments::isArgument(size_t argument) { if (argument >= m_numArguments) return false; - if (m_slowArguments && m_slowArguments[argument].status == SlowArgument::Deleted) + if (m_slowArgumentData && m_slowArgumentData->slowArguments()[argument].status == SlowArgument::Deleted) return false; return true; } @@ -215,20 +261,20 @@ inline bool Arguments::isArgument(size_t argument) inline WriteBarrierBase& Arguments::argument(size_t argument) { ASSERT(isArgument(argument)); - if (!m_slowArguments) + if (!m_slowArgumentData) return m_registers[CallFrame::argumentOffset(argument)]; - int index = m_slowArguments[argument].index; - if (!m_activation || m_slowArguments[argument].status != SlowArgument::Captured) + int index = m_slowArgumentData->slowArguments()[argument].index; + if (!m_activation || m_slowArgumentData->slowArguments()[argument].status != SlowArgument::Captured) return m_registers[index]; - return m_activation->registerAt(index); + return m_activation->registerAt(index - m_slowArgumentData->bytecodeToMachineCaptureOffset()); } inline void Arguments::finishCreation(CallFrame* callFrame) { Base::finishCreation(callFrame->vm()); - ASSERT(inherits(&s_info)); + ASSERT(inherits(info())); JSFunction* callee = jsCast(callFrame->callee()); m_numArguments = callFrame->argumentCount(); @@ -239,13 +285,16 @@ inline void Arguments::finishCreation(CallFrame* callFrame) m_overrodeCaller = false; m_isStrictMode = callFrame->codeBlock()->isStrictMode(); - SharedSymbolTable* symbolTable = callFrame->codeBlock()->symbolTable(); - const SlowArgument* slowArguments = symbolTable->slowArguments(); - if (slowArguments) { - allocateSlowArguments(); + CodeBlock* codeBlock = callFrame->codeBlock(); + if (codeBlock->hasSlowArguments()) { + SymbolTable* symbolTable = codeBlock->symbolTable(); + const SlowArgument* slowArguments = codeBlock->machineSlowArguments(); + allocateSlowArguments(callFrame->vm()); size_t count = std::min(m_numArguments, symbolTable->parameterCount()); for (size_t i = 0; i < count; ++i) - m_slowArguments[i] = slowArguments[i]; + m_slowArgumentData->slowArguments()[i] = slowArguments[i]; + m_slowArgumentData->setBytecodeToMachineCaptureOffset( + codeBlock->framePointerOffsetToGetActivationRegisters()); } // The bytecode generator omits op_tear_off_activation in cases of no @@ -257,11 +306,16 @@ inline void Arguments::finishCreation(CallFrame* callFrame) inline void Arguments::finishCreation(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) { Base::finishCreation(callFrame->vm()); - ASSERT(inherits(&s_info)); + ASSERT(inherits(info())); JSFunction* callee = inlineCallFrame->calleeForCallFrame(callFrame); m_numArguments = inlineCallFrame->arguments.size() - 1; - m_registers = reinterpret_cast*>(callFrame->registers()) + inlineCallFrame->stackOffset; + + if (m_numArguments) { + int offsetForArgumentOne = inlineCallFrame->arguments[1].virtualRegister().offset(); + m_registers = reinterpret_cast*>(callFrame->registers()) + offsetForArgumentOne - virtualRegisterForArgument(1).offset(); + } else + m_registers = 0; m_callee.set(callFrame->vm(), this, callee); m_overrodeLength = false; m_overrodeCallee = false;