1/*
2 *  Copyright (C) 1999-2001 Harri Porten (porten@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 "CallFrame.h"
26#include "Register.h"
27#include <wtf/HashSet.h>
28#include <wtf/Vector.h>
29
30namespace JSC {
31
32class SlotVisitor;
33
34class MarkedArgumentBuffer {
35    WTF_MAKE_NONCOPYABLE(MarkedArgumentBuffer);
36    friend class VM;
37    friend class ArgList;
38
39private:
40    static const size_t inlineCapacity = 8;
41    typedef HashSet<MarkedArgumentBuffer*> ListSet;
42
43public:
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_size(0)
48        , m_capacity(inlineCapacity)
49        , m_buffer(m_inlineBuffer)
50        , m_markSet(0)
51    {
52    }
53
54    ~MarkedArgumentBuffer()
55    {
56        if (m_markSet)
57            m_markSet->remove(this);
58
59        if (EncodedJSValue* base = mallocBase())
60            delete [] base;
61    }
62
63    size_t size() const { return m_size; }
64    bool isEmpty() const { return !m_size; }
65
66    JSValue at(int i) const
67    {
68        if (i >= m_size)
69            return jsUndefined();
70
71        return JSValue::decode(slotFor(i));
72    }
73
74    void clear()
75    {
76        m_size = 0;
77    }
78
79    void append(JSValue v)
80    {
81        if (m_size >= m_capacity)
82            return slowAppend(v);
83
84        slotFor(m_size) = JSValue::encode(v);
85        ++m_size;
86    }
87
88    void removeLast()
89    {
90        ASSERT(m_size);
91        m_size--;
92    }
93
94    JSValue last()
95    {
96        ASSERT(m_size);
97        return JSValue::decode(slotFor(m_size - 1));
98    }
99
100    static void markLists(HeapRootVisitor&, ListSet&);
101
102private:
103    JS_EXPORT_PRIVATE void slowAppend(JSValue);
104
105    EncodedJSValue& slotFor(int item) const
106    {
107        return m_buffer[item];
108    }
109
110    EncodedJSValue* mallocBase()
111    {
112        if (m_capacity == static_cast<int>(inlineCapacity))
113            return 0;
114        return &slotFor(0);
115    }
116
117    int m_size;
118    int m_capacity;
119    EncodedJSValue m_inlineBuffer[inlineCapacity];
120    EncodedJSValue* m_buffer;
121    ListSet* m_markSet;
122
123private:
124    // Prohibits new / delete, which would break GC.
125    void* operator new(size_t size)
126    {
127        return fastMalloc(size);
128    }
129    void operator delete(void* p)
130    {
131        fastFree(p);
132    }
133
134    void* operator new[](size_t);
135    void operator delete[](void*);
136
137    void* operator new(size_t, void*);
138    void operator delete(void*, size_t);
139};
140
141class ArgList {
142    friend class Interpreter;
143    friend class JIT;
144public:
145    ArgList()
146        : m_args(0)
147        , m_argCount(0)
148    {
149    }
150
151    ArgList(ExecState* exec)
152        : m_args(reinterpret_cast<JSValue*>(&exec[CallFrame::argumentOffset(0)]))
153        , m_argCount(exec->argumentCount())
154    {
155    }
156
157    ArgList(const MarkedArgumentBuffer& args)
158        : m_args(reinterpret_cast<JSValue*>(args.m_buffer))
159        , m_argCount(args.size())
160    {
161    }
162
163    JSValue at(int i) const
164    {
165        if (i >= m_argCount)
166            return jsUndefined();
167        return m_args[i];
168    }
169
170    bool isEmpty() const { return !m_argCount; }
171    size_t size() const { return m_argCount; }
172
173    JS_EXPORT_PRIVATE void getSlice(int startIndex, ArgList& result) const;
174
175private:
176    JSValue* data() const { return m_args; }
177
178    JSValue* m_args;
179    int m_argCount;
180};
181
182} // namespace JSC
183
184#endif // ArgList_h
185