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