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 +}