Merge "Re-add read barrier to roots in the verifier."
diff --git a/compiler/dex/bb_optimizations.h b/compiler/dex/bb_optimizations.h
index 2920190..b2c348b 100644
--- a/compiler/dex/bb_optimizations.h
+++ b/compiler/dex/bb_optimizations.h
@@ -34,16 +34,16 @@
 
   void Start(PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    cUnit->mir_graph->DoCacheFieldLoweringInfo();
+    CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph->DoCacheFieldLoweringInfo();
   }
 
   bool Gate(const PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    return cUnit->mir_graph->HasFieldAccess();
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    return c_unit->mir_graph->HasFieldAccess();
   }
 };
 
@@ -58,16 +58,16 @@
 
   void Start(PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    cUnit->mir_graph->DoCacheMethodLoweringInfo();
+    CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph->DoCacheMethodLoweringInfo();
   }
 
   bool Gate(const PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    return cUnit->mir_graph->HasInvokes();
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    return c_unit->mir_graph->HasInvokes();
   }
 };
 
@@ -84,35 +84,35 @@
 
   bool Gate(const PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    return cUnit->mir_graph->InlineSpecialMethodsGate();
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    return c_unit->mir_graph->InlineSpecialMethodsGate();
   }
 
   void Start(PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    cUnit->mir_graph->InlineSpecialMethodsStart();
+    CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph->InlineSpecialMethodsStart();
   }
 
   bool Worker(PassDataHolder* data) const {
     DCHECK(data != nullptr);
     PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
-    CompilationUnit* cUnit = pass_me_data_holder->c_unit;
-    DCHECK(cUnit != nullptr);
+    CompilationUnit* c_unit = pass_me_data_holder->c_unit;
+    DCHECK(c_unit != nullptr);
     BasicBlock* bb = pass_me_data_holder->bb;
     DCHECK(bb != nullptr);
-    cUnit->mir_graph->InlineSpecialMethods(bb);
+    c_unit->mir_graph->InlineSpecialMethods(bb);
     // No need of repeating, so just return false.
     return false;
   }
 
   void End(PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    cUnit->mir_graph->InlineSpecialMethodsEnd();
+    CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph->InlineSpecialMethodsEnd();
   }
 };
 
@@ -127,9 +127,10 @@
 
   void Start(PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    cUnit->mir_graph->VerifyDataflow();
+    CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph->VerifyDataflow();
+    c_unit->mir_graph->ClearAllVisitedFlags();
   }
 
   bool Worker(PassDataHolder* data) const;
@@ -147,26 +148,26 @@
 
   void Start(PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    cUnit->mir_graph->EliminateNullChecksAndInferTypesStart();
+    CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph->EliminateNullChecksAndInferTypesStart();
   }
 
   bool Worker(PassDataHolder* data) const {
     DCHECK(data != nullptr);
     PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
-    CompilationUnit* cUnit = pass_me_data_holder->c_unit;
-    DCHECK(cUnit != nullptr);
+    CompilationUnit* c_unit = pass_me_data_holder->c_unit;
+    DCHECK(c_unit != nullptr);
     BasicBlock* bb = pass_me_data_holder->bb;
     DCHECK(bb != nullptr);
-    return cUnit->mir_graph->EliminateNullChecksAndInferTypes(bb);
+    return c_unit->mir_graph->EliminateNullChecksAndInferTypes(bb);
   }
 
   void End(PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    cUnit->mir_graph->EliminateNullChecksAndInferTypesEnd();
+    CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph->EliminateNullChecksAndInferTypesEnd();
   }
 };
 
