src/Structures.h
author David Anderson <dvander@alliedmods.net>
Sun Jan 06 13:52:21 2013 -0800 (2013-01-06)
changeset 256 3c184218462d
parent 234 26e3035cdffc
child 263 ba85a47ee414
permissions -rw-r--r--
Initial implementation of module imports.
     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   public:
    64     enum Visibility {
    65         Private,
    66         Protected,
    67         Public
    68     };
    69 
    70   private:
    71     // The name of the field.
    72     Barriered<String> name_;
    73 
    74     // The type of the field.
    75     Barriered<Type> type_;
    76 
    77     // The offset into an object at which this field can be accessed.
    78     unsigned offset_;
    79 
    80     Visibility visibility_;
    81 
    82   public:
    83     static Descriptor *New(Zone *zone, Handle<String> name, Handle<Type> type, Visibility visibility);
    84 
    85     String *name() {
    86         return name_;
    87     }
    88     Type *type() {
    89         return type_;
    90     }
    91     unsigned offset() {
    92         assert(offset_ != unsigned(-1));
    93         return offset_;
    94     }
    95     void setOffset(unsigned offset) {
    96         assert(offset_ == unsigned(-1));
    97         offset_ = offset;
    98     }
    99 
   100     // Begin GC descriptor.
   101     static inline size_t offsetOfName() {
   102         return OFFSETOF(Descriptor, name_);
   103     }
   104     static inline size_t offsetOfType() {
   105         return OFFSETOF(Descriptor, type_);
   106     }
   107     // End GC descriptor.
   108     
   109     static inline Descriptor *cast(Object *obj) {
   110         assert(!obj || obj->is(MapKind_Descriptor));
   111         return reinterpret_cast<Descriptor *>(obj);
   112     }
   113 };
   114 
   115 class StructMap : public Map
   116 {
   117     unsigned structureSize_;
   118     unsigned traceOffsetCount_;
   119     Barriered<StructType> type_;
   120 
   121     // List of descriptors which must be allocated upon initialization.
   122     Barriered<FixedArray> composed_;
   123 
   124   public:
   125     static StructMap *New(Zone *zone, const StructureBufferBuilder &builder, Handle<StructType> type);
   126 
   127     unsigned structureSize() {
   128         return structureSize_;
   129     }
   130     unsigned traceOffsetCount() {
   131         return traceOffsetCount_;
   132     }
   133     const unsigned *traceOffsets() {
   134         return reinterpret_cast<unsigned *>(this + 1);
   135     }
   136     size_t objSize() {
   137         return sizeof(StructMap) + sizeof(unsigned) * traceOffsetCount();
   138     }
   139     StructType *type() {
   140         return type_;
   141     }
   142     FixedArray *composed() {
   143         return composed_;
   144     }
   145 
   146     void setType(StructType *type) {
   147         assert(!type_);
   148         type_ = type;
   149     }
   150 
   151     // Begin GC descriptors.
   152     static inline size_t offsetOfType() {
   153         return OFFSETOF(StructMap, type_);
   154     }
   155     static inline size_t offsetOfComposed() {
   156         return OFFSETOF(StructMap, composed_);
   157     }
   158     // End GC descriptors.
   159 
   160     static inline StructMap *cast(Object *obj) {
   161         assert(!obj || obj->is(MapKind_MetaStruct));
   162         return reinterpret_cast<StructMap *>(obj);
   163     }
   164 };
   165 
   166 class Struct : public Object
   167 {
   168   public:
   169     static Struct *New(Zone *zone, Handle<StructMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
   170 
   171     static bool Copy(Zone *zone, Handle<Struct> dest, Handle<Struct> src);
   172 
   173     StructMap *map() {
   174         return StructMap::cast(Object::map());
   175     }
   176 
   177     void *ref(Descriptor *desc) {
   178         return reinterpret_cast<Address>(this) + offsetOfSlotOffset(desc->offset());
   179     }
   180 
   181     static inline size_t SizeFor(StructMap *map) {
   182         return Max(sizeof(Struct) + map->structureSize(), kMinObjectSize);
   183     }
   184 
   185     template <typename T> T get(Descriptor *desc) {
   186         return *reinterpret_cast<T *>(ref(desc));
   187     }
   188 
   189     // This must NOT be used with any Object * type!
   190     // :TODO: prevent with type system
   191     template <typename T> void set(Descriptor *desc, const T &t) {
   192         *reinterpret_cast<T *>(ref(desc)) = t;
   193     }
   194 
   195     void set(Zone *zone, Descriptor *desc, Object *obj) {
   196         // :TODO: write barrier
   197         *reinterpret_cast<Object **>(
   198             reinterpret_cast<Address>(this) +
   199             offsetOfSlotOffset(desc->offset())) = obj;
   200     }
   201 
   202     static inline size_t offsetOfSlotOffset(unsigned offset) {
   203         return sizeof(Struct) + offset;
   204     }
   205 
   206     static inline Struct *cast(Object *obj) {
   207         assert(!obj || obj->is(MapKind_Struct));
   208         return reinterpret_cast<Struct *>(obj);
   209     }
   210 };
   211 
   212 }
   213 
   214 #endif // _include_jc_structure_h_
   215