diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index e2abee38d4..c8f1e17bda 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -4616,34 +4616,51 @@ void LCodeGen::EmitDeepCopy(Handle object, } } - // Copy elements backing store header. - ASSERT(!has_elements || elements->IsFixedArray()); if (has_elements) { + // Copy elements backing store header. __ LoadHeapObject(source, elements); for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) { __ ldr(r2, FieldMemOperand(source, i)); __ str(r2, FieldMemOperand(result, elements_offset + i)); } - } - // Copy elements backing store content. - ASSERT(!has_elements || elements->IsFixedArray()); - int elements_length = has_elements ? elements->length() : 0; - for (int i = 0; i < elements_length; i++) { - int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); - Handle value = JSObject::GetElement(object, i); - if (value->IsJSObject()) { - Handle value_object = Handle::cast(value); - __ add(r2, result, Operand(*offset)); - __ str(r2, FieldMemOperand(result, total_offset)); - __ LoadHeapObject(source, value_object); - EmitDeepCopy(value_object, result, source, offset); - } else if (value->IsHeapObject()) { - __ LoadHeapObject(r2, Handle::cast(value)); - __ str(r2, FieldMemOperand(result, total_offset)); + // Copy elements backing store content. + int elements_length = has_elements ? elements->length() : 0; + if (elements->IsFixedDoubleArray()) { + Handle double_array = + Handle::cast(elements); + for (int i = 0; i < elements_length; i++) { + int64_t value = double_array->get_representation(i); + // We only support little endian mode... + int32_t value_low = value & 0xFFFFFFFF; + int32_t value_high = value >> 32; + int total_offset = + elements_offset + FixedDoubleArray::OffsetOfElementAt(i); + __ mov(r2, Operand(value_low)); + __ str(r2, FieldMemOperand(result, total_offset)); + __ mov(r2, Operand(value_high)); + __ str(r2, FieldMemOperand(result, total_offset + 4)); + } + } else if (elements->IsFixedArray()) { + for (int i = 0; i < elements_length; i++) { + int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); + Handle value = JSObject::GetElement(object, i); + if (value->IsJSObject()) { + Handle value_object = Handle::cast(value); + __ add(r2, result, Operand(*offset)); + __ str(r2, FieldMemOperand(result, total_offset)); + __ LoadHeapObject(source, value_object); + EmitDeepCopy(value_object, result, source, offset); + } else if (value->IsHeapObject()) { + __ LoadHeapObject(r2, Handle::cast(value)); + __ str(r2, FieldMemOperand(result, total_offset)); + } else { + __ mov(r2, Operand(value)); + __ str(r2, FieldMemOperand(result, total_offset)); + } + } } else { - __ mov(r2, Operand(value)); - __ str(r2, FieldMemOperand(result, total_offset)); + UNREACHABLE(); } } } diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 4d4e67872c..838ff32d9b 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -3683,22 +3683,27 @@ static bool IsFastLiteral(Handle boilerplate, Handle elements(boilerplate->elements()); if (elements->length() > 0 && elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) { - if (!boilerplate->HasFastElements()) return false; - int length = elements->length(); - for (int i = 0; i < length; i++) { - if ((*max_properties)-- == 0) return false; - Handle value = JSObject::GetElement(boilerplate, i); - if (value->IsJSObject()) { - Handle value_object = Handle::cast(value); - if (!IsFastLiteral(value_object, - max_depth - 1, - max_properties, - total_size)) { - return false; + if (boilerplate->HasFastDoubleElements()) { + *total_size += FixedDoubleArray::SizeFor(elements->length()); + } else if (boilerplate->HasFastElements()) { + int length = elements->length(); + for (int i = 0; i < length; i++) { + if ((*max_properties)-- == 0) return false; + Handle value = JSObject::GetElement(boilerplate, i); + if (value->IsJSObject()) { + Handle value_object = Handle::cast(value); + if (!IsFastLiteral(value_object, + max_depth - 1, + max_properties, + total_size)) { + return false; + } } } + *total_size += FixedArray::SizeFor(length); + } else { + return false; } - *total_size += FixedArray::SizeFor(length); } Handle properties(boilerplate->properties()); diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 6da2c624da..2c5a167470 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -4470,33 +4470,47 @@ void LCodeGen::EmitDeepCopy(Handle object, } } - // Copy elements backing store header. - ASSERT(!has_elements || elements->IsFixedArray()); if (has_elements) { + // Copy elements backing store header. __ LoadHeapObject(source, elements); for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) { __ mov(ecx, FieldOperand(source, i)); __ mov(FieldOperand(result, elements_offset + i), ecx); } - } - // Copy elements backing store content. - ASSERT(!has_elements || elements->IsFixedArray()); - int elements_length = has_elements ? elements->length() : 0; - for (int i = 0; i < elements_length; i++) { - int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); - Handle value = JSObject::GetElement(object, i); - if (value->IsJSObject()) { - Handle value_object = Handle::cast(value); - __ lea(ecx, Operand(result, *offset)); - __ mov(FieldOperand(result, total_offset), ecx); - __ LoadHeapObject(source, value_object); - EmitDeepCopy(value_object, result, source, offset); - } else if (value->IsHeapObject()) { - __ LoadHeapObject(ecx, Handle::cast(value)); - __ mov(FieldOperand(result, total_offset), ecx); + // Copy elements backing store content. + int elements_length = elements->length(); + if (elements->IsFixedDoubleArray()) { + Handle double_array = + Handle::cast(elements); + for (int i = 0; i < elements_length; i++) { + int64_t value = double_array->get_representation(i); + int32_t value_low = value & 0xFFFFFFFF; + int32_t value_high = value >> 32; + int total_offset = + elements_offset + FixedDoubleArray::OffsetOfElementAt(i); + __ mov(FieldOperand(result, total_offset), Immediate(value_low)); + __ mov(FieldOperand(result, total_offset + 4), Immediate(value_high)); + } + } else if (elements->IsFixedArray()) { + for (int i = 0; i < elements_length; i++) { + int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); + Handle value = JSObject::GetElement(object, i); + if (value->IsJSObject()) { + Handle value_object = Handle::cast(value); + __ lea(ecx, Operand(result, *offset)); + __ mov(FieldOperand(result, total_offset), ecx); + __ LoadHeapObject(source, value_object); + EmitDeepCopy(value_object, result, source, offset); + } else if (value->IsHeapObject()) { + __ LoadHeapObject(ecx, Handle::cast(value)); + __ mov(FieldOperand(result, total_offset), ecx); + } else { + __ mov(FieldOperand(result, total_offset), Immediate(value)); + } + } } else { - __ mov(FieldOperand(result, total_offset), Immediate(value)); + UNREACHABLE(); } } } diff --git a/src/objects-inl.h b/src/objects-inl.h index f27a436120..8f60fd5d34 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -944,6 +944,12 @@ MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) { #define WRITE_UINT32_FIELD(p, offset, value) \ (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) +#define READ_INT64_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR(p, offset))) + +#define WRITE_INT64_FIELD(p, offset, value) \ + (*reinterpret_cast(FIELD_ADDR(p, offset)) = value) + #define READ_SHORT_FIELD(p, offset) \ (*reinterpret_cast(FIELD_ADDR(p, offset))) @@ -1701,6 +1707,12 @@ double FixedDoubleArray::get_scalar(int index) { return result; } +int64_t FixedDoubleArray::get_representation(int index) { + ASSERT(map() != HEAP->fixed_cow_array_map() && + map() != HEAP->fixed_array_map()); + ASSERT(index >= 0 && index < this->length()); + return READ_INT64_FIELD(this, kHeaderSize + index * kDoubleSize); +} MaybeObject* FixedDoubleArray::get(int index) { if (is_the_hole(index)) { diff --git a/src/objects.h b/src/objects.h index aa02624f38..49d5da0317 100644 --- a/src/objects.h +++ b/src/objects.h @@ -2345,6 +2345,7 @@ class FixedDoubleArray: public FixedArrayBase { public: // Setter and getter for elements. inline double get_scalar(int index); + inline int64_t get_representation(int index); MUST_USE_RESULT inline MaybeObject* get(int index); inline void set(int index, double value); inline void set_the_hole(int index); diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 0845915dc5..0ad6055511 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -4238,34 +4238,46 @@ void LCodeGen::EmitDeepCopy(Handle object, } } - // Copy elements backing store header. - ASSERT(!has_elements || elements->IsFixedArray()); if (has_elements) { + // Copy elements backing store header. __ LoadHeapObject(source, elements); for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) { __ movq(rcx, FieldOperand(source, i)); __ movq(FieldOperand(result, elements_offset + i), rcx); } - } - // Copy elements backing store content. - ASSERT(!has_elements || elements->IsFixedArray()); - int elements_length = has_elements ? elements->length() : 0; - for (int i = 0; i < elements_length; i++) { - int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); - Handle value = JSObject::GetElement(object, i); - if (value->IsJSObject()) { - Handle value_object = Handle::cast(value); - __ lea(rcx, Operand(result, *offset)); - __ movq(FieldOperand(result, total_offset), rcx); - __ LoadHeapObject(source, value_object); - EmitDeepCopy(value_object, result, source, offset); - } else if (value->IsHeapObject()) { - __ LoadHeapObject(rcx, Handle::cast(value)); - __ movq(FieldOperand(result, total_offset), rcx); + // Copy elements backing store content. + int elements_length = elements->length(); + if (elements->IsFixedDoubleArray()) { + Handle double_array = + Handle::cast(elements); + for (int i = 0; i < elements_length; i++) { + int64_t value = double_array->get_representation(i); + int total_offset = + elements_offset + FixedDoubleArray::OffsetOfElementAt(i); + __ movq(rcx, value, RelocInfo::NONE); + __ movq(FieldOperand(result, total_offset), rcx); + } + } else if (elements->IsFixedArray()) { + for (int i = 0; i < elements_length; i++) { + int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); + Handle value = JSObject::GetElement(object, i); + if (value->IsJSObject()) { + Handle value_object = Handle::cast(value); + __ lea(rcx, Operand(result, *offset)); + __ movq(FieldOperand(result, total_offset), rcx); + __ LoadHeapObject(source, value_object); + EmitDeepCopy(value_object, result, source, offset); + } else if (value->IsHeapObject()) { + __ LoadHeapObject(rcx, Handle::cast(value)); + __ movq(FieldOperand(result, total_offset), rcx); + } else { + __ movq(rcx, value, RelocInfo::NONE); + __ movq(FieldOperand(result, total_offset), rcx); + } + } } else { - __ movq(rcx, value, RelocInfo::NONE); - __ movq(FieldOperand(result, total_offset), rcx); + UNREACHABLE(); } } }