RFC: Try to be much more careful with where we skip the write barrier by:
authorkasperl@chromium.org <kasperl@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 29 Jan 2010 11:46:55 +0000 (11:46 +0000)
committerkasperl@chromium.org <kasperl@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 29 Jan 2010 11:46:55 +0000 (11:46 +0000)
  1. Avoid using SKIP_WRITE_BARRIER when we don't have to (smis).
  2. Check and document the remaining uses of SKIP_WRITE_BARRIER.
  3. Only allow GetWriteBarrierMode when in an AssertNoAllocation scope.

The only functional change should be in DeepCopyBoilerplate where we
no longer use the write barrier mode (because of allocations). I'm
running benchmarks to see if this has a measurable impact on performance.
Review URL: http://codereview.chromium.org/558041

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

src/builtins.cc
src/dateparser.cc
src/globals.h
src/heap.cc
src/objects-inl.h
src/objects.cc
src/objects.h
src/runtime.cc

index 41682bd57e1d8f46872571b19d15fe173767d805..db0770f3a96fead16b44b65ec7f5742c865a7e1e 100644 (file)
@@ -247,8 +247,10 @@ BUILTIN(ArrayCodeGeneric) {
   Smi* len = Smi::FromInt(number_of_elements);
   Object* obj = Heap::AllocateFixedArrayWithHoles(len->value());
   if (obj->IsFailure()) return obj;
+
+  AssertNoAllocation no_gc;
   FixedArray* elms = FixedArray::cast(obj);
-  WriteBarrierMode mode = elms->GetWriteBarrierMode();
+  WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
   // Fill in the content
   for (int index = 0; index < number_of_elements; index++) {
     elms->set(index, args[index+1], mode);
@@ -256,7 +258,7 @@ BUILTIN(ArrayCodeGeneric) {
 
   // Set length and elements on the array.
   array->set_elements(FixedArray::cast(obj));
-  array->set_length(len, SKIP_WRITE_BARRIER);
+  array->set_length(len);
 
   return array;
 }
@@ -283,8 +285,10 @@ BUILTIN(ArrayPush) {
     int capacity = new_length + (new_length >> 1) + 16;
     Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
     if (obj->IsFailure()) return obj;
+
+    AssertNoAllocation no_gc;
     FixedArray* new_elms = FixedArray::cast(obj);
-    WriteBarrierMode mode = new_elms->GetWriteBarrierMode();
+    WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc);
     // Fill out the new array with old elements.
     for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
     // Add the provided values.
@@ -295,7 +299,7 @@ BUILTIN(ArrayPush) {
     array->set_elements(new_elms);
   }
   // Set the length.
-  array->set_length(Smi::FromInt(new_length), SKIP_WRITE_BARRIER);
+  array->set_length(Smi::FromInt(new_length));
   return array->length();
 }
 
@@ -313,7 +317,7 @@ BUILTIN(ArrayPop) {
   Object* top = elms->get(len - 1);
 
   // Set the length.
-  array->set_length(Smi::FromInt(len - 1), SKIP_WRITE_BARRIER);
+  array->set_length(Smi::FromInt(len - 1));
 
   if (!top->IsTheHole()) {
     // Delete the top element.
index 1cc9aa169c55ee1151e495b7ade054882c6d284f..51a63e1a076eb7096066b0a9a4a7daf0752c79bf 100644 (file)
@@ -72,15 +72,9 @@ bool DateParser::DayComposer::Write(FixedArray* output) {
 
   if (!Smi::IsValid(year) || !IsMonth(month) || !IsDay(day)) return false;
 
-  output->set(YEAR,
-              Smi::FromInt(year),
-              SKIP_WRITE_BARRIER);
-  output->set(MONTH,
-              Smi::FromInt(month - 1),
-              SKIP_WRITE_BARRIER);  // 0-based
-  output->set(DAY,
-              Smi::FromInt(day),
-              SKIP_WRITE_BARRIER);
+  output->set(YEAR, Smi::FromInt(year));
+  output->set(MONTH, Smi::FromInt(month - 1));  // 0-based
+  output->set(DAY, Smi::FromInt(day));
   return true;
 }
 
@@ -103,15 +97,9 @@ bool DateParser::TimeComposer::Write(FixedArray* output) {
 
   if (!IsHour(hour) || !IsMinute(minute) || !IsSecond(second)) return false;
 
-  output->set(HOUR,
-              Smi::FromInt(hour),
-              SKIP_WRITE_BARRIER);
-  output->set(MINUTE,
-              Smi::FromInt(minute),
-              SKIP_WRITE_BARRIER);
-  output->set(SECOND,
-              Smi::FromInt(second),
-              SKIP_WRITE_BARRIER);
+  output->set(HOUR, Smi::FromInt(hour));
+  output->set(MINUTE, Smi::FromInt(minute));
+  output->set(SECOND, Smi::FromInt(second));
   return true;
 }
 
@@ -121,13 +109,9 @@ bool DateParser::TimeZoneComposer::Write(FixedArray* output) {
     if (minute_ == kNone) minute_ = 0;
     int total_seconds = sign_ * (hour_ * 3600 + minute_ * 60);
     if (!Smi::IsValid(total_seconds)) return false;
-    output->set(UTC_OFFSET,
-                Smi::FromInt(total_seconds),
-                SKIP_WRITE_BARRIER);
+    output->set(UTC_OFFSET, Smi::FromInt(total_seconds));
   } else {
-    output->set(UTC_OFFSET,
-                Heap::null_value(),
-                SKIP_WRITE_BARRIER);
+    output->set_null(UTC_OFFSET);
   }
   return true;
 }
index f5cb1c093c1b2013c53311909f80c08f742ff15d..39f6bcb260e12fc3b79540ebdddd9ea49da688dc 100644 (file)
@@ -204,6 +204,7 @@ class AccessorInfo;
 class Allocation;
 class Arguments;
 class Assembler;
+class AssertNoAllocation;
 class BreakableStatement;
 class Code;
 class CodeGenerator;
index ecf3cddabe382d38dccf22ff0093da91314a4042..8c6039d0579b072256fe56379a9af5bd87d7b18a 100644 (file)
@@ -1729,7 +1729,7 @@ void Heap::SetNumberStringCache(Object* number, String* string) {
   int mask = (number_string_cache()->length() >> 1) - 1;
   if (number->IsSmi()) {
     hash = smi_get_hash(Smi::cast(number)) & mask;
-    number_string_cache()->set(hash * 2, number, SKIP_WRITE_BARRIER);
+    number_string_cache()->set(hash * 2, Smi::cast(number));
   } else {
     hash = double_get_hash(number->Number()) & mask;
     number_string_cache()->set(hash * 2, number);
@@ -1986,8 +1986,10 @@ Object* Heap::AllocateConsString(String* first, String* second) {
 
   Object* result = Allocate(map, NEW_SPACE);
   if (result->IsFailure()) return result;
+
+  AssertNoAllocation no_gc;
   ConsString* cons_string = ConsString::cast(result);
-  WriteBarrierMode mode = cons_string->GetWriteBarrierMode();
+  WriteBarrierMode mode = cons_string->GetWriteBarrierMode(no_gc);
   cons_string->set_length(length);
   cons_string->set_hash_field(String::kEmptyHashField);
   cons_string->set_first(first, mode);
@@ -2285,7 +2287,7 @@ Object* Heap::InitializeFunction(JSFunction* function,
   function->set_shared(shared);
   function->set_prototype_or_initial_map(prototype);
   function->set_context(undefined_value());
-  function->set_literals(empty_fixed_array(), SKIP_WRITE_BARRIER);
+  function->set_literals(empty_fixed_array());
   return function;
 }
 
@@ -2886,8 +2888,10 @@ Object* Heap::CopyFixedArray(FixedArray* src) {
   HeapObject::cast(obj)->set_map(src->map());
   FixedArray* result = FixedArray::cast(obj);
   result->set_length(len);
+
   // Copy the content
-  WriteBarrierMode mode = result->GetWriteBarrierMode();
+  AssertNoAllocation no_gc;
+  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
   for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
   return result;
 }
@@ -2905,6 +2909,7 @@ Object* Heap::AllocateFixedArray(int length) {
     Object* value = undefined_value();
     // Initialize body.
     for (int index = 0; index < length; index++) {
+      ASSERT(!Heap::InNewSpace(value));  // value = undefined
       array->set(index, value, SKIP_WRITE_BARRIER);
     }
   }
@@ -2960,6 +2965,7 @@ Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
   array->set_length(length);
   Object* value = undefined_value();
   for (int index = 0; index < length; index++) {
+    ASSERT(!Heap::InNewSpace(value));  // value = undefined
     array->set(index, value, SKIP_WRITE_BARRIER);
   }
   return array;
@@ -2977,6 +2983,7 @@ Object* Heap::AllocateFixedArrayWithHoles(int length) {
     // Initialize body.
     Object* value = the_hole_value();
     for (int index = 0; index < length; index++)  {
+      ASSERT(!Heap::InNewSpace(value));  // value = the hole
       array->set(index, value, SKIP_WRITE_BARRIER);
     }
   }
index 58b0f5a86d26a7ef437ae02e4271e03415f930f0..4355fe9e1fb6b72db3400b1b227ee32d0301b0e0 100644 (file)
@@ -1349,7 +1349,7 @@ void FixedArray::set(int index, Object* value) {
 }
 
 
-WriteBarrierMode HeapObject::GetWriteBarrierMode() {
+WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
   if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
   return UPDATE_WRITE_BARRIER;
 }
@@ -1548,9 +1548,7 @@ uint32_t NumberDictionary::max_number_key() {
 }
 
 void NumberDictionary::set_requires_slow_elements() {
-  set(kMaxNumberKeyIndex,
-      Smi::FromInt(kRequiresSlowElementsMask),
-      SKIP_WRITE_BARRIER);
+  set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
 }
 
 
@@ -2973,7 +2971,8 @@ void Dictionary<Shape, Key>::SetEntry(int entry,
                                       PropertyDetails details) {
   ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
   int index = HashTable<Shape, Key>::EntryToIndex(entry);
-  WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
+  AssertNoAllocation no_gc;
+  WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
   FixedArray::set(index, key, mode);
   FixedArray::set(index+1, value, mode);
   FixedArray::fast_set(this, index+2, details.AsSmi());
@@ -3007,8 +3006,13 @@ void JSArray::EnsureSize(int required_size) {
 }
 
 
+void JSArray::set_length(Smi* length) {
+  set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
+}
+
+
 void JSArray::SetContent(FixedArray* storage) {
-  set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
+  set_length(Smi::FromInt(storage->length()));
   set_elements(storage);
 }
 
index c76fc83377b062eaf09dffddd0936a2d6fef2534..6dd1d492420be644ef27060dcd6941eb45c90e41 100644 (file)
@@ -3200,8 +3200,9 @@ Object* FixedArray::UnionOfKeys(FixedArray* other) {
   Object* obj = Heap::AllocateFixedArray(len0 + extra);
   if (obj->IsFailure()) return obj;
   // Fill in the content
+  AssertNoAllocation no_gc;
   FixedArray* result = FixedArray::cast(obj);
-  WriteBarrierMode mode = result->GetWriteBarrierMode();
+  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
   for (int i = 0; i < len0; i++) {
     result->set(i, get(i), mode);
   }
@@ -3225,10 +3226,11 @@ Object* FixedArray::CopySize(int new_length) {
   if (obj->IsFailure()) return obj;
   FixedArray* result = FixedArray::cast(obj);
   // Copy the content
+  AssertNoAllocation no_gc;
   int len = length();
   if (new_length < len) len = new_length;
   result->set_map(map());
-  WriteBarrierMode mode = result->GetWriteBarrierMode();
+  WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
   for (int i = 0; i < len; i++) {
     result->set(i, get(i), mode);
   }
@@ -3237,7 +3239,8 @@ Object* FixedArray::CopySize(int new_length) {
 
 
 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
-  WriteBarrierMode mode = dest->GetWriteBarrierMode();
+  AssertNoAllocation no_gc;
+  WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
   for (int index = 0; index < len; index++) {
     dest->set(dest_pos+index, get(pos+index), mode);
   }
@@ -3271,8 +3274,7 @@ Object* DescriptorArray::Allocate(int number_of_descriptors) {
   if (array->IsFailure()) return array;
   result->set(kContentArrayIndex, array);
   result->set(kEnumerationIndexIndex,
-              Smi::FromInt(PropertyDetails::kInitialIndex),
-              SKIP_WRITE_BARRIER);
+              Smi::FromInt(PropertyDetails::kInitialIndex));
   return result;
 }
 
@@ -4700,8 +4702,8 @@ void Map::ClearNonLiveTransitions(Object* real_prototype) {
       ASSERT(target->IsHeapObject());
       if (!target->IsMarked()) {
         ASSERT(target->IsMap());
-        contents->set(i + 1, NullDescriptorDetails, SKIP_WRITE_BARRIER);
-        contents->set(i, Heap::null_value(), SKIP_WRITE_BARRIER);
+        contents->set(i + 1, NullDescriptorDetails);
+        contents->set_null(i);
         ASSERT(target->prototype() == this ||
                target->prototype() == real_prototype);
         // Getter prototype() is read-only, set_prototype() has side effects.
@@ -5161,7 +5163,8 @@ void JSObject::SetFastElements(FixedArray* elems) {
   uint32_t len = static_cast<uint32_t>(elems->length());
   for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole());
 #endif
-  WriteBarrierMode mode = elems->GetWriteBarrierMode();
+  AssertNoAllocation no_gc;
+  WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc);
   switch (GetElementsKind()) {
     case FAST_ELEMENTS: {
       FixedArray* old_elements = FixedArray::cast(elements());
@@ -5228,7 +5231,7 @@ Object* JSObject::SetSlowElements(Object* len) {
 
 Object* JSArray::Initialize(int capacity) {
   ASSERT(capacity >= 0);
-  set_length(Smi::FromInt(0), SKIP_WRITE_BARRIER);
+  set_length(Smi::FromInt(0));
   FixedArray* new_elements;
   if (capacity == 0) {
     new_elements = Heap::empty_fixed_array();
@@ -5288,7 +5291,7 @@ Object* JSObject::SetElementsLength(Object* len) {
             for (int i = value; i < old_length; i++) {
               FixedArray::cast(elements())->set_the_hole(i);
             }
-            JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER);
+            JSArray::cast(this)->set_length(Smi::cast(smi_length));
           }
           return this;
         }
@@ -5298,8 +5301,9 @@ Object* JSObject::SetElementsLength(Object* len) {
             !ShouldConvertToSlowElements(new_capacity)) {
           Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
           if (obj->IsFailure()) return obj;
-          if (IsJSArray()) JSArray::cast(this)->set_length(smi_length,
-                                                           SKIP_WRITE_BARRIER);
+          if (IsJSArray()) {
+            JSArray::cast(this)->set_length(Smi::cast(smi_length));
+          }
           SetFastElements(FixedArray::cast(obj));
           return this;
         }
@@ -5318,7 +5322,7 @@ Object* JSObject::SetElementsLength(Object* len) {
             static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
             element_dictionary()->RemoveNumberEntries(value, old_length);
           }
-          JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER);
+          JSArray::cast(this)->set_length(Smi::cast(smi_length));
         }
         return this;
       }
@@ -5343,8 +5347,7 @@ Object* JSObject::SetElementsLength(Object* len) {
   Object* obj = Heap::AllocateFixedArray(1);
   if (obj->IsFailure()) return obj;
   FixedArray::cast(obj)->set(0, len);
-  if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1),
-                                                   SKIP_WRITE_BARRIER);
+  if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1));
   set_elements(FixedArray::cast(obj));
   return this;
 }
@@ -5614,8 +5617,7 @@ Object* JSObject::SetFastElement(uint32_t index, Object* value) {
       CHECK(Array::IndexFromObject(JSArray::cast(this)->length(),
                                    &array_length));
       if (index >= array_length) {
-        JSArray::cast(this)->set_length(Smi::FromInt(index + 1),
-                                        SKIP_WRITE_BARRIER);
+        JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
       }
     }
     return value;
@@ -5631,8 +5633,9 @@ Object* JSObject::SetFastElement(uint32_t index, Object* value) {
       Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
       if (obj->IsFailure()) return obj;
       SetFastElements(FixedArray::cast(obj));
-      if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(index + 1),
-                                                       SKIP_WRITE_BARRIER);
+      if (IsJSArray()) {
+        JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
+      }
       FixedArray::cast(elements())->set(index, value);
       return value;
     }
@@ -6129,7 +6132,8 @@ template<typename Shape, typename Key>
 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) {
   int pos = 0;
   int capacity = HashTable<Shape, Key>::Capacity();
-  WriteBarrierMode mode = elements->GetWriteBarrierMode();
+  AssertNoAllocation no_gc;
+  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
   for (int i = 0; i < capacity; i++) {
     Object* k =  Dictionary<Shape, Key>::KeyAt(i);
     if (Dictionary<Shape, Key>::IsKey(k)) {
@@ -6500,7 +6504,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
       for (int i = 0; i < length; i++) {
         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
           if (storage != NULL) {
-            storage->set(counter, Smi::FromInt(i), SKIP_WRITE_BARRIER);
+            storage->set(counter, Smi::FromInt(i));
           }
           counter++;
         }
@@ -6512,7 +6516,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
       int length = PixelArray::cast(elements())->length();
       while (counter < length) {
         if (storage != NULL) {
-          storage->set(counter, Smi::FromInt(counter), SKIP_WRITE_BARRIER);
+          storage->set(counter, Smi::FromInt(counter));
         }
         counter++;
       }
@@ -6529,7 +6533,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
       int length = ExternalArray::cast(elements())->length();
       while (counter < length) {
         if (storage != NULL) {
-          storage->set(counter, Smi::FromInt(counter), SKIP_WRITE_BARRIER);
+          storage->set(counter, Smi::FromInt(counter));
         }
         counter++;
       }
@@ -6554,7 +6558,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
       String* str = String::cast(val);
       if (storage) {
         for (int i = 0; i < str->length(); i++) {
-          storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER);
+          storage->set(counter + i, Smi::FromInt(i));
         }
       }
       counter += str->length();
@@ -6886,8 +6890,10 @@ Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
 
   Object* obj = Allocate(nof * 2);
   if (obj->IsFailure()) return obj;
+
+  AssertNoAllocation no_gc;
   HashTable* table = HashTable::cast(obj);
-  WriteBarrierMode mode = table->GetWriteBarrierMode();
+  WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc);
 
   // Copy prefix to new array.
   for (int i = kPrefixStartIndex;
@@ -7134,7 +7140,7 @@ Object* JSObject::PrepareElementsForSort(uint32_t limit) {
 
   // Split elements into defined, undefined and the_hole, in that order.
   // Only count locations for undefined and the hole, and fill them afterwards.
-  WriteBarrierMode write_barrier = elements->GetWriteBarrierMode();
+  WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc);
   unsigned int undefs = limit;
   unsigned int holes = limit;
   // Assume most arrays contain no holes and undefined values, so minimize the
@@ -7629,7 +7635,7 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
   if (obj->IsFailure()) return obj;
   FixedArray* iteration_order = FixedArray::cast(obj);
   for (int i = 0; i < length; i++) {
-    iteration_order->set(i, Smi::FromInt(i), SKIP_WRITE_BARRIER);
+    iteration_order->set(i, Smi::FromInt(i));
   }
 
   // Allocate array with enumeration order.
@@ -7642,9 +7648,7 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
   int pos = 0;
   for (int i = 0; i < capacity; i++) {
     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
-      enumeration_order->set(pos++,
-                             Smi::FromInt(DetailsAt(i).index()),
-                             SKIP_WRITE_BARRIER);
+      enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index()));
     }
   }
 
@@ -7655,9 +7659,7 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
   for (int i = 0; i < length; i++) {
     int index = Smi::cast(iteration_order->get(i))->value();
     int enum_index = PropertyDetails::kInitialIndex + i;
-    enumeration_order->set(index,
-                           Smi::FromInt(enum_index),
-                           SKIP_WRITE_BARRIER);
+    enumeration_order->set(index, Smi::FromInt(enum_index));
   }
 
   // Update the dictionary with new indices.
@@ -7805,8 +7807,7 @@ void NumberDictionary::UpdateMaxNumberKey(uint32_t key) {
   Object* max_index_object = get(kMaxNumberKeyIndex);
   if (!max_index_object->IsSmi() || max_number_key() < key) {
     FixedArray::set(kMaxNumberKeyIndex,
-                    Smi::FromInt(key << kRequiresSlowElementsTagSize),
-                    SKIP_WRITE_BARRIER);
+                    Smi::FromInt(key << kRequiresSlowElementsTagSize));
   }
 }
 
@@ -7897,9 +7898,7 @@ void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
        PropertyDetails details = DetailsAt(i);
        if (details.IsDeleted() || details.IsDontEnum()) continue;
        storage->set(index, k);
-       sort_array->set(index,
-                       Smi::FromInt(details.index()),
-                       SKIP_WRITE_BARRIER);
+       sort_array->set(index, Smi::FromInt(details.index()));
        index++;
      }
   }
