src/Array.cpp
changeset 187 9308d52205a0
parent 186 03a663e96860
child 188 bab29bcec7fe
     1.1 --- a/src/Array.cpp	Sat Sep 15 19:33:24 2012 -0700
     1.2 +++ b/src/Array.cpp	Sun Sep 16 19:02:23 2012 -0700
     1.3 @@ -72,58 +72,121 @@
     1.4  }
     1.5  
     1.6  Array *
     1.7 -Array::New(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
     1.8 +Array::NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure)
     1.9  {
    1.10 -    assert(map->type()->isFixedLength());
    1.11 +    if (nelements > (INT_MAX / SizeFor(map->type(), 1))) {
    1.12 +        zone->reportError(Message_ArraySizeTooBig);
    1.13 +        return NULL;
    1.14 +    }
    1.15  
    1.16 -    return Array::New(zone, map, map->type()->fixedLength(), tenure);
    1.17 -}
    1.18 -
    1.19 -Array *
    1.20 -Array::New(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure)
    1.21 -{
    1.22 -    size_t elementBytes = SizeFor(map->type(), elements);
    1.23 +    size_t elementBytes = SizeFor(map->type(), nelements);
    1.24      size_t bytes = sizeof(Array) + elementBytes;
    1.25      Local<Array> array(zone, Array::cast(zone->allocate(map, bytes, tenure)));
    1.26      if (!array)
    1.27          return NULL;
    1.28  
    1.29 -    array->nelements_ = elements;
    1.30 +    array->nelements_ = nelements;
    1.31      array->elements_ = (Array *)array + 1;
    1.32 +    memset(array->vec(), 0, elementBytes);
    1.33  
    1.34 -    if (map->type()->contained()->isArray()) {
    1.35 -        Local<ArrayMap> childMap(zone, ArrayMap::cast(map->type()->contained()->newMap()));
    1.36 -        Local<Array> child(zone);
    1.37 -        for (unsigned i = 0; i < elements; i++) {
    1.38 -            unsigned length = map->type()->contained()->isFixedLength()
    1.39 -                              ? map->type()->contained()->fixedLength()
    1.40 -                              : 0;
    1.41 -            child = Array::New(zone, childMap, length, tenure);
    1.42 -            if (!child)
    1.43 -                return NULL;
    1.44 -
    1.45 -            array->writeObject(zone, i, child);
    1.46 -        }
    1.47 -    } else if (map->type()->contained()->isStruct()) {
    1.48 +    if (map->type()->contained()->isStruct()) {
    1.49          Local<StructMap> childMap(zone, StructMap::cast(map->type()->contained()->newMap()));
    1.50          Local<Struct> child(zone);
    1.51 -        for (unsigned i = 0; i < elements; i++) {
    1.52 +        for (unsigned i = 0; i < nelements; i++) {
    1.53              child = Struct::New(zone, childMap, tenure);
    1.54              if (!child)
    1.55                  return NULL;
    1.56  
    1.57              array->writeObject(zone, i, child);
    1.58          }
    1.59 -    } else {
    1.60 -        memset(array->elements_, 0, elementBytes);
    1.61 +    }
    1.62 +
    1.63 +    return array;
    1.64 +}
    1.65 +
    1.66 +static Array *
    1.67 +ConstructSizedArray(Zone *zone, Handle<ArrayMap> map, int dims[MAX_ARRAY_DEPTH],
    1.68 +                    unsigned level, Heap::Tenure tenure)
    1.69 +{
    1.70 +    Local<Array> array(zone, Array::NewRaw(zone, map, dims[level], tenure));
    1.71 +    if (!array)
    1.72 +        return NULL;
    1.73 +
    1.74 +    if (map->type()->contained()->isArray()) {
    1.75 +        Local<ArrayMap> childMap(zone, ArrayMap::cast(map->type()->contained()->newMap()));
    1.76 +        Local<Array> child(zone);
    1.77 +
    1.78 +        for (unsigned i = 0; i < unsigned(dims[level]); i++) {
    1.79 +            child = ConstructSizedArray(zone, childMap, dims, level + 1, tenure);
    1.80 +            if (!child)
    1.81 +                return NULL;
    1.82 +
    1.83 +            array->writeObject(zone, i, child);
    1.84 +        }
    1.85 +    }
    1.86 +
    1.87 +    return array;
    1.88 +}
    1.89 +
    1.90 +Array *
    1.91 +Array::NewSized(Zone *zone, Handle<ArrayMap> map, int dims[MAX_ARRAY_DEPTH], Heap::Tenure tenure)
    1.92 +{
    1.93 +    for (size_t i = 0; i < map->type()->levels(); i++) {
    1.94 +        if (dims[i] < 0) {
    1.95 +            zone->reportError(Message_InvalidDimensionSize, dims[i], i);
    1.96 +            return NULL;
    1.97 +        }
    1.98      }
    1.99 +
   1.100 +    return ConstructSizedArray(zone, map, dims, 0, tenure);
   1.101 +}
   1.102 +
   1.103 +static Array *
   1.104 +ConstructFixedArray(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
   1.105 +{
   1.106 +    unsigned length = map->type()->fixedLength();
   1.107 +    Local<Array> array(zone, Array::NewRaw(zone, map, length, tenure));
   1.108 +    if (!array)
   1.109 +        return NULL;
   1.110 +
   1.111 +    if (map->type()->contained()->isArray()) {
   1.112 +        Local<ArrayMap> childMap(zone, ArrayMap::cast(map->type()->contained()->newMap()));
   1.113 +        Local<Array> child(zone);
   1.114 +
   1.115 +        if (childMap->type()->isFixedLength()) {
   1.116 +            for (unsigned i = 0; i < length; i++) {
   1.117 +                child = ConstructFixedArray(zone, childMap, tenure);
   1.118 +                if (!child)
   1.119 +                    return NULL;
   1.120 +
   1.121 +                array->writeObject(zone, i, child);
   1.122 +            }
   1.123 +        } else {
   1.124 +            for (unsigned i = 0; i < length; i++) {
   1.125 +                child = Array::NewRaw(zone, childMap, 0, tenure);
   1.126 +                if (!child)
   1.127 +                    return NULL;
   1.128 +
   1.129 +                array->writeObject(zone, i, child);
   1.130 +            }
   1.131 +        }
   1.132 +    }
   1.133 +
   1.134      return array;
   1.135  }
   1.136  
   1.137  Array *
   1.138 +Array::NewFixed(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
   1.139 +{
   1.140 +    return ConstructFixedArray(zone, map, tenure);
   1.141 +}
   1.142 +
   1.143 +Array *
   1.144  Array::NewString(Zone *zone, Handle<ArrayMap> map, Address buffer, size_t length, Heap::Tenure tenure)
   1.145  {
   1.146 -    Local<Array> array(zone, Array::New(zone, map, length, tenure));
   1.147 +    assert(map->type()->isCharArray());
   1.148 +
   1.149 +    Local<Array> array(zone, Array::New1D(zone, map, length, tenure));
   1.150      if (!array)
   1.151          return NULL;
   1.152  
   1.153 @@ -133,6 +196,21 @@
   1.154  }
   1.155  
   1.156  Array *
   1.157 +Array::New1D(Zone *zone, Handle<ArrayMap> map, uint32 elements, Heap::Tenure tenure)
   1.158 +{
   1.159 +    assert(map->type()->levels());
   1.160 +    return Array::NewRaw(zone, map, elements, tenure);
   1.161 +}
   1.162 +
   1.163 +Array *
   1.164 +Array::NewEmpty(Zone *zone, Handle<ArrayMap> map, Heap::Tenure tenure)
   1.165 +{
   1.166 +    assert(!map->type()->isFixedLength());
   1.167 +
   1.168 +    return Array::NewRaw(zone, map, 0, tenure);
   1.169 +}
   1.170 +
   1.171 +Array *
   1.172  Array::NewExternal(Zone *zone, Handle<ArrayMap> map, uint32 nelements, void *buffer,
   1.173                     Heap::Tenure tenure)
   1.174  {