Revision: 7514
Author:   [email protected]
Date:     Wed Apr  6 05:31:10 2011
Log: Combine the incremental-marking write barrier and the remembered-set
write barrier into one stub.
Review URL: http://codereview.chromium.org/6794052
http://code.google.com/p/v8/source/detail?r=7514

Modified:
 /branches/experimental/gc/src/code-stubs.h
 /branches/experimental/gc/src/ia32/assembler-ia32.h
 /branches/experimental/gc/src/ia32/code-stubs-ia32.cc
 /branches/experimental/gc/src/ia32/code-stubs-ia32.h
 /branches/experimental/gc/src/ia32/codegen-ia32.cc
 /branches/experimental/gc/src/ia32/full-codegen-ia32.cc
 /branches/experimental/gc/src/ia32/ic-ia32.cc
 /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/code-stubs.h  Tue Mar 15 12:46:33 2011
+++ /branches/experimental/gc/src/code-stubs.h  Wed Apr  6 05:31:10 2011
@@ -46,7 +46,7 @@
   V(Compare)                             \
   V(CompareIC)                           \
   V(MathPow)                             \
-  V(IncrementalMarkingRecordWrite)       \
+  V(RecordWrite)                         \
   V(StoreBufferOverflow)                 \
   V(RegExpExec)                          \
   V(TranscendentalCache)                 \
=======================================
--- /branches/experimental/gc/src/ia32/assembler-ia32.h Tue Mar 15 12:46:33 2011 +++ /branches/experimental/gc/src/ia32/assembler-ia32.h Wed Apr 6 05:31:10 2011
@@ -965,6 +965,18 @@
   void dd(uint32_t data);

   int pc_offset() const { return pc_ - buffer_; }
+
+  // Used for patching the code stream while it is being emitted.
+  inline byte get_opcode(int offset) {
+    ASSERT(offset < 0);
+    ASSERT(pc_ + offset >= buffer_);
+    return pc_[offset];
+  }
+  inline void set_opcode(int offset, byte opcode) {
+    ASSERT(offset < 0);
+    ASSERT(pc_ + offset >= buffer_);
+    pc_[offset] = opcode;
+  }

   // Check if there is less than kGap bytes available in the buffer.
   // If this is the case, we need to grow the buffer before emitting
@@ -997,6 +1009,7 @@
   void emit_sse_operand(Register dst, XMMRegister src);

   byte* addr_at(int pos)  { return buffer_ + pos; }
+
  private:
   byte byte_at(int pos)  { return buffer_[pos]; }
   void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
=======================================
--- /branches/experimental/gc/src/ia32/code-stubs-ia32.cc Tue Mar 15 12:46:33 2011 +++ /branches/experimental/gc/src/ia32/code-stubs-ia32.cc Wed Apr 6 05:31:10 2011
@@ -6464,19 +6464,38 @@
 }


