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