Revision: 11729
Author:   [email protected]
Date:     Wed Jun  6 04:05:28 2012
Log:      Optimize write barrier of map-only elements transitions

[email protected]

Review URL: https://chromiumcodereview.appspot.com/10544005
http://code.google.com/p/v8/source/detail?r=11729

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

=======================================
--- /branches/bleeding_edge/src/assembler.cc    Wed Apr 18 00:02:21 2012
+++ /branches/bleeding_edge/src/assembler.cc    Wed Jun  6 04:05:28 2012
@@ -1131,6 +1131,12 @@
                                     FUNCTION_ADDR(math_log_double),
                                     BUILTIN_FP_CALL));
 }
+
+
+ExternalReference ExternalReference::page_flags(Page* page) {
+  return ExternalReference(reinterpret_cast<Address>(page) +
+                           MemoryChunk::kFlagsOffset);
+}


 // Helper function to compute x^y, where y is known to be an
=======================================
--- /branches/bleeding_edge/src/assembler.h     Thu Apr 12 02:23:26 2012
+++ /branches/bleeding_edge/src/assembler.h     Wed Jun  6 04:05:28 2012
@@ -656,6 +656,8 @@
   static ExternalReference math_tan_double_function(Isolate* isolate);
   static ExternalReference math_log_double_function(Isolate* isolate);

+  static ExternalReference page_flags(Page* page);
+
   Address address() const {return reinterpret_cast<Address>(address_);}

 #ifdef ENABLE_DEBUGGER_SUPPORT
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Mon Jun 4 07:42:58 2012 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Jun 6 04:05:28 2012
@@ -3573,18 +3573,25 @@
   ElementsKind to_kind = to_map->elements_kind();

   Label not_applicable;
+  bool is_simple_map_transition =
+      IsSimpleMapChangeTransition(from_kind, to_kind);
+  Label::Distance branch_distance =
+      is_simple_map_transition ? Label::kNear : Label::kFar;
   __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
-  __ j(not_equal, &not_applicable);
-  __ mov(new_map_reg, to_map);
-  if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
+  __ j(not_equal, &not_applicable, branch_distance);
+  if (is_simple_map_transition) {
     Register object_reg = ToRegister(instr->object());
-    __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg);
+    Handle<Map> map = instr->hydrogen()->transitioned_map();
+    __ mov(FieldOperand(object_reg, HeapObject::kMapOffset),
+           Immediate(map));
     // Write barrier.
     ASSERT_NE(instr->temp_reg(), NULL);
-    __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
-                        ToRegister(instr->temp_reg()), kDontSaveFPRegs);
+    __ RecordWriteForMap(object_reg, to_map, new_map_reg,
+                         ToRegister(instr->temp_reg()),
+                         kDontSaveFPRegs);
   } else if (IsFastSmiElementsKind(from_kind) &&
              IsFastDoubleElementsKind(to_kind)) {
+    __ mov(new_map_reg, to_map);
     Register fixed_object_reg = ToRegister(instr->temp_reg());
     ASSERT(fixed_object_reg.is(edx));
     ASSERT(new_map_reg.is(ebx));
@@ -3593,6 +3600,7 @@
              RelocInfo::CODE_TARGET, instr);
   } else if (IsFastDoubleElementsKind(from_kind) &&
              IsFastObjectElementsKind(to_kind)) {
+    __ mov(new_map_reg, to_map);
     Register fixed_object_reg = ToRegister(instr->temp_reg());
     ASSERT(fixed_object_reg.is(edx));
     ASSERT(new_map_reg.is(ebx));
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Wed May 23 07:24:29 2012 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Wed Jun 6 04:05:28 2012
@@ -235,6 +235,70 @@
     mov(dst, Immediate(BitCast<int32_t>(kZapValue)));
   }
 }
