Merge "Port the "abstract methods are not implementations" fix to art." into dalvik-dev
diff --git a/build/Android.common.mk b/build/Android.common.mk
index f35458c..65cb75d 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -258,6 +258,7 @@
 	src/utils.cc \
 	src/vector_output_stream.cc \
 	src/verifier/dex_gc_map.cc \
+	src/verifier/instruction_flags.cc \
 	src/verifier/method_verifier.cc \
 	src/verifier/reg_type.cc \
 	src/verifier/reg_type_cache.cc \
diff --git a/src/base/histogram-inl.h b/src/base/histogram-inl.h
index 3ffb9a0..9e3de9f 100644
--- a/src/base/histogram-inl.h
+++ b/src/base/histogram-inl.h
@@ -169,7 +169,7 @@
   double per_1 = per_0 + interval;
   os << Name() << ":\t";
   TimeUnit unit = GetAppropriateTimeUnit(Mean() * kAdjust);
-  os << interval << "% C.I. "
+  os << (interval * 100) << "% C.I. "
      << FormatDuration(Percentile(per_0) * kAdjust, unit);
   os << "-" << FormatDuration(Percentile(per_1) * kAdjust, unit) << " ";
   os << "Avg: " << FormatDuration(Mean() * kAdjust, unit) << " Max: ";
@@ -240,6 +240,13 @@
 
   double value = lower_value + (upper_value - lower_value) *
                                (per - lower_perc) / (upper_perc - lower_perc);
+
+  if (value < min_value_added_) {
+    value = min_value_added_;
+  } else if (value > max_value_added_) {
+    value = max_value_added_;
+  }
+
   return value;
 }
 
diff --git a/src/base/histogram_test.cc b/src/base/histogram_test.cc
index 28812fd..7a6c235 100644
--- a/src/base/histogram_test.cc
+++ b/src/base/histogram_test.cc
@@ -29,7 +29,7 @@
   hist->AddValue(28);
   hist->AddValue(28);
   mean = hist->Mean();
-  EXPECT_EQ(mean, 20.5);
+  EXPECT_EQ(20.5, mean);
 }
 
 TEST(Histtest, VarianceTest) {
@@ -42,7 +42,7 @@
   hist->AddValue(28);
   hist->CreateHistogram();
   variance = hist->Variance();
-  EXPECT_EQ(variance, 64.25);
+  EXPECT_EQ(64.25, variance);
   delete hist;
 }
 
@@ -69,7 +69,7 @@
 
   hist->CreateHistogram();
   PerValue = hist->Percentile(0.50);
-  EXPECT_EQ(static_cast<int>(PerValue * 10), 875);
+  EXPECT_EQ(875, static_cast<int>(PerValue * 10));
 
   delete hist;
 }
@@ -106,7 +106,7 @@
   std::string text;
   std::stringstream stream;
   std::string expected =
-      "UpdateRange:\t0.99% C.I. 1.050us-214.475us Avg: 126.380us Max: 212us\n";
+      "UpdateRange:\t99% C.I. 15us-212us Avg: 126.380us Max: 212us\n";
   hist->PrintConfidenceIntervals(stream, 0.99);
 
   EXPECT_EQ(expected, stream.str());
@@ -152,7 +152,7 @@
   std::string text;
   std::stringstream stream;
   std::string expected =
-      "Reset:\t0.99% C.I. 1.050us-214.475us Avg: 126.380us Max: 212us\n";
+      "Reset:\t99% C.I. 15us-212us Avg: 126.380us Max: 212us\n";
   hist->PrintConfidenceIntervals(stream, 0.99);
 
   EXPECT_EQ(expected, stream.str());
@@ -192,10 +192,9 @@
   hist->AddValue(212);
   hist->CreateHistogram();
   PerValue = hist->Percentile(0.50);
-
   std::stringstream stream;
   std::string expected =
