src/Structures.h
author David Anderson <dvander@alliedmods.net>
Sat Aug 04 23:26:49 2012 -0700 (2012-08-04)
changeset 152 153d0cafc1fd
parent 147 9c544823d090
child 153 fc91c4a3dfe2
permissions -rw-r--r--
Support assigning structs.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of SourcePawn.
     6  *
     7  * SourcePawn is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * SourcePawn. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #ifndef _include_jc_structure_h_
    20 #define _include_jc_structure_h_
    21 
    22 #include "Objects.h"
    23 #include "Handles.h"
    24 #include "Vector.h"
    25 #include "Heap.h"
    26 
    27 namespace ke {
    28 
    29 class Type;
    30 class String;
    31 class FixedArray;
    32 
    33 // When describing composite structures, the GC must be able to trace interior
    34 // references to Objects. To make this possible, maps that describe composite
    35 // structures must provide a list of offsets into their objects that are
    36 // traceable. StructureBufferBuilder assists with this.
    37 class StructureBufferBuilder
    38 {
    39   public:
    40     StructureBufferBuilder();
    41 
    42     bool add(Handle<Type> type, unsigned *offset);
    43 
    44     unsigned structureSize() const {
    45         return size_;
    46     }
    47     unsigned traceableOffsetCount() const {
    48         return offsets_.length();
    49     }
    50     const unsigned *offsets() const {
    51         return offsets_.buffer();
    52     }
    53 
    54   private:
    55     Vector<unsigned> offsets_;
    56     unsigned size_;
    57 };
    58 
    59 // Represents a property descriptor for a structure field.
    60 class Descriptor : public Object
    61 {
    62     // The name of the field.
    63     Barriered<String> name_;
    64 
    65     // The type of the field.
    66     Barriered<Type> type_;
    67 
    68     // The offset into an object at which this field can be accessed.
    69     unsigned offset_;
    70 
    71   public:
    72     static Descriptor *New(Zone *zone, Handle<String> name, Handle<Type> type,
    73                            unsigned offset);
    74 
    75     String *name() {
    76         return name_;
    77     }
    78     Type *type() {
    79         return type_;
    80     }
    81     unsigned offset() {
    82         return offset_;
    83     }
    84 
    85     // Begin GC descriptor.
    86     static inline size_t offsetOfName() {
    87         return OFFSETOF(Descriptor, name_);
    88     }
    89     static inline size_t offsetOfType() {
    90         return OFFSETOF(Descriptor, type_);
    91     }
    92     // End GC descriptor.
    93     
    94     static inline Descriptor *cast(Object *obj) {
    95         assert(!obj || obj->is(MapKind_Descriptor));
    96         return reinterpret_cast<Descriptor *>(obj);
    97     }
    98 };
    99 
   100 class StructMap : public Map
   101 {
   102     unsigned structureSize_;
   103     unsigned traceOffsetCount_;
   104     Barriered<Type> type_;
   105 
   106   public:
   107     static StructMap *New(Zone *zone, const StructureBufferBuilder &builder);
   108 
   109     unsigned structureSize() {
   110         return structureSize_;
   111     }
   112     unsigned traceOffsetCount() {
   113         return traceOffsetCount_;
   114     }
   115     const unsigned *traceOffsets() {
   116         return reinterpret_cast<unsigned *>(this + 1);
   117     }
   118     size_t size() {
   119         return Align(sizeof(StructMap) + sizeof(unsigned) * traceOffsetCount(), kObjectAlignment);
   120     }
   121     Type *type() {
   122         return type_;
   123     }
   124     void setType(Type *type) {
   125         assert(!type_);
   126         type_ = type;
   127     }
   128 
   129     // Begin GC descriptors.
   130     static inline size_t offsetOfType() {
   131         return OFFSETOF(StructMap, type_);
   132     }
   133     // End GC descriptors.
   134 
   135     static inline StructMap *cast(Object *obj) {
   136         assert(!obj || obj->is(MapKind_MetaStruct));
   137         return reinterpret_cast<StructMap *>(obj);
   138     }
   139 };
   140 
   141 class Struct : public Object
   142 {
   143   public:
   144     static Struct *New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
   145 
   146     size_t size() {
   147         return Align(sizeof(Struct) + map()->structureSize(), kObjectAlignment);
   148     }
   149     StructMap *map() {
   150         return StructMap::cast(Object::map());
   151     }
   152 
   153     // This must NOT be used with any Object * type!
   154     template <typename T> T get(Descriptor *desc) {
   155         return *reinterpret_cast<T *>(
   156                     reinterpret_cast<Address>(this) +
   157                     offsetOfSlotOffset(desc->offset()));
   158     }
   159 
   160     template <typename T> void set(Descriptor *desc, const T &t) {
   161         *reinterpret_cast<T *>(
   162             reinterpret_cast<Address>(this) +
   163             offsetOfSlotOffset(desc->offset())) = t;
   164     }
   165 
   166     void set(Zone *zone, Descriptor *desc, Object *obj) {
   167         // :TODO: write barrier
   168         *reinterpret_cast<Object **>(
   169             reinterpret_cast<Address>(this) +
   170             offsetOfSlotOffset(desc->offset())) = obj;
   171     }
   172 
   173     static inline size_t offsetOfSlotOffset(unsigned offset) {
   174         return sizeof(Struct) + offset;
   175     }
   176 
   177     static inline Struct *cast(Object *obj) {
   178         assert(!obj || obj->is(MapKind_Struct));
   179         return reinterpret_cast<Struct *>(obj);
   180     }
   181 };
   182 
   183 }
   184 
   185 #endif // _include_jc_structure_h_
   186