src/Array.h
author David Anderson <dvander@alliedmods.net>
Sun Jan 06 13:52:21 2013 -0800 (2013-01-06)
changeset 256 3c184218462d
parent 247 7721042bdb67
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_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     static ArrayMap *New(Zone *zone, Handle<ArrayType> type);
   170 
   171     // DependentArray maps are never attached, and are just free-floating,
   172     // rooted ultimately by the bytecode. A :TODO: that we might need to
   173     // cache these, or attach them somewhere saner like ArrayType, which
   174     // itself will eventually be cached.
   175     static ArrayMap *NewDependent(Zone *zone, Handle<ArrayType> type);
   176 
   177     ArrayType *type() {
   178         return type_;
   179     }
   180 
   181     // GC Descriptor.
   182     static inline size_t offsetOfType() {
   183         return OFFSETOF(ArrayMap, type_);
   184     }
   185     // End GC Descriptor.
   186     
   187     static ArrayMap *cast(Object *obj) {
   188         assert(!obj || obj->is(MapKind_MetaArray));
   189         return reinterpret_cast<ArrayMap *>(obj);
   190     }
   191 };
   192 
   193 inline void *
   194 Array::bytes()
   195 {
   196     assert(!type()->contained()->isTraceable());
   197     assert(type()->hasInlineElements() ||
   198            type()->isExternalArray() ||
   199            is(MapKind_DependentArray) ||
   200            !length() ||
   201            ByteArray::cast((Object *)elements_));
   202 
   203     return Address(elements_) + ByteArray::offsetToElements();
   204 }
   205 
   206 inline int *
   207 Array::int32Vec()
   208 {
   209     assert(type()->contained()->isInt32());
   210     return reinterpret_cast<int *>(bytes());
   211 }
   212 
   213 inline float *
   214 Array::floatVec()
   215 {
   216     assert(type()->contained()->isFloat());
   217     return reinterpret_cast<float *>(bytes());
   218 }
   219 
   220 inline char *
   221 Array::chars()
   222 {
   223     assert(type()->isCharArray());
   224     return reinterpret_cast<char *>(bytes());
   225 }
   226 
   227 inline ArrayType *
   228 Array::type()
   229 {
   230     return ArrayMap::cast(map())->type();
   231 }
   232 
   233 inline size_t
   234 Array::objSize(ArrayMap *map)
   235 {
   236     assert(this->map() == map);
   237     if (map->type()->hasInlineElements())
   238         return sizeof(Array) + Array::SizeForElement(map->type()) * length();
   239     return sizeof(Array);
   240 }
   241 
   242 }
   243 
   244 #endif // _include_jitcraft_array_h_