ART: Refactor try/catch block info, store exception type

This patch replaces HBasicBlock fields storing try/catch info with a
single TryCatchInformation data structure, saving memory for the
majority of non-try/catch blocks. It also changes builder to store
the exception type for catch blocks.

Change-Id: Ib3e43f7db247e6915d67c267fc62410420e230c9
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index f09e958..c4f64b4 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -555,6 +555,59 @@
   DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
 };
 
+// Stores try/catch information for basic blocks.
+// Note that HGraph is constructed so that catch blocks cannot simultaneously
+// be try blocks.
+class TryCatchInformation : public ArenaObject<kArenaAllocMisc> {
+ public:
+  // Try block information constructor.
+  explicit TryCatchInformation(const HTryBoundary& try_entry)
+      : try_entry_(&try_entry),
+        catch_dex_file_(nullptr),
+        catch_type_index_(DexFile::kDexNoIndex16) {
+    DCHECK(try_entry_ != nullptr);
+  }
+
+  // Catch block information constructor.
+  TryCatchInformation(uint16_t catch_type_index, const DexFile& dex_file)
+      : try_entry_(nullptr),
+        catch_dex_file_(&dex_file),
+        catch_type_index_(catch_type_index) {}
+
+  bool IsTryBlock() const { return try_entry_ != nullptr; }
+
+  const HTryBoundary& GetTryEntry() const {
+    DCHECK(IsTryBlock());
+    return *try_entry_;
+  }
+
+  bool IsCatchBlock() const { return catch_dex_file_ != nullptr; }
+
+  bool IsCatchAllTypeIndex() const {
+    DCHECK(IsCatchBlock());
+    return catch_type_index_ == DexFile::kDexNoIndex16;
+  }
+
+  uint16_t GetCatchTypeIndex() const {
+    DCHECK(IsCatchBlock());
+    return catch_type_index_;
+  }
+
+  const DexFile& GetCatchDexFile() const {
+    DCHECK(IsCatchBlock());
+    return *catch_dex_file_;
+  }
+
+ private:
+  // One of possibly several TryBoundary instructions entering the block's try.
+  // Only set for try blocks.
+  const HTryBoundary* try_entry_;
+
+  // Exception type information. Only set for catch blocks.
+  const DexFile* catch_dex_file_;
+  const uint16_t catch_type_index_;
+};
+
 static constexpr size_t kNoLifetime = -1;
 static constexpr uint32_t kNoDexPc = -1;
 
@@ -575,7 +628,7 @@
         dex_pc_(dex_pc),
         lifetime_start_(kNoLifetime),
         lifetime_end_(kNoLifetime),
-        is_catch_block_(false) {}
+        try_catch_information_(nullptr) {}
 
   const GrowableArray<HBasicBlock*>& GetPredecessors() const {
     return predecessors_;
@@ -853,14 +906,24 @@
 
   bool IsInLoop() const { return loop_information_ != nullptr; }
 
-  HTryBoundary* GetTryEntry() const { return try_entry_; }
-  void SetTryEntry(HTryBoundary* try_entry) { try_entry_ = try_entry; }
-  bool IsInTry() const { return try_entry_ != nullptr; }
+  TryCatchInformation* GetTryCatchInformation() const { return try_catch_information_; }
+
+  void SetTryCatchInformation(TryCatchInformation* try_catch_information) {
+    try_catch_information_ = try_catch_information;
+  }
+
+  bool IsTryBlock() const {
+    return try_catch_information_ != nullptr && try_catch_information_->IsTryBlock();
+  }
+
+  bool IsCatchBlock() const {
+    return try_catch_information_ != nullptr && try_catch_information_->IsCatchBlock();
+  }
 
   // Returns the try entry that this block's successors should have. They will
   // be in the same try, unless the block ends in a try boundary. In that case,
   // the appropriate try entry will be returned.
-  HTryBoundary* ComputeTryEntryOfSuccessors() const;
+  const HTryBoundary* ComputeTryEntryOfSuccessors() const;
 
   // Returns whether this block dominates the blocked passed as parameter.
   bool Dominates(HBasicBlock* block) const;
@@ -873,9 +936,6 @@
 
   uint32_t GetDexPc() const { return dex_pc_; }
 
-  bool IsCatchBlock() const { return is_catch_block_; }
-  void SetIsCatchBlock() { is_catch_block_ = true; }
-
   bool EndsWithControlFlowInstruction() const;
   bool EndsWithIf() const;
   bool EndsWithTryBoundary() const;
@@ -895,11 +955,7 @@
   const uint32_t dex_pc_;
   size_t lifetime_start_;
   size_t lifetime_end_;
-  bool is_catch_block_;
-
-  // If this block is in a try block, `try_entry_` stores one of, possibly
-  // several, TryBoundary instructions entering it.
-  HTryBoundary* try_entry_;
+  TryCatchInformation* try_catch_information_;
 
   friend class HGraph;
   friend class HInstruction;
@@ -1676,7 +1732,9 @@
     UNREACHABLE();
   }
   virtual bool IsControlFlow() const { return false; }
+
   virtual bool CanThrow() const { return false; }
+  bool CanThrowIntoCatchBlock() const { return CanThrow() && block_->IsTryBlock(); }
 
   bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
   bool DoesAnyWrite() const { return side_effects_.DoesAnyWrite(); }