@@ -1424,44 +1424,29 @@ abstract class AstCodeGenerator
14241424 b.end ();
14251425 }
14261426
1427- final brTable = switchInfo.brTable;
1428- if (brTable != null ) {
1429- // Map each entry in the range to the appropriate jump table entry.
1430- final indexBlocks = < w.Label > [];
1431- final caseMap = brTable.caseMap;
1432- final defaultLabel =
1433- defaultCase != null ? switchLabels[defaultCase]! : doneLabel;
1434- for (int i = 0 ; i < brTable.rangeSize; i++ ) {
1435- final c = caseMap[i];
1436- indexBlocks.add (c == null ? defaultLabel : switchLabels[c]! );
1437- }
1438- brTable.brTableExpr (switchValueNonNullableLocal);
1439- b.br_table (indexBlocks, defaultLabel);
1440- } else {
1441- // Compare against all case values
1442- for (SwitchCase c in node.cases) {
1443- for (Expression exp in c.expressions) {
1444- if (exp is NullLiteral ||
1445- exp is ConstantExpression && exp.constant is NullConstant ) {
1446- // Null already checked, skip
1447- } else {
1448- switchInfo.compare (
1449- switchValueNonNullableLocal,
1450- () => translateExpression (exp, switchInfo.nonNullableType),
1451- );
1452- b.br_if (switchLabels[c]! );
1453- }
1427+ // Compare against all case values
1428+ for (SwitchCase c in node.cases) {
1429+ for (Expression exp in c.expressions) {
1430+ if (exp is NullLiteral ||
1431+ exp is ConstantExpression && exp.constant is NullConstant ) {
1432+ // Null already checked, skip
1433+ } else {
1434+ switchInfo.compare (
1435+ switchValueNonNullableLocal,
1436+ () => translateExpression (exp, switchInfo.nonNullableType),
1437+ );
1438+ b.br_if (switchLabels[c]! );
14541439 }
14551440 }
1441+ }
14561442
1457- // No explicit cases matched
1458- if (node.isExplicitlyExhaustive) {
1459- b.unreachable ();
1460- } else {
1461- w.Label defaultLabel =
1462- defaultCase != null ? switchLabels[defaultCase]! : doneLabel;
1463- b.br (defaultLabel);
1464- }
1443+ // No explicit cases matched
1444+ if (node.isExplicitlyExhaustive) {
1445+ b.unreachable ();
1446+ } else {
1447+ w.Label defaultLabel =
1448+ defaultCase != null ? switchLabels[defaultCase]! : doneLabel;
1449+ b.br (defaultLabel);
14651450 }
14661451
14671452 // Emit case bodies
@@ -4312,47 +4297,6 @@ class SwitchBackwardJumpInfo {
43124297 : defaultLoopLabel = null ;
43134298}
43144299
4315- /// Info needed to represent a switch statement using a br_table instruction.
4316- ///
4317- /// This is used for switches on integers and enums (using their indicies). We
4318- /// map each option to an index in the jump table and then jump directly to the
4319- /// target case. This is much faster than iteratively comparing each cases's
4320- /// expression to the switch expression.
4321- ///
4322- /// Sometimes switches over ranges of ints are sparse enough that a table would
4323- /// bloat the code compared to the iterative comparison.
4324- class BrTableInfo {
4325- // This is the minimum ratio of br_table indicies to actual mapped cases. If
4326- // this gets too large then most of the br_table indicies are unmapped and the
4327- // extra code size is not worth using a br_table.
4328- static const double _minTableSparseness = 2 ;
4329- // This is the maximum size where it's always worth it to use a br_table.
4330- // If the br_table is bigger than this then we start to check sparseness.
4331- // Below this point we always accept the potential code size hit.
4332- static const int _maxSparseSize = 50 ;
4333-
4334- final int rangeSize;
4335- final void Function (w.Local switchExprLocal) brTableExpr;
4336- final Map <int , SwitchCase > caseMap;
4337-
4338- BrTableInfo ._(this .rangeSize, this .caseMap, this .brTableExpr)
4339- : assert (! isTooSparse (rangeSize, caseMap));
4340-
4341- /// Heuristically validate whether the provided table would be too sparse and
4342- /// if so return null. Otherwise return the expected table.
4343- static BrTableInfo ? build (int rangeSize, Map <int , SwitchCase > caseMap,
4344- void Function (w.Local switchExprLocal) brTableExpr) {
4345- // Validate the table density and size is worth putting into a br_table.
4346- if (isTooSparse (rangeSize, caseMap)) return null ;
4347-
4348- return BrTableInfo ._(rangeSize, caseMap, brTableExpr);
4349- }
4350-
4351- static bool isTooSparse (int rangeSize, Map <int , SwitchCase > caseMap) =>
4352- (rangeSize / caseMap.length) > _minTableSparseness &&
4353- rangeSize > _maxSparseSize;
4354- }
4355-
43564300class SwitchInfo {
43574301 /// Non-nullable Wasm type of the `switch` expression. Used when the
43584302 /// expression is not nullable, and after the null check.
@@ -4379,11 +4323,6 @@ class SwitchInfo {
43794323 /// The `null: ...` case, if exists.
43804324 late final SwitchCase ? nullCase;
43814325
4382- /// Info needed to compile this switch statement into a wasm br_table. If null
4383- /// this switch statement should not use a br_table and should use comparison
4384- /// based case matching instead.
4385- BrTableInfo ? brTable;
4386-
43874326 SwitchInfo (AstCodeGenerator codeGen, SwitchStatement node) {
43884327 final translator = codeGen.translator;
43894328
@@ -4514,39 +4453,6 @@ class SwitchInfo {
45144453 nonNullableType = w.NumType .i64;
45154454 nullableType =
45164455 translator.classInfo[translator.boxedIntClass]! .nullableType;
4517-
4518- // Calculate the range covered by the cases and create the jump table.
4519- int ? minValue;
4520- int ? maxValue;
4521- Map <int , SwitchCase > caseMap = {};
4522- for (final c in node.cases) {
4523- for (final e in c.expressions) {
4524- final value = e is IntLiteral
4525- ? e.value
4526- : ((e as ConstantExpression ).constant as IntConstant ).value;
4527- caseMap[value] = c;
4528- if (minValue == null || value < minValue) minValue = value;
4529- if (maxValue == null || value > maxValue) maxValue = value;
4530- }
4531- }
4532- if (maxValue != null ) {
4533- final range = maxValue - minValue! + 1 ;
4534- if (minValue != 0 ) {
4535- caseMap = caseMap.map ((i, c) => MapEntry (i - minValue! , c));
4536- }
4537- brTable = BrTableInfo .build (range, caseMap, (switchExprLocal) {
4538- codeGen.b.local_get (switchExprLocal);
4539- // Normalize the value on 0 if necessary.
4540- if (minValue != 0 ) {
4541- codeGen.b.i64_const (minValue! );
4542- codeGen.b.i64_sub ();
4543- }
4544- // Now that we've normalized to 0 it should be safe to switch to i32.
4545- codeGen.b.i32_wrap_i64 ();
4546- });
4547- }
4548-
4549- // Provide a compare as a fallback in case the range is too sparse.
45504456 compare = (switchExprLocal, pushCaseExpr) {
45514457 codeGen.b.local_get (switchExprLocal);
45524458 pushCaseExpr ();
@@ -4561,68 +4467,6 @@ class SwitchInfo {
45614467 pushCaseExpr ();
45624468 codeGen.call (translator.jsStringEquals.reference);
45634469 };
4564- } else if (switchExprClass.isEnum) {
4565- // If this is an applicable switch over enums, create a jump table.
4566- bool isValid = true ;
4567- final caseMap = < int , SwitchCase > {};
4568- int ? minIndex;
4569- int maxIndex = 0 ;
4570- outer:
4571- for (final c in node.cases) {
4572- for (final e in c.expressions) {
4573- if (e is ! ConstantExpression ) {
4574- isValid = false ;
4575- break outer;
4576- }
4577- final constant = e.constant;
4578- if (constant is ! InstanceConstant ) {
4579- isValid = false ;
4580- break outer;
4581- }
4582- if (constant.classNode != switchExprClass) {
4583- isValid = false ;
4584- break outer;
4585- }
4586- final enumIndex =
4587- (constant.fieldValues[translator.enumIndexField.fieldReference]
4588- as IntConstant )
4589- .value;
4590- caseMap[enumIndex] = c;
4591- if (enumIndex > maxIndex) maxIndex = enumIndex;
4592- if (minIndex == null || enumIndex < minIndex) minIndex = enumIndex;
4593- }
4594- }
4595-
4596- if (isValid && minIndex != null ) {
4597- final range = maxIndex - minIndex + 1 ;
4598- brTable = BrTableInfo .build (range, caseMap, (switchExprLocal) {
4599- codeGen.b.local_get (switchExprLocal);
4600- codeGen.call (translator.enumIndexField.getterReference);
4601- if (minIndex != 0 ) {
4602- codeGen.b.i64_const (minIndex! );
4603- codeGen.b.i64_sub ();
4604- }
4605- // Now that we've normalized to 0 it should be safe to switch to i32.
4606- codeGen.b.i32_wrap_i64 ();
4607- });
4608- }
4609-
4610- if (brTable == null ) {
4611- // Object identity switch
4612- nonNullableType = translator.topTypeNonNullable;
4613- nullableType = translator.topType;
4614- } else {
4615- nonNullableType =
4616- translator.classInfo[switchExprClass]! .nonNullableType;
4617- nullableType = translator.classInfo[switchExprClass]! .nullableType;
4618- }
4619-
4620- // Set compare anyway for state machine handling
4621- compare = (switchExprLocal, pushCaseExpr) {
4622- codeGen.b.local_get (switchExprLocal);
4623- pushCaseExpr ();
4624- codeGen.call (translator.coreTypes.identicalProcedure.reference);
4625- };
46264470 } else {
46274471 // Object identity switch
46284472 nonNullableType = translator.topTypeNonNullable;
0 commit comments