dvander@146: /* vim: set ts=4 sw=4 tw=99 et: dvander@85: * dvander@85: * Copyright (C) 2012 David Anderson dvander@85: * dvander@146: * This file is part of SourcePawn. dvander@85: * dvander@146: * SourcePawn is free software: you can redistribute it and/or modify it under dvander@85: * the terms of the GNU General Public License as published by the Free dvander@85: * Software Foundation, either version 3 of the License, or (at your option) dvander@85: * any later version. dvander@85: * dvander@146: * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY dvander@85: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@85: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@85: * dvander@85: * You should have received a copy of the GNU General Public License along with dvander@146: * SourcePawn. If not, see http://www.gnu.org/licenses/. dvander@85: */ dvander@85: #ifndef _include_jc_structure_h_ dvander@85: #define _include_jc_structure_h_ dvander@85: dvander@85: #include "Objects.h" dvander@85: #include "Handles.h" dvander@85: #include "Vector.h" dvander@147: #include "Heap.h" dvander@85: dvander@85: namespace ke { dvander@85: dvander@85: class Type; dvander@85: class String; dvander@85: class FixedArray; dvander@195: class StructType; dvander@85: dvander@85: // When describing composite structures, the GC must be able to trace interior dvander@85: // references to Objects. To make this possible, maps that describe composite dvander@85: // structures must provide a list of offsets into their objects that are dvander@85: // traceable. StructureBufferBuilder assists with this. dvander@85: class StructureBufferBuilder dvander@85: { dvander@85: public: dvander@85: StructureBufferBuilder(); dvander@85: dvander@85: bool add(Handle type, unsigned *offset); dvander@85: dvander@85: unsigned structureSize() const { dvander@85: return size_; dvander@85: } dvander@85: unsigned traceableOffsetCount() const { dvander@85: return offsets_.length(); dvander@85: } dvander@147: const unsigned *offsets() const { dvander@85: return offsets_.buffer(); dvander@85: } dvander@85: dvander@85: private: dvander@85: Vector offsets_; dvander@85: unsigned size_; dvander@85: }; dvander@85: dvander@146: // Represents a property descriptor for a structure field. dvander@146: class Descriptor : public Object dvander@146: { dvander@146: // The name of the field. dvander@146: Barriered name_; dvander@146: dvander@146: // The type of the field. dvander@146: Barriered type_; dvander@146: dvander@146: // The offset into an object at which this field can be accessed. dvander@146: unsigned offset_; dvander@146: dvander@146: public: dvander@195: static Descriptor *New(Zone *zone, Handle name, Handle type); dvander@146: dvander@146: String *name() { dvander@146: return name_; dvander@146: } dvander@146: Type *type() { dvander@146: return type_; dvander@146: } dvander@146: unsigned offset() { dvander@195: assert(offset_ != unsigned(-1)); dvander@146: return offset_; dvander@146: } dvander@195: void setOffset(unsigned offset) { dvander@195: assert(offset_ == unsigned(-1)); dvander@195: offset_ = offset; dvander@195: } dvander@146: dvander@146: // Begin GC descriptor. dvander@146: static inline size_t offsetOfName() { dvander@146: return OFFSETOF(Descriptor, name_); dvander@146: } dvander@146: static inline size_t offsetOfType() { dvander@146: return OFFSETOF(Descriptor, type_); dvander@146: } dvander@146: // End GC descriptor. dvander@146: dvander@146: static inline Descriptor *cast(Object *obj) { dvander@146: assert(!obj || obj->is(MapKind_Descriptor)); dvander@146: return reinterpret_cast(obj); dvander@146: } dvander@146: }; dvander@146: dvander@147: class StructMap : public Map dvander@147: { dvander@147: unsigned structureSize_; dvander@147: unsigned traceOffsetCount_; dvander@195: Barriered type_; dvander@147: dvander@153: // List of descriptors which must be allocated upon initialization. dvander@153: Barriered composed_; dvander@153: dvander@147: public: dvander@195: static StructMap *New(Zone *zone, const StructureBufferBuilder &builder, Handle type); dvander@147: dvander@147: unsigned structureSize() { dvander@147: return structureSize_; dvander@147: } dvander@147: unsigned traceOffsetCount() { dvander@147: return traceOffsetCount_; dvander@147: } dvander@147: const unsigned *traceOffsets() { dvander@147: return reinterpret_cast(this + 1); dvander@147: } dvander@161: size_t objSize() { dvander@161: return sizeof(StructMap) + sizeof(unsigned) * traceOffsetCount(); dvander@147: } dvander@195: StructType *type() { dvander@147: return type_; dvander@147: } dvander@153: FixedArray *composed() { dvander@153: return composed_; dvander@153: } dvander@153: dvander@195: void setType(StructType *type) { dvander@147: assert(!type_); dvander@147: type_ = type; dvander@147: } dvander@147: dvander@147: // Begin GC descriptors. dvander@147: static inline size_t offsetOfType() { dvander@147: return OFFSETOF(StructMap, type_); dvander@147: } dvander@153: static inline size_t offsetOfComposed() { dvander@153: return OFFSETOF(StructMap, composed_); dvander@153: } dvander@147: // End GC descriptors. dvander@147: dvander@147: static inline StructMap *cast(Object *obj) { dvander@147: assert(!obj || obj->is(MapKind_MetaStruct)); dvander@147: return reinterpret_cast(obj); dvander@147: } dvander@147: }; dvander@147: dvander@147: class Struct : public Object dvander@147: { dvander@147: public: dvander@147: static Struct *New(Zone *zone, Handle map, Heap::Tenure tenure = Heap::Tenure_Default); dvander@147: dvander@161: size_t objSize() { dvander@161: return sizeof(Struct) + map()->structureSize(); dvander@147: } dvander@147: StructMap *map() { dvander@147: return StructMap::cast(Object::map()); dvander@147: } dvander@147: dvander@164: void *ref(Descriptor *desc) { dvander@164: return reinterpret_cast
(this) + offsetOfSlotOffset(desc->offset()); dvander@164: } dvander@164: dvander@152: // This must NOT be used with any Object * type! dvander@152: template T get(Descriptor *desc) { dvander@164: return *reinterpret_cast(ref(desc)); dvander@152: } dvander@152: dvander@152: template void set(Descriptor *desc, const T &t) { dvander@164: *reinterpret_cast(ref(desc)) = t; dvander@152: } dvander@152: dvander@152: void set(Zone *zone, Descriptor *desc, Object *obj) { dvander@152: // :TODO: write barrier dvander@152: *reinterpret_cast( dvander@152: reinterpret_cast
(this) + dvander@152: offsetOfSlotOffset(desc->offset())) = obj; dvander@152: } dvander@152: dvander@147: static inline size_t offsetOfSlotOffset(unsigned offset) { dvander@147: return sizeof(Struct) + offset; dvander@147: } dvander@147: dvander@147: static inline Struct *cast(Object *obj) { dvander@147: assert(!obj || obj->is(MapKind_Struct)); dvander@147: return reinterpret_cast(obj); dvander@147: } dvander@147: }; dvander@147: dvander@85: } dvander@85: dvander@85: #endif // _include_jc_structure_h_ dvander@146: