From a04490517a38087e0f9881461fc352372c425ea2 Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Mon, 19 Aug 2013 13:37:57 +0000 Subject: [PATCH] ARM: Fix register misuse bug in Allocate(). The bug is triggered if flags contains DOUBLE_ALIGNMENT and the object_size is not an ARM immediate value. In this case, the code for DOUBLE_ALIGNMENT uses the scratch2 register, which is aliased to obj_size_reg containing the object_size. Instead of pre-loading the object_size, which is difficult since we are out of registers here, we simply generate a non-empty sequence of add instructions for the addition of the constant object_size (carefully handling possible overflow in each step). Also turn static ASSERT into STATIC_ASSERT in Allocate(). BUG=v8:2851 R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/23323002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16221 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/macro-assembler-arm.cc | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index a56744b..4e28021 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -1702,15 +1702,9 @@ void MacroAssembler::Allocate(int object_size, ASSERT((limit - top) == kPointerSize); ASSERT(result.code() < ip.code()); - // Set up allocation top address and object size registers. + // Set up allocation top address register. Register topaddr = scratch1; - Register obj_size_reg = scratch2; mov(topaddr, Operand(allocation_top)); - Operand obj_size_operand = Operand(object_size); - if (!obj_size_operand.is_single_instruction(this)) { - // We are about to steal IP, so we need to load this value first - mov(obj_size_reg, obj_size_operand); - } // This code stores a temporary value in ip. This is OK, as the code below // does not need ip for implicit literal generation. @@ -1734,7 +1728,7 @@ void MacroAssembler::Allocate(int object_size, // Align the next allocation. Storing the filler map without checking top is // always safe because the limit of the heap is always aligned. ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0); - ASSERT(kPointerAlignment * 2 == kDoubleAlignment); + STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment); and_(scratch2, result, Operand(kDoubleAlignmentMask), SetCC); Label aligned; b(eq, &aligned); @@ -1744,13 +1738,25 @@ void MacroAssembler::Allocate(int object_size, } // Calculate new top and bail out if new space is exhausted. Use result - // to calculate the new top. - if (obj_size_operand.is_single_instruction(this)) { - // We can add the size as an immediate - add(scratch2, result, obj_size_operand, SetCC); - } else { - // Doesn't fit in an immediate, we have to use the register - add(scratch2, result, obj_size_reg, SetCC); + // to calculate the new top. We must preserve the ip register at this + // point, so we cannot just use add(). + ASSERT(object_size > 0); + Register source = result; + Condition cond = al; + int shift = 0; + while (object_size != 0) { + if (((object_size >> shift) & 0x03) == 0) { + shift += 2; + } else { + int bits = object_size & (0xff << shift); + object_size -= bits; + shift += 8; + Operand bits_operand(bits); + ASSERT(bits_operand.is_single_instruction(this)); + add(scratch2, source, bits_operand, SetCC, cond); + source = scratch2; + cond = cc; + } } b(cs, gc_required); cmp(scratch2, Operand(ip)); -- 2.7.4