Restructure Array so the elements vector can be replaced.
Restructure Array so the elements vector can be replaced.
1.1 --- a/src/API.cpp Sun Sep 16 19:02:23 2012 -0700
1.2 +++ b/src/API.cpp Sun Sep 16 21:34:10 2012 -0700
1.3 @@ -489,34 +489,36 @@
1.4
1.5 case Ke::Parameter::Array:
1.6 {
1.7 - ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->genericArrayMap());
1.8 + ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->externalGenericArrayMap());
1.9 if (params[i].writeback()) {
1.10 - slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].length(),
1.11 - params[i].buffer(), Heap::Tenure_Stack);
1.12 + slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].buffer(),
1.13 + params[i].length(), Heap::Tenure_Stack);
1.14 if (!slot.obj)
1.15 return false;
1.16 } else {
1.17 Array *array = Array::New1D(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
1.18 if (!slot.obj)
1.19 return false;
1.20 - memcpy(array->vec(), params[i].buffer(), params[i].length() * sizeof(int));
1.21 + if (params[i].length())
1.22 + memcpy(array->bytes(), params[i].buffer(), params[i].length() * sizeof(int));
1.23 }
1.24 break;
1.25 }
1.26
1.27 case Ke::Parameter::CharArray:
1.28 {
1.29 - ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->charArrayMap());
1.30 + ke::Local<ke::ArrayMap> map(ke::ZONE(), ke::ZONE()->externalCharArrayMap());
1.31 if (params[i].writeback()) {
1.32 - slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].length(),
1.33 - params[i].buffer(), Heap::Tenure_Stack);
1.34 + slot.obj = Array::NewExternal(ke::ZONE(), map, params[i].buffer(),
1.35 + params[i].length(), Heap::Tenure_Stack);
1.36 if (!slot.obj)
1.37 return false;
1.38 } else {
1.39 Array *array = Array::New1D(ke::ZONE(), map, params[i].length(), Heap::Tenure_Stack);
1.40 if (!slot.obj)
1.41 return false;
1.42 - memcpy(array->vec(), params[i].buffer(), params[i].length() * sizeof(char));
1.43 + if (params[i].length())
1.44 + memcpy(array->bytes(), params[i].buffer(), params[i].length() * sizeof(char));
1.45 }
1.46 break;
1.47 }
2.1 --- a/src/Array.cpp Sun Sep 16 19:02:23 2012 -0700
2.2 +++ b/src/Array.cpp Sun Sep 16 21:34:10 2012 -0700
2.3 @@ -18,6 +18,7 @@
2.4 */
2.5 #include <string.h>
2.6 #include "Array.h"
2.7 +#include "FixedArray.h"
2.8 #include "Heap.h"
2.9 #include "Zone.h"
2.10 #include "Structures.h"
2.11 @@ -58,37 +59,60 @@
2.12 return map;
2.13 }
2.14
2.15 -static inline size_t
2.16 -SizeFor(Type *type, unsigned elements)
2.17 -{
2.18 - if (type->contained()->isTraceable())
2.19 - return sizeof(Array) + elements * sizeof(ke::Object *);
2.20 - if (type->contained()->isInt32())
2.21 - return sizeof(Array) + elements * sizeof(int);
2.22 - if (type->contained()->primitive() == PrimitiveType_Char)
2.23 - return sizeof(Array) + elements * sizeof(char);
2.24 - assert(type->contained()->isFloat());
2.25 - return elements * sizeof(float);
2.26 -}
2.27 -
2.28 Array *
2.29 Array::NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure)
2.30 {
2.31 - if (nelements > (INT_MAX / SizeFor(map->type(), 1))) {
2.32 + if (nelements > (INT_MAX / SizeForElement(map->type()))) {
2.33 zone->reportError(Message_ArraySizeTooBig);
2.34 return NULL;
2.35 }
2.36
2.37 - size_t elementBytes = SizeFor(map->type(), nelements);
2.38 - size_t bytes = sizeof(Array) + elementBytes;
2.39 + size_t bytes = sizeof(Array);
2.40 + if (map->type()->hasInlineElements())
2.41 + bytes += SizeForElement(map->type()) * nelements;
2.42 +
2.43 Local<Array> array(zone, Array::cast(zone->allocate(map, bytes, tenure)));
2.44 if (!array)
2.45 return NULL;
2.46
2.47 - array->nelements_ = nelements;
2.48 - array->elements_ = (Array *)array + 1;
2.49 - memset(array->vec(), 0, elementBytes);
2.50 + array->length_ = 0;
2.51 + array->elements_ = NULL;
2.52 +
2.53 + if (map->type()->hasInlineElements()) {
2.54 + // This must be a fixed array containing no traceables.
2.55 + assert(nelements > 0);
2.56 + assert(map->type()->isFixedLength());
2.57 + assert(!map->type()->contained()->isTraceable());
2.58 +
2.59 + // Compute an interior |elements_| pointer, such that if elements_
2.60 + // is accessed like a FixedArray, we reach the appropriate vector.
2.61 + array->elements_ = Address((Array *)array + 1) - ByteArray::offsetToElements();
2.62 + array->length_ = nelements;
2.63 + memset(array->bytes(), 0, SizeForElement(map->type()) * nelements);
2.64 + return array;
2.65 + }
2.66
2.67 + // If there is nothing to allocate, we don't bother creating elements yet.
2.68 + if (!nelements)
2.69 + return array;
2.70 +
2.71 + if (!map->type()->contained()->isTraceable()) {
2.72 + size_t nbytes = SizeForElement(map->type()) * nelements;
2.73 + Local<ByteArray> elements(zone, ByteArray::New(zone, nbytes, tenure));
2.74 + if (!elements)
2.75 + return NULL;
2.76 +
2.77 + array->updateLengthAndElements(zone, nelements, elements);
2.78 + return array;
2.79 + }
2.80 +
2.81 + Local<FixedArray> elements(zone, FixedArray::New(zone, nelements, tenure));
2.82 + if (!elements)
2.83 + return NULL;
2.84 +
2.85 + array->updateLengthAndElements(zone, nelements, elements);
2.86 +
2.87 + // If this is an array of structs, we're required to allocate those structs now.
2.88 if (map->type()->contained()->isStruct()) {
2.89 Local<StructMap> childMap(zone, StructMap::cast(map->type()->contained()->newMap()));
2.90 Local<Struct> child(zone);
2.91 @@ -97,7 +121,7 @@
2.92 if (!child)
2.93 return NULL;
2.94
2.95 - array->writeObject(zone, i, child);
2.96 + elements->set(zone, i, child);
2.97 }
2.98 }
2.99
2.100 @@ -211,15 +235,15 @@
2.101 }
2.102
2.103 Array *
2.104 -Array::NewExternal(Zone *zone, Handle<ArrayMap> map, uint32 nelements, void *buffer,
2.105 +Array::NewExternal(Zone *zone, Handle<ArrayMap> map, void *buffer, unsigned length,
2.106 Heap::Tenure tenure)
2.107 {
2.108 Local<Array> array(zone, Array::cast(zone->allocate(map, sizeof(Array), tenure)));
2.109 if (!array)
2.110 return NULL;
2.111
2.112 - array->nelements_ = nelements;
2.113 - array->elements_ = buffer;
2.114 + array->length_ = length;
2.115 + array->elements_ = Address(buffer) - ByteArray::offsetToElements();
2.116 return array;
2.117 }
2.118
3.1 --- a/src/Array.h Sun Sep 16 19:02:23 2012 -0700
3.2 +++ b/src/Array.h Sun Sep 16 21:34:10 2012 -0700
3.3 @@ -22,6 +22,7 @@
3.4 #include "Heap.h"
3.5 #include "Handles.h"
3.6 #include "Types.h"
3.7 +#include "FixedArray.h"
3.8
3.9 namespace ke {
3.10
3.11 @@ -31,34 +32,59 @@
3.12 {
3.13 friend class ArrayMap;
3.14
3.15 - uint32 nelements_;
3.16 - void *elements_;
3.17 + // Note: we do not write barrier |elements_|, since it can be set to
3.18 + // arbitrary pointers.
3.19 + uint32 length_;
3.20 + union {
3.21 + void *elements_;
3.22 + Object *objelements_;
3.23 + };
3.24 +
3.25 + private:
3.26 + void updateLengthAndElements(Zone *zone, unsigned length, Object *array) {
3.27 + length_ = length;
3.28 + write(zone, &objelements_, array);
3.29 + }
3.30
3.31 public:
3.32 static Array *NewFixed(Zone *zone, Handle<ArrayMap> map, Heap::Tenure = Heap::Tenure_Default);
3.33 static Array *NewString(Zone *zone, Handle<ArrayMap> map, Address buffer, size_t length, Heap::Tenure = Heap::Tenure_Default);
3.34 static Array *NewSized(Zone *zone, Handle<ArrayMap> map, int sizes[MAX_ARRAY_DEPTH], Heap::Tenure = Heap::Tenure_Default);
3.35 - static Array *NewExternal(Zone *zone, Handle<ArrayMap> map, uint32 nelements,
3.36 - void *elements, Heap::Tenure = Heap::Tenure_Default);
3.37
3.38 static Array *New1D(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure = Heap::Tenure_Default);
3.39 static Array *NewEmpty(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure = Heap::Tenure_Default);
3.40 static Array *NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure);
3.41
3.42 + static Array *NewExternal(Zone *zone,
3.43 + Handle<ArrayMap> map,
3.44 + void *buffer,
3.45 + unsigned length,
3.46 + Heap::Tenure tenure = Heap::Tenure_Default);
3.47 +
3.48 uint32 length() {
3.49 - return nelements_;
3.50 + return length_;
3.51 }
3.52 - void *vec() {
3.53 - return elements_;
3.54 - }
3.55 +
3.56 + inline Type *type();
3.57
3.58 inline int *int32Vec();
3.59 inline float *floatVec();
3.60 - inline Object **objVec();
3.61 inline char *chars();
3.62 + inline void *bytes();
3.63 +
3.64
3.65 - inline Type *type();
3.66 - inline size_t elementSize();
3.67 + static inline size_t SizeForElement(Type *type) {
3.68 + if (type->contained()->isTraceable())
3.69 + return sizeof(ke::Object *);
3.70 + if (type->contained()->isInt32())
3.71 + return sizeof(int);
3.72 + if (type->contained()->primitive() == PrimitiveType_Char)
3.73 + return sizeof(char);
3.74 + assert(type->contained()->isFloat());
3.75 + return sizeof(float);
3.76 + }
3.77 +
3.78 + inline size_t objSize(ArrayMap *map);
3.79
3.80 int readInt32(size_t index) {
3.81 assert(index < length());
3.82 @@ -84,27 +110,18 @@
3.83 assert(index < length());
3.84 floatVec()[index] = f;
3.85 }
3.86 - inline void *slotPtr(size_t index);
3.87 Object *readObject(size_t index) {
3.88 - assert(index < length());
3.89 - return objVec()[index];
3.90 + return FixedArray::cast(objelements_)->at(index);
3.91 }
3.92 void writeObject(Zone *zone, size_t index, Object *ptr) {
3.93 - assert(index < length());
3.94 - write(zone, &objVec()[index], ptr);
3.95 + FixedArray::cast(objelements_)->set(zone, index, ptr);
3.96 }
3.97
3.98 - bool isExternal() {
3.99 - // Inline arrays always have their elements pointing at the next slot.
3.100 - Address buffer = reinterpret_cast<Address>(elements_);
3.101 - return buffer != reinterpret_cast<Address>(this + 1);
3.102 + // GC Descriptor.
3.103 + static inline size_t offsetOfElements() {
3.104 + return offsetof(Array, objelements_);
3.105 }
3.106 -
3.107 - static inline size_t SizeOf(Array *array) {
3.108 - if (array->isExternal())
3.109 - return sizeof(Array);
3.110 - return sizeof(Array) + array->length() * array->elementSize();
3.111 - }
3.112 + // End GC Descriptor.
3.113
3.114 static Array *cast(Object *obj) {
3.115 assert(!obj || obj->is(MapKind_Array));
3.116 @@ -136,44 +153,37 @@
3.117 }
3.118 };
3.119
3.120 +inline void *
3.121 +Array::bytes()
3.122 +{
3.123 + assert(!type()->contained()->isTraceable());
3.124 + assert(type()->hasInlineElements() ||
3.125 + type()->isExternalArray() ||
3.126 + !length() ||
3.127 + ByteArray::cast((Object *)elements_));
3.128 +
3.129 + return Address(elements_) + ByteArray::offsetToElements();
3.130 +}
3.131 +
3.132 inline int *
3.133 Array::int32Vec()
3.134 {
3.135 - assert(type()->levels() == 1);
3.136 assert(type()->contained()->isInt32());
3.137 - return reinterpret_cast<int *>(vec());
3.138 + return reinterpret_cast<int *>(bytes());
3.139 }
3.140
3.141 inline float *
3.142 Array::floatVec()
3.143 {
3.144 - assert(type()->levels() == 1);
3.145 assert(type()->contained()->isFloat());
3.146 - return reinterpret_cast<float *>(vec());
3.147 -}
3.148 -
3.149 -inline Object **
3.150 -Array::objVec()
3.151 -{
3.152 - assert(type()->contained()->isTraceable());
3.153 - return reinterpret_cast<Object **>(vec());
3.154 -}
3.155 -
3.156 -inline void *
3.157 -Array::slotPtr(size_t index)
3.158 -{
3.159 - assert(type()->contained()->primitive() == PrimitiveType_Int32 ||
3.160 - type()->contained()->primitive() == PrimitiveType_Float);
3.161 - assert(index < length());
3.162 - return reinterpret_cast<int *>(vec()) + index;
3.163 + return reinterpret_cast<float *>(bytes());
3.164 }
3.165
3.166 inline char *
3.167 Array::chars()
3.168 {
3.169 - assert(type()->levels() == 1);
3.170 - assert(type()->contained()->primitive() == PrimitiveType_Char);
3.171 - return reinterpret_cast<char *>(vec());
3.172 + assert(type()->isCharArray());
3.173 + return reinterpret_cast<char *>(bytes());
3.174 }
3.175
3.176 inline Type *
3.177 @@ -183,20 +193,12 @@
3.178 }
3.179
3.180 inline size_t
3.181 -Array::elementSize()
3.182 +Array::objSize(ArrayMap *map)
3.183 {
3.184 - assert(type()->isArray());
3.185 - if (type()->contained()->isArray())
3.186 - return sizeof(Object *);
3.187 - switch (type()->contained()->primitive()) {
3.188 - case PrimitiveType_Float:
3.189 - return sizeof(float);
3.190 - case PrimitiveType_Int32:
3.191 - return sizeof(int);
3.192 - default:
3.193 - assert(type()->contained()->primitive() == PrimitiveType_Char);
3.194 - return sizeof(char);
3.195 - }
3.196 + assert(this->map() == map);
3.197 + if (map->type()->hasInlineElements())
3.198 + return sizeof(Array) + Array::SizeForElement(map->type()) * length();
3.199 + return sizeof(Array);
3.200 }
3.201
3.202 }
4.1 --- a/src/BytecodeCompiler.cpp Sun Sep 16 19:02:23 2012 -0700
4.2 +++ b/src/BytecodeCompiler.cpp Sun Sep 16 21:34:10 2012 -0700
4.3 @@ -1049,12 +1049,6 @@
4.4 Variable *var = arg->toNameProxy()->binding()->toVariable();
4.5 __ note_position(node->pos());
4.6 __ newref(var);
4.7 - } else if (arg->isIndexExpression()) {
4.8 - IndexExpression *expr = arg->toIndexExpression();
4.9 - expr->left()->accept(this);
4.10 - expr->right()->accept(this);
4.11 - __ note_position(expr->pos());
4.12 - __ arrayref_lifo();
4.13 } else if (arg->isFieldExpression()) {
4.14 FieldExpression *expr = arg->toFieldExpression();
4.15 expr->left()->accept(this);
5.1 --- a/src/BytecodeEmitter.h Sun Sep 16 19:02:23 2012 -0700
5.2 +++ b/src/BytecodeEmitter.h Sun Sep 16 21:34:10 2012 -0700
5.3 @@ -491,11 +491,6 @@
5.4 singleByteOp(OP_SLOTREF_LIFO);
5.5 markOop(1);
5.6 }
5.7 - void arrayref_lifo() {
5.8 - recordOops();
5.9 - singleByteOp(OP_ARRAYREF_LIFO);
5.10 - markOop(1);
5.11 - }
5.12 void fieldref_lifo(unsigned index) {
5.13 recordOops();
5.14 ensure(OP_FIELDREF_LIFO_LENGTH);
6.1 --- a/src/FixedArray.cpp Sun Sep 16 19:02:23 2012 -0700
6.2 +++ b/src/FixedArray.cpp Sun Sep 16 21:34:10 2012 -0700
6.3 @@ -75,3 +75,4 @@
6.4 memset(array->raw(), 0, length);
6.5 return array;
6.6 }
6.7 +
7.1 --- a/src/FixedArray.h Sun Sep 16 19:02:23 2012 -0700
7.2 +++ b/src/FixedArray.h Sun Sep 16 21:34:10 2012 -0700
7.3 @@ -51,7 +51,7 @@
7.4 return SizeFor(length());
7.5 }
7.6
7.7 - static size_t SizeFor(unsigned length) {
7.8 + static inline size_t SizeFor(unsigned length) {
7.9 return sizeof(FixedArray) + sizeof(Object *) * length;
7.10 }
7.11
7.12 @@ -74,13 +74,17 @@
7.13 return length_;
7.14 }
7.15 Address raw() {
7.16 - return reinterpret_cast<uint8 *>(this + 1);
7.17 + return Address(this) + offsetToElements();
7.18 }
7.19 size_t objSize() {
7.20 return SizeFor(length());
7.21 }
7.22
7.23 - static size_t SizeFor(unsigned length) {
7.24 + static inline size_t offsetToElements() {
7.25 + return sizeof(ByteArray);
7.26 + }
7.27 +
7.28 + static inline size_t SizeFor(unsigned length) {
7.29 return sizeof(ByteArray) + sizeof(uint8) * length;
7.30 }
7.31
8.1 --- a/src/Interpreter.cpp Sun Sep 16 19:02:23 2012 -0700
8.2 +++ b/src/Interpreter.cpp Sun Sep 16 21:34:10 2012 -0700
8.3 @@ -141,7 +141,8 @@
8.4 ? source->length() <= dest->length()
8.5 : source->length() == dest->length());
8.6
8.7 - memcpy(dest->vec(), source->vec(), source->length() * source->elementSize());
8.8 + assert(dest->length());
8.9 + memcpy(dest->bytes(), source->bytes(), source->length() * Array::SizeForElement(dest->type()));
8.10 return true;
8.11 }
8.12
8.13 @@ -320,7 +321,7 @@
8.14 cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
8.15 } else {
8.16 assert(param->isArray());
8.17 - cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->vec());
8.18 + cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->bytes());
8.19 }
8.20 }
8.21
8.22 @@ -332,7 +333,7 @@
8.23 cells[i + 1] = reinterpret_cast<intptr_t>(arg.ref->location());
8.24 } else {
8.25 assert(arg.obj->is(MapKind_Array));
8.26 - cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->vec());
8.27 + cells[i + 1] = reinterpret_cast<intptr_t>(arg.array->bytes());
8.28 }
8.29 }
8.30
8.31 @@ -901,24 +902,6 @@
8.32 break;
8.33 }
8.34
8.35 -case OP_ARRAYREF_LIFO:
8.36 -{
8.37 - Local<Array> array(zone, Array::cast(top.sp[-2].obj));
8.38 -
8.39 - int index = top.sp[-1].i32;
8.40 - if (index < 0 || unsigned(index) >= array->length()) {
8.41 - zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
8.42 - goto error;
8.43 - }
8.44 -
8.45 - Local<Reference> ref(zone, Reference::NewArray(zone, array, index, Heap::Tenure_Stack));
8.46 - if (!ref)
8.47 - goto error;
8.48 - top.sp[-2].ref = ref;
8.49 - top.sp--;
8.50 - break;
8.51 -}
8.52 -
8.53 case OP_SLOTREF_LIFO:
8.54 {
8.55 Reference *ref = Reference::NewStack(zone, top.sp[-1], Heap::Tenure_Stack);
9.1 --- a/src/Messages.tbl Sun Sep 16 19:02:23 2012 -0700
9.2 +++ b/src/Messages.tbl Sun Sep 16 21:34:10 2012 -0700
9.3 @@ -77,4 +77,5 @@
9.4 MSG(ExpectedStringLiteral, SyntaxError, "expected string literal")
9.5 MSG(UnexpectedArrayLiteral, SyntaxError, "unexpected array literal")
9.6 MSG(InvalidDimensionSize, TypeError, "invalid size %d for dimension %d")
9.7 +MSG(CannotComputeIndexRef, SyntaxError, "cannot use an array index as a reference")
9.8
10.1 --- a/src/ObjectVisitor.h Sun Sep 16 19:02:23 2012 -0700
10.2 +++ b/src/ObjectVisitor.h Sun Sep 16 21:34:10 2012 -0700
10.3 @@ -117,14 +117,9 @@
10.4 }
10.5
10.6 size_t iterateArray(Array *array, ArrayMap *map) {
10.7 - assert(map->type()->isArray());
10.8 - if (map->type()->contained()->isTraceable()) {
10.9 - unsigned length = array->length();
10.10 - Object **vec = array->objVec();
10.11 - for (unsigned i = 0; i < length; i++)
10.12 - this->visit(vec + i);
10.13 - }
10.14 - return Array::SizeOf(array);
10.15 + if (!map->type()->fixedLength() || map->type()->contained()->isTraceable())
10.16 + visitField(array, Array::offsetOfElements());
10.17 + return array->objSize(map);
10.18 }
10.19
10.20 size_t iterateBox(Box *obj) {
10.21 @@ -289,7 +284,7 @@
10.22 return sizeof(Native);
10.23
10.24 case MapKind_Array:
10.25 - return Align(Array::SizeOf(Array::cast(obj)), kObjectAlignment);
10.26 + return Align(Array::cast(obj)->objSize(ArrayMap::cast(map)), kObjectAlignment);
10.27
10.28 case MapKind_Box:
10.29 return sizeof(Box);
11.1 --- a/src/Opcodes.cpp Sun Sep 16 19:02:23 2012 -0700
11.2 +++ b/src/Opcodes.cpp Sun Sep 16 21:34:10 2012 -0700
11.3 @@ -85,7 +85,6 @@
11.4 op == OP_VARREF_LIFO ||
11.5 op == OP_ARGREF_LIFO ||
11.6 op == OP_SLOTREF_LIFO ||
11.7 - op == OP_ARRAYREF_LIFO ||
11.8 op == OP_COPYARRAY);
11.9 #endif
11.10
11.11 @@ -179,7 +178,6 @@
11.12 case OP_GETREF_F:
11.13 case OP_SETREF_F:
11.14 case OP_SLOTREF_LIFO:
11.15 - case OP_ARRAYREF_LIFO:
11.16 case OP_COPYARRAY:
11.17 case OP_COPYSTRUCT:
11.18 case OP_DUP:
12.1 --- a/src/Opcodes.tbl Sun Sep 16 19:02:23 2012 -0700
12.2 +++ b/src/Opcodes.tbl Sun Sep 16 21:34:10 2012 -0700
12.3 @@ -174,23 +174,22 @@
12.4 OPDEF(OP_VARREF_LIFO, 69, "varref.lifo", 5, 0, 1)
12.5 OPDEF(OP_ARGREF_LIFO, 70, "argref.lifo", 5, 0, 1)
12.6 OPDEF(OP_SLOTREF_LIFO, 71, "slotref.lifo", 1, 1, 1)
12.7 -OPDEF(OP_ARRAYREF_LIFO, 72, "arrayref.lifo",1, 2, 1)
12.8 -OPDEF(OP_GETREF_I, 73, "getref.i", 1, 1, 1)
12.9 -OPDEF(OP_SETREF_I, 74, "setref.i", 1, 2, 1)
12.10 -OPDEF(OP_GETREF_F, 75, "getref.f", 1, 1, 1)
12.11 -OPDEF(OP_SETREF_F, 76, "setref.f", 1, 2, 1)
12.12 +OPDEF(OP_GETREF_I, 72, "getref.i", 1, 1, 1)
12.13 +OPDEF(OP_SETREF_I, 73, "setref.i", 1, 2, 1)
12.14 +OPDEF(OP_GETREF_F, 74, "getref.f", 1, 1, 1)
12.15 +OPDEF(OP_SETREF_F, 75, "setref.f", 1, 2, 1)
12.16
12.17 // Pushes an object reference onto the stack.
12.18 -OPDEF(OP_OBJECT, 77, "object", 5, 0, 1)
12.19 +OPDEF(OP_OBJECT, 76, "object", 5, 0, 1)
12.20
12.21 // Duplicates the top item on the stack.
12.22 -OPDEF(OP_DUP, 78, "dup", 1, 1, 2)
12.23 +OPDEF(OP_DUP, 77, "dup", 1, 1, 2)
12.24
12.25 // Duplicates the top two items on the stack.
12.26 -OPDEF(OP_DUP2, 79, "dup2", 1, 2, 4)
12.27 +OPDEF(OP_DUP2, 78, "dup2", 1, 2, 4)
12.28
12.29 // Swaps the two items at the top of the stack.
12.30 -OPDEF(OP_SWAP, 80, "swap", 1, 2, 2)
12.31 +OPDEF(OP_SWAP, 79, "swap", 1, 2, 2)
12.32
12.33 // Roll operation is the same as Forth. It steals a value on the stack,
12.34 // shifting all stack values down, and then places the stolen value back at
12.35 @@ -200,14 +199,14 @@
12.36 // sp[-3] = sp[-2]
12.37 // sp[-2] = sp[-1]
12.38 // sp[-1] = p
12.39 -OPDEF(OP_ROLL3, 81, "roll3", 1, 3, 3)
12.40 +OPDEF(OP_ROLL3, 80, "roll3", 1, 3, 3)
12.41
12.42 // Pick operation is the same as Forth. It pushes a copy of a slot at a
12.43 // specific depth.
12.44 //
12.45 // push(sp[-n])
12.46 -OPDEF(OP_PICK2, 82, "pick2", 1, 2, 3)
12.47 -OPDEF(OP_PICK3, 83, "pick3", 1, 3, 4)
12.48 +OPDEF(OP_PICK2, 81, "pick2", 1, 2, 3)
12.49 +OPDEF(OP_PICK3, 82, "pick3", 1, 3, 4)
12.50
12.51 // Calls a native function. During the course of calling a native, arguments
12.52 // on the stack are re-pushed to match the cell-based native calling
12.53 @@ -218,57 +217,57 @@
12.54 //
12.55 // [u8 Opcode] [u32 Index] [u32 ArgCount]
12.56 //
12.57 -OPDEF(OP_CALLNATIVE, 84, "callnative", 9, -1, 1)
12.58 +OPDEF(OP_CALLNATIVE, 83, "callnative", 9, -1, 1)
12.59
12.60 // Returns from a function that does return a value.
12.61 -OPDEF(OP_RETURNVOID, 85, "returnvoid", 1, 0, 0)
12.62 +OPDEF(OP_RETURNVOID, 84, "returnvoid", 1, 0, 0)
12.63
12.64 // Loads the module of the running function.
12.65 -OPDEF(OP_MODULE, 86, "module", 1, 0, 1)
12.66 +OPDEF(OP_MODULE, 85, "module", 1, 0, 1)
12.67
12.68 // Loads a function from a module object. The operand is the slot number
12.69 // in the module.
12.70 -OPDEF(OP_GETMODULE_FN, 87, "getmodule.fn", 5, 1, 1)
12.71 +OPDEF(OP_GETMODULE_FN, 86, "getmodule.fn", 5, 1, 1)
12.72
12.73 // Opcodes for accessing an environment slot in the global scope.
12.74 -OPDEF(OP_SETGLOBAL_I, 88, "setglobal.i", 5, 1, 1)
12.75 -OPDEF(OP_SETGLOBAL_F, 89, "setglobal.f", 5, 1, 1)
12.76 -OPDEF(OP_SETGLOBAL_O, 90, "setglobal.o", 5, 1, 1)
12.77 -OPDEF(OP_GETGLOBAL_I, 91, "getglobal.i", 5, 0, 1)
12.78 -OPDEF(OP_GETGLOBAL_F, 92, "getglobal.f", 5, 0, 1)
12.79 -OPDEF(OP_GETGLOBAL_O, 93, "getglobal.o", 5, 0, 1)
12.80 +OPDEF(OP_SETGLOBAL_I, 87, "setglobal.i", 5, 1, 1)
12.81 +OPDEF(OP_SETGLOBAL_F, 88, "setglobal.f", 5, 1, 1)
12.82 +OPDEF(OP_SETGLOBAL_O, 89, "setglobal.o", 5, 1, 1)
12.83 +OPDEF(OP_GETGLOBAL_I, 90, "getglobal.i", 5, 0, 1)
12.84 +OPDEF(OP_GETGLOBAL_F, 91, "getglobal.f", 5, 0, 1)
12.85 +OPDEF(OP_GETGLOBAL_O, 92, "getglobal.o", 5, 0, 1)
12.86
12.87 // Reinterprets a 32-bit integer as a float, or vice-versa.
12.88 -OPDEF(OP_BITS_I2F, 94, "bits.i2f", 1, 1, 1)
12.89 -OPDEF(OP_BITS_F2I, 95, "bits.f2i", 1, 1, 1)
12.90 +OPDEF(OP_BITS_I2F, 93, "bits.i2f", 1, 1, 1)
12.91 +OPDEF(OP_BITS_F2I, 94, "bits.f2i", 1, 1, 1)
12.92
12.93 // Pushes a boolean value.
12.94 -OPDEF(OP_TRUE, 96, "true", 1, 0, 1)
12.95 -OPDEF(OP_FALSE, 97, "false", 1, 0, 1)
12.96 +OPDEF(OP_TRUE, 95, "true", 1, 0, 1)
12.97 +OPDEF(OP_FALSE, 96, "false", 1, 0, 1)
12.98
12.99 // Allocate a struct. The HeapTenure is stored as a byte following pc. The
12.100 // StructMap to use is specified as an index into the script's Map table.
12.101 //
12.102 // Format:
12.103 // [u8 op] [u8 tenure] [u32 index]
12.104 -OPDEF(OP_NEWSTRUCT, 98, "newstruct", 6, 0, 1)
12.105 +OPDEF(OP_NEWSTRUCT, 97, "newstruct", 6, 0, 1)
12.106
12.107 // Performs a struct-to-struct assignment.
12.108 // Left = pop()
12.109 // Right = pop()
12.110 // copy(Left, Right)
12.111 // push(Left)
12.112 -OPDEF(OP_COPYSTRUCT, 99, "structcopy", 1, 2, 1)
12.113 +OPDEF(OP_COPYSTRUCT, 98, "structcopy", 1, 2, 1)
12.114
12.115 // Sets or gets a property in a struct. The index of the field is specified as
12.116 // a 32-bit integer. Note that these opcodes follow a new style of deriving
12.117 // their types at runtime.
12.118 -OPDEF(OP_GETFIELD, 100, "getfield", 5, 1, 1)
12.119 -OPDEF(OP_SETFIELD, 101, "setfield", 5, 2, 1)
12.120 +OPDEF(OP_GETFIELD, 99, "getfield", 5, 1, 1)
12.121 +OPDEF(OP_SETFIELD, 100, "setfield", 5, 2, 1)
12.122
12.123 -OPDEF(OP_FIELDREF_LIFO, 102, "fieldref.lifo", 5, 1, 1)
12.124 +OPDEF(OP_FIELDREF_LIFO, 101, "fieldref.lifo", 5, 1, 1)
12.125
12.126 // Table-based jump.
12.127 // [u8 op] [i32 low] [i32 high] [u32 jump] [u32 jumps...]
12.128 -OPDEF(OP_TABLESWITCH, 103, "tableswitch", 9, 1, 0)
12.129 +OPDEF(OP_TABLESWITCH, 102, "tableswitch", 9, 1, 0)
12.130
13.1 --- a/src/Reference.cpp Sun Sep 16 19:02:23 2012 -0700
13.2 +++ b/src/Reference.cpp Sun Sep 16 21:34:10 2012 -0700
13.3 @@ -50,18 +50,6 @@
13.4 }
13.5
13.6 Reference *
13.7 -Reference::NewArray(Zone *zone, Handle<Array> base, size_t index, Heap::Tenure tenure)
13.8 -{
13.9 - Local<Reference> ref(zone, Reference::cast(zone->allocate(MapKind_Reference, sizeof(Reference), tenure)));
13.10 - if (!ref)
13.11 - return NULL;
13.12 -
13.13 - ref->location_ = base->slotPtr(index);
13.14 - ref->base_ = base;
13.15 - return ref;
13.16 -}
13.17 -
13.18 -Reference *
13.19 Reference::NewField(Zone *zone, Handle<Struct> obj, size_t index, Heap::Tenure tenure)
13.20 {
13.21 Local<Reference> ref(zone, Reference::cast(zone->allocate(MapKind_Reference, sizeof(Reference), tenure)));
14.1 --- a/src/Reference.h Sun Sep 16 19:02:23 2012 -0700
14.2 +++ b/src/Reference.h Sun Sep 16 21:34:10 2012 -0700
14.3 @@ -40,7 +40,6 @@
14.4 public:
14.5 static Reference *NewStack(Zone *zone, void *location, Heap::Tenure tenure = Heap::Tenure_Default);
14.6 static Reference *NewStack(Zone *zone, const LocalSlot &slot, Heap::Tenure tenure = Heap::Tenure_Default);
14.7 - static Reference *NewArray(Zone *zone, Handle<Array> base, size_t index, Heap::Tenure tenure = Heap::Tenure_Default);
14.8 static Reference *NewField(Zone *zone, Handle<Struct> obj, size_t index, Heap::Tenure tenure = Heap::Tenure_Default);
14.9
14.10 int getInt() {
15.1 --- a/src/SemanticAnalysis.cpp Sun Sep 16 19:02:23 2012 -0700
15.2 +++ b/src/SemanticAnalysis.cpp Sun Sep 16 21:34:10 2012 -0700
15.3 @@ -1420,13 +1420,22 @@
15.4 } else {
15.5 Local<Type> actual(zone_, type->parameterAt(i));
15.6
15.7 - if (expression->isIndexExpression() && actual->isArray()) {
15.8 - // We special case the ability to pass x[y] into x[], which
15.9 - // creates an array slice. We only do this if we know the
15.10 - // assignment would otherwise not type-check.
15.11 - IndexExpression *index = expression->toIndexExpression();
15.12 - if (index->left()->type()->levels() == actual->levels())
15.13 - given = index->left()->type();
15.14 + if (expression->isIndexExpression()) {
15.15 + // Disabled until we can make it work.
15.16 +#if 0
15.17 + if (actual->isArray()) {
15.18 + // We special case the ability to pass x[y] into x[], which
15.19 + // creates an array slice. We only do this if we know the
15.20 + // assignment would otherwise not type-check.
15.21 + IndexExpression *index = expression->toIndexExpression();
15.22 + if (index->left()->type()->levels() == actual->levels())
15.23 + given = index->left()->type();
15.24 + } else
15.25 +#endif
15.26 + if (actual->isReference()) {
15.27 + cc_.reportError(expression->pos(), Message_CannotComputeIndexRef);
15.28 + return;
15.29 + }
15.30 }
15.31
15.32 if (!typeCheckParameter(expression, given, actual))
16.1 --- a/src/TypeManager.cpp Sun Sep 16 19:02:23 2012 -0700
16.2 +++ b/src/TypeManager.cpp Sun Sep 16 21:34:10 2012 -0700
16.3 @@ -72,6 +72,12 @@
16.4 }
16.5
16.6 Type *
16.7 +TypeManager::newExternalArray(Handle<Type> contained)
16.8 +{
16.9 + return Type::NewExternalArray(zone_, contained);
16.10 +}
16.11 +
16.12 +Type *
16.13 TypeManager::getReference(Handle<Type> type, bool isConst)
16.14 {
16.15 if (!isConst && type->isPrimitive())
17.1 --- a/src/TypeManager.h Sun Sep 16 19:02:23 2012 -0700
17.2 +++ b/src/TypeManager.h Sun Sep 16 21:34:10 2012 -0700
17.3 @@ -54,6 +54,7 @@
17.4 }
17.5 Type *getReference(Handle<Type> type, bool isConst);
17.6 Type *newArray(Handle<Type> contained, int elements, bool isConst);
17.7 + Type *newExternalArray(Handle<Type> contained);
17.8 Type *newEnum(Handle<String> name);
17.9 Type *newFunction(Handle<Type> returnType, Handle<FixedArray> args,
17.10 Handle<FixedArray> deafults);
18.1 --- a/src/Types.cpp Sun Sep 16 19:02:23 2012 -0700
18.2 +++ b/src/Types.cpp Sun Sep 16 21:34:10 2012 -0700
18.3 @@ -104,6 +104,29 @@
18.4 }
18.5
18.6 Type *
18.7 +Type::NewExternalArray(Zone *zone, Handle<Type> contained)
18.8 +{
18.9 + Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
18.10 + if (!type)
18.11 + return NULL;
18.12 +
18.13 + assert(contained->isPrimitive());
18.14 +
18.15 + type->kind_ = EXTERNAL_ARRAY;
18.16 + type->name_ = NULL;
18.17 + type->contained_ = contained;
18.18 + type->returnType_ = NULL;
18.19 + type->parameters_ = NULL;
18.20 + type->defaults_ = NULL;
18.21 + type->fields_ = NULL;
18.22 + type->newMap_ = NULL;
18.23 + type->elements_ = DYNAMIC_ARRAY_SIZE;
18.24 + type->levels_ = 1;
18.25 + type->const_ = false;
18.26 + return type;
18.27 +}
18.28 +
18.29 +Type *
18.30 Type::NewReference(Zone *zone, Handle<Type> contained, bool isConst)
18.31 {
18.32 Local<Type> type(zone, Type::cast(zone->allocate(MapKind_Type, sizeof(Type), Heap::Tenure_Old)));
19.1 --- a/src/Types.h Sun Sep 16 19:02:23 2012 -0700
19.2 +++ b/src/Types.h Sun Sep 16 21:34:10 2012 -0700
19.3 @@ -65,6 +65,7 @@
19.4
19.5 // An array is a fixed-length vector of any other type.
19.6 ARRAY,
19.7 + EXTERNAL_ARRAY,
19.8
19.9 // A reference type may only be specified on parameters, and
19.10 // references may only be computed to primitives or enums.
19.11 @@ -105,6 +106,7 @@
19.12 static Type *NewUnchecked(Zone *zone);
19.13 static Type *NewPrimitive(Zone *zone, PrimitiveType type);
19.14 static Type *NewArray(Zone *zone, Handle<Type> contained, int elements, bool isConst);
19.15 + static Type *NewExternalArray(Zone *zone, Handle<Type> contained);
19.16 static Type *NewReference(Zone *zone, Handle<Type> contained, bool isConst);
19.17 static Type *NewFunction(Zone *zone, Handle<Type> returnType, Handle<FixedArray> parameters,
19.18 Handle<FixedArray> defaults);
19.19 @@ -124,7 +126,7 @@
19.20 return kind() == PRIMITIVE;
19.21 }
19.22 bool isArray() {
19.23 - return kind() == ARRAY;
19.24 + return kind() == ARRAY || kind() == EXTERNAL_ARRAY;
19.25 }
19.26 bool isReference() {
19.27 return kind() == REFERENCE;
19.28 @@ -179,6 +181,14 @@
19.29 assert(isArray());
19.30 return levels_;
19.31 }
19.32 + bool hasInlineElements() {
19.33 + assert(isArray());
19.34 +
19.35 + // We don't allocate traceable elements inline, since there's no
19.36 + // point to the optimization; we're going to be allocating lots of
19.37 + // objects anyway (in theory).
19.38 + return isFixedLength() && !contained()->isTraceable();
19.39 + }
19.40 Type *innermost() {
19.41 assert(isArray());
19.42 Type *temp = contained();
19.43 @@ -203,6 +213,9 @@
19.44 contained()->isPrimitive() &&
19.45 contained()->primitive() == PrimitiveType_Char;
19.46 }
19.47 + bool isExternalArray() {
19.48 + return kind() == EXTERNAL_ARRAY;
19.49 + }
19.50 Type *returnType() {
19.51 assert(isFunction());
19.52 return returnType_;
19.53 @@ -222,7 +235,9 @@
19.54 return !isPrimitive();
19.55 }
19.56 bool isConst() {
19.57 - assert(kind() == PRIMITIVE || kind() == ARRAY || kind() == REFERENCE);
19.58 + assert(isPrimitive() ||
19.59 + isArray() ||
19.60 + isReference());
19.61 return const_;
19.62 }
19.63 bool isEnum() {
20.1 --- a/src/Zone.cpp Sun Sep 16 19:02:23 2012 -0700
20.2 +++ b/src/Zone.cpp Sun Sep 16 21:34:10 2012 -0700
20.3 @@ -114,24 +114,24 @@
20.4 if (!type)
20.5 return false;
20.6
20.7 - type = types_->newArray(type, Type::DYNAMIC_ARRAY_SIZE, false);
20.8 + type = types_->newExternalArray(type);
20.9 if (!type)
20.10 return false;
20.11
20.12 - genericArrayMap_ = ArrayMap::New(this, type);
20.13 - if (!genericArrayMap_)
20.14 + externalGenericArrayMap_ = ArrayMap::Attach(this, type);
20.15 + if (!externalGenericArrayMap_)
20.16 return false;
20.17
20.18 type = types_->getPrimitive(PrimitiveType_Char);
20.19 if (!type)
20.20 return false;
20.21
20.22 - type = types_->newArray(type, Type::DYNAMIC_ARRAY_SIZE, false);
20.23 + type = types_->newExternalArray(type);
20.24 if (!type)
20.25 return false;
20.26
20.27 - charArrayMap_ = ArrayMap::New(this, type);
20.28 - if (!charArrayMap_)
20.29 + externalCharArrayMap_ = ArrayMap::Attach(this, type);
20.30 + if (!externalCharArrayMap_)
20.31 return false;
20.32 }
20.33
20.34 @@ -154,8 +154,8 @@
20.35 {
20.36 for (unsigned i = 0; i < MapKinds_Total; i++)
20.37 visitor->visit(maps_[i].address());
20.38 - visitor->visit(charArrayMap_.address());
20.39 - visitor->visit(genericArrayMap_.address());
20.40 + visitor->visit(externalCharArrayMap_.address());
20.41 + visitor->visit(externalGenericArrayMap_.address());
20.42 types()->accept(visitor);
20.43
20.44 Local<Object> *local = lastLocalRoot_;
21.1 --- a/src/Zone.h Sun Sep 16 19:02:23 2012 -0700
21.2 +++ b/src/Zone.h Sun Sep 16 21:34:10 2012 -0700
21.3 @@ -46,8 +46,8 @@
21.4
21.5 // Map cache.
21.6 Unbarriered<Map> maps_[MapKinds_Total];
21.7 - Unbarriered<ArrayMap> genericArrayMap_;
21.8 - Unbarriered<ArrayMap> charArrayMap_;
21.9 + Unbarriered<ArrayMap> externalGenericArrayMap_;
21.10 + Unbarriered<ArrayMap> externalCharArrayMap_;
21.11
21.12 TypeManager *types_;
21.13 StringPool *symbols_;
21.14 @@ -93,11 +93,11 @@
21.15 }
21.16 Map *allocateMap(MapKind kind, size_t bytes, MapKind parent = MapKind_Meta);
21.17
21.18 - ArrayMap *genericArrayMap() {
21.19 - return genericArrayMap_;
21.20 + ArrayMap *externalGenericArrayMap() {
21.21 + return externalGenericArrayMap_;
21.22 }
21.23 - ArrayMap *charArrayMap() {
21.24 - return charArrayMap_;
21.25 + ArrayMap *externalCharArrayMap() {
21.26 + return externalCharArrayMap_;
21.27 }
21.28
21.29 TypeManager *types() const {