Revert "Revert "Refactor HGraphBuilder and SsaBuilder to remove HLocals""

This patch merges the instruction-building phases from HGraphBuilder
and SsaBuilder into a single HInstructionBuilder class. As a result,
it is not necessary to generate HLocal, HLoadLocal and HStoreLocal
instructions any more, as the builder produces SSA form directly.

Saves 5-15% of arena-allocated memory (see bug for more data):
  GMS      20.46MB  =>  19.26MB  (-5.86%)
  Maps     24.12MB  =>  21.47MB  (-10.98%)
  YouTube  28.60MB  =>  26.01MB  (-9.05%)

This CL fixed an issue with parsing quickened instructions.

Bug: 27894376
Bug: 27998571
Bug: 27995065

Change-Id: I20dbe1bf2d0fe296377478db98cb86cba695e694
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index 50a1334..4f46d5e 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -24,14 +24,14 @@
 #include "dex_file-inl.h"
 #include "driver/compiler_driver.h"
 #include "driver/dex_compilation_unit.h"
+#include "instruction_builder.h"
 #include "optimizing_compiler_stats.h"
 #include "primitive.h"
 #include "nodes.h"
+#include "ssa_builder.h"
 
 namespace art {
 
-class Instruction;
-
 class HGraphBuilder : public ValueObject {
  public:
   HGraphBuilder(HGraph* graph,
@@ -42,245 +42,65 @@
                 CompilerDriver* driver,
                 OptimizingCompilerStats* compiler_stats,
                 const uint8_t* interpreter_metadata,
-                Handle<mirror::DexCache> dex_cache)
-      : arena_(graph->GetArena()),
-        locals_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)),
-        current_block_(nullptr),
-        graph_(graph),
+                Handle<mirror::DexCache> dex_cache,
+                StackHandleScopeCollection* handles)
+      : graph_(graph),
         dex_file_(dex_file),
         code_item_(code_item),
         dex_compilation_unit_(dex_compilation_unit),
         compiler_driver_(driver),
-        outer_compilation_unit_(outer_compilation_unit),
-        return_type_(Primitive::GetType(dex_compilation_unit_->GetShorty()[0])),
-        code_start_(code_item.insns_),
-        block_builder_(graph, dex_file, code_item),
-        latest_result_(nullptr),
         compilation_stats_(compiler_stats),
-        interpreter_metadata_(interpreter_metadata),
-        dex_cache_(dex_cache) {}
+        block_builder_(graph, dex_file, code_item),
+        ssa_builder_(graph, handles),
+        instruction_builder_(graph,
+                             &block_builder_,
+                             &ssa_builder_,
+                             dex_file,
+                             code_item_,
+                             Primitive::GetType(dex_compilation_unit_->GetShorty()[0]),
+                             dex_compilation_unit,
+                             outer_compilation_unit,
+                             driver,
+                             interpreter_metadata,
+                             compiler_stats,
+                             dex_cache) {}
 
   // Only for unit testing.
   HGraphBuilder(HGraph* graph,
                 const DexFile::CodeItem& code_item,
+                StackHandleScopeCollection* handles,
                 Primitive::Type return_type = Primitive::kPrimInt)
-      : arena_(graph->GetArena()),
-        locals_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)),
-        current_block_(nullptr),
-        graph_(graph),
+      : graph_(graph),
         dex_file_(nullptr),
         code_item_(code_item),
         dex_compilation_unit_(nullptr),
         compiler_driver_(nullptr),
-        outer_compilation_unit_(nullptr),
-        return_type_(return_type),
-        code_start_(code_item.insns_),
-        block_builder_(graph, nullptr, code_item),
-        latest_result_(nullptr),
-        compilation_stats_(nullptr),
-        interpreter_metadata_(nullptr),
         null_dex_cache_(),
-        dex_cache_(null_dex_cache_) {}
+        compilation_stats_(nullptr),
+        block_builder_(graph, nullptr, code_item),
+        ssa_builder_(graph, handles),
+        instruction_builder_(graph,
+                             &block_builder_,
+                             &ssa_builder_,
+                             /* dex_file */ nullptr,
+                             code_item_,
+                             return_type,
+                             /* dex_compilation_unit */ nullptr,
+                             /* outer_compilation_unit */ nullptr,
+                             /* compiler_driver */ nullptr,
+                             /* interpreter_metadata */ nullptr,
+                             /* compiler_stats */ nullptr,
+                             null_dex_cache_) {}
 
