diff -r 03a663e96860 -r 9308d52205a0 src/Array.cpp --- a/src/Array.cpp Sat Sep 15 19:33:24 2012 -0700 +++ b/src/Array.cpp Sun Sep 16 19:02:23 2012 -0700 @@ -72,58 +72,121 @@ } Array * -Array::New(Zone *zone, Handle map, Heap::Tenure tenure) +Array::NewRaw(Zone *zone, Handle map, unsigned nelements, Heap::Tenure tenure) { - assert(map->type()->isFixedLength()); + if (nelements > (INT_MAX / SizeFor(map->type(), 1))) { + zone->reportError(Message_ArraySizeTooBig); + return NULL; + } - return Array::New(zone, map, map->type()->fixedLength(), tenure); -} - -Array * -Array::New(Zone *zone, Handle map, uint32 elements, Heap::Tenure tenure) -{ - size_t elementBytes = SizeFor(map->type(), elements); + size_t elementBytes = SizeFor(map->type(), nelements); size_t bytes = sizeof(Array) + elementBytes; Local array(zone, Array::cast(zone->allocate(map, bytes, tenure))); if (!array) return NULL; - array->nelements_ = elements; + array->nelements_ = nelements; array->elements_ = (Array *)array + 1; + memset(array->vec(), 0, elementBytes); - if (map->type()->contained()->isArray()) { - Local childMap(zone, ArrayMap::cast(map->type()->contained()->newMap())); - Local child(zone); - for (unsigned i = 0; i < elements; i++) { - unsigned length = map->type()->contained()->isFixedLength() - ? map->type()->contained()->fixedLength() - : 0; - child = Array::New(zone, childMap, length, tenure); - if (!child) - return NULL; - - array->writeObject(zone, i, child); - } - } else if (map->type()->contained()->isStruct()) { + if (map->type()->contained()->isStruct()) { Local childMap(zone, StructMap::cast(map->type()->contained()->newMap())); Local child(zone); - for (unsigned i = 0; i < elements; i++) { + for (unsigned i = 0; i < nelements; i++) { child = Struct::New(zone, childMap, tenure); if (!child) return NULL; array->writeObject(zone, i, child); } - } else { - memset(array->elements_, 0, elementBytes); + } + + return array; +} + +static Array * +ConstructSizedArray(Zone *zone, Handle map, int dims[MAX_ARRAY_DEPTH], + unsigned level, Heap::Tenure tenure) +{ + Local array(zone, Array::NewRaw(zone, map, dims[level], tenure)); + if (!array) + return NULL; + + if (map->type()->contained()->isArray()) { + Local childMap(zone, ArrayMap::cast(map->type()->contained()->newMap())); + Local child(zone); + + for (unsigned i = 0; i < unsigned(dims[level]); i++) { + child = ConstructSizedArray(zone, childMap, dims, level + 1, tenure); + if (!child) + return NULL; + + array->writeObject(zone, i, child); + } + } + + return array; +} + +Array * +Array::NewSized(Zone *zone, Handle map, int dims[MAX_ARRAY_DEPTH], Heap::Tenure tenure) +{ + for (size_t i = 0; i < map->type()->levels(); i++) { + if (dims[i] < 0) { + zone->reportError(Message_InvalidDimensionSize, dims[i], i); + return NULL; + } } + + return ConstructSizedArray(zone, map, dims, 0, tenure); +} + +static Array * +ConstructFixedArray(Zone *zone, Handle map, Heap::Tenure tenure) +{ + unsigned length = map->type()->fixedLength(); + Local array(zone, Array::NewRaw(zone, map, length, tenure)); + if (!array) + return NULL; + + if (map->type()->contained()->isArray()) { + Local childMap(zone, ArrayMap::cast(map->type()->contained()->newMap())); + Local child(zone); + + if (childMap->type()->isFixedLength()) { + for (unsigned i = 0; i < length; i++) { + child = ConstructFixedArray(zone, childMap, tenure); + if (!child) + return NULL; + + array->writeObject(zone, i, child); + } + } else { + for (unsigned i = 0; i < length; i++) { + child = Array::NewRaw(zone, childMap, 0, tenure); + if (!child) + return NULL; + + array->writeObject(zone, i, child); + } + } + } + return array; } Array * +Array::NewFixed(Zone *zone, Handle map, Heap::Tenure tenure) +{ + return ConstructFixedArray(zone, map, tenure); +} + +Array * Array::NewString(Zone *zone, Handle map, Address buffer, size_t length, Heap::Tenure tenure) { - Local array(zone, Array::New(zone, map, length, tenure)); + assert(map->type()->isCharArray()); + + Local array(zone, Array::New1D(zone, map, length, tenure)); if (!array) return NULL; @@ -133,6 +196,21 @@ } Array * +Array::New1D(Zone *zone, Handle map, uint32 elements, Heap::Tenure tenure) +{ + assert(map->type()->levels()); + return Array::NewRaw(zone, map, elements, tenure); +} + +Array * +Array::NewEmpty(Zone *zone, Handle map, Heap::Tenure tenure) +{ + assert(!map->type()->isFixedLength()); + + return Array::NewRaw(zone, map, 0, tenure); +} + +Array * Array::NewExternal(Zone *zone, Handle map, uint32 nelements, void *buffer, Heap::Tenure tenure) {