]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/ScopeChain.h
c382008f11587428e96ac8790642756a6072bb74
[apple/javascriptcore.git] / runtime / ScopeChain.h
1 /*
2 * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21 #ifndef ScopeChain_h
22 #define ScopeChain_h
23
24 #include "JSCell.h"
25 #include "Structure.h"
26 #include <wtf/FastAllocBase.h>
27
28 namespace JSC {
29
30 class JSGlobalData;
31 class JSGlobalObject;
32 class JSObject;
33 class LLIntOffsetsExtractor;
34 class ScopeChainIterator;
35 class SlotVisitor;
36
37 class ScopeChainNode : public JSCell {
38 private:
39 ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
40 : JSCell(*globalData, globalData->scopeChainNodeStructure.get())
41 , globalData(globalData)
42 , next(*globalData, this, next, WriteBarrier<ScopeChainNode>::MayBeNull)
43 , object(*globalData, this, object)
44 , globalObject(*globalData, this, globalObject)
45 , globalThis(*globalData, this, globalThis)
46 {
47 }
48
49 protected:
50 void finishCreation(JSGlobalData* globalData, JSGlobalObject* globalObject)
51 {
52 Base::finishCreation(*globalData);
53 ASSERT_UNUSED(globalObject, globalObject);
54 }
55
56 public:
57 typedef JSCell Base;
58
59 static ScopeChainNode* create(ExecState* exec, ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
60 {
61 ScopeChainNode* node = new (NotNull, allocateCell<ScopeChainNode>(*exec->heap())) ScopeChainNode(next, object, globalData, globalObject, globalThis);
62 node->finishCreation(globalData, globalObject);
63 return node;
64 }
65 static ScopeChainNode* create(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
66 {
67 ScopeChainNode* node = new (NotNull, allocateCell<ScopeChainNode>(globalData->heap)) ScopeChainNode(next, object, globalData, globalObject, globalThis);
68 node->finishCreation(globalData, globalObject);
69 return node;
70 }
71
72 JSGlobalData* globalData;
73 WriteBarrier<ScopeChainNode> next;
74 WriteBarrier<JSObject> object;
75 WriteBarrier<JSGlobalObject> globalObject;
76 WriteBarrier<JSObject> globalThis;
77
78 ScopeChainNode* push(JSObject*);
79 ScopeChainNode* pop();
80
81 ScopeChainIterator begin();
82 ScopeChainIterator end();
83
84 int localDepth();
85
86 #ifndef NDEBUG
87 void print();
88 #endif
89
90 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
91 static void visitChildren(JSCell*, SlotVisitor&);
92 static JS_EXPORTDATA const ClassInfo s_info;
93
94 private:
95 friend class LLIntOffsetsExtractor;
96
97 static const unsigned StructureFlags = OverridesVisitChildren;
98 };
99
100 inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
101 {
102 ASSERT(o);
103 return ScopeChainNode::create(this, o, globalData, globalObject.get(), globalThis.get());
104 }
105
106 inline ScopeChainNode* ScopeChainNode::pop()
107 {
108 ASSERT(next);
109 return next.get();
110 }
111
112 class ScopeChainIterator {
113 public:
114 ScopeChainIterator(ScopeChainNode* node)
115 : m_node(node)
116 {
117 }
118
119 WriteBarrier<JSObject> const & operator*() const { return m_node->object; }
120 WriteBarrier<JSObject> const * operator->() const { return &(operator*()); }
121
122 ScopeChainIterator& operator++() { m_node = m_node->next.get(); return *this; }
123
124 // postfix ++ intentionally omitted
125
126 bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; }
127 bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
128
129 private:
130 ScopeChainNode* m_node;
131 };
132
133 inline ScopeChainIterator ScopeChainNode::begin()
134 {
135 return ScopeChainIterator(this);
136 }
137
138 inline ScopeChainIterator ScopeChainNode::end()
139 {
140 return ScopeChainIterator(0);
141 }
142
143 ALWAYS_INLINE JSGlobalData& ExecState::globalData() const
144 {
145 ASSERT(scopeChain()->globalData);
146 return *scopeChain()->globalData;
147 }
148
149 ALWAYS_INLINE JSGlobalObject* ExecState::lexicalGlobalObject() const
150 {
151 return scopeChain()->globalObject.get();
152 }
153
154 ALWAYS_INLINE JSObject* ExecState::globalThisValue() const
155 {
156 return scopeChain()->globalThis.get();
157 }
158
159 ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const
160 {
161 return static_cast<ScopeChainNode*>(jsValue().asCell());
162 }
163
164 ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain)
165 {
166 *this = JSValue(scopeChain);
167 return *this;
168 }
169
170 } // namespace JSC
171
172 #endif // ScopeChain_h