1a9bf2f52276916eff2e7e15a522e555699736d7
[WebKit-https.git] / Source / JavaScriptCore / runtime / ArgList.h
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 #pragma once
23
24 #include "CallFrame.h"
25 #include <wtf/HashSet.h>
26
27 namespace JSC {
28
29 class MarkedArgumentBuffer {
30     WTF_MAKE_NONCOPYABLE(MarkedArgumentBuffer);
31     friend class VM;
32     friend class ArgList;
33
34 private:
35     static const size_t inlineCapacity = 8;
36     typedef HashSet<MarkedArgumentBuffer*> ListSet;
37
38 public:
39     // Constructor for a read-write list, to which you may append values.
40     // FIXME: Remove all clients of this API, then remove this API.
41     MarkedArgumentBuffer()
42         : m_size(0)
43         , m_capacity(inlineCapacity)
44         , m_buffer(m_inlineBuffer)
45         , m_markSet(0)
46     {
47     }
48
49     ~MarkedArgumentBuffer()
50     {
51         if (m_markSet)
52             m_markSet->remove(this);
53
54         if (EncodedJSValue* base = mallocBase())
55             fastFree(base);
56     }
57
58     size_t size() const { return m_size; }
59     bool isEmpty() const { return !m_size; }
60
61     JSValue at(int i) const
62     {
63         if (i >= m_size)
64             return jsUndefined();
65
66         return JSValue::decode(slotFor(i));
67     }
68
69     void clear()
70     {
71         m_size = 0;
72     }
73
74     void append(JSValue v)
75     {
76         if (m_size >= m_capacity || mallocBase())
77             return slowAppend(v);
78
79         slotFor(m_size) = JSValue::encode(v);
80         ++m_size;
81     }
82
83     void removeLast()
84     { 
85         ASSERT(m_size);
86         m_size--;
87     }
88
89     JSValue last() 
90     {
91         ASSERT(m_size);
92         return JSValue::decode(slotFor(m_size - 1));
93     }
94         
95     static void markLists(HeapRootVisitor&, ListSet&);
96
97 private:
98     void expandCapacity();
99
100     void addMarkSet(JSValue);
101
102     JS_EXPORT_PRIVATE void slowAppend(JSValue);
103         
104     EncodedJSValue& slotFor(int item) const
105     {
106         return m_buffer[item];
107     }
108         
109     EncodedJSValue* mallocBase()
110     {
111         if (m_buffer == m_inlineBuffer)
112             return 0;
113         return &slotFor(0);
114     }
115         
116     int m_size;
117     int m_capacity;
118     EncodedJSValue m_inlineBuffer[inlineCapacity];
119     EncodedJSValue* m_buffer;
120     ListSet* m_markSet;
121 };
122
123 class ArgList {
124     friend class Interpreter;
125     friend class JIT;
126 public:
127     ArgList()
128         : m_args(0)
129         , m_argCount(0)
130     {
131     }
132
133     ArgList(ExecState* exec)
134         : m_args(reinterpret_cast<JSValue*>(&exec[CallFrame::argumentOffset(0)]))
135         , m_argCount(exec->argumentCount())
136     {
137     }
138
139     ArgList(const MarkedArgumentBuffer& args)
140         : m_args(reinterpret_cast<JSValue*>(args.m_buffer))
141         , m_argCount(args.size())
142     {
143     }
144
145     JSValue at(int i) const
146     {
147         if (i >= m_argCount)
148             return jsUndefined();
149         return m_args[i];
150     }
151
152     bool isEmpty() const { return !m_argCount; }
153     size_t size() const { return m_argCount; }
154         
155     JS_EXPORT_PRIVATE void getSlice(int startIndex, ArgList& result) const;
156
157 private:
158     JSValue* data() const { return m_args; }
159
160     JSValue* m_args;
161     int m_argCount;
162 };
163
164 } // namespace JSC