Create codegen work item for all members

Ensures that constants of effectively constant instance fields are
registered also with --omit-implicit-checks.

Change-Id: Icc31799f1cc5f565321c832780f30c711e9c8c50
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/96160
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index e605804..3f13c78 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -26,7 +26,6 @@
 import '../js_backend/native_data.dart';
 import '../kernel/kernel_strategy.dart';
 import '../native/behavior.dart';
-import '../options.dart';
 import '../ssa/builder_kernel.dart';
 import '../ssa/nodes.dart';
 import '../ssa/ssa.dart';
@@ -138,21 +137,9 @@
   KernelCodegenWorkItemBuilder(
       this._backend, this._closedWorld, this._globalInferenceResults);
 
-  CompilerOptions get _options => _backend.compiler.options;
-
   @override
   CodegenWorkItem createWorkItem(MemberEntity entity) {
     if (entity.isAbstract) return null;
-
-    // Codegen inlines field initializers. It only needs to generate
-    // code for checked setters.
-    if (entity.isField && entity.isInstanceMember) {
-      if (!_options.parameterCheckPolicy.isEmitted ||
-          entity.enclosingClass.isClosure) {
-        return null;
-      }
-    }
-
     return new KernelCodegenWorkItem(
         _backend, _closedWorld, _globalInferenceResults, entity);
   }
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index e1fe0fb..bbb9618 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -238,6 +238,15 @@
                 // eager and non-final fields.
                 backend.constants.registerLazyStatic(targetElement);
               }
+            } else {
+              assert(targetElement.isInstanceMember);
+              if (_fieldAnalysis
+                      .getFieldData(targetElement)
+                      .isEffectivelyFinal ||
+                  !options.parameterCheckPolicy.isEmitted) {
+                // No need for a checked setter.
+                return null;
+              }
             }
             buildField(target);
           } else if (target is ir.FunctionExpression) {
@@ -262,8 +271,8 @@
           buildConstructorBody(constructor);
           break;
         case MemberKind.closureField:
-          failedAt(targetElement, "Unexpected closure field: $targetElement");
-          break;
+          // Closure fields have no setter and therefore never require any code.
+          return null;
         case MemberKind.signature:
           ir.Node target = definition.node;
           ir.FunctionNode originalClosureNode;
diff --git a/tests/compiler/dart2js_extra/effectively_constant_instance_field_test.dart b/tests/compiler/dart2js_extra/effectively_constant_instance_field_test.dart
new file mode 100644
index 0000000..94020a2
--- /dev/null
+++ b/tests/compiler/dart2js_extra/effectively_constant_instance_field_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--omit-implicit-checks
+
+import 'package:expect/expect.dart';
+
+class C {
+  const C();
+}
+
+class A {
+  var field = const C();
+}
+
+class B {
+  var field;
+}
+
+@pragma('dart2js:noInline')
+test(o) => o.field;
+
+main() {
+  Expect.isNotNull(test(new A()));
+  Expect.isNull(test(new B()));
+}