Use statically-initialised std::vectors for decoder data

Replace fixed size arrays with std::vector for static data used by the decoder,
and store const references rather than copies in each decoding node.
diff --git a/src/aarch64/decoder-aarch64.cc b/src/aarch64/decoder-aarch64.cc
index a84ce6a..a4e2989 100644
--- a/src/aarch64/decoder-aarch64.cc
+++ b/src/aarch64/decoder-aarch64.cc
@@ -70,7 +70,7 @@
     // Add a node for each instruction form named, identified by having no '_'
     // prefix on the node name.
     const DecodeMapping& map = kDecodeMapping[i];
-    for (unsigned j = 0; j < kMaxDecodeMappings; j++) {
+    for (unsigned j = 0; j < map.mapping.size(); j++) {
       if ((map.mapping[j].handler != NULL) &&
           (map.mapping[j].handler[0] != '_')) {
         AddDecodeNode(DecodeNode(map.mapping[j].handler, this));
@@ -142,30 +142,9 @@
   }
 }
 
-void DecodeNode::SetSampledBits(const uint8_t* bits, int bit_count) {
-  VIXL_ASSERT(!IsCompiled());
-
-  sampled_bits_.resize(bit_count);
-  for (int i = 0; i < bit_count; i++) {
-    sampled_bits_[i] = bits[i];
-  }
-}
-
-std::vector<uint8_t> DecodeNode::GetSampledBits() const {
-  return sampled_bits_;
-}
-
-size_t DecodeNode::GetSampledBitsCount() const { return sampled_bits_.size(); }
-
-void DecodeNode::AddPatterns(const DecodePattern* patterns) {
-  VIXL_ASSERT(!IsCompiled());
-  for (unsigned i = 0; i < kMaxDecodeMappings; i++) {
-    // Empty string indicates end of patterns.
-    if (patterns[i].pattern == 0) break;
-    VIXL_ASSERT(GetPatternLength(patterns[i].pattern) == GetSampledBitsCount());
-    pattern_table_.push_back(patterns[i]);
-  }
-}
+// Initialise empty vectors for sampled bits and pattern table.
+const std::vector<uint8_t> DecodeNode::kEmptySampledBits;
+const std::vector<DecodePattern> DecodeNode::kEmptyPatternTable;
 
 void DecodeNode::CompileNodeForBits(Decoder* decoder,
                                     std::string name,
@@ -434,7 +413,7 @@
       // value test.
       uint32_t single_decode_mask = 0;
       uint32_t single_decode_value = 0;
-      std::vector<uint8_t> bits = GetSampledBits();
+      const std::vector<uint8_t>& bits = GetSampledBits();
 
       // Construct the instruction mask and value from the pattern.
       VIXL_ASSERT(bits.size() == GetPatternLength(pattern_table_[0].pattern));
@@ -454,9 +433,7 @@
 
       // Set DecodeNode for when the instruction after masking doesn't match the
       // value.
-      const char* doesnt_match_handler =
-          (table_size == 1) ? "unallocated" : pattern_table_[1].handler;
-      CompileNodeForBits(decoder, doesnt_match_handler, 0);
+      CompileNodeForBits(decoder, "unallocated", 0);
 
       // Set DecodeNode for when it does match.
       CompileNodeForBits(decoder, pattern_table_[0].handler, 1);
@@ -545,7 +522,7 @@
 }
 
 uint32_t DecodeNode::GenerateOrderedPattern(uint32_t pattern) const {
-  std::vector<uint8_t> sampled_bits = GetSampledBits();
+  const std::vector<uint8_t>& sampled_bits = GetSampledBits();
   uint64_t temp = 0xffffffffffffffff;
 
   // Place symbols into the field of set bits. Symbols are two bits wide and
@@ -578,10 +555,9 @@
 }
 
 uint32_t DecodeNode::GenerateSampledBitsMask() const {
-  std::vector<uint8_t> sampled_bits = GetSampledBits();
   uint32_t mask = 0;
-  for (size_t i = 0; i < sampled_bits.size(); i++) {
-    mask |= 1 << sampled_bits[i];
+  for (int bit : GetSampledBits()) {
+    mask |= 1 << bit;
   }
   return mask;
 }
diff --git a/src/aarch64/decoder-aarch64.h b/src/aarch64/decoder-aarch64.h
index 99fb644..22c66e8 100644
--- a/src/aarch64/decoder-aarch64.h
+++ b/src/aarch64/decoder-aarch64.h
@@ -394,8 +394,6 @@
   std::map<std::string, DecodeNode> decode_nodes_;
 };
 
-const int kMaxDecodeSampledBits = 24;
-const int kMaxDecodeMappings = 280;
 typedef void (Decoder::*DecodeFnPtr)(const Instruction*);
 typedef uint32_t (Instruction::*BitExtractFn)(void) const;
 
@@ -425,8 +423,8 @@
 // sampled bits match to the corresponding name of a node.
 struct DecodeMapping {
   const char* name;
-  const uint8_t sampled_bits[kMaxDecodeSampledBits];
-  const DecodePattern mapping[kMaxDecodeMappings];
+  const std::vector<uint8_t> sampled_bits;
+  const std::vector<DecodePattern> mapping;
 };
 
 // For speed, before nodes can be used for decoding instructions, they must
@@ -512,29 +510,35 @@
 class DecodeNode {
  public:
   // Default constructor needed for map initialisation.
-  DecodeNode() : compiled_node_(NULL) {}
+  DecodeNode()
+      : sampled_bits_(DecodeNode::kEmptySampledBits),
+        pattern_table_(DecodeNode::kEmptyPatternTable),
+        compiled_node_(NULL) {}
 
   // Constructor for DecodeNode wrappers around visitor functions. These are
   // marked as "compiled", as there is no decoding left to do.
   explicit DecodeNode(const std::string& iname, Decoder* decoder)
       : name_(iname),
+        sampled_bits_(DecodeNode::kEmptySampledBits),
         instruction_name_(iname),
+        pattern_table_(DecodeNode::kEmptyPatternTable),
         decoder_(decoder),
         compiled_node_(NULL) {}
 
   // Constructor for DecodeNodes that map bit patterns to other DecodeNodes.
   explicit DecodeNode(const DecodeMapping& map, Decoder* decoder = NULL)
       : name_(map.name),
+        sampled_bits_(map.sampled_bits),
         instruction_name_("node"),
+        pattern_table_(map.mapping),
         decoder_(decoder),
         compiled_node_(NULL) {
-    // The length of the bit string in the first mapping determines the number
-    // of sampled bits. When adding patterns later, we assert that all mappings
-    // sample the same number of bits.
-    size_t bit_count = GetPatternLength(map.mapping[0].pattern);
-    VIXL_CHECK(bit_count <= 32);
-    SetSampledBits(map.sampled_bits, static_cast<int>(bit_count));
-    AddPatterns(map.mapping);
+    // With the current two bits per symbol encoding scheme, the maximum pattern
+    // length is (32 - 2) / 2 = 15 bits.
+    VIXL_CHECK(GetPatternLength(map.mapping[0].pattern) <= 15);
+    for (const DecodePattern& p : map.mapping) {
+      VIXL_CHECK(GetPatternLength(p.pattern) == map.sampled_bits.size());
+    }
   }
 
   ~DecodeNode() {
@@ -544,17 +548,11 @@
     }
   }
 
-  // Set the bits sampled from the instruction by this node.
-  void SetSampledBits(const uint8_t* bits, int bit_count);
-
   // Get the bits sampled from the instruction by this node.
-  std::vector<uint8_t> GetSampledBits() const;
+  const std::vector<uint8_t>& GetSampledBits() const { return sampled_bits_; }
 
   // Get the number of bits sampled from the instruction by this node.
-  size_t GetSampledBitsCount() const;
-
-  // Add patterns to this node's internal pattern table.
-  void AddPatterns(const DecodePattern* patterns);
+  size_t GetSampledBitsCount() const { return sampled_bits_.size(); }
 
   // A leaf node is a DecodeNode that wraps the visitor function for the
   // identified instruction class.
@@ -671,14 +669,16 @@
 
   // Vector of bits sampled from an instruction to determine which node to look
   // up next in the decode process.
-  std::vector<uint8_t> sampled_bits_;
+  const std::vector<uint8_t>& sampled_bits_;
+  static const std::vector<uint8_t> kEmptySampledBits;
 
   // For leaf nodes, this is the name of the instruction form that the node
   // represents. For other nodes, this is always set to "node".
   std::string instruction_name_;
 
   // Source mapping from bit pattern to name of next decode stage.
-  std::vector<DecodePattern> pattern_table_;
+  const std::vector<DecodePattern>& pattern_table_;
+  static const std::vector<DecodePattern> kEmptyPatternTable;
 
   // Pointer to the decoder containing this node, used to call its visitor
   // function for leaf nodes.