From 1345eb8baaf5a65db0502c21c80481d40c9c5fd2 Mon Sep 17 00:00:00 2001 From: Nicholas Shahan Date: Fri, 8 Oct 2021 20:41:37 +0000 Subject: [PATCH] [ddc] Fix list literal control flow optimization Restore the behavior originally added in https://dart-review.googlesource.com/c/sdk/+/172082 to call `.push()` on Javascript Arrays directly when it is safe. After some experimenting this optimization no longer appears to be as effective for lists of native types (the type check is little overhead) but is still observable for lists of user defined interface types. Change-Id: I034666a512a7886e5022498e2d6bd3f8aaceebbd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215483 Reviewed-by: Stephen Adams Commit-Queue: Nicholas Shahan --- pkg/dev_compiler/lib/src/kernel/compiler.dart | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart index f55ce1a3d1b..ca5860bf7ec 100644 --- a/pkg/dev_compiler/lib/src/kernel/compiler.dart +++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart @@ -4803,21 +4803,33 @@ class ProgramCompiler extends ComputeOnceConstantVisitor /// list and the element type is known to be invariant so it can skip the /// type check. bool isNativeListInvariantAdd(InvocationExpression node) { - Expression receiver; - if (receiver != null && node.name.text == 'add') { + if (node is InstanceInvocation && + node.isInvariant && + node.name.text == 'add') { // The call to add is marked as invariant, so the type check on the // parameter to add is not needed. + var receiver = node.receiver; if (receiver is VariableGet && receiver.variable.isFinal && !receiver.variable.isLate) { // The receiver is a final variable, so it only contains the // initializer value. Also, avoid late variables in case the CFE // lowering of late variables is changed in the future. - if (receiver.variable.initializer is ListLiteral) { + var initializer = receiver.variable.initializer; + if (initializer is ListLiteral) { // The initializer is a list literal, so we know the list can be // grown, modified, and is represented by a JavaScript Array. return true; } + if (initializer is StaticInvocation && + initializer.target.enclosingClass == _coreTypes.listClass && + initializer.target.name.text == 'of' && + initializer.arguments.named.isEmpty) { + // The initializer is a `List.of()` call from the dart:core library + // and the growable named argument has not been passed (it defaults + // to true). + return true; + } } } return false;