@@ -178,26 +179,26 @@
 
   bool Gate(const PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    return cUnit->mir_graph->EliminateClassInitChecksGate();
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    return c_unit->mir_graph->EliminateClassInitChecksGate();
   }
 
   bool Worker(PassDataHolder* data) const {
     DCHECK(data != nullptr);
     PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
-    CompilationUnit* cUnit = pass_me_data_holder->c_unit;
-    DCHECK(cUnit != nullptr);
+    CompilationUnit* c_unit = pass_me_data_holder->c_unit;
+    DCHECK(c_unit != nullptr);
     BasicBlock* bb = pass_me_data_holder->bb;
     DCHECK(bb != nullptr);
-    return cUnit->mir_graph->EliminateClassInitChecks(bb);
+    return c_unit->mir_graph->EliminateClassInitChecks(bb);
   }
 
   void End(PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    cUnit->mir_graph->EliminateClassInitChecksEnd();
+    CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph->EliminateClassInitChecksEnd();
   }
 };
 
@@ -213,26 +214,26 @@
 
   bool Gate(const PassDataHolder* data) const OVERRIDE {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    return cUnit->mir_graph->ApplyGlobalValueNumberingGate();
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    return c_unit->mir_graph->ApplyGlobalValueNumberingGate();
   }
 
   bool Worker(PassDataHolder* data) const {
     DCHECK(data != nullptr);
     PassMEDataHolder* pass_me_data_holder = down_cast<PassMEDataHolder*>(data);
-    CompilationUnit* cUnit = pass_me_data_holder->c_unit;
-    DCHECK(cUnit != nullptr);
+    CompilationUnit* c_unit = pass_me_data_holder->c_unit;
+    DCHECK(c_unit != nullptr);
     BasicBlock* bb = pass_me_data_holder->bb;
     DCHECK(bb != nullptr);
-    return cUnit->mir_graph->ApplyGlobalValueNumbering(bb);
+    return c_unit->mir_graph->ApplyGlobalValueNumbering(bb);
   }
 
   void End(PassDataHolder* data) const OVERRIDE {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    cUnit->mir_graph->ApplyGlobalValueNumberingEnd();
+    CompilationUnit* c_unit = down_cast<PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    c_unit->mir_graph->ApplyGlobalValueNumberingEnd();
   }
 };
 
@@ -247,9 +248,9 @@
 
   bool Gate(const PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    return ((cUnit->disable_opt & (1 << kSuppressExceptionEdges)) != 0);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    return ((c_unit->disable_opt & (1 << kSuppressExceptionEdges)) != 0);
   }
 
   bool Worker(PassDataHolder* data) const;
@@ -266,9 +267,9 @@
 
   bool Gate(const PassDataHolder* data) const {
     DCHECK(data != nullptr);
-    CompilationUnit* cUnit = down_cast<const PassMEDataHolder*>(data)->c_unit;
-    DCHECK(cUnit != nullptr);
-    return ((cUnit->disable_opt & (1 << kBBOpt)) == 0);
+    CompilationUnit* c_unit = down_cast<const PassMEDataHolder*>(data)->c_unit;
+    DCHECK(c_unit != nullptr);
+    return ((c_unit->disable_opt & (1 << kBBOpt)) == 0);
   }
 
   void Start(PassDataHolder* data) const;
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 5d7cbed..7ac878f 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -678,26 +678,40 @@
   }
 }
 
