| Index: src/arm/macro-assembler-arm.cc
|
| diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
|
| index f7b57300937a8e7e0eced51d591b221f9781d8ff..e7e1ea5e323688a114da863d1ddeaa58c69c9c60 100644
|
| --- a/src/arm/macro-assembler-arm.cc
|
| +++ b/src/arm/macro-assembler-arm.cc
|
| @@ -1985,6 +1985,7 @@ void MacroAssembler::Allocate(int object_size,
|
| Label* gc_required,
|
| AllocationFlags flags) {
|
| DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
|
| + DCHECK((flags & ALLOCATION_FOLDED) == 0);
|
| if (!FLAG_inline_new) {
|
| if (emit_debug_code()) {
|
| // Trash the registers to simulate an allocation failure.
|
| @@ -2077,9 +2078,14 @@ void MacroAssembler::Allocate(int object_size,
|
| cond = cc;
|
| }
|
| }
|
| +
|
| cmp(result_end, Operand(alloc_limit));
|
| b(hi, gc_required);
|
| - str(result_end, MemOperand(top_address));
|
| +
|
| + if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
|
| + // The top pointer is not updated for allocation folding dominators.
|
| + str(result_end, MemOperand(top_address));
|
| + }
|
|
|
| // Tag object.
|
| add(result, result, Operand(kHeapObjectTag));
|
| @@ -2089,6 +2095,7 @@ void MacroAssembler::Allocate(int object_size,
|
| void MacroAssembler::Allocate(Register object_size, Register result,
|
| Register result_end, Register scratch,
|
| Label* gc_required, AllocationFlags flags) {
|
| + DCHECK((flags & ALLOCATION_FOLDED) == 0);
|
| if (!FLAG_inline_new) {
|
| if (emit_debug_code()) {
|
| // Trash the registers to simulate an allocation failure.
|
| @@ -2164,7 +2171,7 @@ void MacroAssembler::Allocate(Register object_size, Register result,
|
| } else {
|
| add(result_end, result, Operand(object_size), SetCC);
|
| }
|
| - b(cs, gc_required);
|
| +
|
| cmp(result_end, Operand(alloc_limit));
|
| b(hi, gc_required);
|
|
|
| @@ -2173,12 +2180,122 @@ void MacroAssembler::Allocate(Register object_size, Register result,
|
| tst(result_end, Operand(kObjectAlignmentMask));
|
| Check(eq, kUnalignedAllocationInNewSpace);
|
| }
|
| - str(result_end, MemOperand(top_address));
|
| + if ((flags & ALLOCATION_FOLDING_DOMINATOR) == 0) {
|
| + // The top pointer is not updated for allocation folding dominators.
|
| + str(result_end, MemOperand(top_address));
|
| + }
|
|
|
| // Tag object.
|
| add(result, result, Operand(kHeapObjectTag));
|
| }
|
|
|
| +void MacroAssembler::FastAllocate(Register object_size, Register result,
|
| + Register result_end, Register scratch,
|
| + AllocationFlags flags) {
|
| + // |object_size| and |result_end| may overlap if the DOUBLE_ALIGNMENT flag
|
| + // is not specified. Other registers must not overlap.
|
| + DCHECK(!AreAliased(object_size, result, scratch, ip));
|
| + DCHECK(!AreAliased(result_end, result, scratch, ip));
|
| + DCHECK((flags & DOUBLE_ALIGNMENT) == 0 || !object_size.is(result_end));
|
| +
|
| + ExternalReference allocation_top =
|
| + AllocationUtils::GetAllocationTopReference(isolate(), flags);
|
| +
|
| + Register top_address = scratch;
|
| + mov(top_address, Operand(allocation_top));
|
| + ldr(result, MemOperand(top_address));
|
| +
|
| + if ((flags & DOUBLE_ALIGNMENT) != 0) {
|
| + // Align the next allocation. Storing the filler map without checking top is
|
| + // safe in new-space because the limit of the heap is aligned there.
|
| + DCHECK(kPointerAlignment * 2 == kDoubleAlignment);
|
| + and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC);
|
| + Label aligned;
|
| + b(eq, &aligned);
|
| + mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
|
| + str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex));
|
| + bind(&aligned);
|
| + }
|
| +
|
| + // Calculate new top using result. Object size may be in words so a shift is
|
| + // required to get the number of bytes.
|
| + if ((flags & SIZE_IN_WORDS) != 0) {
|
| + add(result_end, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC);
|
| + } else {
|
| + add(result_end, result, Operand(object_size), SetCC);
|
| + }
|
| +
|
| + // Update allocation top. result temporarily holds the new top.
|
| + if (emit_debug_code()) {
|
| + tst(result_end, Operand(kObjectAlignmentMask));
|
| + Check(eq, kUnalignedAllocationInNewSpace);
|
| + }
|
| + // The top pointer is not updated for allocation folding dominators.
|
| + str(result_end, MemOperand(top_address));
|
| +
|
| + add(result, result, Operand(kHeapObjectTag));
|
| +}
|
| +
|
| +void MacroAssembler::FastAllocate(int object_size, Register result,
|
| + Register scratch1, Register scratch2,
|
| + AllocationFlags flags) {
|
| + DCHECK(object_size <= Page::kMaxRegularHeapObjectSize);
|
| + DCHECK(!AreAliased(result, scratch1, scratch2, ip));
|
| +
|
| + // Make object size into bytes.
|
| + if ((flags & SIZE_IN_WORDS) != 0) {
|
| + object_size *= kPointerSize;
|
| + }
|
| + DCHECK_EQ(0, object_size & kObjectAlignmentMask);
|
| +
|
| + ExternalReference allocation_top =
|
| + AllocationUtils::GetAllocationTopReference(isolate(), flags);
|
| +
|
| + // Set up allocation top address register.
|
| + Register top_address = scratch1;
|
| + Register result_end = scratch2;
|
| + mov(top_address, Operand(allocation_top));
|
| + ldr(result, MemOperand(top_address));
|
| +
|
| + if ((flags & DOUBLE_ALIGNMENT) != 0) {
|
| + // Align the next allocation. Storing the filler map without checking top is
|
| + // safe in new-space because the limit of the heap is aligned there.
|
| + STATIC_ASSERT(kPointerAlignment * 2 == kDoubleAlignment);
|
| + and_(result_end, result, Operand(kDoubleAlignmentMask), SetCC);
|
| + Label aligned;
|
| + b(eq, &aligned);
|
| + mov(result_end, Operand(isolate()->factory()->one_pointer_filler_map()));
|
| + str(result_end, MemOperand(result, kDoubleSize / 2, PostIndex));
|
| + bind(&aligned);
|
| + }
|
| +
|
| + // Calculate new top using result. Object size may be in words so a shift is
|
| + // required to get the number of bytes. We must preserve the ip register at
|
| + // this point, so we cannot just use add().
|
| + DCHECK(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);
|
| + DCHECK(bits_operand.instructions_required(this) == 1);
|
| + add(result_end, source, bits_operand, LeaveCC, cond);
|
| + source = result_end;
|
| + cond = cc;
|
| + }
|
| + }
|
| +
|
| + // The top pointer is not updated for allocation folding dominators.
|
| + str(result_end, MemOperand(top_address));
|
| +
|
| + add(result, result, Operand(kHeapObjectTag));
|
| +}
|
|
|
| void MacroAssembler::AllocateTwoByteString(Register result,
|
| Register length,
|
|
|