| 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();
|
| }
|
|
|