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.
29 #include "JSActivation.h"
30 #include "JSGlobalObject.h"
31 #include "JSNameScope.h"
32 #include "JSWithScope.h"
33 #include "JSCInlines.h"
37 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSScope
);
39 void JSScope::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
41 JSScope
* thisObject
= jsCast
<JSScope
*>(cell
);
42 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
43 COMPILE_ASSERT(StructureFlags
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
);
44 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
46 Base::visitChildren(thisObject
, visitor
);
47 visitor
.append(&thisObject
->m_next
);
50 // Returns true if we found enough information to terminate optimization.
51 static inline bool abstractAccess(ExecState
* exec
, JSScope
* scope
, const Identifier
& ident
, GetOrPut getOrPut
, size_t depth
, bool& needsVarInjectionChecks
, ResolveOp
& op
)
53 if (JSActivation
* activation
= jsDynamicCast
<JSActivation
*>(scope
)) {
54 if (ident
== exec
->propertyNames().arguments
) {
55 // We know the property will be at this activation scope, but we don't know how to cache it.
56 op
= ResolveOp(Dynamic
, 0, 0, 0, 0, 0);
60 SymbolTableEntry entry
= activation
->symbolTable()->get(ident
.impl());
61 if (entry
.isReadOnly() && getOrPut
== Put
) {
62 // We know the property will be at this activation scope, but we don't know how to cache it.
63 op
= ResolveOp(Dynamic
, 0, 0, 0, 0, 0);
67 if (!entry
.isNull()) {
68 op
= ResolveOp(makeType(ClosureVar
, needsVarInjectionChecks
), depth
, 0, activation
, entry
.watchpointSet(), entry
.getIndex());
72 if (activation
->symbolTable()->usesNonStrictEval())
73 needsVarInjectionChecks
= true;
77 if (JSGlobalObject
* globalObject
= jsDynamicCast
<JSGlobalObject
*>(scope
)) {
78 SymbolTableEntry entry
= globalObject
->symbolTable()->get(ident
.impl());
79 if (!entry
.isNull()) {
80 if (getOrPut
== Put
&& entry
.isReadOnly()) {
81 // We know the property will be at global scope, but we don't know how to cache it.
82 op
= ResolveOp(Dynamic
, 0, 0, 0, 0, 0);
87 makeType(GlobalVar
, needsVarInjectionChecks
), depth
, 0, 0, entry
.watchpointSet(),
88 reinterpret_cast<uintptr_t>(globalObject
->registerAt(entry
.getIndex()).slot()));
92 PropertySlot
slot(globalObject
);
93 if (!globalObject
->getOwnPropertySlot(globalObject
, exec
, ident
, slot
)
94 || !slot
.isCacheableValue()
95 || !globalObject
->structure()->propertyAccessesAreCacheable()
96 || (globalObject
->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto() && getOrPut
== Put
)) {
97 // We know the property will be at global scope, but we don't know how to cache it.
98 ASSERT(!scope
->next());
99 op
= ResolveOp(makeType(GlobalProperty
, needsVarInjectionChecks
), depth
, 0, 0, 0, 0);
103 op
= ResolveOp(makeType(GlobalProperty
, needsVarInjectionChecks
), depth
, globalObject
->structure(), 0, 0, slot
.cachedOffset());
107 op
= ResolveOp(Dynamic
, 0, 0, 0, 0, 0);
111 JSObject
* JSScope::objectAtScope(JSScope
* scope
)
113 JSObject
* object
= scope
;
114 if (object
->type() == WithScopeType
)
115 return jsCast
<JSWithScope
*>(object
)->object();
123 for (JSScope
* scope
= this; scope
; scope
= scope
->next())
128 JSValue
JSScope::resolve(ExecState
* exec
, JSScope
* scope
, const Identifier
& ident
)
130 ScopeChainIterator end
= scope
->end();
131 ScopeChainIterator it
= scope
->begin();
133 JSObject
* object
= it
.get();
135 if (++it
== end
) // Global scope.
138 if (object
->hasProperty(exec
, ident
))
143 ResolveOp
JSScope::abstractResolve(ExecState
* exec
, JSScope
* scope
, const Identifier
& ident
, GetOrPut getOrPut
, ResolveType unlinkedType
)
145 ResolveOp
op(Dynamic
, 0, 0, 0, 0, 0);
146 if (unlinkedType
== Dynamic
)
150 bool needsVarInjectionChecks
= JSC::needsVarInjectionChecks(unlinkedType
);
151 for (; scope
; scope
= scope
->next()) {
152 if (abstractAccess(exec
, scope
, ident
, getOrPut
, depth
, needsVarInjectionChecks
, op
))
160 const char* resolveModeName(ResolveMode mode
)
162 static const char* const names
[] = {
164 "DoNotThrowIfNotFound"
169 const char* resolveTypeName(ResolveType type
)
171 static const char* const names
[] = {
175 "GlobalPropertyWithVarInjectionChecks",
176 "GlobalVarWithVarInjectionChecks",
177 "ClosureVarWithVarInjectionChecks",
180 ASSERT(type
< sizeof(names
) / sizeof(names
[0]));