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 MarkStack; 34 class ScopeChainIterator; 35 36 class ScopeChainNode : public JSCell { 37 public: ScopeChainNode(ScopeChainNode * next,JSObject * object,JSGlobalData * globalData,JSGlobalObject * globalObject,JSObject * globalThis)38 ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) 39 : JSCell(*globalData, globalData->scopeChainNodeStructure.get()) 40 , globalData(globalData) 41 , next(*globalData, this, next) 42 , object(*globalData, this, object) 43 , globalObject(*globalData, this, globalObject) 44 , globalThis(*globalData, this, globalThis) 45 { 46 ASSERT(globalData); 47 ASSERT(globalObject); 48 } 49 50 JSGlobalData* globalData; 51 WriteBarrier<ScopeChainNode> next; 52 WriteBarrier<JSObject> object; 53 WriteBarrier<JSGlobalObject> globalObject; 54 WriteBarrier<JSObject> globalThis; 55 56 ScopeChainNode* push(JSObject*); 57 ScopeChainNode* pop(); 58 59 ScopeChainIterator begin(); 60 ScopeChainIterator end(); 61 62 int localDepth(); 63 64 #ifndef NDEBUG 65 void print(); 66 #endif 67 createStructure(JSGlobalData & globalData,JSValue proto)68 static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); } 69 virtual void markChildren(MarkStack&); 70 private: 71 static const unsigned StructureFlags = OverridesMarkChildren; 72 static const ClassInfo s_info; 73 }; 74 push(JSObject * o)75 inline ScopeChainNode* ScopeChainNode::push(JSObject* o) 76 { 77 ASSERT(o); 78 return new (globalData) ScopeChainNode(this, o, globalData, globalObject.get(), globalThis.get()); 79 } 80 pop()81 inline ScopeChainNode* ScopeChainNode::pop() 82 { 83 ASSERT(next); 84 return next.get(); 85 } 86 87 class ScopeChainIterator { 88 public: ScopeChainIterator(ScopeChainNode * node)89 ScopeChainIterator(ScopeChainNode* node) 90 : m_node(node) 91 { 92 } 93 94 WriteBarrier<JSObject> const & operator*() const { return m_node->object; } 95 WriteBarrier<JSObject> const * operator->() const { return &(operator*()); } 96 97 ScopeChainIterator& operator++() { m_node = m_node->next.get(); return *this; } 98 99 // postfix ++ intentionally omitted 100 101 bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; } 102 bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; } 103 104 private: 105 ScopeChainNode* m_node; 106 }; 107 begin()108 inline ScopeChainIterator ScopeChainNode::begin() 109 { 110 return ScopeChainIterator(this); 111 } 112 end()113 inline ScopeChainIterator ScopeChainNode::end() 114 { 115 return ScopeChainIterator(0); 116 } 117 globalData()118 ALWAYS_INLINE JSGlobalData& ExecState::globalData() const 119 { 120 ASSERT(scopeChain()->globalData); 121 return *scopeChain()->globalData; 122 } 123 lexicalGlobalObject()124 ALWAYS_INLINE JSGlobalObject* ExecState::lexicalGlobalObject() const 125 { 126 return scopeChain()->globalObject.get(); 127 } 128 globalThisValue()129 ALWAYS_INLINE JSObject* ExecState::globalThisValue() const 130 { 131 return scopeChain()->globalThis.get(); 132 } 133 scopeChain()134 ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const 135 { 136 return static_cast<ScopeChainNode*>(jsValue().asCell()); 137 } 138 139 ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain) 140 { 141 *this = JSValue(scopeChain); 142 return *this; 143 } 144 145 } // namespace JSC 146 147 #endif // ScopeChain_h 148