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
This commit is contained in:
parent
66c8130b8a
commit
df529fb05f
@ -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 ----
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user