Revision: 7030
Author: [email protected]
Date: Wed Mar  2 07:11:09 2011
Log: Move IncrementalRecordWrite to a stub.

Patch stub to enable/disable it.

Don't activate incremental marker for small heaps.

BUG=
TEST=

Review URL: http://codereview.chromium.org/6597104
http://code.google.com/p/v8/source/detail?r=7030

Modified:
 /branches/experimental/gc/src/assembler.cc
 /branches/experimental/gc/src/code-stubs.h
 /branches/experimental/gc/src/heap.cc
 /branches/experimental/gc/src/heap.h
 /branches/experimental/gc/src/ia32/code-stubs-ia32.cc
 /branches/experimental/gc/src/ia32/code-stubs-ia32.h
 /branches/experimental/gc/src/ia32/lithium-codegen-ia32.cc
 /branches/experimental/gc/src/ia32/macro-assembler-ia32.cc
 /branches/experimental/gc/src/ia32/macro-assembler-ia32.h
 /branches/experimental/gc/src/ia32/stub-cache-ia32.cc
 /branches/experimental/gc/src/incremental-marking.cc
 /branches/experimental/gc/src/incremental-marking.h
 /branches/experimental/gc/src/mark-compact.cc

=======================================
--- /branches/experimental/gc/src/assembler.cc  Wed Feb 23 06:43:51 2011
+++ /branches/experimental/gc/src/assembler.cc  Wed Mar  2 07:11:09 2011
@@ -592,8 +592,10 @@
   : address_(table_ref.address()) {}


-ExternalReference ExternalReference::incremental_marking_record_write_function() { - return ExternalReference(Redirect(FUNCTION_ADDR(IncrementalMarking::RecordWrite)));
+ExternalReference ExternalReference::
+    incremental_marking_record_write_function() {
+  return ExternalReference(Redirect(
+      FUNCTION_ADDR(IncrementalMarking::RecordWrite)));
 }


=======================================
--- /branches/experimental/gc/src/code-stubs.h  Wed Feb 16 10:02:22 2011
+++ /branches/experimental/gc/src/code-stubs.h  Wed Mar  2 07:11:09 2011
@@ -47,6 +47,7 @@
   V(Compare)                             \
   V(CompareIC)                           \
   V(MathPow)                             \
+  V(IncrementalMarkingRecordWrite)       \
   V(StoreBufferOverflow)                 \
   V(RegExpExec)                          \
   V(TranscendentalCache)                 \
=======================================
--- /branches/experimental/gc/src/heap.cc       Wed Feb 23 06:43:51 2011
+++ /branches/experimental/gc/src/heap.cc       Wed Mar  2 07:11:09 2011
@@ -501,7 +501,7 @@
   }

   ASSERT(IncrementalMarking::state() == IncrementalMarking::STOPPED);
-  if (NextGCIsLikelyToBeFull() && FLAG_incremental_marking) {
+  if (IncrementalMarking::WorthActivating() && NextGCIsLikelyToBeFull()) {
     IncrementalMarking::Start();
   }

=======================================
--- /branches/experimental/gc/src/heap.h        Wed Feb 23 06:43:51 2011
+++ /branches/experimental/gc/src/heap.h        Wed Mar  2 07:11:09 2011
@@ -1155,6 +1155,9 @@
   static void ClearNormalizedMapCaches();

   static GCTracer* tracer() { return tracer_; }
+
+  // Returns the size of objects residing in non new spaces.
+  static intptr_t PromotedSpaceSize();

  private:
   static int reserved_semispace_size_;
@@ -1189,9 +1192,6 @@
   static LargeObjectSpace* lo_space_;
   static HeapState gc_state_;

-  // Returns the size of object residing in non new spaces.
-  static intptr_t PromotedSpaceSize();
-
   // Returns the amount of external memory registered since last global gc.
   static int PromotedExternalMemorySize();

=======================================
--- /branches/experimental/gc/src/ia32/code-stubs-ia32.cc Wed Feb 16 10:02:22 2011 +++ /branches/experimental/gc/src/ia32/code-stubs-ia32.cc Wed Mar 2 07:11:09 2011
@@ -6651,6 +6651,23 @@
__ mov_b(Operand(external_pointer, untagged_key, times_1, 0), untagged_value);
   __ ret(0);  // Return value in eax.
 }
+
+
+void IncrementalMarkingRecordWriteStub::Generate(MacroAssembler* masm) {
+  if (IncrementalMarking::IsStopped()) {
+    __ ret(0);
+  } else {
+    __ nop();
+  }
+
+  __ IncrementalMarkingRecordWriteHelper(object_,
+                                         value_,
+                                         scratch_,
+                                         object_mode_,
+                                         value_mode_,
+                                         scratch_mode_);
+  __ ret(0);
+}


 #undef __
