src/Array.cpp
changeset 188 bab29bcec7fe
parent 187 9308d52205a0
child 209 5cbec15fadfe
     1.1 --- a/src/Array.cpp	Sun Sep 16 19:02:23 2012 -0700
     1.2 +++ b/src/Array.cpp	Sun Sep 16 21:34:10 2012 -0700
     1.3 @@ -18,6 +18,7 @@
     1.4   */
     1.5  #include <string.h>
     1.6  #include "Array.h"
     1.7 +#include "FixedArray.h"
     1.8  #include "Heap.h"
     1.9  #include "Zone.h"
    1.10  #include "Structures.h"
    1.11 @@ -58,37 +59,60 @@
    1.12      return map;
    1.13  }
    1.14  
    1.15 -static inline size_t
    1.16 -SizeFor(Type *type, unsigned elements)
    1.17 -{
    1.18 -    if (type->contained()->isTraceable())
    1.19 -        return sizeof(Array) + elements * sizeof(ke::Object *);
    1.20 -    if (type->contained()->isInt32())
    1.21 -        return sizeof(Array) + elements * sizeof(int);
    1.22 -    if (type->contained()->primitive() == PrimitiveType_Char)
    1.23 -        return sizeof(Array) + elements * sizeof(char);
    1.24 -    assert(type->contained()->isFloat());
    1.25 -    return elements * sizeof(float);
    1.26 -}
    1.27 -
    1.28  Array *
    1.29  Array::NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure)
    1.30  {
    1.31 -    if (nelements > (INT_MAX / SizeFor(map->type(), 1))) {
    1.32 +    if (nelements > (INT_MAX / SizeForElement(map->type()))) {
    1.33          zone->reportError(Message_ArraySizeTooBig);
    1.34          return NULL;
    1.35      }
    1.36  
    1.37 -    size_t elementBytes = SizeFor(map->type(), nelements);
    1.38 -    size_t bytes = sizeof(Array) + elementBytes;
    1.39 +    size_t bytes = sizeof(Array);
    1.40 +    if (map->type()->hasInlineElements())
    1.41 +        bytes += SizeForElement(map->type()) * nelements;
    1.42 +
    1.43      Local<Array> array(zone, Array::cast(zone->allocate(map, bytes, tenure)));
    1.44      if (!array)
    1.45          return NULL;
    1.46  
    1.47 -    array->nelements_ = nelements;
    1.48 -    array->elements_ = (Array *)array + 1;
    1.49 -    memset(array->vec(), 0, elementBytes);
    1.50 +    array->length_ = 0;
    1.51 +    array->elements_ = NULL;
    1.52 +
    1.53 +    if (map->type()->hasInlineElements()) {
    1.54 +        // This must be a fixed array containing no traceables.
    1.55 +        assert(nelements > 0);
    1.56 +        assert(map->type()->isFixedLength());
    1.57 +        assert(!map->type()->contained()->isTraceable());
    1.58 +
    1.59 +        // Compute an interior |elements_| pointer, such that if elements_
    1.60 +        // is accessed like a FixedArray, we reach the appropriate vector.
    1.61 +        array->elements_ = Address((Array *)array + 1) - ByteArray::offsetToElements();
    1.62 +        array->length_ = nelements;
    1.63 +        memset(array->bytes(), 0, SizeForElement(map->type()) * nelements);
    1.64 +        return array;
    1.65 +    }
    1.66  
    1.67 +    // If there is nothing to allocate, we don't bother creating elements yet.
    1.68 +    if (!nelements)
    1.69 +        return array;
    1.70 +
    1.71 +    if (!map->type()->contained()->isTraceable()) {
    1.72 +        size_t nbytes = SizeForElement(map->type()) * nelements;
    1.73 +        Local<ByteArray> elements(zone, ByteArray::New(zone, nbytes, tenure));
    1.74 +        if (!elements)
    1.75 +            return NULL;
    1.76 +
    1.77 +        array->updateLengthAndElements(zone, nelements, elements);
    1.78 +        return array;
    1.79 +    }
    1.80 +
    1.81 +    Local<FixedArray> elements(zone, FixedArray::New(zone, nelements, tenure));
    1.82 +    if (!elements)
    1.83 +        return NULL;
    1.84 +
    1.85 +    array->updateLengthAndElements(zone, nelements, elements);
    1.86 +
    1.87 +    // If this is an array of structs, we're required to allocate those structs now.
    1.88      if (map->type()->contained()->isStruct()) {
    1.89          Local<StructMap> childMap(zone, StructMap::cast(map->type()->contained()->newMap()));
    1.90          Local<Struct> child(zone);
    1.91 @@ -97,7 +121,7 @@
    1.92              if (!child)
    1.93                  return NULL;
    1.94  
    1.95 -            array->writeObject(zone, i, child);
    1.96 +            elements->set(zone, i, child);
    1.97          }
    1.98      }
    1.99  
   1.100 @@ -211,15 +235,15 @@
   1.101  }
   1.102  
   1.103  Array *
   1.104 -Array::NewExternal(Zone *zone, Handle<ArrayMap> map, uint32 nelements, void *buffer,
   1.105 +Array::NewExternal(Zone *zone, Handle<ArrayMap> map, void *buffer, unsigned length,
   1.106                     Heap::Tenure tenure)
   1.107  {
   1.108      Local<Array> array(zone, Array::cast(zone->allocate(map, sizeof(Array), tenure)));
   1.109      if (!array)
   1.110          return NULL;
   1.111  
   1.112 -    array->nelements_ = nelements;
   1.113 -    array->elements_ = buffer;
   1.114 +    array->length_ = length;
   1.115 +    array->elements_ = Address(buffer) - ByteArray::offsetToElements();
   1.116      return array;
   1.117  }
   1.118