Revert "Refactor HGraphBuilder and SsaBuilder to remove HLocals"

Bug: 27995065
This reverts commit e3ff7b293be2a6791fe9d135d660c0cffe4bd73f.

Change-Id: I5363c7ce18f47fd422c15eed5423a345a57249d8
diff --git a/compiler/optimizing/ssa_builder.h b/compiler/optimizing/ssa_builder.h
index c37c28c..83da378 100644
--- a/compiler/optimizing/ssa_builder.h
+++ b/compiler/optimizing/ssa_builder.h
@@ -23,6 +23,8 @@
 
 namespace art {
 
+static constexpr int kDefaultNumberOfLoops = 2;
+
 /**
  * Transforms a graph into SSA form. The liveness guarantees of
  * this transformation are listed below. A DEX register
@@ -45,48 +47,38 @@
  *     is not set, values of Dex registers only used by environments
  *     are killed.
  */
-class SsaBuilder : public ValueObject {
+class SsaBuilder : public HGraphVisitor {
  public:
-  SsaBuilder(HGraph* graph, StackHandleScopeCollection* handles)
-      : graph_(graph),
+  SsaBuilder(HGraph* graph, const DexFile::CodeItem& code_item, StackHandleScopeCollection* handles)
+      : HGraphVisitor(graph),
+        code_item_(code_item),
         handles_(handles),
         agets_fixed_(false),
-        ambiguous_agets_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)),
-        ambiguous_asets_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)),
-        uninitialized_strings_(graph->GetArena()->Adapter(kArenaAllocGraphBuilder)) {
-    graph_->InitializeInexactObjectRTI(handles);
+        current_locals_(nullptr),
+        loop_headers_(graph->GetArena()->Adapter(kArenaAllocSsaBuilder)),
+        ambiguous_agets_(graph->GetArena()->Adapter(kArenaAllocSsaBuilder)),
+        ambiguous_asets_(graph->GetArena()->Adapter(kArenaAllocSsaBuilder)),
+        uninitialized_strings_(graph->GetArena()->Adapter(kArenaAllocSsaBuilder)),
+        locals_for_(graph->GetBlocks().size(),
+                    ArenaVector<HInstruction*>(graph->GetArena()->Adapter(kArenaAllocSsaBuilder)),
+                    graph->GetArena()->Adapter(kArenaAllocSsaBuilder)) {
+    loop_headers_.reserve(kDefaultNumberOfLoops);
   }
 
   GraphAnalysisResult BuildSsa();
 
-  HInstruction* GetFloatOrDoubleEquivalent(HInstruction* instruction, Primitive::Type type);
-  HInstruction* GetReferenceTypeEquivalent(HInstruction* instruction);
+  // Returns locals vector for `block`. If it is a catch block, the vector will be
+  // prepopulated with catch phis for vregs which are defined in `current_locals_`.
+  ArenaVector<HInstruction*>* GetLocalsFor(HBasicBlock* block);
+  HInstruction* ValueOfLocal(HBasicBlock* block, size_t local);
 
-  void MaybeAddAmbiguousArrayGet(HArrayGet* aget) {
-    Primitive::Type type = aget->GetType();
-    DCHECK(!Primitive::IsFloatingPointType(type));
-    if (Primitive::IsIntOrLongType(type)) {
-      ambiguous_agets_.push_back(aget);
-    }
-  }
-
-  void MaybeAddAmbiguousArraySet(HArraySet* aset) {
-    Primitive::Type type = aset->GetValue()->GetType();
-    if (Primitive::IsIntOrLongType(type)) {
-      ambiguous_asets_.push_back(aset);
-    }
-  }
-
-  void AddUninitializedString(HNewInstance* string) {
-    // In some rare cases (b/27847265), the same NewInstance may be seen
-    // multiple times. We should only consider it once for removal, so we
-    // ensure it is not added more than once.
-    // Note that we cannot check whether this really is a NewInstance of String
-    // before RTP. We DCHECK that in RemoveRedundantUninitializedStrings.
-    if (!ContainsElement(uninitialized_strings_, string)) {
-      uninitialized_strings_.push_back(string);
-    }
-  }
+  void VisitBasicBlock(HBasicBlock* block) OVERRIDE;
+  void VisitLoadLocal(HLoadLocal* load) OVERRIDE;
+  void VisitStoreLocal(HStoreLocal* store) OVERRIDE;
+  void VisitInstruction(HInstruction* instruction) OVERRIDE;
+  void VisitArrayGet(HArrayGet* aget) OVERRIDE;
+  void VisitArraySet(HArraySet* aset) OVERRIDE;
+  void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE;
 
  private:
   void SetLoopHeaderPhiInputs();
@@ -104,6 +96,9 @@
   bool UpdatePrimitiveType(HPhi* phi, ArenaVector<HPhi*>* worklist);
   void ProcessPrimitiveTypePropagationWorklist(ArenaVector<HPhi*>* worklist);
 
+  HInstruction* GetFloatOrDoubleEquivalent(HInstruction* instruction, Primitive::Type type);
+  HInstruction* GetReferenceTypeEquivalent(HInstruction* instruction);
+
   HFloatConstant* GetFloatEquivalent(HIntConstant* constant);
   HDoubleConstant* GetDoubleEquivalent(HLongConstant* constant);
   HPhi* GetFloatDoubleOrReferenceEquivalentOfPhi(HPhi* phi, Primitive::Type type);
@@ -111,16 +106,30 @@
 
   void RemoveRedundantUninitializedStrings();
 
-  HGraph* graph_;
+  // Returns whether `instruction` is the first generated HInstruction for its
+  // dex_pc position.
+  bool IsFirstAtThrowingDexPc(HInstruction* instruction) const;
+
+  const DexFile::CodeItem& code_item_;
   StackHandleScopeCollection* const handles_;
 
   // True if types of ambiguous ArrayGets have been resolved.
   bool agets_fixed_;
 
+  // Locals for the current block being visited.
+  ArenaVector<HInstruction*>* current_locals_;
+
+  // Keep track of loop headers found. The last phase of the analysis iterates
+  // over these blocks to set the inputs of their phis.
+  ArenaVector<HBasicBlock*> loop_headers_;
+
   ArenaVector<HArrayGet*> ambiguous_agets_;
   ArenaVector<HArraySet*> ambiguous_asets_;
   ArenaVector<HNewInstance*> uninitialized_strings_;
 
+  // HEnvironment for each block.
+  ArenaVector<ArenaVector<HInstruction*>> locals_for_;
+
   DISALLOW_COPY_AND_ASSIGN(SsaBuilder);
 };