Merge r10187, r10188 from the bleeding_edge to the 3.7 branch.

Rescan cells at the end of mark-sweep.  This means they don't need a
write barrier.
Review URL: http://codereview.chromium.org/8816021
------------------------------------------------------------------------


Remove write barriers for cells on x64, ARM and MIPS.
Review URL: http://codereview.chromium.org/8834005
------------------------------------------------------------------------
Review URL: http://codereview.chromium.org/9190007

git-svn-id: http://v8.googlecode.com/svn/branches/3.7@10392 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 6bc868e..0a4a691 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2266,21 +2266,7 @@
 
   // Store the value.
   __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
-
-  // Cells are always in the remembered set.
-  if (instr->hydrogen()->NeedsWriteBarrier()) {
-    HType type = instr->hydrogen()->value()->type();
-    SmiCheck check_needed =
-        type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
-    __ RecordWriteField(scratch,
-                        JSGlobalPropertyCell::kValueOffset,
-                        value,
-                        scratch2,
-                        kLRHasBeenSaved,
-                        kSaveFPRegs,
-                        OMIT_REMEMBERED_SET,
-                        check_needed);
-  }
+  // Cells are always rescanned, so no write barrier here.
 }
 
 
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 47778f5..d229ae6 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -2587,15 +2587,7 @@
 
   // Store the value in the cell.
   __ str(r0, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset));
-
-  __ mov(r1, r0);
-  __ RecordWriteField(r4,
-                      JSGlobalPropertyCell::kValueOffset,
-                      r1,
-                      r2,
-                      kLRHasNotBeenSaved,
-                      kDontSaveFPRegs,
-                      OMIT_REMEMBERED_SET);
+  // Cells are always rescanned, so no write barrier here.
 
   Counters* counters = masm()->isolate()->counters();
   __ IncrementCounter(counters->named_store_global_inline(), 1, r4, r3);
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index fbae95c..3a286f0 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -4540,7 +4540,8 @@
     // megamorphic.
     __ cmp(ecx, Immediate(UninitializedSentinel(isolate)));
     __ j(equal, &initialize, Label::kNear);
-    // MegamorphicSentinel is a root so no write-barrier is needed.
+    // MegamorphicSentinel is an immortal immovable object (undefined) so no
+    // write-barrier is needed.
     __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
            Immediate(MegamorphicSentinel(isolate)));
     __ jmp(&call, Label::kNear);
@@ -4548,14 +4549,7 @@
     // An uninitialized cache is patched with the function.
     __ bind(&initialize);
     __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset), edi);
-    __ mov(ecx, edi);
-    __ RecordWriteField(ebx,
-                        JSGlobalPropertyCell::kValueOffset,
-                        ecx,
-                        edx,
-                        kDontSaveFPRegs,
-                        OMIT_REMEMBERED_SET,  // Cells are rescanned.
-                        OMIT_SMI_CHECK);
+    // No need for a write barrier here - cells are rescanned.
 
     __ bind(&call);
   }
@@ -4587,6 +4581,8 @@
     // non-function case.
     __ mov(ebx, Operand(esp, 0));
     __ mov(ebx, Operand(ebx, 1));
+    // MegamorphicSentinel is an immortal immovable object (undefined) so no
+    // write barrier is needed.
     __ mov(FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset),
            Immediate(MegamorphicSentinel(isolate)));
   }
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 8b778f3..aacce59 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -2139,20 +2139,7 @@
 
   // Store the value.
   __ mov(FieldOperand(object, offset), value);
-
-  // Cells are always in the remembered set.
-  if (instr->hydrogen()->NeedsWriteBarrier()) {
-    HType type = instr->hydrogen()->value()->type();
-    SmiCheck check_needed =
-        type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
-    __ RecordWriteField(object,
-                        offset,
-                        value,
-                        address,
-                        kSaveFPRegs,
-                        OMIT_REMEMBERED_SET,
-                        check_needed);
-  }
+  // Cells are always rescanned, so no write barrier here.
 }
 
 
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index aa8f47a..722d718 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -2522,23 +2522,9 @@
 
   // Store the value in the cell.
   __ mov(cell_operand, eax);
-  Label done;
-  __ test(eax, Immediate(kSmiTagMask));
-  __ j(zero, &done);
-
-  __ mov(ecx, eax);
-  __ lea(edx, cell_operand);
-  // Cells are always in the remembered set.
-  __ RecordWrite(ebx,  // Object.
-                 edx,  // Address.
-                 ecx,  // Value.
-                 kDontSaveFPRegs,
-                 OMIT_REMEMBERED_SET,
-                 OMIT_SMI_CHECK);
+  // No write barrier here, because cells are always rescanned.
 
   // Return the value (register eax).
