From 5492cfd1bc0317d49f788856c63692804138e0d4 Mon Sep 17 00:00:00 2001 From: Stephen Adams Date: Wed, 27 Aug 2025 11:44:04 -0700 Subject: [PATCH] [dart2js] Never elide `_Enum.index` This ensures that `_Enum.index` is always available for switch strength reduction optimizations. Most real programs use the index of at least one `enum`, so the field is not usually elided. This change makes small tests and benchmarks behave more like real programs where these optimizations happen. Bug: #51657 CoreLibraryReviewExempt: dart2js specific annotation Change-Id: If98e483d7cce265e823fd574565089e328215cca Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/446481 Reviewed-by: Nate Biggs Commit-Queue: Stephen Adams Reviewed-by: Mayank Patke --- benchmarks/SwitchFSM/dart/SwitchFSM.dart | 6 ------ .../model_data/effectively_constant_state.dart | 18 ++++++++---------- sdk/lib/core/enum.dart | 2 ++ 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/benchmarks/SwitchFSM/dart/SwitchFSM.dart b/benchmarks/SwitchFSM/dart/SwitchFSM.dart index cb1214baf6e..50e4accedb0 100644 --- a/benchmarks/SwitchFSM/dart/SwitchFSM.dart +++ b/benchmarks/SwitchFSM/dart/SwitchFSM.dart @@ -136,12 +136,6 @@ class Benchmark extends BenchmarkBase { enum SomeEnum { element } void main() { - // TODO(http://dartbug.com/51657): dart2js will remove `_Enum.index` in simple - // programs that don't appear to use the field. This defeats the enum-switch - // optimization that works more reliably in larger programs. Remove this code - // that marks `_Enum.index` as used when #51657 is fixed. - Expect.equals(0, SomeEnum.element.index); - final benchmarks = [ Benchmark('enum', match_enum.match), Benchmark('int', match_int.match), diff --git a/pkg/compiler/test/codegen/model_data/effectively_constant_state.dart b/pkg/compiler/test/codegen/model_data/effectively_constant_state.dart index c55dba2104c..7baca39a319 100644 --- a/pkg/compiler/test/codegen/model_data/effectively_constant_state.dart +++ b/pkg/compiler/test/codegen/model_data/effectively_constant_state.dart @@ -4,16 +4,15 @@ enum Enum { a, b, c } -/*member: tester1:params=0*/ -@pragma('dart2js:noInline') +@pragma('dart2js:never-inline') tester1() {} /*member: tester2:params=0*/ -@pragma('dart2js:noInline') +@pragma('dart2js:never-inline') tester2() {} /*member: tester3:params=0*/ -@pragma('dart2js:noInline') +@pragma('dart2js:never-inline') tester3() {} class Class { @@ -26,7 +25,7 @@ class Class { Class({this.state1 = 1, this.state2 = Enum.c}); /*member: Class.method1a:calls=[tester2(0)],params=0*/ - @pragma('dart2js:noInline') + @pragma('dart2js:never-inline') method1a() { if (state1 == 0) { return tester1(); @@ -39,7 +38,7 @@ class Class { // TODO(johnniwinther): Inline switch cases with constant expressions. /*member: Class.method1b:calls=[tester2(0)],params=0,switch*/ - @pragma('dart2js:noInline') + @pragma('dart2js:never-inline') method1b() { switch (state1) { case 0: @@ -52,7 +51,7 @@ class Class { } /*member: Class.method2a:calls=[tester3(0)],params=0*/ - @pragma('dart2js:noInline') + @pragma('dart2js:never-inline') method2a() { if (state2 == Enum.a) { return tester1(); @@ -63,10 +62,9 @@ class Class { } } - /*member: Class.method2b:calls=[tester1(0),tester2(0),tester3(0)],params=0,switch*/ - @pragma('dart2js:noInline') + /*member: Class.method2b:calls=[tester3(0)],params=0,switch*/ + @pragma('dart2js:never-inline') method2b() { - // TODO(johnniwinther): Eliminate dead code in enum switch. switch (state2) { case Enum.a: return tester1(); diff --git a/sdk/lib/core/enum.dart b/sdk/lib/core/enum.dart index 3cbbf5068d4..35ce1764d61 100644 --- a/sdk/lib/core/enum.dart +++ b/sdk/lib/core/enum.dart @@ -102,6 +102,8 @@ abstract interface class Enum { /// Superclass of all enum class implementations. @pragma('dyn-module:language-impl:extendable') abstract class _Enum implements Enum { + // See http://dartbug.com/51657 for discussion of dart2js pragma. + @pragma('dart2js:noElision') final int index; @pragma('dyn-module:language-impl:callable')