-  GraphAnalysisResult BuildGraph(StackHandleScopeCollection* handles);
+  GraphAnalysisResult BuildGraph();
 
   static constexpr const char* kBuilderPassName = "builder";
 
  private:
-  bool GenerateInstructions();
-  bool AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_pc);
-
-  void FindNativeDebugInfoLocations(ArenaBitVector* locations);
-
-  bool CanDecodeQuickenedInfo() const;
-  uint16_t LookupQuickenedInfo(uint32_t dex_pc);
-
-  HBasicBlock* FindBlockStartingAt(uint32_t dex_pc) const {
-    return block_builder_.GetBlockAt(dex_pc);
-  }
-
-  void InitializeLocals(uint16_t count);
-  HLocal* GetLocalAt(uint32_t register_index) const;
-  void UpdateLocal(uint32_t register_index, HInstruction* instruction, uint32_t dex_pc) const;
-  HInstruction* LoadLocal(uint32_t register_index, Primitive::Type type, uint32_t dex_pc) const;
-  void InitializeParameters(uint16_t number_of_parameters);
-
-  // Returns whether the current method needs access check for the type.
-  // Output parameter finalizable is set to whether the type is finalizable.
-  bool NeedsAccessCheck(uint32_t type_index, /*out*/bool* finalizable) const;
-
-  template<typename T>
-  void Unop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
-
-  template<typename T>
-  void Binop_23x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
-
-  template<typename T>
-  void Binop_23x_shift(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
-
-  void Binop_23x_cmp(const Instruction& instruction,
-                     Primitive::Type type,
-                     ComparisonBias bias,
-                     uint32_t dex_pc);
-
-  template<typename T>
-  void Binop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
-
-  template<typename T>
-  void Binop_12x_shift(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
-
-  template<typename T>
-  void Binop_22b(const Instruction& instruction, bool reverse, uint32_t dex_pc);
-
-  template<typename T>
-  void Binop_22s(const Instruction& instruction, bool reverse, uint32_t dex_pc);
-
-  template<typename T> void If_21t(const Instruction& instruction, uint32_t dex_pc);
-  template<typename T> void If_22t(const Instruction& instruction, uint32_t dex_pc);
-
-  void Conversion_12x(const Instruction& instruction,
-                      Primitive::Type input_type,
-                      Primitive::Type result_type,
-                      uint32_t dex_pc);
-
-  void BuildCheckedDivRem(uint16_t out_reg,
-                          uint16_t first_reg,
-                          int64_t second_reg_or_constant,
-                          uint32_t dex_pc,
-                          Primitive::Type type,
-                          bool second_is_lit,
-                          bool is_div);
-
-  void BuildReturn(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
-
-  // Builds an instance field access node and returns whether the instruction is supported.
-  bool BuildInstanceFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put);
-
-  void BuildUnresolvedStaticFieldAccess(const Instruction& instruction,
-                                        uint32_t dex_pc,
-                                        bool is_put,
-                                        Primitive::Type field_type);
-  // Builds a static field access node and returns whether the instruction is supported.
-  bool BuildStaticFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put);
-
-  void BuildArrayAccess(const Instruction& instruction,
-                        uint32_t dex_pc,
-                        bool is_get,
-                        Primitive::Type anticipated_type);
-
-  // Builds an invocation node and returns whether the instruction is supported.
-  bool BuildInvoke(const Instruction& instruction,
-                   uint32_t dex_pc,
-                   uint32_t method_idx,
-                   uint32_t number_of_vreg_arguments,
-                   bool is_range,
-                   uint32_t* args,
-                   uint32_t register_index);
-
-  // Builds a new array node and the instructions that fill it.
-  void BuildFilledNewArray(uint32_t dex_pc,
-                           uint32_t type_index,
-                           uint32_t number_of_vreg_arguments,
-                           bool is_range,
-                           uint32_t* args,
-                           uint32_t register_index);
-
-  void BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc);
-
-  // Fills the given object with data as specified in the fill-array-data
-  // instruction. Currently only used for non-reference and non-floating point
-  // arrays.
-  template <typename T>
-  void BuildFillArrayData(HInstruction* object,
-                          const T* data,
-                          uint32_t element_count,
-                          Primitive::Type anticipated_type,
-                          uint32_t dex_pc);
-
-  // Fills the given object with data as specified in the fill-array-data
-  // instruction. The data must be for long and double arrays.
-  void BuildFillWideArrayData(HInstruction* object,
-                              const int64_t* data,
-                              uint32_t element_count,
-                              uint32_t dex_pc);
-
-  // Builds a `HInstanceOf`, or a `HCheckCast` instruction.
-  void BuildTypeCheck(const Instruction& instruction,
-                      uint8_t destination,
-                      uint8_t reference,
-                      uint16_t type_index,
-                      uint32_t dex_pc);
-
-  // Builds an instruction sequence for a switch statement.
-  void BuildSwitch(const Instruction& instruction, uint32_t dex_pc);
-
+  void MaybeRecordStat(MethodCompilationStat compilation_stat);
   bool SkipCompilation(size_t number_of_branches);
 