-      "MultipleCreateHist:\t0.99% C.I. 1.050us-214.475us Avg: 126.380us Max: 212us\n";
+      "MultipleCreateHist:\t99% C.I. 15us-212us Avg: 126.380us Max: 212us\n";
   hist->PrintConfidenceIntervals(stream, 0.99);
 
   EXPECT_EQ(expected, stream.str());
@@ -208,16 +207,38 @@
 TEST(Histtest, SingleValue) {
 
   Histogram<uint64_t> *hist = new Histogram<uint64_t>("SingleValue");
-
   hist->AddValue(1);
   hist->CreateHistogram();
-
   std::stringstream stream;
-  std::string expected =
-      "SingleValue:\t0.99% C.I. 0.025us-4.975us Avg: 1us Max: 1us\n";
+  std::string expected = "SingleValue:\t99% C.I. 1us-1us Avg: 1us Max: 1us\n";
   hist->PrintConfidenceIntervals(stream, 0.99);
-  EXPECT_EQ(stream.str(), expected);
+  EXPECT_EQ(expected, stream.str());
+  delete hist;
+}
 
+TEST(Histtest, CappingPercentiles) {
+
+  double per_995;
+  double per_005;
+  Histogram<uint64_t> *hist = new Histogram<uint64_t>("CappingPercentiles");
+  // All values are similar.
+  for (uint64_t idx = 0ull; idx < 150ull; idx++) {
+    hist->AddValue(0);
+  }
+  hist->CreateHistogram();
+  per_995 = hist->Percentile(0.995);
+  EXPECT_EQ(per_995, 0);
+  hist->Reset();
+  for (size_t idx = 0; idx < 200; idx++) {
+    for (uint64_t val = 1ull; val <= 4ull; val++) {
+      hist->AddValue(val);
+    }
+  }
+  hist->CreateHistogram();
+  per_005 = hist->Percentile(0.005);
+  per_995 = hist->Percentile(0.995);
+  EXPECT_EQ(1, per_005);
+  EXPECT_EQ(4, per_995);
   delete hist;
 }
 
@@ -230,15 +251,13 @@
       hist->AddValue(idx * idx_inner);
     }
   }
-
   hist->AddValue(10000);
   hist->CreateHistogram();
-
   std::stringstream stream;
   std::string expected =
-      "SpikyValues:\t0.99% C.I. 0.089us-2541.825us Avg: 95.033us Max: 10000us\n";
+      "SpikyValues:\t99% C.I. 0.089us-2541.825us Avg: 95.033us Max: 10000us\n";
   hist->PrintConfidenceIntervals(stream, 0.99);
-  EXPECT_EQ(stream.str(), expected);
+  EXPECT_EQ(expected, stream.str());
 
   delete hist;
 }
diff --git a/src/compiler_llvm/ir_builder.h b/src/compiler_llvm/ir_builder.h
index 4a58515..60a0f2a 100644
--- a/src/compiler_llvm/ir_builder.h
+++ b/src/compiler_llvm/ir_builder.h
@@ -65,6 +65,15 @@
     return inst;
   }
 
+  llvm::AtomicCmpXchgInst*
+  CreateAtomicCmpXchgInst(llvm::Value* ptr, llvm::Value* cmp, llvm::Value* val,
+                          llvm::MDNode* tbaa_info) {
+    llvm::AtomicCmpXchgInst* inst =
+        LLVMIRBuilder::CreateAtomicCmpXchg(ptr, cmp, val, llvm::Acquire);
+    inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_info);
+    return inst;
+  }
+
 
   //--------------------------------------------------------------------------
   // TBAA
@@ -120,6 +129,17 @@
     StoreToObjectOffset(object_addr, offset, new_value, mdb_.GetTBAAMemoryJType(special_ty, j_ty));
   }
 
+  llvm::AtomicCmpXchgInst*
+  CompareExchangeObjectOffset(llvm::Value* object_addr,
+                              int64_t offset,
+                              llvm::Value* cmp_value,
+                              llvm::Value* new_value,
+                              TBAASpecialType special_ty) {
+    DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
+    return CompareExchangeObjectOffset(object_addr, offset, cmp_value, new_value,
+                                       mdb_.GetTBAASpecialType(special_ty));
+  }
+
   void SetTBAA(llvm::Instruction* inst, TBAASpecialType special_ty) {
     inst->setMetadata(llvm::LLVMContext::MD_tbaa, mdb_.GetTBAASpecialType(special_ty));
   }
