diff options
author | Steve Block <steveblock@google.com> | 2011-05-13 06:44:40 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-05-13 06:44:40 -0700 |
commit | 08014c20784f3db5df3a89b73cce46037b77eb59 (patch) | |
tree | 47749210d31e19e6e2f64036fa8fae2ad693476f /Source/JavaScriptCore/runtime/ScopeChain.h | |
parent | 860220379e56aeb66424861ad602b07ee22b4055 (diff) | |
parent | 4c3661f7918f8b3f139f824efb7855bedccb4c94 (diff) | |
download | external_webkit-08014c20784f3db5df3a89b73cce46037b77eb59.zip external_webkit-08014c20784f3db5df3a89b73cce46037b77eb59.tar.gz external_webkit-08014c20784f3db5df3a89b73cce46037b77eb59.tar.bz2 |
Merge changes Ide388898,Ic49f367c,I1158a808,Iacb6ca5d,I2100dd3a,I5c1abe54,Ib0ef9902,I31dbc523,I570314b3
* changes:
Merge WebKit at r75315: Update WebKit version
Merge WebKit at r75315: Add FrameLoaderClient PageCache stubs
Merge WebKit at r75315: Stub out AXObjectCache::remove()
Merge WebKit at r75315: Fix ImageBuffer
Merge WebKit at r75315: Fix PluginData::initPlugins()
Merge WebKit at r75315: Fix conflicts
Merge WebKit at r75315: Fix Makefiles
Merge WebKit at r75315: Move Android-specific WebCore files to Source
Merge WebKit at r75315: Initial merge by git.
Diffstat (limited to 'Source/JavaScriptCore/runtime/ScopeChain.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/ScopeChain.h | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/runtime/ScopeChain.h b/Source/JavaScriptCore/runtime/ScopeChain.h new file mode 100644 index 0000000..0b15b67 --- /dev/null +++ b/Source/JavaScriptCore/runtime/ScopeChain.h @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef ScopeChain_h +#define ScopeChain_h + +#include "FastAllocBase.h" + +namespace JSC { + + class JSGlobalData; + class JSGlobalObject; + class JSObject; + class MarkStack; + class ScopeChainIterator; + + class ScopeChainNode : public FastAllocBase { + public: + ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) + : next(next) + , object(object) + , globalData(globalData) + , globalObject(globalObject) + , globalThis(globalThis) + , refCount(1) + { + ASSERT(globalData); + ASSERT(globalObject); + } +#ifndef NDEBUG + // Due to the number of subtle and timing dependent bugs that have occurred due + // to deleted but still "valid" ScopeChainNodes we now deliberately clobber the + // contents in debug builds. + ~ScopeChainNode() + { + next = 0; + object = 0; + globalData = 0; + globalObject = 0; + globalThis = 0; + } +#endif + + ScopeChainNode* next; + JSObject* object; + JSGlobalData* globalData; + JSGlobalObject* globalObject; + JSObject* globalThis; + int refCount; + + void deref() { ASSERT(refCount); if (--refCount == 0) { release();} } + void ref() { ASSERT(refCount); ++refCount; } + void release(); + + // Before calling "push" on a bare ScopeChainNode, a client should + // logically "copy" the node. Later, the client can "deref" the head + // of its chain of ScopeChainNodes to reclaim all the nodes it added + // after the logical copy, leaving nodes added before the logical copy + // (nodes shared with other clients) untouched. + ScopeChainNode* copy() + { + ref(); + return this; + } + + ScopeChainNode* push(JSObject*); + ScopeChainNode* pop(); + + ScopeChainIterator begin() const; + ScopeChainIterator end() const; + +#ifndef NDEBUG + void print() const; +#endif + }; + + inline ScopeChainNode* ScopeChainNode::push(JSObject* o) + { + ASSERT(o); + return new ScopeChainNode(this, o, globalData, globalObject, globalThis); + } + + inline ScopeChainNode* ScopeChainNode::pop() + { + ASSERT(next); + ScopeChainNode* result = next; + + if (--refCount != 0) + ++result->refCount; + else + delete this; + + return result; + } + + inline void ScopeChainNode::release() + { + // This function is only called by deref(), + // Deref ensures these conditions are true. + ASSERT(refCount == 0); + ScopeChainNode* n = this; + do { + ScopeChainNode* next = n->next; + delete n; + n = next; + } while (n && --n->refCount == 0); + } + + class ScopeChainIterator { + public: + ScopeChainIterator(const ScopeChainNode* node) + : m_node(node) + { + } + + JSObject* const & operator*() const { return m_node->object; } + JSObject* const * operator->() const { return &(operator*()); } + + ScopeChainIterator& operator++() { m_node = m_node->next; return *this; } + + // postfix ++ intentionally omitted + + bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; } + bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; } + + private: + const ScopeChainNode* m_node; + }; + + inline ScopeChainIterator ScopeChainNode::begin() const + { + return ScopeChainIterator(this); + } + + inline ScopeChainIterator ScopeChainNode::end() const + { + return ScopeChainIterator(0); + } + + class NoScopeChain {}; + + class ScopeChain { + friend class JIT; + public: + ScopeChain(NoScopeChain) + : m_node(0) + { + } + + ScopeChain(JSObject* o, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) + : m_node(new ScopeChainNode(0, o, globalData, globalObject, globalThis)) + { + } + + ScopeChain(const ScopeChain& c) + : m_node(c.m_node->copy()) + { + } + + ScopeChain& operator=(const ScopeChain& c); + + explicit ScopeChain(ScopeChainNode* node) + : m_node(node->copy()) + { + } + + ~ScopeChain() + { + if (m_node) + m_node->deref(); +#ifndef NDEBUG + m_node = 0; +#endif + } + + void swap(ScopeChain&); + + ScopeChainNode* node() const { return m_node; } + + JSObject* top() const { return m_node->object; } + + ScopeChainIterator begin() const { return m_node->begin(); } + ScopeChainIterator end() const { return m_node->end(); } + + void push(JSObject* o) { m_node = m_node->push(o); } + + void pop() { m_node = m_node->pop(); } + void clear() { m_node->deref(); m_node = 0; } + + JSGlobalObject* globalObject() const { return m_node->globalObject; } + + void markAggregate(MarkStack&) const; + + // Caution: this should only be used if the codeblock this is being used + // with needs a full scope chain, otherwise this returns the depth of + // the preceeding call frame + // + // Returns the depth of the current call frame's scope chain + int localDepth() const; + +#ifndef NDEBUG + void print() const { m_node->print(); } +#endif + + private: + ScopeChainNode* m_node; + }; + + inline void ScopeChain::swap(ScopeChain& o) + { + ScopeChainNode* tmp = m_node; + m_node = o.m_node; + o.m_node = tmp; + } + + inline ScopeChain& ScopeChain::operator=(const ScopeChain& c) + { + ScopeChain tmp(c); + swap(tmp); + return *this; + } + +} // namespace JSC + +#endif // ScopeChain_h |