src/Array.h
author David Anderson <dvander@alliedmods.net>
Tue Dec 25 16:32:06 2012 -0800 (2012-12-25)
changeset 238 e9bec7549c28
parent 234 26e3035cdffc
child 247 7721042bdb67
permissions -rw-r--r--
Preparatory refactoring for const types.
     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_jitcraft_array_h_
    20 #define _include_jitcraft_array_h_
    21 
    22 #include "Heap.h"
    23 #include "Handles.h"
    24 #include "Types.h"
    25 #include "FixedArray.h"
    26 
    27 namespace ke {
    28 
    29 class ArrayMap;
    30 
    31 class Array : public Object
    32 {
    33     friend class ArrayMap;
    34 
    35     // Note: we do not write barrier |elements_|, since it can be set to
    36     // arbitrary pointers.
    37     uint32 length_;
    38     union {
    39         void *elements_;
    40         Object *objelements_;
    41     };
    42 
    43   private:
    44     void updateLengthAndElements(Zone *zone, unsigned length, Object *array) {
    45         length_ = length;
    46         write(zone, &objelements_, array);
    47     }
    48 
    49   public:
    50     static Array *NewFixed(Zone *zone, Handle<ArrayMap> map, Heap::Tenure = Heap::Tenure_Default);
    51     static Array *NewString(Zone *zone, Handle<ArrayMap> map, char *buffer, size_t length, Heap::Tenure = Heap::Tenure_Default);
    52     static Array *NewSized(Zone *zone, Handle<ArrayMap> map, int sizes[MAX_ARRAY_DEPTH], Heap::Tenure = Heap::Tenure_Default);
    53 
    54     static Array *New1D(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure = Heap::Tenure_Default);
    55     static Array *NewEmpty(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
    56     static Array *NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure);
    57 
    58     static Array *NewExternal(Zone *zone,
    59                               Handle<ArrayMap> map,
    60                               void *buffer,
    61                               unsigned length,
    62                               Heap::Tenure tenure = Heap::Tenure_Default);
    63 
    64     // Copies an array from one reference to another, obeying language semantics.
    65     static bool ShallowCopy(Zone *zone, Handle<Array> dest, Handle<Array> source);
    66 
    67     // Creates a full duplicate of an array, following all array references as if
    68     // they were fixed. Array references inside structs or objects use ShallowCopy
    69     // semantics, as this is only intended for duplicating array literals, which
    70     // cannot contain structs.
    71     static Array *DeepCopy(Zone *zone, Handle<Array> source, Heap::Tenure tenure);
    72 
    73     uint32 length() {
    74         return length_;
    75     }
    76 
    77     inline ArrayType *type();
    78 
    79     inline int *int32Vec();
    80     inline float *floatVec();
    81     inline char *chars();
    82     inline void *bytes();
    83 
    84     bool resize(Zone *zone, size_t newLength);
    85 
    86     static inline size_t SizeForElement(ArrayType *type) {
    87         if (type->contained()->isTraceable())
    88             return sizeof(ke::Object *);
    89         if (type->contained()->isInt32())
    90             return sizeof(int);
    91         if (type->contained()->primitive() == PrimitiveType_Char)
    92             return sizeof(char);
    93         assert(type->contained()->isFloat());
    94         return sizeof(float);
    95     }
    96 
    97     inline size_t objSize(ArrayMap *map);
    98 
    99     int readInt32(size_t index) {
   100         assert(index < length());
   101         return int32Vec()[index];
   102     }
   103     void writeInt32(size_t index, int i) {
   104         assert(index < length());
   105         int32Vec()[index] = i;
   106     }
   107     char readChar(size_t index) {
   108         assert(index < length());
   109         return chars()[index];
   110     }
   111     void writeChar(size_t index, char c) {
   112         assert(index < length());
   113         chars()[index] = c;
   114     }
   115     float readFloat(size_t index) {
   116         assert(index < length());
   117         return floatVec()[index];
   118     }
   119     void writeFloat(size_t index, float f) {
   120         assert(index < length());
   121         floatVec()[index] = f;
   122     }
   123     Object *readObject(size_t index) {
   124         return FixedArray::cast(objelements_)->at(index);
   125     }
   126     void writeObject(Zone *zone, size_t index, Object *ptr) {
   127         FixedArray::cast(objelements_)->set(zone, index, ptr);
   128     }
   129 
   130     // GC Descriptor.
   131     static inline size_t offsetOfElements() {
   132         return offsetof(Array, objelements_);
   133     }
   134     // End GC Descriptor.
   135 
   136     static Array *cast(Object *obj) {
   137         assert(!obj || obj->is(MapKind_Array));
   138         return reinterpret_cast<Array *>(obj);
   139     }
   140 };
   141 
   142 class ArrayMap : public Map
   143 {
   144     Barriered<ArrayType> type_;
   145 
   146   public:
   147     static ArrayMap *New(Zone *zone, Handle<ArrayType> type);
   148     static ArrayMap *Attach(Zone *zone, Handle<ArrayType> type);
   149 
   150     ArrayType *type() {
   151         return type_;
   152     }
   153 
   154     // GC Descriptor.
   155     static inline size_t offsetOfType() {
   156         return OFFSETOF(ArrayMap, type_);
   157     }
   158     // End GC Descriptor.
   159     
   160     static ArrayMap *cast(Object *obj) {
   161         assert(!obj || obj->is(MapKind_MetaArray));
   162         return reinterpret_cast<ArrayMap *>(obj);
   163     }
   164 };
   165 
   166 inline void *
   167 Array::bytes()
   168 {
   169     assert(!type()->contained()->isTraceable());
   170     assert(type()->hasInlineElements() ||
   171            type()->isExternalArray() ||
   172            !length() ||
   173            ByteArray::cast((Object *)elements_));
   174 
   175     return Address(elements_) + ByteArray::offsetToElements();
   176 }
   177 
   178 inline int *
   179 Array::int32Vec()
   180 {
   181     assert(type()->contained()->isInt32());
   182     return reinterpret_cast<int *>(bytes());
   183 }
   184 
   185 inline float *
   186 Array::floatVec()
   187 {
   188     assert(type()->contained()->isFloat());
   189     return reinterpret_cast<float *>(bytes());
   190 }
   191 
   192 inline char *
   193 Array::chars()
   194 {
   195     assert(type()->isCharArray());
   196     return reinterpret_cast<char *>(bytes());
   197 }
   198 
   199 inline ArrayType *
   200 Array::type()
   201 {
   202     return ArrayMap::cast(map())->type();
   203 }
   204 
   205 inline size_t
   206 Array::objSize(ArrayMap *map)
   207 {
   208     assert(this->map() == map);
   209     if (map->type()->hasInlineElements())
   210         return sizeof(Array) + Array::SizeForElement(map->type()) * length();
   211     return sizeof(Array);
   212 }
   213 
   214 }
   215 
   216 #endif // _include_jitcraft_array_h_