Unreviewed buildfix after FTL upstream.
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSScope.h
1 /*
2  * Copyright (C) 2012, 2013 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
35 enum ResolveMode {
36     ThrowIfNotFound,
37     DoNotThrowIfNotFound
38 };
39
40 enum ResolveType {
41     // Lexical scope guaranteed a certain type of variable access.
42     GlobalProperty,
43     GlobalVar,
44     ClosureVar,
45
46     // Ditto, but at least one intervening scope used non-strict eval, which
47     // can inject an intercepting var delcaration at runtime.
48     GlobalPropertyWithVarInjectionChecks,
49     GlobalVarWithVarInjectionChecks,
50     ClosureVarWithVarInjectionChecks,
51
52     // Lexical scope didn't prove anything -- probably because of a 'with' scope.
53     Dynamic
54 };
55
56 inline ResolveType makeType(ResolveType type, bool needsVarInjectionChecks)
57 {
58     if (!needsVarInjectionChecks)
59         return type;
60
61     switch (type) {
62     case GlobalProperty:
63         return GlobalPropertyWithVarInjectionChecks;
64     case GlobalVar:
65         return GlobalVarWithVarInjectionChecks;
66     case ClosureVar:
67         return ClosureVarWithVarInjectionChecks;
68     case GlobalPropertyWithVarInjectionChecks:
69     case GlobalVarWithVarInjectionChecks:
70     case ClosureVarWithVarInjectionChecks:
71     case Dynamic:
72         return type;
73     }
74 }
75
76 inline bool needsVarInjectionChecks(ResolveType type)
77 {
78     switch (type) {
79     case GlobalProperty:
80     case GlobalVar:
81     case ClosureVar:
82         return false;
83     case GlobalPropertyWithVarInjectionChecks:
84     case GlobalVarWithVarInjectionChecks:
85     case ClosureVarWithVarInjectionChecks:
86     case Dynamic:
87         return true;
88     default:
89         RELEASE_ASSERT_NOT_REACHED();
90         return true;
91     }
92 }
93
94 struct ResolveOp {
95     ResolveOp(ResolveType type, size_t depth, Structure* structure, uintptr_t operand)
96         : type(type)
97         , depth(depth)
98         , structure(structure)
99         , operand(operand)
100     {
101     }
102
103     ResolveType type;
104     size_t depth;
105     Structure* structure;
106     uintptr_t operand;
107 };
108
109 class ResolveModeAndType {
110     typedef unsigned Operand;
111 public:
112     static const size_t shift = sizeof(Operand) * 8 / 2;
113     static const unsigned mask = (1 << shift) - 1;
114
115     ResolveModeAndType(ResolveMode resolveMode, ResolveType resolveType)
116         : m_operand((resolveMode << shift) | resolveType)
117     {
118     }
119
120     explicit ResolveModeAndType(unsigned operand)
121         : m_operand(operand)
122     {
123     }
124
125     ResolveMode mode() { return static_cast<ResolveMode>(m_operand >> shift); }
126     ResolveType type() { return static_cast<ResolveType>(m_operand & mask); }
127     unsigned operand() { return m_operand; }
128
129 private:
130     Operand m_operand;
131 };
132
133 enum GetOrPut { Get, Put };
134
135 class JSScope : public JSNonFinalObject {
136 public:
137     typedef JSNonFinalObject Base;
138
139     friend class LLIntOffsetsExtractor;
140     static size_t offsetOfNext();
141
142     JS_EXPORT_PRIVATE static JSObject* objectAtScope(JSScope*);
143
144     static JSValue resolve(ExecState*, JSScope*, const Identifier&);
145     static ResolveOp abstractResolve(ExecState*, JSScope*, const Identifier&, GetOrPut, ResolveType);
146
147     static void visitChildren(JSCell*, SlotVisitor&);
148
149     ScopeChainIterator begin();
150     ScopeChainIterator end();
151     JSScope* next();
152     int depth();
153
154     JSGlobalObject* globalObject();
155     VM* vm();
156     JSObject* globalThis();
157
158 protected:
159     JSScope(VM&, Structure*, JSScope* next);
160     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
161
162 private:
163     WriteBarrier<JSScope> m_next;
164 };
165
166 inline JSScope::JSScope(VM& vm, Structure* structure, JSScope* next)
167     : Base(vm, structure)
168     , m_next(vm, this, next, WriteBarrier<JSScope>::MayBeNull)
169 {
170 }
171
172 class ScopeChainIterator {
173 public:
174     ScopeChainIterator(JSScope* node)
175         : m_node(node)
176     {
177     }
178
179     JSObject* get() const { return JSScope::objectAtScope(m_node); }
180     JSObject* operator->() const { return JSScope::objectAtScope(m_node); }
181
182     ScopeChainIterator& operator++() { m_node = m_node->next(); return *this; }
183
184     // postfix ++ intentionally omitted
185
186     bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; }
187     bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
188
189 private:
190     JSScope* m_node;
191 };
192
193 inline ScopeChainIterator JSScope::begin()
194 {
195     return ScopeChainIterator(this); 
196 }
197
198 inline ScopeChainIterator JSScope::end()
199
200     return ScopeChainIterator(0); 
201 }
202
203 inline JSScope* JSScope::next()
204
205     return m_next.get();
206 }
207
208 inline JSGlobalObject* JSScope::globalObject()
209
210     return structure()->globalObject();
211 }
212
213 inline VM* JSScope::vm()
214
215     return Heap::heap(this)->vm();
216 }
217
218 inline Register& Register::operator=(JSScope* scope)
219 {
220     *this = JSValue(scope);
221     return *this;
222 }
223
224 inline JSScope* Register::scope() const
225 {
226     return jsCast<JSScope*>(jsValue());
227 }
228
229 inline VM& ExecState::vm() const
230 {
231     ASSERT(scope()->vm());
232     return *scope()->vm();
233 }
234
235 inline JSGlobalObject* ExecState::lexicalGlobalObject() const
236 {
237     return scope()->globalObject();
238 }
239
240 inline JSObject* ExecState::globalThisValue() const
241 {
242     return scope()->globalThis();
243 }
244
245 inline size_t JSScope::offsetOfNext()
246 {
247     return OBJECT_OFFSETOF(JSScope, m_next);
248 }
249
250 } // namespace JSC
251
252 #endif // JSScope_h