[vm] Don't re-enqueue functions after unoptimized compiles

Change-Id: I18ea0915971f073af14a99273fe75ed2ec32ed07
Reviewed-on: https://dart-review.googlesource.com/c/81161
Commit-Queue: Zach Anderson <zra@google.com>
Reviewed-by: RĂ©gis Crelier <regis@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 83c5fe9..f3c1792 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -1213,9 +1213,8 @@
 #endif  // !defined(PRODUCT)
 
   // If running with interpreter, do the unoptimized compilation first.
-  const bool optimized = !FLAG_enable_interpreter ||
-                         ((function.unoptimized_code() != Object::null()) &&
-                          function.WasCompiled());
+  const bool optimized = function.ShouldCompilerOptimize();
+  ASSERT(FLAG_enable_interpreter || optimized);
 
   // If we are in the optimizing in the mutator/Dart thread, then
   // this is either an OSR compilation or background compilation is
@@ -1659,6 +1658,10 @@
         function = function_queue()->PeekFunction();
       }
       while (running_ && !function.IsNull() && !isolate_->IsTopLevelParsing()) {
+        // This is false if we are compiling bytecode -> unoptimized code.
+        const bool optimizing = function.ShouldCompilerOptimize();
+        ASSERT(FLAG_enable_interpreter || optimizing);
+
         // Check that we have aggregated and cleared the stats.
         Compiler::CompileOptimizedFunction(thread, function,
                                            Compiler::kNoOSRDeoptId);
@@ -1674,7 +1677,8 @@
             const Function& old = Function::Handle(qelem->Function());
             // If an optimizable method is not optimized, put it back on
             // the background queue (unless it was passed to foreground).
-            if ((!old.HasOptimizedCode() && old.IsOptimizable()) ||
+            if ((optimizing && !old.HasOptimizedCode() &&
+                 old.IsOptimizable()) ||
                 FLAG_stress_test_background_compilation) {
               if (old.is_background_optimizable() &&
                   Compiler::CanOptimizeFunction(thread, old)) {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 44f95e8..640e298 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -8119,6 +8119,11 @@
   return HasCode() && Code::Handle(CurrentCode()).is_optimized();
 }
 
+bool Function::ShouldCompilerOptimize() const {
+  return !FLAG_enable_interpreter ||
+         ((unoptimized_code() != Object::null()) && WasCompiled());
+}
+
 RawString* Function::UserVisibleName() const {
   if (FLAG_show_internal_names) {
     return name();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index d1beda1..c0685db 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2670,6 +2670,9 @@
 
   bool HasOptimizedCode() const;
 
+  // Whether the function is ready for compiler optimizations.
+  bool ShouldCompilerOptimize() const;
+
   // Returns true if the argument counts are valid for calling this function.
   // Otherwise, it returns false and the reason (if error_message is not NULL).
   bool AreValidArgumentCounts(intptr_t num_type_arguments,