src/Structures.h
author David Anderson <dvander@alliedmods.net>
Sat Dec 22 18:22:14 2012 -0800 (2012-12-22)
changeset 230 fb3cd08bc7fb
parent 195 c1ba166f3fc4
child 234 26e3035cdffc
permissions -rw-r--r--
Re-add LIFO stack optimizations.
     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 class StructType;
    33 
    34 // When describing composite structures, the GC must be able to trace interior
    35 // references to Objects. To make this possible, maps that describe composite
    36 // structures must provide a list of offsets into their objects that are
    37 // traceable. StructureBufferBuilder assists with this.
    38 class StructureBufferBuilder
    39 {
    40   public:
    41     StructureBufferBuilder();
    42 
    43     bool add(Handle<Type> type, unsigned *offset);
    44 
    45     unsigned structureSize() const {
    46         return size_;
    47     }
    48     unsigned traceableOffsetCount() const {
    49         return offsets_.length();
    50     }
    51     const unsigned *offsets() const {
    52         return offsets_.buffer();
    53     }
    54 
    55   private:
    56     Vector<unsigned> offsets_;
    57     unsigned size_;
    58 };
    59 
    60 // Represents a property descriptor for a structure field.
    61 class Descriptor : public Object
    62 {
    63     // The name of the field.
    64     Barriered<String> name_;
    65 
    66     // The type of the field.
    67     Barriered<Type> type_;
    68 
    69     // The offset into an object at which this field can be accessed.
    70     unsigned offset_;
    71 
    72   public:
    73     static Descriptor *New(Zone *zone, Handle<String> name, Handle<Type> type);
    74 
    75     String *name() {
    76         return name_;
    77     }
    78     Type *type() {
    79         return type_;
    80     }
    81     unsigned offset() {
    82         assert(offset_ != unsigned(-1));
    83         return offset_;
    84     }
    85     void setOffset(unsigned offset) {
    86         assert(offset_ == unsigned(-1));
    87         offset_ = offset;
    88     }
    89 
    90     // Begin GC descriptor.
    91     static inline size_t offsetOfName() {
    92         return OFFSETOF(Descriptor, name_);
    93     }
    94     static inline size_t offsetOfType() {
    95         return OFFSETOF(Descriptor, type_);
    96     }
    97     // End GC descriptor.
    98     
    99     static inline Descriptor *cast(Object *obj) {
   100         assert(!obj || obj->is(MapKind_Descriptor));
   101         return reinterpret_cast<Descriptor *>(obj);
   102     }
   103 };
   104 
   105 class StructMap : public Map
   106 {
   107     unsigned structureSize_;
   108     unsigned traceOffsetCount_;
   109     Barriered<StructType> type_;
   110 
   111     // List of descriptors which must be allocated upon initialization.
   112     Barriered<FixedArray> composed_;
   113 
   114   public:
   115     static StructMap *New(Zone *zone, const StructureBufferBuilder &builder, Handle<StructType> type);
   116 
   117     unsigned structureSize() {
   118         return structureSize_;
   119     }
   120     unsigned traceOffsetCount() {
   121         return traceOffsetCount_;
   122     }
   123     const unsigned *traceOffsets() {
   124         return reinterpret_cast<unsigned *>(this + 1);
   125     }
   126     size_t objSize() {
   127         return sizeof(StructMap) + sizeof(unsigned) * traceOffsetCount();
   128     }
   129     StructType *type() {
   130         return type_;
   131     }
   132     FixedArray *composed() {
   133         return composed_;
   134     }
   135 
   136     void setType(StructType *type) {
   137         assert(!type_);
   138         type_ = type;
   139     }
   140 
   141     // Begin GC descriptors.
   142     static inline size_t offsetOfType() {
   143         return OFFSETOF(StructMap, type_);
   144     }
   145     static inline size_t offsetOfComposed() {
   146         return OFFSETOF(StructMap, composed_);
   147     }
   148     // End GC descriptors.
   149 
   150     static inline StructMap *cast(Object *obj) {
   151         assert(!obj || obj->is(MapKind_MetaStruct));
   152         return reinterpret_cast<StructMap *>(obj);
   153     }
   154 };
   155 
   156 class Struct : public Object
   157 {
   158   public:
   159     static Struct *New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
   160 
   161     size_t objSize() {
   162         return sizeof(Struct) + map()->structureSize();
   163     }
   164     StructMap *map() {
   165         return StructMap::cast(Object::map());
   166     }
   167 
   168     void *ref(Descriptor *desc) {
   169         return reinterpret_cast<Address>(this) + offsetOfSlotOffset(desc->offset());
   170     }
   171 
   172     // This must NOT be used with any Object * type!
   173     template <typename T> T get(Descriptor *desc) {
   174         return *reinterpret_cast<T *>(ref(desc));
   175     }
   176 
   177     template <typename T> void set(Descriptor *desc, const T &t) {
   178         *reinterpret_cast<T *>(ref(desc)) = t;
   179     }
   180 
   181     void set(Zone *zone, Descriptor *desc, Object *obj) {
   182         // :TODO: write barrier
   183         *reinterpret_cast<Object **>(
   184             reinterpret_cast<Address>(this) +
   185             offsetOfSlotOffset(desc->offset())) = obj;
   186     }
   187 
   188     static inline size_t offsetOfSlotOffset(unsigned offset) {
   189         return sizeof(Struct) + offset;
   190     }
   191 
   192     static inline Struct *cast(Object *obj) {
   193         assert(!obj || obj->is(MapKind_Struct));
   194         return reinterpret_cast<Struct *>(obj);
   195     }
   196 };
   197 
   198 }
   199 
   200 #endif // _include_jc_structure_h_
   201