Convert Name and StringPool to a GC-safe symbol table.
authorDavid Anderson <dvander@alliedmods.net>
Sat Jul 07 20:28:29 2012 -0700 (2012-07-07)
changeset 548e22792a3921
parent 53 13bd3a8df334
child 55 e073a9fe8e57
Convert Name and StringPool to a GC-safe symbol table.
jitcraft/AST.h
jitcraft/AllocatorPolicies.h
jitcraft/BytecodeCompiler.cpp
jitcraft/FixedArray.h
jitcraft/Handles.h
jitcraft/HashTable.h
jitcraft/Heap.cpp
jitcraft/NameBinding.cpp
jitcraft/NameBinding.h
jitcraft/ObjectVisitor.h
jitcraft/Objects.h
jitcraft/Opcodes.cpp
jitcraft/Parser.cpp
jitcraft/Parser.h
jitcraft/Scanner.h
jitcraft/Scopes.cpp
jitcraft/Scopes.h
jitcraft/SemanticAnalysis.cpp
jitcraft/StringPool.cpp
jitcraft/StringPool.h
jitcraft/Strings.cpp
jitcraft/Strings.h
jitcraft/TypeManager.cpp
jitcraft/TypeManager.h
jitcraft/Types.cpp
jitcraft/Types.h
jitcraft/Utility.h
jitcraft/Zone.cpp
jitcraft/Zone.h
jitcraft/jitcraft.vcxproj
jitcraft/main.cpp
     1.1 --- a/jitcraft/AST.h	Sat Jul 07 17:11:31 2012 -0700
     1.2 +++ b/jitcraft/AST.h	Sat Jul 07 20:28:29 2012 -0700
     1.3 @@ -20,8 +20,8 @@
     1.4  
     1.5  #include "PoolAllocator.h"
     1.6  #include "Token.h"
     1.7 -#include "StringPool.h"
     1.8  #include "NameBinding.h"
     1.9 +#include <vector>
    1.10  
    1.11  namespace jc {
    1.12  
    1.13 @@ -160,10 +160,10 @@
    1.14      Variable *variable_;
    1.15      Expression *initialization_;
    1.16      ExpressionList *postDimensions_;
    1.17 -    Name *tag_;
    1.18 +    ScopedRoot<String> tag_;
    1.19  
    1.20    public:
    1.21 -    VariableDeclaration(const SourcePosition &pos, Variable *var, Name *tag,
    1.22 +    VariableDeclaration(const SourcePosition &pos, Variable *var, Handle<String> tag,
    1.23                          ExpressionList *postDimensions, Expression *initialization)
    1.24        : Statement(pos),
    1.25          variable_(var),
    1.26 @@ -173,7 +173,7 @@
    1.27      {
    1.28      }
    1.29  
    1.30 -    Name *tag() const {
    1.31 +    String *tag() const {
    1.32          return tag_;
    1.33      }
    1.34      Kind kind() const {
    1.35 @@ -196,18 +196,18 @@
    1.36  class Parameter : public PoolObject
    1.37  {
    1.38      Variable *variable_;
    1.39 -    Name *tag_;
    1.40 +    ScopedRoot<String> tag_;
    1.41      bool reference_;
    1.42  
    1.43    public:
    1.44 -    Parameter(Variable *var, Name *tag, bool reference)
    1.45 +    Parameter(Variable *var, Handle<String> tag, bool reference)
    1.46        : variable_(var),
    1.47          tag_(tag),
    1.48          reference_(reference)
    1.49      {
    1.50      }
    1.51  
    1.52 -    Name *tag() const {
    1.53 +    String *tag() const {
    1.54          return tag_;
    1.55      }
    1.56      Variable *variable() const {
    1.57 @@ -220,11 +220,11 @@
    1.58  
    1.59  class NameProxy : public Expression
    1.60  {
    1.61 -    Name *name_;
    1.62 +    ScopedRoot<String> name_;
    1.63      BoundName *binding_;
    1.64  
    1.65    public:
    1.66 -    NameProxy(const SourcePosition &pos, Name *name, BoundName *binding)
    1.67 +    NameProxy(const SourcePosition &pos, Handle<String> name, BoundName *binding)
    1.68        : Expression(pos),
    1.69          name_(name),
    1.70          binding_(binding)
    1.71 @@ -234,7 +234,7 @@
    1.72      Kind kind() const {
    1.73          return kNameProxy;
    1.74      }
    1.75 -    Name *name() const {
    1.76 +    String *name() const {
    1.77          return name_;
    1.78      }
    1.79      void accept(AstVisitor *visitor) {
    1.80 @@ -688,7 +688,7 @@
    1.81  
    1.82  class EnumStatement : public Statement
    1.83  {
    1.84 -    Name *name_;
    1.85 +    ScopedRoot<String> name_;
    1.86  
    1.87    public:
    1.88      struct Entry {
    1.89 @@ -705,7 +705,7 @@
    1.90      typedef std::vector<Entry> EntryList;
    1.91  
    1.92    public:
    1.93 -    EnumStatement(const SourcePosition &pos, Name *name, EntryList *entries)
    1.94 +    EnumStatement(const SourcePosition &pos, Handle<String> name, EntryList *entries)
    1.95        : Statement(pos),
    1.96          name_(name),
    1.97          entries_(entries)
    1.98 @@ -715,7 +715,7 @@
    1.99      Kind kind() const {
   1.100          return kEnumStatement;
   1.101      }
   1.102 -    Name *name() const {
   1.103 +    String *name() const {
   1.104          return name_;
   1.105      }
   1.106      EntryList *entries() const {
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/jitcraft/AllocatorPolicies.h	Sat Jul 07 20:28:29 2012 -0700
     2.3 @@ -0,0 +1,45 @@
     2.4 +/*
     2.5 + * Copyright (C) 2012 David Anderson
     2.6 + *
     2.7 + * This file is part of JITCraft.
     2.8 + *
     2.9 + * JITCraft is free software: you can redistribute it and/or modify it under
    2.10 + * the terms of the GNU General Public License as published by the Free
    2.11 + * Software Foundation, either version 3 of the License, or (at your option)
    2.12 + * any later version.
    2.13 + * 
    2.14 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    2.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    2.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    2.17 + *
    2.18 + * You should have received a copy of the GNU General Public License along with
    2.19 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    2.20 + */
    2.21 +#ifndef _include_jc_allocators_h_
    2.22 +#define _include_jc_allocators_h_
    2.23 +
    2.24 +#include <stdlib.h>
    2.25 +
    2.26 +namespace jc {
    2.27 +
    2.28 +class ZoneAllocatorPolicy
    2.29 +{
    2.30 +  protected:
    2.31 +    void reportOutOfMemory();
    2.32 +    void reportAllocationOverflow();
    2.33 +
    2.34 +  public:
    2.35 +    void free(void *memory) {
    2.36 +        ::free(memory);
    2.37 +    }
    2.38 +    void *malloc(size_t bytes) {
    2.39 +        void *ptr = ::malloc(bytes);
    2.40 +        if (!ptr)
    2.41 +            reportOutOfMemory();
    2.42 +        return ptr;
    2.43 +    }
    2.44 +};
    2.45 +
    2.46 +}
    2.47 +
    2.48 +#endif // _include_jc_allocators_h_
     3.1 --- a/jitcraft/BytecodeCompiler.cpp	Sat Jul 07 17:11:31 2012 -0700
     3.2 +++ b/jitcraft/BytecodeCompiler.cpp	Sat Jul 07 20:28:29 2012 -0700
     3.3 @@ -21,6 +21,7 @@
     3.4  #include "Modules.h"
     3.5  #include "Types.h"
     3.6  #include "Array.h"
     3.7 +#include "Strings.h"
     3.8  #include "Zone.h"
     3.9  #include "Heap-inl.h"
    3.10  
     4.1 --- a/jitcraft/FixedArray.h	Sat Jul 07 17:11:31 2012 -0700
     4.2 +++ b/jitcraft/FixedArray.h	Sat Jul 07 20:28:29 2012 -0700
     4.3 @@ -1,4 +1,5 @@
     4.4 -/*
     4.5 +/* vim: set ts=4 sw=4 tw=99 et
     4.6 + *
     4.7   * Copyright (C) 2012 David Anderson
     4.8   *
     4.9   * This file is part of JITCraft.
    4.10 @@ -62,11 +63,6 @@
    4.11  {
    4.12      uint32 length_;
    4.13  
    4.14 -  private:
    4.15 -    Object **vec() {
    4.16 -        return reinterpret_cast<Object **>(this + 1);
    4.17 -    }
    4.18 -
    4.19    public:
    4.20      static ByteArray *New(Zone *zone, unsigned length, Heap::Tenure tenure = Heap::Tenure_Default);
    4.21  
    4.22 @@ -78,7 +74,7 @@
    4.23      }
    4.24  
    4.25      static size_t SizeFor(unsigned length) {
    4.26 -        return sizeof(FixedArray) + sizeof(uint8) * length;
    4.27 +        return Align(sizeof(ByteArray) + sizeof(uint8) * length, kObjectAlignment);
    4.28      }
    4.29  
    4.30      static inline ByteArray *cast(Object *obj) {
     5.1 --- a/jitcraft/Handles.h	Sat Jul 07 17:11:31 2012 -0700
     5.2 +++ b/jitcraft/Handles.h	Sat Jul 07 20:28:29 2012 -0700
     5.3 @@ -112,6 +112,9 @@
     5.4      Object * const *address() const {
     5.5          return (Object * const *)&thing_;
     5.6      }
     5.7 +    T **ref() {
     5.8 +        return &thing_;
     5.9 +    }
    5.10      operator T *() {
    5.11          return thing_;
    5.12      }
     6.1 --- a/jitcraft/HashTable.h	Sat Jul 07 17:11:31 2012 -0700
     6.2 +++ b/jitcraft/HashTable.h	Sat Jul 07 20:28:29 2012 -0700
     6.3 @@ -1,23 +1,28 @@
     6.4 -// vim: set ts=4 sw=4 tw=99 et:
     6.5 -//
     6.6 -//  
     6.7 -// (C) Copyright 2010-2011 AlliedModders LLC
     6.8 -//
     6.9 -// Initial Author: David Anderson
    6.10 -// Contributors:
    6.11 -//
    6.12 -//
    6.13 -
    6.14 +/*
    6.15 + * Copyright (C) 2012 David Anderson
    6.16 + *
    6.17 + * This file is part of JITCraft.
    6.18 + *
    6.19 + * JITCraft is free software: you can redistribute it and/or modify it under
    6.20 + * the terms of the GNU General Public License as published by the Free
    6.21 + * Software Foundation, either version 3 of the License, or (at your option)
    6.22 + * any later version.
    6.23 + * 
    6.24 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    6.25 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    6.26 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    6.27 + *
    6.28 + * You should have received a copy of the GNU General Public License along with
    6.29 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    6.30 + */
    6.31  #ifndef _INCLUDE_KEIMA_HASHTABLE_H_
    6.32  #define _INCLUDE_KEIMA_HASHTABLE_H_
    6.33  
    6.34  #include <new>
    6.35  #include <limits.h>
    6.36 -#include "Object.h"
    6.37 -#include "vm/Array.h"
    6.38 -#include "Environment.h"
    6.39 +#include "Utility.h"
    6.40  
    6.41 -namespace ke {
    6.42 +namespace jc {
    6.43  
    6.44  template <typename T>
    6.45  class HashTableEntry
    6.46 @@ -38,9 +43,10 @@
    6.47      }
    6.48      void setRemoved() {
    6.49          hash_ = kRemovedHash;
    6.50 -        destruct();
    6.51 +        t_ = T();
    6.52      }
    6.53      void construct() {
    6.54 +        hash_ = kFreeHash;
    6.55          new (&t_) T();
    6.56      }
    6.57      void destruct() {
    6.58 @@ -66,6 +72,8 @@
    6.59  template <typename HashPolicy, typename AllocPolicy>
    6.60  class HashTable : public AllocPolicy
    6.61  {
    6.62 +    friend class iterator;
    6.63 +
    6.64      typedef typename HashPolicy::Payload Payload;
    6.65      typedef HashTableEntry<Payload> Entry;
    6.66  
    6.67 @@ -73,6 +81,7 @@
    6.68      uint32 nelements_;
    6.69      uint32 ndeleted_;
    6.70      Entry *table_;
    6.71 +    uint32 minCapacity_;
    6.72  
    6.73    private:
    6.74      static const uint32 kMinCapacity = 16;
    6.75 @@ -88,7 +97,7 @@
    6.76      }
    6.77  
    6.78      Entry *createTable(uint32 capacity) {
    6.79 -        KE_ASSERT(capacity <= kMaxCapacity);
    6.80 +        assert(capacity <= kMaxCapacity);
    6.81  
    6.82          Entry *table = (Entry *)this->malloc(capacity * sizeof(Entry));
    6.83          if (!table)
    6.84 @@ -154,7 +163,7 @@
    6.85            : hash_(hash),
    6.86              capacity_(capacity)
    6.87          {
    6.88 -            KE_ASSERT(IsPowerOfTwo(capacity_)); 
    6.89 +            assert(IsPowerOfTwo(capacity_)); 
    6.90          }
    6.91  
    6.92          uint32 entry() const {
    6.93 @@ -176,11 +185,13 @@
    6.94      }
    6.95  
    6.96      bool shrink() {
    6.97 +        if ((capacity_ >> 1) < minCapacity_)
    6.98 +            return true;
    6.99          return changeCapacity(capacity_ >> 1);
   6.100      }
   6.101      
   6.102      bool grow() {
   6.103 -        KE_ASSERT(IsPowerOfTwo(kMaxCapacity));
   6.104 +        assert(IsPowerOfTwo(kMaxCapacity));
   6.105          if (capacity_ >= kMaxCapacity) {
   6.106              this->reportAllocationOverflow();
   6.107              return false;
   6.108 @@ -188,16 +199,8 @@
   6.109          return changeCapacity(capacity_ << 1);
   6.110      }
   6.111  
   6.112 -    bool checkDensity() {
   6.113 -        if (underloaded())
   6.114 -            return shrink(); 
   6.115 -        if (overloaded())
   6.116 -            return grow();
   6.117 -        return true;
   6.118 -    }
   6.119 -
   6.120      bool changeCapacity(uint32 newCapacity) {
   6.121 -        KE_ASSERT(newCapacity <= kMaxCapacity);
   6.122 +        assert(newCapacity <= kMaxCapacity);
   6.123  
   6.124          Entry *newTable = createTable(newCapacity);
   6.125          if (!newTable)
   6.126 @@ -219,7 +222,7 @@
   6.127              }
   6.128              oldEntry.destruct();
   6.129          }
   6.130 -        this->free(table_);
   6.131 +        this->free(oldTable);
   6.132  
   6.133          return true;
   6.134      }
   6.135 @@ -277,7 +280,7 @@
   6.136      }
   6.137  
   6.138      bool add(Insert &i) {
   6.139 -        KE_ASSERT(!i.found());
   6.140 +        assert(!i.found());
   6.141  
   6.142          // If the entry is deleted, just re-use the slot.
   6.143          if (i.entry().removed()) {
   6.144 @@ -310,13 +313,21 @@
   6.145          return true;
   6.146      }
   6.147  
   6.148 +    void remove(Entry &e) {
   6.149 +        assert(!e.isLive());
   6.150 +        e.setRemoved();
   6.151 +        ndeleted_++;
   6.152 +        nelements_--;
   6.153 +    }
   6.154 +
   6.155    public:
   6.156      HashTable(AllocPolicy ap)
   6.157        : AllocPolicy(ap),
   6.158          capacity_(0),
   6.159          nelements_(0),
   6.160          ndeleted_(0),
   6.161 -        table_(NULL)
   6.162 +        table_(NULL),
   6.163 +        minCapacity_(kMinCapacity)
   6.164      {
   6.165      }
   6.166  
   6.167 @@ -333,7 +344,9 @@
   6.168          else if (capacity > kMaxCapacity)
   6.169              capacity = kMaxCapacity;
   6.170  
   6.171 -        KE_ASSERT(IsPowerOfTwo(capacity));
   6.172 +        minCapacity_ = capacity;
   6.173 +
   6.174 +        assert(IsPowerOfTwo(capacity));
   6.175          capacity_ = capacity;
   6.176  
   6.177          table_ = createTable(capacity_);
   6.178 @@ -359,9 +372,52 @@
   6.179          *i = payload;
   6.180          return true;
   6.181      }
   6.182 +
   6.183 +    bool checkDensity() {
   6.184 +        if (underloaded())
   6.185 +            return shrink(); 
   6.186 +        if (overloaded())
   6.187 +            return grow();
   6.188 +        return true;
   6.189 +    }
   6.190 +
   6.191 +  public:
   6.192 +    class iterator
   6.193 +    {
   6.194 +        HashTable *table_;
   6.195 +        Entry *i_;
   6.196 +        Entry *end_;
   6.197 +
   6.198 +      public:
   6.199 +        iterator(HashTable *table)
   6.200 +          : table_(table),
   6.201 +            i_(table->table_),
   6.202 +            end_(table->table_ + table->capacity_)
   6.203 +        {
   6.204 +            while (i_ < end_ && !i_->isLive())
   6.205 +                i_++;
   6.206 +        }
   6.207 +
   6.208 +        bool empty() const {
   6.209 +            return i_ == end_;
   6.210 +        }
   6.211 +
   6.212 +        void erase() {
   6.213 +            assert(!empty());
   6.214 +            table_->remove(*i_);
   6.215 +        }
   6.216 +
   6.217 +        const Payload &operator *() const {
   6.218 +            return i_->payload();
   6.219 +        }
   6.220 +
   6.221 +        void next() {
   6.222 +            while (i_ < end_ && !i_->isLive())
   6.223 +                i_++;
   6.224 +        }
   6.225 +    };
   6.226  };
   6.227  
   6.228  }
   6.229  
   6.230  #endif // _INCLUDE_KEIMA_HASHTABLE_H_
   6.231 -
     7.1 --- a/jitcraft/Heap.cpp	Sat Jul 07 17:11:31 2012 -0700
     7.2 +++ b/jitcraft/Heap.cpp	Sat Jul 07 20:28:29 2012 -0700
     7.3 @@ -22,6 +22,7 @@
     7.4  #include "VirtualObjectVisitor.h"
     7.5  #include "ObjectVisitor.h"
     7.6  #include "Zone.h"
     7.7 +#include "StringPool.h"
     7.8  
     7.9  using namespace jc;
    7.10  
    7.11 @@ -351,6 +352,9 @@
    7.12  void
    7.13  Heap::sweep()
    7.14  {
    7.15 +    // Before destroying mark bits, sweep weak roots.
    7.16 +    zone_->symbols()->sweep();
    7.17 +
    7.18      // Note: we don't bother sweeping the LIFO space.
    7.19      SweepOldSpace(&mapSpace_);
    7.20      SweepOldSpace(&oldSpace_);
     8.1 --- a/jitcraft/NameBinding.cpp	Sat Jul 07 17:11:31 2012 -0700
     8.2 +++ b/jitcraft/NameBinding.cpp	Sat Jul 07 20:28:29 2012 -0700
     8.3 @@ -16,11 +16,12 @@
     8.4   * JITCraft. If not, see http://www.gnu.org/licenses/.
     8.5   */
     8.6  #include "NameBinding.h"
     8.7 +#include "Strings.h"
     8.8  #include "Zone.h"
     8.9  
    8.10  using namespace jc;
    8.11  
    8.12 -BoundName::BoundName(Scope *scope, Name *name, const SourcePosition &pos)
    8.13 +BoundName::BoundName(Scope *scope, Handle<String> name, const SourcePosition &pos)
    8.14    : scope_(scope),
    8.15      name_(name),
    8.16      type_(NULL),
    8.17 @@ -28,12 +29,12 @@
    8.18  {
    8.19  }
    8.20  
    8.21 -NamedFunction::NamedFunction(Scope *scope, Name *name, const SourcePosition &pos)
    8.22 +NamedFunction::NamedFunction(Scope *scope, Handle<String> name, const SourcePosition &pos)
    8.23    : BoundName(scope, name, pos)
    8.24  {
    8.25  }
    8.26  
    8.27 -Variable::Variable(Scope *scope, Name *name, const SourcePosition &pos)
    8.28 +Variable::Variable(Scope *scope, Handle<String> name, const SourcePosition &pos)
    8.29    : BoundName(scope, name, pos),
    8.30      location_(UNALLOCATED)
    8.31  {
     9.1 --- a/jitcraft/NameBinding.h	Sat Jul 07 17:11:31 2012 -0700
     9.2 +++ b/jitcraft/NameBinding.h	Sat Jul 07 20:28:29 2012 -0700
     9.3 @@ -19,7 +19,6 @@
     9.4  #define _include_name_binding_h_
     9.5  
     9.6  #include "PoolAllocator.h"
     9.7 -#include "StringPool.h"
     9.8  #include "Types.h"
     9.9  #include "Scanner.h"
    9.10  
    9.11 @@ -31,11 +30,12 @@
    9.12  class Type;
    9.13  class NamedEnum;
    9.14  class NamedConstant;
    9.15 +class String;
    9.16  
    9.17  class BoundName : public PoolObject
    9.18  {
    9.19      Scope *scope_;
    9.20 -    Name *name_;
    9.21 +    ScopedRoot<String> name_;
    9.22      ScopedRoot<Type> type_;
    9.23      SourcePosition pos_;
    9.24  
    9.25 @@ -47,11 +47,11 @@
    9.26        CONSTANT
    9.27      };
    9.28  
    9.29 -    BoundName(Scope *scope, Name *name, const SourcePosition &pos);
    9.30 +    BoundName(Scope *scope, Handle<String> name, const SourcePosition &pos);
    9.31  
    9.32      virtual Kind kind() const = 0;
    9.33  
    9.34 -    Name *name() const {
    9.35 +    String *name() const {
    9.36          return name_;
    9.37      }
    9.38      Scope *scope() const {
    9.39 @@ -85,7 +85,7 @@
    9.40      unsigned slot_;
    9.41  
    9.42    public:
    9.43 -    NamedFunction(Scope *scope, Name *name, const SourcePosition &pos);
    9.44 +    NamedFunction(Scope *scope, Handle<String> name, const SourcePosition &pos);
    9.45  
    9.46      Kind kind() const {
    9.47          return FUNCTION;
    9.48 @@ -101,7 +101,7 @@
    9.49  class NamedEnum : public BoundName
    9.50  {
    9.51    public:
    9.52 -    NamedEnum(Scope *scope, Name *name, const SourcePosition &pos)
    9.53 +    NamedEnum(Scope *scope, Handle<String> name, const SourcePosition &pos)
    9.54        : BoundName(scope, name, pos)
    9.55      {
    9.56      }
    9.57 @@ -117,7 +117,7 @@
    9.58      Type *type_;
    9.59  
    9.60    public:
    9.61 -    NamedConstant(Scope *scope, Name *name, const SourcePosition &pos)
    9.62 +    NamedConstant(Scope *scope, Handle<String> name, const SourcePosition &pos)
    9.63        : BoundName(scope, name, pos),
    9.64          type_(NULL)
    9.65      {
    9.66 @@ -147,7 +147,7 @@
    9.67          PARAMETER
    9.68      };
    9.69  
    9.70 -    Variable(Scope *scope, Name *name, const SourcePosition &pos);
    9.71 +    Variable(Scope *scope, Handle<String> name, const SourcePosition &pos);
    9.72  
    9.73      Kind kind() const {
    9.74          return VARIABLE;
    10.1 --- a/jitcraft/ObjectVisitor.h	Sat Jul 07 17:11:31 2012 -0700
    10.2 +++ b/jitcraft/ObjectVisitor.h	Sat Jul 07 20:28:29 2012 -0700
    10.3 @@ -27,6 +27,7 @@
    10.4  #include "Modules.h"
    10.5  #include "Functions.h"
    10.6  #include "Array.h"
    10.7 +#include "Strings.h"
    10.8  
    10.9  namespace jc {
   10.10  
   10.11 @@ -45,6 +46,7 @@
   10.12          visitField(obj, Type::offsetOfContained());
   10.13          visitField(obj, Type::offsetOfReturnType());
   10.14          visitField(obj, Type::offsetOfParameters());
   10.15 +        visitField(obj, Type::offsetOfTag());
   10.16          return sizeof(Type);
   10.17      }
   10.18  
   10.19 @@ -86,6 +88,10 @@
   10.20          return sizeof(Function);
   10.21      }
   10.22  
   10.23 +    size_t iterateString(Object *obj) {
   10.24 +        return String::SizeFor(String::cast(obj)->length());
   10.25 +    }
   10.26 +
   10.27      size_t iterateArray(Array *array, ArrayMap *map) {
   10.28          if (map->type()->isArray()) {
   10.29              unsigned length = array->nelements();
   10.30 @@ -117,7 +123,7 @@
   10.31              return iterateFixedArray(FixedArray::cast(obj));
   10.32  
   10.33            case MapKind_ByteArray:
   10.34 -            return Align(iterateByteArray(ByteArray::cast(obj)), kObjectAlignment);
   10.35 +            return iterateByteArray(ByteArray::cast(obj));
   10.36  
   10.37            case MapKind_Code:
   10.38              return iterateCode(obj);
   10.39 @@ -131,6 +137,9 @@
   10.40            case MapKind_Function:
   10.41              return iterateFunction(obj);
   10.42  
   10.43 +          case MapKind_String:
   10.44 +            return iterateString(obj);
   10.45 +
   10.46            case MapKind_Array:
   10.47              return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
   10.48  
   10.49 @@ -155,7 +164,7 @@
   10.50          return FixedArray::SizeFor(FixedArray::cast(obj)->length());
   10.51  
   10.52        case MapKind_ByteArray:
   10.53 -        return Align(ByteArray::SizeFor(ByteArray::cast(obj)->length()), kObjectAlignment);
   10.54 +        return ByteArray::SizeFor(ByteArray::cast(obj)->length());
   10.55  
   10.56        case MapKind_Code:
   10.57          return sizeof(Code);
   10.58 @@ -169,6 +178,9 @@
   10.59        case MapKind_Function:
   10.60          return sizeof(Function);
   10.61  
   10.62 +      case MapKind_String:
   10.63 +        return String::SizeFor(String::cast(obj)->length());
   10.64 +
   10.65        case MapKind_Array:
   10.66          return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
   10.67  
    11.1 --- a/jitcraft/Objects.h	Sat Jul 07 17:11:31 2012 -0700
    11.2 +++ b/jitcraft/Objects.h	Sat Jul 07 20:28:29 2012 -0700
    11.3 @@ -45,6 +45,7 @@
    11.4      MapKind_Reference,
    11.5      MapKind_Module,
    11.6      MapKind_Function,
    11.7 +    MapKind_String,
    11.8      MapKind_FreeRegion,     // Special map denoting freed space.
    11.9  
   11.10      // Used to represent Arrays. This does not have a canonical map.
    12.1 --- a/jitcraft/Opcodes.cpp	Sat Jul 07 17:11:31 2012 -0700
    12.2 +++ b/jitcraft/Opcodes.cpp	Sat Jul 07 20:28:29 2012 -0700
    12.3 @@ -16,11 +16,13 @@
    12.4   * You should have received a copy of the GNU General Public License along with
    12.5   * JITCraft. If not, see http://www.gnu.org/licenses/.
    12.6   */
    12.7 +#include <stdlib.h>
    12.8  #include "Opcodes.h"
    12.9  #include "Utility.h"
   12.10  #include "Code.h"
   12.11  #include "Zone.h"
   12.12  #include "Array.h"
   12.13 +#include "Strings.h"
   12.14  #include "Heap-inl.h"
   12.15  
   12.16  using namespace jc;
   12.17 @@ -186,7 +188,7 @@
   12.18            {
   12.19              ArrayMap *map = ArrayMap::cast(code->map(READ_UINT32(pc)));
   12.20              fprintf(fp, "%s:", map->type()->innermost()->tag()
   12.21 -                               ? map->type()->innermost()->tag()
   12.22 +                               ? map->type()->innermost()->tag()->chars()
   12.23                                 : "_");
   12.24              for (; map; map = map->contained()) {
   12.25                  Type *type = map->type();
    13.1 --- a/jitcraft/Parser.cpp	Sat Jul 07 17:11:31 2012 -0700
    13.2 +++ b/jitcraft/Parser.cpp	Sat Jul 07 20:28:29 2012 -0700
    13.3 @@ -20,14 +20,15 @@
    13.4  #include "Parser.h"
    13.5  #include "FixedArray.h"
    13.6  #include "Heap.h"
    13.7 +#include "Strings.h"
    13.8  #include "Heap-inl.h"
    13.9  
   13.10  using namespace jc;
   13.11  
   13.12 -Parser::Parser(CompileContext &cc, const char *stream, size_t length)
   13.13 -  : cc_(cc),
   13.14 -    pool_(ZONE()->pool()),
   13.15 -    strings_(pool_),
   13.16 +Parser::Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length)
   13.17 +  : zone_(zone),
   13.18 +    cc_(cc),
   13.19 +    pool_(zone_->pool()),
   13.20      scanner_(cc, stream, length),
   13.21      scope_(NULL),
   13.22      unbound_(NULL)
   13.23 @@ -64,7 +65,7 @@
   13.24  }
   13.25  
   13.26  NameProxy *
   13.27 -Parser::bind(Name *name)
   13.28 +Parser::bind(Handle<String> name)
   13.29  {
   13.30      BoundName *bound = scope_->lookup(name);
   13.31      NameProxy *proxy = new (pool_) NameProxy(scanner_.begin(), name, bound);
   13.32 @@ -74,22 +75,22 @@
   13.33  }
   13.34  
   13.35  bool
   13.36 -Parser::matchName(Name **name, TokenKind kind)
   13.37 +Parser::matchName(String **name, TokenKind kind)
   13.38  {
   13.39      assert(kind == TOK_NAME || kind == TOK_LABEL);
   13.40      *name = NULL;
   13.41      if (!match(kind))
   13.42          return false;
   13.43 -    *name = strings_.add(scanner_.literal());
   13.44 +    *name = zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
   13.45      return true;
   13.46  }
   13.47  
   13.48 -Name *
   13.49 +String *
   13.50  Parser::expectName()
   13.51  {
   13.52      if (!expect(TOK_NAME))
   13.53          return NULL;
   13.54 -    return strings_.add(scanner_.literal());
   13.55 +    return zone_->makeSymbol(scanner_.literal(), scanner_.literal_length());
   13.56  }
   13.57  
   13.58  void
   13.59 @@ -105,8 +106,9 @@
   13.60      switch (kind) {
   13.61        case TOK_NAME:
   13.62        {
   13.63 -        scanner_.scan();
   13.64 -        Name *name = strings_.add(scanner_.literal());
   13.65 +        Local<String> name(zone_, expectName());
   13.66 +        if (!name)
   13.67 +            return NULL;
   13.68          return bind(name);
   13.69        }
   13.70  
   13.71 @@ -127,10 +129,10 @@
   13.72        case TOK_STRING_LITERAL:
   13.73        {
   13.74          scanner_.scan();
   13.75 -        Local<ByteArray> array(ZONE(), ByteArray::New(ZONE(), scanner_.literal_length()));
   13.76 +        Local<ByteArray> array(zone_, ByteArray::New(zone_, scanner_.literal_length() + 1));
   13.77          if (!array)
   13.78              return NULL;
   13.79 -        memcpy(array->raw(), scanner_.literal(), scanner_.literal_length());
   13.80 +        memcpy(array->raw(), scanner_.literal(), scanner_.literal_length() + 1);
   13.81          return new (pool_) StringLiteral(scanner_.begin(), array);
   13.82        }
   13.83  
   13.84 @@ -562,11 +564,11 @@
   13.85      if (!expect(TOK_NEW))
   13.86          return NULL;
   13.87  
   13.88 -    Name *tag;
   13.89 -    if (matchName(&tag, TOK_LABEL) && !tag)
   13.90 +    Local<String> tag(zone_);
   13.91 +    if (matchName(tag.ref(), TOK_LABEL) && !tag)
   13.92          return NULL;
   13.93  
   13.94 -    Name *name = expectName();
   13.95 +    Local<String> name(zone_, expectName());
   13.96      if (!name)
   13.97          return NULL;
   13.98  
   13.99 @@ -785,9 +787,9 @@
  13.100  
  13.101      SourcePosition pos = scanner_.begin();
  13.102  
  13.103 -    Name *name = NULL;
  13.104 -    if (match(TOK_NAME)) {
  13.105 -        if ((name = strings_.add(scanner_.literal())) == NULL)
  13.106 +    Local<String> name(zone_);
  13.107 +    if (matchName(name.ref())) {
  13.108 +        if (!name)
  13.109              return NULL;
  13.110  
  13.111          if (BoundName *other = scope_->localLookup(name)) {
  13.112 @@ -808,7 +810,7 @@
  13.113          if (scanner_.peek() == TOK_RBRACE)
  13.114              break;
  13.115  
  13.116 -        Name *name = expectName();
  13.117 +        Local<String> name(zone_, expectName());
  13.118          if (!name)
  13.119              return NULL;
  13.120  
  13.121 @@ -838,7 +840,7 @@
  13.122  Statement *
  13.123  Parser::function()
  13.124  {
  13.125 -    Name *name = expectName();
  13.126 +    Local<String> name(zone_, expectName());
  13.127      if (!name)
  13.128          return NULL;
  13.129  
  13.130 @@ -867,7 +869,7 @@
  13.131          while (true) {
  13.132              bool ref = match(TOK_AMPERSAND);
  13.133  
  13.134 -            Name *name = expectName();
  13.135 +            Local<String> name(zone_, expectName());
  13.136              if (!name)
  13.137                  return NULL;
  13.138  
  13.139 @@ -879,7 +881,8 @@
  13.140              if (!arg)
  13.141                  return NULL;
  13.142  
  13.143 -            Parameter *parameter = new (pool_) Parameter(arg, NULL, ref);
  13.144 +            Local<String> tag(zone_);
  13.145 +            Parameter *parameter = new (pool_) Parameter(arg, tag, ref);
  13.146              parameters->push_back(parameter);
  13.147  
  13.148              if (!match(TOK_COMMA))
  13.149 @@ -966,7 +969,7 @@
  13.150  
  13.151      void visit(NameProxy *name) {
  13.152          prefix();
  13.153 -        fprintf(fp_, "[ NameProxy (%s)%s\n", name->name(),
  13.154 +        fprintf(fp_, "[ NameProxy (%s)%s\n", name->name()->chars(),
  13.155                  (name->binding() ? "" : " unbound"));
  13.156      }
  13.157      void visit(CallExpression *node) {
  13.158 @@ -980,7 +983,7 @@
  13.159      }
  13.160      void visit(FunctionStatement *node) {
  13.161          prefix();
  13.162 -        fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name());
  13.163 +        fprintf(fp_, "[ FunctionStatement (%s)\n", node->fun()->name()->chars());
  13.164          indent();
  13.165          node->body()->accept(this);
  13.166          unindent();
  13.167 @@ -1038,7 +1041,7 @@
  13.168      }
  13.169      void visit(VariableDeclaration *node) {
  13.170          prefix();
  13.171 -        fprintf(fp_, "[ VariableDeclaration (%s)\n", node->variable()->name());
  13.172 +        fprintf(fp_, "[ VariableDeclaration (%s)\n", node->variable()->name()->chars());
  13.173          indent();
  13.174          if (node->initialization())
  13.175              node->initialization()->accept(this);
  13.176 @@ -1071,11 +1074,11 @@
  13.177      }
  13.178      void visit(EnumStatement *node) {
  13.179          prefix();
  13.180 -        fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name() : "<anonymous>");
  13.181 +        fprintf(fp_, "[ EnumStatement (%s)\n", node->name() ? node->name()->chars() : "<anonymous>");
  13.182          indent();
  13.183          for (size_t i = 0; i < node->entries()->size(); i++) {
  13.184              prefix();
  13.185 -            fprintf(fp_, "%s =\n", node->entries()->at(i).name->name());
  13.186 +            fprintf(fp_, "%s =\n", node->entries()->at(i).name->name()->chars());
  13.187              if (node->entries()->at(i).expr) {
  13.188                  indent();
  13.189                  node->entries()->at(i).expr->accept(this);
    14.1 --- a/jitcraft/Parser.h	Sat Jul 07 17:11:31 2012 -0700
    14.2 +++ b/jitcraft/Parser.h	Sat Jul 07 20:28:29 2012 -0700
    14.3 @@ -21,17 +21,17 @@
    14.4  #include <stdio.h>
    14.5  #include <vector>
    14.6  #include "AST.h"
    14.7 -#include "StringPool.h"
    14.8  #include "Scanner.h"
    14.9  #include "Scopes.h"
   14.10 +#include "Strings.h"
   14.11  
   14.12  namespace jc {
   14.13  
   14.14  class Parser
   14.15  {
   14.16 +    Zone *zone_;
   14.17      CompileContext &cc_;
   14.18      PoolAllocator &pool_;
   14.19 -    StringPool strings_;
   14.20      Scanner scanner_;
   14.21      Scope *scope_;
   14.22      std::vector<NameProxy *> *unbound_;
   14.23 @@ -44,9 +44,9 @@
   14.24      Scope *enterScope(Scope::Kind kind);
   14.25  
   14.26      VariableDeclaration *variableDeclaration();
   14.27 -    bool matchName(Name **name, TokenKind kind = TOK_NAME);
   14.28 -    Name *expectName();
   14.29 -    NameProxy *bind(Name *name);
   14.30 +    bool matchName(String **name, TokenKind kind = TOK_NAME);
   14.31 +    String *expectName();
   14.32 +    NameProxy *bind(Handle<String> name);
   14.33      Expression *primitive();
   14.34      Expression *call(Expression *callee);
   14.35      Expression *index(Expression *left);
   14.36 @@ -77,7 +77,7 @@
   14.37      Statement *returnStatement();
   14.38  
   14.39    public:
   14.40 -    Parser(CompileContext &cc, const char *stream, size_t length);
   14.41 +    Parser(Zone *zone, CompileContext &cc, const char *stream, size_t length);
   14.42  
   14.43      ParseTree *parse();
   14.44  };
    15.1 --- a/jitcraft/Scanner.h	Sat Jul 07 17:11:31 2012 -0700
    15.2 +++ b/jitcraft/Scanner.h	Sat Jul 07 20:28:29 2012 -0700
    15.3 @@ -72,7 +72,7 @@
    15.4          return literal_.c_str();
    15.5      }
    15.6      size_t literal_length() const {
    15.7 -        return literal_.size() + 1;
    15.8 +        return literal_.size();
    15.9      }
   15.10  };
   15.11  
    16.1 --- a/jitcraft/Scopes.cpp	Sat Jul 07 17:11:31 2012 -0700
    16.2 +++ b/jitcraft/Scopes.cpp	Sat Jul 07 20:28:29 2012 -0700
    16.3 @@ -20,6 +20,7 @@
    16.4  #include "Zone.h"
    16.5  #include "Types.h"
    16.6  #include "TypeManager.h"
    16.7 +#include "Strings.h"
    16.8  
    16.9  using namespace jc;
   16.10  
   16.11 @@ -65,7 +66,7 @@
   16.12  }
   16.13  
   16.14  BoundName *
   16.15 -Scope::localLookup(Name *name)
   16.16 +Scope::localLookup(Handle<String> name)
   16.17  {
   16.18      for (size_t i = 0; i < names_.size(); i++) {
   16.19          if (names_[i]->name() == name)
   16.20 @@ -75,7 +76,7 @@
   16.21  }
   16.22  
   16.23  BoundName *
   16.24 -Scope::lookup(Name *name)
   16.25 +Scope::lookup(Handle<String> name)
   16.26  {
   16.27      for (Scope *scope = this; scope; scope = scope->enclosing()) {
   16.28          if (BoundName *bound = scope->localLookup(name))
   16.29 @@ -85,7 +86,7 @@
   16.30  }
   16.31  
   16.32  Variable *
   16.33 -Scope::declareVariable(Name *name, const SourcePosition &pos)
   16.34 +Scope::declareVariable(Handle<String> name, const SourcePosition &pos)
   16.35  {
   16.36      assert(!localLookup(name));
   16.37      
   16.38 @@ -95,7 +96,7 @@
   16.39  }
   16.40  
   16.41  Variable *
   16.42 -Scope::declareArgument(Name *name, const SourcePosition &pos)
   16.43 +Scope::declareArgument(Handle<String> name, const SourcePosition &pos)
   16.44  {
   16.45      assert(kind() == FUNCTION);
   16.46      Variable *var = declareVariable(name, pos);
   16.47 @@ -105,7 +106,7 @@
   16.48  }
   16.49  
   16.50  NamedFunction *
   16.51 -Scope::declareFunction(Name *name, const SourcePosition &pos)
   16.52 +Scope::declareFunction(Handle<String> name, const SourcePosition &pos)
   16.53  {
   16.54      assert(!localLookup(name));
   16.55      assert(kind() == GLOBAL);
   16.56 @@ -116,7 +117,7 @@
   16.57  }
   16.58  
   16.59  NamedEnum *
   16.60 -Scope::declareEnum(Name *name, const SourcePosition &pos)
   16.61 +Scope::declareEnum(Handle<String> name, const SourcePosition &pos)
   16.62  {
   16.63      NamedEnum *e = new (pool_) NamedEnum(this, name, pos);
   16.64      names_.push_back(e);
   16.65 @@ -124,7 +125,7 @@
   16.66  }
   16.67  
   16.68  NamedConstant *
   16.69 -Scope::declareConstant(Name *name, const SourcePosition &pos)
   16.70 +Scope::declareConstant(Handle<String> name, const SourcePosition &pos)
   16.71  {
   16.72      NamedConstant *constant = new (pool_) NamedConstant(this, name, pos);
   16.73      names_.push_back(constant);
   16.74 @@ -190,15 +191,17 @@
   16.75  bool
   16.76  Scope::Bind(ParseTree *tree)
   16.77  {
   16.78 +    Local<String> name(ZONE());
   16.79      for (size_t i = 0; i < tree->unbound()->size(); i++) {
   16.80          NameProxy *proxy = tree->unbound()->at(i);
   16.81 -        BoundName *name = tree->scope()->lookup(proxy->name());
   16.82 -        if (!name) {
   16.83 +        name = proxy->name();
   16.84 +        BoundName *binding = tree->scope()->lookup(name);
   16.85 +        if (!binding) {
   16.86              assert(false);
   16.87              return false;
   16.88          }
   16.89  
   16.90 -        proxy->bind(name);
   16.91 +        proxy->bind(binding);
   16.92      }
   16.93      return true;
   16.94  }
   16.95 @@ -227,6 +230,7 @@
   16.96      if (!type)
   16.97          return;
   16.98  
   16.99 -    lifoSlot_ = new (pool_) Variable(this, NULL, SourcePosition());
  16.100 +    Local<String> name(ZONE());
  16.101 +    lifoSlot_ = new (pool_) Variable(this, name, SourcePosition());
  16.102      lifoSlot_->setType(type);
  16.103  }
    17.1 --- a/jitcraft/Scopes.h	Sat Jul 07 17:11:31 2012 -0700
    17.2 +++ b/jitcraft/Scopes.h	Sat Jul 07 20:28:29 2012 -0700
    17.3 @@ -79,14 +79,14 @@
    17.4      void setUsesLifoHeap();
    17.5  
    17.6      Scope *unlinkIfEmpty();
    17.7 -    BoundName *localLookup(Name *name);
    17.8 -    BoundName *lookup(Name *name);
    17.9 +    BoundName *localLookup(Handle<String> name);
   17.10 +    BoundName *lookup(Handle<String> name);
   17.11  
   17.12 -    NamedFunction *declareFunction(Name *name, const SourcePosition &pos);
   17.13 -    Variable *declareVariable(Name *name, const SourcePosition &pos);
   17.14 -    Variable *declareArgument(Name *name, const SourcePosition &pos);
   17.15 -    NamedEnum *declareEnum(Name *name, const SourcePosition &pos);
   17.16 -    NamedConstant *declareConstant(Name *name, const SourcePosition &pos);
   17.17 +    NamedFunction *declareFunction(Handle<String> name, const SourcePosition &pos);
   17.18 +    Variable *declareVariable(Handle<String> name, const SourcePosition &pos);
   17.19 +    Variable *declareArgument(Handle<String> name, const SourcePosition &pos);
   17.20 +    NamedEnum *declareEnum(Handle<String> name, const SourcePosition &pos);
   17.21 +    NamedConstant *declareConstant(Handle<String> name, const SourcePosition &pos);
   17.22  
   17.23      void allocate(Variable *var);
   17.24      void allocate();
    18.1 --- a/jitcraft/SemanticAnalysis.cpp	Sat Jul 07 17:11:31 2012 -0700
    18.2 +++ b/jitcraft/SemanticAnalysis.cpp	Sat Jul 07 20:28:29 2012 -0700
    18.3 @@ -22,6 +22,7 @@
    18.4  #include "TypeManager.h"
    18.5  #include "Scopes.h"
    18.6  #include "Heap-inl.h"
    18.7 +#include "Strings.h"
    18.8  
    18.9  using namespace jc;
   18.10  
   18.11 @@ -158,6 +159,7 @@
   18.12      return expression->type();
   18.13  }
   18.14  
   18.15 +// :TODO: this leaks an interior pointer.
   18.16  static inline const char *
   18.17  GetTypeName(Type *type)
   18.18  {
   18.19 @@ -168,7 +170,7 @@
   18.20      if (type->isReference())
   18.21          type = type->contained();
   18.22      if (type->tag())
   18.23 -        return type->tag();
   18.24 +        return type->tag()->chars();
   18.25      return "int";
   18.26  }
   18.27  
   18.28 @@ -388,7 +390,8 @@
   18.29  void
   18.30  SemanticAnalysis::visit(VariableDeclaration *node)
   18.31  {
   18.32 -    Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(node->tag()));
   18.33 +    Local<String> tag(zone_, node->tag());
   18.34 +    Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   18.35      if (!type)
   18.36          return;
   18.37  
   18.38 @@ -528,7 +531,8 @@
   18.39      for (size_t i = 0; i < node->parameters()->size(); i++) {
   18.40          Parameter *parameter = node->parameters()->at(i);
   18.41          
   18.42 -        Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(parameter->tag()));
   18.43 +        Local<String> tag(zone_, parameter->tag());
   18.44 +        Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   18.45          if (!type)
   18.46              return false;
   18.47  
   18.48 @@ -617,8 +621,9 @@
   18.49      }
   18.50  
   18.51      if (given->primitive() != actual->primitive()) {
   18.52 -        const char *givenTag = given->tag() ? given->tag() : "_";
   18.53 -        const char *actualTag = given->tag() ? given->tag() : "_";
   18.54 +        // :TODO: leaks an interior pointer.
   18.55 +        const char *givenTag = given->tag() ? given->tag()->chars() : "_";
   18.56 +        const char *actualTag = given->tag() ? given->tag()->chars() : "_";
   18.57          cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
   18.58          return false;
   18.59      }
   18.60 @@ -652,8 +657,9 @@
   18.61      }
   18.62      
   18.63      if (given->primitive() != actual->primitive()) {
   18.64 -        const char *givenTag = given->tag() ? given->tag() : "_";
   18.65 -        const char *actualTag = given->tag() ? given->tag() : "_";
   18.66 +        // :TODO: leaks an interior pointer
   18.67 +        const char *givenTag = given->tag() ? given->tag()->chars() : "_";
   18.68 +        const char *actualTag = given->tag() ? given->tag()->chars() : "_";
   18.69          cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
   18.70          return false;
   18.71      }
   18.72 @@ -746,11 +752,11 @@
   18.73  SemanticAnalysis::visit(EnumStatement *node)
   18.74  {
   18.75      // Forbid the blessed types.
   18.76 -    Name *tag = node->name();
   18.77 -    if (!strcmp(tag, "Float") ||
   18.78 -        !strcmp(tag, "String") ||
   18.79 -        !strcmp(tag, "any") ||
   18.80 -        !strcmp(tag, "bool"))
   18.81 +    Local<String> tag(zone_, node->name());
   18.82 +    if (!strcmp(tag->chars(), "Float") ||
   18.83 +        !strcmp(tag->chars(), "String") ||
   18.84 +        !strcmp(tag->chars(), "any") ||
   18.85 +        !strcmp(tag->chars(), "bool"))
   18.86      {
   18.87          cc_.reportError(node->pos(), Message_InvalidEnumName);
   18.88          return;
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/jitcraft/StringPool.cpp	Sat Jul 07 20:28:29 2012 -0700
    19.3 @@ -0,0 +1,69 @@
    19.4 +/*
    19.5 + * Copyright (C) 2012 David Anderson
    19.6 + *
    19.7 + * This file is part of JITCraft.
    19.8 + *
    19.9 + * JITCraft is free software: you can redistribute it and/or modify it under
   19.10 + * the terms of the GNU General Public License as published by the Free
   19.11 + * Software Foundation, either version 3 of the License, or (at your option)
   19.12 + * any later version.
   19.13 + * 
   19.14 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   19.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   19.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   19.17 + *
   19.18 + * You should have received a copy of the GNU General Public License along with
   19.19 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   19.20 + */
   19.21 +#include "StringPool.h"
   19.22 +#include "Strings.h"
   19.23 +#include "Spaces.h"
   19.24 +
   19.25 +using namespace jc;
   19.26 +
   19.27 +StringPool::StringPool(Zone *zone)
   19.28 +  : zone_(zone),
   19.29 +    set_(ZoneAllocatorPolicy())
   19.30 +{
   19.31 +}
   19.32 +
   19.33 +StringPool::~StringPool()
   19.34 +{
   19.35 +}
   19.36 +
   19.37 +bool
   19.38 +StringPool::initialize()
   19.39 +{
   19.40 +    if (!set_.init(32))
   19.41 +        return false;
   19.42 +    return true;
   19.43 +}
   19.44 +
   19.45 +String *
   19.46 +StringPool::add(const char *str, size_t length)
   19.47 +{
   19.48 +    StringSet::Insert i = set_.findForAdd(CharsAndLength(str, length));
   19.49 +    if (i.found())
   19.50 +        return *i;
   19.51 +
   19.52 +    String *obj = String::New(zone_, str, length, Heap::Tenure_Old);
   19.53 +    if (!obj)
   19.54 +        return NULL;
   19.55 +
   19.56 +    set_.add(i, obj);
   19.57 +    return obj;
   19.58 +}
   19.59 +
   19.60 +void
   19.61 +StringPool::sweep()
   19.62 +{
   19.63 +    for (StringSet::iterator i(&set_); !i.empty(); i.next()) {
   19.64 +        String *obj = *i;
   19.65 +        MarkBit bits = HeapChunk::GetMarkBit(obj);
   19.66 +        if (HeapChunk::IsWhite(bits))
   19.67 +            i.erase();
   19.68 +        else
   19.69 +            assert(HeapChunk::IsBlack(bits));
   19.70 +    }
   19.71 +    set_.checkDensity();
   19.72 +}
    20.1 --- a/jitcraft/StringPool.h	Sat Jul 07 17:11:31 2012 -0700
    20.2 +++ b/jitcraft/StringPool.h	Sat Jul 07 20:28:29 2012 -0700
    20.3 @@ -18,37 +18,66 @@
    20.4  #ifndef _include_jitcraft_string_pool_h_
    20.5  #define _include_jitcraft_string_pool_h_
    20.6  
    20.7 -#include <vector>
    20.8 -#include <string.h>
    20.9 -#include "PoolAllocator.h"
   20.10 +#include "AllocatorPolicies.h"
   20.11 +#include "HashTable.h"
   20.12 +#include "Strings.h"
   20.13  
   20.14  namespace jc {
   20.15  
   20.16 -typedef const char Name;
   20.17 +class Zone;
   20.18 +class String;
   20.19  
   20.20 -// Guarantee that strings with the same contents will map to one pointer. The
   20.21 -// strings are pool allocated, and search is linear for simplicity.
   20.22 +// Guarantee that strings with the same contents will map to one pointer. 
   20.23  class StringPool
   20.24  {
   20.25 -    PoolAllocator &pool_;
   20.26 -    std::vector<Name *> strings_;
   20.27 +    class CharsAndLength {
   20.28 +        const char *str_;
   20.29 +        size_t length_;
   20.30 +
   20.31 +      public:
   20.32 +        CharsAndLength(const char *str, size_t length)
   20.33 +          : str_(str),
   20.34 +            length_(length)
   20.35 +        {
   20.36 +        }
   20.37 +
   20.38 +        const char *str() const {
   20.39 +            return str_;
   20.40 +        }
   20.41 +        size_t length() const {
   20.42 +            return length_;
   20.43 +        }
   20.44 +    };
   20.45 +
   20.46 +    struct Policy
   20.47 +    {
   20.48 +        typedef String * Payload;
   20.49 +
   20.50 +        static uint32 hash(const CharsAndLength &key) {
   20.51 +            return HashCharSequence(key.str(), key.length());
   20.52 +        }
   20.53 +        
   20.54 +        static bool matches(const CharsAndLength &key, String *string) {
   20.55 +            if (string->length() != key.length())
   20.56 +                return false;
   20.57 +            return memcmp(string->chars(), key.str(), key.length() * sizeof(char)) == 0;
   20.58 +        }
   20.59 +    };
   20.60 +
   20.61 +    typedef HashTable<Policy, ZoneAllocatorPolicy> StringSet;
   20.62  
   20.63    public:
   20.64 -    StringPool(PoolAllocator &pool)
   20.65 -      : pool_(pool)
   20.66 -    {
   20.67 -    }
   20.68 +    StringPool(Zone *zone);
   20.69 +    ~StringPool();
   20.70 +    bool initialize();
   20.71  
   20.72 -    Name *add(const char *string) {
   20.73 -        for (size_t i = 0; i < strings_.size(); i++) {
   20.74 -            if (strcmp(strings_[i], string) == 0)
   20.75 -                return strings_[i];
   20.76 -        }
   20.77 -        char *name = (char *)pool_.allocate(strlen(string) + 1);
   20.78 -        strcpy(name, string);
   20.79 -        strings_.push_back(name);
   20.80 -        return name;
   20.81 -    }
   20.82 +  public:
   20.83 +    String *add(const char *str, size_t len);
   20.84 +    void sweep();
   20.85 +
   20.86 +  private:
   20.87 +    Zone *zone_;
   20.88 +    StringSet set_;
   20.89  };
   20.90  
   20.91  }
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/jitcraft/Strings.cpp	Sat Jul 07 20:28:29 2012 -0700
    21.3 @@ -0,0 +1,43 @@
    21.4 +/* vim: set ts=4 sw=4 tw=99 et:
    21.5 + *
    21.6 + * Copyright (C) 2012 David Anderson
    21.7 + *
    21.8 + * This file is part of JITCraft.
    21.9 + *
   21.10 + * JITCraft is free software: you can redistribute it and/or modify it under
   21.11 + * the terms of the GNU General Public License as published by the Free
   21.12 + * Software Foundation, either version 3 of the License, or (at your option)
   21.13 + * any later version.
   21.14 + * 
   21.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   21.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   21.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   21.18 + *
   21.19 + * You should have received a copy of the GNU General Public License along with
   21.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   21.21 + */
   21.22 +#include "Strings.h"
   21.23 +#include "Zone.h"
   21.24 +#include "Heap-inl.h"
   21.25 +
   21.26 +using namespace jc;
   21.27 +
   21.28 +String *
   21.29 +String::New(Zone *zone, const char *from, Heap::Tenure tenure)
   21.30 +{
   21.31 +    return New(zone, from, strlen(from), tenure);
   21.32 +}
   21.33 +
   21.34 +String *
   21.35 +String::New(Zone *zone, const char *from, size_t length, Heap::Tenure tenure)
   21.36 +{
   21.37 +    size_t bytes = SizeFor(length);
   21.38 +    Local<String> string(zone, String::cast(zone->allocate(MapKind_String, bytes, tenure)));
   21.39 +    if (!string)
   21.40 +        return NULL;
   21.41 +
   21.42 +    string->length_ = length;
   21.43 +    memcpy(string->chars(), from, length + 1);
   21.44 +
   21.45 +    return string;
   21.46 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/jitcraft/Strings.h	Sat Jul 07 20:28:29 2012 -0700
    22.3 @@ -0,0 +1,54 @@
    22.4 +/* vim: set ts=4 sw=4 tw=99 et:
    22.5 + *
    22.6 + * Copyright (C) 2012 David Anderson
    22.7 + *
    22.8 + * This file is part of JITCraft.
    22.9 + *
   22.10 + * JITCraft is free software: you can redistribute it and/or modify it under
   22.11 + * the terms of the GNU General Public License as published by the Free
   22.12 + * Software Foundation, either version 3 of the License, or (at your option)
   22.13 + * any later version.
   22.14 + * 
   22.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   22.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   22.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   22.18 + *
   22.19 + * You should have received a copy of the GNU General Public License along with
   22.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   22.21 + */
   22.22 +#ifndef _include_jitcraft_string_h_
   22.23 +#define _include_jitcraft_string_h_
   22.24 +
   22.25 +#include "Heap.h"
   22.26 +
   22.27 +namespace jc {
   22.28 +
   22.29 +// A fixed-length string containing UTF-8 characters.
   22.30 +class String : public Object
   22.31 +{
   22.32 +    uint32 length_;
   22.33 +    
   22.34 +  public:
   22.35 +    static String *New(Zone *zone, const char *from, Heap::Tenure tenure = Heap::Tenure_Default);
   22.36 +    static String *New(Zone *zone, const char *from, size_t length, Heap::Tenure tenure = Heap::Tenure_Default);
   22.37 +
   22.38 +    unsigned length() {
   22.39 +        return length_;
   22.40 +    }
   22.41 +    char *chars() {
   22.42 +        return reinterpret_cast<char *>(this + 1);
   22.43 +    }
   22.44 +
   22.45 +    static size_t SizeFor(unsigned length) {
   22.46 +        return Align(sizeof(String) + sizeof(char) * (length + 1), kObjectAlignment);
   22.47 +    }
   22.48 +
   22.49 +    static inline String *cast(Object *obj) {
   22.50 +        assert(!obj || obj->is(MapKind_String));
   22.51 +        return reinterpret_cast<String *>(obj);
   22.52 +    }
   22.53 +};
   22.54 +
   22.55 +}
   22.56 +
   22.57 +#endif // _include_jitcraft_string_h_
    23.1 --- a/jitcraft/TypeManager.cpp	Sat Jul 07 17:11:31 2012 -0700
    23.2 +++ b/jitcraft/TypeManager.cpp	Sat Jul 07 20:28:29 2012 -0700
    23.3 @@ -19,6 +19,7 @@
    23.4  #include "Types.h"
    23.5  #include "TypeManager.h"
    23.6  #include "Zone.h"
    23.7 +#include "Strings.h"
    23.8  
    23.9  using namespace jc;
   23.10  
   23.11 @@ -31,13 +32,23 @@
   23.12  bool
   23.13  TypeManager::initialize()
   23.14  {
   23.15 -    if ((primitiveTypes_[PrimitiveType_Int32] = Type::NewPrimitive(zone_, NULL)) == NULL)
   23.16 +    Local<String> floatTag(zone_, zone_->makeSymbol("Float"));
   23.17 +    if (!floatTag)
   23.18 +        return false;
   23.19 +
   23.20 +    Local<String> stringTag(zone_, zone_->makeSymbol("String"));
   23.21 +    if (!stringTag)
   23.22          return false;
   23.23 -    if ((primitiveTypes_[PrimitiveType_Float] = Type::NewPrimitive(zone_, "Float")) == NULL)
   23.24 +
   23.25 +    Local<String> nullTag(zone_);
   23.26 +
   23.27 +    if ((primitiveTypes_[PrimitiveType_Int32] = Type::NewPrimitive(zone_, nullTag)) == NULL)
   23.28 +        return false;
   23.29 +    if ((primitiveTypes_[PrimitiveType_Float] = Type::NewPrimitive(zone_, floatTag)) == NULL)
   23.30          return false;
   23.31      if ((primitiveTypes_[PrimitiveType_Native] = Type::NewPrimitive(zone_, PrimitiveType_Native)) == NULL)
   23.32          return false;
   23.33 -    if ((primitiveTypes_[PrimitiveType_Char] = Type::NewPrimitive(zone_, "String")) == NULL)
   23.34 +    if ((primitiveTypes_[PrimitiveType_Char] = Type::NewPrimitive(zone_, stringTag)) == NULL)
   23.35          return false;
   23.36  
   23.37      Local<Type> type(zone_);
   23.38 @@ -51,13 +62,13 @@
   23.39  }
   23.40  
   23.41  Type *
   23.42 -TypeManager::getPrimitiveForTag(Name *tag)
   23.43 +TypeManager::getPrimitiveForTag(Handle<String> tag)
   23.44  {
   23.45 -    if (tag == NULL)
   23.46 +    if (!tag)
   23.47          return getPrimitive(PrimitiveType_Int32);
   23.48 -    if (strcmp(tag, "Float") == 0)
   23.49 +    if (strcmp(tag->chars(), "Float") == 0)
   23.50          return getPrimitive(PrimitiveType_Float);
   23.51 -    if (strcmp(tag, "String") == 0)
   23.52 +    if (strcmp(tag->chars(), "String") == 0)
   23.53          return getPrimitive(PrimitiveType_Char);
   23.54      return NULL;
   23.55  }
    24.1 --- a/jitcraft/TypeManager.h	Sat Jul 07 17:11:31 2012 -0700
    24.2 +++ b/jitcraft/TypeManager.h	Sat Jul 07 20:28:29 2012 -0700
    24.3 @@ -24,6 +24,8 @@
    24.4  
    24.5  namespace jc {
    24.6  
    24.7 +class String;
    24.8 +
    24.9  class TypeManager
   24.10  {
   24.11      Zone *zone_;
   24.12 @@ -37,7 +39,7 @@
   24.13  
   24.14      bool initialize();
   24.15  
   24.16 -    Type *getPrimitiveForTag(Name *tag);
   24.17 +    Type *getPrimitiveForTag(Handle<String>);
   24.18      Type *getPrimitive(PrimitiveType type) {
   24.19          return primitiveTypes_[type];
   24.20      }
    25.1 --- a/jitcraft/Types.cpp	Sat Jul 07 17:11:31 2012 -0700
    25.2 +++ b/jitcraft/Types.cpp	Sat Jul 07 20:28:29 2012 -0700
    25.3 @@ -17,12 +17,13 @@
    25.4   */
    25.5  #include "Types.h"
    25.6  #include "Zone.h"
    25.7 +#include "Strings.h"
    25.8  #include "Heap-inl.h"
    25.9  
   25.10  using namespace jc;
   25.11  
   25.12  Type *
   25.13 -Type::NewPrimitive(Zone *zone, Name *tag)
   25.14 +Type::NewPrimitive(Zone *zone, Handle<String> tag)
   25.15  {
   25.16      Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   25.17      if (!type)
   25.18 @@ -34,9 +35,9 @@
   25.19      type->returnType_ = NULL;
   25.20      type->parameters_ = NULL;
   25.21  
   25.22 -    if (tag && strcmp(tag, "Float") == 0)
   25.23 +    if (tag && strcmp(tag->chars(), "Float") == 0)
   25.24          type->primitive_ = PrimitiveType_Float;
   25.25 -    else if (tag && strcmp(tag, "String") == 0)
   25.26 +    else if (tag && strcmp(tag->chars(), "String") == 0)
   25.27          type->primitive_ = PrimitiveType_Char;
   25.28      else
   25.29          type->primitive_ = PrimitiveType_Int32;
    26.1 --- a/jitcraft/Types.h	Sat Jul 07 17:11:31 2012 -0700
    26.2 +++ b/jitcraft/Types.h	Sat Jul 07 20:28:29 2012 -0700
    26.3 @@ -19,13 +19,14 @@
    26.4  #ifndef _include_jc_types_h_
    26.5  #define _include_jc_types_h_
    26.6  
    26.7 -#include "StringPool.h"
    26.8  #include "Heap.h"
    26.9  #include "Barriers.h"
   26.10  #include "FixedArray.h"
   26.11  
   26.12  namespace jc {
   26.13  
   26.14 +class String;
   26.15 +
   26.16  enum PrimitiveType
   26.17  {
   26.18      PrimitiveType_Char,         // signed, 8-bit character
   26.19 @@ -53,7 +54,7 @@
   26.20      static const int UNKNOWN_SIZE = -1;
   26.21      static const size_t MAX_UNSAFE_ARRAY_DEPTH = 5;
   26.22      
   26.23 -    static Type *NewPrimitive(Zone *zone, Name *tag);
   26.24 +    static Type *NewPrimitive(Zone *zone, Handle<String> tag);
   26.25      static Type *NewPrimitive(Zone *zone, PrimitiveType type);
   26.26      static Type *NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst);
   26.27      static Type *NewReference(Zone *zone, Handle<Type> contained);
   26.28 @@ -92,7 +93,7 @@
   26.29          assert(isArray());
   26.30          return levels_;
   26.31      }
   26.32 -    Name *tag() {
   26.33 +    String *tag() {
   26.34          assert(isPrimitive());
   26.35          return tag_;
   26.36      }
   26.37 @@ -143,12 +144,15 @@
   26.38      static inline size_t offsetOfParameters() {
   26.39          return offsetof(Type, parameters_);
   26.40      }
   26.41 +    static inline size_t offsetOfTag() {
   26.42 +        return offsetof(Type, tag_);
   26.43 +    }
   26.44      // End GC Descriptor.
   26.45  
   26.46    private:
   26.47      Kind kind_;
   26.48      PrimitiveType primitive_;
   26.49 -    Name *tag_;
   26.50 +    Barriered<String> tag_;
   26.51  
   26.52      // Arrays only.
   26.53      int32 elements_;
    27.1 --- a/jitcraft/Utility.h	Sat Jul 07 17:11:31 2012 -0700
    27.2 +++ b/jitcraft/Utility.h	Sat Jul 07 20:28:29 2012 -0700
    27.3 @@ -70,6 +70,45 @@
    27.4      }
    27.5  };
    27.6  
    27.7 +// Bob Jenkin's one-at-a-time hash function[1].
    27.8 +//
    27.9 +// [1] http://burtleburtle.net/bob/hash/doobs.html
   27.10 +class CharacterStreamHasher
   27.11 +{
   27.12 +    uint32 hash;
   27.13 +
   27.14 +  public:
   27.15 +    CharacterStreamHasher()
   27.16 +      : hash(0)
   27.17 +    { }
   27.18 +
   27.19 +    void add(char c) {
   27.20 +        hash += c;
   27.21 +        hash += (hash << 10);
   27.22 +        hash ^= (hash >> 6);
   27.23 +    }
   27.24 +
   27.25 +    void add(const char *s, size_t length) {
   27.26 +        for (size_t i = 0; i < length; i++)
   27.27 +            add(s[i]);
   27.28 +    }
   27.29 +
   27.30 +    uint32 result() {
   27.31 +        hash += (hash << 3);
   27.32 +        hash ^= (hash >> 11);
   27.33 +        hash += (hash << 15);
   27.34 +        return hash;
   27.35 +    }
   27.36 +};
   27.37 +
   27.38 +static inline uint32
   27.39 +HashCharSequence(const char *s, size_t length)
   27.40 +{
   27.41 +    CharacterStreamHasher hasher;
   27.42 +    hasher.add(s, length);
   27.43 +    return hasher.result();
   27.44 +}
   27.45 +
   27.46  static inline size_t
   27.47  Log2(size_t number)
   27.48  {
    28.1 --- a/jitcraft/Zone.cpp	Sat Jul 07 17:11:31 2012 -0700
    28.2 +++ b/jitcraft/Zone.cpp	Sat Jul 07 20:28:29 2012 -0700
    28.3 @@ -17,7 +17,9 @@
    28.4   * JITCraft. If not, see http://www.gnu.org/licenses/.
    28.5   */
    28.6  #include "Zone.h"
    28.7 +#include "StringPool.h"
    28.8  #include "TypeManager.h"
    28.9 +#include "AllocatorPolicies.h"
   28.10  
   28.11  using namespace jc;
   28.12  
   28.13 @@ -30,6 +32,12 @@
   28.14  {
   28.15  }
   28.16  
   28.17 +Zone::~Zone()
   28.18 +{
   28.19 +    delete symbols_;
   28.20 +    delete types_;
   28.21 +}
   28.22 +
   28.23  bool
   28.24  Zone::initialize()
   28.25  {
   28.26 @@ -38,6 +46,10 @@
   28.27      if (!heap_.initialize())
   28.28          return false;
   28.29  
   28.30 +    symbols_ = new StringPool(this);
   28.31 +    if (!symbols_ || !symbols_->initialize())
   28.32 +        return false;
   28.33 +
   28.34      maps_[MapKind_Meta] = heap_.metaMap();
   28.35      if ((maps_[MapKind_Type] = allocateMap(MapKind_Type, sizeof(Map))) == NULL)
   28.36          return false;
   28.37 @@ -55,6 +67,8 @@
   28.38          return false;
   28.39      if ((maps_[MapKind_Function] = allocateMap(MapKind_Function, sizeof(Map))) == NULL)
   28.40          return false;
   28.41 +    if ((maps_[MapKind_String] = allocateMap(MapKind_String, sizeof(Map))) == NULL)
   28.42 +        return false;
   28.43      if ((maps_[MapKind_FreeRegion] = allocateMap(MapKind_FreeRegion, sizeof(Map))) == NULL)
   28.44          return false;
   28.45  
   28.46 @@ -94,3 +108,28 @@
   28.47      stack_.accept(visitor);
   28.48  }
   28.49  
   28.50 +String *
   28.51 +Zone::makeSymbol(const char *str, size_t length)
   28.52 +{
   28.53 +    return symbols_->add(str, length);
   28.54 +}
   28.55 +
   28.56 +String *
   28.57 +Zone::makeSymbol(const char *str)
   28.58 +{
   28.59 +    return makeSymbol(str, strlen(str));
   28.60 +}
   28.61 +
   28.62 +void
   28.63 +ZoneAllocatorPolicy::reportOutOfMemory()
   28.64 +{
   28.65 +    // :TODO: report
   28.66 +    assert(false);
   28.67 +}
   28.68 +
   28.69 +void
   28.70 +ZoneAllocatorPolicy::reportAllocationOverflow()
   28.71 +{
   28.72 +    // :TODO: report
   28.73 +    assert(false);
   28.74 +}
    29.1 --- a/jitcraft/Zone.h	Sat Jul 07 17:11:31 2012 -0700
    29.2 +++ b/jitcraft/Zone.h	Sat Jul 07 20:28:29 2012 -0700
    29.3 @@ -30,6 +30,8 @@
    29.4  namespace jc {
    29.5  
    29.6  class TypeManager;
    29.7 +class String;
    29.8 +class StringPool;
    29.9  
   29.10  class Zone
   29.11  {
   29.12 @@ -41,6 +43,7 @@
   29.13      Unbarriered<Map> maps_[MapKinds_Total];
   29.14  
   29.15      TypeManager *types_;
   29.16 +    StringPool *symbols_;
   29.17  
   29.18      // Root list.
   29.19      Local<Object> *lastLocalRoot_;
   29.20 @@ -48,6 +51,7 @@
   29.21  
   29.22    public:
   29.23      Zone();
   29.24 +    ~Zone();
   29.25      bool initialize();
   29.26  
   29.27      PoolAllocator &pool() {
   29.28 @@ -84,6 +88,12 @@
   29.29      RootScopeManager &rootScopes() {
   29.30          return rootScopes_;
   29.31      }
   29.32 +    StringPool *symbols() {
   29.33 +        return symbols_;
   29.34 +    }
   29.35 +
   29.36 +    String *makeSymbol(const char *string, size_t length);
   29.37 +    String *makeSymbol(const char *string);
   29.38  
   29.39      void accept(VirtualObjectVisitor *visitor);
   29.40  };
    30.1 --- a/jitcraft/jitcraft.vcxproj	Sat Jul 07 17:11:31 2012 -0700
    30.2 +++ b/jitcraft/jitcraft.vcxproj	Sat Jul 07 20:28:29 2012 -0700
    30.3 @@ -98,11 +98,14 @@
    30.4      <ClCompile Include="SemanticAnalysis.cpp" />
    30.5      <ClCompile Include="Spaces.cpp" />
    30.6      <ClCompile Include="Stack.cpp" />
    30.7 +    <ClCompile Include="StringPool.cpp" />
    30.8 +    <ClCompile Include="Strings.cpp" />
    30.9      <ClCompile Include="TypeManager.cpp" />
   30.10      <ClCompile Include="Types.cpp" />
   30.11      <ClCompile Include="Zone.cpp" />
   30.12    </ItemGroup>
   30.13    <ItemGroup>
   30.14 +    <ClInclude Include="AllocatorPolicies.h" />
   30.15      <ClInclude Include="Array.h" />
   30.16      <ClInclude Include="AST.h" />
   30.17      <ClInclude Include="Barriers.h" />
   30.18 @@ -134,6 +137,7 @@
   30.19      <ClInclude Include="Spaces-inl.h" />
   30.20      <ClInclude Include="Spaces.h" />
   30.21      <ClInclude Include="Stack.h" />
   30.22 +    <ClInclude Include="Strings.h" />
   30.23      <ClInclude Include="StringPool.h" />
   30.24      <ClInclude Include="TypeManager.h" />
   30.25      <ClInclude Include="Types.h" />
    31.1 --- a/jitcraft/main.cpp	Sat Jul 07 17:11:31 2012 -0700
    31.2 +++ b/jitcraft/main.cpp	Sat Jul 07 20:28:29 2012 -0700
    31.3 @@ -62,7 +62,7 @@
    31.4      RootScope roots(ZONE());
    31.5      CompileContext cc(ZONE());
    31.6  
    31.7 -    Parser parser(cc, stream, length);
    31.8 +    Parser parser(ZONE(), cc, stream, length);
    31.9      ParseTree *tree = parser.parse();
   31.10      if (!tree)
   31.11          return false;