+
+
+void MacroAssembler::RecordWriteForMap(
+    Register object,
+    Handle<Map> map,
+    Register scratch1,
+    Register scratch2,
+    SaveFPRegsMode save_fp) {
+  // First, check if a write barrier is even needed. The tests below
+  // catch stores of Smis.
+  Label done;
+
+  Register address = scratch1;
+  Register value = scratch2;
+  if (emit_debug_code()) {
+    Label ok;
+    lea(address, FieldOperand(object, HeapObject::kMapOffset));
+    test_b(address, (1 << kPointerSizeLog2) - 1);
+    j(zero, &ok, Label::kNear);
+    int3();
+    bind(&ok);
+  }
+
+  ASSERT(!object.is(value));
+  ASSERT(!object.is(address));
+  ASSERT(!value.is(address));
+  if (emit_debug_code()) {
+    AbortIfSmi(object);
+  }
+
+  if (!FLAG_incremental_marking) {
+    return;
+  }
+
+ // A single check of the map's pages interesting flag suffices, since it is + // only set during incremental collection, and then it's also guaranteed that + // the from object's page's interesting flag is also set. This optimization
+  // relies on the fact that maps can never be in new space.
+  ASSERT(!isolate()->heap()->InNewSpace(*map));
+  CheckPageFlagForMap(map,
+                      MemoryChunk::kPointersToHereAreInterestingMask,
+                      zero,
+                      &done,
+                      Label::kNear);
+
+ // Delay the initialization of |address| and |value| for the stub until it's
+  // known that the will be needed. Up until this point their value are not
+ // needed since they are embedded in the operands of instructions that need
+  // them.
+  lea(address, FieldOperand(object, HeapObject::kMapOffset));
+  mov(value, Immediate(map));
+ RecordWriteStub stub(object, value, address, OMIT_REMEMBERED_SET, save_fp);
+  CallStub(&stub);
+
+  bind(&done);
+
+ // Clobber clobbered input registers when running with the debug-code flag
+  // turned on to provoke errors.
+  if (emit_debug_code()) {
+    mov(value, Immediate(BitCast<int32_t>(kZapValue)));
+    mov(scratch1, Immediate(BitCast<int32_t>(kZapValue)));
+    mov(scratch2, Immediate(BitCast<int32_t>(kZapValue)));
+  }
+}


 void MacroAssembler::RecordWrite(Register object,
@@ -2616,6 +2680,28 @@
   }
   j(cc, condition_met, condition_met_distance);
 }
+
+
+void MacroAssembler::CheckPageFlagForMap(
+    Handle<Map> map,
+    int mask,
+    Condition cc,
+    Label* condition_met,
+    Label::Distance condition_met_distance) {
+  ASSERT(cc == zero || cc == not_zero);
+  Page* page = Page::FromAddress(map->address());
+  ExternalReference reference(ExternalReference::page_flags(page));
+  // The inlined static address check of the page's flags relies
+  // on maps never being compacted.
+  ASSERT(!isolate()->heap()->mark_compact_collector()->
+         IsOnEvacuationCandidate(*map));
+  if (mask < (1 << kBitsPerByte)) {
+    test_b(Operand::StaticVariable(reference), static_cast<uint8_t>(mask));
+  } else {
+    test(Operand::StaticVariable(reference), Immediate(mask));
+  }
+  j(cc, condition_met, condition_met_distance);
+}


 void MacroAssembler::JumpIfBlack(Register object,
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Wed May 23 07:24:29 2012 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Wed Jun 6 04:05:28 2012
@@ -90,6 +90,13 @@
                      Label* condition_met,
                      Label::Distance condition_met_distance = Label::kFar);

+  void CheckPageFlagForMap(
+      Handle<Map> map,
+      int mask,
+      Condition cc,
+      Label* condition_met,
+      Label::Distance condition_met_distance = Label::kFar);
+
// Check if object is in new space. Jumps if the object is not in new space. // The register scratch can be object itself, but scratch will be clobbered.
   void JumpIfNotInNewSpace(Register object,
@@ -194,6 +201,16 @@
       RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
       SmiCheck smi_check = INLINE_SMI_CHECK);

+  // For page containing |object| mark the region covering the object's map
+ // dirty. |object| is the object being stored into, |map| is the Map object
+  // that was stored.
+  void RecordWriteForMap(
+      Register object,
+      Handle<Map> map,
+      Register scratch1,
+      Register scratch2,
+      SaveFPRegsMode save_fp);
+
 #ifdef ENABLE_DEBUGGER_SUPPORT
// ---------------------------------------------------------------------------
   // Debugger Support

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to