Merge "Move --dump-cfg and dump-cfg-append to CompilerOptions."
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc
index dd50f69..3e64762 100644
--- a/compiler/elf_writer_debug.cc
+++ b/compiler/elf_writer_debug.cc
@@ -653,6 +653,21 @@
             info_.EndTag();  // DW_TAG_member.
           }
 
+          if (type->IsStringClass()) {
+            // Emit debug info about an artifical class member for java.lang.String which represents
+            // the first element of the data stored in a string instance. Consumers of the debug
+            // info will be able to read the content of java.lang.String based on the count (real
+            // field) and based on the location of this data member.
+            info_.StartTag(DW_TAG_member);
+            WriteName("value");
+            // We don't support fields with C like array types so we just say its type is java char.
+            WriteLazyType("C");  // char.
+            info_.WriteUdata(DW_AT_data_member_location,
+                             mirror::String::ValueOffset().Uint32Value());
+            info_.WriteSdata(DW_AT_accessibility, DW_ACCESS_private);
+            info_.EndTag();  // DW_TAG_member.
+          }
+
           EndClassTag(desc);
         }
       }
@@ -883,6 +898,8 @@
         info_.EndTag();
       } else {
         // Primitive types.
+        DCHECK_EQ(desc.size(), 1u);
+
         const char* name;
         uint32_t encoding;
         uint32_t byte_size;
@@ -1226,26 +1243,8 @@
   std::vector<uintptr_t> debug_line_patches;
 };
 
-// Get all types loaded by the runtime.
-static std::vector<mirror::Class*> GetLoadedRuntimeTypes() SHARED_REQUIRES(Locks::mutator_lock_) {
-  std::vector<mirror::Class*> result;
-  class CollectClasses : public ClassVisitor {
-   public:
-    virtual bool Visit(mirror::Class* klass) {
-      classes_->push_back(klass);
-      return true;
-    }
-    std::vector<mirror::Class*>* classes_;
-  };
-  CollectClasses visitor;
-  visitor.classes_ = &result;
-  Runtime::Current()->GetClassLinker()->VisitClasses(&visitor);
-  return result;
-}
-
 template<typename ElfTypes>
 static void WriteDebugSections(ElfBuilder<ElfTypes>* builder,
-                               bool write_loaded_runtime_types,
                                const ArrayRef<const MethodDebugInfo>& method_infos) {
   // Group the methods into compilation units based on source file.
   std::vector<CompilationUnit> compilation_units;
@@ -1274,19 +1273,12 @@
   }
 
   // Write .debug_info section.
-  if (!compilation_units.empty() || write_loaded_runtime_types) {
+  if (!compilation_units.empty()) {
     DebugInfoWriter<ElfTypes> info_writer(builder);
     info_writer.Start();
     for (const auto& compilation_unit : compilation_units) {
       info_writer.WriteCompilationUnit(compilation_unit);
     }
-    if (write_loaded_runtime_types) {
-      Thread* self = Thread::Current();
-      // The lock prevents the classes being moved by the GC.
-      ReaderMutexLock mu(self, *Locks::mutator_lock_);
-      std::vector<mirror::Class*> types = GetLoadedRuntimeTypes();
-      info_writer.WriteTypes(ArrayRef<mirror::Class*>(types.data(), types.size()));
-    }
     info_writer.End();
   }
 }
@@ -1353,7 +1345,6 @@
 
 template <typename ElfTypes>
 void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,
-                    bool write_loaded_runtime_types,
                     const ArrayRef<const MethodDebugInfo>& method_infos,
                     CFIFormat cfi_format) {
   // Add methods to .symtab.
@@ -1361,7 +1352,7 @@
   // Generate CFI (stack unwinding information).
   WriteCFISection(builder, method_infos, cfi_format);
   // Write DWARF .debug_* sections.
-  WriteDebugSections(builder, write_loaded_runtime_types, method_infos);
+  WriteDebugSections(builder, method_infos);
 }
 
 template <typename ElfTypes>
@@ -1374,7 +1365,6 @@
   std::unique_ptr<ElfBuilder<ElfTypes>> builder(new ElfBuilder<ElfTypes>(isa, &out));
   builder->Start();
   WriteDebugInfo(builder.get(),
-                 false,
                  ArrayRef<const MethodDebugInfo>(&method_info, 1),
                  DW_DEBUG_FRAME_FORMAT);
   builder->End();
@@ -1396,8 +1386,8 @@
 }
 
 template <typename ElfTypes>
