Index: runtime/vm/assembler_ia32.cc |
=================================================================== |
--- runtime/vm/assembler_ia32.cc (revision 42713) |
+++ runtime/vm/assembler_ia32.cc (working copy) |
@@ -1457,6 +1457,15 @@ |
} |
+void Assembler::testb(const Address& address, const Immediate& imm) { |
+ ASSERT(imm.is_int8()); |
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
+ EmitUint8(0xF6); |
+ EmitOperand(0, address); |
+ EmitUint8(imm.value() & 0xFF); |
+} |
+ |
+ |
void Assembler::andl(Register dst, Register src) { |
AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
EmitUint8(0x23); |
@@ -2212,7 +2221,21 @@ |
} |
-void Assembler::VerifyHeapWord(const Address& address) { |
+void Assembler::VerifyHeapWord(const Address& address, |
+ FieldContent old_content) { |
+#if defined(DEBUG) |
+ switch (old_content) { |
+ case kEmptyOrSmiOrNull: |
+ VerifyUninitialized(address); |
+ break; |
+ case kHeapObjectOrSmi: |
+ VerifyObjectOrSmi(address); |
+ break; |
+ case kOnlySmi: |
+ VerifySmi(address); |
+ break; |
+ } |
+#endif // DEBUG |
if (VerifiedMemory::enabled()) { |
Register addr_reg = EDX; |
Register value = EBX; |
@@ -2233,8 +2256,10 @@ |
} |
-void Assembler::VerifiedWrite(const Address& dest, Register value) { |
- VerifyHeapWord(dest); |
+void Assembler::VerifiedWrite(const Address& dest, |
+ Register value, |
+ FieldContent old_content) { |
+ VerifyHeapWord(dest, old_content); |
movl(dest, value); |
if (VerifiedMemory::enabled()) { |
Register temp = (value == EDX) ? ECX : EDX; |
@@ -2246,6 +2271,44 @@ |
} |
+#if defined(DEBUG) |
+void Assembler::VerifyObjectOrSmi(const Address& dest) { |
+ Label ok; |
+ testb(dest, Immediate(kHeapObjectTag)); |
+ j(ZERO, &ok, Assembler::kNearJump); |
+ // Non-smi case: Verify object pointer is word-aligned when untagged. |
+ COMPILE_ASSERT(kHeapObjectTag == 1); |
+ testb(dest, Immediate((kWordSize - 1) - kHeapObjectTag)); |
+ j(ZERO, &ok, Assembler::kNearJump); |
+ Stop("Expected heap object or Smi"); |
+ Bind(&ok); |
+} |
+ |
+ |
+void Assembler::VerifyUninitialized(const Address& dest) { |
+ Label ok; |
+ testb(dest, Immediate(kHeapObjectTag)); |
+ j(ZERO, &ok, Assembler::kNearJump); |
+ // Non-smi case: Check for the special zap word or null. |
+ cmpl(dest, Immediate(Heap::kZap32Bits)); |
+ j(EQUAL, &ok, Assembler::kNearJump); |
+ cmpl(dest, Immediate(reinterpret_cast<uint32_t>(Object::null()))); |
+ j(EQUAL, &ok, Assembler::kNearJump); |
+ Stop("Expected zapped, Smi or null"); |
+ Bind(&ok); |
+} |
+ |
+ |
+void Assembler::VerifySmi(const Address& dest, const char* stop_msg) { |
+ Label done; |
+ testb(dest, Immediate(kHeapObjectTag)); |
+ j(ZERO, &done, Assembler::kNearJump); |
+ Stop(stop_msg); |
+ Bind(&done); |
+} |
+#endif // defined(DEBUG) |
+ |
+ |
// Destroys the value register. |
void Assembler::StoreIntoObject(Register object, |
const Address& dest, |
@@ -2252,7 +2315,7 @@ |
Register value, |
bool can_value_be_smi) { |
ASSERT(object != value); |
- VerifiedWrite(dest, value); |
+ VerifiedWrite(dest, value, kHeapObjectOrSmi); |
Label done; |
if (can_value_be_smi) { |
StoreIntoObjectFilter(object, value, &done); |
@@ -2277,8 +2340,9 @@ |
void Assembler::StoreIntoObjectNoBarrier(Register object, |
const Address& dest, |
- Register value) { |
- VerifiedWrite(dest, value); |
+ Register value, |
+ FieldContent old_content) { |
+ VerifiedWrite(dest, value, old_content); |
#if defined(DEBUG) |
Label done; |
pushl(value); |
@@ -2304,8 +2368,9 @@ |
void Assembler::StoreIntoObjectNoBarrier(Register object, |
const Address& dest, |
- const Object& value) { |
- VerifyHeapWord(dest); |
+ const Object& value, |
+ FieldContent old_content) { |
+ VerifyHeapWord(dest, old_content); |
if (value.IsSmi() || value.InVMHeap()) { |
Immediate imm_value(reinterpret_cast<int32_t>(value.raw())); |
movl(dest, imm_value); |
@@ -2331,20 +2396,19 @@ |
void Assembler::StoreIntoSmiField(const Address& dest, Register value) { |
- VerifiedWrite(dest, value); |
#if defined(DEBUG) |
Label done; |
testl(value, Immediate(kHeapObjectTag)); |
j(ZERO, &done); |
- Stop("Smi expected"); |
+ Stop("New value must be Smi."); |
Bind(&done); |
#endif // defined(DEBUG) |
+ VerifiedWrite(dest, value, kOnlySmi); |
} |
-void Assembler::ZeroSmiField(const Address& dest) { |
- // TODO(koda): Add VerifySmi once we distinguish initalization. |
- VerifyHeapWord(dest); |
+void Assembler::ZeroInitSmiField(const Address& dest) { |
+ VerifyHeapWord(dest, kEmptyOrSmiOrNull); |
Immediate zero(Smi::RawValue(0)); |
movl(dest, zero); |
if (VerifiedMemory::enabled()) { |
@@ -2360,8 +2424,7 @@ |
void Assembler::IncrementSmiField(const Address& dest, int32_t increment) { |
// Note: FlowGraphCompiler::EdgeCounterIncrementSizeInBytes depends on |
// the length of this instruction sequence. |
- // TODO(koda): Add VerifySmi once we distinguish initalization. |
- VerifyHeapWord(dest); |
+ VerifyHeapWord(dest, kOnlySmi); |
Immediate inc_imm(Smi::RawValue(increment)); |
addl(dest, inc_imm); |
if (VerifiedMemory::enabled()) { |