@@ -210,6 +230,21 @@
     CreateStore(new_value, value_addr, tbaa_info);
   }
 
+  llvm::AtomicCmpXchgInst* CompareExchangeObjectOffset(llvm::Value* object_addr,
+                                                       int64_t offset,
+                                                       llvm::Value* cmp_value,
+                                                       llvm::Value* new_value,
+                                                       llvm::MDNode* tbaa_info) {
+    // Convert offset to llvm::value
+    llvm::Value* llvm_offset = getPtrEquivInt(offset);
+    // Calculate the value's address
+    llvm::Value* value_addr = CreatePtrDisp(object_addr,
+                                            llvm_offset,
+                                            new_value->getType()->getPointerTo());
+    // Atomic compare and exchange
+    return CreateAtomicCmpXchgInst(value_addr, cmp_value, new_value, tbaa_info);
+  }
+
 
   //--------------------------------------------------------------------------
   // Runtime Helper Function
diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc
index 36b5fa1..e661ec4 100644
--- a/src/compiler_llvm/runtime_support_builder.cc
+++ b/src/compiler_llvm/runtime_support_builder.cc
@@ -167,9 +167,49 @@
 /* Monitor */
 
 void RuntimeSupportBuilder::EmitLockObject(llvm::Value* object) {
-  // TODO: Implement a fast path.
+  Value* monitor =
+      irb_.LoadFromObjectOffset(object,
+                                mirror::Object::MonitorOffset().Int32Value(),
+                                irb_.getJIntTy(),
+                                kTBAARuntimeInfo);
+
+  Value* real_monitor =
+      irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
+
+  // Is thin lock, unheld and not recursively acquired.
+  Value* unheld = irb_.CreateICmpEQ(real_monitor, irb_.getInt32(0));
+
+  Function* parent_func = irb_.GetInsertBlock()->getParent();
+  BasicBlock* bb_fast = BasicBlock::Create(context_, "lock_fast", parent_func);
+  BasicBlock* bb_slow = BasicBlock::Create(context_, "lock_slow", parent_func);
+  BasicBlock* bb_cont = BasicBlock::Create(context_, "lock_cont", parent_func);
+  irb_.CreateCondBr(unheld, bb_fast, bb_slow, kLikely);
+
+  irb_.SetInsertPoint(bb_fast);
+
+  // Calculate new monitor: new = old | (lock_id << LW_LOCK_OWNER_SHIFT)
+  Value* lock_id =
+      EmitLoadFromThreadOffset(Thread::ThinLockIdOffset().Int32Value(),
+                               irb_.getInt32Ty(), kTBAARuntimeInfo);
+
+  Value* owner = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT);
+  Value* new_monitor = irb_.CreateOr(monitor, owner);
+
+  // Atomically update monitor.
+  Value* old_monitor =
+      irb_.CompareExchangeObjectOffset(object,
+                                       mirror::Object::MonitorOffset().Int32Value(),
+                                       monitor, new_monitor, kTBAARuntimeInfo);
+
+  Value* retry_slow_path = irb_.CreateICmpEQ(old_monitor, monitor);
+  irb_.CreateCondBr(retry_slow_path, bb_cont, bb_slow, kLikely);
+
+  irb_.SetInsertPoint(bb_slow);
   Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject);
   irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
