src/Structures.h
author David Anderson <dvander@alliedmods.net>
Sun Sep 16 21:34:10 2012 -0700 (2012-09-16)
changeset 188 bab29bcec7fe
parent 164 3bf7c007883d
child 195 c1ba166f3fc4
permissions -rw-r--r--
Restructure Array so the elements vector can be replaced.
     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     // List of descriptors which must be allocated upon initialization.
   107     Barriered<FixedArray> composed_;
   108 
   109   public:
   110     static StructMap *New(Zone *zone, const StructureBufferBuilder &builder, Handle<FixedArray> composed);
   111 
   112     unsigned structureSize() {
   113         return structureSize_;
   114     }
   115     unsigned traceOffsetCount() {
   116         return traceOffsetCount_;
   117     }
   118     const unsigned *traceOffsets() {
   119         return reinterpret_cast<unsigned *>(this + 1);
   120     }
   121     size_t objSize() {
   122         return sizeof(StructMap) + sizeof(unsigned) * traceOffsetCount();
   123     }
   124     Type *type() {
   125         return type_;
   126     }
   127     FixedArray *composed() {
   128         return composed_;
   129     }
   130 
   131     void setType(Type *type) {
   132         assert(!type_);
   133         type_ = type;
   134     }
   135 
   136     // Begin GC descriptors.
   137     static inline size_t offsetOfType() {
   138         return OFFSETOF(StructMap, type_);
   139     }
   140     static inline size_t offsetOfComposed() {
   141         return OFFSETOF(StructMap, composed_);
   142     }
   143     // End GC descriptors.
   144 
   145     static inline StructMap *cast(Object *obj) {
   146         assert(!obj || obj->is(MapKind_MetaStruct));
   147         return reinterpret_cast<StructMap *>(obj);
   148     }
   149 };
   150 
   151 class Struct : public Object
   152 {
   153   public:
   154     static Struct *New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
   155 
   156     size_t objSize() {
   157         return sizeof(Struct) + map()->structureSize();
   158     }
   159     StructMap *map() {
   160         return StructMap::cast(Object::map());
   161     }
   162 
   163     void *ref(Descriptor *desc) {
   164         return reinterpret_cast<Address>(this) + offsetOfSlotOffset(desc->offset());
   165     }
   166 
   167     // This must NOT be used with any Object * type!
   168     template <typename T> T get(Descriptor *desc) {
   169         return *reinterpret_cast<T *>(ref(desc));
   170     }
   171 
   172     template <typename T> void set(Descriptor *desc, const T &t) {
   173         *reinterpret_cast<T *>(ref(desc)) = t;
   174     }
   175 
   176     void set(Zone *zone, Descriptor *desc, Object *obj) {
   177         // :TODO: write barrier
   178         *reinterpret_cast<Object **>(
   179             reinterpret_cast<Address>(this) +
   180             offsetOfSlotOffset(desc->offset())) = obj;
   181     }
   182 
   183     static inline size_t offsetOfSlotOffset(unsigned offset) {
   184         return sizeof(Struct) + offset;
   185     }
   186 
   187     static inline Struct *cast(Object *obj) {
   188         assert(!obj || obj->is(MapKind_Struct));
   189         return reinterpret_cast<Struct *>(obj);
   190     }
   191 };
   192 
   193 }
   194 
   195 #endif // _include_jc_structure_h_
   196