=======================================
--- /branches/experimental/gc/src/ia32/code-stubs-ia32.h Wed Feb 16 10:02:22 2011 +++ /branches/experimental/gc/src/ia32/code-stubs-ia32.h Wed Mar 2 07:11:09 2011
@@ -505,6 +505,64 @@
 };


+class IncrementalMarkingRecordWriteStub: public CodeStub {
+ public:
+  IncrementalMarkingRecordWriteStub(Register object,
+                                    Register value,
+                                    Register scratch,
+                                    ObjectMode object_mode,
+                                    ValueMode value_mode,
+                                    ScratchMode scratch_mode)
+      : object_(object),
+        value_(value),
+        scratch_(scratch),
+        object_mode_(object_mode),
+        value_mode_(value_mode),
+        scratch_mode_(scratch_mode) {
+  }
+
+
+  static byte GetInstruction(bool enable) {
+    static const byte kNopInstruction = 0x90;
+    static const byte kRet0Instruction = 0xc3;
+    return enable ? kNopInstruction : kRet0Instruction;
+  }
+
+  static void Patch(Code* stub, bool enable) {
+    ASSERT(*stub->instruction_start() == GetInstruction(!enable));
+    *stub->instruction_start() = GetInstruction(enable);
+  }
+
+ private:
+  void Generate(MacroAssembler* masm);
+
+  Major MajorKey() { return IncrementalMarkingRecordWrite; }
+
+  int MinorKey() {
+    return ObjectBits::encode(object_.code()) |
+        ValueBits::encode(value_.code()) |
+        ScratchBits::encode(scratch_.code()) |
+        ObjectModeBits::encode(object_mode_) |
+        ValueModeBits::encode(value_mode_) |
+        ScratchModeBits::encode(scratch_mode_);
+  }
+
+  class ObjectBits: public BitField<int, 0, 3> {};
+  class ValueBits: public BitField<int, 3, 3> {};
+  class ScratchBits: public BitField<int, 6, 3> {};
+  class ObjectModeBits: public BitField<ObjectMode, 9, 1> {};
+  class ValueModeBits: public BitField<ValueMode, 10, 1> {};
+  class ScratchModeBits: public BitField<ScratchMode, 11, 1> {};
+
+  Register object_;
+  Register value_;
+  Register scratch_;
+  ObjectMode object_mode_;
+  ValueMode value_mode_;
+  ScratchMode scratch_mode_;
+};
+
+
// Generate code to load an element from a pixel array. The receiver is assumed
 // to not be a smi and to have elements, the caller must guarantee this
 // precondition. If key is not a smi, then the generated code branches to
=======================================
--- /branches/experimental/gc/src/ia32/lithium-codegen-ia32.cc Wed Feb 23 06:43:51 2011 +++ /branches/experimental/gc/src/ia32/lithium-codegen-ia32.cc Wed Mar 2 07:11:09 2011
@@ -1955,12 +1955,13 @@
   __ mov(object, Immediate(cell_handle));
   __ mov(FieldOperand(object, JSGlobalPropertyCell::kValueOffset), value);

-  NearLabel done;
-  __ test(value, Immediate(kSmiTagMask));
-  __ j(zero, &done);
-  __ IncrementalMarkingRecordWrite(object, value, scratch);
-  __ bind(&done);
-
+  __ IncrementalMarkingRecordWrite(object,
+                                   value,
+                                   scratch,
+                                   INLINE_SMI_CHECK,
+                                   DESTROY_OBJECT,
+                                   DESTROY_VALUE,
+                                   DESTROY_SCRATCH);
 }


=======================================
--- /branches/experimental/gc/src/ia32/macro-assembler-ia32.cc Wed Feb 23 06:43:51 2011 +++ /branches/experimental/gc/src/ia32/macro-assembler-ia32.cc Wed Mar 2 07:11:09 2011
@@ -49,22 +49,70 @@
 }