-  void MaybeRecordStat(MethodCompilationStat compilation_stat);
-
-  // Returns the outer-most compiling method's class.
-  mirror::Class* GetOutermostCompilingClass() const;
-
-  // Returns the class whose method is being compiled.
-  mirror::Class* GetCompilingClass() const;
-
-  // Returns whether `type_index` points to the outer-most compiling method's class.
-  bool IsOutermostCompilingClass(uint16_t type_index) const;
-
-  void PotentiallySimplifyFakeString(uint16_t original_dex_register,
-                                     uint32_t dex_pc,
-                                     HInvoke* invoke);
-
-  bool SetupInvokeArguments(HInvoke* invoke,
-                            uint32_t number_of_vreg_arguments,
-                            uint32_t* args,
-                            uint32_t register_index,
-                            bool is_range,
-                            const char* descriptor,
-                            size_t start_index,
-                            size_t* argument_index);
-
-  bool HandleInvoke(HInvoke* invoke,
-                    uint32_t number_of_vreg_arguments,
-                    uint32_t* args,
-                    uint32_t register_index,
-                    bool is_range,
-                    const char* descriptor,
-                    HClinitCheck* clinit_check);
-
-  bool HandleStringInit(HInvoke* invoke,
-                        uint32_t number_of_vreg_arguments,
-                        uint32_t* args,
-                        uint32_t register_index,
-                        bool is_range,
-                        const char* descriptor);
-
-  HClinitCheck* ProcessClinitCheckForInvoke(
-      uint32_t dex_pc,
-      ArtMethod* method,
-      uint32_t method_idx,
-      HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement)
-      SHARED_REQUIRES(Locks::mutator_lock_);
-
-  // Build a HNewInstance instruction.
-  bool BuildNewInstance(uint16_t type_index, uint32_t dex_pc);
-
-  // Return whether the compiler can assume `cls` is initialized.
-  bool IsInitialized(Handle<mirror::Class> cls) const
-      SHARED_REQUIRES(Locks::mutator_lock_);
-
-  // Try to resolve a method using the class linker. Return null if a method could
-  // not be resolved.
-  ArtMethod* ResolveMethod(uint16_t method_idx, InvokeType invoke_type);
-
-  ArenaAllocator* const arena_;
-
-  ArenaVector<HLocal*> locals_;
-
-  HBasicBlock* current_block_;
   HGraph* const graph_;
-
-  // The dex file where the method being compiled is, and the bytecode data.
   const DexFile* const dex_file_;
   const DexFile::CodeItem& code_item_;
 
@@ -290,31 +110,13 @@
 
   CompilerDriver* const compiler_driver_;
 
-  // The compilation unit of the outermost method being compiled. That is the
-  // method being compiled (and not inlined), and potentially inlining other
-  // methods.
-  const DexCompilationUnit* const outer_compilation_unit_;
-
-  // The return type of the method being compiled.
-  const Primitive::Type return_type_;
-
-  // The pointer in the dex file where the instructions of the code item
-  // being currently compiled start.
-  const uint16_t* code_start_;
-
-  HBasicBlockBuilder block_builder_;
-
-  // The last invoke or fill-new-array being built. Only to be
-  // used by move-result instructions.
-  HInstruction* latest_result_;
+  ScopedNullHandle<mirror::DexCache> null_dex_cache_;
 
   OptimizingCompilerStats* compilation_stats_;
 
-  const uint8_t* interpreter_metadata_;
-
-  // Dex cache for dex_file_.
-  ScopedNullHandle<mirror::DexCache> null_dex_cache_;
-  Handle<mirror::DexCache> dex_cache_;
+  HBasicBlockBuilder block_builder_;
+  SsaBuilder ssa_builder_;
+  HInstructionBuilder instruction_builder_;
 
   DISALLOW_COPY_AND_ASSIGN(HGraphBuilder);
 };