Index: src/builtins.cc |
diff --git a/src/builtins.cc b/src/builtins.cc |
index 91cb1515200ac8555ed181cfb9de15ed926848ff..122fbba2c4aac4464c2a5bc1d37cf66d283b30bb 100644 |
--- a/src/builtins.cc |
+++ b/src/builtins.cc |
@@ -443,6 +443,38 @@ BUILTIN(ArrayPop) { |
} |
+static FixedArray* LeftTrimFixedArray(FixedArray* elms) { |
+ // For now this trick is only applied to fixed arrays in new space. |
+ // In large object space the object's start must coincide with chunk |
+ // and thus the trick is just not applicable. |
+ // In old space we do not use this trick to avoid dealing with |
+ // remembered sets. |
+ ASSERT(Heap::new_space()->Contains(elms)); |
+ |
+ Object** former_map = |
+ HeapObject::RawField(elms, FixedArray::kMapOffset); |
+ Object** former_length = |
+ HeapObject::RawField(elms, FixedArray::kLengthOffset); |
+ Object** former_first = |
+ HeapObject::RawField(elms, FixedArray::kHeaderSize); |
+ // Check that we don't forget to copy all the bits. |
+ STATIC_ASSERT(FixedArray::kMapOffset + 2 * kPointerSize |
+ == FixedArray::kHeaderSize); |
+ |
+ int len = elms->length(); |
+ |
+ *former_first = reinterpret_cast<Object*>(len - 1); |
+ *former_length = Heap::fixed_array_map(); |
+ // Technically in new space this write might be omitted (except for |
+ // debug mode which iterates through the heap), but to play safer |
+ // we still do it. |
+ *former_map = Heap::raw_unchecked_one_pointer_filler_map(); |
+ |
+ ASSERT(elms->address() + kPointerSize == (elms + kPointerSize)->address()); |
+ return elms + kPointerSize; |
+} |
+ |
+ |
BUILTIN(ArrayShift) { |
Object* receiver = *args.receiver(); |
FixedArray* elms = NULL; |
@@ -462,10 +494,14 @@ BUILTIN(ArrayShift) { |
first = Heap::undefined_value(); |
} |
- // Shift the elements. |
- AssertNoAllocation no_gc; |
- MoveElements(&no_gc, elms, 0, elms, 1, len - 1); |
- elms->set(len - 1, Heap::the_hole_value()); |
+ if (Heap::new_space()->Contains(elms)) { |
+ array->set_elements(LeftTrimFixedArray(elms)); |
+ } else { |
+ // Shift the elements. |
+ AssertNoAllocation no_gc; |
+ MoveElements(&no_gc, elms, 0, elms, 1, len - 1); |
+ elms->set(len - 1, Heap::the_hole_value()); |
+ } |
// Set the length. |
array->set_length(Smi::FromInt(len - 1)); |