X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/ba379fdc102753d6be2c4d937058fe40257329fe..1981f5dfe8d77d97469d20652f712a09400c48ed:/runtime/ScopeChain.h diff --git a/runtime/ScopeChain.h b/runtime/ScopeChain.h index 17aff24..c382008 100644 --- a/runtime/ScopeChain.h +++ b/runtime/ScopeChain.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2008 Apple Inc. All rights reserved. + * 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 @@ -21,117 +21,105 @@ #ifndef ScopeChain_h #define ScopeChain_h -#include "FastAllocBase.h" +#include "JSCell.h" +#include "Structure.h" +#include namespace JSC { class JSGlobalData; class JSGlobalObject; class JSObject; + class LLIntOffsetsExtractor; class ScopeChainIterator; + class SlotVisitor; - class ScopeChainNode : public FastAllocBase { - public: - ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSObject* globalThis) - : next(next) - , object(object) + class ScopeChainNode : public JSCell { + private: + ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) + : JSCell(*globalData, globalData->scopeChainNodeStructure.get()) , globalData(globalData) - , globalThis(globalThis) - , refCount(1) + , next(*globalData, this, next, WriteBarrier::MayBeNull) + , object(*globalData, this, object) + , globalObject(*globalData, this, globalObject) + , globalThis(*globalData, this, globalThis) { - ASSERT(globalData); } -#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() + + protected: + void finishCreation(JSGlobalData* globalData, JSGlobalObject* globalObject) { - next = 0; - object = 0; - globalData = 0; - globalThis = 0; + Base::finishCreation(*globalData); + ASSERT_UNUSED(globalObject, globalObject); } -#endif - ScopeChainNode* next; - JSObject* object; - JSGlobalData* globalData; - 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() + public: + typedef JSCell Base; + + static ScopeChainNode* create(ExecState* exec, ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) + { + ScopeChainNode* node = new (NotNull, allocateCell(*exec->heap())) ScopeChainNode(next, object, globalData, globalObject, globalThis); + node->finishCreation(globalData, globalObject); + return node; + } + static ScopeChainNode* create(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) { - ref(); - return this; + ScopeChainNode* node = new (NotNull, allocateCell(globalData->heap)) ScopeChainNode(next, object, globalData, globalObject, globalThis); + node->finishCreation(globalData, globalObject); + return node; } + + JSGlobalData* globalData; + WriteBarrier next; + WriteBarrier object; + WriteBarrier globalObject; + WriteBarrier globalThis; ScopeChainNode* push(JSObject*); ScopeChainNode* pop(); - ScopeChainIterator begin() const; - ScopeChainIterator end() const; + ScopeChainIterator begin(); + ScopeChainIterator end(); - JSGlobalObject* globalObject() const; // defined in JSGlobalObject.h - JSObject* globalThisObject() const { return globalThis; } + int localDepth(); #ifndef NDEBUG - void print() const; + void print(); #endif + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); } + static void visitChildren(JSCell*, SlotVisitor&); + static JS_EXPORTDATA const ClassInfo s_info; + + private: + friend class LLIntOffsetsExtractor; + + static const unsigned StructureFlags = OverridesVisitChildren; }; inline ScopeChainNode* ScopeChainNode::push(JSObject* o) { ASSERT(o); - return new ScopeChainNode(this, o, globalData, globalThis); + return ScopeChainNode::create(this, o, globalData, globalObject.get(), globalThis.get()); } 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); + return next.get(); } class ScopeChainIterator { public: - ScopeChainIterator(const ScopeChainNode* node) + ScopeChainIterator(ScopeChainNode* node) : m_node(node) { } - JSObject* const & operator*() const { return m_node->object; } - JSObject* const * operator->() const { return &(operator*()); } + WriteBarrier const & operator*() const { return m_node->object; } + WriteBarrier const * operator->() const { return &(operator*()); } - ScopeChainIterator& operator++() { m_node = m_node->next; return *this; } + ScopeChainIterator& operator++() { m_node = m_node->next.get(); return *this; } // postfix ++ intentionally omitted @@ -139,99 +127,43 @@ namespace JSC { bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; } private: - const ScopeChainNode* m_node; + ScopeChainNode* m_node; }; - inline ScopeChainIterator ScopeChainNode::begin() const + inline ScopeChainIterator ScopeChainNode::begin() { return ScopeChainIterator(this); } - inline ScopeChainIterator ScopeChainNode::end() const + inline ScopeChainIterator ScopeChainNode::end() { return ScopeChainIterator(0); } - class NoScopeChain {}; - - class ScopeChain { - friend class JIT; - public: - ScopeChain(NoScopeChain) - : m_node(0) - { - } - - ScopeChain(JSObject* o, JSGlobalData* globalData, JSObject* globalThis) - : m_node(new ScopeChainNode(0, o, globalData, 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 mark() 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) + ALWAYS_INLINE JSGlobalData& ExecState::globalData() const { - ScopeChainNode* tmp = m_node; - m_node = o.m_node; - o.m_node = tmp; + ASSERT(scopeChain()->globalData); + return *scopeChain()->globalData; } - inline ScopeChain& ScopeChain::operator=(const ScopeChain& c) + ALWAYS_INLINE JSGlobalObject* ExecState::lexicalGlobalObject() const + { + return scopeChain()->globalObject.get(); + } + + ALWAYS_INLINE JSObject* ExecState::globalThisValue() const + { + return scopeChain()->globalThis.get(); + } + + ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const + { + return static_cast(jsValue().asCell()); + } + + ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain) { - ScopeChain tmp(c); - swap(tmp); + *this = JSValue(scopeChain); return *this; }