-/* Try to make common case the fallthrough path */
+/* Try to make common case the fallthrough path. */
 bool MIRGraph::LayoutBlocks(BasicBlock* bb) {
-  // TODO: For now, just looking for direct throws.  Consider generalizing for profile feedback
+  // TODO: For now, just looking for direct throws.  Consider generalizing for profile feedback.
   if (!bb->explicit_throw) {
     return false;
   }
+
+  // If we visited it, we are done.
+  if (bb->visited) {
+    return false;
+  }
+  bb->visited = true;
+
   BasicBlock* walker = bb;
   while (true) {
-    // Check termination conditions
+    // Check termination conditions.
     if ((walker->block_type == kEntryBlock) || (Predecessors(walker) != 1)) {
       break;
     }
     BasicBlock* prev = GetBasicBlock(walker->predecessors->Get(0));
+
+    // If we visited the predecessor, we are done.
+    if (prev->visited) {
+      return false;
+    }
+    prev->visited = true;
+
     if (prev->conditional_branch) {
       if (GetBasicBlock(prev->fall_through) == walker) {
-        // Already done - return
+        // Already done - return.
         break;
       }
       DCHECK_EQ(walker, GetBasicBlock(prev->taken));
-      // Got one.  Flip it and exit
+      // Got one.  Flip it and exit.
       Instruction::Code opcode = prev->last_mir_insn->dalvikInsn.opcode;
       switch (opcode) {
         case Instruction::IF_EQ: opcode = Instruction::IF_NE; break;
@@ -721,6 +735,10 @@
       break;
     }
     walker = prev;
+
+    if (walker->visited) {
+      break;
+    }
   }
   return false;
 }
diff --git a/compiler/dex/quick/arm/assemble_arm.cc b/compiler/dex/quick/arm/assemble_arm.cc
index 06d9dd5..dcec861 100644
--- a/compiler/dex/quick/arm/assemble_arm.cc
+++ b/compiler/dex/quick/arm/assemble_arm.cc
@@ -427,7 +427,7 @@
                  REG_DEF_LR | NEEDS_FIXUP, "vldr", "!0s, [!1C, #!2E]", 4, kFixupVLoad),
     ENCODING_MAP(kThumb2Vldrd,       0xed900b00,
                  kFmtDfp, 22, 12, kFmtBitBlt, 19, 16, kFmtBitBlt, 7, 0,
-                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD_OFF |
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE1 | IS_LOAD_OFF4 |
                  REG_DEF_LR | NEEDS_FIXUP, "vldr", "!0S, [!1C, #!2E]", 4, kFixupVLoad),
     ENCODING_MAP(kThumb2Vmuls,        0xee200a00,
                  kFmtSfp, 22, 12, kFmtSfp, 7, 16, kFmtSfp, 5, 0,
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 26b6c60..4342234 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4427,7 +4427,6 @@
     return false;
   }
   CreateReferenceInstanceOffsets(klass);
-  CreateReferenceStaticOffsets(klass);
   CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus());
 
   if (!klass->IsTemp() || (!init_done_ && klass->GetClassSize() == class_size)) {
@@ -5160,20 +5159,13 @@
       return;
     }
   }
-  CreateReferenceOffsets(klass, false, reference_offsets);
+  CreateReferenceOffsets(klass, reference_offsets);
 }
 
-void ClassLinker::CreateReferenceStaticOffsets(ConstHandle<mirror::Class> klass) {
-  CreateReferenceOffsets(klass, true, 0);
-}
-
-void ClassLinker::CreateReferenceOffsets(ConstHandle<mirror::Class> klass, bool is_static,
+void ClassLinker::CreateReferenceOffsets(ConstHandle<mirror::Class> klass,
                                          uint32_t reference_offsets) {
-  size_t num_reference_fields =
-      is_static ? klass->NumReferenceStaticFieldsDuringLinking()
-                : klass->NumReferenceInstanceFieldsDuringLinking();
-  mirror::ObjectArray<mirror::ArtField>* fields =
-      is_static ? klass->GetSFields() : klass->GetIFields();
+  size_t num_reference_fields = klass->NumReferenceInstanceFieldsDuringLinking();
+  mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields();
   // All of the fields that contain object references are guaranteed
   // to be at the beginning of the fields list.
   for (size_t i = 0; i < num_reference_fields; ++i) {
@@ -5191,12 +5183,7 @@
       break;
     }
   }
-  // Update fields in klass
-  if (is_static) {
-    klass->SetReferenceStaticOffsets(reference_offsets);
-  } else {
-    klass->SetReferenceInstanceOffsets(reference_offsets);
-  }
+  klass->SetReferenceInstanceOffsets(reference_offsets);
 }
 
 mirror::String* ClassLinker::ResolveString(const DexFile& dex_file, uint32_t string_idx,
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 0248a21..158816d 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -533,10 +533,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void CreateReferenceInstanceOffsets(ConstHandle<mirror::Class> klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void CreateReferenceStaticOffsets(ConstHandle<mirror::Class> klass)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void CreateReferenceOffsets(ConstHandle<mirror::Class> klass, bool is_static,
-                              uint32_t reference_offsets)
+  void CreateReferenceOffsets(ConstHandle<mirror::Class> klass, uint32_t reference_offsets)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // For use by ImageWriter to find DexCaches for its roots
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 69c281e..b250918 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -528,7 +528,6 @@
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, object_size_),                   "objectSize"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, primitive_type_),                "primitiveType"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, reference_instance_offsets_),    "referenceInstanceOffsets"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, reference_static_offsets_),      "referenceStaticOffsets"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, status_),                        "status"));
   };
 };
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 760d54c..e7d8163 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -292,18 +292,6 @@
                     new_reference_offsets);
 }
 
