]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/JSScope.h
JavaScriptCore-7600.1.4.11.8.tar.gz
[apple/javascriptcore.git] / runtime / JSScope.h
CommitLineData
93a37866 1/*
81345200 2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All Rights Reserved.
93a37866
A
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"
93a37866
A
30
31namespace JSC {
32
33class ScopeChainIterator;
81345200
A
34class VariableWatchpointSet;
35
36enum ResolveMode {
37 ThrowIfNotFound,
38 DoNotThrowIfNotFound
39};
40
41enum 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
57const char* resolveModeName(ResolveMode mode);
58const char* resolveTypeName(ResolveType type);
59
60inline 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
83inline 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
101struct 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
120class ResolveModeAndType {
121 typedef unsigned Operand;
122public:
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
140private:
141 Operand m_operand;
142};
143
144enum GetOrPut { Get, Put };
93a37866
A
145
146class JSScope : public JSNonFinalObject {
147public:
148 typedef JSNonFinalObject Base;
149
150 friend class LLIntOffsetsExtractor;
151 static size_t offsetOfNext();
152
153 JS_EXPORT_PRIVATE static JSObject* objectAtScope(JSScope*);
154
81345200
A
155 static JSValue resolve(ExecState*, JSScope*, const Identifier&);
156 static ResolveOp abstractResolve(ExecState*, JSScope*, const Identifier&, GetOrPut, ResolveType);
93a37866
A
157
158 static void visitChildren(JSCell*, SlotVisitor&);
159
93a37866
A
160 ScopeChainIterator begin();
161 ScopeChainIterator end();
162 JSScope* next();
81345200 163 int depth();
93a37866
A
164
165 JSGlobalObject* globalObject();
166 VM* vm();
167 JSObject* globalThis();
168
169protected:
170 JSScope(VM&, Structure*, JSScope* next);
171 static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
172
173private:
174 WriteBarrier<JSScope> m_next;
93a37866
A
175};
176
177inline JSScope::JSScope(VM& vm, Structure* structure, JSScope* next)
178 : Base(vm, structure)
179 , m_next(vm, this, next, WriteBarrier<JSScope>::MayBeNull)
180{
181}
182
183class ScopeChainIterator {
184public:
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
200private:
201 JSScope* m_node;
202};
203
204inline ScopeChainIterator JSScope::begin()
205{
206 return ScopeChainIterator(this);
207}
208
209inline ScopeChainIterator JSScope::end()
210{
211 return ScopeChainIterator(0);
212}
213
214inline JSScope* JSScope::next()
215{
216 return m_next.get();
217}
218
219inline JSGlobalObject* JSScope::globalObject()
220{
221 return structure()->globalObject();
222}
223
224inline VM* JSScope::vm()
225{
81345200 226 return MarkedBlock::blockFor(this)->vm();
93a37866
A
227}
228
229inline Register& Register::operator=(JSScope* scope)
230{
231 *this = JSValue(scope);
232 return *this;
233}
234
235inline JSScope* Register::scope() const
236{
237 return jsCast<JSScope*>(jsValue());
238}
239
240inline VM& ExecState::vm() const
241{
242 ASSERT(scope()->vm());
243 return *scope()->vm();
244}
245
246inline JSGlobalObject* ExecState::lexicalGlobalObject() const
247{
248 return scope()->globalObject();
249}
250
251inline JSObject* ExecState::globalThisValue() const
252{
253 return scope()->globalThis();
254}
255
256inline size_t JSScope::offsetOfNext()
257{
258 return OBJECT_OFFSETOF(JSScope, m_next);
259}
260
261} // namespace JSC
262
263#endif // JSScope_h