src/Array.h
author Michael Busby <prodigysim@gmail.com>
Mon Jun 10 01:50:18 2013 +0100 (2013-06-10)
changeset 264 70b8f318c379
parent 263 ba85a47ee414
permissions -rw-r--r--
Parse assignment RTL instead of LTR, fixes multiple assignment (bug 5420).
asherkin@263
     1
/* vim: set ts=4 sw=4 tw=99 et:
asherkin@263
     2
 *
asherkin@263
     3
 * Copyright (C) 2012 David Anderson
asherkin@263
     4
 *
asherkin@263
     5
 * This file is part of SourcePawn.
asherkin@263
     6
 *
asherkin@263
     7
 * SourcePawn is free software: you can redistribute it and/or modify it under
asherkin@263
     8
 * the terms of the GNU General Public License as published by the Free
asherkin@263
     9
 * Software Foundation, either version 3 of the License, or (at your option)
asherkin@263
    10
 * any later version.
asherkin@263
    11
 * 
asherkin@263
    12
 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
asherkin@263
    13
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
asherkin@263
    14
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
asherkin@263
    15
 *
asherkin@263
    16
 * You should have received a copy of the GNU General Public License along with
asherkin@263
    17
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
asherkin@263
    18
 */
asherkin@263
    19
#ifndef _include_jitcraft_array_h_
asherkin@263
    20
#define _include_jitcraft_array_h_
asherkin@263
    21
asherkin@263
    22
#include "Heap.h"
asherkin@263
    23
#include "Handles.h"
asherkin@263
    24
#include "Types.h"
asherkin@263
    25
#include "FixedArray.h"
asherkin@263
    26
asherkin@263
    27
