| Index: src/x64/codegen-x64.cc
|
| diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
|
| index f7e8fc114fae7485d600a00e03e6c1a0fa6a7654..8947f70055f64745333a35e1b840480e1c0a1796 100644
|
| --- a/src/x64/codegen-x64.cc
|
| +++ b/src/x64/codegen-x64.cc
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2011 the V8 project authors. All rights reserved.
|
| +// Copyright 2012 the V8 project authors. All rights reserved.
|
| // Redistribution and use in source and binary forms, with or without
|
| // modification, are permitted provided that the following conditions are
|
| // met:
|
| @@ -182,12 +182,17 @@ void ElementsTransitionGenerator::GenerateSmiOnlyToDouble(
|
| // -- rsp[0] : return address
|
| // -----------------------------------
|
| // The fail label is not actually used since we do not allocate.
|
| - Label allocated, cow_array;
|
| + Label allocated, cow_array, only_change_map, done;
|
| +
|
| + // Check for empty arrays, which only require a map transition and no changes
|
| + // to the backing store.
|
| + __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset));
|
| + __ CompareRoot(r8, Heap::kEmptyFixedArrayRootIndex);
|
| + __ j(equal, &only_change_map);
|
|
|
| // Check backing store for COW-ness. If the negative case, we do not have to
|
| // allocate a new array, since FixedArray and FixedDoubleArray do not differ
|
| // in size.
|
| - __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset));
|
| __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset));
|
| __ CompareRoot(FieldOperand(r8, HeapObject::kMapOffset),
|
| Heap::kFixedCOWArrayMapRootIndex);
|
| @@ -241,6 +246,18 @@ void ElementsTransitionGenerator::GenerateSmiOnlyToDouble(
|
| __ movq(FieldOperand(r14, FixedDoubleArray::kLengthOffset), r11);
|
| __ jmp(&allocated);
|
|
|
| + __ bind(&only_change_map);
|
| + // Set transitioned map.
|
| + __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx);
|
| + __ RecordWriteField(rdx,
|
| + HeapObject::kMapOffset,
|
| + rbx,
|
| + rdi,
|
| + kDontSaveFPRegs,
|
| + OMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| + __ jmp(&done);
|
| +
|
| // Conversion loop.
|
| __ bind(&loop);
|
| __ movq(rbx,
|
| @@ -264,6 +281,8 @@ void ElementsTransitionGenerator::GenerateSmiOnlyToDouble(
|
| __ bind(&entry);
|
| __ decq(r9);
|
| __ j(not_sign, &loop);
|
| +
|
| + __ bind(&done);
|
| }
|
|
|
|
|
| @@ -276,7 +295,14 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
|
| // -- rdx : receiver
|
| // -- rsp[0] : return address
|
| // -----------------------------------
|
| - Label loop, entry, convert_hole, gc_required;
|
| + Label loop, entry, convert_hole, gc_required, only_change_map;
|
| +
|
| + // Check for empty arrays, which only require a map transition and no changes
|
| + // to the backing store.
|
| + __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset));
|
| + __ CompareRoot(r8, Heap::kEmptyFixedArrayRootIndex);
|
| + __ j(equal, &only_change_map);
|
| +
|
| __ push(rax);
|
|
|
| __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset));
|
| @@ -345,15 +371,6 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
|
| __ decq(r9);
|
| __ j(not_sign, &loop);
|
|
|
| - // Set transitioned map.
|
| - __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx);
|
| - __ RecordWriteField(rdx,
|
| - HeapObject::kMapOffset,
|
| - rbx,
|
| - rdi,
|
| - kDontSaveFPRegs,
|
| - EMIT_REMEMBERED_SET,
|
| - OMIT_SMI_CHECK);
|
| // Replace receiver's backing store with newly created and filled FixedArray.
|
| __ movq(FieldOperand(rdx, JSObject::kElementsOffset), r11);
|
| __ RecordWriteField(rdx,
|
| @@ -365,6 +382,17 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
|
| OMIT_SMI_CHECK);
|
| __ pop(rax);
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| +
|
| + __ bind(&only_change_map);
|
| + // Set transitioned map.
|
| + __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx);
|
| + __ RecordWriteField(rdx,
|
| + HeapObject::kMapOffset,
|
| + rbx,
|
| + rdi,
|
| + kDontSaveFPRegs,
|
| + OMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| }
|
|
|
|
|
|
|