1/*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2007, 2008, 2009, 2016 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 fastFree(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 || mallocBase())
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 void expandCapacity();
104
105 void addMarkSet(JSValue);
106
107 JS_EXPORT_PRIVATE void slowAppend(JSValue);
108
109 EncodedJSValue& slotFor(int item) const
110 {
111 return m_buffer[item];
112 }
113
114 EncodedJSValue* mallocBase()
115 {
116 if (m_buffer == m_inlineBuffer)
117 return 0;
118 return &slotFor(0);
119 }
120
121 int m_size;
122 int m_capacity;
123 EncodedJSValue m_inlineBuffer[inlineCapacity];
124 EncodedJSValue* m_buffer;
125 ListSet* m_markSet;
126};
127
128class ArgList {
129 friend class Interpreter;
130 friend class JIT;
131public:
132 ArgList()
133 : m_args(0)
134 , m_argCount(0)
135 {
136 }
137
138 ArgList(ExecState* exec)
139 : m_args(reinterpret_cast<JSValue*>(&exec[CallFrame::argumentOffset(0)]))
140 , m_argCount(exec->argumentCount())
141 {
142 }
143
144 ArgList(const MarkedArgumentBuffer& args)
145 : m_args(reinterpret_cast<JSValue*>(args.m_buffer))
146 , m_argCount(args.size())
147 {
148 }
149
150 JSValue at(int i) const
151 {
152 if (i >= m_argCount)
153 return jsUndefined();
154 return m_args[i];
155 }
156
157 bool isEmpty() const { return !m_argCount; }
158 size_t size() const { return m_argCount; }
159
160 JS_EXPORT_PRIVATE void getSlice(int startIndex, ArgList& result) const;
161
162private:
163 JSValue* data() const { return m_args; }
164
165 JSValue* m_args;
166 int m_argCount;
167};
168
169} // namespace JSC
170
171#endif // ArgList_h
172