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