Index: src/arm/codegen-arm.cc |
=================================================================== |
--- src/arm/codegen-arm.cc (revision 5120) |
+++ src/arm/codegen-arm.cc (working copy) |
@@ -151,6 +151,8 @@ |
// ------------------------------------------------------------------------- |
// CodeGenerator implementation |
+int CodeGenerator::inlined_write_barrier_size_ = -1; |
+ |
CodeGenerator::CodeGenerator(MacroAssembler* masm) |
: deferred_(8), |
masm_(masm), |
@@ -6225,7 +6227,13 @@ |
}; |
+// Takes value in r0, receiver in r1 and returns the result (the |
+// value) in r0. |
void DeferredReferenceSetNamedValue::Generate() { |
+ // Record the entry frame and spill. |
+ VirtualFrame copied_frame(*frame_state()->frame()); |
+ copied_frame.SpillAll(); |
+ |
// Ensure value in r0, receiver in r1 to match store ic calling |
// convention. |
ASSERT(value_.is(r0) && receiver_.is(r1)); |
@@ -6241,6 +6249,12 @@ |
// named store has been inlined. |
__ nop(PROPERTY_ACCESS_INLINED); |
+ // Go back to the frame we entered with. The instructions |
+ // generated by this merge are skipped over by the inline store |
+ // patching mechanism when looking for the branch instruction that |
+ // tells it where the code to patch is. |
+ copied_frame.MergeTo(frame_state()->frame()); |
+ |
// Block the constant pool for one more instruction after leaving this |
// constant pool block scope to include the branch instruction ending the |
// deferred code. |
@@ -6365,11 +6379,38 @@ |
int offset = 0; |
__ str(value, MemOperand(receiver, offset)); |
- // Update the write barrier. |
- __ RecordWrite(receiver, Operand(offset), scratch0, scratch1); |
+ // Update the write barrier and record its size. We do not use |
+ // the RecordWrite macro here because we want the offset |
+ // addition instruction first to make it easy to patch. |
+ Label record_write_start, record_write_done; |
+ __ bind(&record_write_start); |
+ // Add offset into the object. |
+ __ add(scratch0, receiver, Operand(offset)); |
+ // Test that the object is not in the new space. We cannot set |
+ // region marks for new space pages. |
+ __ InNewSpace(receiver, scratch1, eq, &record_write_done); |
+ // Record the actual write. |
+ __ RecordWriteHelper(receiver, scratch0, scratch1); |
+ __ bind(&record_write_done); |
+ // Clobber all input registers when running with the debug-code flag |
+ // turned on to provoke errors. |
+ if (FLAG_debug_code) { |
+ __ mov(receiver, Operand(BitCast<int32_t>(kZapValue))); |
+ __ mov(scratch0, Operand(BitCast<int32_t>(kZapValue))); |
+ __ mov(scratch1, Operand(BitCast<int32_t>(kZapValue))); |
+ } |
+ // Check that this is the first inlined write barrier or that |
+ // this inlined write barrier has the same size as all the other |
+ // inlined write barriers. |
+ ASSERT((inlined_write_barrier_size_ == -1) || |
+ (inlined_write_barrier_size_ == |
+ masm()->InstructionsGeneratedSince(&record_write_start))); |
+ inlined_write_barrier_size_ = |
+ masm()->InstructionsGeneratedSince(&record_write_start); |
+ |
// Make sure that the expected number of instructions are generated. |
ASSERT_EQ(GetInlinedNamedStoreInstructionsAfterPatch(), |
- masm_->InstructionsGeneratedSince(&check_inlined_codesize)); |
+ masm()->InstructionsGeneratedSince(&check_inlined_codesize)); |
} |
deferred->BindExit(); |
} |