Add more dwarf debug line info for Optimized methods.

Optimizing compiler generates minimum debug line info that
is built using the dex_pc information about suspend points.
This is not enough for performance and debugging needs.

This CL generates additional debug line information for
instructions which have known dex_pc and it ensures that
whole call sites are mapped (as opposed to suspend points
which map only one instruction past the function call).

Bug: 23157336
Change-Id: I9f2b1c2038e3560847c175b8121cf9496b8b58fa
Signed-off-by: Yevgeny Rouban <yevgeny.y.rouban@intel.com>
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 3f69270..a6fc455 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -239,7 +239,10 @@
         InitLocationsBaseline(current);
       }
       DCHECK(CheckTypeConsistency(current));
+      uintptr_t native_pc_begin = GetAssembler()->CodeSize();
       current->Accept(instruction_visitor);
+      uintptr_t native_pc_end = GetAssembler()->CodeSize();
+      RecordNativeDebugInfo(current->GetDexPc(), native_pc_begin, native_pc_end);
     }
   }
 
@@ -604,15 +607,6 @@
   }
 }
 
-void CodeGenerator::BuildSourceMap(DefaultSrcMap* src_map) const {
-  for (size_t i = 0, num = stack_map_stream_.GetNumberOfStackMaps(); i != num; ++i) {
-    const StackMapStream::StackMapEntry& stack_map_entry = stack_map_stream_.GetStackMap(i);
-    uint32_t pc2dex_offset = stack_map_entry.native_pc_offset;
-    int32_t pc2dex_dalvik_offset = stack_map_entry.dex_pc;
-    src_map->push_back(SrcMapElem({pc2dex_offset, pc2dex_dalvik_offset}));
-  }
-}
-
 void CodeGenerator::BuildMappingTable(ArenaVector<uint8_t>* data) const {
   uint32_t pc2dex_data_size = 0u;
   uint32_t pc2dex_entries = stack_map_stream_.GetNumberOfStackMaps();
@@ -728,6 +722,15 @@
   stack_map_stream_.FillIn(region);
 }
 
+void CodeGenerator::RecordNativeDebugInfo(uint32_t dex_pc,
+                                          uintptr_t native_pc_begin,
+                                          uintptr_t native_pc_end) {
+  if (src_map_ != nullptr && dex_pc != kNoDexPc && native_pc_begin != native_pc_end) {
+    src_map_->push_back(SrcMapElem({static_cast<uint32_t>(native_pc_begin),
+                                    static_cast<int32_t>(dex_pc)}));
+  }
+}
+
 void CodeGenerator::RecordPcInfo(HInstruction* instruction,
                                  uint32_t dex_pc,
                                  SlowPathCode* slow_path) {
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 754b5ec..b3c4d72 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -229,7 +229,11 @@
     return (fpu_callee_save_mask_ & (1 << reg)) != 0;
   }
 
+  // Record native to dex mapping for a suspend point.  Required by runtime.
   void RecordPcInfo(HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path = nullptr);
+  // Record additional native to dex mappings for native debugging/profiling tools.
+  void RecordNativeDebugInfo(uint32_t dex_pc, uintptr_t native_pc_begin, uintptr_t native_pc_end);
+
   bool CanMoveNullCheckToUser(HNullCheck* null_check);
   void MaybeRecordImplicitNullCheck(HInstruction* instruction);
 
@@ -237,7 +241,8 @@
     slow_paths_.Add(slow_path);
   }
 
-  void BuildSourceMap(DefaultSrcMap* src_map) const;
+  void SetSrcMap(DefaultSrcMap* src_map) { src_map_ = src_map; }
+
   void BuildMappingTable(ArenaVector<uint8_t>* vector) const;
   void BuildVMapTable(ArenaVector<uint8_t>* vector) const;
   void BuildNativeGCMap(
@@ -395,6 +400,7 @@
         disasm_info_(nullptr),
         graph_(graph),
         compiler_options_(compiler_options),
+        src_map_(nullptr),
         slow_paths_(graph->GetArena(), 8),
         current_block_index_(0),
         is_leaf_(true),
@@ -489,6 +495,8 @@
   HGraph* const graph_;
   const CompilerOptions& compiler_options_;
 
+  // Native to dex_pc map used for native debugging/profiling tools.
+  DefaultSrcMap* src_map_;
   GrowableArray<SlowPathCode*> slow_paths_;
 
   // The current block index in `block_order_` of the block
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index ee82fda..9bf3968 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1732,9 +1732,7 @@
 
   virtual bool NeedsEnvironment() const { return false; }
   virtual uint32_t GetDexPc() const {
-    LOG(FATAL) << "GetDexPc() cannot be called on an instruction that"
-                  " does not need an environment";
-    UNREACHABLE();
+    return kNoDexPc;
   }
   virtual bool IsControlFlow() const { return false; }
 
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 898b656..8e48f6d 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -558,15 +558,14 @@
 
   ArenaAllocator* arena = graph->GetArena();
   CodeVectorAllocator allocator(arena);
+  DefaultSrcMap src_mapping_table;
+  codegen->SetSrcMap(compiler_driver->GetCompilerOptions().GetGenerateDebugInfo()
+                         ? &src_mapping_table
+                         : nullptr);
   codegen->CompileOptimized(&allocator);
 
   ArenaVector<LinkerPatch> linker_patches = EmitAndSortLinkerPatches(codegen);
 
-  DefaultSrcMap src_mapping_table;
-  if (compiler_driver->GetCompilerOptions().GetGenerateDebugInfo()) {
-    codegen->BuildSourceMap(&src_mapping_table);
-  }
-
   ArenaVector<uint8_t> stack_map(arena->Adapter(kArenaAllocStackMaps));
   codegen->BuildStackMaps(&stack_map);
 
@@ -601,16 +600,16 @@
     PassObserver* pass_observer) const {
   ArenaAllocator* arena = codegen->GetGraph()->GetArena();
   CodeVectorAllocator allocator(arena);
+  DefaultSrcMap src_mapping_table;
+  codegen->SetSrcMap(compiler_driver->GetCompilerOptions().GetGenerateDebugInfo()
+                         ? &src_mapping_table
+                         : nullptr);
   codegen->CompileBaseline(&allocator);
 
   ArenaVector<LinkerPatch> linker_patches = EmitAndSortLinkerPatches(codegen);
 
   ArenaVector<uint8_t> mapping_table(arena->Adapter(kArenaAllocBaselineMaps));
   codegen->BuildMappingTable(&mapping_table);
-  DefaultSrcMap src_mapping_table;
-  if (compiler_driver->GetCompilerOptions().GetGenerateDebugInfo()) {
-    codegen->BuildSourceMap(&src_mapping_table);
-  }
   ArenaVector<uint8_t> vmap_table(arena->Adapter(kArenaAllocBaselineMaps));
   codegen->BuildVMapTable(&vmap_table);
   ArenaVector<uint8_t> gc_map(arena->Adapter(kArenaAllocBaselineMaps));