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
;
42 // Lexical scope guaranteed a certain type of variable access.
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
,
54 // Lexical scope didn't prove anything -- probably because of a 'with' scope.
58 const char* resolveModeName(ResolveMode mode
);
59 const char* resolveTypeName(ResolveType type
);
61 inline ResolveType
makeType(ResolveType type
, bool needsVarInjectionChecks
)
63 if (!needsVarInjectionChecks
)
68 return GlobalPropertyWithVarInjectionChecks
;
70 return GlobalVarWithVarInjectionChecks
;
73 return ClosureVarWithVarInjectionChecks
;
74 case GlobalPropertyWithVarInjectionChecks
:
75 case GlobalVarWithVarInjectionChecks
:
76 case ClosureVarWithVarInjectionChecks
:
81 RELEASE_ASSERT_NOT_REACHED();
85 inline bool needsVarInjectionChecks(ResolveType type
)
93 case GlobalPropertyWithVarInjectionChecks
:
94 case GlobalVarWithVarInjectionChecks
:
95 case ClosureVarWithVarInjectionChecks
:
99 RELEASE_ASSERT_NOT_REACHED();
105 ResolveOp(ResolveType type
, size_t depth
, Structure
* structure
, JSLexicalEnvironment
* lexicalEnvironment
, WatchpointSet
* watchpointSet
, uintptr_t operand
)
108 , structure(structure
)
109 , lexicalEnvironment(lexicalEnvironment
)
110 , watchpointSet(watchpointSet
)
117 Structure
* structure
;
118 JSLexicalEnvironment
* lexicalEnvironment
;
119 WatchpointSet
* watchpointSet
;
123 class ResolveModeAndType
{
124 typedef unsigned Operand
;
126 static const size_t shift
= sizeof(Operand
) * 8 / 2;
127 static const unsigned mask
= (1 << shift
) - 1;
129 ResolveModeAndType(ResolveMode resolveMode
, ResolveType resolveType
)
130 : m_operand((resolveMode
<< shift
) | resolveType
)
134 explicit ResolveModeAndType(unsigned operand
)
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
; }
147 enum GetOrPut
{ Get
, Put
};
149 class JSScope
: public JSNonFinalObject
{
151 typedef JSNonFinalObject Base
;
152 static const unsigned StructureFlags
= Base::StructureFlags
;
154 friend class LLIntOffsetsExtractor
;
155 static size_t offsetOfNext();
157 static JSObject
* objectAtScope(JSScope
*);
159 static JSValue
resolve(ExecState
*, JSScope
*, const Identifier
&);
160 static ResolveOp
abstractResolve(ExecState
*, bool hasTopActivation
, JSScope
*, const Identifier
&, GetOrPut
, ResolveType
);
162 static void visitChildren(JSCell
*, SlotVisitor
&);
164 ScopeChainIterator
begin();
165 ScopeChainIterator
end();
169 JSGlobalObject
* globalObject();
171 JSObject
* globalThis();
174 JSScope(VM
&, Structure
*, JSScope
* next
);
177 WriteBarrier
<JSScope
> m_next
;
180 inline JSScope::JSScope(VM
& vm
, Structure
* structure
, JSScope
* next
)
181 : Base(vm
, structure
)
182 , m_next(vm
, this, next
, WriteBarrier
<JSScope
>::MayBeNull
)
186 class ScopeChainIterator
{
188 ScopeChainIterator(JSScope
* node
)
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
; }
197 ScopeChainIterator
& operator++() { m_node
= m_node
->next(); return *this; }
199 // postfix ++ intentionally omitted
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
; }
208 inline ScopeChainIterator
JSScope::begin()
210 return ScopeChainIterator(this);
213 inline ScopeChainIterator
JSScope::end()
215 return ScopeChainIterator(0);
218 inline JSScope
* JSScope::next()
223 inline JSGlobalObject
* JSScope::globalObject()
225 return structure()->globalObject();
228 inline VM
* JSScope::vm()
230 return MarkedBlock::blockFor(this)->vm();
233 inline Register
& Register::operator=(JSScope
* scope
)
235 *this = JSValue(scope
);
239 inline JSScope
* Register::scope() const
241 return jsCast
<JSScope
*>(jsValue());
244 inline JSGlobalObject
* ExecState::lexicalGlobalObject() const
246 return callee()->globalObject();
249 inline size_t JSScope::offsetOfNext()
251 return OBJECT_OFFSETOF(JSScope
, m_next
);