src/Array.h
author David Anderson <dvander@alliedmods.net>
Sat Sep 15 17:39:45 2012 -0700 (2012-09-15)
changeset 184 387d76b1e981
parent 169 0456a16c2a63
child 185 10936f3a2ba3
permissions -rw-r--r--
Add support for array reference semantics.
     1 /*
     2  * Copyright (C) 2012 David Anderson
     3  *
     4  * This file is part of JITCraft.
     5  *
     6  * JITCraft is free software: you can redistribute it and/or modify it under
     7  * the terms of the GNU General Public License as published by the Free
     8  * Software Foundation, either version 3 of the License, or (at your option)
     9  * any later version.
    10  * 
    11  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along with
    16  * JITCraft. If not, see http://www.gnu.org/licenses/.
    17  */
    18 #ifndef _include_jitcraft_array_h_
    19 #define _include_jitcraft_array_h_
    20 
    21 #include "Heap.h"
    22 #include "Handles.h"
    23 #include "Types.h"
    24 
    25 namespace ke {
    26 
    27 class ArrayMap;
    28 
    29 class Array : public Object
    30 {
    31     friend class ArrayMap;
    32 
    33     uint32 nelements_;
    34     void *elements_;
    35 
    36   public:
    37     static Array *New(Zone *zone, Handle<ArrayMap> map, uint32 elements,
    38                       Heap::Tenure = Heap::Tenure_Default);
    39     static Array *NewString(Zone *zone, Handle<ArrayMap> map, Address buffer, size_t length, Heap::Tenure = Heap::Tenure_Default);
    40     static Array *NewExternal(Zone *zone, Handle<ArrayMap> map, uint32 nelements,
    41                               void *elements, Heap::Tenure = Heap::Tenure_Default);
    42 
    43     uint32 length() {
    44         return nelements_;
    45     }
    46     void *vec() {
    47         return elements_;
    48     }
    49 
    50     inline int *int32Vec();
    51     inline float *floatVec();
    52     inline Object **objVec();
    53     inline char *chars();
    54 
    55     inline Type *type();
    56     inline size_t elementSize();
    57 
    58     int readInt32(size_t index) {
    59         assert(index < length());
    60         return int32Vec()[index];
    61     }
    62     void writeInt32(size_t index, int i) {
    63         assert(index < length());
    64         int32Vec()[index] = i;
    65     }
    66     char readChar(size_t index) {
    67         assert(index < length());
    68         return chars()[index];
    69     }
    70     void writeChar(size_t index, char c) {
    71         assert(index < length());
    72         chars()[index] = c;
    73     }
    74     float readFloat(size_t index) {
    75         assert(index < length());
    76         return floatVec()[index];
    77     }
    78     void writeFloat(size_t index, float f) {
    79         assert(index < length());
    80         floatVec()[index] = f;
    81     }
    82     inline void *slotPtr(size_t index);
    83     Object *readObject(size_t index) {
    84         assert(index < length());
    85         return objVec()[index];
    86     }
    87     void writeObject(Zone *zone, size_t index, Object *ptr) {
    88         assert(index < length());
    89         write(zone, &objVec()[index], ptr);
    90     }
    91 
    92     bool isExternal() {
    93         // Inline arrays always have their elements pointing at the next slot.
    94         Address buffer = reinterpret_cast<Address>(elements_);
    95         return buffer != reinterpret_cast<Address>(this + 1);
    96     }
    97 
    98     static inline size_t SizeOf(Array *array) {
    99         if (array->isExternal())
   100             return sizeof(Array);
   101         return sizeof(Array) + array->length() * array->elementSize();
   102     }
   103 
   104     static Array *cast(Object *obj) {
   105         assert(!obj || obj->is(MapKind_Array));
   106         return reinterpret_cast<Array *>(obj);
   107     }
   108 };
   109 
   110 class ArrayMap : public Map
   111 {
   112     Barriered<Type> type_;
   113 
   114   public:
   115     static ArrayMap *New(Zone *zone, Handle<Type> type);
   116     static ArrayMap *Attach(Zone *zone, Handle<Type> type);
   117 
   118     Type *type() {
   119         return type_;
   120     }
   121 
   122     // GC Descriptor.
   123     static inline size_t offsetOfType() {
   124         return OFFSETOF(ArrayMap, type_);
   125     }
   126     // End GC Descriptor.
   127     
   128     static ArrayMap *cast(Object *obj) {
   129         assert(!obj || obj->is(MapKind_MetaArray));
   130         return reinterpret_cast<ArrayMap *>(obj);
   131     }
   132 };
   133 
   134 inline int *
   135 Array::int32Vec()
   136 {
   137     assert(type()->levels() == 1);
   138     assert(type()->contained()->isInt32());
   139     return reinterpret_cast<int *>(vec());
   140 }
   141 
   142 inline float *
   143 Array::floatVec()
   144 {
   145     assert(type()->levels() == 1);
   146     assert(type()->contained()->isFloat());
   147     return reinterpret_cast<float *>(vec());
   148 }
   149 
   150 inline Object **
   151 Array::objVec()
   152 {
   153     assert(type()->contained()->isTraceable());
   154     return reinterpret_cast<Object **>(vec());
   155 }
   156 
   157 inline void *
   158 Array::slotPtr(size_t index)
   159 {
   160     assert(type()->contained()->primitive() == PrimitiveType_Int32 ||
   161            type()->contained()->primitive() == PrimitiveType_Float);
   162     assert(index < length());
   163     return reinterpret_cast<int *>(vec()) + index;
   164 }
   165 
   166 inline char *
   167 Array::chars()
   168 {
   169     assert(type()->levels() == 1);
   170     assert(type()->contained()->primitive() == PrimitiveType_Char);
   171     return reinterpret_cast<char *>(vec());
   172 }
   173 
   174 inline Type *
   175 Array::type()
   176 {
   177     return ArrayMap::cast(map())->type();
   178 }
   179 
   180 inline size_t
   181 Array::elementSize()
   182 {
   183     assert(type()->isArray());
   184     if (type()->contained()->isArray())
   185         return sizeof(Object *);
   186     switch (type()->contained()->primitive()) {
   187       case PrimitiveType_Float:
   188         return sizeof(float);
   189       case PrimitiveType_Int32:
   190         return sizeof(int);
   191       default:
   192         assert(type()->contained()->primitive() == PrimitiveType_Char);
   193         return sizeof(char);
   194     }
   195 }
   196 
   197 }
   198 
   199 #endif // _include_jitcraft_array_h_