src/Array.h
author David Anderson <dvander@alliedmods.net>
Tue Jan 01 20:06:25 2013 -0800 (2013-01-01)
changeset 253 544c478362c2
parent 247 7721042bdb67
child 256 3c184218462d
permissions -rw-r--r--
Add WIN32 define for MSVC builds.
     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   protected:
    36     // Note: we do not write barrier |elements_|, since it can be set to
    37     // arbitrary pointers.
    38     uint32 length_;
    39     union {
    40         void *elements_;
    41         Object *objelements_;
    42     };
    43 
    44   protected:
    45     void updateLengthAndElements(Zone *zone, unsigned length, Object *array) {
    46         length_ = length;
    47         write(zone, &objelements_, array);
    48     }
    49 
    50   public:
    51     static Array *NewFixed(Zone *zone, Handle<ArrayMap> map, Heap::Tenure = Heap::Tenure_Default);
    52     static Array *NewString(Zone *zone, Handle<ArrayMap> map, char *buffer, size_t length, Heap::Tenure = Heap::Tenure_Default);
    53     static Array *NewSized(Zone *zone, Handle<ArrayMap> map, int sizes[MAX_ARRAY_DEPTH], Heap::Tenure = Heap::Tenure_Default);
    54 
    55     static Array *New1D(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure = Heap::Tenure_Default);
    56     static Array *NewEmpty(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
    57     static Array *NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure);
    58 
    59     static Array *NewExternal(Zone *zone,
    60                               Handle<ArrayMap> map,
    61                               void *buffer,
    62                               unsigned length,
    63                               Heap::Tenure tenure = Heap::Tenure_Default);
    64 
    65     // Copies an array from one reference to another, obeying language semantics.
    66     static bool ShallowCopy(Zone *zone, Handle<Array> dest, Handle<Array> source);
    67 
    68     // Creates a full duplicate of an array, following all array references as if
    69     // they were fixed. Array references inside structs or objects use ShallowCopy
    70     // semantics, as this is only intended for duplicating array literals, which
    71     // cannot contain structs.
    72     static Array *DeepCopy(Zone *zone, Handle<Array> source, Heap::Tenure tenure);
    73 
    74     uint32 length() {
    75         return length_;
    76     }
    77 
    78     inline ArrayType *type();
    79 
    80     inline int *int32Vec();
    81     inline float *floatVec();
    82     inline char *chars();
    83     inline void *bytes();
    84 
    85     bool resize(Zone *zone, size_t newLength);
    86 
    87     static inline size_t SizeForElement(ArrayType *type) {
    88         if (type->contained()->isTraceable())
    89             return sizeof(ke::Object *);
    90         if (type->contained()->isInt32())
    91             return sizeof(int);
    92         if (type->contained()->primitive() == PrimitiveType_Char)
    93             return sizeof(char);
    94         assert(type->contained()->isFloat());
    95         return sizeof(float);
    96     }
    97 
    98     inline size_t objSize(ArrayMap *map);
    99 
   100     int readInt32(size_t index) {
   101         assert(index < length());
   102         return int32Vec()[index];
   103     }
   104     void writeInt32(size_t index, int i) {
   105         assert(index < length());
   106         int32Vec()[index] = i;
   107     }
   108     char readChar(size_t index) {
   109         assert(index < length());
   110         return chars()[index];
   111     }
   112     void writeChar(size_t index, char c) {
   113         assert(index < length());
   114         chars()[index] = c;
   115     }
   116     float readFloat(size_t index) {
   117         assert(index < length());
   118         return floatVec()[index];
   119     }
   120     void writeFloat(size_t index, float f) {
   121         assert(index < length());
   122         floatVec()[index] = f;
   123     }
   124     Object *readObject(size_t index) {
   125         return FixedArray::cast(objelements_)->at(index);
   126     }
   127     void writeObject(Zone *zone, size_t index, Object *ptr) {
   128         FixedArray::cast(objelements_)->set(zone, index, ptr);
   129     }
   130 
   131     // GC Descriptor.
   132     static inline size_t offsetOfElements() {
   133         return offsetof(Array, objelements_);
   134     }
   135     // End GC Descriptor.
   136 
   137     static Array *cast(Object *obj) {
   138         assert(!obj ||
   139                obj->is(MapKind_Array) ||
   140                obj->is(MapKind_DependentArray));
   141         return reinterpret_cast<Array *>(obj);
   142     }
   143 };
   144 
   145 class DependentArray : public Array
   146 {
   147     Barriered<Array> root_;
   148 
   149   public:
   150     static Array *New(Zone *zone, Handle<Array> source, Handle<ArrayMap> map, unsigned index);
   151 
   152     // GC Descriptor.
   153     static inline size_t offsetOfRoot() {
   154         return offsetof(DependentArray, root_);
   155     }
   156     // End GC Descriptor.
   157 
   158     static DependentArray *cast(Object *obj) {
   159         assert(!obj || obj->is(MapKind_DependentArray));
   160         return reinterpret_cast<DependentArray *>(obj);
   161     }
   162 };
   163 
   164 class ArrayMap : public Map
   165 {
   166     Barriered<ArrayType> type_;
   167 
   168   public:
   169     // The way array maps work is kind of clownshoes. In the future, these
   170     // should be created immediately (or lazily) on the Type directly, and not
   171     // manually created via ::Attach. :TODO: do this when we begin caching
   172     // array types.
   173     static ArrayMap *New(Zone *zone, Handle<ArrayType> type);
   174     static ArrayMap *Attach(Zone *zone, Handle<ArrayType> type);
   175 
   176     // DependentArray maps are never attached, and are just free-floating,
   177     // rooted ultimately by the bytecode. A :TODO: that we might need to
   178     // cache these, or attach them somewhere saner like ArrayType, which
   179     // itself will eventually be cached.
   180     static ArrayMap *NewDependent(Zone *zone, Handle<ArrayType> type);
   181 
   182     ArrayType *type() {
   183         return type_;
   184     }
   185 
   186     // GC Descriptor.
   187     static inline size_t offsetOfType() {
   188         return OFFSETOF(ArrayMap, type_);
   189     }
   190     // End GC Descriptor.
   191     
   192     static ArrayMap *cast(Object *obj) {
   193         assert(!obj || obj->is(MapKind_MetaArray));
   194         return reinterpret_cast<ArrayMap *>(obj);
   195     }
   196 };
   197 
   198 inline void *
   199 Array::bytes()
   200 {
   201     assert(!type()->contained()->isTraceable());
   202     assert(type()->hasInlineElements() ||
   203            type()->isExternalArray() ||
   204            is(MapKind_DependentArray) ||
   205            !length() ||
   206            ByteArray::cast((Object *)elements_));
   207 
   208     return Address(elements_) + ByteArray::offsetToElements();
   209 }
   210 
   211 inline int *
   212 Array::int32Vec()
   213 {
   214     assert(type()->contained()->isInt32());
   215     return reinterpret_cast<int *>(bytes());
   216 }
   217 
   218 inline float *
   219 Array::floatVec()
   220 {
   221     assert(type()->contained()->isFloat());
   222     return reinterpret_cast<float *>(bytes());
   223 }
   224 
   225 inline char *
   226 Array::chars()
   227 {
   228     assert(type()->isCharArray());
   229     return reinterpret_cast<char *>(bytes());
   230 }
   231 
   232 inline ArrayType *
   233 Array::type()
   234 {
   235     return ArrayMap::cast(map())->type();
   236 }
   237 
   238 inline size_t
   239 Array::objSize(ArrayMap *map)
   240 {
   241     assert(this->map() == map);
   242     if (map->type()->hasInlineElements())
   243         return sizeof(Array) + Array::SizeForElement(map->type()) * length();
   244     return sizeof(Array);
   245 }
   246 
   247 }
   248 
   249 #endif // _include_jitcraft_array_h_