namespace ke {
asherkin@263
    28
asherkin@263
    29
class ArrayMap;
asherkin@263
    30
asherkin@263
    31
class Array : public Object
asherkin@263
    32
{
asherkin@263
    33
    friend class ArrayMap;
asherkin@263
    34
asherkin@263
    35
  protected:
asherkin@263
    36
    // Note: we do not write barrier |elements_|, since it can be set to
asherkin@263
    37
    // arbitrary pointers.
asherkin@263
    38
    uint32 length_;
asherkin@263
    39
    union {
asherkin@263
    40
        void *elements_;
asherkin@263
    41
        Object *objelements_;
asherkin@263
    42
    };
asherkin@263
    43
asherkin@263
    44
  protected:
asherkin@263
    45
    void updateLengthAndElements(Zone *zone, unsigned length, Object *array) {
asherkin@263
    46
        length_ = length;
asherkin@263
    47
        write(zone, &objelements_, array);
asherkin@263
    48
    }
asherkin@263
    49
asherkin@263
    50
  public:
asherkin@263
    51
    static Array *NewFixed(Zone *zone, Handle<ArrayMap> map, Heap::Tenure = Heap::Tenure_Default);
asherkin@263
    52
    static Array *NewString(Zone *zone, Handle<ArrayMap> map, char *buffer, size_t length, Heap::Tenure = Heap::Tenure_Default);
asherkin@263
    53
    static Array *NewSized(Zone *zone, Handle<ArrayMap> map, int sizes[MAX_ARRAY_DEPTH], Heap::Tenure = Heap::Tenure_Default);
asherkin@263
    54
asherkin@263
    55
    static Array *New1D(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure = Heap::Tenure_Default);
asherkin@263
    56
    static Array *NewEmpty(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
asherkin@263
    57
    static Array *NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure);
asherkin@263
    58
asherkin@263
    59
    static Array *NewExternal(Zone *zone,
asherkin@263
    60
                              Handle<ArrayMap> map,
asherkin@263
    61
                              void *buffer,
asherkin@263
    62
                              unsigned length,
asherkin@263
    63
                              Heap::Tenure tenure = Heap::Tenure_Default);
asherkin@263
    64
asherkin@263
    65
    // Copies an array from one reference to another, obeying language semantics.
asherkin@263
    66
    static bool ShallowCopy(Zone *zone, Handle<Array> dest, Handle<Array> source);
asherkin@263
    67
asherkin@263
    68
    // Creates a full duplicate of an array, following all array references as if
asherkin@263
    69
    // they were fixed. Array references inside structs or objects use ShallowCopy
asherkin@263
    70
    // semantics, as this is only intended for duplicating array literals, which
asherkin@263
    71
    // cannot contain structs.
asherkin@263
    72
    static Array *DeepCopy(Zone *zone, Handle<Array> source, Heap::Tenure tenure);
asherkin@263
    73
asherkin@263
    74
    uint32 length() {
asherkin@263
    75
        return length_;
asherkin@263
    76
    }
asherkin@263
    77
asherkin@263
    78
    inline ArrayType *type();
asherkin@263
    79
asherkin@263
    80
    inline int *int32Vec();
asherkin@263
    81
    inline float *floatVec();
asherkin@263
    82
    inline char *chars();
asherkin@263
    83
    inline void *bytes();
asherkin@263
    84
asherkin@263
    85
    bool resize(Zone *zone, size_t newLength);
asherkin@263
    86
asherkin@263
    87
    static inline size_t SizeForElement(ArrayType *type) {
asherkin@263
    88
        if (type->contained()->isTraceable())
asherkin@263
    89
            return sizeof(ke::Object *);
asherkin@263
    90
        if (type->contained()->isInt32())
asherkin@263
    91
            return sizeof(int);
asherkin@263
    92
        if (type->contained()->primitive() == PrimitiveType_Char)
asherkin@263
    93
            return sizeof(char);
asherkin@263
    94
        assert(type->contained()->isFloat());
asherkin@263
    95
        return sizeof(float);
asherkin@263
    96
    }
asherkin@263
    97
asherkin@263
    98
    inline size_t objSize(ArrayMap *map);
asherkin@263
    99
asherkin@263
   100
    int readInt32(size_t index) {
asherkin@263
   101
        assert(index < length());
asherkin@263
   102
        return int32Vec()[index];
asherkin@263
   103
    }
asherkin@263
   104
    void writeInt32(size_t index, int i) {
asherkin@263
   105
        assert(index < length());
asherkin@263
   106
        int32Vec()[index] = i;
asherkin@263
   107
    }
asherkin@263
   108
    char readChar(size_t index) {
asherkin@263
   109
        assert(index < length());
asherkin@263
   110
        return chars()[index];
asherkin@263
   111
    }
asherkin@263
   112
    void writeChar(size_t index, char c) {
asherkin@263
   113
        assert(index < length());
asherkin@263
   114
        chars()[index] = c;
asherkin@263
   115
    }
asherkin@263
   116
    float readFloat(size_t index) {
asherkin@263
   117
        assert(index < length());
asherkin@263
   118
        return floatVec()[index];
asherkin@263
   119
    }
asherkin@263
   120
    void writeFloat(size_t index, float f) {
asherkin@263
   121
        assert(index < length());
asherkin@263
   122
        floatVec()[index] = f;
asherkin@263
   123
    }
asherkin@263
   124
    Object *readObject(size_t index) {
asherkin@263
   125
        return FixedArray::cast(objelements_)->at(index);
asherkin@263
   126
    }
asherkin@263
   127
    void writeObject(Zone *zone, size_t index, Object *ptr) {
asherkin@263
   128
        FixedArray::cast(objelements_)->set(zone, index, ptr);
asherkin@263
   129
    }
asherkin@263
   130
asherkin@263
   131
    // GC Descriptor.
asherkin@263
   132
    static inline size_t offsetOfElements() {
asherkin@263
   133
        return offsetof(Array, objelements_);
asherkin@263
   134
    }
asherkin@263
   135
    // End GC Descriptor.
asherkin@263
   136
asherkin@263
   137
    static Array *cast(Object *obj) {
asherkin@263
   138
        assert(!obj ||
asherkin@263
   139
               obj->is(MapKind_Array) ||
asherkin@263
   140
               obj->is(MapKind_DependentArray));
asherkin@263
   141
        return reinterpret_cast<Array *>(obj);
asherkin@263
   142
    }
asherkin@263
   143
};
asherkin@263
   144
asherkin@263
   145
class DependentArray : public Array
asherkin@263
   146
{
asherkin@263
   147
    Barriered<Array> root_;
asherkin@263
   148
asherkin@263
   149
  public:
asherkin@263
   150
    static Array *New(Zone *zone, Handle<Array> source, Handle<ArrayMap> map, unsigned index);
asherkin@263
   151
asherkin@263
   152
    // GC Descriptor.
asherkin@263
   153
    static inline size_t offsetOfRoot() {
asherkin@263
   154
        return offsetof(DependentArray, root_);
asherkin@263
   155
    }
asherkin@263
   156
    // End GC Descriptor.
asherkin@263
   157
asherkin@263
   158
    static DependentArray *cast(Object *obj) {
asherkin@263
   159
        assert(!obj || obj->is(MapKind_DependentArray));
asherkin@263
   160
        return reinterpret_cast<DependentArray *>(obj);
asherkin@263
   161
    }
asherkin@263
   162
};
asherkin@263
   163
asherkin@263
   164
class ArrayMap : public Map
asherkin@263
   165
{
asherkin@263
   166
    Barriered<ArrayType> type_;
asherkin@263
   167
asherkin@263
   168
  public:
asherkin@263
   169
    static ArrayMap *New(Zone *zone, Handle<ArrayType> type);
asherkin@263
   170
asherkin@263
   171
    // DependentArray maps are never attached, and are just free-floating,
asherkin@263
   172
    // rooted ultimately by the bytecode. A :TODO: that we might need to
asherkin@263
   173
    // cache these, or attach them somewhere saner like ArrayType, which
asherkin@263
   174
    // itself will eventually be cached.
asherkin@263
   175
    static ArrayMap *NewDependent(Zone *zone, Handle<ArrayType> type);
asherkin@263
   176
asherkin@263
   177
    ArrayType *type() {
asherkin@263
   178
        return type_;
asherkin@263
   179
    }
asherkin@263
   180
asherkin@263
   181
    // GC Descriptor.
asherkin@263
   182
    static inline size_t offsetOfType() {
asherkin@263
   183
        return OFFSETOF(ArrayMap, type_);
asherkin@263
   184
    }
asherkin@263
   185
    // End GC Descriptor.
asherkin@263
   186
    
asherkin@263
   187
    static ArrayMap *cast(Object *obj) {
asherkin@263
   188
        assert(!obj || obj->is(MapKind_MetaArray));
asherkin@263
   189
        return reinterpret_cast<ArrayMap *>(obj);
asherkin@263
   190
    }
asherkin@263
   191
};
asherkin@263
   192
asherkin@263
   193
inline void *
asherkin@263
   194
Array::bytes()
asherkin@263
   195
{
asherkin@263
   196
    assert(!type()->contained()->isTraceable());
asherkin@263
   197
    assert(type()->hasInlineElements() ||
asherkin@263
   198
           type()->isExternalArray() ||
asherkin@263
   199
           is(MapKind_DependentArray) ||
asherkin@263
   200
           !length() ||
asherkin@263
   201
           ByteArray::cast((Object *)elements_));
asherkin@263
   202
asherkin@263
   203
    return Address(elements_) + ByteArray::offsetToElements();
asherkin@263
   204
}
asherkin@263
   205
asherkin@263
   206
inline int *
asherkin@263
   207
Array::int32Vec()
asherkin@263
   208
{
asherkin@263
   209
    assert(type()->contained()->isInt32());
asherkin@263
   210
    return reinterpret_cast<int *>(bytes());
asherkin@263
   211
}
asherkin@263
   212
asherkin@263
   213
inline float *
asherkin@263
   214
Array::floatVec()
asherkin@263
   215
{
asherkin@263
   216
    assert(type()->contained()->isFloat());
asherkin@263
   217
    return reinterpret_cast<float *>(bytes());
asherkin@263
   218
}
asherkin@263
   219
asherkin@263
   220
inline char *
asherkin@263
   221
Array::chars()
asherkin@263
   222
{
asherkin@263
   223
    assert(type()->isCharArray());
asherkin@263
   224
    return reinterpret_cast<char *>(bytes());
asherkin@263
   225
}
asherkin@263
   226
asherkin@263
   227
inline ArrayType *
asherkin@263
   228
Array::type()
asherkin@263
   229
{
asherkin@263
   230
    return ArrayMap::cast(map())->type();
asherkin@263
   231
}
asherkin@263
   232
asherkin@263
   233
inline size_t
asherkin@263
   234
Array::objSize(ArrayMap *map)
asherkin@263
   235
{
asherkin@263
   236
    assert(this->map() == map);
asherkin@263
   237
    if (map->type()->hasInlineElements())
asherkin@263
   238
        return sizeof(Array) + Array::SizeForElement(map->type()) * length();
asherkin@263
   239
    return sizeof(Array);
asherkin@263
   240
}
asherkin@263
   241
asherkin@263
   242
}
asherkin@263
   243
asherkin@263
   244
#endif // _include_jitcraft_array_h_