Index: runtime/vm/assembler_x64.cc |
=================================================================== |
--- runtime/vm/assembler_x64.cc (revision 41785) |
+++ runtime/vm/assembler_x64.cc (working copy) |
@@ -2384,6 +2384,9 @@ |
void Assembler::j(Condition condition, Label* label, bool near) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ if (VerifiedMemory::enabled()) { |
+ near = Assembler::kFarJump; |
+ } |
if (label->IsBound()) { |
static const int kShortSize = 2; |
static const int kLongSize = 6; |
@@ -2436,6 +2439,9 @@ |
void Assembler::jmp(Label* label, bool near) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ if (VerifiedMemory::enabled()) { |
+ near = Assembler::kFarJump; |
+ } |
if (label->IsBound()) { |
static const int kShortSize = 2; |
static const int kLongSize = 5; |
@@ -2871,12 +2877,46 @@ |
} |
+void Assembler::VerifyHeapWord(const Address& address) { |
+ if (VerifiedMemory::enabled()) { |
+ Register addr_reg = RDX; |
+ Register value = RBX; |
+ // Preserve registers. |
+ pushq(addr_reg); |
+ pushq(value); |
+ leaq(addr_reg, address); |
+ // ASSERT(*address == *(address + offset)) |
+ movq(value, Address(addr_reg, 0)); |
+ cmpq(value, Address(addr_reg, VerifiedMemory::offset())); |
+ Label ok; |
+ j(EQUAL, &ok); |
+ Stop("Write barrier verification failed"); |
+ Bind(&ok); |
+ popq(value); |
+ popq(addr_reg); |
+ } |
+} |
+ |
+ |
+void Assembler::VerifiedWrite(const Address& dest, Register value) { |
+ VerifyHeapWord(dest); |
+ movq(dest, value); |
+ if (VerifiedMemory::enabled()) { |
+ Register temp = (value == RDX) ? RCX : RDX; |
+ pushq(temp); |
+ leaq(temp, dest); |
+ movq(Address(temp, VerifiedMemory::offset()), value); |
+ popq(temp); |
+ } |
+} |
+ |
+ |
void Assembler::StoreIntoObject(Register object, |
const Address& dest, |
Register value, |
bool can_value_be_smi) { |
ASSERT(object != value); |
- movq(dest, value); |
+ VerifiedWrite(dest, value); |
Label done; |
if (can_value_be_smi) { |
StoreIntoObjectFilter(object, value, &done); |
@@ -2898,7 +2938,7 @@ |
void Assembler::StoreIntoObjectNoBarrier(Register object, |
const Address& dest, |
Register value) { |
- movq(dest, value); |
+ VerifiedWrite(dest, value); |
#if defined(DEBUG) |
Label done; |
pushq(value); |
@@ -2911,6 +2951,50 @@ |
} |
+void Assembler::StoreIntoSmiField(const Address& dest, Register value) { |
+ VerifiedWrite(dest, value); |
+#if defined(DEBUG) |
+ Label done; |
+ testq(value, Immediate(kHeapObjectTag)); |
+ j(ZERO, &done); |
+ Stop("Smi expected"); |
+ Bind(&done); |
+#endif // defined(DEBUG) |
+} |
+ |
+ |
+void Assembler::ZeroSmiField(const Address& dest) { |
+ // TODO(koda): Add VerifySmi once we distinguish initalization. |
+ VerifyHeapWord(dest); |
+ Immediate zero(Smi::RawValue(0)); |
+ movq(dest, zero); |
+ if (VerifiedMemory::enabled()) { |
+ Register temp = RCX; |
+ pushq(temp); |
+ leaq(temp, dest); |
+ movq(Address(temp, VerifiedMemory::offset()), zero); |
+ popq(temp); |
+ } |
+} |
+ |
+ |
+void Assembler::IncrementSmiField(const Address& dest, int64_t increment) { |
+ // Note: FlowGraphCompiler::EdgeCounterIncrementSizeInBytes depends on |
+ // the length of this instruction sequence. |
+ // TODO(koda): Add VerifySmi once we distinguish initalization. |
+ VerifyHeapWord(dest); |
+ Immediate inc_imm(Smi::RawValue(increment)); |
+ addq(dest, inc_imm); |
+ if (VerifiedMemory::enabled()) { |
+ Register temp = RCX; |
+ pushq(temp); |
+ leaq(temp, dest); |
+ addq(Address(temp, VerifiedMemory::offset()), inc_imm); |
+ popq(temp); |
+ } |
+} |
+ |
+ |
void Assembler::DoubleNegate(XmmRegister d) { |
static const struct ALIGN16 { |
uint64_t a; |