+  irb_.CreateBr(bb_cont);
+
+  irb_.SetInsertPoint(bb_cont);
 }
 
 void RuntimeSupportBuilder::EmitUnlockObject(llvm::Value* object) {
diff --git a/src/disassembler_x86.cc b/src/disassembler_x86.cc
index 38171f6..bda162a 100644
--- a/src/disassembler_x86.cc
+++ b/src/disassembler_x86.cc
@@ -480,6 +480,7 @@
         break;
       case 0xAE:
         if (prefix[0] == 0xF3) {
+          prefix[0] = 0;  // clear prefix now it's served its purpose as part of the opcode
           static const char* xAE_opcodes[] = {"rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase", "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE"};
           modrm_opcodes = xAE_opcodes;
           reg_is_opcode = true;
@@ -731,7 +732,18 @@
   for (size_t i = 0; begin_instr + i < instr; ++i) {
     hex << StringPrintf("%02X", begin_instr[i]);
   }
-  os << StringPrintf("%p: %22s    \t%-7s ", begin_instr, hex.str().c_str(), opcode.str().c_str()) << args.str() << '\n';
+  std::stringstream prefixed_opcode;
+  switch (prefix[0]) {
+    case 0xF0: prefixed_opcode << "lock "; break;
+    case 0xF2: prefixed_opcode << "repne "; break;
+    case 0xF3: prefixed_opcode << "repe "; break;
+    case 0: break;
+    default: LOG(FATAL) << "Unreachable";
+  }
+  prefixed_opcode << opcode.str();
+  os << StringPrintf("%p: %22s    \t%-7s ", begin_instr, hex.str().c_str(),
+                     prefixed_opcode.str().c_str())
+     << args.str() << '\n';
   return instr - begin_instr;
 }
 
diff --git a/src/oat/runtime/support_deoptimize.cc b/src/oat/runtime/support_deoptimize.cc
index 0d88c52..c77d034 100644
--- a/src/oat/runtime/support_deoptimize.cc
+++ b/src/oat/runtime/support_deoptimize.cc
@@ -51,11 +51,10 @@
       CHECK(code_item != NULL);
       uint16_t num_regs =  code_item->registers_size_;
       shadow_frame_ = ShadowFrame::Create(num_regs, NULL, m, GetDexPc());
-      std::vector<int32_t> kinds =
-          verifier::MethodVerifier::DescribeVRegs(m->GetDexMethodIndex(), &mh.GetDexFile(),
-                                                  mh.GetDexCache(), mh.GetClassLoader(),
-                                                  mh.GetClassDefIndex(), code_item, m,
-                                                  m->GetAccessFlags(), GetDexPc());
+      std::vector<int32_t> kinds = DescribeVRegs(m->GetDexMethodIndex(), &mh.GetDexFile(),
+                                                 mh.GetDexCache(), mh.GetClassLoader(),
+                                                 mh.GetClassDefIndex(), code_item, m,
+                                                 m->GetAccessFlags(), GetDexPc());
       for(uint16_t reg = 0; reg < num_regs; reg++) {
         VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
         switch (kind) {
@@ -72,6 +71,22 @@
       }
       return false;  // Stop now we have built the shadow frame.
     }
+
+    std::vector<int32_t> DescribeVRegs(uint32_t dex_method_idx,
+                                       const DexFile* dex_file,
+                                       mirror::DexCache* dex_cache,
+                                       mirror::ClassLoader* class_loader,
+                                       uint32_t class_def_idx,
+                                       const DexFile::CodeItem* code_item,
+                                       mirror::AbstractMethod* method,
+                                       uint32_t method_access_flags, uint32_t dex_pc)
+        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+      verifier::MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item,
+                                        dex_method_idx, method, method_access_flags, true);
+      verifier.Verify();
+      return verifier.DescribeVRegs(dex_pc);
+    }
+
     ShadowFrame* shadow_frame_;
     uint32_t runtime_frames_;
   } visitor(self, self->GetLongJumpContext());
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 3fe62bc..4063d70 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -585,14 +585,22 @@
                         uint32_t dex_method_idx, const DexFile* dex_file,
                         uint32_t class_def_idx, const DexFile::CodeItem* code_item,
                         uint32_t method_access_flags, uint32_t dex_pc) {
+    static UniquePtr<verifier::MethodVerifier> verifier;
+    static const DexFile* verified_dex_file = NULL;
+    static uint32_t verified_dex_method_idx = DexFile::kDexNoIndex;
+    if (dex_file != verified_dex_file || verified_dex_method_idx != dex_method_idx) {
+      ScopedObjectAccess soa(Thread::Current());
+      mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file);
+      mirror::ClassLoader* class_loader = NULL;
+      verifier.reset(new verifier::MethodVerifier(dex_file, dex_cache, class_loader, class_def_idx,
+                                                  code_item, dex_method_idx, NULL,
+                                                  method_access_flags, true));
+      verifier->Verify();
+      verified_dex_file = dex_file;
+      verified_dex_method_idx = dex_method_idx;
+    }
+    std::vector<int32_t> kinds = verifier->DescribeVRegs(dex_pc);
     bool first = true;
