diff -r bbb498ccb4ac -r 26e3035cdffc src/Interpreter.cpp --- a/src/Interpreter.cpp Sat Dec 22 23:18:57 2012 -0800 +++ b/src/Interpreter.cpp Mon Dec 24 02:49:20 2012 -0800 @@ -82,69 +82,27 @@ return true; } -static bool CopyStruct(Zone *zone, Handle left, Handle right); - static bool -ChangeArrayLength(Zone *zone, Handle source, Handle dest) +DuplicateArray(Zone *zone, Handle src) { - return true; -} + Local map(zone, ArrayMap::cast(src->map())); + Local dest(zone); -// Even though this function can fail, we immediately bail out, so it doesn't -// matter if we've leaving things unrooted. -static bool -CopyArray(Zone *zone, Handle dest, Handle source) -{ - if (source->length() != dest->length()) { - if (!ChangeArrayLength(zone, source, dest)) - return false; + if (map->type()->isFixedLength()) { + dest = Array::NewFixed(zone, map); + } else { + Type *type = map->type(); + int sizes[MAX_ARRAY_DEPTH]; + for (unsigned i = 0; i < map->type()->levels(); i++) { + ArrayType *atype = ArrayType::cast(type); + sizes[i] = atype->isFixedLength() + ? atype->fixedLength() + : 0; + type = atype->contained(); + } } - Local contained(zone, source->type()->contained()); - if (contained->isArray() && ArrayType::cast(contained)->isFixedLength()) { - assert(dest->type()->contained()->isArray()); - assert(source->length() == dest->length()); - - Local left(zone); - Local right(zone); - for (unsigned i = 0; i < source->length(); i++) { - left = Array::cast(dest->readObject(i)); - right = Array::cast(source->readObject(i)); - if (!CopyArray(zone, left, right)) - return false; - } - return true; - } - - if (contained->isStruct()) { - assert(dest->type()->contained() == contained); - assert(source->length() == dest->length()); - - Local left(zone); - Local right(zone); - for (unsigned i = 0; i < source->length(); i++) { - left = Struct::cast(dest->readObject(i)); - right = Struct::cast(source->readObject(i)); - if (!CopyStruct(zone, left, right)) - return false; - } - return true; - } - - if (contained->isTraceable()) { - for (unsigned i = 0; i < source->length(); i++) - dest->writeObject(zone, i, source->readObject(i)); - return true; - } - - assert(contained->pod() == dest->type()->contained()->pod()); - assert(contained->pod() == PrimitiveType_Char - ? source->length() <= dest->length() - : source->length() == dest->length()); - - assert(dest->length()); - memcpy(dest->bytes(), source->bytes(), source->length() * Array::SizeForElement(dest->type())); - return true; + Local dst(zone); } static void @@ -269,49 +227,6 @@ StoreField(zone, obj, desc, v); } -// Even though this function can fail, we immediately bail out, so it doesn't -// matter if we've leaving things unrooted. -static bool -CopyStruct(Zone *zone, Handle left, Handle right) -{ - assert(left->map()->type() == right->map()->type()); - - Local type(zone, StructType::cast(left->map()->type())); - Local leftStruct(zone); - Local rightStruct(zone); - Local leftArray(zone); - Local rightArray(zone); - for (unsigned i = 0; i < type->fields()->length(); i++) { - Descriptor *desc = Descriptor::cast(type->fields()->at(i)); - - LocalSlot rval; - FetchField(right, desc, &rval); - - // If the field is a struct, we need to deep-copy. - if (desc->type()->isStruct()) { - LocalSlot lval; - - FetchField(left, desc, &lval); - leftStruct = Struct::cast(lval.obj); - rightStruct = Struct::cast(rval.obj); - if (!CopyStruct(zone, leftStruct, rightStruct)) - return false; - } else if (desc->type()->isArray()) { - LocalSlot lval; - - FetchField(left, desc, &lval); - leftArray = Array::cast(lval.obj); - rightArray = Array::cast(rval.obj); - if (!CopyArray(zone, leftArray, rightArray)) - return false; - } else { - StoreField(zone, left, desc, rval); - } - } - - return true; -} - static bool InvokeNative(Zone *zone, Handle native, void *identity, LocalSlot *args, unsigned argc, int *result) @@ -773,6 +688,15 @@ break; } +case OP_DUPARRAY: +{ + Local src(zone, Array::cast(top.sp[-1].obj)); + top.sp[-1].obj = Array::DeepCopy(zone, src, Heap::Tenure_Default); + if (!top.sp[-1].obj) + goto error; + break; +} + case OP_NEWFIXED: { Heap::Tenure tenure = (Heap::Tenure)top.pc[1]; @@ -905,7 +829,7 @@ // right, since in this case the result of the expression could be different. Local left(zone, Array::cast(top.sp[-2].array)); Local right(zone, Array::cast(top.sp[-1].array)); - if (!CopyArray(zone, left, right)) + if (!Array::ShallowCopy(zone, left, right)) goto error; top.sp--; break; @@ -1016,7 +940,7 @@ { Local left(zone, Struct::cast(top.sp[-2].obj)); Local right(zone, Struct::cast(top.sp[-1].obj)); - if (!CopyStruct(zone, left, right)) + if (!Struct::Copy(zone, left, right)) goto error; top.sp[-2].obj = top.sp[-1].obj; top.sp--;