OSDN Git Service

Move code around in OptimizingCompiler::Compile to reduce stack space.
authorNicolas Geoffray <ngeoffray@google.com>
Fri, 9 Jan 2015 14:53:50 +0000 (14:53 +0000)
committerNicolas Geoffray <ngeoffray@google.com>
Mon, 12 Jan 2015 08:49:25 +0000 (08:49 +0000)
Also fix an (intentional) memory leak, by allocating the CodeGenerator
on the heap instead of the arena: they construct an Assembler object
that requires destruction.

BUG:18787334

Change-Id: I8cf0667cb70ce5b14d4ac334bd4487a562635f1b

compiler/optimizing/code_generator.cc
compiler/optimizing/code_generator.h
compiler/optimizing/optimizing_compiler.cc

index 4d8154e..a5d82a8 100644 (file)
@@ -325,26 +325,25 @@ bool CodeGenerator::GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) con
   return current->GetBlockId() + 1 == next->GetBlockId();
 }
 
-CodeGenerator* CodeGenerator::Create(ArenaAllocator* allocator,
-                                     HGraph* graph,
+CodeGenerator* CodeGenerator::Create(HGraph* graph,
                                      InstructionSet instruction_set,
                                      const InstructionSetFeatures& isa_features) {
   switch (instruction_set) {
     case kArm:
     case kThumb2: {
-      return new (allocator) arm::CodeGeneratorARM(graph,
+      return new arm::CodeGeneratorARM(graph,
           isa_features.AsArmInstructionSetFeatures());
     }
     case kArm64: {
-      return new (allocator) arm64::CodeGeneratorARM64(graph);
+      return new arm64::CodeGeneratorARM64(graph);
     }
     case kMips:
       return nullptr;
     case kX86: {
-      return new (allocator) x86::CodeGeneratorX86(graph);
+      return new x86::CodeGeneratorX86(graph);
     }
     case kX86_64: {
-      return new (allocator) x86_64::CodeGeneratorX86_64(graph);
+      return new x86_64::CodeGeneratorX86_64(graph);
     }
     default:
       return nullptr;
index 4205ebe..bb0dda0 100644 (file)
@@ -77,16 +77,16 @@ class SlowPathCode : public ArenaObject<kArenaAllocSlowPaths> {
   DISALLOW_COPY_AND_ASSIGN(SlowPathCode);
 };
 
-class CodeGenerator : public ArenaObject<kArenaAllocMisc> {
+class CodeGenerator {
  public:
   // Compiles the graph to executable instructions. Returns whether the compilation
   // succeeded.
   void CompileBaseline(CodeAllocator* allocator, bool is_leaf = false);
   void CompileOptimized(CodeAllocator* allocator);
-  static CodeGenerator* Create(ArenaAllocator* allocator,
-                               HGraph* graph,
+  static CodeGenerator* Create(HGraph* graph,
                                InstructionSet instruction_set,
                                const InstructionSetFeatures& isa_features);
+  virtual ~CodeGenerator() {}
 
   HGraph* GetGraph() const { return graph_; }
 
@@ -212,7 +212,6 @@ class CodeGenerator : public ArenaObject<kArenaAllocMisc> {
         slow_paths_(graph->GetArena(), 8),
         is_leaf_(true),
         stack_map_stream_(graph->GetArena()) {}
-  ~CodeGenerator() {}
 
   // Register allocation logic.
   void AllocateRegistersLocally(HInstruction* instruction) const;
index 1a27724..692d452 100644 (file)
@@ -118,6 +118,18 @@ class OptimizingCompiler FINAL : public Compiler {
   // just run the code generation after the graph was built.
   const bool run_optimizations_;
 
+  // Optimize and compile `graph`.
+  CompiledMethod* CompileOptimized(HGraph* graph,
+                                   CodeGenerator* codegen,
+                                   CompilerDriver* driver,
+                                   const DexCompilationUnit& dex_compilation_unit,
+                                   const HGraphVisualizer& visualizer) const;
+
+  // Just compile without doing optimizations.
+  CompiledMethod* CompileBaseline(CodeGenerator* codegen,
+                                  CompilerDriver* driver,
+                                  const DexCompilationUnit& dex_compilation_unit) const;
+
   mutable OptimizingCompilerStats compilation_stats_;
 
   std::unique_ptr<std::ostream> visualizer_output_;
@@ -234,6 +246,73 @@ static ArrayRef<const uint8_t> AlignVectorSize(std::vector<uint8_t>& vector) {
   return ArrayRef<const uint8_t>(vector);
 }
 
+
+CompiledMethod* OptimizingCompiler::CompileOptimized(HGraph* graph,
+                                                     CodeGenerator* codegen,
+                                                     CompilerDriver* compiler_driver,
+                                                     const DexCompilationUnit& dex_compilation_unit,
+                                                     const HGraphVisualizer& visualizer) const {
+  RunOptimizations(
+      graph, compiler_driver, &compilation_stats_, dex_compilation_unit, visualizer);
+
+  PrepareForRegisterAllocation(graph).Run();
+  SsaLivenessAnalysis liveness(*graph, codegen);
+  liveness.Analyze();
+  visualizer.DumpGraph(kLivenessPassName);
+
+  RegisterAllocator register_allocator(graph->GetArena(), codegen, liveness);
+  register_allocator.AllocateRegisters();
+  visualizer.DumpGraph(kRegisterAllocatorPassName);
+
+  CodeVectorAllocator allocator;
+  codegen->CompileOptimized(&allocator);
+
+  std::vector<uint8_t> stack_map;
+  codegen->BuildStackMaps(&stack_map);
+
+  compilation_stats_.RecordStat(MethodCompilationStat::kCompiledOptimized);
+
+  return CompiledMethod::SwapAllocCompiledMethodStackMap(
+      compiler_driver,
+      codegen->GetInstructionSet(),
+      ArrayRef<const uint8_t>(allocator.GetMemory()),
+      codegen->GetFrameSize(),
+      codegen->GetCoreSpillMask(),
+      0, /* FPR spill mask, unused */
+      ArrayRef<const uint8_t>(stack_map));
+}
+
+
+CompiledMethod* OptimizingCompiler::CompileBaseline(
+    CodeGenerator* codegen,
+    CompilerDriver* compiler_driver,
+    const DexCompilationUnit& dex_compilation_unit) const {
+  CodeVectorAllocator allocator;
+  codegen->CompileBaseline(&allocator);
+
+  std::vector<uint8_t> mapping_table;
+  DefaultSrcMap src_mapping_table;
+  bool include_debug_symbol = compiler_driver->GetCompilerOptions().GetIncludeDebugSymbols();
+  codegen->BuildMappingTable(&mapping_table, include_debug_symbol ? &src_mapping_table : nullptr);
+  std::vector<uint8_t> vmap_table;
+  codegen->BuildVMapTable(&vmap_table);
+  std::vector<uint8_t> gc_map;
+  codegen->BuildNativeGCMap(&gc_map, dex_compilation_unit);
+
+  compilation_stats_.RecordStat(MethodCompilationStat::kCompiledBaseline);
+  return CompiledMethod::SwapAllocCompiledMethod(compiler_driver,
+                                                 codegen->GetInstructionSet(),
+                                                 ArrayRef<const uint8_t>(allocator.GetMemory()),
+                                                 codegen->GetFrameSize(),
+                                                 codegen->GetCoreSpillMask(),
+                                                 0, /* FPR spill mask, unused */
+                                                 &src_mapping_table,
+                                                 AlignVectorSize(mapping_table),
+                                                 AlignVectorSize(vmap_table),
+                                                 AlignVectorSize(gc_map),
+                                                 ArrayRef<const uint8_t>());
+}
+
 CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
                                             uint32_t access_flags,
                                             InvokeType invoke_type,
@@ -290,22 +369,21 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
   }
 
   CompilerDriver* compiler_driver = GetCompilerDriver();
-  CodeGenerator* codegen = CodeGenerator::Create(&arena, graph, instruction_set,
-      *compiler_driver->GetInstructionSetFeatures());
-  if (codegen == nullptr) {
+  std::unique_ptr<CodeGenerator> codegen(
+      CodeGenerator::Create(graph, instruction_set, *compiler_driver->GetInstructionSetFeatures()));
+  if (codegen.get() == nullptr) {
     CHECK(!shouldCompile) << "Could not find code generator for optimizing compiler";
     compilation_stats_.RecordStat(MethodCompilationStat::kNotCompiledNoCodegen);
     return nullptr;
   }
 
   HGraphVisualizer visualizer(
-      visualizer_output_.get(), graph, kStringFilter, *codegen, method_name.c_str());
+      visualizer_output_.get(), graph, kStringFilter, *codegen.get(), method_name.c_str());
   visualizer.DumpGraph("builder");
 
-  CodeVectorAllocator allocator;
-
   bool can_optimize = CanOptimize(*code_item);
   bool can_allocate_registers = RegisterAllocator::CanAllocateRegistersFor(*graph, instruction_set);
+  CompiledMethod* result = nullptr;
   if (run_optimizations_ && can_optimize && can_allocate_registers) {
     VLOG(compiler) << "Optimizing " << PrettyMethod(method_idx, dex_file);
     if (!graph->TryBuildingSsa()) {
@@ -314,34 +392,9 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
                 << ": it contains a non natural loop";
       // We could not transform the graph to SSA, bailout.
       compilation_stats_.RecordStat(MethodCompilationStat::kNotCompiledCannotBuildSSA);
-      return nullptr;
+    } else {
+      result = CompileOptimized(graph, codegen.get(), compiler_driver, dex_compilation_unit, visualizer);
     }
-    RunOptimizations(
-        graph, compiler_driver, &compilation_stats_, dex_compilation_unit, visualizer);
-
-    PrepareForRegisterAllocation(graph).Run();
-    SsaLivenessAnalysis liveness(*graph, codegen);
-    liveness.Analyze();
-    visualizer.DumpGraph(kLivenessPassName);
-
-    RegisterAllocator register_allocator(graph->GetArena(), codegen, liveness);
-    register_allocator.AllocateRegisters();
-
-    visualizer.DumpGraph(kRegisterAllocatorPassName);
-    codegen->CompileOptimized(&allocator);
-
-    std::vector<uint8_t> stack_map;
-    codegen->BuildStackMaps(&stack_map);
-
-    compilation_stats_.RecordStat(MethodCompilationStat::kCompiledOptimized);
-    return CompiledMethod::SwapAllocCompiledMethodStackMap(
-        compiler_driver,
-        instruction_set,
-        ArrayRef<const uint8_t>(allocator.GetMemory()),
-        codegen->GetFrameSize(),
-        codegen->GetCoreSpillMask(),
-        0, /* FPR spill mask, unused */
-        ArrayRef<const uint8_t>(stack_map));
   } else if (shouldOptimize && RegisterAllocator::Supports(instruction_set)) {
     LOG(FATAL) << "Could not allocate registers in optimizing compiler";
     UNREACHABLE();
@@ -356,30 +409,9 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item,
       compilation_stats_.RecordStat(MethodCompilationStat::kNotOptimizedRegisterAllocator);
     }
 
-    codegen->CompileBaseline(&allocator);
-
-    std::vector<uint8_t> mapping_table;
-    DefaultSrcMap src_mapping_table;
-    bool include_debug_symbol = compiler_driver->GetCompilerOptions().GetIncludeDebugSymbols();
-    codegen->BuildMappingTable(&mapping_table, include_debug_symbol ? &src_mapping_table : nullptr);
-    std::vector<uint8_t> vmap_table;
-    codegen->BuildVMapTable(&vmap_table);
-    std::vector<uint8_t> gc_map;
-    codegen->BuildNativeGCMap(&gc_map, dex_compilation_unit);
-
-    compilation_stats_.RecordStat(MethodCompilationStat::kCompiledBaseline);
-    return CompiledMethod::SwapAllocCompiledMethod(compiler_driver,
-                                                   instruction_set,
-                                                   ArrayRef<const uint8_t>(allocator.GetMemory()),
-                                                   codegen->GetFrameSize(),
-                                                   codegen->GetCoreSpillMask(),
-                                                   0, /* FPR spill mask, unused */
-                                                   &src_mapping_table,
-                                                   AlignVectorSize(mapping_table),
-                                                   AlignVectorSize(vmap_table),
-                                                   AlignVectorSize(gc_map),
-                                                   ArrayRef<const uint8_t>());
+    result = CompileBaseline(codegen.get(), compiler_driver, dex_compilation_unit);
   }
+  return result;
 }
 
 Compiler* CreateOptimizingCompiler(CompilerDriver* driver) {