From df529fb05fa8069fc643a010b92d21bd92a8a1bb Mon Sep 17 00:00:00 2001 From: "m.m.capewell@googlemail.com" Date: Thu, 13 Mar 2014 13:18:48 +0000 Subject: [PATCH] A64: Implement and use FillFields BUG= R=ulan@chromium.org Review URL: https://codereview.chromium.org/190763012 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19895 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/a64/builtins-a64.cc | 48 ++++++++++++++++++++++------------ src/a64/lithium-a64.cc | 3 ++- src/a64/lithium-a64.h | 7 +++-- src/a64/lithium-codegen-a64.cc | 23 ++++++++-------- src/a64/macro-assembler-a64.cc | 39 +++++++++++++++++++++------ src/a64/macro-assembler-a64.h | 13 +++++---- 6 files changed, 87 insertions(+), 46 deletions(-) diff --git a/src/a64/builtins-a64.cc b/src/a64/builtins-a64.cc index bb107055b7..0641c10d13 100644 --- a/src/a64/builtins-a64.cc +++ b/src/a64/builtins-a64.cc @@ -415,15 +415,14 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, Register empty = x5; __ LoadRoot(empty, Heap::kEmptyFixedArrayRootIndex); __ Str(init_map, MemOperand(new_obj, JSObject::kMapOffset)); - __ Str(empty, MemOperand(new_obj, JSObject::kPropertiesOffset)); - __ Str(empty, MemOperand(new_obj, JSObject::kElementsOffset)); + STATIC_ASSERT(JSObject::kElementsOffset == + (JSObject::kPropertiesOffset + kPointerSize)); + __ Stp(empty, empty, MemOperand(new_obj, JSObject::kPropertiesOffset)); Register first_prop = x5; __ Add(first_prop, new_obj, JSObject::kHeaderSize); // Fill all of the in-object properties with the appropriate filler. - Register obj_end = x6; - __ Add(obj_end, new_obj, Operand(obj_size, LSL, kPointerSizeLog2)); Register undef = x7; __ LoadRoot(undef, Heap::kUndefinedValueRootIndex); @@ -439,23 +438,42 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, __ Ubfx(inobject_props, inst_sizes, Map::kInObjectPropertiesByte * kBitsPerByte, kBitsPerByte); + // Calculate number of property fields in the object. + Register prop_fields = x6; + __ Sub(prop_fields, obj_size, JSObject::kHeaderSize / kPointerSize); + if (count_constructions) { + // Fill the pre-allocated fields with undef. + __ FillFields(first_prop, prealloc_fields, undef); + // Register first_non_prealloc is the offset of the first field after // pre-allocated fields. Register first_non_prealloc = x12; __ Add(first_non_prealloc, first_prop, Operand(prealloc_fields, LSL, kPointerSizeLog2)); + first_prop = NoReg; + if (FLAG_debug_code) { + Register obj_end = x5; + __ Add(obj_end, new_obj, Operand(obj_size, LSL, kPointerSizeLog2)); __ Cmp(first_non_prealloc, obj_end); __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); } - __ InitializeFieldsWithFiller(first_prop, first_non_prealloc, undef); - // To allow for truncation. - __ LoadRoot(x12, Heap::kOnePointerFillerMapRootIndex); - __ InitializeFieldsWithFiller(first_prop, obj_end, x12); + + // Fill the remaining fields with one pointer filler map. + Register one_pointer_filler = x5; + Register non_prealloc_fields = x6; + __ LoadRoot(one_pointer_filler, Heap::kOnePointerFillerMapRootIndex); + __ Sub(non_prealloc_fields, prop_fields, prealloc_fields); + __ FillFields(first_non_prealloc, non_prealloc_fields, + one_pointer_filler); + prop_fields = NoReg; } else { - __ InitializeFieldsWithFiller(first_prop, obj_end, undef); + // Fill all of the property fields with undef. + __ FillFields(first_prop, prop_fields, undef); + first_prop = NoReg; + prop_fields = NoReg; } // Add the object tag to make the JSObject real, so that we can continue @@ -467,11 +485,12 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // Check if a non-empty properties array is needed. Continue with // allocated object if not, or fall through to runtime call if it is. Register element_count = x3; - __ Ldrb(x3, FieldMemOperand(init_map, Map::kUnusedPropertyFieldsOffset)); + __ Ldrb(element_count, + FieldMemOperand(init_map, Map::kUnusedPropertyFieldsOffset)); // The field instance sizes contains both pre-allocated property fields // and in-object properties. - __ Add(x3, x3, prealloc_fields); - __ Subs(element_count, x3, inobject_props); + __ Add(element_count, element_count, prealloc_fields); + __ Subs(element_count, element_count, inobject_props); // Done if no extra properties are to be allocated. __ B(eq, &allocated); @@ -494,11 +513,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // Initialize the fields to undefined. Register elements = x10; - Register elements_end = x11; __ Add(elements, new_array, FixedArray::kHeaderSize); - __ Add(elements_end, elements, - Operand(element_count, LSL, kPointerSizeLog2)); - __ InitializeFieldsWithFiller(elements, elements_end, undef); + __ FillFields(elements, element_count, undef); // Store the initialized FixedArray into the properties field of the // JSObject. diff --git a/src/a64/lithium-a64.cc b/src/a64/lithium-a64.cc index ab76044546..289bd3b01d 100644 --- a/src/a64/lithium-a64.cc +++ b/src/a64/lithium-a64.cc @@ -878,7 +878,8 @@ LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { LOperand* size = UseRegisterOrConstant(instr->size()); LOperand* temp1 = TempRegister(); LOperand* temp2 = TempRegister(); - LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2); + LOperand* temp3 = instr->MustPrefillWithFiller() ? TempRegister() : NULL; + LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2, temp3); return AssignPointerMap(DefineAsRegister(result)); } diff --git a/src/a64/lithium-a64.h b/src/a64/lithium-a64.h index 6403542bc5..7f96df18ae 100644 --- a/src/a64/lithium-a64.h +++ b/src/a64/lithium-a64.h @@ -612,22 +612,25 @@ class LAddS V8_FINAL : public LTemplateInstruction<1, 2, 0> { }; -class LAllocate V8_FINAL : public LTemplateInstruction<1, 2, 2> { +class LAllocate V8_FINAL : public LTemplateInstruction<1, 2, 3> { public: LAllocate(LOperand* context, LOperand* size, LOperand* temp1, - LOperand* temp2) { + LOperand* temp2, + LOperand* temp3) { inputs_[0] = context; inputs_[1] = size; temps_[0] = temp1; temps_[1] = temp2; + temps_[2] = temp3; } LOperand* context() { return inputs_[0]; } LOperand* size() { return inputs_[1]; } LOperand* temp1() { return temps_[0]; } LOperand* temp2() { return temps_[1]; } + LOperand* temp3() { return temps_[2]; } DECLARE_CONCRETE_INSTRUCTION(Allocate, "allocate") DECLARE_HYDROGEN_ACCESSOR(Allocate) diff --git a/src/a64/lithium-codegen-a64.cc b/src/a64/lithium-codegen-a64.cc index 4766fa55fd..feb4862d7a 100644 --- a/src/a64/lithium-codegen-a64.cc +++ b/src/a64/lithium-codegen-a64.cc @@ -1517,23 +1517,22 @@ void LCodeGen::DoAllocate(LAllocate* instr) { __ Bind(deferred->exit()); if (instr->hydrogen()->MustPrefillWithFiller()) { + Register filler_count = temp1; + Register filler = temp2; + Register untagged_result = ToRegister(instr->temp3()); + if (instr->size()->IsConstantOperand()) { int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); - __ Mov(temp1, size - kPointerSize); + __ Mov(filler_count, size / kPointerSize); } else { - __ Sub(temp1.W(), ToRegister32(instr->size()), kPointerSize); + __ Lsr(filler_count.W(), ToRegister32(instr->size()), kPointerSizeLog2); } - __ Sub(result, result, kHeapObjectTag); - // TODO(jbramley): Optimize this loop using stp. - Label loop; - __ Bind(&loop); - __ Mov(temp2, Operand(isolate()->factory()->one_pointer_filler_map())); - __ Str(temp2, MemOperand(result, temp1)); - __ Subs(temp1, temp1, kPointerSize); - __ B(ge, &loop); - - __ Add(result, result, kHeapObjectTag); + __ Sub(untagged_result, result, kHeapObjectTag); + __ Mov(filler, Operand(isolate()->factory()->one_pointer_filler_map())); + __ FillFields(untagged_result, filler_count, filler); + } else { + ASSERT(instr->temp3() == NULL); } } diff --git a/src/a64/macro-assembler-a64.cc b/src/a64/macro-assembler-a64.cc index d4f33b794d..41930a3230 100644 --- a/src/a64/macro-assembler-a64.cc +++ b/src/a64/macro-assembler-a64.cc @@ -2452,17 +2452,40 @@ void MacroAssembler::CopyBytes(Register dst, } -void MacroAssembler::InitializeFieldsWithFiller(Register start_offset, - Register end_offset, - Register filler) { - Label loop, entry; +void MacroAssembler::FillFields(Register dst, + Register field_count, + Register filler) { + ASSERT(!dst.Is(csp)); + UseScratchRegisterScope temps(this); + Register field_ptr = temps.AcquireX(); + Register counter = temps.AcquireX(); + Label done; + + // Decrement count. If the result < zero, count was zero, and there's nothing + // to do. If count was one, flags are set to fail the gt condition at the end + // of the pairs loop. + Subs(counter, field_count, 1); + B(lt, &done); + + // There's at least one field to fill, so do this unconditionally. + Str(filler, MemOperand(dst, kPointerSize, PostIndex)); + + // If the bottom bit of counter is set, there are an even number of fields to + // fill, so pull the start pointer back by one field, allowing the pairs loop + // to overwrite the field that was stored above. + And(field_ptr, counter, 1); + Sub(field_ptr, dst, Operand(field_ptr, LSL, kPointerSizeLog2)); + + // Store filler to memory in pairs. + Label entry, loop; B(&entry); Bind(&loop); - // TODO(all): consider using stp here. - Str(filler, MemOperand(start_offset, kPointerSize, PostIndex)); + Stp(filler, filler, MemOperand(field_ptr, 2 * kPointerSize, PostIndex)); + Subs(counter, counter, 2); Bind(&entry); - Cmp(start_offset, end_offset); - B(lt, &loop); + B(gt, &loop); + + Bind(&done); } diff --git a/src/a64/macro-assembler-a64.h b/src/a64/macro-assembler-a64.h index 71bc319e89..651be99a6f 100644 --- a/src/a64/macro-assembler-a64.h +++ b/src/a64/macro-assembler-a64.h @@ -964,6 +964,12 @@ class MacroAssembler : public Assembler { // MacroAssembler::TmpList(). void CopyFields(Register dst, Register src, CPURegList temps, unsigned count); + // Starting at address in dst, initialize field_count 64-bit fields with + // 64-bit value in register filler. Register dst is corrupted. + void FillFields(Register dst, + Register field_count, + Register filler); + // Copies a number of bytes from src to dst. All passed registers are // clobbered. On exit src and dst will point to the place just after where the // last byte was read or written and length will be zero. Hint may be used to @@ -974,13 +980,6 @@ class MacroAssembler : public Assembler { Register scratch, CopyHint hint = kCopyUnknown); - // Initialize fields with filler values. Fields starting at start_offset not - // including end_offset are overwritten with the value in filler. At the end - // of the loop, start_offset takes the value of end_offset. - void InitializeFieldsWithFiller(Register start_offset, - Register end_offset, - Register filler); - // ---- String Utilities ----