-void IncrementalMarkingRecordWriteStub::Generate(MacroAssembler* masm) {
-  if (IncrementalMarking::IsStopped()) {
-    __ ret(0);
-  } else {
-    __ nop();
+void RecordWriteStub::Generate(MacroAssembler* masm) {
+  NearLabel skip_incremental_part;
+  __ jmp(&skip_incremental_part);
+  if (!IncrementalMarking::IsStopped()) {
+    ASSERT(masm->get_opcode(-2) == kSkipIncrementalPartInstruction);
+    masm->set_opcode(-2, kTwoByteNopInstruction);
   }

-  __ IncrementalMarkingRecordWriteHelper(object_,
-                                         value_,
-                                         scratch_,
-                                         object_mode_,
-                                         value_mode_,
-                                         scratch_mode_);
+ // If we are also emitting the remembered set code in this stub then we have + // the object we are writing into in the 'object' register and the slot in + // the 'address' register. We insert a primitive test here to ensure that + // this is the case. Otherwise the 'address' register is merely a scratch
+  // register.
+  if (FLAG_debug_code && emit_remembered_set_ == EMIT_REMEMBERED_SET) {
+    NearLabel ok;
+    __ cmp(address_, Operand(object_));
+    __ j(above_equal, &ok);
+    __ int3();
+    __ bind(&ok);
+  }
+
+  __ IncrementalMarkingRecordWriteHelper(object_, value_, address_);
+
+  __ bind(&skip_incremental_part);
+
+  if (emit_remembered_set_ == EMIT_REMEMBERED_SET) {
+    Register scratch = value_;
+    NearLabel done;
+    __ InNewSpace(object_, scratch, equal, &done);
+    __ RememberedSetHelper(object_, address_, scratch, save_fp_regs_mode_);
+    __ bind(&done);
+  }
   __ ret(0);
 }

=======================================
--- /branches/experimental/gc/src/ia32/code-stubs-ia32.h Tue Mar 15 12:46:33 2011 +++ /branches/experimental/gc/src/ia32/code-stubs-ia32.h Wed Apr 6 05:31:10 2011
@@ -505,27 +505,31 @@
 };


-class IncrementalMarkingRecordWriteStub: public CodeStub {
+class RecordWriteStub: public CodeStub {
  public:
-  IncrementalMarkingRecordWriteStub(Register object,
-                                    Register value,
-                                    Register scratch,
-                                    ObjectMode object_mode,
-                                    ValueMode value_mode,
-                                    ScratchMode scratch_mode)
+  RecordWriteStub(Register object,
+                  Register value,
+                  Register address,
+                  EmitRememberedSet emit_remembered_set,
+                  SaveFPRegsMode fp_mode)
       : object_(object),
         value_(value),
-        scratch_(scratch),
-        object_mode_(object_mode),
-        value_mode_(value_mode),
-        scratch_mode_(scratch_mode) {
+        address_(address),
+        emit_remembered_set_(emit_remembered_set),
+        save_fp_regs_mode_(fp_mode) {
   }

+ static const byte kTwoByteNopInstruction = 0x3c; // Cmpb al, #imm8.
+  static const byte kSkipIncrementalPartInstruction = 0xeb;  // Jmp #imm8.

   static byte GetInstruction(bool enable) {
-    static const byte kNopInstruction = 0x90;
-    static const byte kRet0Instruction = 0xc3;
-    return enable ? kNopInstruction : kRet0Instruction;
+    // Can't use ternary operator here, because gcc makes an undefined
+    // reference to a static const int.
+    if (enable) {
+      return kTwoByteNopInstruction;
+    } else {
+      return kSkipIncrementalPartInstruction;
+    }
   }

   static void Patch(Code* stub, bool enable) {
@@ -536,30 +540,27 @@
  private:
   void Generate(MacroAssembler* masm);

-  Major MajorKey() { return IncrementalMarkingRecordWrite; }
+  Major MajorKey() { return RecordWrite; }

   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_);
+        AddressBits::encode(address_.code()) |
+        EmitRememberedSetBits::encode(emit_remembered_set_) |
+        SaveFPRegsModeBits::encode(save_fp_regs_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> {};
+  class AddressBits: public BitField<int, 6, 3> {};
+  class EmitRememberedSetBits: public BitField<EmitRememberedSet, 9, 1> {};
+  class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 10, 1> {};

   Register object_;
   Register value_;
-  Register scratch_;
-  ObjectMode object_mode_;
-  ValueMode value_mode_;
-  ScratchMode scratch_mode_;
+  Register address_;
+  EmitRememberedSet emit_remembered_set_;
+  SaveFPRegsMode save_fp_regs_mode_;
 };


=======================================
--- /branches/experimental/gc/src/ia32/codegen-ia32.cc Tue Mar 15 12:46:33 2011 +++ /branches/experimental/gc/src/ia32/codegen-ia32.cc Wed Apr 6 05:31:10 2011
@@ -7831,9 +7831,18 @@
   // Possible optimization: do a check that both values are Smis
   // (or them and test against Smi mask.)

+ // Since we are swapping two objects, the incremental marker is not disturbed,
+  // so we don't call the stub that handles this.  TODO(gc): Optimize by
+  // checking the scan_on_scavenge flag, probably by calling the stub.
   __ mov(tmp2.reg(), tmp1.reg());
- __ RecordWriteHelper(tmp2.reg(), index1.reg(), object.reg(), kDontSaveFPRegs); - __ RecordWriteHelper(tmp1.reg(), index2.reg(), object.reg(), kDontSaveFPRegs);
+  __ RememberedSetHelper(tmp2.reg(),
+                         index1.reg(),
+                         object.reg(),
+                         kDontSaveFPRegs);
+  __ RememberedSetHelper(tmp1.reg(),
+                         index2.reg(),
+                         object.reg(),
+                         kDontSaveFPRegs);
   __ bind(&done);

   deferred->BindExit();
@@ -9786,10 +9795,12 @@
     __ InNewSpace(receiver.reg(), value.reg(), equal, &skip_write_barrier);
int delta_to_record_write = masm_->SizeOfCodeGeneratedSince(&patch_site);
     __ lea(scratch.reg(), Operand(receiver.reg(), offset));
-    __ RecordWriteHelper(receiver.reg(),
-                         scratch.reg(),
-                         value.reg(),
-                         kDontSaveFPRegs);
+ // This code does not work with the incremental marker! Luckily this file
+    // is going away soon.
+    __ RememberedSetHelper(receiver.reg(),
+                           scratch.reg(),
+                           value.reg(),
+                           kDontSaveFPRegs);
     if (FLAG_debug_code) {
       __ mov(receiver.reg(), Immediate(BitCast<int32_t>(kZapValue)));
       __ mov(value.reg(), Immediate(BitCast<int32_t>(kZapValue)));
=======================================
--- /branches/experimental/gc/src/ia32/full-codegen-ia32.cc Tue Mar 15 12:46:33 2011 +++ /branches/experimental/gc/src/ia32/full-codegen-ia32.cc Wed Apr 6 05:31:10 2011
@@ -3093,8 +3093,11 @@
   __ InNewSpace(elements, temp, equal, &new_space);

   __ mov(object, elements);
-  __ RecordWriteHelper(object, index_1, temp, kDontSaveFPRegs);
-  __ RecordWriteHelper(elements, index_2, temp, kDontSaveFPRegs);
+ // Since we are swapping two objects, the incremental marker is not disturbed,
+  // so we don't call the stub that handles this.  TODO(gc): Optimize by
+  // checking the scan_on_scavenge flag, probably by calling the stub.
+  __ RememberedSetHelper(object, index_1, temp, kDontSaveFPRegs);
+  __ RememberedSetHelper(elements, index_2, temp, kDontSaveFPRegs);

   __ bind(&new_space);

=======================================
--- /branches/experimental/gc/src/ia32/ic-ia32.cc       Tue Mar 15 12:46:33 2011
+++ /branches/experimental/gc/src/ia32/ic-ia32.cc       Wed Apr  6 05:31:10 2011
@@ -268,7 +268,7 @@

   // Update write barrier. Make sure not to clobber the value.
   __ mov(r1, value);
-  __ RecordWrite(elements, r0, r1, kDontSaveFPRegs);
+  __ RecordWrite(elements, r0, r1, EMIT_REMEMBERED_SET, kDontSaveFPRegs);
 }


=======================================
--- /branches/experimental/gc/src/ia32/lithium-codegen-ia32.cc Tue Mar 15 12:46:33 2011 +++ /branches/experimental/gc/src/ia32/lithium-codegen-ia32.cc Wed Apr 6 05:31:10 2011
@@ -2033,7 +2033,7 @@

 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) {
   Register object = ToRegister(instr->temp1());
-  Register scratch = ToRegister(instr->temp2());
+  Register address = ToRegister(instr->temp2());
   Register value = ToRegister(instr->InputAt(0));
   Handle<JSGlobalPropertyCell> cell_handle(instr->hydrogen()->cell());

@@ -2048,15 +2048,12 @@

   // Store the value.
   __ mov(object, Immediate(cell_handle));
-  __ mov(FieldOperand(object, JSGlobalPropertyCell::kValueOffset), value);
-
-  __ IncrementalMarkingRecordWrite(object,
-                                   value,
-                                   scratch,
-                                   INLINE_SMI_CHECK,
-                                   DESTROY_OBJECT,
-                                   DESTROY_VALUE,
-                                   DESTROY_SCRATCH);
+ __ lea(address, FieldOperand(object, JSGlobalPropertyCell::kValueOffset));
+  __ mov(Operand(address, 0), value);
+
+
+  // Cells are always in the remembered set.
+  __ RecordWrite(object, address, value, OMIT_REMEMBERED_SET, kSaveFPRegs);
 }


@@ -2878,7 +2875,7 @@
                         key,
                         times_pointer_size,
                         FixedArray::kHeaderSize));
-    __ RecordWrite(elements, key, value, kSaveFPRegs);
+    __ RecordWrite(elements, key, value, EMIT_REMEMBERED_SET, kSaveFPRegs);
   }
 }

