Fix aliasing problem in inlined stores on x64 and ia32. The receiver
authorager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 23 Jul 2010 11:55:03 +0000 (11:55 +0000)
committerager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 23 Jul 2010 11:55:03 +0000 (11:55 +0000)
and the value can share a register. We need to remove this aliasing
before modifying the registers.

I haven't managed to generate a stand-alon test case for this
yet. I'll do that as a separate change. This was found while loading
Wave.

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

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

src/ia32/codegen-ia32.cc
src/x64/codegen-x64.cc

index 55317ee..9a11075 100644 (file)
@@ -8968,16 +8968,21 @@ Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
 
     // Allocate scratch register for write barrier.
     Result scratch = allocator()->Allocate();
-    ASSERT(scratch.is_valid() &&
-           result.is_valid() &&
-           receiver.is_valid() &&
-           value.is_valid());
+    ASSERT(scratch.is_valid());
 
     // The write barrier clobbers all input registers, so spill the
     // receiver and the value.
     frame_->Spill(receiver.reg());
     frame_->Spill(value.reg());
 
+    // If the receiver and the value share a register allocate a new
+    // register for the receiver.
+    if (receiver.reg().is(value.reg())) {
+      receiver = allocator()->Allocate();
+      ASSERT(receiver.is_valid());
+      __ mov(receiver.reg(), Operand(value.reg()));
+    }
+
     // Update the write barrier. To save instructions in the inlined
     // version we do not filter smis.
     Label skip_write_barrier;
index 4ba9fae..35c1a3d 100644 (file)
@@ -8103,16 +8103,21 @@ Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
 
     // Allocate scratch register for write barrier.
     Result scratch = allocator()->Allocate();
-    ASSERT(scratch.is_valid() &&
-           result.is_valid() &&
-           receiver.is_valid() &&
-           value.is_valid());
+    ASSERT(scratch.is_valid());
 
     // The write barrier clobbers all input registers, so spill the
     // receiver and the value.
     frame_->Spill(receiver.reg());
     frame_->Spill(value.reg());
 
+    // If the receiver and the value share a register allocate a new
+    // register for the receiver.
+    if (receiver.reg().is(value.reg())) {
+      receiver = allocator()->Allocate();
+      ASSERT(receiver.is_valid());
+      __ movq(receiver.reg(), value.reg());
+    }
+
     // Update the write barrier. To save instructions in the inlined
     // version we do not filter smis.
     Label skip_write_barrier;