-  __ bind(&done);
-
   Counters* counters = isolate()->counters();
   __ IncrementCounter(counters->named_store_global_inline(), 1);
   __ ret(0);
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 1bca5f6..db5ed0f 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -2100,6 +2100,24 @@
 
   PrepareForCodeFlushing();
 
+  if (was_marked_incrementally_) {
+    // There is no write barrier on cells so we have to scan them now at the end
+    // of the incremental marking.
+    {
+      HeapObjectIterator cell_iterator(heap()->cell_space());
+      HeapObject* cell;
+      while ((cell = cell_iterator.Next()) != NULL) {
+        ASSERT(cell->IsJSGlobalPropertyCell());
+        if (IsMarked(cell)) {
+          int offset = JSGlobalPropertyCell::kValueOffset;
+          StaticMarkingVisitor::VisitPointer(
+              heap(),
+              reinterpret_cast<Object**>(cell->address() + offset));
+        }
+      }
+    }
+  }
+
   RootMarkingVisitor root_visitor(heap());
   MarkRoots(&root_visitor);
 
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 5fe904e..54c6dd6 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -2141,21 +2141,7 @@
 
   // Store the value.
   __ sw(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
-
-  // Cells are always in the remembered set.
-  if (instr->hydrogen()->NeedsWriteBarrier()) {
-    HType type = instr->hydrogen()->value()->type();
-    SmiCheck check_needed =
-        type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
-    __ RecordWriteField(scratch,
-                        JSGlobalPropertyCell::kValueOffset,
-                        value,
-                        scratch2,
-                        kRAHasBeenSaved,
-                        kSaveFPRegs,
-                        OMIT_REMEMBERED_SET,
-                        check_needed);
-  }
+  // Cells are always rescanned, so no write barrier here.
 }
 
 
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index 76452f0..9f214a3 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -2605,15 +2605,7 @@
   // Store the value in the cell.
   __ sw(a0, FieldMemOperand(t0, JSGlobalPropertyCell::kValueOffset));
   __ mov(v0, a0);  // Stored value must be returned in v0.
-
-  // This trashes a0 but the value is returned in v0 anyway.
-  __ RecordWriteField(t0,
-                      JSGlobalPropertyCell::kValueOffset,
-                      a0,
-                      a2,
-                      kRAHasNotBeenSaved,
-                      kDontSaveFPRegs,
-                      OMIT_REMEMBERED_SET);
+  // Cells are always rescanned, so no write barrier here.
 
   Counters* counters = masm()->isolate()->counters();
   __ IncrementCounter(counters->named_store_global_inline(), 1, a1, a3);
diff --git a/src/version.cc b/src/version.cc
index 9b243be..115181e 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     7
 #define BUILD_NUMBER      12
-#define PATCH_LEVEL       16
+#define PATCH_LEVEL       17
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index bc9c3ce..623c4b4 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -2049,25 +2049,7 @@
 
   // Store the value.
   __ movq(Operand(address, 0), value);
-
-  if (instr->hydrogen()->NeedsWriteBarrier()) {
-    Label smi_store;
-    HType type = instr->hydrogen()->value()->type();
-    if (!type.IsHeapNumber() && !type.IsString() && !type.IsNonPrimitive()) {
-      __ JumpIfSmi(value, &smi_store, Label::kNear);
-    }
-
-    int offset = JSGlobalPropertyCell::kValueOffset - kHeapObjectTag;
-    __ lea(object, Operand(address, -offset));
-    // Cells are always in the remembered set.
-    __ RecordWrite(object,
-                   address,
-                   value,
-                   kSaveFPRegs,
-                   OMIT_REMEMBERED_SET,
-                   OMIT_SMI_CHECK);
-    __ bind(&smi_store);
-  }
+  // Cells are always rescanned, so no write barrier here.
 }
 
 
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 5a81c89..58994f2 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -2370,23 +2370,9 @@
 
   // Store the value in the cell.
   __ movq(cell_operand, rax);
-  Label done;
-  __ JumpIfSmi(rax, &done);
-
-  __ movq(rcx, rax);
-  __ lea(rdx, cell_operand);
-  // Cells are always in the remembered set.
-  __ RecordWrite(rbx,  // Object.
-                 rdx,  // Address.
-                 rcx,  // Value.
-                 kDontSaveFPRegs,
-                 OMIT_REMEMBERED_SET,
-                 OMIT_SMI_CHECK);
-
+  // Cells are always rescanned, so no write barrier here.
 
   // Return the value (register rax).
-  __ bind(&done);
-
   Counters* counters = isolate()->counters();
   __ IncrementCounter(counters->named_store_global_inline(), 1);
   __ ret(0);