-    ScopedObjectAccess soa(Thread::Current());
-    mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file);
-    mirror::ClassLoader* class_loader = NULL;
-    std::vector<int32_t> kinds =
-        verifier::MethodVerifier::DescribeVRegs(dex_method_idx, dex_file, dex_cache,
-                                                class_loader, class_def_idx, code_item, NULL,
-                                                method_access_flags, dex_pc);
     for (size_t reg = 0; reg < code_item->registers_size_; reg++) {
       VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
       if (kind != kUndefined) {
diff --git a/src/verifier/instruction_flags.cc b/src/verifier/instruction_flags.cc
new file mode 100644
index 0000000..823edde
--- /dev/null
+++ b/src/verifier/instruction_flags.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "instruction_flags.h"
+
+#include <string.h>
+
+namespace art {
+namespace verifier {
+
+std::string InstructionFlags::ToString() const {
+  char encoding[6];
+  if (!IsOpcode()) {
+    strncpy(encoding, "XXXXX", sizeof(encoding));
+  } else {
+    strncpy(encoding, "-----", sizeof(encoding));
+    if (IsInTry())        encoding[kInTry] = 'T';
+    if (IsBranchTarget()) encoding[kBranchTarget] = 'B';
+    if (IsGcPoint())      encoding[kGcPoint] = 'G';
+    if (IsVisited())      encoding[kVisited] = 'V';
+    if (IsChanged())      encoding[kChanged] = 'C';
+  }
+  return encoding;
+}
+
+}  // namespace verifier
+}  // namespace art
diff --git a/src/verifier/instruction_flags.h b/src/verifier/instruction_flags.h
new file mode 100644
index 0000000..7f0d240
--- /dev/null
+++ b/src/verifier/instruction_flags.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_VERIFIER_METHOD_INSTRUCTION_FLAGS_H_
+#define ART_SRC_VERIFIER_METHOD_INSTRUCTION_FLAGS_H_
+
+#include "base/logging.h"
+
+#include <stdint.h>
+#include <string>
+
+namespace art {
+namespace verifier {
+
+class InstructionFlags {
+ public:
+  InstructionFlags() : length_(0), flags_(0) {}
+
+  void SetLengthInCodeUnits(size_t length) {
+    DCHECK_LT(length, 65536u);
+    length_ = length;
+  }
+  size_t GetLengthInCodeUnits() {
+    return length_;
+  }
+  bool IsOpcode() const {
+    return length_ != 0;
+  }
+
+  void SetInTry() {
+    flags_ |= 1 << kInTry;
+  }
+  void ClearInTry() {
+    flags_ &= ~(1 << kInTry);
+  }
+  bool IsInTry() const {
+    return (flags_ & (1 << kInTry)) != 0;
+  }
+
+  void SetBranchTarget() {
+    flags_ |= 1 << kBranchTarget;
+  }
+  void ClearBranchTarget() {
+    flags_ &= ~(1 << kBranchTarget);
+  }
+  bool IsBranchTarget() const {
+    return (flags_ & (1 << kBranchTarget)) != 0;
+  }
+
+  void SetGcPoint() {
+    flags_ |= 1 << kGcPoint;
+  }
+  void ClearGcPoint() {
+    flags_ &= ~(1 << kGcPoint);
+  }
+  bool IsGcPoint() const {
+    return (flags_ & (1 << kGcPoint)) != 0;
+  }
+
+  void SetVisited() {
+    flags_ |= 1 << kVisited;
+  }
+  void ClearVisited() {
+    flags_ &= ~(1 << kVisited);
+  }
+  bool IsVisited() const {
+    return (flags_ & (1 << kVisited)) != 0;
+  }
+
+  void SetChanged() {
+    flags_ |= 1 << kChanged;
+  }
+  void ClearChanged() {
+    flags_ &= ~(1 << kChanged);
+  }
+  bool IsChanged() const {
+    return (flags_ & (1 << kChanged)) != 0;
+  }
+
+  bool IsVisitedOrChanged() const {
+    return IsVisited() || IsChanged();
+  }
+
+  std::string ToString() const;
+
+ private:
+  enum {
+    kInTry,
+    kBranchTarget,
+    kGcPoint,
+    kVisited,
+    kChanged,
+  };
+
+  // Size of instruction in code units.
+  uint16_t length_;
+  uint8_t flags_;
+};
+
+}  // namespace verifier
+}  // namespace art
+
+#endif  // ART_SRC_VERIFIER_METHOD_INSTRUCTION_FLAGS_H_
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index bcac374..56344cf 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -50,105 +50,7 @@
 
 static const bool gDebugVerify = false;
 
-class InsnFlags {
- public:
-  InsnFlags() : length_(0), flags_(0) {}
-
-  void SetLengthInCodeUnits(size_t length) {
-    CHECK_LT(length, 65536u);
-    length_ = length;
-  }
-  size_t GetLengthInCodeUnits() {
-    return length_;
-  }
-  bool IsOpcode() const {
-    return length_ != 0;
-  }
-
-  void SetInTry() {
-    flags_ |= 1 << kInTry;
-  }
-  void ClearInTry() {
-    flags_ &= ~(1 << kInTry);
-  }
-  bool IsInTry() const {
-    return (flags_ & (1 << kInTry)) != 0;
-  }
-
-  void SetBranchTarget() {
-    flags_ |= 1 << kBranchTarget;
-  }
-  void ClearBranchTarget() {
-    flags_ &= ~(1 << kBranchTarget);
-  }
-  bool IsBranchTarget() const {
-    return (flags_ & (1 << kBranchTarget)) != 0;
-  }
-
-  void SetGcPoint() {
-    flags_ |= 1 << kGcPoint;
-  }
-  void ClearGcPoint() {
-    flags_ &= ~(1 << kGcPoint);
-  }
-  bool IsGcPoint() const {
-    return (flags_ & (1 << kGcPoint)) != 0;
-  }
-
-  void SetVisited() {
-    flags_ |= 1 << kVisited;
-  }
-  void ClearVisited() {
-    flags_ &= ~(1 << kVisited);
-  }
-  bool IsVisited() const {
-    return (flags_ & (1 << kVisited)) != 0;
-  }
-
-  void SetChanged() {
-    flags_ |= 1 << kChanged;
-  }
-  void ClearChanged() {
-    flags_ &= ~(1 << kChanged);
-  }
-  bool IsChanged() const {
-    return (flags_ & (1 << kChanged)) != 0;
-  }
-
-  bool IsVisitedOrChanged() const {
-    return IsVisited() || IsChanged();
-  }
-
-  std::string Dump() {
-    char encoding[6];
-    if (!IsOpcode()) {
-      strncpy(encoding, "XXXXX", sizeof(encoding));
-    } else {
-      strncpy(encoding, "-----", sizeof(encoding));
-      if (IsInTry())        encoding[kInTry] = 'T';
-      if (IsBranchTarget()) encoding[kBranchTarget] = 'B';
-      if (IsGcPoint())      encoding[kGcPoint] = 'G';
-      if (IsVisited())      encoding[kVisited] = 'V';
-      if (IsChanged())      encoding[kChanged] = 'C';
-    }
-    return std::string(encoding);
-  }
-
- private:
-  enum {
-    kInTry,
-    kBranchTarget,
-    kGcPoint,
-    kVisited,
-    kChanged,
-  };
-
-  // Size of instruction in code units
-  uint16_t length_;
-  uint8_t flags_;
-};
-
-void PcToRegisterLineTable::Init(RegisterTrackingMode mode, InsnFlags* flags,
+void PcToRegisterLineTable::Init(RegisterTrackingMode mode, InstructionFlags* flags,
                                  uint32_t insns_size, uint16_t registers_size,
                                  MethodVerifier* verifier) {
   DCHECK_GT(insns_size, 0U);
@@ -357,20 +259,6 @@
   verifier.Dump(os);
 }
 
-std::vector<int32_t> MethodVerifier::DescribeVRegs(uint32_t dex_method_idx,
-                                                   const DexFile* dex_file,
-                                                   mirror::DexCache* dex_cache,
-                                                   mirror::ClassLoader* class_loader,
-                                                   uint32_t class_def_idx,
-                                                   const DexFile::CodeItem* code_item,
-                                                   mirror::AbstractMethod* method,
-                                                   uint32_t method_access_flags, uint32_t dex_pc) {
-  MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item,
-                          dex_method_idx, method, method_access_flags, true);
-  verifier.Verify();
-  return verifier.DescribeVRegs(dex_pc);
-}
-
 MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_cache,
                                mirror::ClassLoader* class_loader, uint32_t class_def_idx,
                                const DexFile::CodeItem* code_item,
@@ -435,7 +323,7 @@
     return false;
   }
   // Allocate and initialize an array to hold instruction data.
-  insn_flags_.reset(new InsnFlags[code_item_->insns_size_in_code_units_]());
+  insn_flags_.reset(new InstructionFlags[code_item_->insns_size_in_code_units_]());
   // Run through the instructions and see if the width checks out.
   bool result = ComputeWidthsAndCountOps();
   // Flag instructions guarded by a "try" block and check exception handlers.
@@ -1109,7 +997,7 @@
     if (reg_line != NULL) {
       indent_os << reg_line->Dump() << "\n";
     }
-    indent_os << StringPrintf("0x%04zx", dex_pc) << ": " << insn_flags_[dex_pc].Dump() << " ";
+    indent_os << StringPrintf("0x%04zx", dex_pc) << ": " << insn_flags_[dex_pc].ToString() << " ";
     const bool kDumpHexOfInstruction = false;
     if (kDumpHexOfInstruction) {
       indent_os << inst->DumpHex(5) << " ";
@@ -3228,7 +3116,7 @@
   return true;
 }
 
-InsnFlags* MethodVerifier::CurrentInsnFlags() {
+InstructionFlags* MethodVerifier::CurrentInsnFlags() {
   return &insn_flags_[work_insn_idx_];
 }
 
@@ -3421,7 +3309,7 @@
       result.push_back(kUndefined);
       result.push_back(0);
     } else {
-      CHECK(type.IsNonZeroReferenceTypes()) << type;
+      CHECK(type.IsNonZeroReferenceTypes());
       result.push_back(kReferenceVReg);
       result.push_back(0);
     }
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
index a36a1f9..4939217 100644
--- a/src/verifier/method_verifier.h
+++ b/src/verifier/method_verifier.h
@@ -17,8 +17,6 @@
 #ifndef ART_SRC_VERIFIER_METHOD_VERIFIER_H_
 #define ART_SRC_VERIFIER_METHOD_VERIFIER_H_
 
-#include <deque>
-#include <limits>
 #include <set>
 #include <vector>
 
@@ -28,6 +26,7 @@
 #include "compiler.h"
 #include "dex_file.h"
 #include "dex_instruction.h"
+#include "instruction_flags.h"
 #include "mirror/object.h"
 #include "reg_type.h"
 #include "reg_type_cache.h"
@@ -48,7 +47,6 @@
 namespace verifier {
 
 class MethodVerifier;
-class InsnFlags;
 class DexPcToReferenceMap;
 
 /*
@@ -125,7 +123,7 @@
   // Initialize the RegisterTable. Every instruction address can have a different set of information
   // about what's in which register, but for verification purposes we only need to store it at
   // branch target addresses (because we merge into that).
-  void Init(RegisterTrackingMode mode, InsnFlags* flags, uint32_t insns_size,
+  void Init(RegisterTrackingMode mode, InstructionFlags* flags, uint32_t insns_size,
             uint16_t registers_size, MethodVerifier* verifier);
 
   RegisterLine* GetLine(size_t idx) {
@@ -147,7 +145,6 @@
 #if defined(ART_USE_LLVM_COMPILER)
   typedef greenland::InferredRegCategoryMap InferredRegCategoryMap;
 #endif
-
  public:
   enum FailureKind {
     kNoFailure,
@@ -169,15 +166,6 @@
                                   mirror::AbstractMethod* method, uint32_t method_access_flags)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static std::vector<int32_t> DescribeVRegs(uint32_t dex_method_idx,
-                                            const DexFile* dex_file, mirror::DexCache* dex_cache,
-                                            mirror::ClassLoader* class_loader,
-                                            uint32_t class_def_idx,
-                                            const DexFile::CodeItem* code_item,
-                                            mirror::AbstractMethod* method,
-                                            uint32_t method_access_flags, uint32_t dex_pc)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   uint8_t EncodePcToReferenceMapData() const;
 
   uint32_t DexFileVersion() const {
@@ -228,14 +216,21 @@
     return can_load_classes_;
   }
 
- private:
-  explicit MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_cache,
-                          mirror::ClassLoader* class_loader, uint32_t class_def_idx,
-                          const DexFile::CodeItem* code_item,
-                          uint32_t method_idx, mirror::AbstractMethod* method, uint32_t access_flags,
-                          bool can_load_classes)
+  MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_cache,
+                 mirror::ClassLoader* class_loader, uint32_t class_def_idx,
+                 const DexFile::CodeItem* code_item,
+                 uint32_t method_idx, mirror::AbstractMethod* method,
+                 uint32_t access_flags, bool can_load_classes)
           SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Run verification on the method. Returns true if verification completes and false if the input
+  // has an irrecoverable corruption.
+  bool Verify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Describe VRegs at the given dex pc.
+  std::vector<int32_t> DescribeVRegs(uint32_t dex_pc);
+
+ private:
   // Adds the given string to the beginning of the last failure message.
   void PrependToLastFailMessage(std::string);
 
@@ -260,10 +255,6 @@
                                   mirror::AbstractMethod* method, uint32_t method_access_flags)
           SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  // Run verification on the method. Returns true if verification completes and false if the input
-  // has an irrecoverable corruption.
-  bool Verify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   void FindLocksAtDexPc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   /*
@@ -597,10 +588,7 @@
   // Compute sizes for GC map data
   void ComputeGcMapSizes(size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc);
 
-  // Describe VRegs at the given dex pc.
-  std::vector<int32_t> DescribeVRegs(uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  InsnFlags* CurrentInsnFlags();
+  InstructionFlags* CurrentInsnFlags();
 
   // All the GC maps that the verifier has created
   typedef SafeMap<const Compiler::MethodReference, const std::vector<uint8_t>*> DexGcMapTable;
@@ -652,7 +640,8 @@
   mirror::ClassLoader* class_loader_ GUARDED_BY(Locks::mutator_lock_);
   uint32_t class_def_idx_;  // The class def index of the declaring class of the method.
   const DexFile::CodeItem* code_item_;  // The code item containing the code for the method.
-  UniquePtr<InsnFlags[]> insn_flags_;  // Instruction widths and flags, one entry per code unit.
+  // Instruction widths and flags, one entry per code unit.
+  UniquePtr<InstructionFlags[]> insn_flags_;
 
   // The dex PC of a FindLocksAtDexPc request, -1 otherwise.
   uint32_t interesting_dex_pc_;