# HG changeset patch # User David Anderson # Date 1344133986 25200 # Node ID 9c544823d090f38befa49c0ddcccd928f126f668 # Parent dc7d3b7a918c0b1db3459b901ad9d863a9117ada Structure declaration support. diff -r dc7d3b7a918c -r 9c544823d090 src/BytecodeCompiler.cpp --- a/src/BytecodeCompiler.cpp Sat Aug 04 17:51:43 2012 -0700 +++ b/src/BytecodeCompiler.cpp Sat Aug 04 19:33:06 2012 -0700 @@ -758,12 +758,24 @@ __ note_position(node->pos()); __ arraycopy(); } + } else if (type->isStruct()) { + Local map(zone_, type->newMap()); + if (var->scope()->kind() == Scope::GLOBAL) + __ newstruct(map, Heap::Tenure_Old); + else if (var->needsHeapAllocation()) + __ newstruct(map, Heap::Tenure_Default); + else + __ newstruct(map, Heap::Tenure_Stack); } else { if (node->initialization()) { node->initialization()->accept(this); } else { - if (!node->postDimensions()) + if (type->isInt32OrEnum() || type->isBool()) { __ int_(0); + } else { + assert(type->isFloat()); + __ float_(0); + } } } diff -r dc7d3b7a918c -r 9c544823d090 src/BytecodeEmitter.h --- a/src/BytecodeEmitter.h Sat Aug 04 17:51:43 2012 -0700 +++ b/src/BytecodeEmitter.h Sat Aug 04 19:33:06 2012 -0700 @@ -394,6 +394,23 @@ } } + void getfield(unsigned index, Type *type) { + ensure(OP_GETFIELD_LENGTH); + writeOp(OP_GETFIELD); + writeUint32(index); + + if (type->isTraceable()) + markOop(1); + } + void setfield(unsigned index, Type *type) { + ensure(OP_SETFIELD_LENGTH); + writeOp(OP_SETFIELD); + writeUint32(index); + + if (type->isTraceable()) + markOop(1); + } + void getglobal(Variable *var) { ensure(OP_GETGLOBAL_F_LENGTH); if (var->type()->isPrimitive()) { @@ -454,6 +471,14 @@ writeObject(map); markOop(1); } + void newstruct(Handle map, Heap::Tenure tenure) { + recordOops(); + ensure(OP_NEWSTRUCT_LENGTH); + writeOp(OP_NEWSTRUCT); + writeUint8(tenure); + writeObject(map); + markOop(1); + } void savelifo(unsigned slot) { ensure(OP_SAVELIFO_LENGTH); writeOp(OP_SAVELIFO); diff -r dc7d3b7a918c -r 9c544823d090 src/Environments.cpp --- a/src/Environments.cpp Sat Aug 04 17:51:43 2012 -0700 +++ b/src/Environments.cpp Sat Aug 04 19:33:06 2012 -0700 @@ -84,8 +84,8 @@ // Allocate the actual map now. size_t bytesNeeded = sizeof(EnvironmentMap) + structure.traceableOffsetCount() * sizeof(unsigned); + Local map(zone); - map = EnvironmentMap::cast(zone->allocateMap(MapKind_Environment, bytesNeeded, MapKind_MetaEnvironment)); if (!map) return NULL; diff -r dc7d3b7a918c -r 9c544823d090 src/Environments.h --- a/src/Environments.h Sat Aug 04 17:51:43 2012 -0700 +++ b/src/Environments.h Sat Aug 04 19:33:06 2012 -0700 @@ -135,9 +135,11 @@ return slots_->at(slot); } + // Begin GC descriptors. static inline size_t offsetOfSlots() { return OFFSETOF(EnvironmentMap, slots_); } + // End GC descriptors. static inline EnvironmentMap *cast(Object *obj) { assert(!obj || obj->is(MapKind_MetaEnvironment)); diff -r dc7d3b7a918c -r 9c544823d090 src/Interpreter.cpp --- a/src/Interpreter.cpp Sat Aug 04 17:51:43 2012 -0700 +++ b/src/Interpreter.cpp Sat Aug 04 19:33:06 2012 -0700 @@ -25,6 +25,7 @@ #include "Reference.h" #include "Strings.h" #include "Environments.h" +#include "Structures.h" #include "Heap-inl.h" using namespace ke; @@ -699,6 +700,17 @@ break; } +case OP_NEWSTRUCT: +{ + Heap::Tenure tenure = (Heap::Tenure)top.pc[1]; + Local map(zone, StructMap::cast(top.fp->code()->map(READ_UINT32(top.pc + 1)))); + top.sp->obj = Struct::New(zone, map, tenure); + if (!top.sp->obj) + goto error; + top.sp++; + break; +} + case OP_SAVELIFO: { unsigned slot = READ_UINT32(top.pc); diff -r dc7d3b7a918c -r 9c544823d090 src/ObjectVisitor.h --- a/src/ObjectVisitor.h Sat Aug 04 17:51:43 2012 -0700 +++ b/src/ObjectVisitor.h Sat Aug 04 19:33:06 2012 -0700 @@ -143,6 +143,11 @@ return map->size(); } + size_t iterateStructMap(StructMap *map) { + visitField(map, StructMap::offsetOfType()); + return map->size(); + } + size_t iterateEnvironment(Environment *env) { EnvironmentMap *map = env->map(); const unsigned *offsets = map->traceOffsets(); @@ -152,6 +157,15 @@ return env->size(); } + size_t iterateStruct(Struct *obj) { + StructMap *map = obj->map(); + const unsigned *offsets = map->traceOffsets(); + unsigned noffsets = map->traceOffsetCount(); + for (unsigned i = 0; i < noffsets; i++) + visitField(obj, Struct::offsetOfSlotOffset(offsets[i])); + return obj->size(); + } + public: size_t iterate(Object *obj) { visitField(obj, Object::offsetOfMap()); @@ -190,6 +204,9 @@ case MapKind_Array: return Align(iterateArray(Array::cast(obj), ArrayMap::cast(map)), kObjectAlignment); + case MapKind_Struct: + return iterateStruct(Struct::cast(obj)); + case MapKind_EnvironmentSlotDescriptorArray: return iterateEnvironmentSlotDescriptorArray(EnvironmentSlotDescriptorArray::cast(obj)); @@ -205,6 +222,9 @@ case MapKind_MetaEnvironment: return iterateEnvironmentMap(EnvironmentMap::cast(obj)); + case MapKind_MetaStruct: + return iterateStructMap(StructMap::cast(obj)); + default: assert(map->kind() == MapKind_Meta); return sizeof(Map); @@ -249,6 +269,9 @@ case MapKind_Array: return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment); + case MapKind_Struct: + return Struct::cast(obj)->size(); + case MapKind_EnvironmentSlotDescriptorArray: return EnvironmentSlotDescriptorArray::cast(obj)->size(); @@ -261,6 +284,9 @@ case MapKind_MetaEnvironment: return EnvironmentMap::cast(obj)->size(); + case MapKind_MetaStruct: + return StructMap::cast(obj)->size(); + case MapKind_FreeRegion: return *reinterpret_cast(reinterpret_cast
(obj + 1)); diff -r dc7d3b7a918c -r 9c544823d090 src/Objects.h --- a/src/Objects.h Sat Aug 04 17:51:43 2012 -0700 +++ b/src/Objects.h Sat Aug 04 19:33:06 2012 -0700 @@ -52,14 +52,16 @@ MapKind_Environment, MapKind_Descriptor, - // Used to represent Arrays. This does not have a canonical map. + // These do not have canonical maps. MapKind_Array, + MapKind_Struct, // These represent special Map subclasses that require special tracing. MapKinds_Special, MapKind_Meta, // (default map class) MapKind_MetaArray, // ArrayMap instances MapKind_MetaEnvironment, // EnvironmentMap instances + MapKind_MetaStruct, // StructMap instances MapKinds_EndSpecial, MapKinds_Total diff -r dc7d3b7a918c -r 9c544823d090 src/Opcodes.cpp --- a/src/Opcodes.cpp Sat Aug 04 17:51:43 2012 -0700 +++ b/src/Opcodes.cpp Sat Aug 04 19:33:06 2012 -0700 @@ -24,6 +24,7 @@ #include "Array.h" #include "Strings.h" #include "CompactBuffer.h" +#include "Structures.h" #include "Heap-inl.h" using namespace ke; @@ -259,6 +260,18 @@ break; } + case OP_NEWSTRUCT: + { + Heap::Tenure tenure = (Heap::Tenure)pc[1]; + StructMap *map = StructMap::cast(code->map(READ_UINT32(pc + 1))); + fprintf(fp, "%s", map->type()->name()->chars()); + if (tenure == Heap::Tenure_Stack) + fprintf(fp, " ; lifo"); + else if (tenure == Heap::Tenure_Old) + fprintf(fp, " ; pretenured"); + break; + } + case OP_GETLOCAL: case OP_SETLOCAL: case OP_GETARG: diff -r dc7d3b7a918c -r 9c544823d090 src/Opcodes.tbl --- a/src/Opcodes.tbl Sat Aug 04 17:51:43 2012 -0700 +++ b/src/Opcodes.tbl Sat Aug 04 19:33:06 2012 -0700 @@ -253,3 +253,16 @@ OPDEF(OP_TRUE, 101, "true", 1, 0, 1) OPDEF(OP_FALSE, 102, "false", 1, 0, 1) +// Allocate a struct. The HeapTenure is stored as a byte following pc. The +// StructMap to use is specified as an index into the script's Map table. +// +// Format: +// [u8 op] [u32 index] +OPDEF(OP_NEWSTRUCT, 103, "newstruct", 6, 0, 1) + +// Sets or gets a property in a struct. The index of the field is specified as +// a 32-bit integer. Note that these opcodes follow a new style of deriving +// their types at runtime. +OPDEF(OP_GETFIELD, 104, "getfield", 5, 1, 1) +OPDEF(OP_SETFIELD, 105, "setfield", 5, 2, 1) + diff -r dc7d3b7a918c -r 9c544823d090 src/SemanticAnalysis.cpp --- a/src/SemanticAnalysis.cpp Sat Aug 04 17:51:43 2012 -0700 +++ b/src/SemanticAnalysis.cpp Sat Aug 04 19:33:06 2012 -0700 @@ -160,7 +160,10 @@ enumstmt->decl()->setType(type); } else if (statement->isStructureStatement()) { - statement->accept(this); + StructureStatement *node = statement->toStructureStatement(); + node->accept(this); + if (!node->decl()->type()) + return false; } } @@ -285,7 +288,7 @@ return "function"; if (type->isVoid()) return "void"; - if (type->isEnum()) + if (type->isEnum() || type->isStruct()) return type->name()->chars(); if (type->isReference()) type = type->contained(); @@ -782,12 +785,6 @@ if (check) check = check->contained(); } - - // If this variable is stack allocated, we could use the LIFO heap - // to allocate it. If that's the case, make sure to reserve a slot - // so we can unwind the LIFO heap at the end of this scope. - if (!node->variable()->needsHeapAllocation()) - scope_->setUsesLifoHeap(); } else { if (node->initialization()) { Local right(zone_, visitForLoad(node->initialization())); @@ -796,12 +793,21 @@ if (!typeCheckAssignment(node, type, right, true)) return; } - if (type->primitive() == PrimitiveType_Char) { + + if (type->isPrimitive() && type->primitive() == PrimitiveType_Char) { cc_.reportError(node->pos(), Message_CannotDeclareStringCell); return; } } + // If this variable is stack allocated, we could use the LIFO heap + // to allocate it. If that's the case, make sure to reserve a slot + // so we can unwind the LIFO heap at the end of this scope. + if (!node->variable()->needsHeapAllocation()) { + if (type->isArray() || type->isStruct()) + scope_->setUsesLifoHeap(); + } + node->variable()->setType(type); } @@ -1245,11 +1251,16 @@ desctable->set(zone_, i, desc); } + Local map(zone_, StructMap::New(zone_, builder)); + if (!map) + return; + name = node->decl()->name(); - type = zone_->types()->newStruct(name, desctable); + type = zone_->types()->newStruct(name, desctable, map); if (!type) return; + map->setType(type); node->decl()->setType(type); } diff -r dc7d3b7a918c -r 9c544823d090 src/Structures.cpp --- a/src/Structures.cpp Sat Aug 04 17:51:43 2012 -0700 +++ b/src/Structures.cpp Sat Aug 04 19:33:06 2012 -0700 @@ -16,6 +16,7 @@ * You should have received a copy of the GNU General Public License along with * SourcePawn. If not, see http://www.gnu.org/licenses/. */ +#include #include "Structures.h" #include "Zone.h" #include "Types.h" @@ -62,3 +63,35 @@ return desc; } +StructMap * +StructMap::New(Zone *zone, const StructureBufferBuilder &builder) +{ + size_t bytesNeeded = sizeof(StructMap) + + (builder.traceableOffsetCount() * sizeof(unsigned)); + + Local map(zone); + map = StructMap::cast(zone->allocateMap(MapKind_Struct, bytesNeeded, MapKind_MetaStruct)); + if (!map) + return NULL; + + map->structureSize_ = builder.structureSize(); + map->traceOffsetCount_ = builder.traceableOffsetCount(); + map->type_ = NULL; + memcpy(const_cast(map->traceOffsets()), builder.offsets(), + sizeof(unsigned) * builder.traceableOffsetCount()); + + return map; +} + +Struct * +Struct::New(Zone *zone, Handle map, Heap::Tenure tenure) +{ + size_t bytesNeeded = sizeof(Struct) + map->structureSize(); + Local obj(zone, Struct::cast(zone->allocate(map, bytesNeeded, tenure))); + if (!obj) + return NULL; + + memset((Struct *)obj + 1, 0, map->structureSize()); + return obj; +} + diff -r dc7d3b7a918c -r 9c544823d090 src/Structures.h --- a/src/Structures.h Sat Aug 04 17:51:43 2012 -0700 +++ b/src/Structures.h Sat Aug 04 19:33:06 2012 -0700 @@ -22,6 +22,7 @@ #include "Objects.h" #include "Handles.h" #include "Vector.h" +#include "Heap.h" namespace ke { @@ -46,7 +47,7 @@ unsigned traceableOffsetCount() const { return offsets_.length(); } - const unsigned *offsets() { + const unsigned *offsets() const { return offsets_.buffer(); } @@ -96,6 +97,69 @@ } }; +class StructMap : public Map +{ + unsigned structureSize_; + unsigned traceOffsetCount_; + Barriered type_; + + public: + static StructMap *New(Zone *zone, const StructureBufferBuilder &builder); + + unsigned structureSize() { + return structureSize_; + } + unsigned traceOffsetCount() { + return traceOffsetCount_; + } + const unsigned *traceOffsets() { + return reinterpret_cast(this + 1); + } + size_t size() { + return Align(sizeof(StructMap) + sizeof(unsigned) * traceOffsetCount(), kObjectAlignment); + } + Type *type() { + return type_; + } + void setType(Type *type) { + assert(!type_); + type_ = type; + } + + // Begin GC descriptors. + static inline size_t offsetOfType() { + return OFFSETOF(StructMap, type_); + } + // End GC descriptors. + + static inline StructMap *cast(Object *obj) { + assert(!obj || obj->is(MapKind_MetaStruct)); + return reinterpret_cast(obj); + } +}; + +class Struct : public Object +{ + public: + static Struct *New(Zone *zone, Handle map, Heap::Tenure tenure = Heap::Tenure_Default); + + size_t size() { + return Align(sizeof(Struct) + map()->structureSize(), kObjectAlignment); + } + StructMap *map() { + return StructMap::cast(Object::map()); + } + + static inline size_t offsetOfSlotOffset(unsigned offset) { + return sizeof(Struct) + offset; + } + + static inline Struct *cast(Object *obj) { + assert(!obj || obj->is(MapKind_Struct)); + return reinterpret_cast(obj); + } +}; + } #endif // _include_jc_structure_h_ diff -r dc7d3b7a918c -r 9c544823d090 src/TypeManager.cpp --- a/src/TypeManager.cpp Sat Aug 04 17:51:43 2012 -0700 +++ b/src/TypeManager.cpp Sat Aug 04 19:33:06 2012 -0700 @@ -98,9 +98,9 @@ } Type * -TypeManager::newStruct(Handle name, Handle fields) +TypeManager::newStruct(Handle name, Handle fields, Handle newMap) { - return Type::NewStruct(zone_, name, fields); + return Type::NewStruct(zone_, name, fields, newMap); } void diff -r dc7d3b7a918c -r 9c544823d090 src/TypeManager.h --- a/src/TypeManager.h Sat Aug 04 17:51:43 2012 -0700 +++ b/src/TypeManager.h Sat Aug 04 19:33:06 2012 -0700 @@ -52,7 +52,7 @@ Type *newEnum(Handle name); Type *newFunction(Handle returnType, Handle args); Type *newNative(Handle returnType, Handle args, bool variadic); - Type *newStruct(Handle name, Handle fields); + Type *newStruct(Handle name, Handle fields, Handle newMap); void accept(VirtualObjectVisitor *visitor); }; diff -r dc7d3b7a918c -r 9c544823d090 src/Types.cpp --- a/src/Types.cpp Sat Aug 04 17:51:43 2012 -0700 +++ b/src/Types.cpp Sat Aug 04 19:33:06 2012 -0700 @@ -36,6 +36,7 @@ type->returnType_ = NULL; type->parameters_ = NULL; type->fields_ = NULL; + type->newMap_ = NULL; return type; } @@ -52,6 +53,8 @@ type->returnType_ = NULL; type->parameters_ = NULL; type->fields_ = NULL; + type->newMap_ = NULL; + type->newMap_ = NULL; type->primitive_ = prim; return type; } @@ -69,6 +72,7 @@ type->returnType_ = NULL; type->parameters_ = NULL; type->fields_ = NULL; + type->newMap_ = NULL; type->elements_ = elements; if (!contained->isArray()) type->levels_ = 1; @@ -91,6 +95,7 @@ type->returnType_ = NULL; type->parameters_ = NULL; type->fields_ = NULL; + type->newMap_ = NULL; type->const_ = isConst; return type; } @@ -106,6 +111,7 @@ type->name_ = NULL; type->contained_ = NULL; type->fields_ = NULL; + type->newMap_ = NULL; type->returnType_ = returnType; type->parameters_ = parameters; return type; @@ -124,11 +130,12 @@ type->returnType_ = NULL; type->parameters_ = NULL; type->fields_ = NULL; + type->newMap_ = NULL; return type; } Type * -Type::NewStruct(Zone *zone, Handle name, Handle fields) +Type::NewStruct(Zone *zone, Handle name, Handle fields, Handle newMap) { Local type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old))); if (!type) @@ -139,6 +146,7 @@ type->contained_ = NULL; type->returnType_ = NULL; type->parameters_ = NULL; + type->newMap_ = newMap; type->fields_ = fields; return type; } @@ -154,6 +162,7 @@ type->name_ = NULL; type->contained_ = NULL; type->fields_ = NULL; + type->newMap_ = NULL; type->returnType_ = returnType; type->parameters_ = parameters; type->variadicNative_ = variadic; diff -r dc7d3b7a918c -r 9c544823d090 src/Types.h --- a/src/Types.h Sat Aug 04 17:51:43 2012 -0700 +++ b/src/Types.h Sat Aug 04 19:33:06 2012 -0700 @@ -83,7 +83,7 @@ static Type *NewFunction(Zone *zone, Handle returnType, Handle parameters); static Type *NewNative(Zone *zone, Handle returnType, Handle parameters, bool isVariadic); static Type *NewEnum(Zone *zone, Handle name); - static Type *NewStruct(Zone *zone, Handle name, Handle fields); + static Type *NewStruct(Zone *zone, Handle name, Handle fields, Handle newMap); static bool Compare(Type *left, Type *right); @@ -110,6 +110,9 @@ bool isVoid() { return kind() == VOID; } + bool isStruct() { + return kind() == STRUCT; + } bool isNativeVariadic() { assert(isNative()); return variadicNative_; @@ -152,6 +155,9 @@ bool isInt32OrEnum() { return isInt32() || isEnum(); } + bool isBool() { + return isPrimitive() && primitive() == PrimitiveType_Bool; + } bool isCharArray() { return isArray() && contained()->isPrimitive() && @@ -180,10 +186,16 @@ } String *name() { - assert(isEnum()); + assert(isEnum() || isStruct()); return name_; } + // Objects of this type can be created with this cached map. + Map *newMap() { + assert(isStruct()); + return newMap_; + } + // GC Descriptor. static inline size_t offsetOfContained() { return OFFSETOF(Type, contained_); @@ -200,6 +212,9 @@ static inline size_t offsetOfFields() { return OFFSETOF(Type, fields_); } + static inline size_t offsetOfNewMap() { + return OFFSETOF(Type, newMap_); + } // End GC Descriptor. private: @@ -226,6 +241,7 @@ // Structs only. Barriered fields_; + Barriered newMap_; }; class BoxedPrimitive diff -r dc7d3b7a918c -r 9c544823d090 src/Zone.cpp --- a/src/Zone.cpp Sat Aug 04 17:51:43 2012 -0700 +++ b/src/Zone.cpp Sat Aug 04 19:33:06 2012 -0700 @@ -78,6 +78,8 @@ return false; if ((maps_[MapKind_MetaArray] = allocateMap(MapKind_MetaArray, sizeof(Map))) == NULL) return false; + if ((maps_[MapKind_MetaStruct] = allocateMap(MapKind_MetaStruct, sizeof(Map))) == NULL) + return false; if ((maps_[MapKind_MetaEnvironment] = allocateMap(MapKind_MetaEnvironment, sizeof(Map))) == NULL) return false; if ((maps_[MapKind_Module] = allocateMap(MapKind_Module, sizeof(Map))) == NULL)