src/Array.cpp
changeset 234 26e3035cdffc
parent 209 5cbec15fadfe
child 236 072f1114ea5d
     1.1 --- a/src/Array.cpp	Sat Dec 22 23:18:57 2012 -0800
     1.2 +++ b/src/Array.cpp	Mon Dec 24 02:49:20 2012 -0800
     1.3 @@ -62,6 +62,8 @@
     1.4  Array *
     1.5  Array::NewRaw(Zone *zone, Handle<ArrayMap> map, unsigned nelements, Heap::Tenure tenure)
     1.6  {
     1.7 +    assert(!map->type()->isFixedLength() || nelements == map->type()->fixedLength());
     1.8 +
     1.9      if (nelements > (INT_MAX / SizeForElement(map->type()))) {
    1.10          zone->reportError(Message_ArraySizeTooBig);
    1.11          return NULL;
    1.12 @@ -209,16 +211,21 @@
    1.13  }
    1.14  
    1.15  Array *
    1.16 -Array::NewString(Zone *zone, Handle<ArrayMap> map, Address buffer, size_t length, Heap::Tenure tenure)
    1.17 +Array::NewString(Zone *zone, Handle<ArrayMap> map, char *buffer, size_t length, Heap::Tenure tenure)
    1.18  {
    1.19      assert(map->type()->isCharArray());
    1.20  
    1.21 -    Local<Array> array(zone, Array::New1D(zone, map, length, tenure));
    1.22 +    Local<Array> array(zone);
    1.23 +    
    1.24 +    if (map->type()->isFixedLength())
    1.25 +        array = Array::NewFixed(zone, map, tenure);
    1.26 +    else
    1.27 +        array = Array::New1D(zone, map, length + 1, tenure);
    1.28      if (!array)
    1.29          return NULL;
    1.30  
    1.31 -    assert(array->length() >= length);
    1.32 -    memcpy(array->chars(), buffer, length);
    1.33 +    assert(array->length() >= length + 1);
    1.34 +    memcpy(array->chars(), buffer, length + 1);
    1.35      return array;
    1.36  }
    1.37  
    1.38 @@ -250,3 +257,90 @@
    1.39      return array;
    1.40  }
    1.41  
    1.42 +static bool
    1.43 +CopyArrayElements(Zone *zone, Handle<Type> contained, Handle<Array> dest, Handle<Array> source)
    1.44 +{
    1.45 +    if (contained->isTraceable()) {
    1.46 +        if (contained->isStruct()) {
    1.47 +            assert(dest->type()->contained() == contained);
    1.48 +            assert(source->length() == dest->length());
    1.49 +
    1.50 +            Local<Struct> left(zone);
    1.51 +            Local<Struct> right(zone);
    1.52 +            for (unsigned i = 0; i < source->length(); i++) {
    1.53 +                left = Struct::cast(dest->readObject(i));
    1.54 +                right = Struct::cast(source->readObject(i));
    1.55 +                if (!Struct::Copy(zone, left, right))
    1.56 +                    return false;
    1.57 +            }
    1.58 +        } else {
    1.59 +            assert(dest->length() == source->length());
    1.60 +            for (unsigned i = 0; i < source->length(); i++)
    1.61 +                dest->writeObject(zone, i, source->readObject(i));
    1.62 +        }
    1.63 +    } else {
    1.64 +        assert(contained->pod() == dest->type()->contained()->pod());
    1.65 +        assert(contained->pod() == PrimitiveType_Char
    1.66 +               ? source->length() <= dest->length()
    1.67 +               : source->length() == dest->length());
    1.68 +    
    1.69 +        assert(dest->length());
    1.70 +        memcpy(dest->bytes(), source->bytes(), source->length() * Array::SizeForElement(dest->type()));
    1.71 +    }
    1.72 +    return true;
    1.73 +}
    1.74 +
    1.75 +// Shallow copy an array. Fixed slots in the destination are copied from
    1.76 +// the source, but otherwise, references are assigned.
    1.77 +bool
    1.78 +Array::ShallowCopy(Zone *zone, Handle<Array> dest, Handle<Array> source)
    1.79 +{
    1.80 +#if 0
    1.81 +    Local<Type> contained(zone, source->type()->contained());
    1.82 +    if (contained->isArray() && ArrayType::cast(contained)->isFixedLength()) {
    1.83 +        assert(dest->type()->contained()->isArray());
    1.84 +        assert(source->length() == dest->length());
    1.85 +
    1.86 +        Local<Array> left(zone);
    1.87 +        Local<Array> right(zone);
    1.88 +        for (unsigned i = 0; i < source->length(); i++) {
    1.89 +            left = Array::cast(dest->readObject(i));
    1.90 +            right = Array::cast(source->readObject(i));
    1.91 +            if (!ShallowCopy(zone, left, right))
    1.92 +                return false;
    1.93 +        }
    1.94 +        return true;
    1.95 +    }
    1.96 +    
    1.97 +#endif
    1.98 +    assert(false);
    1.99 +    return false;
   1.100 +}
   1.101 +
   1.102 +Array *
   1.103 +Array::DeepCopy(Zone *zone, Handle<Array> source, Heap::Tenure tenure)
   1.104 +{
   1.105 +    Local<ArrayMap> map(zone, ArrayMap::cast(source->map()));
   1.106 +
   1.107 +    Local<Array> dest(zone, Array::NewRaw(zone, map, source->length(), tenure));
   1.108 +    if (!dest)
   1.109 +        return NULL;
   1.110 +
   1.111 +    Local<Type> contained(zone, source->type()->contained());
   1.112 +    if (contained->isArray()) {
   1.113 +        assert(false);
   1.114 +        Local<Array> sub(zone);
   1.115 +        for (size_t i = 0; i < source->length(); i++) {
   1.116 +            sub = Array::cast(source->readObject(i));
   1.117 +            sub = DeepCopy(zone, sub, tenure);
   1.118 +            if (!sub)
   1.119 +                return NULL;
   1.120 +            dest->writeObject(zone, i, sub);
   1.121 +        }
   1.122 +    } else {
   1.123 +        if (!CopyArrayElements(zone, contained, dest, source))
   1.124 +            return NULL;
   1.125 +    }
   1.126 +
   1.127 +    return dest;
   1.128 +}