-void Class::SetReferenceStaticOffsets(uint32_t new_reference_offsets) {
-  if (new_reference_offsets != CLASS_WALK_SUPER) {
-    // Sanity check that the number of bits set in the reference offset bitmap
-    // agrees with the number of references
-    CHECK_EQ((size_t)POPCOUNT(new_reference_offsets),
-             NumReferenceStaticFieldsDuringLinking());
-  }
-  // Not called within a transaction.
-  SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_),
-                    new_reference_offsets);
-}
-
 bool Class::IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2) {
   size_t i = 0;
   while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 0d30bc6..cf9501a 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -871,14 +871,6 @@
   // TODO: uint16_t
   void SetStaticField(uint32_t i, ArtField* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  uint32_t GetReferenceStaticOffsets() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_));
-  }
-
-  void SetReferenceStaticOffsets(uint32_t new_reference_offsets)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   // Find a static or instance field using the JLS resolution order
   static ArtField* FindField(Thread* self, Handle<Class> klass, const StringPiece& name,
                              const StringPiece& type)
@@ -1150,9 +1142,6 @@
   // Bitmap of offsets of ifields.
   uint32_t reference_instance_offsets_;
 
-  // Bitmap of offsets of sfields.
-  uint32_t reference_static_offsets_;
-
   // State of class initialization.
   Status status_;
 
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 8c1dc7d..166ea9c 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -888,9 +888,9 @@
 
 template<bool kVisitClass, bool kIsStatic, typename Visitor>
 inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
-  if (LIKELY(ref_offsets != CLASS_WALK_SUPER)) {
+  if (!kIsStatic && LIKELY(ref_offsets != CLASS_WALK_SUPER)) {
     if (!kVisitClass) {
-     // Mask out the class from the reference offsets.
+      // Mask out the class from the reference offsets.
       ref_offsets ^= kWordHighBitMask;
     }
     DCHECK_EQ(ClassOffset().Uint32Value(), 0U);
@@ -902,7 +902,7 @@
       ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
     }
   } else {
-    // There is no reference offset bitmap.  In the non-static case, walk up the class
+    // There is no reference offset bitmap. In the non-static case, walk up the class
     // inheritance hierarchy and find reference offsets the hard way. In the static case, just
     // consider this class.
     for (mirror::Class* klass = kIsStatic ? AsClass() : GetClass(); klass != nullptr;
@@ -930,8 +930,7 @@
 template<bool kVisitClass, typename Visitor>
 inline void Object::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
   DCHECK(!klass->IsTemp());
-  klass->VisitFieldsReferences<kVisitClass, true>(
-      klass->GetReferenceStaticOffsets<kVerifyNone>(), visitor);
+  klass->VisitFieldsReferences<kVisitClass, true>(0, visitor);
 }
 
 template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor,