Trim underlying fixed array by one element from the left when doing shift.
authorantonm@chromium.org <antonm@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 23 Mar 2010 14:05:16 +0000 (14:05 +0000)
committerantonm@chromium.org <antonm@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 23 Mar 2010 14:05:16 +0000 (14:05 +0000)
For now this trick is only done to objects in new space, see comments
for reasons.

Review URL: http://codereview.chromium.org/1076010

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4229 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/builtins.cc

index 91cb1515200ac8555ed181cfb9de15ed926848ff..122fbba2c4aac4464c2a5bc1d37cf66d283b30bb 100644 (file)
@@ -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));