From 79e332010a4ad190043c55b2dd8cb4ba66cececf Mon Sep 17 00:00:00 2001 From: "ager@chromium.org" Date: Fri, 23 Jul 2010 11:55:03 +0000 Subject: [PATCH] Fix aliasing problem in inlined stores on x64 and ia32. The receiver 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 | 13 +++++++++---- src/x64/codegen-x64.cc | 13 +++++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index 55317ee..9a11075 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -8968,16 +8968,21 @@ Result CodeGenerator::EmitNamedStore(Handle 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; diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index 4ba9fae..35c1a3d 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -8103,16 +8103,21 @@ Result CodeGenerator::EmitNamedStore(Handle 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; -- 2.7.4