Move CallFrame and Register inlines functions out of JSScope.h.
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSScope.h
1 /*
2  * Copyright (C) 2012, 2013, 2014 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef JSScope_h
27 #define JSScope_h
28
29 #include "JSObject.h"
30
31 namespace JSC {
32
33 class ScopeChainIterator;
34 class VariableWatchpointSet;
35
36 enum ResolveMode {
37     ThrowIfNotFound,
38     DoNotThrowIfNotFound
39 };
40
41 enum ResolveType {
42     // Lexical scope guaranteed a certain type of variable access.
43     GlobalProperty,
44     GlobalVar,
45     ClosureVar,
46
47     // Ditto, but at least one intervening scope used non-strict eval, which
48     // can inject an intercepting var delcaration at runtime.
49     GlobalPropertyWithVarInjectionChecks,
50     GlobalVarWithVarInjectionChecks,
51     ClosureVarWithVarInjectionChecks,
52
53     // Lexical scope didn't prove anything -- probably because of a 'with' scope.
54     Dynamic
55 };
56
57 const char* resolveModeName(ResolveMode mode);
58 const char* resolveTypeName(ResolveType type);
59
60 inline ResolveType makeType(ResolveType type, bool needsVarInjectionChecks)
61 {
62     if (!needsVarInjectionChecks)
63         return type;
64
65     switch (type) {
66     case GlobalProperty:
67         return GlobalPropertyWithVarInjectionChecks;
68     case GlobalVar:
69         return GlobalVarWithVarInjectionChecks;
70     case ClosureVar:
71         return ClosureVarWithVarInjectionChecks;
72     case GlobalPropertyWithVarInjectionChecks:
73     case GlobalVarWithVarInjectionChecks:
74     case ClosureVarWithVarInjectionChecks:
75     case Dynamic:
76         return type;
77     }
78
79     RELEASE_ASSERT_NOT_REACHED();
80     return type;
81 }
82
83 inline bool needsVarInjectionChecks(ResolveType type)
84 {
85     switch (type) {
86     case GlobalProperty:
87     case GlobalVar:
88     case ClosureVar:
89         return false;
90     case GlobalPropertyWithVarInjectionChecks:
91     case GlobalVarWithVarInjectionChecks:
92     case ClosureVarWithVarInjectionChecks:
93     case Dynamic:
94         return true;
95     default:
96         RELEASE_ASSERT_NOT_REACHED();
97         return true;
98     }
99 }
100
101 struct ResolveOp {
102     ResolveOp(ResolveType type, size_t depth, Structure* structure, JSActivation* activation, VariableWatchpointSet* watchpointSet, uintptr_t operand)
103         : type(type)
104         , depth(depth)
105         , structure(structure)
106         , activation(activation)
107         , watchpointSet(watchpointSet)
108         , operand(operand)
109     {
110     }
111
112     ResolveType type;
113     size_t depth;
114     Structure* structure;
115     JSActivation* activation;
116     VariableWatchpointSet* watchpointSet;
117     uintptr_t operand;
118 };
119
120 class ResolveModeAndType {
121     typedef unsigned Operand;
122 public:
123     static const size_t shift = sizeof(Operand) * 8 / 2;
124     static const unsigned mask = (1 << shift) - 1;
125
126     ResolveModeAndType(ResolveMode resolveMode, ResolveType resolveType)
127         : m_operand((resolveMode << shift) | resolveType)
128     {
129     }
130
131     explicit ResolveModeAndType(unsigned operand)
132         : m_operand(operand)
133     {
134     }
135
136     ResolveMode mode() { return static_cast<ResolveMode>(m_operand >> shift); }
137     ResolveType type() { return static_cast<ResolveType>(m_operand & mask); }
138     unsigned operand() { return m_operand; }
139
140 private:
141     Operand m_operand;
142 };
143
144 enum GetOrPut { Get, Put };
145
146 class JSScope : public JSNonFinalObject {
147 public:
148     typedef JSNonFinalObject Base;
149
150     friend class LLIntOffsetsExtractor;
151     static size_t offsetOfNext();
152
153     static JSObject* objectAtScope(JSScope*);
154
155     static JSValue resolve(ExecState*, JSScope*, const Identifier&);
156     static ResolveOp abstractResolve(ExecState*, bool hasTopActivation, JSScope*, const Identifier&, GetOrPut, ResolveType);
157
158     static void visitChildren(JSCell*, SlotVisitor&);
159
160     ScopeChainIterator begin();
161     ScopeChainIterator end();
162     JSScope* next();
163     int depth();
164
165     JSGlobalObject* globalObject();
166     VM* vm();
167     JSObject* globalThis();
168
169 protected:
170     JSScope(VM&, Structure*, JSScope* next);
171
172 private:
173     WriteBarrier<JSScope> m_next;
174 };
175
176 inline JSScope::JSScope(VM& vm, Structure* structure, JSScope* next)
177     : Base(vm, structure)
178     , m_next(vm, this, next, WriteBarrier<JSScope>::MayBeNull)
179 {
180 }
181
182 class ScopeChainIterator {
183 public:
184     ScopeChainIterator(JSScope* node)
185         : m_node(node)
186     {
187     }
188
189     JSObject* get() const { return JSScope::objectAtScope(m_node); }
190     JSObject* operator->() const { return JSScope::objectAtScope(m_node); }
191
192     ScopeChainIterator& operator++() { m_node = m_node->next(); return *this; }
193
194     // postfix ++ intentionally omitted
195
196     bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; }
197     bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
198
199 private:
200     JSScope* m_node;
201 };
202
203 inline ScopeChainIterator JSScope::begin()
204 {
205     return ScopeChainIterator(this); 
206 }
207
208 inline ScopeChainIterator JSScope::end()
209
210     return ScopeChainIterator(0); 
211 }
212
213 inline JSScope* JSScope::next()
214
215     return m_next.get();
216 }
217
218 inline JSGlobalObject* JSScope::globalObject()
219
220     return structure()->globalObject();
221 }
222
223 inline VM* JSScope::vm()
224
225     return MarkedBlock::blockFor(this)->vm();
226 }
227
228 inline size_t JSScope::offsetOfNext()
229 {
230     return OBJECT_OFFSETOF(JSScope, m_next);
231 }
232
233 } // namespace JSC
234
235 #endif // JSScope_h