asherkin@263: /* vim: set ts=4 sw=4 tw=99 et: asherkin@263: * asherkin@263: * Copyright (C) 2012 David Anderson asherkin@263: * asherkin@263: * This file is part of SourcePawn. asherkin@263: * asherkin@263: * SourcePawn is free software: you can redistribute it and/or modify it under asherkin@263: * the terms of the GNU General Public License as published by the Free asherkin@263: * Software Foundation, either version 3 of the License, or (at your option) asherkin@263: * any later version. asherkin@263: * asherkin@263: * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY asherkin@263: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS asherkin@263: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. asherkin@263: * asherkin@263: * You should have received a copy of the GNU General Public License along with asherkin@263: * SourcePawn. If not, see http://www.gnu.org/licenses/. asherkin@263: */ asherkin@263: #ifndef _include_jc_root_scopes_h_ asherkin@263: #define _include_jc_root_scopes_h_ asherkin@263: asherkin@263: #include "../include/keima.h" asherkin@263: #include "Objects.h" asherkin@263: #include "VirtualObjectVisitor.h" asherkin@263: asherkin@263: namespace ke { asherkin@263: asherkin@263: class RootScope; asherkin@263: asherkin@263: // A RootScopeManager is essentially a specialized PoolAllocator that can asherkin@263: // only allocate Object ** entries. It is used to allow huge, temporary asherkin@263: // heap data structures like ASTs to hold safe references to objects. When asherkin@263: // the data structures is no longer needed, all of the roots are removed asherkin@263: // at once. asherkin@263: class RootScopeManager asherkin@263: { asherkin@263: static const size_t kObjectsPerBlock = 4096; asherkin@263: asherkin@263: struct Block { asherkin@263: Object *objects[kObjectsPerBlock]; asherkin@263: Object **cur; asherkin@263: Object **end; asherkin@263: Block *prev; asherkin@263: asherkin@263: Block(Block *prev) asherkin@263: : cur(objects), asherkin@263: end(objects + kObjectsPerBlock), asherkin@263: prev(prev) asherkin@263: { asherkin@263: } asherkin@263: }; asherkin@263: asherkin@263: private: asherkin@263: bool grow(); asherkin@263: void unwindSlow(Object **position); asherkin@263: asherkin@263: public: asherkin@263: RootScopeManager(); asherkin@263: ~RootScopeManager(); asherkin@263: asherkin@263: Object **position() const { asherkin@263: return blocks_->cur; asherkin@263: } asherkin@263: asherkin@263: void unwind(Object **position) { asherkin@263: if (position >= blocks_->cur && position <= blocks_->end) { asherkin@263: blocks_->cur = position; asherkin@263: return; asherkin@263: } asherkin@263: unwindSlow(position); asherkin@263: } asherkin@263: asherkin@263: Object **make(Object *obj) { asherkin@263: assert(scope_); asherkin@263: if (blocks_->cur + 1 > blocks_->end) { asherkin@263: if (!grow()) asherkin@263: return NULL; asherkin@263: } asherkin@263: Object **ptr = blocks_->cur; asherkin@263: blocks_->cur++; asherkin@263: *ptr = obj; asherkin@263: return ptr; asherkin@263: } asherkin@263: asherkin@263: Ke::HandleScope **scope() { asherkin@263: return &scope_; asherkin@263: } asherkin@263: asherkin@263: void accept(VirtualObjectVisitor *visitor); asherkin@263: asherkin@263: private: asherkin@263: Block *blocks_; asherkin@263: Block first_; asherkin@263: Ke::HandleScope *scope_; asherkin@263: }; asherkin@263: asherkin@263: class RootScope : public Ke::HandleScope asherkin@263: { asherkin@263: public: asherkin@263: // These are implemented in Zone.h. asherkin@263: inline RootScope(Zone *zone); asherkin@263: }; asherkin@263: asherkin@263: } asherkin@263: asherkin@263: #endif // _include_jc_root_scope_h_