-static ArrayRef<const uint8_t> WriteDebugElfFileForClassInternal(const InstructionSet isa,
-                                                                 mirror::Class* type)
+static ArrayRef<const uint8_t> WriteDebugElfFileForClassesInternal(
+    const InstructionSet isa, const ArrayRef<mirror::Class*>& types)
     SHARED_REQUIRES(Locks::mutator_lock_) {
   std::vector<uint8_t> buffer;
   buffer.reserve(KB);
@@ -1407,7 +1397,7 @@
 
   DebugInfoWriter<ElfTypes> info_writer(builder.get());
   info_writer.Start();
-  info_writer.WriteTypes(ArrayRef<mirror::Class*>(&type, 1));
+  info_writer.WriteTypes(types);
   info_writer.End();
 
   builder->End();
@@ -1419,23 +1409,22 @@
   return ArrayRef<const uint8_t>(result, buffer.size());
 }
 
-ArrayRef<const uint8_t> WriteDebugElfFileForClass(const InstructionSet isa, mirror::Class* type) {
+ArrayRef<const uint8_t> WriteDebugElfFileForClasses(const InstructionSet isa,
+                                                    const ArrayRef<mirror::Class*>& types) {
   if (Is64BitInstructionSet(isa)) {
-    return WriteDebugElfFileForClassInternal<ElfTypes64>(isa, type);
+    return WriteDebugElfFileForClassesInternal<ElfTypes64>(isa, types);
   } else {
-    return WriteDebugElfFileForClassInternal<ElfTypes32>(isa, type);
+    return WriteDebugElfFileForClassesInternal<ElfTypes32>(isa, types);
   }
 }
 
 // Explicit instantiations
 template void WriteDebugInfo<ElfTypes32>(
     ElfBuilder<ElfTypes32>* builder,
-    bool write_loaded_runtime_types,
     const ArrayRef<const MethodDebugInfo>& method_infos,
     CFIFormat cfi_format);
 template void WriteDebugInfo<ElfTypes64>(
     ElfBuilder<ElfTypes64>* builder,
-    bool write_loaded_runtime_types,
     const ArrayRef<const MethodDebugInfo>& method_infos,
     CFIFormat cfi_format);
 
diff --git a/compiler/elf_writer_debug.h b/compiler/elf_writer_debug.h
index 91da00f..e4bc856 100644
--- a/compiler/elf_writer_debug.h
+++ b/compiler/elf_writer_debug.h
@@ -32,13 +32,13 @@
 
 template <typename ElfTypes>
 void WriteDebugInfo(ElfBuilder<ElfTypes>* builder,
-                    bool write_loaded_runtime_types,
                     const ArrayRef<const MethodDebugInfo>& method_infos,
                     CFIFormat cfi_format);
 
 ArrayRef<const uint8_t> WriteDebugElfFileForMethod(const dwarf::MethodDebugInfo& method_info);
 
-ArrayRef<const uint8_t> WriteDebugElfFileForClass(const InstructionSet isa, mirror::Class* type)
+ArrayRef<const uint8_t> WriteDebugElfFileForClasses(const InstructionSet isa,
+                                                    const ArrayRef<mirror::Class*>& types)
     SHARED_REQUIRES(Locks::mutator_lock_);
 
 }  // namespace dwarf
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index a67f3bd..7b1bdd7 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -152,7 +152,7 @@
 void ElfWriterQuick<ElfTypes>::WriteDebugInfo(
     const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) {
   if (compiler_options_->GetGenerateDebugInfo()) {
-    dwarf::WriteDebugInfo(builder_.get(), /* write_types */ true, method_infos, kCFIFormat);
+    dwarf::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat);
   }
 }
 
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index 9df4e84..3a3275a 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -28,6 +28,8 @@
 #include "dex/quick_compiler_callbacks.h"
 #include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
+#include "elf_writer_debug.h"
+#include "jit/debugger_interface.h"
 #include "jit/jit.h"
 #include "jit/jit_code_cache.h"
 #include "oat_file-inl.h"
@@ -65,6 +67,17 @@
   return jit_compiler->CompileMethod(self, method);
 }
 
+extern "C" void jit_types_loaded(void* handle, mirror::Class** types, size_t count)
+    SHARED_REQUIRES(Locks::mutator_lock_) {
+  auto* jit_compiler = reinterpret_cast<JitCompiler*>(handle);
+  DCHECK(jit_compiler != nullptr);
+  if (jit_compiler->GetCompilerOptions()->GetGenerateDebugInfo()) {
+    const ArrayRef<mirror::Class*> types_array(types, count);
+    ArrayRef<const uint8_t> elf_file = dwarf::WriteDebugElfFileForClasses(kRuntimeISA, types_array);
+    CreateJITCodeEntry(std::unique_ptr<const uint8_t[]>(elf_file.data()), elf_file.size());
+  }
+}
+
 // Callers of this method assume it has NO_RETURN.
 NO_RETURN static void Usage(const char* fmt, ...) {
   va_list ap;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index ddd285a..ed833c4 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1880,6 +1880,9 @@
    */
   Dbg::PostClassPrepare(h_new_class.Get());
 
+  // Notify native debugger of the new class and its layout.
+  jit::Jit::NewTypeLoadedIfUsingJit(h_new_class.Get());
+
   return h_new_class.Get();
 }
 