index 367e9465b04ef2d9bb6689673cca2ecb122bb34f..f6411965a5aa3b6f9b3320bb749083661b3179a3 100644 (file)
@@ -1023,8 +1023,12 @@ class HeapObject: public Object {
   // Casting.
   static inline HeapObject* cast(Object* obj);
 
-  // Return the write barrier mode for this.
-  inline WriteBarrierMode GetWriteBarrierMode();
+  // Return the write barrier mode for this. Callers of this function
+  // must be able to present a reference to an AssertNoAllocation
+  // object as a sign that they are not going to use this function
+  // from code that allocates and thus invalidates the returned write
+  // barrier mode.
+  inline WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation&);
 
   // Dispatched behavior.
   void HeapObjectShortPrint(StringStream* accumulator);
@@ -4475,6 +4479,10 @@ class JSArray: public JSObject {
   // [length]: The length property.
   DECL_ACCESSORS(length, Object)
 
+  // Overload the length setter to skip write barrier when the length
+  // is set to a smi. This matches the set function on FixedArray.
+  inline void set_length(Smi* length);
+
   Object* JSArrayUpdateLengthFromIndex(uint32_t index, Object* value);
 
   // Initialize the array with the given capacity. The function may
index 4f68a658e060dd0650fd75a694282ac3b762b892..58ed3b3e321ae991cca1f2056eb4c72a30fa29c2 100644 (file)
@@ -107,25 +107,23 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
   // Deep copy local properties.
   if (copy->HasFastProperties()) {
     FixedArray* properties = copy->properties();
-    WriteBarrierMode mode = properties->GetWriteBarrierMode();
     for (int i = 0; i < properties->length(); i++) {
       Object* value = properties->get(i);
       if (value->IsJSObject()) {
-        JSObject* jsObject = JSObject::cast(value);
-        result = DeepCopyBoilerplate(jsObject);
+        JSObject* js_object = JSObject::cast(value);
+        result = DeepCopyBoilerplate(js_object);
         if (result->IsFailure()) return result;
-        properties->set(i, result, mode);
+        properties->set(i, result);
       }
     }
-    mode = copy->GetWriteBarrierMode();
     int nof = copy->map()->inobject_properties();
     for (int i = 0; i < nof; i++) {
       Object* value = copy->InObjectPropertyAt(i);
       if (value->IsJSObject()) {
-        JSObject* jsObject = JSObject::cast(value);
-        result = DeepCopyBoilerplate(jsObject);
+        JSObject* js_object = JSObject::cast(value);
+        result = DeepCopyBoilerplate(js_object);
         if (result->IsFailure()) return result;
-        copy->InObjectPropertyAtPut(i, result, mode);
+        copy->InObjectPropertyAtPut(i, result);
       }
     }
   } else {
@@ -135,20 +133,20 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
     copy->GetLocalPropertyNames(names, 0);
     for (int i = 0; i < names->length(); i++) {
       ASSERT(names->get(i)->IsString());
-      String* keyString = String::cast(names->get(i));
+      String* key_string = String::cast(names->get(i));
       PropertyAttributes attributes =
-        copy->GetLocalPropertyAttribute(keyString);
+          copy->GetLocalPropertyAttribute(key_string);
       // Only deep copy fields from the object literal expression.
       // In particular, don't try to copy the length attribute of
       // an array.
       if (attributes != NONE) continue;
-      Object* value = copy->GetProperty(keyString, &attributes);
+      Object* value = copy->GetProperty(key_string, &attributes);
       ASSERT(!value->IsFailure());
       if (value->IsJSObject()) {
-        JSObject* jsObject = JSObject::cast(value);
-        result = DeepCopyBoilerplate(jsObject);
+        JSObject* js_object = JSObject::cast(value);
+        result = DeepCopyBoilerplate(js_object);
         if (result->IsFailure()) return result;
-        result = copy->SetProperty(keyString, result, NONE);
+        result = copy->SetProperty(key_string, result, NONE);
         if (result->IsFailure()) return result;
       }
     }
@@ -160,14 +158,13 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
   switch (copy->GetElementsKind()) {
     case JSObject::FAST_ELEMENTS: {
       FixedArray* elements = FixedArray::cast(copy->elements());
-      WriteBarrierMode mode = elements->GetWriteBarrierMode();
       for (int i = 0; i < elements->length(); i++) {
         Object* value = elements->get(i);
         if (value->IsJSObject()) {
-          JSObject* jsObject = JSObject::cast(value);
-          result = DeepCopyBoilerplate(jsObject);
+          JSObject* js_object = JSObject::cast(value);
+          result = DeepCopyBoilerplate(js_object);
           if (result->IsFailure()) return result;
-          elements->set(i, result, mode);
+          elements->set(i, result);
         }
       }
       break;
@@ -180,8 +177,8 @@ static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
         if (element_dictionary->IsKey(k)) {
           Object* value = element_dictionary->ValueAt(i);
           if (value->IsJSObject()) {
-            JSObject* jsObject = JSObject::cast(value);
-            result = DeepCopyBoilerplate(jsObject);
+            JSObject* js_object = JSObject::cast(value);
+            result = DeepCopyBoilerplate(js_object);
             if (result->IsFailure()) return result;
             element_dictionary->ValueAtPut(i, result);
           }
@@ -1439,6 +1436,8 @@ static Object* Runtime_SetCode(Arguments args) {
       literals->set(JSFunction::kLiteralGlobalContextIndex,
                     context->global_context());
     }
+    // It's okay to skip the write barrier here because the literals
+    // are guaranteed to be in old space.
     target->set_literals(*literals, SKIP_WRITE_BARRIER);
   }
 
@@ -4717,7 +4716,9 @@ static Object* Runtime_NewArguments(Arguments args) {
     if (obj->IsFailure()) return obj;
     FixedArray* array = FixedArray::cast(obj);
     ASSERT(array->length() == length);
-    WriteBarrierMode mode = array->GetWriteBarrierMode();
+
+    AssertNoAllocation no_gc;
+    WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
     for (int i = 0; i < length; i++) {
       array->set(i, frame->GetParameter(i), mode);
     }
@@ -4742,10 +4743,13 @@ static Object* Runtime_NewArgumentsFast(Arguments args) {
     // Allocate the fixed array.
     Object* obj = Heap::AllocateRawFixedArray(length);
     if (obj->IsFailure()) return obj;
+
+    AssertNoAllocation no_gc;
     reinterpret_cast<Array*>(obj)->set_map(Heap::fixed_array_map());
     FixedArray* array = FixedArray::cast(obj);
     array->set_length(length);
-    WriteBarrierMode mode = array->GetWriteBarrierMode();
+
+    WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
     for (int i = 0; i < length; i++) {
       array->set(i, *--parameters, mode);
     }
@@ -6030,7 +6034,7 @@ static Object* Runtime_MoveArrayContents(Arguments args) {
   to->SetContent(FixedArray::cast(from->elements()));
   to->set_length(from->length());
   from->SetContent(Heap::empty_fixed_array());
-  from->set_length(0);
+  from->set_length(Smi::FromInt(0));
   return to;
 }
 
@@ -6073,9 +6077,7 @@ static Object* Runtime_GetArrayKeys(Arguments args) {
   } else {
     Handle<FixedArray> single_interval = Factory::NewFixedArray(2);
     // -1 means start of array.
-    single_interval->set(0,
-                         Smi::FromInt(-1),
-                         SKIP_WRITE_BARRIER);
+    single_interval->set(0, Smi::FromInt(-1));
     uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
     uint32_t min_length = actual_length < length ? actual_length : length;
     Handle<Object> length_object =
@@ -7448,7 +7450,9 @@ static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
   const int length = frame->GetProvidedParametersCount();
   Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
   Handle<FixedArray> array = Factory::NewFixedArray(length);
-  WriteBarrierMode mode = array->GetWriteBarrierMode();
+
+  AssertNoAllocation no_gc;
+  WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
   for (int i = 0; i < length; i++) {
     array->set(i, frame->GetParameter(i), mode);
   }
@@ -8032,7 +8036,7 @@ static Object* Runtime_CollectStackTrace(Arguments args) {
       if (cursor + 2 < elements->length()) {
         elements->set(cursor++, recv);
         elements->set(cursor++, fun);
-        elements->set(cursor++, offset, SKIP_WRITE_BARRIER);
+        elements->set(cursor++, offset);
       } else {
         HandleScope scope;
         Handle<Object> recv_handle(recv);
@@ -8045,8 +8049,7 @@ static Object* Runtime_CollectStackTrace(Arguments args) {
     iter.Advance();
   }
 
-  result->set_length(Smi::FromInt(cursor), SKIP_WRITE_BARRIER);
-
+  result->set_length(Smi::FromInt(cursor));
   return *result;
 }