Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 25033ce

Browse files
askeksacommit-bot@chromium.org
authored andcommitted
[CFE] Control inlining of const variables from backend.
Needed for dart-lang/sdk#36535 Also preserve StaticGet of unavailable constants not in const context, rather than wrapping it in an unevaluated constant. Change-Id: Ifac6f251ea9a90a17d06014be12c0d387a32d757 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99020 Reviewed-by: Vijay Menon <[email protected]>
1 parent afc54e2 commit 25033ce

File tree

2 files changed

+44
-23
lines changed

2 files changed

+44
-23
lines changed

pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ class JavaScriptIntConstant extends DoubleConstant {
135135
}
136136

137137
class ConstantsTransformer extends Transformer {
138+
final ConstantsBackend backend;
138139
final ConstantEvaluator constantEvaluator;
139140
final TypeEnvironment typeEnvironment;
140141

@@ -146,7 +147,7 @@ class ConstantsTransformer extends Transformer {
146147
final bool errorOnUnevaluatedConstant;
147148

148149
ConstantsTransformer(
149-
ConstantsBackend backend,
150+
this.backend,
150151
Map<String, String> environmentDefines,
151152
this.keepFields,
152153
this.keepVariables,
@@ -300,18 +301,11 @@ class ConstantsTransformer extends Transformer {
300301
if (node.isConst) {
301302
final Constant constant = evaluateWithContext(node, node.initializer);
302303
constantEvaluator.env.addVariableValue(node, constant);
304+
node.initializer = makeConstantExpression(constant, node.initializer)
305+
..parent = node;
303306

304-
if (keepVariables) {
305-
// So the value of the variable is still available for debugging
306-
// purposes we convert the constant variable to be a final variable
307-
// initialized to the evaluated constant expression.
308-
node.initializer = makeConstantExpression(constant, node.initializer)
309-
..parent = node;
310-
node.isFinal = true;
311-
node.isConst = false;
312-
} else {
313-
// Since we convert all use-sites of constants, the constant
314-
// [VariableDeclaration] is unused and we'll therefore remove it.
307+
// If this constant is inlined, remove it.
308+
if (!keepVariables && shouldInline(node.initializer)) {
315309
return null;
316310
}
317311
} else {
@@ -324,20 +318,17 @@ class ConstantsTransformer extends Transformer {
324318
visitField(Field node) {
325319
return constantEvaluator.withNewEnvironment(() {
326320
if (node.isConst) {
327-
// Since we convert all use-sites of constants, the constant [Field]
328-
// cannot be referenced anymore. We therefore get rid of it if
329-
// [keepFields] was not specified.
330-
if (!keepFields) {
331-
return null;
332-
}
333-
334-
// Otherwise we keep the constant [Field] and convert it's initializer.
335321
transformAnnotations(node.annotations, node);
336322
if (node.initializer != null) {
337323
node.initializer =
338324
evaluateAndTransformWithContext(node, node.initializer)
339325
..parent = node;
340326
}
327+
328+
// If this constant is inlined, remove it.
329+
if (!keepFields && shouldInline(node.initializer)) {
330+
return null;
331+
}
341332
} else {
342333
transformAnnotations(node.annotations, node);
343334
if (node.initializer != null) {
@@ -357,7 +348,15 @@ class ConstantsTransformer extends Transformer {
357348
visitStaticGet(StaticGet node) {
358349
final Member target = node.target;
359350
if (target is Field && target.isConst) {
360-
return evaluateAndTransformWithContext(node, node);
351+
if (target.initializer != null) {
352+
// Make sure the initializer is evaluated first.
353+
target.initializer =
354+
evaluateAndTransformWithContext(target, target.initializer)
355+
..parent = target;
356+
if (shouldInline(target.initializer)) {
357+
return evaluateAndTransformWithContext(node, node);
358+
}
359+
}
361360
} else if (target is Procedure && target.kind == ProcedureKind.Method) {
362361
return evaluateAndTransformWithContext(node, node);
363362
}
@@ -370,8 +369,14 @@ class ConstantsTransformer extends Transformer {
370369
}
371370

372371
visitVariableGet(VariableGet node) {
373-
if (node.variable.isConst) {
374-
return evaluateAndTransformWithContext(node, node);
372+
final VariableDeclaration variable = node.variable;
373+
if (variable.isConst) {
374+
variable.initializer =
375+
evaluateAndTransformWithContext(variable, variable.initializer)
376+
..parent = variable;
377+
if (shouldInline(variable.initializer)) {
378+
return evaluateAndTransformWithContext(node, node);
379+
}
375380
}
376381
return super.visitVariableGet(node);
377382
}
@@ -456,6 +461,13 @@ class ConstantsTransformer extends Transformer {
456461
return new ConstantExpression(constant, node.getStaticType(typeEnvironment))
457462
..fileOffset = node.fileOffset;
458463
}
464+
465+
bool shouldInline(Expression initializer) {
466+
if (initializer is ConstantExpression) {
467+
return backend.shouldInlineConstant(initializer);
468+
}
469+
return true;
470+
}
459471
}
460472

461473
class ConstantEvaluator extends RecursiveVisitor<Constant> {

pkg/kernel/lib/target/targets.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ class ConstantsBackend {
5757

5858
/// Number semantics to use for this backend.
5959
NumberSemantics get numberSemantics => NumberSemantics.vm;
60+
61+
/// Inline control of constant variables. The given constant expression
62+
/// is the initializer of a [Field] or [VariableDeclaration] node.
63+
/// If this method returns `true`, the variable will be inlined at all
64+
/// points of reference and the variable itself removed (unless overridden
65+
/// by the `keepFields` or `keepVariables` flag to the constant transformer).
66+
/// This method must be deterministic, i.e. it must always return the same
67+
/// value for the same constant value and place in the AST.
68+
bool shouldInlineConstant(ConstantExpression initializer) => true;
6069
}
6170

6271
/// A target provides backend-specific options for generating kernel IR.

0 commit comments

Comments
 (0)