=======================================
--- /branches/experimental/gc/src/ia32/macro-assembler-ia32.cc Thu Mar 17 03:33:29 2011 +++ /branches/experimental/gc/src/ia32/macro-assembler-ia32.cc Wed Apr 6 05:31:10 2011
@@ -52,12 +52,9 @@
 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));
+    Register address) {
+  ASSERT(!object.is(address));
+  ASSERT(!value.is(address));
   ASSERT(!value.is(object));

   bool preserve[Register::kNumRegisters];
@@ -67,9 +64,9 @@
   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);
+  preserve[object.code()] = true;
+  preserve[value.code()] = true;
+  preserve[address.code()] = true;

   for (int i = 0; i < Register::kNumRegisters; i++) {
     if (preserve[i]) push(Register::from_code(i));
@@ -77,7 +74,7 @@

   // TODO(gc) we are assuming that xmm registers are not modified by
   // the C function we are calling.
-  PrepareCallCFunction(2, scratch);
+  PrepareCallCFunction(2, address);
   mov(Operand(esp, 0 * kPointerSize), object);
   mov(Operand(esp, 1 * kPointerSize), value);
   CallCFunction(
@@ -89,42 +86,15 @@
 }


-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);
-    }
-  }
-}
-
-
-void MacroAssembler::RecordWriteHelper(Register object,
-                                       Register addr,
-                                       Register scratch,
-                                       SaveFPRegsMode save_fp) {
+void MacroAssembler::RememberedSetHelper(Register object,
+                                         Register addr,
+                                         Register scratch,
+                                         SaveFPRegsMode save_fp) {
   if (emit_debug_code()) {
     // Check that the object is not in new space.
     Label not_in_new_space;
     InNewSpace(object, scratch, not_equal, &not_in_new_space);
-    Abort("new-space object passed to RecordWriteHelper");
+    Abort("new-space object passed to RememberedSetHelper");
     bind(&not_in_new_space);
   }

@@ -152,36 +122,26 @@
 void MacroAssembler::RecordWrite(Register object,
                                  int offset,
                                  Register value,
-                                 Register scratch,
+                                 Register dst,
                                  SaveFPRegsMode save_fp) {
   // First, check if a write barrier is even needed. The tests below
   // catch stores of Smis and stores into young gen.
-  Label done;
+  NearLabel done;

   // Skip barrier if writing a smi.
   ASSERT_EQ(0, kSmiTag);
   test(value, Immediate(kSmiTagMask));
   j(zero, &done);

-  IncrementalMarkingRecordWrite(object,
-                                value,
-                                scratch,
-                                OMIT_SMI_CHECK,
-                                PRESERVE_OBJECT,
-                                DESTROY_VALUE,
-                                (offset == 0) ? PRESERVE_SCRATCH
-                                              : DESTROY_SCRATCH);
-
-  InNewSpace(object, value, equal, &done);
-
   // The offset is relative to a tagged or untagged HeapObject pointer,
   // so either offset or offset + kHeapObjectTag must be a
   // multiple of kPointerSize.
   ASSERT(IsAligned(offset, kPointerSize) ||
          IsAligned(offset + kHeapObjectTag, kPointerSize));

-  Register dst = scratch;
   if (offset != 0) {
+    // If offset is unspecified, then dst is a scratch register.  We use it
+    // to store the address of the cell that is being stored to.
     lea(dst, Operand(object, offset));
   } else {
// Array access: calculate the destination address in the same manner as
@@ -192,7 +152,8 @@
     lea(dst, Operand(object, dst, times_half_pointer_size,
                      FixedArray::kHeaderSize - kHeapObjectTag));
   }
-  RecordWriteHelper(object, dst, value, save_fp);
+
+ RecordWrite(object, dst, value, EMIT_REMEMBERED_SET, save_fp, OMIT_SMI_CHECK);

   bind(&done);

@@ -201,7 +162,7 @@
   if (emit_debug_code()) {
     mov(object, Immediate(BitCast<int32_t>(kZapValue)));
     mov(value, Immediate(BitCast<int32_t>(kZapValue)));
-    mov(scratch, Immediate(BitCast<int32_t>(kZapValue)));
+    mov(dst, Immediate(BitCast<int32_t>(kZapValue)));
   }
 }

@@ -209,29 +170,30 @@
 void MacroAssembler::RecordWrite(Register object,
                                  Register address,
                                  Register value,
-                                 SaveFPRegsMode save_fp) {
+                                 EmitRememberedSet emit_remembered_set,
+                                 SaveFPRegsMode fp_mode,
+                                 SmiCheck smi_check) {
+  if (emit_remembered_set == OMIT_REMEMBERED_SET &&
+      FLAG_incremental_marking == false) {
+    return;
+  }
   // First, check if a write barrier is even needed. The tests below
   // catch stores of Smis and stores into young gen.
-  Label done;
-
-  // Skip barrier if writing a smi.
-  ASSERT_EQ(0, kSmiTag);
-  test(value, Immediate(kSmiTagMask));
-  j(zero, &done);
-
-  IncrementalMarkingRecordWrite(object,
-                                value,
-                                address,
-                                OMIT_SMI_CHECK,
-                                PRESERVE_OBJECT,
-                                DESTROY_VALUE,
-                                PRESERVE_SCRATCH);
-
-  InNewSpace(object, value, equal, &done);
-
-  RecordWriteHelper(object, address, value, save_fp);
-
-  bind(&done);
+  NearLabel done;
+
+  if (smi_check == INLINE_SMI_CHECK) {
+    // Skip barrier if writing a smi.
+    ASSERT_EQ(0, kSmiTag);
+    test(value, Immediate(kSmiTagMask));
+    j(zero, &done);
+  }
+
+ RecordWriteStub stub(object, value, address, emit_remembered_set, fp_mode);
+  CallStub(&stub);
+
+  if (smi_check == INLINE_SMI_CHECK) {
+    bind(&done);
+  }

   // Clobber all input registers when running with the debug-code flag
   // turned on to provoke errors.
=======================================
--- /branches/experimental/gc/src/ia32/macro-assembler-ia32.h Tue Mar 15 12:46:33 2011 +++ /branches/experimental/gc/src/ia32/macro-assembler-ia32.h Wed Apr 6 05:31:10 2011
@@ -53,10 +53,11 @@
 class JumpTarget;
 class PostCallGenerator;

+enum EmitRememberedSet { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
 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 };
+enum AddressMode { PRESERVE_ADDRESS, DESTROY_ADDRESS };

 // MacroAssembler implements a collection of frequently used macros.
 class MacroAssembler: public Assembler {
@@ -68,28 +69,15 @@

   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,
-                                     SmiCheck smi_check,
-                                     ObjectMode object_mode,
-                                     ValueMode value_mode,
-                                     ScratchMode scratch_mode);
-
+                                           Register address);

   // For page containing |object| mark region covering |addr| dirty.
-  // RecordWriteHelper only works if the object is not in new
+  // RememberedSetHelper only works if the object is not in new
   // space.
-  void RecordWriteHelper(Register object,
-                         Register addr,
-                         Register scratch,
-                         SaveFPRegsMode save_fp);
+  void RememberedSetHelper(Register object,
+                           Register addr,
+                           Register scratch,
+                           SaveFPRegsMode save_fp);

   // Check if object is in new space.
   // scratch can be object itself, but it will be clobbered.
@@ -120,7 +108,9 @@
   void RecordWrite(Register object,
                    Register address,
                    Register value,
-                   SaveFPRegsMode save_fp);
+                   EmitRememberedSet emit_remembered_set,
+                   SaveFPRegsMode save_fp,
+                   SmiCheck smi_check = INLINE_SMI_CHECK);

 #ifdef ENABLE_DEBUGGER_SUPPORT
// ---------------------------------------------------------------------------
=======================================
--- /branches/experimental/gc/src/ia32/stub-cache-ia32.cc Thu Mar 17 03:33:29 2011 +++ /branches/experimental/gc/src/ia32/stub-cache-ia32.cc Wed Apr 6 05:31:10 2011
@@ -1464,7 +1464,7 @@

     if (argc == 1) {  // Otherwise fall through to call builtin.
       Label exit, attempt_to_grow_elements;
-      Label with_write_barrier;
+      NearLabel with_write_barrier;

       // Get the array's length into eax and calculate new length.
       __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
@@ -1498,23 +1498,19 @@

       __ bind(&with_write_barrier);

-      __ IncrementalMarkingRecordWrite(ebx,
-                                       ecx,
-                                       edx,
-                                       OMIT_SMI_CHECK,
-                                       PRESERVE_OBJECT,
-                                       DESTROY_VALUE,
-                                       PRESERVE_SCRATCH);
-
-      __ InNewSpace(ebx, ecx, equal, &exit);
-
-      __ RecordWriteHelper(ebx, edx, ecx, kDontSaveFPRegs);
+      __ RecordWrite(
+ ebx, edx, ecx, EMIT_REMEMBERED_SET, kDontSaveFPRegs, OMIT_SMI_CHECK);
+
       __ ret((argc + 1) * kPointerSize);

       __ bind(&attempt_to_grow_elements);
       if (!FLAG_inline_new) {
         __ jmp(&call_builtin);
       }
+
+      // We could be lucky and the elements array could be at the top of
+ // new-space. In this case we can just grow it in place by moving the
+      // allocation pointer up.

       ExternalReference new_space_allocation_top =
           ExternalReference::new_space_allocation_top_address();
@@ -1547,13 +1543,13 @@
                Immediate(Factory::the_hole_value()));
       }

