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