Skip to content

Commit

Permalink
[cfe] Turn wildcard locals into ExpressionStatements or EmptyStatements.
Browse files Browse the repository at this point in the history
This CL converts VariableDeclarations to ExpressionStatements or EmptyStatements.
If the declaration has an initializer, it will be converted to an ExpressionStatement, otherwise, an EmptyStatement.

This will help the VM and potentially other backends, avoid allocating space for a variable declaration that will never be used.

Bug: #55655
Change-Id: I845b7e5e61fbb0340623ec0dee7269491bc09513
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373640
Commit-Queue: Kallen Tu <kallentu@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
  • Loading branch information
kallentu authored and Commit Queue committed Jul 2, 2024
1 parent 27cbf50 commit 2f80ad6
Show file tree
Hide file tree
Showing 19 changed files with 214 additions and 42 deletions.
70 changes: 58 additions & 12 deletions pkg/front_end/lib/src/kernel/body_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4065,13 +4065,26 @@ class BodyBuilder extends StackListenerImpl
return;
}
VariableDeclaration variable = node as VariableDeclaration;
if (annotations != null) {
for (int i = 0; i < annotations.length; i++) {
variable.addAnnotation(annotations[i]);
if (variable.isWildcard && scope.kind != ScopeKind.forStatement) {
// Wildcard variable declarations can be removed, except for the ones in
// for loops. This logic turns them into `ExpressionStatement`s or
// `EmptyStatement`s so the backends don't need to allocate space for
// them.
if (variable.initializer case var initializer?) {
push(forest.createExpressionStatement(
offsetForToken(endToken), initializer));
} else {
push(forest.createEmptyStatement(offsetForToken(endToken)));
}
} else {
if (annotations != null) {
for (int i = 0; i < annotations.length; i++) {
variable.addAnnotation(annotations[i]);
}
(variablesWithMetadata ??= <VariableDeclaration>[]).add(variable);
}
(variablesWithMetadata ??= <VariableDeclaration>[]).add(variable);
push(variable);
}
push(variable);
} else {
List<VariableDeclaration>? variables =
const FixedNullableList<VariableDeclaration>()
Expand All @@ -4085,19 +4098,52 @@ class BodyBuilder extends StackListenerImpl
push(new ParserRecovery(offsetForToken(endToken)));
return;
}
if (annotations != null) {
VariableDeclaration first = variables.first;
for (int i = 0; i < annotations.length; i++) {
first.addAnnotation(annotations[i]);
if (scope.kind != ScopeKind.forStatement) {
// Wildcard variable declarations can be removed, except for the ones in
// for loops. This logic turns them into `ExpressionStatement`s or
// `EmptyStatement`s so the backends don't need to allocate space for
// them.
List<Statement> declarationStatements = [];
for (VariableDeclaration variable in variables) {
if (variable.isWildcard) {
if (variable.initializer case var initializer?) {
declarationStatements.add(forest.createExpressionStatement(
offsetForToken(endToken), initializer));
} else {
declarationStatements
.add(forest.createEmptyStatement(offsetForToken(endToken)));
}
} else {
declarationStatements.add(variable);
}
}
(multiVariablesWithMetadata ??= <List<VariableDeclaration>>[])
.add(variables);
Object variablesDeclaration =
forest.variablesDeclaration(declarationStatements, uri);
addVariableAnnotations(
forest
.variablesDeclarationExtractDeclarations(variablesDeclaration),
annotations);
push(variablesDeclaration);
} else {
addVariableAnnotations(variables, annotations);
push(forest.variablesDeclaration(variables, uri));
}
push(forest.variablesDeclaration(variables, uri));
}
_exitLocalState();
}

void addVariableAnnotations(List<VariableDeclaration> annotationVariables,
List<Expression>? annotations) {
if (annotations != null && annotationVariables.isNotEmpty) {
VariableDeclaration first = annotationVariables.first;
for (int i = 0; i < annotations.length; i++) {
first.addAnnotation(annotations[i]);
}
(multiVariablesWithMetadata ??= <List<VariableDeclaration>>[])
.add(annotationVariables);
}
}

/// Stack containing assigned variables info for try statements.
///
/// These are created in [beginTryStatement] and ended in either [beginBlock]
Expand Down
40 changes: 28 additions & 12 deletions pkg/front_end/lib/src/kernel/forest.dart
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ class Forest {
Statement statement = statements[i];
if (statement is _VariablesDeclaration) {
copy ??= new List<Statement>.of(statements.getRange(0, i));
copy.addAll(statement.declarations);
copy.addAll(statement.variableOrWildcardInitializers);
} else if (copy != null) {
copy.add(statement);
}
Expand Down Expand Up @@ -547,19 +547,20 @@ class Forest {
}

_VariablesDeclaration variablesDeclaration(
List<VariableDeclaration> declarations, Uri uri) {
return new _VariablesDeclaration(declarations, uri);
List<Statement> statements, Uri uri) {
return new _VariablesDeclaration(statements, uri);
}

List<VariableDeclaration> variablesDeclarationExtractDeclarations(
Object? variablesDeclaration) {
return (variablesDeclaration as _VariablesDeclaration).declarations;
return (variablesDeclaration as _VariablesDeclaration).variables;
}

Statement wrapVariables(Statement statement) {
if (statement is _VariablesDeclaration) {
return new Block(
new List<Statement>.of(statement.declarations, growable: true))
return new Block(new List<Statement>.of(
statement.variableOrWildcardInitializers,
growable: true))
..fileOffset = statement.fileOffset;
} else if (statement is VariableDeclaration) {
return new Block(<Statement>[statement])
Expand Down Expand Up @@ -908,11 +909,19 @@ class Forest {
}

class _VariablesDeclaration extends AuxiliaryStatement {
final List<VariableDeclaration> declarations;
/// A list of variable declarations with [ExpressionStatement]s and
/// [EmptyStatement]s from wildcard variable declarations.
final List<Statement> variableOrWildcardInitializers;

// A list of variable declarations that are not wildcard variables.
final List<VariableDeclaration> variables = [];
final Uri uri;

_VariablesDeclaration(this.declarations, this.uri) {
setParents(declarations, this);
_VariablesDeclaration(this.variableOrWildcardInitializers, this.uri) {
setParents(variableOrWildcardInitializers, this);
for (Statement statement in variableOrWildcardInitializers) {
if (statement is VariableDeclaration) variables.add(statement);
}
}

@override
Expand Down Expand Up @@ -953,12 +962,19 @@ class _VariablesDeclaration extends AuxiliaryStatement {
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
for (int index = 0; index < declarations.length; index++) {
for (int index = 0;
index < variableOrWildcardInitializers.length;
index++) {
Statement statement = variableOrWildcardInitializers[index];
if (index > 0) {
printer.write(', ');
}
printer.writeVariableDeclaration(declarations[index],
includeModifiersAndType: index == 0);
if (statement is VariableDeclaration) {
printer.writeVariableDeclaration(statement,
includeModifiersAndType: index == 0);
} else {
printer.writeStatement(statement);
}
}
printer.write(';');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ class Field extends core::Object {
: super core::Object::•()
;
method member() → void {
wildcard core::int _ = 1;
wildcard core::int _ = 2;
1;
2;
this.{self::Field::_} = 3;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ class Field extends core::Object {
: super core::Object::•()
;
method member() → void {
wildcard core::int _ = 1;
wildcard core::int _ = 2;
1;
2;
this.{self::Field::_} = 3;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ class Field extends core::Object {
: super core::Object::•()
;
method member() → void {
wildcard core::int _ = 1;
wildcard core::int _ = 2;
1;
2;
this.{self::Field::_} = 3;
}
}
9 changes: 9 additions & 0 deletions pkg/front_end/testcases/wildcard_variables/local_var.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,13 @@ test() {
var _ = 1;
int _ = 2;
_ = 3;

var _ = 2, _ = 2;

int test2() => 1;
var _ = test2();

late bool _;
late int _, _ = 3, x = 2;
late int _ = 3, _ = 3;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,20 @@ import self as self;
import "dart:core" as core;

static method test() → dynamic {
wildcard core::int _ = 1;
wildcard core::int _ = 2;
1;
2;
invalid-expression "pkg/front_end/testcases/wildcard_variables/local_var.dart:8:3: Error: Setter not found: '_'.
_ = 3;
^";
2;
2;
function test2() → core::int
return 1;
test2(){() → core::int};
;
;
3;
late core::int x = 2;
3;
3;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,20 @@ import self as self;
import "dart:core" as core;

static method test() → dynamic {
wildcard core::int _ = 1;
wildcard core::int _ = 2;
1;
2;
invalid-expression "pkg/front_end/testcases/wildcard_variables/local_var.dart:8:3: Error: Setter not found: '_'.
_ = 3;
^";
2;
2;
function test2() → core::int
return 1;
test2(){() → core::int};
;
;
3;
late core::int x = 2;
3;
3;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,20 @@ import self as self;
import "dart:core" as core;

static method test() → dynamic {
wildcard core::int _ = 1;
wildcard core::int _ = 2;
1;
2;
invalid-expression "pkg/front_end/testcases/wildcard_variables/local_var.dart:8:3: Error: Setter not found: '_'.
_ = 3;
^";
2;
2;
function test2() → core::int
return 1;
test2(){() → core::int};
;
;
3;
late core::int x = 2;
3;
3;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "dart:core" as core;

static field core::int _ = 100;
static method main() → dynamic {
wildcard core::int _ = 1;
wildcard core::int _ = 2;
1;
2;
self::_ = 3;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "dart:core" as core;

static field core::int _ = 100;
static method main() → dynamic {
wildcard core::int _ = 1;
wildcard core::int _ = 2;
1;
2;
self::_ = 3;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "dart:core" as core;

static field core::int _ = 100;
static method main() → dynamic {
wildcard core::int _ = 1;
wildcard core::int _ = 2;
1;
2;
self::_ = 3;
}
12 changes: 12 additions & 0 deletions pkg/front_end/testcases/wildcard_variables/local_var_order.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2024, 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.

String foo(String s) {
print(s);
return s;
}

test() {
String a = foo("a"), _ = foo("b"), c = foo("c"), _ = foo("d");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
library;
import self as self;
import "dart:core" as core;

static method foo(core::String s) → core::String {
core::print(s);
return s;
}
static method test() → dynamic {
core::String a = self::foo("a");
self::foo("b");
core::String c = self::foo("c");
self::foo("d");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
library;
import self as self;
import "dart:core" as core;

static method foo(core::String s) → core::String {
core::print(s);
return s;
}
static method test() → dynamic {
core::String a = self::foo("a");
self::foo("b");
core::String c = self::foo("c");
self::foo("d");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
library;
import self as self;
import "dart:core" as core;

static method foo(core::String s) → core::String
;
static method test() → dynamic
;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
library;
import self as self;
import "dart:core" as core;

static method foo(core::String s) → core::String {
core::print(s);
return s;
}
static method test() → dynamic {
core::String a = self::foo("a");
self::foo("b");
core::String c = self::foo("c");
self::foo("d");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
String foo(String s) {}

test() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
String foo(String s) {}

test() {}

0 comments on commit 2f80ad6

Please sign in to comment.