-      __ IncrementalMarkingRecordWrite(ebx,
-                                       ecx,
-                                       edx,
-                                       INLINE_SMI_CHECK,
-                                       PRESERVE_OBJECT,
-                                       DESTROY_VALUE,
-                                       DESTROY_SCRATCH);
+      // We know the elements array is in new space so we don't need the
+ // remembered set, but we just pushed a value onto it so we may have to + // tell the incremental marker to rescan the object that we just grew. We + // don't need to worry about the holes because they are in old space and
+      // already marked black.
+      __ mov(edi, ebx);
+      __ RecordWrite(edi, edx, ecx, OMIT_REMEMBERED_SET, kDontSaveFPRegs);

       // Restore receiver to edx as finish sequence assumes it's here.
       __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
@@ -2621,13 +2617,8 @@
   __ j(zero, &done);

   __ mov(ecx, eax);
-  __ IncrementalMarkingRecordWrite(ebx,
-                                   ecx,
-                                   edx,
-                                   INLINE_SMI_CHECK,
-                                   DESTROY_OBJECT,
-                                   DESTROY_VALUE,
-                                   DESTROY_SCRATCH);
+  // Cells are always in the remembered set.
+  __ RecordWrite(ebx, edx, ecx, OMIT_REMEMBERED_SET, kDontSaveFPRegs);

   // Return the value (register eax).
   __ bind(&done);
=======================================
--- /branches/experimental/gc/src/incremental-marking.cc Tue Mar 29 02:35:57 2011 +++ /branches/experimental/gc/src/incremental-marking.cc Wed Apr 6 05:31:10 2011
@@ -169,10 +169,10 @@
       uint32_t key = NumberToUint32(k);

       if (CodeStub::MajorKeyFromKey(key) ==
-          CodeStub::IncrementalMarkingRecordWrite) {
+          CodeStub::RecordWrite) {
         Object* e = stubs->ValueAt(i);
         if (e->IsCode()) {
-          IncrementalMarkingRecordWriteStub::Patch(Code::cast(e), enable);
+          RecordWriteStub::Patch(Code::cast(e), enable);
         }
       }
     }

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

Reply via email to