-void MacroAssembler::IncrementalMarkingRecordWrite(Register object,
-                                                   Register value,
-                                                   Register scratch) {
+void MacroAssembler::IncrementalMarkingRecordWriteHelper(
+    Register object,
+    Register value,
+    Register scratch,
+    ObjectMode object_mode,
+    ValueMode value_mode,
+    ScratchMode scratch_mode) {
   ASSERT(!object.is(scratch));
   ASSERT(!value.is(scratch));
-  push(eax);
-  push(ecx);
-  push(edx);
+  ASSERT(!value.is(object));
+
+  bool preserve[Register::kNumRegisters];
+
+  for (int i = 0; i < Register::kNumRegisters; i++) preserve[i] = false;
+
+  preserve[eax.code()] = true;
+  preserve[ecx.code()] = true;
+  preserve[edx.code()] = true;
+  preserve[object.code()] = (object_mode == PRESERVE_OBJECT);
+  preserve[value.code()] = (value_mode == PRESERVE_VALUE);
+  preserve[scratch.code()] = (scratch_mode == PRESERVE_SCRATCH);
+
+  for (int i = 0; i < Register::kNumRegisters; i++) {
+    if (preserve[i]) push(Register::from_code(i));
+  }
+
+  // TODO(gc) we are assuming that xmm registers are not modified by
+  // the C function we are calling.
   PrepareCallCFunction(2, scratch);
   mov(Operand(esp, 0 * kPointerSize), object);
   mov(Operand(esp, 1 * kPointerSize), value);
   CallCFunction(
       ExternalReference::incremental_marking_record_write_function(), 2);
-  pop(edx);
-  pop(ecx);
-  pop(eax);
+
+  for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
+    if (preserve[i]) pop(Register::from_code(i));
+  }
+}
+
+
+void MacroAssembler::IncrementalMarkingRecordWrite(Register object,
+                                                   Register value,
+                                                   Register scratch,
+                                                   SmiCheck smi_check,
+                                                   ObjectMode object_mode,
+                                                   ValueMode value_mode,
+ ScratchMode scratch_mode) {
+  if (FLAG_incremental_marking) {
+    Label done;
+
+    if (smi_check == INLINE_SMI_CHECK) {
+      ASSERT_EQ(0, kSmiTag);
+      test(value, Immediate(kSmiTagMask));
+      j(zero, &done);
+    }
+
+    IncrementalMarkingRecordWriteStub stub(
+        object, value, scratch, object_mode, value_mode, scratch_mode);
+    CallStub(&stub);
+
+    if (smi_check == INLINE_SMI_CHECK) {
+      bind(&done);
+    }
+  }
 }


@@ -115,7 +163,14 @@
   test(value, Immediate(kSmiTagMask));
   j(zero, &done);

-  IncrementalMarkingRecordWrite(object, value, scratch);
+  IncrementalMarkingRecordWrite(object,
+                                value,
+                                scratch,
+                                OMIT_SMI_CHECK,
+                                PRESERVE_OBJECT,
+                                DESTROY_VALUE,
+                                (offset == 0) ? PRESERVE_SCRATCH
+                                              : DESTROY_SCRATCH);

   InNewSpace(object, value, equal, &done);

=======================================
--- /branches/experimental/gc/src/ia32/macro-assembler-ia32.h Wed Feb 23 06:43:51 2011 +++ /branches/experimental/gc/src/ia32/macro-assembler-ia32.h Wed Mar 2 07:11:09 2011
@@ -53,6 +53,11 @@
 class JumpTarget;
 class PostCallGenerator;

+enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
+enum ObjectMode { PRESERVE_OBJECT, DESTROY_OBJECT };
+enum ValueMode { PRESERVE_VALUE, DESTROY_VALUE };
+enum ScratchMode { PRESERVE_SCRATCH, DESTROY_SCRATCH };
+
 // MacroAssembler implements a collection of frequently used macros.
 class MacroAssembler: public Assembler {
  public:
@@ -61,9 +66,22 @@
// ---------------------------------------------------------------------------
   // GC Support

+  void IncrementalMarkingRecordWriteHelper(Register object,
+                                           Register value,
+                                           Register scratch,
+                                           ObjectMode object_mode,
+                                           ValueMode value_mode,
+                                           ScratchMode scratch_mode);
+
+
   void IncrementalMarkingRecordWrite(Register object,
                                      Register value,
-                                     Register scratch);
+                                     Register scratch,
+                                     SmiCheck smi_check,
+                                     ObjectMode object_mode,
+                                     ValueMode value_mode,
+                                     ScratchMode scratch_mode);
+

   // For page containing |object| mark region covering |addr| dirty.
   // RecordWriteHelper only works if the object is not in new
=======================================
--- /branches/experimental/gc/src/ia32/stub-cache-ia32.cc Wed Feb 23 06:43:51 2011 +++ /branches/experimental/gc/src/ia32/stub-cache-ia32.cc Wed Mar 2 07:11:09 2011
@@ -1498,7 +1498,13 @@

       __ bind(&with_write_barrier);

