]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/ArgList.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / runtime / ArgList.h
index 3c8256188e7fe6375a19463a03534549500f2684..9aafc90707dd4e31137eb75e8d904e8c90ef6be2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2007, 2008, 2009 Apple Computer, Inc.
+ *  Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
 #ifndef ArgList_h
 #define ArgList_h
 
+#include "CallFrame.h"
 #include "Register.h"
-
 #include <wtf/HashSet.h>
-#include <wtf/Noncopyable.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
-    
-    class MarkedArgumentBuffer : Noncopyable {
-    private:
-        static const unsigned inlineCapacity = 8;
-        typedef Vector<Register, inlineCapacity> VectorType;
-        typedef HashSet<MarkedArgumentBuffer*> ListSet;
-
-    public:
-        typedef VectorType::iterator iterator;
-        typedef VectorType::const_iterator const_iterator;
-
-        // Constructor for a read-write list, to which you may append values.
-        // FIXME: Remove all clients of this API, then remove this API.
-        MarkedArgumentBuffer()
-            : m_isUsingInlineBuffer(true)
-            , m_markSet(0)
-#ifndef NDEBUG
-            , m_isReadOnly(false)
-#endif
-        {
-            m_buffer = m_vector.data();
-            m_size = 0;
-        }
-
-        // Constructor for a read-only list whose data has already been allocated elsewhere.
-        MarkedArgumentBuffer(Register* buffer, size_t size)
-            : m_buffer(buffer)
-            , m_size(size)
-            , m_isUsingInlineBuffer(true)
-            , m_markSet(0)
-#ifndef NDEBUG
-            , m_isReadOnly(true)
-#endif
-        {
-        }
-
-        void initialize(Register* buffer, size_t size)
-        {
-            ASSERT(!m_markSet);
-            ASSERT(isEmpty());
-
-            m_buffer = buffer;
-            m_size = size;
-#ifndef NDEBUG
-            m_isReadOnly = true;
-#endif
-        }
-
-        ~MarkedArgumentBuffer()
-        {
-            if (m_markSet)
-                m_markSet->remove(this);
-        }
-
-        size_t size() const { return m_size; }
-        bool isEmpty() const { return !m_size; }
-
-        JSValue at(size_t i) const
-        {
-            if (i < m_size)
-                return m_buffer[i].jsValue();
-            return jsUndefined();
-        }
-
-        void clear()
-        {
-            m_vector.clear();
-            m_buffer = 0;
-            m_size = 0;
-        }
-
-        void append(JSValue v)
-        {
-            ASSERT(!m_isReadOnly);
-            
-            if (m_isUsingInlineBuffer && m_size < inlineCapacity) {
-                m_vector.uncheckedAppend(v);
-                ++m_size;
-            } else {
-                // Putting this case all in one function measurably improves
-                // the performance of the fast "just append to inline buffer" case.
-                slowAppend(v);
-                ++m_size;
-                m_isUsingInlineBuffer = false;
-            }
-        }
-
-        void removeLast()
-        { 
-            ASSERT(m_size);
-            m_size--;
-            m_vector.removeLast();
-        }
-
-        JSValue last() 
-        {
-            ASSERT(m_size);
-            return m_buffer[m_size - 1].jsValue();
-        }
-        
-        iterator begin() { return m_buffer; }
-        iterator end() { return m_buffer + m_size; }
 
-        const_iterator begin() const { return m_buffer; }
-        const_iterator end() const { return m_buffer + m_size; }
-
-        static void markLists(ListSet&);
+class SlotVisitor;
+
+class MarkedArgumentBuffer {
+    WTF_MAKE_NONCOPYABLE(MarkedArgumentBuffer);
+    friend class VM;
+    friend class ArgList;
+
+private:
+    static const size_t inlineCapacity = 8;
+    typedef HashSet<MarkedArgumentBuffer*> ListSet;
+
+public:
+    // Constructor for a read-write list, to which you may append values.
+    // FIXME: Remove all clients of this API, then remove this API.
+    MarkedArgumentBuffer()
+        : m_size(0)
+        , m_capacity(inlineCapacity)
+        , m_buffer(m_inlineBuffer)
+        , m_markSet(0)
+    {
+    }
+
+    ~MarkedArgumentBuffer()
+    {
+        if (m_markSet)
+            m_markSet->remove(this);
+
+        if (EncodedJSValue* base = mallocBase())
+            delete [] base;
+    }
+
+    size_t size() const { return m_size; }
+    bool isEmpty() const { return !m_size; }
+
+    JSValue at(int i) const
+    {
+        if (i >= m_size)
+            return jsUndefined();
 
-    private:
-        void slowAppend(JSValue);
+        return JSValue::decode(slotFor(i));
+    }
+
+    void clear()
+    {
+        m_size = 0;
+    }
+
+    void append(JSValue v)
+    {
+        if (m_size >= m_capacity)
+            return slowAppend(v);
+
+        slotFor(m_size) = JSValue::encode(v);
+        ++m_size;
+    }
+
+    void removeLast()
+    { 
+        ASSERT(m_size);
+        m_size--;
+    }
+
+    JSValue last() 
+    {
+        ASSERT(m_size);
+        return JSValue::decode(slotFor(m_size - 1));
+    }
         
-        Register* m_buffer;
-        size_t m_size;
-        bool m_isUsingInlineBuffer;
-
-        VectorType m_vector;
-        ListSet* m_markSet;
-#ifndef NDEBUG
-        bool m_isReadOnly;
-#endif
-
-    private:
-        // Prohibits new / delete, which would break GC.
-        friend class JSGlobalData;
+    static void markLists(HeapRootVisitor&, ListSet&);
+
+private:
+    JS_EXPORT_PRIVATE void slowAppend(JSValue);
         
-        void* operator new(size_t size)
-        {
-            return fastMalloc(size);
-        }
-        void operator delete(void* p)
-        {
-            fastFree(p);
-        }
-
-        void* operator new[](size_t);
-        void operator delete[](void*);
-
-        void* operator new(size_t, void*);
-        void operator delete(void*, size_t);
-    };
-
-    class ArgList {
-        friend class JIT;
-    public:
-        typedef JSValue* iterator;
-        typedef const JSValue* const_iterator;
-
-        ArgList()
-            : m_args(0)
-            , m_argCount(0)
-        {
-        }
+    EncodedJSValue& slotFor(int item) const
+    {
+        return m_buffer[item];
+    }
         
-        ArgList(JSValue* args, unsigned argCount)
-            : m_args(args)
-            , m_argCount(argCount)
-        {
-        }
+    EncodedJSValue* mallocBase()
+    {
+        if (m_capacity == static_cast<int>(inlineCapacity))
+            return 0;
+        return &slotFor(0);
+    }
         
-        ArgList(Register* args, int argCount)
-            : m_args(reinterpret_cast<JSValue*>(args))
-            , m_argCount(argCount)
-        {
-            ASSERT(argCount >= 0);
-        }
-
-        ArgList(const MarkedArgumentBuffer& args)
-            : m_args(reinterpret_cast<JSValue*>(const_cast<Register*>(args.begin())))
-            , m_argCount(args.size())
-        {
-        }
-
-        JSValue at(size_t idx) const
-        {
-            if (idx < m_argCount)
-                return m_args[idx];
+    int m_size;
+    int m_capacity;
+    EncodedJSValue m_inlineBuffer[inlineCapacity];
+    EncodedJSValue* m_buffer;
+    ListSet* m_markSet;
+
+private:
+    // Prohibits new / delete, which would break GC.
+    void* operator new(size_t size)
+    {
+        return fastMalloc(size);
+    }
+    void operator delete(void* p)
+    {
+        fastFree(p);
+    }
+
+    void* operator new[](size_t);
+    void operator delete[](void*);
+
+    void* operator new(size_t, void*);
+    void operator delete(void*, size_t);
+};
+
+class ArgList {
+    friend class Interpreter;
+    friend class JIT;
+public:
+    ArgList()
+        : m_args(0)
+        , m_argCount(0)
+    {
+    }
+
+    ArgList(ExecState* exec)
+        : m_args(reinterpret_cast<JSValue*>(&exec[CallFrame::argumentOffset(0)]))
+        , m_argCount(exec->argumentCount())
+    {
+    }
+
+    ArgList(const MarkedArgumentBuffer& args)
+        : m_args(reinterpret_cast<JSValue*>(args.m_buffer))
+        , m_argCount(args.size())
+    {
+    }
+
+    JSValue at(int i) const
+    {
+        if (i >= m_argCount)
             return jsUndefined();
-        }
-
-        bool isEmpty() const { return !m_argCount; }
+        return m_args[i];
+    }
 
-        size_t size() const { return m_argCount; }
-        
-        iterator begin() { return m_args; }
-        iterator end() { return m_args + m_argCount; }
+    bool isEmpty() const { return !m_argCount; }
+    size_t size() const { return m_argCount; }
         
-        const_iterator begin() const { return m_args; }
-        const_iterator end() const { return m_args + m_argCount; }
-
-        void getSlice(int startIndex, ArgList& result) const;
-    private:
-        JSValue* m_args;
-        size_t m_argCount;
-    };
+    JS_EXPORT_PRIVATE void getSlice(int startIndex, ArgList& result) const;
+
+private:
+    JSValue* data() const { return m_args; }
+
+    JSValue* m_args;
+    int m_argCount;
+};
 
 } // namespace JSC