Home | History | Annotate | Download | only in runtime
      1 /*
      2  *  Copyright (C) 1999-2001 Harri Porten (porten (at) kde.org)
      3  *  Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
      4  *
      5  *  This library is free software; you can redistribute it and/or
      6  *  modify it under the terms of the GNU Library General Public
      7  *  License as published by the Free Software Foundation; either
      8  *  version 2 of the License, or (at your option) any later version.
      9  *
     10  *  This library is distributed in the hope that it will be useful,
     11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  *  Library General Public License for more details.
     14  *
     15  *  You should have received a copy of the GNU Library General Public License
     16  *  along with this library; see the file COPYING.LIB.  If not, write to
     17  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  *  Boston, MA 02110-1301, USA.
     19  *
     20  */
     21 
     22 #ifndef ArgList_h
     23 #define ArgList_h
     24 
     25 #include "Register.h"
     26 #include <wtf/HashSet.h>
     27 #include <wtf/Noncopyable.h>
     28 #include <wtf/Vector.h>
     29 
     30 namespace JSC {
     31 
     32     class MarkStack;
     33 
     34     class MarkedArgumentBuffer : public Noncopyable {
     35     private:
     36         static const unsigned inlineCapacity = 8;
     37         typedef Vector<Register, inlineCapacity> VectorType;
     38         typedef HashSet<MarkedArgumentBuffer*> ListSet;
     39 
     40     public:
     41         typedef VectorType::iterator iterator;
     42         typedef VectorType::const_iterator const_iterator;
     43 
     44         // Constructor for a read-write list, to which you may append values.
     45         // FIXME: Remove all clients of this API, then remove this API.
     46         MarkedArgumentBuffer()
     47             : m_isUsingInlineBuffer(true)
     48             , m_markSet(0)
     49 #ifndef NDEBUG
     50             , m_isReadOnly(false)
     51 #endif
     52         {
     53             m_buffer = m_vector.data();
     54             m_size = 0;
     55         }
     56 
     57         // Constructor for a read-only list whose data has already been allocated elsewhere.
     58         MarkedArgumentBuffer(Register* buffer, size_t size)
     59             : m_buffer(buffer)
     60             , m_size(size)
     61             , m_isUsingInlineBuffer(true)
     62             , m_markSet(0)
     63 #ifndef NDEBUG
     64             , m_isReadOnly(true)
     65 #endif
     66         {
     67         }
     68 
     69         void initialize(Register* buffer, size_t size)
     70         {
     71             ASSERT(!m_markSet);
     72             ASSERT(isEmpty());
     73 
     74             m_buffer = buffer;
     75             m_size = size;
     76 #ifndef NDEBUG
     77             m_isReadOnly = true;
     78 #endif
     79         }
     80 
     81         ~MarkedArgumentBuffer()
     82         {
     83             if (m_markSet)
     84                 m_markSet->remove(this);
     85         }
     86 
     87         size_t size() const { return m_size; }
     88         bool isEmpty() const { return !m_size; }
     89 
     90         JSValue at(size_t i) const
     91         {
     92             if (i < m_size)
     93                 return m_buffer[i].jsValue();
     94             return jsUndefined();
     95         }
     96 
     97         void clear()
     98         {
     99             m_vector.clear();
    100             m_buffer = 0;
    101             m_size = 0;
    102         }
    103 
    104         void append(JSValue v)
    105         {
    106             ASSERT(!m_isReadOnly);
    107 
    108 #if ENABLE(JSC_ZOMBIES)
    109             ASSERT(!v.isZombie());
    110 #endif
    111 
    112             if (m_isUsingInlineBuffer && m_size < inlineCapacity) {
    113                 m_vector.uncheckedAppend(v);
    114                 ++m_size;
    115             } else {
    116                 // Putting this case all in one function measurably improves
    117                 // the performance of the fast "just append to inline buffer" case.
    118                 slowAppend(v);
    119                 ++m_size;
    120                 m_isUsingInlineBuffer = false;
    121             }
    122         }
    123 
    124         void removeLast()
    125         {
    126             ASSERT(m_size);
    127             m_size--;
    128             m_vector.removeLast();
    129         }
    130 
    131         JSValue last()
    132         {
    133             ASSERT(m_size);
    134             return m_buffer[m_size - 1].jsValue();
    135         }
    136 
    137         iterator begin() { return m_buffer; }
    138         iterator end() { return m_buffer + m_size; }
    139 
    140         const_iterator begin() const { return m_buffer; }
    141         const_iterator end() const { return m_buffer + m_size; }
    142 
    143         static void markLists(MarkStack&, ListSet&);
    144 
    145     private:
    146         void slowAppend(JSValue);
    147 
    148         Register* m_buffer;
    149         size_t m_size;
    150         bool m_isUsingInlineBuffer;
    151 
    152         VectorType m_vector;
    153         ListSet* m_markSet;
    154 #ifndef NDEBUG
    155         bool m_isReadOnly;
    156 #endif
    157 
    158     private:
    159         // Prohibits new / delete, which would break GC.
    160         friend class JSGlobalData;
    161 
    162         void* operator new(size_t size)
    163         {
    164             return fastMalloc(size);
    165         }
    166         void operator delete(void* p)
    167         {
    168             fastFree(p);
    169         }
    170 
    171         void* operator new[](size_t);
    172         void operator delete[](void*);
    173 
    174         void* operator new(size_t, void*);
    175         void operator delete(void*, size_t);
    176     };
    177 
    178     class ArgList {
    179         friend class JIT;
    180     public:
    181         typedef JSValue* iterator;
    182         typedef const JSValue* const_iterator;
    183 
    184         ArgList()
    185             : m_args(0)
    186             , m_argCount(0)
    187         {
    188         }
    189 
    190         ArgList(JSValue* args, unsigned argCount)
    191             : m_args(args)
    192             , m_argCount(argCount)
    193         {
    194 #if ENABLE(JSC_ZOMBIES)
    195             for (size_t i = 0; i < argCount; i++)
    196                 ASSERT(!m_args[i].isZombie());
    197 #endif
    198         }
    199 
    200         ArgList(Register* args, int argCount)
    201             : m_args(reinterpret_cast<JSValue*>(args))
    202             , m_argCount(argCount)
    203         {
    204             ASSERT(argCount >= 0);
    205         }
    206 
    207         ArgList(const MarkedArgumentBuffer& args)
    208             : m_args(reinterpret_cast<JSValue*>(const_cast<Register*>(args.begin())))
    209             , m_argCount(args.size())
    210         {
    211         }
    212 
    213         JSValue at(size_t idx) const
    214         {
    215             if (idx < m_argCount)
    216                 return m_args[idx];
    217             return jsUndefined();
    218         }
    219 
    220         bool isEmpty() const { return !m_argCount; }
    221 
    222         size_t size() const { return m_argCount; }
    223 
    224         iterator begin() { return m_args; }
    225         iterator end() { return m_args + m_argCount; }
    226 
    227         const_iterator begin() const { return m_args; }
    228         const_iterator end() const { return m_args + m_argCount; }
    229 
    230         void getSlice(int startIndex, ArgList& result) const;
    231     private:
    232         JSValue* m_args;
    233         size_t m_argCount;
    234     };
    235 
    236 } // namespace JSC
    237 
    238 #endif // ArgList_h
    239