]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/Arguments.h
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / runtime / Arguments.h
index 58ac782b6b6155315fc09dea5150dd78910a920e..6970cb8db948637dcf78756be4345404ac17d0d4 100644 (file)
 
 #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 <wtf/StdLibExtras.h>
 
 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<Unknown>) * 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<Unknown>& argument(size_t);
-    void allocateSlowArguments();
+    void allocateSlowArguments(VM&);
 
     void init(CallFrame*);
 
@@ -132,9 +147,35 @@ private:
     bool m_isStrictMode;
 
     WriteBarrierBase<Unknown>* m_registers;
-    OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray;
+    CopyWriteBarrier<WriteBarrier<Unknown>> m_registerArray;
 
-    OwnArrayPtr<SlowArgument> m_slowArguments;
+public:
+    struct SlowArgumentData {
+    public:
+        SlowArgumentData()
+            : m_bytecodeToMachineCaptureOffset(0)
+        {
+        }
+
+        SlowArgument* slowArguments()
+        {
+            return reinterpret_cast<SlowArgument*>(WTF::roundUpToMultipleOf<8>(reinterpret_cast<size_t>(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<SlowArgumentData> m_slowArgumentData;
 
     WriteBarrier<JSFunction> 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<Arguments*>(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<SlowArgumentData*>(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<Unknown>& 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<JSFunction*>(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<unsigned>(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<WriteBarrierBase<Unknown>*>(callFrame->registers()) + inlineCallFrame->stackOffset;
+    
+    if (m_numArguments) {
+        int offsetForArgumentOne = inlineCallFrame->arguments[1].virtualRegister().offset();
+        m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()) + offsetForArgumentOne - virtualRegisterForArgument(1).offset();
+    } else
+        m_registers = 0;
     m_callee.set(callFrame->vm(), this, callee);
     m_overrodeLength = false;
     m_overrodeCallee = false;