2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
33 class ScopeChainIterator
;
34 class VariableWatchpointSet
;
42 // Lexical scope guaranteed a certain type of variable access.
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
,
53 // Lexical scope didn't prove anything -- probably because of a 'with' scope.
57 const char* resolveModeName(ResolveMode mode
);
58 const char* resolveTypeName(ResolveType type
);
60 inline ResolveType
makeType(ResolveType type
, bool needsVarInjectionChecks
)
62 if (!needsVarInjectionChecks
)
67 return GlobalPropertyWithVarInjectionChecks
;
69 return GlobalVarWithVarInjectionChecks
;
71 return ClosureVarWithVarInjectionChecks
;
72 case GlobalPropertyWithVarInjectionChecks
:
73 case GlobalVarWithVarInjectionChecks
:
74 case ClosureVarWithVarInjectionChecks
:
79 RELEASE_ASSERT_NOT_REACHED();
83 inline bool needsVarInjectionChecks(ResolveType type
)
90 case GlobalPropertyWithVarInjectionChecks
:
91 case GlobalVarWithVarInjectionChecks
:
92 case ClosureVarWithVarInjectionChecks
:
96 RELEASE_ASSERT_NOT_REACHED();
102 ResolveOp(ResolveType type
, size_t depth
, Structure
* structure
, JSActivation
* activation
, VariableWatchpointSet
* watchpointSet
, uintptr_t operand
)
105 , structure(structure
)
106 , activation(activation
)
107 , watchpointSet(watchpointSet
)
114 Structure
* structure
;
115 JSActivation
* activation
;
116 VariableWatchpointSet
* watchpointSet
;
120 class ResolveModeAndType
{
121 typedef unsigned Operand
;
123 static const size_t shift
= sizeof(Operand
) * 8 / 2;
124 static const unsigned mask
= (1 << shift
) - 1;
126 ResolveModeAndType(ResolveMode resolveMode
, ResolveType resolveType
)
127 : m_operand((resolveMode
<< shift
) | resolveType
)
131 explicit ResolveModeAndType(unsigned operand
)
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
; }
144 enum GetOrPut
{ Get
, Put
};
146 class JSScope
: public JSNonFinalObject
{
148 typedef JSNonFinalObject Base
;
150 friend class LLIntOffsetsExtractor
;
151 static size_t offsetOfNext();
153 JS_EXPORT_PRIVATE
static JSObject
* objectAtScope(JSScope
*);
155 static JSValue
resolve(ExecState
*, JSScope
*, const Identifier
&);
156 static ResolveOp
abstractResolve(ExecState
*, JSScope
*, const Identifier
&, GetOrPut
, ResolveType
);
158 static void visitChildren(JSCell
*, SlotVisitor
&);
160 ScopeChainIterator
begin();
161 ScopeChainIterator
end();
165 JSGlobalObject
* globalObject();
167 JSObject
* globalThis();
170 JSScope(VM
&, Structure
*, JSScope
* next
);
171 static const unsigned StructureFlags
= OverridesVisitChildren
| Base::StructureFlags
;
174 WriteBarrier
<JSScope
> m_next
;
177 inline JSScope::JSScope(VM
& vm
, Structure
* structure
, JSScope
* next
)
178 : Base(vm
, structure
)
179 , m_next(vm
, this, next
, WriteBarrier
<JSScope
>::MayBeNull
)
183 class ScopeChainIterator
{
185 ScopeChainIterator(JSScope
* node
)
190 JSObject
* get() const { return JSScope::objectAtScope(m_node
); }
191 JSObject
* operator->() const { return JSScope::objectAtScope(m_node
); }
193 ScopeChainIterator
& operator++() { m_node
= m_node
->next(); return *this; }
195 // postfix ++ intentionally omitted
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
; }
204 inline ScopeChainIterator
JSScope::begin()
206 return ScopeChainIterator(this);
209 inline ScopeChainIterator
JSScope::end()
211 return ScopeChainIterator(0);
214 inline JSScope
* JSScope::next()
219 inline JSGlobalObject
* JSScope::globalObject()
221 return structure()->globalObject();
224 inline VM
* JSScope::vm()
226 return MarkedBlock::blockFor(this)->vm();
229 inline Register
& Register::operator=(JSScope
* scope
)
231 *this = JSValue(scope
);
235 inline JSScope
* Register::scope() const
237 return jsCast
<JSScope
*>(jsValue());
240 inline VM
& ExecState::vm() const
242 ASSERT(scope()->vm());
243 return *scope()->vm();
246 inline JSGlobalObject
* ExecState::lexicalGlobalObject() const
248 return scope()->globalObject();
251 inline JSObject
* ExecState::globalThisValue() const
253 return scope()->globalThis();
256 inline size_t JSScope::offsetOfNext()
258 return OBJECT_OFFSETOF(JSScope
, m_next
);