OSDN Git Service

ART: Optimize catch phi creation to save memory.
authorDavid Brazdil <dbrazdil@google.com>
Fri, 18 Sep 2015 13:58:57 +0000 (14:58 +0100)
committerDavid Brazdil <dbrazdil@google.com>
Fri, 18 Sep 2015 14:00:28 +0000 (15:00 +0100)
Catch phis are eagerly created for all vregs and then removed as
throwing instructions with undefined locals are encountered. This can
be optimized since rougly one third of vregs is already undefined with
the first throwing instruction.

Change-Id: Ia4e66f19ea03f9a129b4b64d4193d262fff45224

compiler/optimizing/ssa_builder.cc
compiler/optimizing/ssa_builder.h

index 6f71ea3..f511603 100644 (file)
@@ -345,6 +345,33 @@ void SsaBuilder::BuildSsa() {
   }
 }
 
+ArenaVector<HInstruction*>* SsaBuilder::GetLocalsFor(HBasicBlock* block) {
+  DCHECK_LT(block->GetBlockId(), locals_for_.size());
+  ArenaVector<HInstruction*>* locals = &locals_for_[block->GetBlockId()];
+  const size_t vregs = GetGraph()->GetNumberOfVRegs();
+  if (locals->empty() && vregs != 0u) {
+    locals->resize(vregs, nullptr);
+
+    if (block->IsCatchBlock()) {
+      ArenaAllocator* arena = GetGraph()->GetArena();
+      // We record incoming inputs of catch phis at throwing instructions and
+      // must therefore eagerly create the phis. Phis for undefined vregs will
+      // be deleted when the first throwing instruction with the vreg undefined
+      // is encountered. Unused phis will be removed by dead phi analysis.
+      for (size_t i = 0; i < vregs; ++i) {
+        // No point in creating the catch phi if it is already undefined at
+        // the first throwing instruction.
+        if ((*current_locals_)[i] != nullptr) {
+          HPhi* phi = new (arena) HPhi(arena, i, 0, Primitive::kPrimVoid);
+          block->AddPhi(phi);
+          (*locals)[i] = phi;
+        }
+      }
+    }
+  }
+  return locals;
+}
+
 HInstruction* SsaBuilder::ValueOfLocal(HBasicBlock* block, size_t local) {
   ArenaVector<HInstruction*>* locals = GetLocalsFor(block);
   DCHECK_LT(local, locals->size());
index 804296f..79f1a28 100644 (file)
@@ -61,28 +61,9 @@ class SsaBuilder : public HGraphVisitor {
 
   void BuildSsa();
 
-  ArenaVector<HInstruction*>* GetLocalsFor(HBasicBlock* block) {
-    DCHECK_LT(block->GetBlockId(), locals_for_.size());
-    ArenaVector<HInstruction*>* locals = &locals_for_[block->GetBlockId()];
-    if (locals->empty() && GetGraph()->GetNumberOfVRegs() != 0u) {
-      const size_t vregs = GetGraph()->GetNumberOfVRegs();
-      locals->resize(vregs, nullptr);
-
-      if (block->IsCatchBlock()) {
-        // We record incoming inputs of catch phis at throwing instructions and
-        // must therefore eagerly create the phis. Unused phis will be removed
-        // in the dead phi analysis.
-        ArenaAllocator* arena = GetGraph()->GetArena();
-        for (size_t i = 0; i < vregs; ++i) {
-          HPhi* phi = new (arena) HPhi(arena, i, 0, Primitive::kPrimVoid);
-          block->AddPhi(phi);
-          (*locals)[i] = phi;
-        }
-      }
-    }
-    return locals;
-  }
-
+  // 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 VisitBasicBlock(HBasicBlock* block);