Merge "Add stack trace info to hprof completion message"
diff --git a/compiler/dex/mir_method_info.cc b/compiler/dex/mir_method_info.cc
index 658e7d6..c250bd9 100644
--- a/compiler/dex/mir_method_info.cc
+++ b/compiler/dex/mir_method_info.cc
@@ -100,8 +100,12 @@
     } else {
       // The method index is actually the dex PC in this case.
       // Calculate the proper dex file and target method idx.
+
+      // We must be in JIT mode if we get here.
       CHECK(use_jit);
-      CHECK_EQ(invoke_type, kVirtual);
+
+      // The invoke type better be virtual, except for the string init special case above.
+      CHECK_EQ(invoke_type, string_init ? kDirect : kVirtual);
       // Don't devirt if we are in a different dex file since we can't have direct invokes in
       // another dex file unless we always put a direct / patch pointer.
       devirt_target = nullptr;
diff --git a/compiler/optimizing/dominator_test.cc b/compiler/optimizing/dominator_test.cc
index feb8b20..91e4a997 100644
--- a/compiler/optimizing/dominator_test.cc
+++ b/compiler/optimizing/dominator_test.cc
@@ -133,9 +133,8 @@
 
   const uint32_t dominators[] = {
       kInvalidBlockId,
-      3,
-      kInvalidBlockId,
-      0
+      0,
+      kInvalidBlockId
   };
 
   TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
diff --git a/compiler/optimizing/graph_test.cc b/compiler/optimizing/graph_test.cc
index d530564..d4b9b71 100644
--- a/compiler/optimizing/graph_test.cc
+++ b/compiler/optimizing/graph_test.cc
@@ -164,7 +164,7 @@
 
   // Ensure there is only one back edge.
   ASSERT_EQ(if_block->GetPredecessors().size(), 2u);
-  ASSERT_EQ(if_block->GetPredecessors()[0], entry_block->GetSingleSuccessor());
+  ASSERT_EQ(if_block->GetPredecessors()[0], entry_block);
   ASSERT_NE(if_block->GetPredecessors()[1], if_block);
 
   // Ensure the new block is the back edge.
@@ -199,7 +199,7 @@
 
   // Ensure there is only one back edge.
   ASSERT_EQ(if_block->GetPredecessors().size(), 2u);
-  ASSERT_EQ(if_block->GetPredecessors()[0], entry_block->GetSingleSuccessor());
+  ASSERT_EQ(if_block->GetPredecessors()[0], entry_block);
   ASSERT_NE(if_block->GetPredecessors()[1], if_block);
 
   // Ensure the new block is the back edge.
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 2e79df1..20c4f1f 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -419,10 +419,7 @@
   size_t inline_max_code_units = compiler_driver_->GetCompilerOptions().GetInlineMaxCodeUnits();
   if (code_item->insns_size_in_code_units_ > inline_max_code_units) {
     VLOG(compiler) << "Method " << PrettyMethod(method)
-                   << " is too big to inline: "
-                   << code_item->insns_size_in_code_units_
-                   << " > "
-                   << inline_max_code_units;
+                   << " is too big to inline";
     return false;
   }
 
@@ -642,12 +639,9 @@
 
   for (; !it.Done(); it.Advance()) {
     HBasicBlock* block = it.Current();
-
-    if (block->IsLoopHeader() && block->GetLoopInformation()->IsIrreducible()) {
-      // Don't inline methods with irreducible loops, they could prevent some
-      // optimizations to run.
+    if (block->IsLoopHeader()) {
       VLOG(compiler) << "Method " << PrettyMethod(method_index, callee_dex_file)
-                     << " could not be inlined because it contains an irreducible loop";
+                     << " could not be inlined because it contains a loop";
       return false;
     }
 
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index adf8734..2eabadf 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -288,10 +288,9 @@
 
   // Make sure the loop has only one pre header. This simplifies SSA building by having
   // to just look at the pre header to know which locals are initialized at entry of the
-  // loop. Also, don't allow the entry block to be a pre header: this simplifies inlining
-  // this graph.
+  // loop.
   size_t number_of_incomings = header->GetPredecessors().size() - info->NumberOfBackEdges();
-  if (number_of_incomings != 1 || (GetEntryBlock()->GetSingleSuccessor() == header)) {
+  if (number_of_incomings != 1) {
     HBasicBlock* pre_header = new (arena_) HBasicBlock(this, header->GetDexPc());
     AddBlock(pre_header);
     pre_header->AddInstruction(new (arena_) HGoto(header->GetDexPc()));
@@ -1838,7 +1837,6 @@
     DCHECK(GetBlocks()[0]->IsEntryBlock());
     DCHECK(GetBlocks()[2]->IsExitBlock());
     DCHECK(!body->IsExitBlock());
-    DCHECK(!body->IsInLoop());
     HInstruction* last = body->GetLastInstruction();
 
     invoke->GetBlock()->instructions_.AddAfter(invoke, body->GetInstructions());
@@ -1897,7 +1895,7 @@
     // Update the meta information surrounding blocks:
     // (1) the graph they are now in,
     // (2) the reverse post order of that graph,
-    // (3) their potential loop information, inner and outer,
+    // (3) the potential loop information they are now in,
     // (4) try block membership.
     // Note that we do not need to update catch phi inputs because they
     // correspond to the register file of the outer method which the inlinee
@@ -1926,24 +1924,15 @@
     for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
       HBasicBlock* current = it.Current();
       if (current != exit_block_ && current != entry_block_ && current != first) {
+        DCHECK(!current->IsInLoop());
         DCHECK(current->GetTryCatchInformation() == nullptr);
         DCHECK(current->GetGraph() == this);
         current->SetGraph(outer_graph);
         outer_graph->AddBlock(current);
         outer_graph->reverse_post_order_[++index_of_at] = current;
-        if (!current->IsInLoop()) {
+        if (loop_info != nullptr) {
           current->SetLoopInformation(loop_info);
-        } else if (current->IsLoopHeader()) {
-          // Clear the information of which blocks are contained in that loop. Since the
-          // information is stored as a bit vector based on block ids, we have to update
-          // it, as those block ids were specific to the callee graph and we are now adding
-          // these blocks to the caller graph.
-          current->GetLoopInformation()->ClearAllBlocks();
-        }
-        if (current->IsInLoop()) {
-          for (HLoopInformationOutwardIterator loop_it(*current);
-               !loop_it.Done();
-               loop_it.Advance()) {
+          for (HLoopInformationOutwardIterator loop_it(*at); !loop_it.Done(); loop_it.Advance()) {
             loop_it.Current()->Add(current);
           }
         }
@@ -1956,9 +1945,7 @@
     outer_graph->AddBlock(to);
     outer_graph->reverse_post_order_[++index_of_at] = to;
     if (loop_info != nullptr) {
-      if (!to->IsInLoop()) {
-        to->SetLoopInformation(loop_info);
-      }
+      to->SetLoopInformation(loop_info);
       for (HLoopInformationOutwardIterator loop_it(*at); !loop_it.Done(); loop_it.Advance()) {
         loop_it.Current()->Add(to);
       }
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 5246fd1..019be5d 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -689,10 +689,6 @@
   void Add(HBasicBlock* block);
   void Remove(HBasicBlock* block);
 
-  void ClearAllBlocks() {
-    blocks_.ClearAllBits();
-  }
-
  private:
   // Internal recursive implementation of `Populate`.
   void PopulateRecursive(HBasicBlock* block);
diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc
index fc257c0..f3f5f95 100644
--- a/runtime/jit/profile_saver.cc
+++ b/runtime/jit/profile_saver.cc
@@ -22,16 +22,16 @@
 
 namespace art {
 
-// An arbitrary value to throttle save requests. Set to 500ms for now.
+// An arbitrary value to throttle save requests. Set to 2s for now.
 static constexpr const uint64_t kMilisecondsToNano = 1000000;
-static constexpr const uint64_t kMinimumTimeBetweenCodeCacheUpdatesNs = 500 * kMilisecondsToNano;
+static constexpr const uint64_t kMinimumTimeBetweenCodeCacheUpdatesNs = 2000 * kMilisecondsToNano;
 
 // TODO: read the constants from ProfileOptions,
 // Add a random delay each time we go to sleep so that we don't hammer the CPU
 // with all profile savers running at the same time.
-static constexpr const uint64_t kRandomDelayMaxMs = 10 * 1000;  // 10 seconds
-static constexpr const uint64_t kMaxBackoffMs = 4 * 60 * 1000;  // 4 minutes
-static constexpr const uint64_t kSavePeriodMs = 4 * 1000;  // 4 seconds
+static constexpr const uint64_t kRandomDelayMaxMs = 20 * 1000;  // 20 seconds
+static constexpr const uint64_t kMaxBackoffMs = 5 * 60 * 1000;  // 5 minutes
+static constexpr const uint64_t kSavePeriodMs = 10 * 1000;  // 10 seconds
 static constexpr const double kBackoffCoef = 1.5;
 
 static constexpr const uint32_t kMinimumNrOrMethodsToSave = 10;
diff --git a/test/004-StackWalk/src/Main.java b/test/004-StackWalk/src/Main.java
index 072b1d0..883ce2c 100644
--- a/test/004-StackWalk/src/Main.java
+++ b/test/004-StackWalk/src/Main.java
@@ -2,14 +2,14 @@
   public Main() {
   }
 
-  boolean doThrow = false;
-
   int $noinline$f() throws Exception {
     g(1);
     g(2);
 
-    // This currently defeats inlining of `f`.
-    if (doThrow) { throw new Error(); }
+    // This loop currently defeats inlining of `f`.
+    for (int i = 0; i < 10; i++) {
+      Thread.sleep(0);
+    }
     return 0;
   }
 
diff --git a/test/482-checker-loop-back-edge-use/src/Main.java b/test/482-checker-loop-back-edge-use/src/Main.java
index f8f0aa3..d0b33b9 100644
--- a/test/482-checker-loop-back-edge-use/src/Main.java
+++ b/test/482-checker-loop-back-edge-use/src/Main.java
@@ -40,9 +40,6 @@
   /// CHECK-EVAL:    <<GotoLiv2>> + 2 == <<ArgLoopUse2>>
 
   public static void loop2(boolean incoming) {
-    // Add some code at entry to avoid having the entry block be a pre header.
-    // This avoids having to create a synthesized block.
-    System.out.println("Enter");
     while (true) {
       System.out.println("foo");
       while (incoming) {}
@@ -173,9 +170,6 @@
   /// CHECK-EVAL:    <<GotoLiv1>> + 2 == <<ArgLoopUse>>
 
   public static void loop9() {
-    // Add some code at entry to avoid having the entry block be a pre header.
-    // This avoids having to create a synthesized block.
-    System.out.println("Enter");
     while (Runtime.getRuntime() != null) {
       // 'incoming' must only have a use in the inner loop.
       boolean incoming = field;
diff --git a/test/510-checker-try-catch/smali/SsaBuilder.smali b/test/510-checker-try-catch/smali/SsaBuilder.smali
index a6a5bfe..710e849 100644
--- a/test/510-checker-try-catch/smali/SsaBuilder.smali
+++ b/test/510-checker-try-catch/smali/SsaBuilder.smali
@@ -21,7 +21,7 @@
 
 ## CHECK-START: int SsaBuilder.testSimplifyCatchBlock(int, int, int) ssa_builder (after)
 
-## CHECK:      name             "B1"
+## CHECK:      name             "B0"
 ## CHECK-NEXT: from_bci
 ## CHECK-NEXT: to_bci
 ## CHECK-NEXT: predecessors
@@ -39,15 +39,12 @@
 ## CHECK:      name             "<<BExtracted>>"
 ## CHECK-NEXT: from_bci
 ## CHECK-NEXT: to_bci
-## CHECK-NEXT: predecessors     "B1" "<<BCatch>>"
+## CHECK-NEXT: predecessors     "B0" "<<BCatch>>"
 ## CHECK-NOT:  flags            "catch_block"
 ## CHECK:      Add
 
 .method public static testSimplifyCatchBlock(III)I
     .registers 4
-    # Avoid entry block be a pre header, which leads to
-    # the cfg simplifier to add a synthesized block.
-    goto :catch_all
 
     :catch_all
     add-int/2addr p0, p1
diff --git a/test/564-checker-inline-loop/expected.txt b/test/564-checker-inline-loop/expected.txt
deleted file mode 100644
index e69de29..0000000
--- a/test/564-checker-inline-loop/expected.txt
+++ /dev/null
diff --git a/test/564-checker-inline-loop/info.txt b/test/564-checker-inline-loop/info.txt
deleted file mode 100644
index a590bc6..0000000
--- a/test/564-checker-inline-loop/info.txt
+++ /dev/null
@@ -1 +0,0 @@
-Tests inlining of loops in the optimizing compiler.
diff --git a/test/564-checker-inline-loop/src/Main.java b/test/564-checker-inline-loop/src/Main.java
deleted file mode 100644
index 6929913..0000000
--- a/test/564-checker-inline-loop/src/Main.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-public class Main {
-
-  /// CHECK-START: int Main.inlineLoop() inliner (before)
-  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  /// CHECK-DAG:                      Return [<<Invoke>>]
-
-  /// CHECK-START: int Main.inlineLoop() inliner (after)
-  /// CHECK-NOT:                      InvokeStaticOrDirect
-
-  /// CHECK-START: int Main.inlineLoop() inliner (after)
-  /// CHECK-DAG:     <<Constant:i\d+>>   IntConstant 42
-  /// CHECK-DAG:                         Return [<<Constant>>]
-
-  /// CHECK-START: int Main.inlineLoop() licm (after)
-  /// CHECK:                         Goto loop:{{B\d+}}
-
-  public static int inlineLoop() {
-    return loopMethod();
-  }
-
-  /// CHECK-START: void Main.inlineWithinLoop() inliner (before)
-  /// CHECK:      InvokeStaticOrDirect
-
-  /// CHECK-START: void Main.inlineWithinLoop() inliner (after)
-  /// CHECK-NOT:  InvokeStaticOrDirect
-
-  /// CHECK-START: void Main.inlineWithinLoop() licm (after)
-  /// CHECK-DAG:  Goto loop:<<OuterLoop:B\d+>> outer_loop:none
-  /// CHECK-DAG:  Goto outer_loop:<<OuterLoop>>
-
-  public static void inlineWithinLoop() {
-    while (doLoop) {
-      loopMethod();
-    }
-  }
-
-  public static int loopMethod() {
-    while (doLoop) {}
-    return 42;
-  }
-
-  public static boolean doLoop = false;
-
-  public static void main(String[] args) {
-    inlineLoop();
-    inlineWithinLoop();
-  }
-}