-      __ IncrementalMarkingRecordWrite(ebx, ecx, edx);
+      __ IncrementalMarkingRecordWrite(ebx,
+                                       ecx,
+                                       edx,
+                                       OMIT_SMI_CHECK,
+                                       PRESERVE_OBJECT,
+                                       DESTROY_VALUE,
+                                       PRESERVE_SCRATCH);

       __ InNewSpace(ebx, ecx, equal, &exit);

@@ -2603,9 +2609,15 @@
   __ j(zero, &done);

   __ mov(ecx, eax);
-  __ IncrementalMarkingRecordWrite(ebx, ecx, edx);
-
-   // Return the value (register eax).
+  __ IncrementalMarkingRecordWrite(ebx,
+                                   ecx,
+                                   edx,
+                                   INLINE_SMI_CHECK,
+                                   DESTROY_OBJECT,
+                                   DESTROY_VALUE,
+                                   DESTROY_SCRATCH);
+
+  // Return the value (register eax).
   __ bind(&done);

   // Return the value (register eax).
=======================================
--- /branches/experimental/gc/src/incremental-marking.cc Wed Feb 23 06:43:51 2011 +++ /branches/experimental/gc/src/incremental-marking.cc Wed Mar 2 07:11:09 2011
@@ -29,6 +29,7 @@

 #include "incremental-marking.h"

+#include "code-stubs.h"

 namespace v8 {
 namespace internal {
@@ -122,6 +123,41 @@
   }
 #endif

+bool IncrementalMarking::WorthActivating() {
+#ifndef DEBUG
+  static const intptr_t kActivationThreshold = 20*MB;
+#else
+  // TODO(gc) consider setting this to some low level so that some
+  // debug tests run with incremental marking and some without.
+  static const intptr_t kActivationThreshold = 0;
+#endif
+
+  return FLAG_incremental_marking &&
+      Heap::PromotedSpaceSize() > kActivationThreshold;
+}
+
+
+static void PatchIncrementalMarkingRecordWriteStubs(bool enable) {
+  NumberDictionary* stubs = Heap::code_stubs();
+
+  int capacity = stubs->Capacity();
+  for (int i = 0; i < capacity; i++) {
+    Object* k = stubs->KeyAt(i);
+    if (stubs->IsKey(k)) {
+      uint32_t key = NumberToUint32(k);
+
+      if (CodeStub::MajorKeyFromKey(key) ==
+          CodeStub::IncrementalMarkingRecordWrite) {
+        Object* e = stubs->ValueAt(i);
+        if (e->IsCode()) {
+          IncrementalMarkingRecordWriteStub::Patch(Code::cast(e), enable);
+        }
+      }
+    }
+  }
+}
+
+
 void IncrementalMarking::Start() {
   if (FLAG_trace_incremental_marking) {
     PrintF("[IncrementalMarking] Start\n");
@@ -130,6 +166,8 @@
   ASSERT(state_ == STOPPED);
   state_ = MARKING;

+  PatchIncrementalMarkingRecordWriteStubs(true);
+
   // Initialize marking stack.
   marking_stack_.Initialize(Heap::new_space()->FromSpaceLow(),
                             Heap::new_space()->FromSpaceHigh());
@@ -181,6 +219,7 @@
 void IncrementalMarking::Finalize() {
   Hurry();
   state_ = STOPPED;
+  PatchIncrementalMarkingRecordWriteStubs(false);
   ASSERT(marking_stack_.is_empty());
 }

=======================================
--- /branches/experimental/gc/src/incremental-marking.h Wed Feb 23 06:43:51 2011 +++ /branches/experimental/gc/src/incremental-marking.h Wed Mar 2 07:11:09 2011
@@ -51,6 +51,8 @@
   }

   static inline bool IsStopped() { return state() == STOPPED; }
+
+  static bool WorthActivating();

   static void Start();

=======================================
--- /branches/experimental/gc/src/mark-compact.cc       Wed Feb 23 06:43:51 2011
+++ /branches/experimental/gc/src/mark-compact.cc       Wed Mar  2 07:11:09 2011
@@ -168,11 +168,12 @@
     }
     MarkLiveObjects();
   }
+
+  if (FLAG_collect_maps) ClearNonLiveTransitions();

 #ifdef DEBUG
   VerifyMarking();
 #endif
-  if (FLAG_collect_maps) ClearNonLiveTransitions();

   SweepSpaces();

@@ -646,7 +647,8 @@
     Object* old_cell = cell;
     VisitPointer(&cell);
     if (cell != old_cell) {
- rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell), NULL);
+      rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell),
+                             NULL);
     }
   }

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

Reply via email to