Structure declaration support.
authorDavid Anderson <dvander@alliedmods.net>
Sat Aug 04 19:33:06 2012 -0700 (2012-08-04)
changeset 1479c544823d090
parent 146 dc7d3b7a918c
child 148 c0740249963c
Structure declaration support.
src/BytecodeCompiler.cpp
src/BytecodeEmitter.h
src/Environments.cpp
src/Environments.h
src/Interpreter.cpp
src/ObjectVisitor.h
src/Objects.h
src/Opcodes.cpp
src/Opcodes.tbl
src/SemanticAnalysis.cpp
src/Structures.cpp
src/Structures.h
src/TypeManager.cpp
src/TypeManager.h
src/Types.cpp
src/Types.h
src/Zone.cpp
     1.1 --- a/src/BytecodeCompiler.cpp	Sat Aug 04 17:51:43 2012 -0700
     1.2 +++ b/src/BytecodeCompiler.cpp	Sat Aug 04 19:33:06 2012 -0700
     1.3 @@ -758,12 +758,24 @@
     1.4              __ note_position(node->pos());
     1.5              __ arraycopy();
     1.6          }
     1.7 +    } else if (type->isStruct()) {
     1.8 +        Local<Map> map(zone_, type->newMap());
     1.9 +        if (var->scope()->kind() == Scope::GLOBAL)
    1.10 +            __ newstruct(map, Heap::Tenure_Old);
    1.11 +        else if (var->needsHeapAllocation())
    1.12 +            __ newstruct(map, Heap::Tenure_Default);
    1.13 +        else
    1.14 +            __ newstruct(map, Heap::Tenure_Stack);
    1.15      } else {
    1.16          if (node->initialization()) {
    1.17              node->initialization()->accept(this);
    1.18          } else {
    1.19 -            if (!node->postDimensions())
    1.20 +            if (type->isInt32OrEnum() || type->isBool()) {
    1.21                  __ int_(0);
    1.22 +            } else {
    1.23 +                assert(type->isFloat());
    1.24 +                __ float_(0);
    1.25 +            }
    1.26          }
    1.27      }
    1.28  
     2.1 --- a/src/BytecodeEmitter.h	Sat Aug 04 17:51:43 2012 -0700
     2.2 +++ b/src/BytecodeEmitter.h	Sat Aug 04 19:33:06 2012 -0700
     2.3 @@ -394,6 +394,23 @@
     2.4          }
     2.5      }
     2.6  
     2.7 +    void getfield(unsigned index, Type *type) {
     2.8 +        ensure(OP_GETFIELD_LENGTH);
     2.9 +        writeOp(OP_GETFIELD);
    2.10 +        writeUint32(index);
    2.11 +
    2.12 +        if (type->isTraceable())
    2.13 +            markOop(1);
    2.14 +    }
    2.15 +    void setfield(unsigned index, Type *type) {
    2.16 +        ensure(OP_SETFIELD_LENGTH);
    2.17 +        writeOp(OP_SETFIELD);
    2.18 +        writeUint32(index);
    2.19 +
    2.20 +        if (type->isTraceable())
    2.21 +            markOop(1);
    2.22 +    }
    2.23 +
    2.24      void getglobal(Variable *var) {
    2.25          ensure(OP_GETGLOBAL_F_LENGTH);
    2.26          if (var->type()->isPrimitive()) {
    2.27 @@ -454,6 +471,14 @@
    2.28          writeObject(map);
    2.29          markOop(1);
    2.30      }
    2.31 +    void newstruct(Handle<Map> map, Heap::Tenure tenure) {
    2.32 +        recordOops();
    2.33 +        ensure(OP_NEWSTRUCT_LENGTH);
    2.34 +        writeOp(OP_NEWSTRUCT);
    2.35 +        writeUint8(tenure);
    2.36 +        writeObject(map);
    2.37 +        markOop(1);
    2.38 +    }
    2.39      void savelifo(unsigned slot) {
    2.40          ensure(OP_SAVELIFO_LENGTH);
    2.41          writeOp(OP_SAVELIFO);
     3.1 --- a/src/Environments.cpp	Sat Aug 04 17:51:43 2012 -0700
     3.2 +++ b/src/Environments.cpp	Sat Aug 04 19:33:06 2012 -0700
     3.3 @@ -84,8 +84,8 @@
     3.4  
     3.5      // Allocate the actual map now.
     3.6      size_t bytesNeeded = sizeof(EnvironmentMap) + structure.traceableOffsetCount() * sizeof(unsigned);
     3.7 +
     3.8      Local<EnvironmentMap> map(zone);
     3.9 -    
    3.10      map = EnvironmentMap::cast(zone->allocateMap(MapKind_Environment, bytesNeeded, MapKind_MetaEnvironment));
    3.11      if (!map)
    3.12          return NULL;
     4.1 --- a/src/Environments.h	Sat Aug 04 17:51:43 2012 -0700
     4.2 +++ b/src/Environments.h	Sat Aug 04 19:33:06 2012 -0700
     4.3 @@ -135,9 +135,11 @@
     4.4          return slots_->at(slot);
     4.5      }
     4.6  
     4.7 +    // Begin GC descriptors.
     4.8      static inline size_t offsetOfSlots() {
     4.9          return OFFSETOF(EnvironmentMap, slots_);
    4.10      }
    4.11 +    // End GC descriptors.
    4.12  
    4.13      static inline EnvironmentMap *cast(Object *obj) {
    4.14          assert(!obj || obj->is(MapKind_MetaEnvironment));
     5.1 --- a/src/Interpreter.cpp	Sat Aug 04 17:51:43 2012 -0700
     5.2 +++ b/src/Interpreter.cpp	Sat Aug 04 19:33:06 2012 -0700
     5.3 @@ -25,6 +25,7 @@
     5.4  #include "Reference.h"
     5.5  #include "Strings.h"
     5.6  #include "Environments.h"
     5.7 +#include "Structures.h"
     5.8  #include "Heap-inl.h"
     5.9  
    5.10  using namespace ke;
    5.11 @@ -699,6 +700,17 @@
    5.12      break;
    5.13  }
    5.14  
    5.15 +case OP_NEWSTRUCT:
    5.16 +{
    5.17 +    Heap::Tenure tenure = (Heap::Tenure)top.pc[1];
    5.18 +    Local<StructMap> map(zone, StructMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1))));
    5.19 +    top.sp->obj = Struct::New(zone, map, tenure);
    5.20 +    if (!top.sp->obj)
    5.21 +        goto error;
    5.22 +    top.sp++;
    5.23 +    break;
    5.24 +}
    5.25 +
    5.26  case OP_SAVELIFO:
    5.27  {
    5.28      unsigned slot = READ_UINT32(top.pc);
     6.1 --- a/src/ObjectVisitor.h	Sat Aug 04 17:51:43 2012 -0700
     6.2 +++ b/src/ObjectVisitor.h	Sat Aug 04 19:33:06 2012 -0700
     6.3 @@ -143,6 +143,11 @@
     6.4          return map->size();
     6.5      }
     6.6  
     6.7 +    size_t iterateStructMap(StructMap *map) {
     6.8 +        visitField(map, StructMap::offsetOfType());
     6.9 +        return map->size();
    6.10 +    }
    6.11 +
    6.12      size_t iterateEnvironment(Environment *env) {
    6.13          EnvironmentMap *map = env->map();
    6.14          const unsigned *offsets = map->traceOffsets();
    6.15 @@ -152,6 +157,15 @@
    6.16          return env->size();
    6.17      }
    6.18  
    6.19 +    size_t iterateStruct(Struct *obj) {
    6.20 +        StructMap *map = obj->map();
    6.21 +        const unsigned *offsets = map->traceOffsets();
    6.22 +        unsigned noffsets = map->traceOffsetCount();
    6.23 +        for (unsigned i = 0; i < noffsets; i++)
    6.24 +            visitField(obj, Struct::offsetOfSlotOffset(offsets[i]));
    6.25 +        return obj->size();
    6.26 +    }
    6.27 +
    6.28    public:
    6.29      size_t iterate(Object *obj) {
    6.30          visitField(obj, Object::offsetOfMap());
    6.31 @@ -190,6 +204,9 @@
    6.32            case MapKind_Array:
    6.33              return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment);
    6.34  
    6.35 +          case MapKind_Struct:
    6.36 +            return iterateStruct(Struct::cast(obj));
    6.37 +
    6.38            case MapKind_EnvironmentSlotDescriptorArray:
    6.39              return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj));
    6.40  
    6.41 @@ -205,6 +222,9 @@
    6.42            case MapKind_MetaEnvironment:
    6.43              return iterateEnvironmentMap(EnvironmentMap::cast(obj));
    6.44  
    6.45 +          case MapKind_MetaStruct:
    6.46 +            return iterateStructMap(StructMap::cast(obj));
    6.47 +
    6.48            default:
    6.49              assert(map->kind() == MapKind_Meta);
    6.50              return sizeof(Map);
    6.51 @@ -249,6 +269,9 @@
    6.52        case MapKind_Array:
    6.53          return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
    6.54  
    6.55 +      case MapKind_Struct:
    6.56 +        return Struct::cast(obj)->size();
    6.57 +
    6.58        case MapKind_EnvironmentSlotDescriptorArray:
    6.59          return EnvironmentSlotDescriptorArray::cast(obj)->size();
    6.60  
    6.61 @@ -261,6 +284,9 @@
    6.62        case MapKind_MetaEnvironment:
    6.63          return EnvironmentMap::cast(obj)->size();
    6.64  
    6.65 +      case MapKind_MetaStruct:
    6.66 +        return StructMap::cast(obj)->size();
    6.67 +
    6.68        case MapKind_FreeRegion:
    6.69          return *reinterpret_cast<size_t *>(reinterpret_cast<Address>(obj + 1));
    6.70  
     7.1 --- a/src/Objects.h	Sat Aug 04 17:51:43 2012 -0700
     7.2 +++ b/src/Objects.h	Sat Aug 04 19:33:06 2012 -0700
     7.3 @@ -52,14 +52,16 @@
     7.4      MapKind_Environment,
     7.5      MapKind_Descriptor,
     7.6  
     7.7 -    // Used to represent Arrays. This does not have a canonical map.
     7.8 +    // These do not have canonical maps.
     7.9      MapKind_Array,
    7.10 +    MapKind_Struct,
    7.11  
    7.12      // These represent special Map subclasses that require special tracing.
    7.13      MapKinds_Special,
    7.14      MapKind_Meta,               // (default map class)
    7.15      MapKind_MetaArray,          // ArrayMap instances
    7.16      MapKind_MetaEnvironment,    // EnvironmentMap instances
    7.17 +    MapKind_MetaStruct,         // StructMap instances
    7.18      MapKinds_EndSpecial,
    7.19  
    7.20      MapKinds_Total
     8.1 --- a/src/Opcodes.cpp	Sat Aug 04 17:51:43 2012 -0700
     8.2 +++ b/src/Opcodes.cpp	Sat Aug 04 19:33:06 2012 -0700
     8.3 @@ -24,6 +24,7 @@
     8.4  #include "Array.h"
     8.5  #include "Strings.h"
     8.6  #include "CompactBuffer.h"
     8.7 +#include "Structures.h"
     8.8  #include "Heap-inl.h"
     8.9  
    8.10  using namespace ke;
    8.11 @@ -259,6 +260,18 @@
    8.12              break;
    8.13            }
    8.14  
    8.15 +          case OP_NEWSTRUCT:
    8.16 +          {
    8.17 +            Heap::Tenure tenure = (Heap::Tenure)pc[1];
    8.18 +            StructMap *map = StructMap::cast(code->map(READ_UINT32(pc + 1)));
    8.19 +            fprintf(fp, "%s", map->type()->name()->chars());
    8.20 +            if (tenure == Heap::Tenure_Stack)
    8.21 +                fprintf(fp, " ; lifo");
    8.22 +            else if (tenure == Heap::Tenure_Old)
    8.23 +                fprintf(fp, " ; pretenured");
    8.24 +            break;
    8.25 +          }
    8.26 +
    8.27            case OP_GETLOCAL:
    8.28            case OP_SETLOCAL:
    8.29            case OP_GETARG:
     9.1 --- a/src/Opcodes.tbl	Sat Aug 04 17:51:43 2012 -0700
     9.2 +++ b/src/Opcodes.tbl	Sat Aug 04 19:33:06 2012 -0700
     9.3 @@ -253,3 +253,16 @@
     9.4  OPDEF(OP_TRUE,          101,        "true",         1,      0, 1)
     9.5  OPDEF(OP_FALSE,         102,        "false",        1,      0, 1)
     9.6  
     9.7 +// Allocate a struct. The HeapTenure is stored as a byte following pc. The
     9.8 +// StructMap to use is specified as an index into the script's Map table.
     9.9 +//
    9.10 +// Format:
    9.11 +//  [u8 op] [u32 index]
    9.12 +OPDEF(OP_NEWSTRUCT,     103,        "newstruct",    6,      0, 1)
    9.13 +
    9.14 +// Sets or gets a property in a struct. The index of the field is specified as
    9.15 +// a 32-bit integer. Note that these opcodes follow a new style of deriving
    9.16 +// their types at runtime.
    9.17 +OPDEF(OP_GETFIELD,      104,        "getfield",     5,      1, 1)
    9.18 +OPDEF(OP_SETFIELD,      105,        "setfield",     5,      2, 1)
    9.19 +
    10.1 --- a/src/SemanticAnalysis.cpp	Sat Aug 04 17:51:43 2012 -0700
    10.2 +++ b/src/SemanticAnalysis.cpp	Sat Aug 04 19:33:06 2012 -0700
    10.3 @@ -160,7 +160,10 @@
    10.4  
    10.5              enumstmt->decl()->setType(type);
    10.6          } else if (statement->isStructureStatement()) {
    10.7 -            statement->accept(this);
    10.8 +            StructureStatement *node = statement->toStructureStatement();
    10.9 +            node->accept(this);
   10.10 +            if (!node->decl()->type())
   10.11 +                return false;
   10.12          }
   10.13      }
   10.14  
   10.15 @@ -285,7 +288,7 @@
   10.16          return "function";
   10.17      if (type->isVoid())
   10.18          return "void";
   10.19 -    if (type->isEnum())
   10.20 +    if (type->isEnum() || type->isStruct())
   10.21          return type->name()->chars();
   10.22      if (type->isReference())
   10.23          type = type->contained();
   10.24 @@ -782,12 +785,6 @@
   10.25              if (check)
   10.26                  check = check->contained();
   10.27          }
   10.28 -
   10.29 -        // If this variable is stack allocated, we could use the LIFO heap
   10.30 -        // to allocate it. If that's the case, make sure to reserve a slot
   10.31 -        // so we can unwind the LIFO heap at the end of this scope.
   10.32 -        if (!node->variable()->needsHeapAllocation())
   10.33 -            scope_->setUsesLifoHeap();
   10.34      } else {
   10.35          if (node->initialization()) {
   10.36              Local<Type> right(zone_, visitForLoad(node->initialization()));
   10.37 @@ -796,12 +793,21 @@
   10.38              if (!typeCheckAssignment(node, type, right, true))
   10.39                  return;
   10.40          }
   10.41 -        if (type->primitive() == PrimitiveType_Char) {
   10.42 +
   10.43 +        if (type->isPrimitive() && type->primitive() == PrimitiveType_Char) {
   10.44              cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
   10.45              return;
   10.46          }
   10.47      }
   10.48  
   10.49 +    // If this variable is stack allocated, we could use the LIFO heap
   10.50 +    // to allocate it. If that's the case, make sure to reserve a slot
   10.51 +    // so we can unwind the LIFO heap at the end of this scope.
   10.52 +    if (!node->variable()->needsHeapAllocation()) {
   10.53 +        if (type->isArray() || type->isStruct())
   10.54 +            scope_->setUsesLifoHeap();
   10.55 +    }
   10.56 +
   10.57      node->variable()->setType(type);
   10.58  }
   10.59  
   10.60 @@ -1245,11 +1251,16 @@
   10.61          desctable->set(zone_, i, desc);
   10.62      }
   10.63  
   10.64 +    Local<StructMap> map(zone_, StructMap::New(zone_, builder));
   10.65 +    if (!map)
   10.66 +        return;
   10.67 +
   10.68      name = node->decl()->name();
   10.69 -    type = zone_->types()->newStruct(name, desctable);
   10.70 +    type = zone_->types()->newStruct(name, desctable, map);
   10.71      if (!type)
   10.72          return;
   10.73  
   10.74 +    map->setType(type);
   10.75      node->decl()->setType(type);
   10.76  }
   10.77  
    11.1 --- a/src/Structures.cpp	Sat Aug 04 17:51:43 2012 -0700
    11.2 +++ b/src/Structures.cpp	Sat Aug 04 19:33:06 2012 -0700
    11.3 @@ -16,6 +16,7 @@
    11.4   * You should have received a copy of the GNU General Public License along with
    11.5   * SourcePawn. If not, see http://www.gnu.org/licenses/.
    11.6   */
    11.7 +#include <string.h>
    11.8  #include "Structures.h"
    11.9  #include "Zone.h"
   11.10  #include "Types.h"
   11.11 @@ -62,3 +63,35 @@
   11.12      return desc;
   11.13  }
   11.14  
   11.15 +StructMap *
   11.16 +StructMap::New(Zone *zone, const StructureBufferBuilder &builder)
   11.17 +{
   11.18 +    size_t bytesNeeded = sizeof(StructMap) +
   11.19 +                         (builder.traceableOffsetCount() * sizeof(unsigned));
   11.20 +
   11.21 +    Local<StructMap> map(zone);
   11.22 +    map = StructMap::cast(zone->allocateMap(MapKind_Struct, bytesNeeded, MapKind_MetaStruct));
   11.23 +    if (!map)
   11.24 +        return NULL;
   11.25 +
   11.26 +    map->structureSize_ = builder.structureSize();
   11.27 +    map->traceOffsetCount_ = builder.traceableOffsetCount();
   11.28 +    map->type_ = NULL;
   11.29 +    memcpy(const_cast<unsigned *>(map->traceOffsets()), builder.offsets(),
   11.30 +           sizeof(unsigned) * builder.traceableOffsetCount());
   11.31 +
   11.32 +    return map;
   11.33 +}
   11.34 +
   11.35 +Struct *
   11.36 +Struct::New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure)
   11.37 +{
   11.38 +    size_t bytesNeeded = sizeof(Struct) + map->structureSize();
   11.39 +    Local<Struct> obj(zone, Struct::cast(zone->allocate(map, bytesNeeded, tenure)));
   11.40 +    if (!obj)
   11.41 +        return NULL;
   11.42 +
   11.43 +    memset((Struct *)obj + 1, 0, map->structureSize());
   11.44 +    return obj;
   11.45 +}
   11.46 +
    12.1 --- a/src/Structures.h	Sat Aug 04 17:51:43 2012 -0700
    12.2 +++ b/src/Structures.h	Sat Aug 04 19:33:06 2012 -0700
    12.3 @@ -22,6 +22,7 @@
    12.4  #include "Objects.h"
    12.5  #include "Handles.h"
    12.6  #include "Vector.h"
    12.7 +#include "Heap.h"
    12.8  
    12.9  namespace ke {
   12.10  
   12.11 @@ -46,7 +47,7 @@
   12.12      unsigned traceableOffsetCount() const {
   12.13          return offsets_.length();
   12.14      }
   12.15 -    const unsigned *offsets() {
   12.16 +    const unsigned *offsets() const {
   12.17          return offsets_.buffer();
   12.18      }
   12.19  
   12.20 @@ -96,6 +97,69 @@
   12.21      }
   12.22  };
   12.23  
   12.24 +class StructMap : public Map
   12.25 +{
   12.26 +    unsigned structureSize_;
   12.27 +    unsigned traceOffsetCount_;
   12.28 +    Barriered<Type> type_;
   12.29 +
   12.30 +  public:
   12.31 +    static StructMap *New(Zone *zone, const StructureBufferBuilder &builder);
   12.32 +
   12.33 +    unsigned structureSize() {
   12.34 +        return structureSize_;
   12.35 +    }
   12.36 +    unsigned traceOffsetCount() {
   12.37 +        return traceOffsetCount_;
   12.38 +    }
   12.39 +    const unsigned *traceOffsets() {
   12.40 +        return reinterpret_cast<unsigned *>(this + 1);
   12.41 +    }
   12.42 +    size_t size() {
   12.43 +        return Align(sizeof(StructMap) + sizeof(unsigned) * traceOffsetCount(), kObjectAlignment);
   12.44 +    }
   12.45 +    Type *type() {
   12.46 +        return type_;
   12.47 +    }
   12.48 +    void setType(Type *type) {
   12.49 +        assert(!type_);
   12.50 +        type_ = type;
   12.51 +    }
   12.52 +
   12.53 +    // Begin GC descriptors.
   12.54 +    static inline size_t offsetOfType() {
   12.55 +        return OFFSETOF(StructMap, type_);
   12.56 +    }
   12.57 +    // End GC descriptors.
   12.58 +
   12.59 +    static inline StructMap *cast(Object *obj) {
   12.60 +        assert(!obj || obj->is(MapKind_MetaStruct));
   12.61 +        return reinterpret_cast<StructMap *>(obj);
   12.62 +    }
   12.63 +};
   12.64 +
   12.65 +class Struct : public Object
   12.66 +{
   12.67 +  public:
   12.68 +    static Struct *New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
   12.69 +
   12.70 +    size_t size() {
   12.71 +        return Align(sizeof(Struct) + map()->structureSize(), kObjectAlignment);
   12.72 +    }
   12.73 +    StructMap *map() {
   12.74 +        return StructMap::cast(Object::map());
   12.75 +    }
   12.76 +
   12.77 +    static inline size_t offsetOfSlotOffset(unsigned offset) {
   12.78 +        return sizeof(Struct) + offset;
   12.79 +    }
   12.80 +
   12.81 +    static inline Struct *cast(Object *obj) {
   12.82 +        assert(!obj || obj->is(MapKind_Struct));
   12.83 +        return reinterpret_cast<Struct *>(obj);
   12.84 +    }
   12.85 +};
   12.86 +
   12.87  }
   12.88  
   12.89  #endif // _include_jc_structure_h_
    13.1 --- a/src/TypeManager.cpp	Sat Aug 04 17:51:43 2012 -0700
    13.2 +++ b/src/TypeManager.cpp	Sat Aug 04 19:33:06 2012 -0700
    13.3 @@ -98,9 +98,9 @@
    13.4  }
    13.5  
    13.6  Type *
    13.7 -TypeManager::newStruct(Handle<String> name, Handle<FixedArray> fields)
    13.8 +TypeManager::newStruct(Handle<String> name, Handle<FixedArray> fields, Handle<Map> newMap)
    13.9  {
   13.10 -    return Type::NewStruct(zone_, name, fields);
   13.11 +    return Type::NewStruct(zone_, name, fields, newMap);
   13.12  }
   13.13  
   13.14  void
    14.1 --- a/src/TypeManager.h	Sat Aug 04 17:51:43 2012 -0700
    14.2 +++ b/src/TypeManager.h	Sat Aug 04 19:33:06 2012 -0700
    14.3 @@ -52,7 +52,7 @@
    14.4      Type *newEnum(Handle<String> name);
    14.5      Type *newFunction(Handle<Type> returnType, Handle<FixedArray> args);
    14.6      Type *newNative(Handle<Type> returnType, Handle<FixedArray> args, bool variadic);
    14.7 -    Type *newStruct(Handle<String> name, Handle<FixedArray> fields);
    14.8 +    Type *newStruct(Handle<String> name, Handle<FixedArray> fields, Handle<Map> newMap);
    14.9      
   14.10      void accept(VirtualObjectVisitor *visitor);
   14.11  };
    15.1 --- a/src/Types.cpp	Sat Aug 04 17:51:43 2012 -0700
    15.2 +++ b/src/Types.cpp	Sat Aug 04 19:33:06 2012 -0700
    15.3 @@ -36,6 +36,7 @@
    15.4      type->returnType_ = NULL;
    15.5      type->parameters_ = NULL;
    15.6      type->fields_ = NULL;
    15.7 +    type->newMap_ = NULL;
    15.8      return type;
    15.9  }
   15.10  
   15.11 @@ -52,6 +53,8 @@
   15.12      type->returnType_ = NULL;
   15.13      type->parameters_ = NULL;
   15.14      type->fields_ = NULL;
   15.15 +    type->newMap_ = NULL;
   15.16 +    type->newMap_ = NULL;
   15.17      type->primitive_ = prim;
   15.18      return type;
   15.19  }
   15.20 @@ -69,6 +72,7 @@
   15.21      type->returnType_ = NULL;
   15.22      type->parameters_ = NULL;
   15.23      type->fields_ = NULL;
   15.24 +    type->newMap_ = NULL;
   15.25      type->elements_ = elements;
   15.26      if (!contained->isArray())
   15.27          type->levels_ = 1;
   15.28 @@ -91,6 +95,7 @@
   15.29      type->returnType_ = NULL;
   15.30      type->parameters_ = NULL;
   15.31      type->fields_ = NULL;
   15.32 +    type->newMap_ = NULL;
   15.33      type->const_ = isConst;
   15.34      return type;
   15.35  }
   15.36 @@ -106,6 +111,7 @@
   15.37      type->name_ = NULL;
   15.38      type->contained_ = NULL;
   15.39      type->fields_ = NULL;
   15.40 +    type->newMap_ = NULL;
   15.41      type->returnType_ = returnType;
   15.42      type->parameters_ = parameters;
   15.43      return type;
   15.44 @@ -124,11 +130,12 @@
   15.45      type->returnType_ = NULL;
   15.46      type->parameters_ = NULL;
   15.47      type->fields_ = NULL;
   15.48 +    type->newMap_ = NULL;
   15.49      return type;
   15.50  }
   15.51  
   15.52  Type *
   15.53 -Type::NewStruct(Zone *zone, Handle<String> name, Handle<FixedArray> fields)
   15.54 +Type::NewStruct(Zone *zone, Handle<String> name, Handle<FixedArray> fields, Handle<Map> newMap)
   15.55  {
   15.56      Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
   15.57      if (!type)
   15.58 @@ -139,6 +146,7 @@
   15.59      type->contained_ = NULL;
   15.60      type->returnType_ = NULL;
   15.61      type->parameters_ = NULL;
   15.62 +    type->newMap_ = newMap;
   15.63      type->fields_ = fields;
   15.64      return type;
   15.65  }
   15.66 @@ -154,6 +162,7 @@
   15.67      type->name_ = NULL;
   15.68      type->contained_ = NULL;
   15.69      type->fields_ = NULL;
   15.70 +    type->newMap_ = NULL;
   15.71      type->returnType_ = returnType;
   15.72      type->parameters_ = parameters;
   15.73      type->variadicNative_ = variadic;
    16.1 --- a/src/Types.h	Sat Aug 04 17:51:43 2012 -0700
    16.2 +++ b/src/Types.h	Sat Aug 04 19:33:06 2012 -0700
    16.3 @@ -83,7 +83,7 @@
    16.4      static Type *NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters);
    16.5      static Type *NewNative(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters, bool isVariadic);
    16.6      static Type *NewEnum(Zone *zone, Handle<String> name);
    16.7 -    static Type *NewStruct(Zone *zone, Handle<String> name, Handle<FixedArray> fields);
    16.8 +    static Type *NewStruct(Zone *zone, Handle<String> name, Handle<FixedArray> fields, Handle<Map> newMap);
    16.9  
   16.10      static bool Compare(Type *left, Type *right);
   16.11  
   16.12 @@ -110,6 +110,9 @@
   16.13      bool isVoid() {
   16.14          return kind() == VOID;
   16.15      }
   16.16 +    bool isStruct() {
   16.17 +        return kind() == STRUCT;
   16.18 +    }
   16.19      bool isNativeVariadic() {
   16.20          assert(isNative());
   16.21          return variadicNative_;
   16.22 @@ -152,6 +155,9 @@
   16.23      bool isInt32OrEnum() {
   16.24          return isInt32() || isEnum();
   16.25      }
   16.26 +    bool isBool() {
   16.27 +        return isPrimitive() && primitive() == PrimitiveType_Bool;
   16.28 +    }
   16.29      bool isCharArray() {
   16.30          return isArray() &&
   16.31                 contained()->isPrimitive() &&
   16.32 @@ -180,10 +186,16 @@
   16.33      }
   16.34  
   16.35      String *name() {
   16.36 -        assert(isEnum());
   16.37 +        assert(isEnum() || isStruct());
   16.38          return name_;
   16.39      }
   16.40  
   16.41 +    // Objects of this type can be created with this cached map.
   16.42 +    Map *newMap() {
   16.43 +        assert(isStruct());
   16.44 +        return newMap_;
   16.45 +    }
   16.46 +
   16.47      // GC Descriptor.
   16.48      static inline size_t offsetOfContained() {
   16.49          return OFFSETOF(Type, contained_);
   16.50 @@ -200,6 +212,9 @@
   16.51      static inline size_t offsetOfFields() {
   16.52          return OFFSETOF(Type, fields_);
   16.53      }
   16.54 +    static inline size_t offsetOfNewMap() {
   16.55 +        return OFFSETOF(Type, newMap_);
   16.56 +    }
   16.57      // End GC Descriptor.
   16.58  
   16.59    private:
   16.60 @@ -226,6 +241,7 @@
   16.61  
   16.62      // Structs only.
   16.63      Barriered<FixedArray> fields_;
   16.64 +    Barriered<Map> newMap_;
   16.65  };
   16.66  
   16.67  class BoxedPrimitive
    17.1 --- a/src/Zone.cpp	Sat Aug 04 17:51:43 2012 -0700
    17.2 +++ b/src/Zone.cpp	Sat Aug 04 19:33:06 2012 -0700
    17.3 @@ -78,6 +78,8 @@
    17.4          return false;
    17.5      if ((maps_[MapKind_MetaArray] = allocateMap(MapKind_MetaArray, sizeof(Map))) == NULL)
    17.6          return false;
    17.7 +    if ((maps_[MapKind_MetaStruct] = allocateMap(MapKind_MetaStruct, sizeof(Map))) == NULL)
    17.8 +        return false;
    17.9      if ((maps_[MapKind_MetaEnvironment] = allocateMap(MapKind_MetaEnvironment, sizeof(Map))) == NULL)
   17.10          return false;
   17.11      if ((maps_[MapKind_Module] = allocateMap(MapKind_Module, sizeof(Map))) == NULL)