]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSScope.h
JavaScriptCore-7600.1.4.16.1.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 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 JS_EXPORT_PRIVATE static JSObject* objectAtScope(JSScope*);
154
155 static JSValue resolve(ExecState*, JSScope*, const Identifier&);
156 static ResolveOp abstractResolve(ExecState*, 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 static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
172
173 private:
174 WriteBarrier<JSScope> m_next;
175 };
176
177 inline JSScope::JSScope(VM& vm, Structure* structure, JSScope* next)
178 : Base(vm, structure)
179 , m_next(vm, this, next, WriteBarrier<JSScope>::MayBeNull)
180 {
181 }
182
183 class ScopeChainIterator {
184 public:
185 ScopeChainIterator(JSScope* node)
186 : m_node(node)
187 {
188 }
189
190 JSObject* get() const { return JSScope::objectAtScope(m_node); }
191 JSObject* operator->() const { return JSScope::objectAtScope(m_node); }
192
193 ScopeChainIterator& operator++() { m_node = m_node->next(); return *this; }
194
195 // postfix ++ intentionally omitted
196
197 bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; }
198 bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
199
200 private:
201 JSScope* m_node;
202 };
203
204 inline ScopeChainIterator JSScope::begin()
205 {
206 return ScopeChainIterator(this);
207 }
208
209 inline ScopeChainIterator JSScope::end()
210 {
211 return ScopeChainIterator(0);
212 }
213
214 inline JSScope* JSScope::next()
215 {
216 return m_next.get();
217 }
218
219 inline JSGlobalObject* JSScope::globalObject()
220 {
221 return structure()->globalObject();
222 }
223
224 inline VM* JSScope::vm()
225 {
226 return MarkedBlock::blockFor(this)->vm();
227 }
228
229 inline Register& Register::operator=(JSScope* scope)
230 {
231 *this = JSValue(scope);
232 return *this;
233 }
234
235 inline JSScope* Register::scope() const
236 {
237 return jsCast<JSScope*>(jsValue());
238 }
239
240 inline VM& ExecState::vm() const
241 {
242 ASSERT(scope()->vm());
243 return *scope()->vm();
244 }
245
246 inline JSGlobalObject* ExecState::lexicalGlobalObject() const
247 {
248 return scope()->globalObject();
249 }
250
251 inline JSObject* ExecState::globalThisValue() const
252 {
253 return scope()->globalThis();
254 }
255
256 inline size_t JSScope::offsetOfNext()
257 {
258 return OBJECT_OFFSETOF(JSScope, m_next);
259 }
260
261 } // namespace JSC
262
263 #endif // JSScope_h