[vm/compiler] Do not generate unnecessary field length guards
GuardFieldLengthInstr::EmitNativeCode aborts background compilation
if we're not tracking list length for a field
(guarded_list_length() == Field::kNoFixedLength).
I'm seeing a lot of aborted background compilations on a Flutter app with
the reason "GuardFieldLengthInstr: field state changed while compiling".
This CL avoids generating these useless (and harmful) GuardFieldLengthInstr
if not tracking list length for a field.
Change-Id: I2a083c5df35e89893c9e787bebe4e3e7d8177c83
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99737
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Aart Bik <ajcbik@google.com>
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 07ac0b0..aff93f9 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -485,8 +485,19 @@
LocalVariable* store_expression = MakeTemporary();
instructions += LoadLocal(store_expression);
instructions += GuardFieldClass(field_clone, GetNextDeoptId());
- instructions += LoadLocal(store_expression);
- instructions += GuardFieldLength(field_clone, GetNextDeoptId());
+
+ // Field length guard can be omitted if it is not needed.
+ // However, it is possible that we were tracking list length previously,
+ // and generated length guards in the past. We need to generate same IL
+ // to keep deopt ids stable, but we can discard generated IL fragment
+ // if length guard is not needed.
+ Fragment length_guard;
+ length_guard += LoadLocal(store_expression);
+ length_guard += GuardFieldLength(field_clone, GetNextDeoptId());
+
+ if (field_clone.needs_length_check()) {
+ instructions += length_guard;
+ }
// If we are tracking exactness of the static type of the field then
// emit appropriate guard.