Reduce memory allocation in verifier.

Remove the use of a map PcToRegisterLineTable for efficiency (matches Dalvik).
Place the register line register values inside the RegisterLine, saves a
secondary allocation and indirection.
Avoid the use of a deque in RegisterLine to avoid an allocation.
Simplify the SirtRef destructor in non-debug builds.
Saves >100ms from the two threaded compile time of ThinkFree on host.

Change-Id: I2dacba61dbaf284ca02d4c194413e1da221dcb76
diff --git a/runtime/sirt_ref.h b/runtime/sirt_ref.h
index 25d6fb3..a1f8a66 100644
--- a/runtime/sirt_ref.h
+++ b/runtime/sirt_ref.h
@@ -30,7 +30,8 @@
     self_->PushSirt(&sirt_);
   }
   ~SirtRef() {
-    CHECK_EQ(self_->PopSirt(), &sirt_);
+    StackIndirectReferenceTable* top_sirt = self_->PopSirt();
+    DCHECK_EQ(top_sirt, &sirt_);
   }
 
   T& operator*() const { return *get(); }
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 4442ee1..6b13517 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -51,7 +51,8 @@
                                  uint32_t insns_size, uint16_t registers_size,
                                  MethodVerifier* verifier) {
   DCHECK_GT(insns_size, 0U);
-
+  register_lines_.reset(new RegisterLine*[insns_size]());
+  size_ = insns_size;
   for (uint32_t i = 0; i < insns_size; i++) {
     bool interesting = false;
     switch (mode) {
@@ -68,7 +69,16 @@
         break;
     }
     if (interesting) {
-      pc_to_register_line_.Put(i, new RegisterLine(registers_size, verifier));
+      register_lines_[i] = RegisterLine::Create(registers_size, verifier);
+    }
+  }
+}
+
+PcToRegisterLineTable::~PcToRegisterLineTable() {
+  for (size_t i = 0; i < size_; i++) {
+    delete register_lines_[i];
+    if (kIsDebugBuild) {
+      register_lines_[i] = nullptr;
     }
   }
 }
@@ -1035,8 +1045,8 @@
                   this);
 
 
-  work_line_.reset(new RegisterLine(registers_size, this));
-  saved_line_.reset(new RegisterLine(registers_size, this));
+  work_line_.reset(RegisterLine::Create(registers_size, this));
+  saved_line_.reset(RegisterLine::Create(registers_size, this));
 
   /* Initialize register types of method arguments. */
   if (!SetTypesFromSignature()) {
@@ -1936,7 +1946,7 @@
 
         if (!cast_type.IsUnresolvedTypes() && !orig_type.IsUnresolvedTypes() &&
             !cast_type.GetClass()->IsInterface() && !cast_type.IsAssignableFrom(orig_type)) {
-          RegisterLine* update_line = new RegisterLine(code_item_->registers_size_, this);
+          RegisterLine* update_line = RegisterLine::Create(code_item_->registers_size_, this);
           if (inst->Opcode() == Instruction::IF_EQZ) {
             fallthrough_line.reset(update_line);
           } else {
@@ -3818,7 +3828,7 @@
     }
   } else {
     UniquePtr<RegisterLine> copy(gDebugVerify ?
-                                 new RegisterLine(target_line->NumRegs(), this) :
+                                 RegisterLine::Create(target_line->NumRegs(), this) :
                                  NULL);
     if (gDebugVerify) {
       copy->CopyFromLine(target_line);
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index f143751..7f33741 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -110,10 +110,8 @@
 // execution of that instruction.
 class PcToRegisterLineTable {
  public:
-  PcToRegisterLineTable() {}
-  ~PcToRegisterLineTable() {
-    STLDeleteValues(&pc_to_register_line_);
-  }
+  PcToRegisterLineTable() : size_(0) {}
+  ~PcToRegisterLineTable();
 
   // 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
@@ -122,17 +120,13 @@
             uint16_t registers_size, MethodVerifier* verifier);
 
   RegisterLine* GetLine(size_t idx) {
-    auto result = pc_to_register_line_.find(idx);
-    if (result == pc_to_register_line_.end()) {
-      return NULL;
-    } else {
-      return result->second;
-    }
+    DCHECK_LT(idx, size_);
+    return register_lines_[idx];
   }
 
  private:
-  typedef SafeMap<int32_t, RegisterLine*> Table;
-  Table pc_to_register_line_;
+  UniquePtr<RegisterLine*[]> register_lines_;
+  size_t size_;
 };
 
 // The verifier
diff --git a/runtime/verifier/register_line.cc b/runtime/verifier/register_line.cc
index a615cc1..1a41657 100644
--- a/runtime/verifier/register_line.cc
+++ b/runtime/verifier/register_line.cc
@@ -456,8 +456,7 @@
 
 bool RegisterLine::MergeRegisters(const RegisterLine* incoming_line) {
   bool changed = false;
-  CHECK(NULL != incoming_line);
-  CHECK(NULL != line_.get());
+  DCHECK(incoming_line != nullptr);
   for (size_t idx = 0; idx < num_regs_; idx++) {
     if (line_[idx] != incoming_line->line_[idx]) {
       const RegType& incoming_reg_type = incoming_line->GetRegisterType(idx);
diff --git a/runtime/verifier/register_line.h b/runtime/verifier/register_line.h
index f19dcca..8b2dadb 100644
--- a/runtime/verifier/register_line.h
+++ b/runtime/verifier/register_line.h
@@ -17,7 +17,6 @@
 #ifndef ART_RUNTIME_VERIFIER_REGISTER_LINE_H_
 #define ART_RUNTIME_VERIFIER_REGISTER_LINE_H_
 
-#include <deque>
 #include <vector>
 
 #include "dex_instruction.h"
@@ -51,12 +50,10 @@
 // stack of entered monitors (identified by code unit offset).
 class RegisterLine {
  public:
-  RegisterLine(size_t num_regs, MethodVerifier* verifier)
-      : line_(new uint16_t[num_regs]),
-        verifier_(verifier),
-        num_regs_(num_regs) {
-    memset(line_.get(), 0, num_regs_ * sizeof(uint16_t));
-    SetResultTypeToUnknown();
+  static RegisterLine* Create(size_t num_regs, MethodVerifier* verifier) {
+    uint8_t* memory = new uint8_t[sizeof(RegisterLine) + (num_regs * sizeof(uint16_t))];
+    RegisterLine* rl = new (memory) RegisterLine(num_regs, verifier);
+    return rl;
   }
 
   // Implement category-1 "move" instructions. Copy a 32-bit value from "vsrc" to "vdst".
@@ -108,7 +105,7 @@
 
   void CopyFromLine(const RegisterLine* src) {
     DCHECK_EQ(num_regs_, src->num_regs_);
-    memcpy(line_.get(), src->line_.get(), num_regs_ * sizeof(uint16_t));
+    memcpy(&line_, &src->line_, num_regs_ * sizeof(uint16_t));
     monitors_ = src->monitors_;
     reg_to_lock_depths_ = src->reg_to_lock_depths_;
   }
@@ -116,7 +113,7 @@
   std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void FillWithGarbage() {
-    memset(line_.get(), 0xf1, num_regs_ * sizeof(uint16_t));
+    memset(&line_, 0xf1, num_regs_ * sizeof(uint16_t));
     while (!monitors_.empty()) {
       monitors_.pop_back();
     }
@@ -161,7 +158,7 @@
   int CompareLine(const RegisterLine* line2) const {
     DCHECK(monitors_ == line2->monitors_);
     // TODO: DCHECK(reg_to_lock_depths_ == line2->reg_to_lock_depths_);
-    return memcmp(line_.get(), line2->line_.get(), num_regs_ * sizeof(uint16_t));
+    return memcmp(&line_, &line2->line_, num_regs_ * sizeof(uint16_t));
   }
 
   size_t NumRegs() const {
@@ -339,23 +336,30 @@
     reg_to_lock_depths_.erase(reg);
   }
 
+  RegisterLine(size_t num_regs, MethodVerifier* verifier)
+      : verifier_(verifier),
+        num_regs_(num_regs) {
+    memset(&line_, 0, num_regs_ * sizeof(uint16_t));
+    SetResultTypeToUnknown();
+  }
+
   // Storage for the result register's type, valid after an invocation
   uint16_t result_[2];
 
-  // An array of RegType Ids associated with each dex register
-  UniquePtr<uint16_t[]> line_;
-
   // Back link to the verifier
   MethodVerifier* verifier_;
 
   // Length of reg_types_
   const uint32_t num_regs_;
   // A stack of monitor enter locations
-  std::deque<uint32_t> monitors_;
+  std::vector<uint32_t> monitors_;
   // A map from register to a bit vector of indices into the monitors_ stack. As we pop the monitor
   // stack we verify that monitor-enter/exit are correctly nested. That is, if there was a
   // monitor-enter on v5 and then on v6, we expect the monitor-exit to be on v6 then on v5
   SafeMap<uint32_t, uint32_t> reg_to_lock_depths_;
+
+  // An array of RegType Ids associated with each dex register.
+  uint16_t line_[0];
 };
 std::ostream& operator<<(std::ostream& os, const RegisterLine& rhs);