@@ -2766,6 +2769,7 @@
 
   mirror::Class* existing = InsertClass(descriptor, new_class.Get(), hash);
   if (existing == nullptr) {
+    jit::Jit::NewTypeLoadedIfUsingJit(new_class.Get());
     return new_class.Get();
   }
   // Another thread must have loaded the class after we
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 05668a9..5c9dab2 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -127,6 +127,13 @@
     *error_msg = "JIT couldn't find jit_compile_method entry point";
     return false;
   }
+  jit_types_loaded_ = reinterpret_cast<void (*)(void*, mirror::Class**, size_t)>(
+      dlsym(jit_library_handle_, "jit_types_loaded"));
+  if (jit_types_loaded_ == nullptr) {
+    dlclose(jit_library_handle_);
+    *error_msg = "JIT couldn't find jit_types_loaded entry point";
+    return false;
+  }
   CompilerCallbacks* callbacks = nullptr;
   bool will_generate_debug_symbols = false;
   VLOG(jit) << "Calling JitLoad interpreter_only="
@@ -214,5 +221,31 @@
       new jit::JitInstrumentationCache(compile_threshold, warmup_threshold));
 }
 
+void Jit::NewTypeLoadedIfUsingJit(mirror::Class* type) {
+  jit::Jit* jit = Runtime::Current()->GetJit();
+  if (jit != nullptr && jit->generate_debug_info_) {
+    DCHECK(jit->jit_types_loaded_ != nullptr);
+    jit->jit_types_loaded_(jit->jit_compiler_handle_, &type, 1);
+  }
+}
+
+void Jit::DumpTypeInfoForLoadedTypes(ClassLinker* linker) {
+  struct CollectClasses : public ClassVisitor {
+    bool Visit(mirror::Class* klass) override {
+      classes_.push_back(klass);
+      return true;
+    }
+    std::vector<mirror::Class*> classes_;
+  };
+
+  if (generate_debug_info_) {
+    ScopedObjectAccess so(Thread::Current());
+
+    CollectClasses visitor;
+    linker->VisitClasses(&visitor);
+    jit_types_loaded_(jit_compiler_handle_, visitor.classes_.data(), visitor.classes_.size());
+  }
+}
+
 }  // namespace jit
 }  // namespace art
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 42bbbe7..429edf6 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -79,6 +79,13 @@
     DumpInfo(os);
   }
 
+  static void NewTypeLoadedIfUsingJit(mirror::Class* type)
+      SHARED_REQUIRES(Locks::mutator_lock_);
+
+  // If debug info generation is turned on then write the type information for types already loaded
+  // into the specified class linker to the jit debug interface,
+  void DumpTypeInfoForLoadedTypes(ClassLinker* linker);
+
  private:
   Jit();
   bool LoadCompiler(std::string* error_msg);
@@ -89,6 +96,7 @@
   void* (*jit_load_)(CompilerCallbacks**, bool*);
   void (*jit_unload_)(void*);
   bool (*jit_compile_method_)(void*, ArtMethod*, Thread*);
+  void (*jit_types_loaded_)(void*, mirror::Class**, size_t count);
 
   // Performance monitoring.
   bool dump_info_on_shutdown_;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index c4694ee..1101acd 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1881,6 +1881,9 @@
     jit_->CreateInstrumentationCache(jit_options_->GetCompileThreshold(),
                                      jit_options_->GetWarmupThreshold());
     jit_->CreateThreadPool();
+
+    // Notify native debugger about the classes already loaded before the creation of the jit.
+    jit_->DumpTypeInfoForLoadedTypes(GetClassLinker());
   } else {
     LOG(WARNING) << "Failed to create JIT " << error_msg;
   }
diff --git a/tools/libcore_failures_concurrent_collector.txt b/tools/libcore_failures_concurrent_collector.txt
index 2cb2c50..e55c000 100644
--- a/tools/libcore_failures_concurrent_collector.txt
+++ b/tools/libcore_failures_concurrent_collector.txt
@@ -27,7 +27,9 @@
   description: "TimeoutException on host-{x86,x86-64}-concurrent-collector",
   result: EXEC_FAILED,
   modes: [host],
-  names: ["libcore.java.util.zip.GZIPOutputStreamTest#testSyncFlushEnabled",
+  names: ["libcore.java.util.zip.DeflaterOutputStreamTest#testSyncFlushDisabled",
+          "libcore.java.util.zip.GZIPOutputStreamTest#testSyncFlushEnabled",
+          "libcore.java.util.zip.OldAndroidGZIPStreamTest#testGZIPStream",
           "libcore.java.util.zip.ZipFileTest#testZipFileWithLotsOfEntries",
           "libcore.java.util.zip.ZipInputStreamTest#testLongMessage"],
   bug: 26507762