Revision: 19895
Author:   [email protected]
Date:     Thu Mar 13 13:18:48 2014 UTC
Log:      A64: Implement and use FillFields

BUG=
[email protected]

Review URL: https://codereview.chromium.org/190763012
http://code.google.com/p/v8/source/detail?r=19895

Modified:
 /branches/bleeding_edge/src/a64/builtins-a64.cc
 /branches/bleeding_edge/src/a64/lithium-a64.cc
 /branches/bleeding_edge/src/a64/lithium-a64.h
 /branches/bleeding_edge/src/a64/lithium-codegen-a64.cc
 /branches/bleeding_edge/src/a64/macro-assembler-a64.cc
 /branches/bleeding_edge/src/a64/macro-assembler-a64.h

=======================================
--- /branches/bleeding_edge/src/a64/builtins-a64.cc Wed Mar 12 15:18:40 2014 UTC +++ /branches/bleeding_edge/src/a64/builtins-a64.cc Thu Mar 13 13:18:48 2014 UTC
@@ -415,15 +415,14 @@
       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 @@
       __ 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 @@
       // 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 @@

       // 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.
=======================================
--- /branches/bleeding_edge/src/a64/lithium-a64.cc Thu Mar 13 07:58:58 2014 UTC +++ /branches/bleeding_edge/src/a64/lithium-a64.cc Thu Mar 13 13:18:48 2014 UTC
@@ -878,7 +878,8 @@
   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));
 }

=======================================
--- /branches/bleeding_edge/src/a64/lithium-a64.h Thu Mar 13 06:11:52 2014 UTC +++ /branches/bleeding_edge/src/a64/lithium-a64.h Thu Mar 13 13:18:48 2014 UTC
@@ -612,22 +612,25 @@
 };


-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)
=======================================
--- /branches/bleeding_edge/src/a64/lithium-codegen-a64.cc Thu Mar 13 08:17:44 2014 UTC +++ /branches/bleeding_edge/src/a64/lithium-codegen-a64.cc Thu Mar 13 13:18:48 2014 UTC
@@ -1517,23 +1517,22 @@
   __ 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);
   }
 }

=======================================
--- /branches/bleeding_edge/src/a64/macro-assembler-a64.cc Wed Mar 12 15:18:40 2014 UTC +++ /branches/bleeding_edge/src/a64/macro-assembler-a64.cc Thu Mar 13 13:18:48 2014 UTC
@@ -2452,17 +2452,40 @@
 }


-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);
 }


=======================================
--- /branches/bleeding_edge/src/a64/macro-assembler-a64.h Thu Mar 13 09:45:02 2014 UTC +++ /branches/bleeding_edge/src/a64/macro-assembler-a64.h Thu Mar 13 13:18:48 2014 UTC
@@ -964,6 +964,12 @@
   // 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 @@
                  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 ----


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to