JavaScriptCore:
[WebKit-https.git] / JavaScriptCore / VM / Register.h
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #ifndef Register_h
30 #define Register_h
31
32 #include "JSValue.h"
33 #include <wtf/VectorTraits.h>
34
35 namespace KJS {
36
37     class CodeBlock;
38     class ExecState;
39     class JSFunction;
40     class JSPropertyNameIterator;
41     class JSValue;
42     class ScopeChainNode;
43     struct Instruction;
44     
45     static JSValue* const nullJSValue = 0;
46
47     class Register {
48     public:
49         Register();
50         Register(JSValue*);
51
52         JSValue* jsValue(ExecState*) const;
53         JSValue* getJSValue() const;
54
55         bool marked() const;
56         void mark();
57         
58     private:
59         friend class Machine;
60
61         // Only the Machine should use these functions.
62
63         Register(CodeBlock*);
64         Register(ScopeChainNode*);
65         Register(intptr_t);
66         Register(Register*);
67         Register(Instruction*);
68         Register(JSPropertyNameIterator*);
69
70         CodeBlock* codeBlock() const;
71         ScopeChainNode* scopeChain() const;
72         intptr_t i() const;
73         Register* r() const;
74         Instruction* vPC() const;
75         JSPropertyNameIterator* jsPropertyNameIterator() const;
76         void* v() const;
77
78         union {
79         private:
80             friend class Register;
81
82             CodeBlock* codeBlock;
83             Instruction* vPC;
84             JSValue* jsValue;
85             ScopeChainNode* scopeChain;
86             JSPropertyNameIterator* jsPropertyNameIterator;
87             Register* r;
88             void* v;
89             intptr_t i;
90         } u;
91
92 #ifndef NDEBUG
93         enum {
94             CodeBlockType = 0, 
95             InstructionType, 
96             JSValueType, 
97             ScopeChainNodeType, 
98             JSPropertyNameIteratorType, 
99             RegisterType, 
100             IntType
101         } m_type;
102 #endif
103     };
104
105     ALWAYS_INLINE Register::Register()
106     {
107 #ifndef NDEBUG
108         *this = nullJSValue;
109 #endif
110     }
111
112     ALWAYS_INLINE Register::Register(JSValue* v)
113     {
114 #ifndef NDEBUG
115         m_type = JSValueType;
116 #endif
117         u.jsValue = v;
118     }
119     
120     // This function is scaffolding for legacy clients. It will eventually go away.
121     ALWAYS_INLINE JSValue* Register::jsValue(ExecState*) const
122     {
123         // Once registers hold doubles, this function will allocate a JSValue*
124         // if the register doesn't hold one already. 
125         ASSERT(m_type == JSValueType);
126         return u.jsValue;
127     }
128     
129     ALWAYS_INLINE JSValue* Register::getJSValue() const
130     {
131         ASSERT(m_type == JSValueType);
132         return u.jsValue;
133     }
134     
135     ALWAYS_INLINE bool Register::marked() const
136     {
137         return getJSValue()->marked();
138     }
139
140     ALWAYS_INLINE void Register::mark()
141     {
142         getJSValue()->mark();
143     }
144     
145     // Machine functions
146
147     ALWAYS_INLINE Register::Register(CodeBlock* codeBlock)
148     {
149 #ifndef NDEBUG
150         m_type = CodeBlockType;
151 #endif
152         u.codeBlock = codeBlock;
153     }
154
155     ALWAYS_INLINE Register::Register(Instruction* vPC)
156     {
157 #ifndef NDEBUG
158         m_type = InstructionType;
159 #endif
160         u.vPC = vPC;
161     }
162
163     ALWAYS_INLINE Register::Register(ScopeChainNode* scopeChain)
164     {
165 #ifndef NDEBUG
166         m_type = ScopeChainNodeType;
167 #endif
168         u.scopeChain = scopeChain;
169     }
170
171     ALWAYS_INLINE Register::Register(JSPropertyNameIterator* jsPropertyNameIterator)
172     {
173 #ifndef NDEBUG
174         m_type = JSPropertyNameIteratorType;
175 #endif
176         u.jsPropertyNameIterator = jsPropertyNameIterator;
177     }
178
179     ALWAYS_INLINE Register::Register(Register* r)
180     {
181 #ifndef NDEBUG
182         m_type = RegisterType;
183 #endif
184         u.r = r;
185     }
186
187     ALWAYS_INLINE Register::Register(intptr_t i)
188     {
189 #ifndef NDEBUG
190         m_type = IntType;
191 #endif
192         u.i = i;
193     }
194
195     ALWAYS_INLINE CodeBlock* Register::codeBlock() const
196     {
197         ASSERT(m_type == CodeBlockType);
198         return u.codeBlock;
199     }
200     
201     ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const
202     {
203         ASSERT(m_type == ScopeChainNodeType);
204         return u.scopeChain;
205     }
206     
207     ALWAYS_INLINE intptr_t Register::i() const
208     {
209         ASSERT(m_type == IntType);
210         return u.i;
211     }
212     
213     ALWAYS_INLINE Register* Register::r() const
214     {
215         ASSERT(m_type == RegisterType);
216         return u.r;
217     }
218     
219     ALWAYS_INLINE Instruction* Register::vPC() const
220     {
221         ASSERT(m_type == InstructionType);
222         return u.vPC;
223     }
224     
225     ALWAYS_INLINE JSPropertyNameIterator* Register::jsPropertyNameIterator() const
226     {
227         ASSERT(m_type == JSPropertyNameIteratorType);
228         return u.jsPropertyNameIterator;
229     }
230     
231     ALWAYS_INLINE void* Register::v() const
232     {
233         return u.v;
234     }
235
236 } // namespace KJS
237
238 namespace WTF {
239
240     template<> struct VectorTraits<KJS::Register> : VectorTraitsBase<true, KJS::Register> { };
241
242 } // namespace WTF
243
244 #endif // Register_h