Ensure method GC maps are setup during runtime verification

Change-Id: Icd5013710a269cc6df439e36c534a8d40c1e3324
diff --git a/src/compiled_method.cc b/src/compiled_method.cc
index 40230b4..ca7858a 100644
--- a/src/compiled_method.cc
+++ b/src/compiled_method.cc
@@ -50,22 +50,7 @@
   CHECK_NE(mapping_table_.size(), 0U);
   CHECK_NE(vmap_table_.size(), 0U);
 
-  std::vector<uint8_t> length_prefixed_gc_map;
-  length_prefixed_gc_map.push_back((gc_map.size() & 0xff000000) >> 24);
-  length_prefixed_gc_map.push_back((gc_map.size() & 0x00ff0000) >> 16);
-  length_prefixed_gc_map.push_back((gc_map.size() & 0x0000ff00) >> 8);
-  length_prefixed_gc_map.push_back((gc_map.size() & 0x000000ff) >> 0);
-  length_prefixed_gc_map.insert(length_prefixed_gc_map.end(),
-                                gc_map.begin(),
-                                gc_map.end());
-  DCHECK_EQ(gc_map.size() + 4, length_prefixed_gc_map.size());
-  DCHECK_EQ(gc_map.size(),
-            static_cast<size_t>((length_prefixed_gc_map[0] << 24) |
-                                (length_prefixed_gc_map[1] << 16) |
-                                (length_prefixed_gc_map[2] << 8) |
-                                (length_prefixed_gc_map[3] << 0)));
-
-  gc_map_ = length_prefixed_gc_map;
+  gc_map_ = gc_map;
 }
 
 CompiledMethod::CompiledMethod(InstructionSet instruction_set,
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index c219042..deffdc2 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -24,7 +24,22 @@
 static const bool gDebugVerify = false;
 
 std::ostream& operator<<(std::ostream& os, const VerifyError& rhs) {
-  return os << (int)rhs;
+  switch (rhs) {
+  case VERIFY_ERROR_NONE: os << "VERIFY_ERROR_NONE"; break;
+  case VERIFY_ERROR_GENERIC: os << "VERIFY_ERROR_GENERIC"; break;
+  case VERIFY_ERROR_NO_CLASS: os << "VERIFY_ERROR_NO_CLASS"; break;
+  case VERIFY_ERROR_NO_FIELD: os << "VERIFY_ERROR_NO_FIELD"; break;
+  case VERIFY_ERROR_NO_METHOD: os << "VERIFY_ERROR_NO_METHOD"; break;
+  case VERIFY_ERROR_ACCESS_CLASS: os << "VERIFY_ERROR_ACCESS_CLASS"; break;
+  case VERIFY_ERROR_ACCESS_FIELD: os << "VERIFY_ERROR_ACCESS_FIELD"; break;
+  case VERIFY_ERROR_ACCESS_METHOD: os << "VERIFY_ERROR_ACCESS_METHOD"; break;
+  case VERIFY_ERROR_CLASS_CHANGE: os << "VERIFY_ERROR_CLASS_CHANGE"; break;
+  case VERIFY_ERROR_INSTANTIATION: os << "VERIFY_ERROR_INSTANTIATION"; break;
+  default:
+    os << "VerifyError[" << static_cast<int>(rhs) << "]";
+    break;
+  }
+  return os;
 }
 
 static const char* type_strings[] = {
@@ -941,6 +956,8 @@
 bool DexVerifier::VerifyMethod(Method* method) {
   DexVerifier verifier(method);
   bool success = verifier.Verify();
+  CHECK_EQ(success, verifier.failure_ == VERIFY_ERROR_NONE);
+
   // We expect either success and no verification error, or failure and a generic failure to
   // reject the class.
   if (success) {
@@ -1496,6 +1513,24 @@
   return true;
 }
 
+const std::vector<uint8_t>* CreateLengthPrefixedGcMap(const std::vector<uint8_t>& gc_map) {
+  std::vector<uint8_t>* length_prefixed_gc_map = new std::vector<uint8_t>;
+  length_prefixed_gc_map->push_back((gc_map.size() & 0xff000000) >> 24);
+  length_prefixed_gc_map->push_back((gc_map.size() & 0x00ff0000) >> 16);
+  length_prefixed_gc_map->push_back((gc_map.size() & 0x0000ff00) >> 8);
+  length_prefixed_gc_map->push_back((gc_map.size() & 0x000000ff) >> 0);
+  length_prefixed_gc_map->insert(length_prefixed_gc_map->end(),
+                                 gc_map.begin(),
+                                 gc_map.end());
+  DCHECK_EQ(gc_map.size() + 4, length_prefixed_gc_map->size());
+  DCHECK_EQ(gc_map.size(),
+            static_cast<size_t>((length_prefixed_gc_map->at(0) << 24) |
+                                (length_prefixed_gc_map->at(1) << 16) |
+                                (length_prefixed_gc_map->at(2) << 8) |
+                                (length_prefixed_gc_map->at(3) << 0)));
+  return length_prefixed_gc_map;
+}
+
 bool DexVerifier::VerifyCodeFlow() {
   uint16_t registers_size = code_item_->registers_size_;
   uint32_t insns_size = code_item_->insns_size_in_code_units_;
@@ -1519,19 +1554,23 @@
   }
   /* Perform code flow verification. */
   if (!CodeFlowVerifyMethod()) {
+    DCHECK_NE(failure_, VERIFY_ERROR_NONE);
     return false;
   }
 
   /* Generate a register map and add it to the method. */
-  const std::vector<uint8_t>* map = GenerateGcMap();
-  if (map == NULL) {
+  UniquePtr<const std::vector<uint8_t> > map(GenerateGcMap());
+  if (map.get() == NULL) {
+    DCHECK_NE(failure_, VERIFY_ERROR_NONE);
     return false;  // Not a real failure, but a failure to encode
   }
-  Compiler::MethodReference ref(dex_file_, method_->GetDexMethodIndex());
-  verifier::DexVerifier::SetGcMap(ref, *map);
 #ifndef NDEBUG
   VerifyGcMap(*map);
 #endif
+  const std::vector<uint8_t>* gc_map = CreateLengthPrefixedGcMap(*(map.get()));
+  Compiler::MethodReference ref(dex_file_, method_->GetDexMethodIndex());
+  verifier::DexVerifier::SetGcMap(ref, *gc_map);
+  method_->SetGcMap(&gc_map->at(0));
   return true;
 }