dvander@187: /* vim: set ts=4 sw=4 tw=99 et: dvander@187: * dvander@12: * Copyright (C) 2012 David Anderson dvander@12: * dvander@187: * This file is part of SourcePawn. dvander@12: * dvander@187: * SourcePawn is free software: you can redistribute it and/or modify it under dvander@12: * the terms of the GNU General Public License as published by the Free dvander@12: * Software Foundation, either version 3 of the License, or (at your option) dvander@12: * any later version. dvander@12: * dvander@187: * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY dvander@12: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@12: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@12: * dvander@12: * You should have received a copy of the GNU General Public License along with dvander@187: * SourcePawn. If not, see http://www.gnu.org/licenses/. dvander@12: */ dvander@12: #ifndef _include_jitcraft_array_h_ dvander@12: #define _include_jitcraft_array_h_ dvander@12: dvander@12: #include "Heap.h" dvander@27: #include "Handles.h" dvander@12: #include "Types.h" dvander@188: #include "FixedArray.h" dvander@12: dvander@59: namespace ke { dvander@12: dvander@12: class ArrayMap; dvander@12: dvander@12: class Array : public Object dvander@12: { dvander@12: friend class ArrayMap; dvander@12: dvander@188: // Note: we do not write barrier |elements_|, since it can be set to dvander@188: // arbitrary pointers. dvander@188: uint32 length_; dvander@188: union { dvander@188: void *elements_; dvander@188: Object *objelements_; dvander@188: }; dvander@188: dvander@188: private: dvander@188: void updateLengthAndElements(Zone *zone, unsigned length, Object *array) { dvander@188: length_ = length; dvander@188: write(zone, &objelements_, array); dvander@188: } dvander@12: dvander@12: public: dvander@187: static Array *NewFixed(Zone *zone, Handle map, Heap::Tenure = Heap::Tenure_Default); dvander@234: static Array *NewString(Zone *zone, Handle map, char *buffer, size_t length, Heap::Tenure = Heap::Tenure_Default); dvander@187: static Array *NewSized(Zone *zone, Handle map, int sizes[MAX_ARRAY_DEPTH], Heap::Tenure = Heap::Tenure_Default); dvander@12: dvander@187: static Array *New1D(Zone *zone, Handle map, uint32 elements, Heap::Tenure tenure = Heap::Tenure_Default); dvander@187: static Array *NewEmpty(Zone *zone, Handle map, Heap::Tenure tenure = Heap::Tenure_Default); dvander@187: static Array *NewRaw(Zone *zone, Handle map, unsigned nelements, Heap::Tenure tenure); dvander@187: dvander@188: static Array *NewExternal(Zone *zone, dvander@188: Handle map, dvander@188: void *buffer, dvander@188: unsigned length, dvander@188: Heap::Tenure tenure = Heap::Tenure_Default); dvander@188: dvander@234: // Copies an array from one reference to another, obeying language semantics. dvander@234: static bool ShallowCopy(Zone *zone, Handle dest, Handle source); dvander@234: dvander@234: // Creates a full duplicate of an array, following all array references as if dvander@234: // they were fixed. Array references inside structs or objects use ShallowCopy dvander@234: // semantics, as this is only intended for duplicating array literals, which dvander@234: // cannot contain structs. dvander@234: static Array *DeepCopy(Zone *zone, Handle source, Heap::Tenure tenure); dvander@234: dvander@155: uint32 length() { dvander@188: return length_; dvander@12: } dvander@188: dvander@209: inline ArrayType *type(); dvander@21: dvander@12: inline int *int32Vec(); dvander@12: inline float *floatVec(); dvander@21: inline char *chars(); dvander@188: inline void *bytes(); dvander@188: dvander@234: bool resize(Zone *zone, size_t newLength); dvander@21: dvander@209: static inline size_t SizeForElement(ArrayType *type) { dvander@188: if (type->contained()->isTraceable()) dvander@188: return sizeof(ke::Object *); dvander@188: if (type->contained()->isInt32()) dvander@188: return sizeof(int); dvander@188: if (type->contained()->primitive() == PrimitiveType_Char) dvander@188: return sizeof(char); dvander@188: assert(type->contained()->isFloat()); dvander@188: return sizeof(float); dvander@188: } dvander@188: dvander@188: inline size_t objSize(ArrayMap *map); dvander@12: dvander@12: int readInt32(size_t index) { dvander@155: assert(index < length()); dvander@12: return int32Vec()[index]; dvander@12: } dvander@12: void writeInt32(size_t index, int i) { dvander@155: assert(index < length()); dvander@12: int32Vec()[index] = i; dvander@12: } dvander@21: char readChar(size_t index) { dvander@155: assert(index < length()); dvander@21: return chars()[index]; dvander@21: } dvander@21: void writeChar(size_t index, char c) { dvander@155: assert(index < length()); dvander@21: chars()[index] = c; dvander@21: } dvander@12: float readFloat(size_t index) { dvander@155: assert(index < length()); dvander@12: return floatVec()[index]; dvander@12: } dvander@12: void writeFloat(size_t index, float f) { dvander@155: assert(index < length()); dvander@12: floatVec()[index] = f; dvander@12: } dvander@12: Object *readObject(size_t index) { dvander@188: return FixedArray::cast(objelements_)->at(index); dvander@12: } dvander@12: void writeObject(Zone *zone, size_t index, Object *ptr) { dvander@188: FixedArray::cast(objelements_)->set(zone, index, ptr); dvander@12: } dvander@12: dvander@188: // GC Descriptor. dvander@188: static inline size_t offsetOfElements() { dvander@188: return offsetof(Array, objelements_); dvander@65: } dvander@188: // End GC Descriptor. dvander@44: dvander@12: static Array *cast(Object *obj) { dvander@31: assert(!obj || obj->is(MapKind_Array)); dvander@12: return reinterpret_cast(obj); dvander@12: } dvander@12: }; dvander@12: dvander@12: class ArrayMap : public Map dvander@12: { dvander@209: Barriered type_; dvander@12: dvander@12: public: dvander@209: static ArrayMap *New(Zone *zone, Handle type); dvander@209: static ArrayMap *Attach(Zone *zone, Handle type); dvander@12: dvander@209: ArrayType *type() { dvander@13: return type_; dvander@12: } dvander@44: dvander@44: // GC Descriptor. dvander@44: static inline size_t offsetOfType() { danderson@91: return OFFSETOF(ArrayMap, type_); dvander@44: } dvander@44: // End GC Descriptor. dvander@12: dvander@12: static ArrayMap *cast(Object *obj) { dvander@12: assert(!obj || obj->is(MapKind_MetaArray)); dvander@12: return reinterpret_cast(obj); dvander@12: } dvander@12: }; dvander@12: dvander@188: inline void * dvander@188: Array::bytes() dvander@188: { dvander@188: assert(!type()->contained()->isTraceable()); dvander@188: assert(type()->hasInlineElements() || dvander@188: type()->isExternalArray() || dvander@188: !length() || dvander@188: ByteArray::cast((Object *)elements_)); dvander@188: dvander@188: return Address(elements_) + ByteArray::offsetToElements(); dvander@188: } dvander@188: dvander@12: inline int * dvander@12: Array::int32Vec() dvander@12: { dvander@21: assert(type()->contained()->isInt32()); dvander@188: return reinterpret_cast(bytes()); dvander@12: } dvander@12: dvander@12: inline float * dvander@12: Array::floatVec() dvander@12: { dvander@21: assert(type()->contained()->isFloat()); dvander@188: return reinterpret_cast(bytes()); dvander@17: } dvander@17: dvander@21: inline char * dvander@21: Array::chars() dvander@21: { dvander@188: assert(type()->isCharArray()); dvander@188: return reinterpret_cast(bytes()); dvander@21: } dvander@21: dvander@209: inline ArrayType * dvander@21: Array::type() dvander@21: { dvander@21: return ArrayMap::cast(map())->type(); dvander@21: } dvander@21: dvander@21: inline size_t dvander@188: Array::objSize(ArrayMap *map) dvander@21: { dvander@188: assert(this->map() == map); dvander@188: if (map->type()->hasInlineElements()) dvander@188: return sizeof(Array) + Array::SizeForElement(map->type()) * length(); dvander@188: return sizeof(Array); dvander@21: } dvander@21: dvander@12: } dvander@12: dvander@12: #endif // _include_jitcraft_array_h_