Revision: 6184
Author: [email protected]
Date: Wed Jan 5 06:17:18 2011
Log: Write buffer based write barrier for IA32 and Crankshaft. Currently
coverage is untested, but believed to be complete.
Review URL: http://codereview.chromium.org/6092007
http://code.google.com/p/v8/source/detail?r=6184
Modified:
/branches/experimental/gc/src/assembler.h
/branches/experimental/gc/src/code-stubs.h
/branches/experimental/gc/src/codegen.cc
/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/runtime.cc
/branches/experimental/gc/src/runtime.h
/branches/experimental/gc/src/serialize.cc
/branches/experimental/gc/src/write-buffer.cc
/branches/experimental/gc/src/write-buffer.h
/branches/experimental/gc/test/cctest/test-alloc.cc
=======================================
--- /branches/experimental/gc/src/assembler.h Tue Dec 21 04:32:46 2010
+++ /branches/experimental/gc/src/assembler.h Wed Jan 5 06:17:18 2011
@@ -152,6 +152,9 @@
};
+enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs };
+
+
//
-----------------------------------------------------------------------------
// Relocation information
=======================================
--- /branches/experimental/gc/src/code-stubs.h Wed Jan 5 05:52:13 2011
+++ /branches/experimental/gc/src/code-stubs.h Wed Jan 5 06:17:18 2011
@@ -47,6 +47,7 @@
V(Compare) \
V(CompareIC) \
V(MathPow) \
+ V(WriteBufferOverflow) \
V(TranscendentalCache) \
V(RecordWrite) \
V(ConvertToDouble) \
@@ -572,11 +573,11 @@
class CEntryStub : public CodeStub {
public:
- explicit CEntryStub(int result_size)
- : result_size_(result_size), save_doubles_(false) { }
+ explicit CEntryStub(int result_size,
+ SaveFPRegsMode save_doubles = kDontSaveFPRegs)
+ : result_size_(result_size), save_doubles_(save_doubles) { }
void Generate(MacroAssembler* masm);
- void SaveDoubles() { save_doubles_ = true; }
private:
void GenerateCore(MacroAssembler* masm,
@@ -592,7 +593,7 @@
// Number of pointers/values returned.
const int result_size_;
- bool save_doubles_;
+ SaveFPRegsMode save_doubles_;
Major MajorKey() { return CEntry; }
int MinorKey();
=======================================
--- /branches/experimental/gc/src/codegen.cc Tue Dec 21 04:32:46 2010
+++ /branches/experimental/gc/src/codegen.cc Wed Jan 5 06:17:18 2011
@@ -472,11 +472,12 @@
int CEntryStub::MinorKey() {
- ASSERT(result_size_ == 1 || result_size_ == 2);
- int result = save_doubles_ ? 1 : 0;
+ int result = (save_doubles_ == kSaveFPRegs) ? 1 : 0;
#ifdef _WIN64
+ ASSERT(result_size_ == 1 || result_size_ == 2);
return result | ((result_size_ == 1) ? 0 : 2);
#else
+ ASSERT(result_size_ == 1);
return result;
#endif
}
=======================================
--- /branches/experimental/gc/src/ia32/code-stubs-ia32.cc Wed Jan 5
05:52:13 2011
+++ /branches/experimental/gc/src/ia32/code-stubs-ia32.cc Wed Jan 5
06:17:18 2011
@@ -257,6 +257,37 @@
__ mov(eax, 0);
__ ret(1 * kPointerSize);
}
+
+
+void WriteBufferOverflowStub::Generate(MacroAssembler* masm) {
+ // We don't allow a GC during a write buffer overflow so there is no
need to
+ // store the registers in any particular way, but we do have to store and
+ // restore them.
+ __ pushad();
+ if (save_doubles_ == kSaveFPRegs) {
+ CpuFeatures::Scope scope(SSE2);
+ __ sub(Operand(esp), Immediate(kDoubleSize *
XMMRegister::kNumRegisters));
+ for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
+ XMMRegister reg = XMMRegister::from_code(i);
+ __ movdbl(Operand(esp, i * kDoubleSize), reg);
+ }
+ }
+ const int argument_count = 0;
+ __ PrepareCallCFunction(argument_count, ecx);
+ ExternalReference write_buffer_overflow =
+
ExternalReference(Runtime::FunctionForId(Runtime::kWriteBufferOverflow));
+ __ CallCFunction(write_buffer_overflow, argument_count);
+ if (save_doubles_ == kSaveFPRegs) {
+ CpuFeatures::Scope scope(SSE2);
+ for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
+ XMMRegister reg = XMMRegister::from_code(i);
+ __ movdbl(reg, Operand(esp, i * kDoubleSize));
+ }
+ __ add(Operand(esp), Immediate(kDoubleSize *
XMMRegister::kNumRegisters));
+ }
+ __ popad();
+ __ ret(0);
+}
const char* GenericBinaryOpStub::GetName() {
@@ -3981,16 +4012,16 @@
// Store last subject and last input.
__ mov(eax, Operand(esp, kSubjectOffset));
__ mov(FieldOperand(ebx, RegExpImpl::kLastSubjectOffset), eax);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
__ mov(ecx, ebx);
- __ RecordWrite(ecx, RegExpImpl::kLastSubjectOffset, eax, edi);
-#endif
+ __ RecordWrite(ecx,
+ RegExpImpl::kLastSubjectOffset,
+ eax,
+ edi,
+ kDontSaveFPRegs);
__ mov(eax, Operand(esp, kSubjectOffset));
__ mov(FieldOperand(ebx, RegExpImpl::kLastInputOffset), eax);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
__ mov(ecx, ebx);
- __ RecordWrite(ecx, RegExpImpl::kLastInputOffset, eax, edi);
-#endif
+ __ RecordWrite(ecx, RegExpImpl::kLastInputOffset, eax, edi,
kDontSaveFPRegs);
// Get the static offsets vector filled by the native regexp code.
ExternalReference address_of_static_offsets_vector =
@@ -4728,7 +4759,7 @@
__ j(zero, &failure_returned, not_taken);
// Exit the JavaScript to C++ exit frame.
- __ LeaveExitFrame(save_doubles_);
+ __ LeaveExitFrame(save_doubles_ == kSaveFPRegs);
__ ret(0);
// Handling of failure.
@@ -4828,7 +4859,7 @@
// a garbage collection and retrying the builtin (twice).
// Enter the exit frame that transitions from JavaScript to C++.
- __ EnterExitFrame(save_doubles_);
+ __ EnterExitFrame(save_doubles_ == kSaveFPRegs);
// eax: result parameter for PerformGC, if any (setup below)
// ebx: pointer to builtin function (C callee-saved)
=======================================
--- /branches/experimental/gc/src/ia32/code-stubs-ia32.h Tue Dec 21
04:32:46 2010
+++ /branches/experimental/gc/src/ia32/code-stubs-ia32.h Wed Jan 5
06:17:18 2011
@@ -72,6 +72,21 @@
};
+class WriteBufferOverflowStub: public CodeStub {
+ public:
+ explicit WriteBufferOverflowStub(SaveFPRegsMode save_fp)
+ : save_doubles_(save_fp) { }
+
+ void Generate(MacroAssembler* masm);
+
+ private:
+ SaveFPRegsMode save_doubles_;
+
+ Major MajorKey() { return WriteBufferOverflow; }
+ int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; }
+};
+
+
// Flag that indicates how to generate code for the stub
GenericBinaryOpStub.
enum GenericBinaryFlags {
NO_GENERIC_BINARY_FLAGS = 0,
=======================================
--- /branches/experimental/gc/src/ia32/codegen-ia32.cc Thu Dec 23 08:04:56
2010
+++ /branches/experimental/gc/src/ia32/codegen-ia32.cc Wed Jan 5 06:17:18
2011
@@ -265,14 +265,16 @@
Result context = allocator_->Allocate();
ASSERT(context.is_valid());
__ mov(SlotOperand(slot, context.reg()), value.reg());
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
int offset = FixedArray::kHeaderSize + slot->index() *
kPointerSize;
Result scratch = allocator_->Allocate();
ASSERT(scratch.is_valid());
frame_->Spill(context.reg());
frame_->Spill(value.reg());
- __ RecordWrite(context.reg(), offset, value.reg(),
scratch.reg());
-#endif
+ __ RecordWrite(context.reg(),
+ offset,
+ value.reg(),
+ scratch.reg(),
+ kDontSaveFPRegs);
}
}
}
@@ -5311,7 +5313,6 @@
ASSERT(start.is_valid());
__ mov(SlotOperand(slot, start.reg()), value.reg());
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// RecordWrite may destroy the value registers.
//
// TODO(204): Avoid actually spilling when the value is not
@@ -5320,10 +5321,13 @@
int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
Result temp = allocator_->Allocate();
ASSERT(temp.is_valid());
- __ RecordWrite(start.reg(), offset, value.reg(), temp.reg());
+ __ RecordWrite(start.reg(),
+ offset,
+ value.reg(),
+ temp.reg(),
+ kDontSaveFPRegs);
// The results start, value, and temp are unused by going out of
// scope.
-#endif
}
exit.Bind();
@@ -5710,13 +5714,15 @@
int offset = i * kPointerSize + FixedArray::kHeaderSize;
__ mov(FieldOperand(elements.reg(), offset), prop_value.reg());
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Update the write barrier for the array address.
frame_->Spill(prop_value.reg()); // Overwritten by the write barrier.
Result scratch = allocator_->Allocate();
ASSERT(scratch.is_valid());
- __ RecordWrite(elements.reg(), offset, prop_value.reg(),
scratch.reg());
-#endif
+ __ RecordWrite(elements.reg(),
+ offset,
+ prop_value.reg(),
+ scratch.reg(),
+ kDontSaveFPRegs);
}
}
@@ -7246,7 +7252,6 @@
// Store the value.
__ mov(FieldOperand(object.reg(), JSValue::kValueOffset), value.reg());
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Update the write barrier. Save the value as it will be
// overwritten by the write barrier code and is needed afterward.
Result duplicate_value = allocator_->Allocate();
@@ -7256,9 +7261,8 @@
// possibly aliased in the frame.
frame_->Spill(object.reg());
__ RecordWrite(object.reg(), JSValue::kValueOffset,
duplicate_value.reg(),
- scratch.reg());
+ scratch.reg(), kDontSaveFPRegs);
duplicate_value.Unuse();
-#endif
object.Unuse();
scratch.Unuse();
@@ -7531,9 +7535,7 @@
__ mov(FieldOperand(ecx, JSFunctionResultCache::kFingerOffset), edx);
// Store key.
__ mov(CodeGenerator::FixedArrayElementOperand(ecx, edx), ebx);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
- __ RecordWrite(ecx, 0, ebx, edx);
-#endif
+ __ RecordWrite(ecx, 0, ebx, edx, kDontSaveFPRegs);
// Store value.
__ pop(ecx); // restore the cache.
@@ -7541,9 +7543,7 @@
__ add(Operand(edx), Immediate(Smi::FromInt(1)));
__ mov(ebx, eax);
__ mov(CodeGenerator::FixedArrayElementOperand(ecx, edx), ebx);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
- __ RecordWrite(ecx, 0, ebx, edx);
-#endif
+ __ RecordWrite(ecx, 0, ebx, edx, kDontSaveFPRegs);
if (!dst_.is(eax)) {
__ mov(dst_, eax);
@@ -7708,17 +7708,15 @@
__ mov(Operand(index2.reg(), 0), object.reg());
__ mov(Operand(index1.reg(), 0), tmp2.reg());
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
Label done;
__ InNewSpace(tmp1.reg(), tmp2.reg(), equal, &done);
// Possible optimization: do a check that both values are Smis
// (or them and test against Smi mask.)
__ mov(tmp2.reg(), tmp1.reg());
- __ RecordWriteHelper(tmp2.reg(), index1.reg(), object.reg());
- __ RecordWriteHelper(tmp1.reg(), index2.reg(), object.reg());
+ __ RecordWriteHelper(tmp2.reg(), index1.reg(), object.reg(),
kDontSaveFPRegs);
+ __ RecordWriteHelper(tmp1.reg(), index2.reg(), object.reg(),
kDontSaveFPRegs);
__ bind(&done);
-#endif
deferred->BindExit();
frame_->Push(Factory::undefined_value());
@@ -9659,22 +9657,20 @@
// Update the write barrier. To save instructions in the inlined
// version we do not filter smis.
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
Label skip_write_barrier;
__ 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());
+ __ RecordWriteHelper(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)));
__ mov(scratch.reg(), Immediate(BitCast<int32_t>(kZapValue)));
}
__ bind(&skip_write_barrier);
-#else
- // Store some dummy value to avoid short encoding of test instruction.
- int delta_to_record_write = 0x0001;
-#endif
value.Unuse();
scratch.Unuse();
receiver.Unuse();
@@ -9808,11 +9804,9 @@
Result tmp2 = allocator_->Allocate();
ASSERT(tmp2.is_valid());
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Determine whether the value is a constant before putting it in a
// register.
bool value_is_constant = result.is_constant();
-#endif
// Make sure that value, key and receiver are in registers.
result.ToRegister();
@@ -9852,7 +9846,6 @@
__ mov(tmp.reg(),
FieldOperand(receiver.reg(), JSArray::kElementsOffset));
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Check whether it is possible to omit the write barrier. If the
elements
// array is in new space or the value written is a smi we can safely
update
// the elements array without write barrier.
@@ -9865,7 +9858,6 @@
__ bind(&in_new_space);
-#endif
// Bind the deferred code patch site to be able to locate the fixed
// array map comparison. When debugging, we patch this comparison to
// always fail so that we will hit the IC call in the deferred code
=======================================
--- /branches/experimental/gc/src/ia32/full-codegen-ia32.cc Wed Jan 5
05:52:13 2011
+++ /branches/experimental/gc/src/ia32/full-codegen-ia32.cc Wed Jan 5
06:17:18 2011
@@ -170,13 +170,11 @@
// Store it in the context.
int context_offset = Context::SlotOffset(slot->index());
__ mov(Operand(esi, context_offset), eax);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Update the write barrier. This clobbers all involved
// registers, so we have use a third register to avoid
// clobbering esi.
__ mov(ecx, esi);
- __ RecordWrite(ecx, context_offset, eax, ebx);
-#endif
+ __ RecordWrite(ecx, context_offset, eax, ebx, kDontSaveFPRegs);
}
}
}
@@ -603,13 +601,11 @@
MemOperand location = EmitSlotSearch(dst, scratch1);
__ mov(location, src);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Emit the write barrier code if the location is in the heap.
if (dst->type() == Slot::CONTEXT) {
int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
- __ RecordWrite(scratch1, offset, src, scratch2);
- }
-#endif
+ __ RecordWrite(scratch1, offset, src, scratch2, kDontSaveFPRegs);
+ }
}
@@ -678,11 +674,9 @@
} else if (function != NULL) {
VisitForAccumulatorValue(function);
__ mov(ContextOperand(esi, slot->index()), result_register());
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
int offset = Context::SlotOffset(slot->index());
__ mov(ebx, esi);
- __ RecordWrite(ebx, offset, result_register(), ecx);
-#endif
+ __ RecordWrite(ebx, offset, result_register(), ecx,
kDontSaveFPRegs);
}
break;
@@ -1452,10 +1446,8 @@
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
__ mov(FieldOperand(ebx, offset), result_register());
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Update the write barrier for the array store.
- __ RecordWrite(ebx, offset, result_register(), ecx);
-#endif
+ __ RecordWrite(ebx, offset, result_register(), ecx, kDontSaveFPRegs);
PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
}
@@ -2024,13 +2016,11 @@
// Perform the assignment and issue the write barrier.
__ mov(target, eax);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// The value of the assignment is in eax. RecordWrite clobbers its
// register arguments.
__ mov(edx, eax);
int offset = FixedArray::kHeaderSize + slot->index() *
kPointerSize;
- __ RecordWrite(ecx, offset, edx, ebx);
-#endif
+ __ RecordWrite(ecx, offset, edx, ebx, kDontSaveFPRegs);
break;
}
@@ -2906,7 +2896,7 @@
VisitForAccumulatorValue(args->at(1)); // Load the value.
__ pop(ebx); // eax = value. ebx = object.
- NearLabel done;
+ Label done;
// If the object is a smi, return the value.
__ test(ebx, Immediate(kSmiTagMask));
__ j(zero, &done);
@@ -2918,12 +2908,10 @@
// Store the value.
__ mov(FieldOperand(ebx, JSValue::kValueOffset), eax);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Update the write barrier. Save the value as it will be
// overwritten by the write barrier code and is needed afterward.
__ mov(edx, eax);
- __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx);
-#endif
+ __ RecordWrite(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs);
__ bind(&done);
context()->Plug(eax);
@@ -3206,16 +3194,14 @@
__ mov(Operand(index_2, 0), object);
__ mov(Operand(index_1, 0), temp);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
Label new_space;
__ InNewSpace(elements, temp, equal, &new_space);
__ mov(object, elements);
- __ RecordWriteHelper(object, index_1, temp);
- __ RecordWriteHelper(elements, index_2, temp);
+ __ RecordWriteHelper(object, index_1, temp, kDontSaveFPRegs);
+ __ RecordWriteHelper(elements, index_2, temp, kDontSaveFPRegs);
__ bind(&new_space);
-#endif
// We are done. Drop elements from the stack, and return undefined.
__ add(Operand(esp), Immediate(3 * kPointerSize));
=======================================
--- /branches/experimental/gc/src/ia32/ic-ia32.cc Wed Jan 5 05:52:13 2011
+++ /branches/experimental/gc/src/ia32/ic-ia32.cc Wed Jan 5 06:17:18 2011
@@ -264,10 +264,8 @@
__ mov(Operand(r0, 0), value);
// Update write barrier. Make sure not to clobber the value.
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
__ mov(r1, value);
- __ RecordWrite(elements, r0, r1);
-#endif
+ __ RecordWrite(elements, r0, r1, kDontSaveFPRegs);
}
@@ -1027,11 +1025,9 @@
// edi: FixedArray receiver->elements
__ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Update write barrier for the elements array address.
__ mov(edx, Operand(eax));
- __ RecordWrite(edi, 0, edx, ecx);
-#endif
+ __ RecordWrite(edi, 0, edx, ecx, kDontSaveFPRegs);
__ ret(0);
}
=======================================
--- /branches/experimental/gc/src/ia32/lithium-codegen-ia32.cc Wed Jan 5
05:52:13 2011
+++ /branches/experimental/gc/src/ia32/lithium-codegen-ia32.cc Wed Jan 5
06:17:18 2011
@@ -2483,24 +2483,20 @@
// Do the store.
if (instr->is_in_object()) {
__ mov(FieldOperand(object, offset), value);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
if (instr->needs_write_barrier()) {
Register temp = ToRegister(instr->temp());
// Update the write barrier for the object for in-object properties.
- __ RecordWrite(object, offset, value, temp);
- }
-#endif
+ __ RecordWrite(object, offset, value, temp, kSaveFPRegs);
+ }
} else {
Register temp = ToRegister(instr->temp());
__ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset));
__ mov(FieldOperand(temp, offset), value);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
if (instr->needs_write_barrier()) {
// Update the write barrier for the properties array.
// object is used as a scratch register.
- __ RecordWrite(temp, offset, value, object);
- }
-#endif
+ __ RecordWrite(temp, offset, value, object, kSaveFPRegs);
+ }
}
}
@@ -2538,14 +2534,12 @@
value);
}
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Update the write barrier unless we're certain that we're storing a
smi.
if (instr->hydrogen()->NeedsWriteBarrier()) {
// Compute address of modified element and store it into key register.
__ lea(key, FieldOperand(elements, key, times_4,
FixedArray::kHeaderSize));
- __ RecordWrite(elements, key, value);
- }
-#endif
+ __ RecordWrite(elements, key, value, kSaveFPRegs);
+ }
}
=======================================
--- /branches/experimental/gc/src/ia32/macro-assembler-ia32.cc Tue Dec 21
04:32:46 2010
+++ /branches/experimental/gc/src/ia32/macro-assembler-ia32.cc Wed Jan 5
06:17:18 2011
@@ -48,10 +48,10 @@
code_object_(Heap::undefined_value()) {
}
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
void MacroAssembler::RecordWriteHelper(Register object,
Register addr,
- Register scratch) {
+ Register scratch,
+ SaveFPRegsMode save_fp) {
if (FLAG_debug_code) {
// Check that the object is not in new space.
Label not_in_new_space;
@@ -60,24 +60,32 @@
bind(¬_in_new_space);
}
- // Compute the page start address from the heap object pointer, and reuse
- // the 'object' register for it.
- and_(object, ~Page::kPageAlignmentMask);
-
- // Compute number of region covering addr. See
Page::GetRegionNumberForAddress
- // method for more details.
- and_(addr, Page::kPageAlignmentMask);
- shr(addr, Page::kRegionSizeLog2);
-
- // Set dirty mark for region.
- bts(Operand(object, Page::kDirtyFlagOffset), addr);
+ // Load write buffer top.
+ ExternalReference write_buffer = ExternalReference::write_buffer_top();
+ mov(scratch, Operand::StaticVariable(write_buffer));
+ // Store pointer to buffer.
+ mov(Operand(scratch, 0), addr);
+ // Increment buffer top.
+ add(Operand(scratch), Immediate(kPointerSize));
+ // Write back new top of buffer.
+ mov(Operand::StaticVariable(write_buffer), scratch);
+ // Call stub on end of buffer.
+ NearLabel no_overflow;
+ // Check for end of buffer.
+ test(scratch, Immediate(WriteBuffer::kWriteBufferOverflowBit));
+ j(equal, &no_overflow);
+ WriteBufferOverflowStub write_buffer_overflow =
+ WriteBufferOverflowStub(save_fp);
+ CallStub(&write_buffer_overflow);
+ bind(&no_overflow);
}
void MacroAssembler::RecordWrite(Register object,
int offset,
Register value,
- Register scratch) {
+ Register scratch,
+ SaveFPRegsMode save_fp) {
// The compiled code assumes that record write doesn't change the
// context register, so we check that none of the clobbered
// registers are esi.
@@ -112,7 +120,7 @@
lea(dst, Operand(object, dst, times_half_pointer_size,
FixedArray::kHeaderSize - kHeapObjectTag));
}
- RecordWriteHelper(object, dst, value);
+ RecordWriteHelper(object, dst, value, save_fp);
bind(&done);
@@ -128,7 +136,8 @@
void MacroAssembler::RecordWrite(Register object,
Register address,
- Register value) {
+ Register value,
+ SaveFPRegsMode save_fp) {
// The compiled code assumes that record write doesn't change the
// context register, so we check that none of the clobbered
// registers are esi.
@@ -145,7 +154,7 @@
InNewSpace(object, value, equal, &done);
- RecordWriteHelper(object, address, value);
+ RecordWriteHelper(object, address, value, save_fp);
bind(&done);
@@ -157,7 +166,7 @@
mov(value, Immediate(BitCast<int32_t>(kZapValue)));
}
}
-#endif
+
#ifdef ENABLE_DEBUGGER_SUPPORT
void MacroAssembler::DebugBreak() {
@@ -382,10 +391,22 @@
// Optionally restore all XMM registers.
if (save_doubles) {
CpuFeatures::Scope scope(SSE2);
- int offset = -2 * kPointerSize;
- for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
- XMMRegister reg = XMMRegister::from_code(i);
- movdbl(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize)));
+ if (save_doubles) {
+ int offset = -2 * kPointerSize;
+ for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
+ XMMRegister reg = XMMRegister::from_code(i);
+ movdbl(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize)));
+ }
+ } else if (FLAG_debug_code) {
+ // Zap all fp registers on a runtime call if we were not asked to
preserve
+ // them.
+ push(eax);
+ mov(eax, Factory::nan_value());
+ for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
+ XMMRegister reg = XMMRegister::from_code(i);
+ movdbl(reg, FieldOperand(eax, HeapNumber::kValueOffset));
+ }
+ pop(eax);
}
}
@@ -1092,8 +1113,7 @@
Runtime::Function* function = Runtime::FunctionForId(id);
Set(eax, Immediate(function->nargs));
mov(ebx, Immediate(ExternalReference(function)));
- CEntryStub ces(1);
- ces.SaveDoubles();
+ CEntryStub ces(1, kSaveFPRegs);
CallStub(&ces);
}
=======================================
--- /branches/experimental/gc/src/ia32/macro-assembler-ia32.h Tue Dec 21
04:32:46 2010
+++ /branches/experimental/gc/src/ia32/macro-assembler-ia32.h Wed Jan 5
06:17:18 2011
@@ -61,13 +61,13 @@
//
---------------------------------------------------------------------------
// GC Support
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// For page containing |object| mark region covering |addr| dirty.
// RecordWriteHelper only works if the object is not in new
// space.
void RecordWriteHelper(Register object,
Register addr,
- Register scratch);
+ Register scratch,
+ SaveFPRegsMode save_fp);
// Check if object is in new space.
// scratch can be object itself, but it will be clobbered.
@@ -87,7 +87,8 @@
void RecordWrite(Register object,
int offset,
Register value,
- Register scratch);
+ Register scratch,
+ SaveFPRegsMode save_fp);
// For page containing |object| mark region covering |address|
// dirty. |object| is the object being stored into, |value| is the
@@ -96,8 +97,8 @@
// write barrier if the value is a smi.
void RecordWrite(Register object,
Register address,
- Register value);
-#endif
+ Register value,
+ SaveFPRegsMode save_fp);
#ifdef ENABLE_DEBUGGER_SUPPORT
//
---------------------------------------------------------------------------
@@ -661,7 +662,6 @@
};
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
template <typename LabelType>
void MacroAssembler::InNewSpace(Register object,
Register scratch,
@@ -685,7 +685,6 @@
j(cc, branch);
}
}
-#endif
// The code patcher is used to patch (typically) small parts of code e.g.
for
=======================================
--- /branches/experimental/gc/src/ia32/stub-cache-ia32.cc Wed Jan 5
05:52:13 2011
+++ /branches/experimental/gc/src/ia32/stub-cache-ia32.cc Wed Jan 5
06:17:18 2011
@@ -818,12 +818,10 @@
int offset = object->map()->instance_size() + (index * kPointerSize);
__ mov(FieldOperand(receiver_reg, offset), eax);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
__ mov(name_reg, Operand(eax));
- __ RecordWrite(receiver_reg, offset, name_reg, scratch);
-#endif
+ __ RecordWrite(receiver_reg, offset, name_reg, scratch,
kDontSaveFPRegs);
} else {
// Write to the properties array.
int offset = index * kPointerSize + FixedArray::kHeaderSize;
@@ -831,12 +829,10 @@
__ mov(scratch, FieldOperand(receiver_reg,
JSObject::kPropertiesOffset));
__ mov(FieldOperand(scratch, offset), eax);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
__ mov(name_reg, Operand(eax));
- __ RecordWrite(scratch, offset, name_reg, receiver_reg);
-#endif
+ __ RecordWrite(scratch, offset, name_reg, receiver_reg,
kDontSaveFPRegs);
}
// Return the value (register eax).
@@ -1483,9 +1479,7 @@
if (argc == 1) { // Otherwise fall through to call builtin.
Label exit, attempt_to_grow_elements;
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
Label with_write_barrier;
-#endif
// Get the array's length into eax and calculate new length.
__ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
@@ -1510,23 +1504,19 @@
__ mov(ecx, Operand(esp, argc * kPointerSize));
__ mov(Operand(edx, 0), ecx);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
// Check if value is a smi.
__ test(ecx, Immediate(kSmiTagMask));
__ j(not_zero, &with_write_barrier);
-#endif
__ bind(&exit);
__ ret((argc + 1) * kPointerSize);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
__ bind(&with_write_barrier);
__ InNewSpace(ebx, ecx, equal, &exit);
- __ RecordWriteHelper(ebx, edx, ecx);
+ __ RecordWriteHelper(ebx, edx, ecx, kDontSaveFPRegs);
__ ret((argc + 1) * kPointerSize);
-#endif
__ bind(&attempt_to_grow_elements);
if (!FLAG_inline_new) {
@@ -2695,9 +2685,7 @@
// the value in register eax.
__ mov(edx, Operand(eax));
__ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax);
-#ifdef ENABLE_CARDMARKING_WRITE_BARRIER
- __ RecordWrite(edi, 0, edx, ecx);
-#endif
+ __ RecordWrite(edi, 0, edx, ecx, kDontSaveFPRegs);
// Done.
__ ret(0);
=======================================
--- /branches/experimental/gc/src/runtime.cc Tue Dec 21 04:32:46 2010
+++ /branches/experimental/gc/src/runtime.cc Wed Jan 5 06:17:18 2011
@@ -5398,6 +5398,12 @@
}
return Heap::nan_value();
}
+
+
+static MaybeObject* Runtime_WriteBufferOverflow(Arguments args) {
+ WriteBuffer::Compact();
+ return Heap::undefined_value();
+}
static MaybeObject* Runtime_AllocateHeapNumber(Arguments args) {
=======================================
--- /branches/experimental/gc/src/runtime.h Tue Dec 21 04:32:46 2010
+++ /branches/experimental/gc/src/runtime.h Wed Jan 5 06:17:18 2011
@@ -82,10 +82,11 @@
F(LazyRecompile, 1, 1) \
F(NotifyDeoptimized, 1, 1) \
F(NotifyOSR, 0, 1) \
- F(DeoptimizeFunction, 1, 1) \
+ F(DeoptimizeFunction, 1, 1) \
F(CompileForOnStackReplacement, 1, 1) \
F(SetNewFunctionAttributes, 1, 1) \
F(AllocateInNewSpace, 1, 1) \
+ F(WriteBufferOverflow, 0, 1) \
\
/* Array join support */ \
F(PushIfAbsent, 2, 1) \
=======================================
--- /branches/experimental/gc/src/serialize.cc Wed Dec 8 06:32:40 2010
+++ /branches/experimental/gc/src/serialize.cc Wed Jan 5 06:17:18 2011
@@ -498,6 +498,10 @@
UNCLASSIFIED,
39,
"power_double_int_function");
+ Add(ExternalReference::write_buffer_top().address(),
+ UNCLASSIFIED,
+ 40,
+ "write_buffer_top");
}
=======================================
--- /branches/experimental/gc/src/write-buffer.cc Thu Dec 16 12:15:51 2010
+++ /branches/experimental/gc/src/write-buffer.cc Wed Jan 5 06:17:18 2011
@@ -83,6 +83,7 @@
memset(reinterpret_cast<void*>(hash_map_2_),
0,
sizeof(uintptr_t) * kHashMapLength);
+ ASSERT(top_ <= limit_);
Address* stop = top_;
top_ = start_;
// Goes through the addresses in the write buffer attempting to remove
=======================================
--- /branches/experimental/gc/src/write-buffer.h Thu Dec 16 12:15:51 2010
+++ /branches/experimental/gc/src/write-buffer.h Wed Jan 5 06:17:18 2011
@@ -61,6 +61,8 @@
static const int kHashMapLengthLog2 = 12;
static const int kHashMapLength = 1 << kHashMapLengthLog2;
+ static void Compact();
+
private:
static Address* top_;
static Address* start_;
@@ -68,8 +70,6 @@
static VirtualMemory* virtual_memory_;
static uintptr_t* hash_map_1_;
static uintptr_t* hash_map_2_;
-
- static void Compact();
};
} } // namespace v8::internal
=======================================
--- /branches/experimental/gc/test/cctest/test-alloc.cc Thu Dec 23 08:04:56
2010
+++ /branches/experimental/gc/test/cctest/test-alloc.cc Wed Jan 5 06:17:18
2011
@@ -192,7 +192,7 @@
if (current_allocated < code_range_size / 10) {
// Allocate a block.
// Geometrically distributed sizes, greater than
Page::kMaxHeapObjectSize.
- // TODO (gc) instead of using 3 use some contant based on
code_range_size
+ // TODO(gc): instead of using 3 use some contant based on
code_range_size
// kMaxHeapObjectSize.
size_t requested = (Page::kMaxHeapObjectSize << (Pseudorandom() %
3)) +
Pseudorandom() % 5000 + 1;
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev