Skip card mark when storing known null reference

We don't need to mark the gc card if storing a null reference.

Change-Id: I445db196a097ed92b67b8bf1e6b486c6fac7d08f
diff --git a/src/compiler/codegen/arm/int_arm.cc b/src/compiler/codegen/arm/int_arm.cc
index 5a9786c..d908bf5 100644
--- a/src/compiler/codegen/arm/int_arm.cc
+++ b/src/compiler/codegen/arm/int_arm.cc
@@ -457,7 +457,7 @@
   RegLocation rl_object = LoadValue(cu, rl_src_obj, kCoreReg);
   RegLocation rl_new_value = LoadValue(cu, rl_src_new_value, kCoreReg);
 
-  if (need_write_barrier) {
+  if (need_write_barrier && !IsConstantNullRef(cu, rl_new_value)) {
     // Mark card for object assuming new value is stored.
     MarkGCCard(cu, rl_new_value.low_reg, rl_object.low_reg);
   }
@@ -946,7 +946,9 @@
   StoreBaseIndexed(cu, r_ptr, r_index, r_value, scale, kWord);
   FreeTemp(cu, r_ptr);
   FreeTemp(cu, r_index);
-  MarkGCCard(cu, r_value, r_array);
+  if (!IsConstantNullRef(cu, rl_src)) {
+    MarkGCCard(cu, r_value, r_array);
+  }
 }
 
 bool ArmCodegen::GenShiftImmOpLong(CompilationUnit* cu, Instruction::Code opcode,
diff --git a/src/compiler/codegen/gen_common.cc b/src/compiler/codegen/gen_common.cc
index a4c8d0c..40ec2bf 100644
--- a/src/compiler/codegen/gen_common.cc
+++ b/src/compiler/codegen/gen_common.cc
@@ -425,7 +425,7 @@
     if (is_volatile) {
       GenMemBarrier(cu, kStoreLoad);
     }
-    if (is_object) {
+    if (is_object && !IsConstantNullRef(cu, rl_src)) {
       MarkGCCard(cu, rl_src.low_reg, rBase);
     }
     FreeTemp(cu, rBase);
@@ -766,7 +766,7 @@
       if (is_volatile) {
         GenMemBarrier(cu, kLoadLoad);
       }
-      if (is_object) {
+      if (is_object && !IsConstantNullRef(cu, rl_src)) {
         MarkGCCard(cu, rl_src.low_reg, rl_obj.low_reg);
       }
     }
diff --git a/src/compiler/codegen/mips/int_mips.cc b/src/compiler/codegen/mips/int_mips.cc
index 675cf8d..41d289e 100644
--- a/src/compiler/codegen/mips/int_mips.cc
+++ b/src/compiler/codegen/mips/int_mips.cc
@@ -639,7 +639,9 @@
   StoreBaseIndexed(cu, r_ptr, r_index, r_value, scale, kWord);
   FreeTemp(cu, r_ptr);
   FreeTemp(cu, r_index);
-  MarkGCCard(cu, r_value, r_array);
+  if (!IsConstantNullRef(cu, rl_src)) {
+    MarkGCCard(cu, r_value, r_array);
+  }
 }
 
 bool MipsCodegen::GenShiftImmOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest,
diff --git a/src/compiler/codegen/x86/int_x86.cc b/src/compiler/codegen/x86/int_x86.cc
index d4a34f7..d47f3dc 100644
--- a/src/compiler/codegen/x86/int_x86.cc
+++ b/src/compiler/codegen/x86/int_x86.cc
@@ -587,7 +587,9 @@
   StoreBaseIndexedDisp(cu, r_array, r_index, scale,
                        data_offset, r_value, INVALID_REG, kWord, INVALID_SREG);
   FreeTemp(cu, r_index);
-  MarkGCCard(cu, r_value, r_array);
+  if (!IsConstantNullRef(cu, rl_src)) {
+    MarkGCCard(cu, r_value, r_array);
+  }
 }
 
 bool X86Codegen::GenShiftImmOpLong(CompilationUnit* cu, Instruction::Code opcode, RegLocation rl_dest,
diff --git a/src/compiler/compiler_ir.h b/src/compiler/compiler_ir.h
index 056c308..2b2dabe 100644
--- a/src/compiler/compiler_ir.h
+++ b/src/compiler/compiler_ir.h
@@ -605,6 +605,11 @@
       Low32Bits(static_cast<int64_t>(cu->constant_values[loc.orig_sreg]));
 }
 
+static inline bool IsConstantNullRef(const CompilationUnit* cu, RegLocation loc)
+{
+  return loc.ref && loc.is_const && (ConstantValue(cu, loc) == 0);
+}
+
 static inline bool MustFlushConstant(const CompilationUnit* cu, RegLocation loc)
 {
   DCHECK(IsConst(cu, loc));