Added RootScopes for AST roots.
authorDavid Anderson <dvander@alliedmods.net>
Tue Jul 03 00:21:37 2012 -0700 (2012-07-03)
changeset 29c0e27b4f0672
parent 28 a9665857cfd5
child 30 8c8bf75114f7
Added RootScopes for AST roots.
jitcraft/AST.h
jitcraft/Handles.h
jitcraft/RootScopes.cpp
jitcraft/RootScopes.h
jitcraft/Zone.h
jitcraft/main.cpp
     1.1 --- a/jitcraft/AST.h	Mon Jul 02 23:37:12 2012 -0700
     1.2 +++ b/jitcraft/AST.h	Tue Jul 03 00:21:37 2012 -0700
     1.3 @@ -135,7 +135,7 @@
     1.4  
     1.5  class Expression : public AstNode
     1.6  {
     1.7 -    Type *type_;
     1.8 +    ScopedRoot<Type> type_;
     1.9  
    1.10    public:
    1.11      Expression(const SourcePosition &pos)
    1.12 @@ -295,7 +295,7 @@
    1.13  
    1.14  class StringLiteral : public Expression
    1.15  {
    1.16 -    ByteArray *string_;
    1.17 +    ScopedRoot<ByteArray> string_;
    1.18  
    1.19    public:
    1.20      StringLiteral(const SourcePosition &pos, ByteArray *array)
     2.1 --- a/jitcraft/Handles.h	Mon Jul 02 23:37:12 2012 -0700
     2.2 +++ b/jitcraft/Handles.h	Tue Jul 03 00:21:37 2012 -0700
     2.3 @@ -1,4 +1,5 @@
     2.4 -/*
     2.5 +/* vim: set ts=4 sw=4 tw=99 et:
     2.6 + *
     2.7   * Copyright (C) 2012 David Anderson
     2.8   *
     2.9   * This file is part of JITCraft.
    2.10 @@ -84,6 +85,7 @@
    2.11      }
    2.12  
    2.13    public:
    2.14 +    // These are implemented in Zone.h.
    2.15      inline explicit Local(Zone *zone, T *thing = NULL);
    2.16      inline ~Local();
    2.17  
    2.18 @@ -126,11 +128,13 @@
    2.19  template <typename T>
    2.20  class ScopedRoot
    2.21  {
    2.22 -    T *thingp_;
    2.23 +    T **thingp_;
    2.24  
    2.25    private:
    2.26 -    inline T **make(const T *&other);
    2.27 -    inline void assign(const T *&other) {
    2.28 +    // This is implemented in Zone.h.
    2.29 +    inline T **make(T *other);
    2.30 +
    2.31 +    void assign(T *other) {
    2.32          if (!thingp_)
    2.33              thingp_ = make(other);
    2.34          else
    2.35 @@ -140,13 +144,15 @@
    2.36    public:
    2.37      ScopedRoot()
    2.38      { }
    2.39 -    inline ScopedRoot(const T *&thing);
    2.40 -    inline ScopedRoot(const ScopedRoot<T> &other);
    2.41 +
    2.42 +    // This is implemented in Zone.h.
    2.43 +    inline ScopedRoot(T *thing);
    2.44 +
    2.45      ScopedRoot &operator =(const ScopedRoot<T> &other) {
    2.46          assign(*other);
    2.47          return *this;
    2.48      }
    2.49 -    ScopedRoot &operator =(const T *&other) {
    2.50 +    ScopedRoot &operator =(T *other) {
    2.51          assign(other);
    2.52          return *this;
    2.53      }
    2.54 @@ -154,10 +160,13 @@
    2.55          return operator *();
    2.56      }
    2.57      T *operator *() const {
    2.58 -        return thingp_;
    2.59 +        return *thingp_;
    2.60 +    }
    2.61 +    operator T *() const {
    2.62 +        return thingp_ ? *thingp_ : NULL;
    2.63      }
    2.64      operator bool () const {
    2.65 -        return !!thingp_;
    2.66 +        return thingp_ && *thingp_;
    2.67      }
    2.68  };
    2.69  
    2.70 @@ -168,33 +177,6 @@
    2.71      thingp_ = reinterpret_cast<T * const*>(local.address());
    2.72  }
    2.73  
    2.74 -// A RootScope is necessary for using ScopedRoot<>.
    2.75 -class RootScope
    2.76 -{
    2.77 -    friend class Zone;
    2.78 -
    2.79 -    struct Block
    2.80 -    {
    2.81 -        static const size_t kItemsPerBlock = 4096 / sizeof(Object *);
    2.82 -
    2.83 -        Object **base;
    2.84 -        Object **ptr;
    2.85 -        Object **end;
    2.86 -        Block *prev;
    2.87 -        
    2.88 -        Block(Block *prev, Object **base)
    2.89 -          : base(base),
    2.90 -            ptr(base),
    2.91 -            end(base + kItemsPerBlock),
    2.92 -            prev(prev)
    2.93 -        {
    2.94 -        }
    2.95 -    };
    2.96 -
    2.97 -  private:
    2.98 -    
    2.99 -};
   2.100 -
   2.101  }
   2.102  
   2.103  #endif // _include_jitcraft_rooting_h_
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/jitcraft/RootScopes.cpp	Tue Jul 03 00:21:37 2012 -0700
     3.3 @@ -0,0 +1,66 @@
     3.4 +/* vim: set ts=4 sw=4 tw=99 et:
     3.5 + *
     3.6 + * Copyright (C) 2012 David Anderson
     3.7 + *
     3.8 + * This file is part of JITCraft.
     3.9 + *
    3.10 + * JITCraft is free software: you can redistribute it and/or modify it under
    3.11 + * the terms of the GNU General Public License as published by the Free
    3.12 + * Software Foundation, either version 3 of the License, or (at your option)
    3.13 + * any later version.
    3.14 + * 
    3.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    3.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    3.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    3.18 + *
    3.19 + * You should have received a copy of the GNU General Public License along with
    3.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    3.21 + */
    3.22 +#include "RootScopes.h"
    3.23 +
    3.24 +using namespace jc;
    3.25 +
    3.26 +RootScopeManager::RootScopeManager()
    3.27 +  : blocks_(&first_),
    3.28 +    first_(NULL),
    3.29 +    scope_(NULL)
    3.30 +{
    3.31 +}
    3.32 +
    3.33 +RootScopeManager::~RootScopeManager()
    3.34 +{
    3.35 +    while (blocks_ != &first_) {
    3.36 +        Block *temp = blocks_;
    3.37 +        delete blocks_;
    3.38 +        blocks_ = temp;
    3.39 +    }
    3.40 +}
    3.41 +
    3.42 +bool
    3.43 +RootScopeManager::grow()
    3.44 +{
    3.45 +    assert(blocks_->cur == blocks_->end);
    3.46 +
    3.47 +    Block *block = new Block(blocks_);
    3.48 +    if (!block)
    3.49 +        return false;
    3.50 +
    3.51 +    blocks_ = block;
    3.52 +    return true;
    3.53 +}
    3.54 +
    3.55 +void
    3.56 +RootScopeManager::unwindSlow(Object **pos)
    3.57 +{
    3.58 +    for (;;) {
    3.59 +        if (pos >= blocks_->cur && pos <= blocks_->end)
    3.60 +            break;
    3.61 +        assert(blocks_ != &first_);
    3.62 +        Block *temp = blocks_;
    3.63 +        delete blocks_;
    3.64 +        blocks_ = temp;
    3.65 +    }
    3.66 +
    3.67 +    blocks_->cur = pos;
    3.68 +}
    3.69 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/jitcraft/RootScopes.h	Tue Jul 03 00:21:37 2012 -0700
     4.3 @@ -0,0 +1,107 @@
     4.4 +/* vim: set ts=4 sw=4 tw=99 et:
     4.5 + *
     4.6 + * Copyright (C) 2012 David Anderson
     4.7 + *
     4.8 + * This file is part of JITCraft.
     4.9 + *
    4.10 + * JITCraft is free software: you can redistribute it and/or modify it under
    4.11 + * the terms of the GNU General Public License as published by the Free
    4.12 + * Software Foundation, either version 3 of the License, or (at your option)
    4.13 + * any later version.
    4.14 + * 
    4.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    4.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    4.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    4.18 + *
    4.19 + * You should have received a copy of the GNU General Public License along with
    4.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    4.21 + */
    4.22 +#ifndef _include_jc_root_scopes_h_
    4.23 +#define _include_jc_root_scopes_h_
    4.24 +
    4.25 +#include "Objects.h"
    4.26 +
    4.27 +namespace jc {
    4.28 +
    4.29 +class RootScope;
    4.30 +
    4.31 +// A RootScopeManager is essentially a specialized PoolAllocator that can
    4.32 +// only allocate Object ** entries. It is used to allow huge, temporary
    4.33 +// heap data structures like ASTs to hold safe references to objects. When
    4.34 +// the data structures is no longer needed, all of the roots are removed
    4.35 +// at once.
    4.36 +class RootScopeManager
    4.37 +{
    4.38 +    static const size_t kObjectsPerBlock = 4096;
    4.39 +
    4.40 +    struct Block {
    4.41 +        Object *objects[kObjectsPerBlock];
    4.42 +        Object **cur;
    4.43 +        Object **end;
    4.44 +        Block *prev;
    4.45 +
    4.46 +        Block(Block *prev)
    4.47 +          : cur(objects),
    4.48 +            end(objects + kObjectsPerBlock),
    4.49 +            prev(prev)
    4.50 +        {
    4.51 +        }
    4.52 +    };
    4.53 +
    4.54 +  private:
    4.55 +    bool grow();
    4.56 +    void unwindSlow(Object **position);
    4.57 +
    4.58 +  public:
    4.59 +    RootScopeManager();
    4.60 +    ~RootScopeManager();
    4.61 +
    4.62 +    Object **position() const {
    4.63 +        return blocks_->cur;
    4.64 +    }
    4.65 +
    4.66 +    void unwind(Object **position) {
    4.67 +        if (position >= blocks_->cur && position <= blocks_->end) {
    4.68 +            blocks_->cur = position;
    4.69 +            return;
    4.70 +        }
    4.71 +        unwindSlow(position);
    4.72 +    }
    4.73 +
    4.74 +    Object **make(Object *obj) {
    4.75 +        assert(scope_);
    4.76 +        if (blocks_->cur + 1 > blocks_->end) {
    4.77 +            if (!grow())
    4.78 +                return NULL;
    4.79 +        }
    4.80 +        Object **ptr = blocks_->cur;
    4.81 +        blocks_->cur++;
    4.82 +        *ptr = obj;
    4.83 +        return ptr;
    4.84 +    }
    4.85 +
    4.86 +    RootScope **scope() {
    4.87 +        return &scope_;
    4.88 +    }
    4.89 +
    4.90 +  private:
    4.91 +    Block *blocks_;
    4.92 +    Block first_;
    4.93 +    RootScope *scope_;
    4.94 +};
    4.95 +
    4.96 +class RootScope
    4.97 +{
    4.98 +    Zone *zone_;
    4.99 +    Object **position_;
   4.100 +    RootScope *prev_;
   4.101 +
   4.102 +  public:
   4.103 +    // These are implemented in Zone.h.
   4.104 +    inline RootScope(Zone *zone);
   4.105 +    inline ~RootScope();
   4.106 +};
   4.107 +
   4.108 +}
   4.109 +
   4.110 +#endif // _include_jc_root_scope_h_
     5.1 --- a/jitcraft/Zone.h	Mon Jul 02 23:37:12 2012 -0700
     5.2 +++ b/jitcraft/Zone.h	Tue Jul 03 00:21:37 2012 -0700
     5.3 @@ -24,6 +24,7 @@
     5.4  #include "Heap.h"
     5.5  #include "Barriers.h"
     5.6  #include "Handles.h"
     5.7 +#include "RootScopes.h"
     5.8  
     5.9  namespace jc {
    5.10  
    5.11 @@ -42,6 +43,7 @@
    5.12  
    5.13      // Root list.
    5.14      Local<Object> *lastLocalRoot_;
    5.15 +    RootScopeManager rootScopes_;
    5.16  
    5.17    public:
    5.18      Zone();
    5.19 @@ -72,6 +74,12 @@
    5.20      Local<Object> **lastLocalRoot() {
    5.21          return &lastLocalRoot_;
    5.22      }
    5.23 +    Object **makeScopedRoot(Object *ptr) {
    5.24 +        return rootScopes_.make(ptr);
    5.25 +    }
    5.26 +    RootScopeManager &rootScopes() {
    5.27 +        return rootScopes_;
    5.28 +    }
    5.29  };
    5.30  
    5.31  // In a multi-threaded system, this would be a TLS variable.
    5.32 @@ -118,6 +126,37 @@
    5.33      *zone_->lastLocalRoot() = prev_;
    5.34  }
    5.35  
    5.36 +template <typename T>
    5.37 +ScopedRoot<T>::ScopedRoot(T *thing)
    5.38 +  : thingp_(NULL)
    5.39 +{
    5.40 +    // Type check that T is an Object.
    5.41 +    (void)static_cast<Object *>(thing);
    5.42 +
    5.43 +    if (thing)
    5.44 +        assign(thing);
    5.45 +}
    5.46 +
    5.47 +template <typename T> T **
    5.48 +ScopedRoot<T>::make(T *other)
    5.49 +{
    5.50 +    return reinterpret_cast<T **>(ZONE()->makeScopedRoot(other));
    5.51 +}
    5.52 +
    5.53 +RootScope::RootScope(Zone *zone)
    5.54 +  : zone_(zone),
    5.55 +    position_(zone->rootScopes().position()),
    5.56 +    prev_(*zone->rootScopes().scope())
    5.57 +{
    5.58 +    *zone->rootScopes().scope() = this;
    5.59 +}
    5.60 +
    5.61 +RootScope::~RootScope()
    5.62 +{
    5.63 +    zone_->rootScopes().unwind(position_);
    5.64 +    *zone_->rootScopes().scope() = prev_;
    5.65 +}
    5.66 +
    5.67  }
    5.68  
    5.69  #endif // _include_jitcraft_thread_h_
     6.1 --- a/jitcraft/main.cpp	Mon Jul 02 23:37:12 2012 -0700
     6.2 +++ b/jitcraft/main.cpp	Tue Jul 03 00:21:37 2012 -0700
     6.3 @@ -25,6 +25,7 @@
     6.4  #include "Code.h"
     6.5  #include "Interpreter.h"
     6.6  #include "Modules.h"
     6.7 +#include "RootScopes.h"
     6.8  
     6.9  using namespace jc;
    6.10  
    6.11 @@ -58,6 +59,7 @@
    6.12      if (!ZONE()->initialize())
    6.13          return false;
    6.14  
    6.15 +    RootScope roots(ZONE());
    6.16      CompileContext cc(ZONE());
    6.17  
    6.18      Parser parser(cc, stream, length);