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
parent 66c8130b
......@@ -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.
......
......@@ -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));
}
......
......@@ -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)
......
......@@ -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);
}
}
......
......@@ -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);
}
......
......@@ -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 ----
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment