Add DCHECKs to ArenaVector and ScopedArenaVector.

Implement dchecked_vector<> template that DCHECK()s element
access and insert()/emplace()/erase() positions. Change the
ArenaVector<> and ScopedArenaVector<> aliases to use the new
template instead of std::vector<>. Remove DCHECK()s that
have now become unnecessary from the Optimizing compiler.

Change-Id: Ib8506bd30d223f68f52bd4476c76d9991acacadc
diff --git a/compiler/dwarf/debug_frame_opcode_writer.h b/compiler/dwarf/debug_frame_opcode_writer.h
index d8077d5..60241f7 100644
--- a/compiler/dwarf/debug_frame_opcode_writer.h
+++ b/compiler/dwarf/debug_frame_opcode_writer.h
@@ -31,8 +31,10 @@
 //  * Choose the most compact encoding of a given opcode.
 //  * Keep track of current state and convert absolute values to deltas.
 //  * Divide by header-defined factors as appropriate.
-template<typename Allocator = std::allocator<uint8_t> >
-class DebugFrameOpCodeWriter : private Writer<Allocator> {
+template<typename Vector = std::vector<uint8_t> >
+class DebugFrameOpCodeWriter : private Writer<Vector> {
+  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+
  public:
   // To save space, DWARF divides most offsets by header-defined factors.
   // They are used in integer divisions, so we make them constants.
@@ -288,11 +290,12 @@
 
   void SetCurrentCFAOffset(int offset) { current_cfa_offset_ = offset; }
 
-  using Writer<Allocator>::data;
+  using Writer<Vector>::data;
 
   DebugFrameOpCodeWriter(bool enabled = true,
-                         const Allocator& alloc = Allocator())
-      : Writer<Allocator>(&opcodes_),
+                         const typename Vector::allocator_type& alloc =
+                             typename Vector::allocator_type())
+      : Writer<Vector>(&opcodes_),
         enabled_(enabled),
         opcodes_(alloc),
         current_cfa_offset_(0),
@@ -318,7 +321,7 @@
   }
 
   bool enabled_;  // If disabled all writes are no-ops.
-  std::vector<uint8_t, Allocator> opcodes_;
+  Vector opcodes_;
   int current_cfa_offset_;
   int current_pc_;
   bool uses_dwarf3_features_;
diff --git a/compiler/dwarf/debug_info_entry_writer.h b/compiler/dwarf/debug_info_entry_writer.h
index f5b9ca5..d9b367b 100644
--- a/compiler/dwarf/debug_info_entry_writer.h
+++ b/compiler/dwarf/debug_info_entry_writer.h
@@ -29,9 +29,11 @@
 
 // 32-bit FNV-1a hash function which we use to find duplicate abbreviations.
 // See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
-template< typename Allocator >
+template <typename Vector>
 struct FNVHash {
-  size_t operator()(const std::vector<uint8_t, Allocator>& v) const {
+  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+
+  size_t operator()(const Vector& v) const {
     uint32_t hash = 2166136261u;
     for (size_t i = 0; i < v.size(); i++) {
       hash = (hash ^ v[i]) * 16777619u;
@@ -52,8 +54,10 @@
  *     EndTag();
  *   EndTag();
  */
-template< typename Allocator = std::allocator<uint8_t> >
-class DebugInfoEntryWriter FINAL : private Writer<Allocator> {
+template <typename Vector = std::vector<uint8_t>>
+class DebugInfoEntryWriter FINAL : private Writer<Vector> {
+  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+
  public:
   // Start debugging information entry.
   void StartTag(Tag tag, Children children) {
@@ -176,12 +180,13 @@
     return patch_locations_;
   }
 
-  using Writer<Allocator>::data;
+  using Writer<Vector>::data;
 
   DebugInfoEntryWriter(bool is64bitArch,
-                       std::vector<uint8_t, Allocator>* debug_abbrev,
-                       const Allocator& alloc = Allocator())
-      : Writer<Allocator>(&entries_),
+                       Vector* debug_abbrev,
+                       const typename Vector::allocator_type& alloc =
+                           typename Vector::allocator_type())
+      : Writer<Vector>(&entries_),
         debug_abbrev_(debug_abbrev),
         current_abbrev_(alloc),
         abbrev_codes_(alloc),
@@ -221,7 +226,7 @@
                                                   NextAbbrevCode()));
     int abbrev_code = it.first->second;
     if (UNLIKELY(it.second)) {  // Inserted new entry.
-      const std::vector<uint8_t, Allocator>& abbrev = it.first->first;
+      const Vector& abbrev = it.first->first;
       debug_abbrev_.Pop();  // Remove abbrev table terminator.
       debug_abbrev_.PushUleb128(abbrev_code);
       debug_abbrev_.PushData(abbrev.data(), abbrev.size());
@@ -234,13 +239,13 @@
 
  private:
   // Fields for writing and deduplication of abbrevs.
-  Writer<Allocator> debug_abbrev_;
-  std::vector<uint8_t, Allocator> current_abbrev_;
-  std::unordered_map<std::vector<uint8_t, Allocator>, int,
-                     FNVHash<Allocator> > abbrev_codes_;
+  Writer<Vector> debug_abbrev_;
+  Vector current_abbrev_;
+  std::unordered_map<Vector, int,
+                     FNVHash<Vector> > abbrev_codes_;
 
   // Fields for writing of debugging information entries.
-  std::vector<uint8_t, Allocator> entries_;
+  Vector entries_;
   bool is64bit_;
   int depth_ = 0;
   size_t abbrev_code_offset_ = 0;  // Location to patch once we know the code.
diff --git a/compiler/dwarf/debug_line_opcode_writer.h b/compiler/dwarf/debug_line_opcode_writer.h
index bdc25e4..201f0b4 100644
--- a/compiler/dwarf/debug_line_opcode_writer.h
+++ b/compiler/dwarf/debug_line_opcode_writer.h
@@ -30,8 +30,10 @@
 //  * Choose the most compact encoding of a given opcode.
 //  * Keep track of current state and convert absolute values to deltas.
 //  * Divide by header-defined factors as appropriate.
-template<typename Allocator = std::allocator<uint8_t>>
-class DebugLineOpCodeWriter FINAL : private Writer<Allocator> {
+template<typename Vector = std::vector<uint8_t>>
+class DebugLineOpCodeWriter FINAL : private Writer<Vector> {
+  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+
  public:
   static constexpr int kOpcodeBase = 13;
   static constexpr bool kDefaultIsStmt = true;
@@ -212,12 +214,13 @@
     return patch_locations_;
   }
 
-  using Writer<Allocator>::data;
+  using Writer<Vector>::data;
 
   DebugLineOpCodeWriter(bool use64bitAddress,
                         int codeFactorBits,
-                        const Allocator& alloc = Allocator())
-      : Writer<Allocator>(&opcodes_),
+                        const typename Vector::allocator_type& alloc =
+                            typename Vector::allocator_type())
+      : Writer<Vector>(&opcodes_),
         opcodes_(alloc),
         uses_dwarf3_features_(false),
         use_64bit_address_(use64bitAddress),
@@ -234,7 +237,7 @@
     return offset >> code_factor_bits_;
   }
 
-  std::vector<uint8_t, Allocator> opcodes_;
+  Vector opcodes_;
   bool uses_dwarf3_features_;
   bool use_64bit_address_;
   int code_factor_bits_;
diff --git a/compiler/dwarf/headers.h b/compiler/dwarf/headers.h
index ae57755..b7eff19 100644
--- a/compiler/dwarf/headers.h
+++ b/compiler/dwarf/headers.h
@@ -36,21 +36,23 @@
 // In particular, it is not related to machine architecture.
 
 // Write common information entry (CIE) to .debug_frame or .eh_frame section.
-template<typename Allocator>
+template<typename Vector>
 void WriteDebugFrameCIE(bool is64bit,
                         ExceptionHeaderValueApplication address_type,
                         Reg return_address_register,
-                        const DebugFrameOpCodeWriter<Allocator>& opcodes,
+                        const DebugFrameOpCodeWriter<Vector>& opcodes,
                         CFIFormat format,
                         std::vector<uint8_t>* debug_frame) {
+  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+
   Writer<> writer(debug_frame);
   size_t cie_header_start_ = writer.data()->size();
   writer.PushUint32(0);  // Length placeholder.
   writer.PushUint32((format == DW_EH_FRAME_FORMAT) ? 0 : 0xFFFFFFFF);  // CIE id.
   writer.PushUint8(1);   // Version.
   writer.PushString("zR");
-  writer.PushUleb128(DebugFrameOpCodeWriter<Allocator>::kCodeAlignmentFactor);
-  writer.PushSleb128(DebugFrameOpCodeWriter<Allocator>::kDataAlignmentFactor);
+  writer.PushUleb128(DebugFrameOpCodeWriter<Vector>::kCodeAlignmentFactor);
+  writer.PushSleb128(DebugFrameOpCodeWriter<Vector>::kDataAlignmentFactor);
   writer.PushUleb128(return_address_register.num());  // ubyte in DWARF2.
   writer.PushUleb128(1);  // z: Augmentation data size.
   if (is64bit) {
@@ -74,13 +76,15 @@
 }
 
 // Write frame description entry (FDE) to .debug_frame or .eh_frame section.
-template<typename Allocator>
+template<typename Vector>
 void WriteDebugFrameFDE(bool is64bit, size_t cie_offset,
                         uint64_t initial_address, uint64_t address_range,
-                        const std::vector<uint8_t, Allocator>* opcodes,
+                        const Vector* opcodes,
                         CFIFormat format,
                         std::vector<uint8_t>* debug_frame,
                         std::vector<uintptr_t>* debug_frame_patches) {
+  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+
   Writer<> writer(debug_frame);
   size_t fde_header_start = writer.data()->size();
   writer.PushUint32(0);  // Length placeholder.
@@ -107,11 +111,13 @@
 }
 
 // Write compilation unit (CU) to .debug_info section.
-template<typename Allocator>
+template<typename Vector>
 void WriteDebugInfoCU(uint32_t debug_abbrev_offset,
-                      const DebugInfoEntryWriter<Allocator>& entries,
+                      const DebugInfoEntryWriter<Vector>& entries,
                       std::vector<uint8_t>* debug_info,
                       std::vector<uintptr_t>* debug_info_patches) {
+  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+
   Writer<> writer(debug_info);
   size_t start = writer.data()->size();
   writer.PushUint32(0);  // Length placeholder.
@@ -135,12 +141,14 @@
 };
 
 // Write line table to .debug_line section.
-template<typename Allocator>
+template<typename Vector>
 void WriteDebugLineTable(const std::vector<std::string>& include_directories,
                          const std::vector<FileEntry>& files,
-                         const DebugLineOpCodeWriter<Allocator>& opcodes,
+                         const DebugLineOpCodeWriter<Vector>& opcodes,
                          std::vector<uint8_t>* debug_line,
                          std::vector<uintptr_t>* debug_line_patches) {
+  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+
   Writer<> writer(debug_line);
   size_t header_start = writer.data()->size();
   writer.PushUint32(0);  // Section-length placeholder.
@@ -151,13 +159,13 @@
   size_t header_length_pos = writer.data()->size();
   writer.PushUint32(0);  // Header-length placeholder.
   writer.PushUint8(1 << opcodes.GetCodeFactorBits());
-  writer.PushUint8(DebugLineOpCodeWriter<Allocator>::kDefaultIsStmt ? 1 : 0);
-  writer.PushInt8(DebugLineOpCodeWriter<Allocator>::kLineBase);
-  writer.PushUint8(DebugLineOpCodeWriter<Allocator>::kLineRange);
-  writer.PushUint8(DebugLineOpCodeWriter<Allocator>::kOpcodeBase);
-  static const int opcode_lengths[DebugLineOpCodeWriter<Allocator>::kOpcodeBase] = {
+  writer.PushUint8(DebugLineOpCodeWriter<Vector>::kDefaultIsStmt ? 1 : 0);
+  writer.PushInt8(DebugLineOpCodeWriter<Vector>::kLineBase);
+  writer.PushUint8(DebugLineOpCodeWriter<Vector>::kLineRange);
+  writer.PushUint8(DebugLineOpCodeWriter<Vector>::kOpcodeBase);
+  static const int opcode_lengths[DebugLineOpCodeWriter<Vector>::kOpcodeBase] = {
       0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 };
-  for (int i = 1; i < DebugLineOpCodeWriter<Allocator>::kOpcodeBase; i++) {
+  for (int i = 1; i < DebugLineOpCodeWriter<Vector>::kOpcodeBase; i++) {
     writer.PushUint8(opcode_lengths[i]);
   }
   for (const std::string& directory : include_directories) {
diff --git a/compiler/dwarf/writer.h b/compiler/dwarf/writer.h
index e703aee..42c32c4 100644
--- a/compiler/dwarf/writer.h
+++ b/compiler/dwarf/writer.h
@@ -26,8 +26,10 @@
 namespace dwarf {
 
 // The base class for all DWARF writers.
-template<typename Allocator = std::allocator<uint8_t>>
+template <typename Vector = std::vector<uint8_t>>
 class Writer {
+  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
+
  public:
   void PushUint8(int value) {
     DCHECK_GE(value, 0);
@@ -116,8 +118,9 @@
     data_->insert(data_->end(), p, p + size);
   }
 
-  template<typename Allocator2>
-  void PushData(const std::vector<uint8_t, Allocator2>* buffer) {
+  template<typename Vector2>
+  void PushData(const Vector2* buffer) {
+    static_assert(std::is_same<typename Vector2::value_type, uint8_t>::value, "Invalid value type");
     data_->insert(data_->end(), buffer->begin(), buffer->end());
   }
 
@@ -155,14 +158,14 @@
     data_->resize(RoundUp(data_->size(), alignment), 0);
   }
 
-  const std::vector<uint8_t, Allocator>* data() const {
+  const Vector* data() const {
     return data_;
   }
 
-  explicit Writer(std::vector<uint8_t, Allocator>* buffer) : data_(buffer) { }
+  explicit Writer(Vector* buffer) : data_(buffer) { }
 
  private:
-  std::vector<uint8_t, Allocator>* data_;
+  Vector* const data_;
 
   DISALLOW_COPY_AND_ASSIGN(Writer);
 };