[cfe] Store the initializer tokens in constructor builders

For const constructors, we need to compile the initializer expressions
and write them into the outline so that we can perform modular
constant evaluation.  As a first step, preserve the tokens for the
initializer expressions in const constructor builders when building
the outline.

Currently they are discarded later during outline building at the
point when we should compile them instead.

Change-Id: Ief8d94ceb752b2315982d720836496b7d597e55c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107509
Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Vyacheslav Egorov 2019-07-03 10:52:35 +00:00 committed by commit-bot@chromium.org
parent bbbeb8b509
commit 9f32f9b87e
12 changed files with 46 additions and 28 deletions

View file

@ -1447,8 +1447,8 @@ class AstBuilder extends StackListener {
}
@override
void endMethod(
Token getOrSet, Token beginToken, Token beginParam, Token endToken) {
void endMethod(Token getOrSet, Token beginToken, Token beginParam,
Token beginInitializers, Token endToken) {
assert(getOrSet == null ||
optional('get', getOrSet) ||
optional('set', getOrSet));

View file

@ -908,10 +908,11 @@ class ForwardingTestListener extends ForwardingListener {
}
@override
void endMethod(
Token getOrSet, Token beginToken, Token beginParam, Token endToken) {
void endMethod(Token getOrSet, Token beginToken, Token beginParam,
Token beginInitializers, Token endToken) {
end('Method');
super.endMethod(getOrSet, beginToken, beginParam, endToken);
super.endMethod(
getOrSet, beginToken, beginParam, beginInitializers, endToken);
}
@override

View file

@ -393,8 +393,8 @@ class MiniAstBuilder extends StackListener {
NullValue.Metadata);
}
void endMethod(
Token getOrSet, Token beginToken, Token beginParam, Token endToken) {
void endMethod(Token getOrSet, Token beginToken, Token beginParam,
Token beginInitializers, Token endToken) {
debugEvent("Method");
pop(); // Body
pop(); // Initializers

View file

@ -671,9 +671,10 @@ class KernelLibraryBuilder
int charOffset,
int charOpenParenOffset,
int charEndOffset,
String nativeMethodName) {
String nativeMethodName,
{Token beginInitializers}) {
MetadataCollector metadataCollector = loader.target.metadataCollector;
ProcedureBuilder procedure = new KernelConstructorBuilder(
KernelConstructorBuilder procedure = new KernelConstructorBuilder(
metadata,
modifiers & ~abstractMask,
returnType,
@ -699,7 +700,12 @@ class KernelLibraryBuilder
if (nativeMethodName != null) {
addNativeMethod(procedure);
}
if (procedure.isConst) currentDeclaration?.hasConstConstructor = true;
if (procedure.isConst) {
currentDeclaration?.hasConstConstructor = true;
// const constructors will have their initializers compiled and written
// into the outline.
procedure.beginInitializers = beginInitializers;
}
}
void addProcedure(

View file

@ -34,6 +34,8 @@ import 'package:kernel/ast.dart'
import 'package:kernel/type_algebra.dart' show containsTypeVariable, substitute;
import '../../scanner/token.dart' show Token;
import '../loader.dart' show Loader;
import '../messages.dart'
@ -415,6 +417,8 @@ class KernelConstructorBuilder extends KernelFunctionBuilder {
RedirectingInitializer redirectingInitializer;
Token beginInitializers;
@override
KernelConstructorBuilder actualOrigin;
@ -489,6 +493,7 @@ class KernelConstructorBuilder extends KernelFunctionBuilder {
void buildOutlineExpressions(LibraryBuilder library) {
KernelMetadataBuilder.buildAnnotations(
target, metadata, library, parent, this);
beginInitializers = null;
}
FunctionNode buildFunction(LibraryBuilder library) {

View file

@ -774,9 +774,10 @@ class ForwardingListener implements Listener {
}
@override
void endMethod(
Token getOrSet, Token beginToken, Token beginParam, Token endToken) {
listener?.endMethod(getOrSet, beginToken, beginParam, endToken);
void endMethod(Token getOrSet, Token beginToken, Token beginParam,
Token beginInitializers, Token endToken) {
listener?.endMethod(
getOrSet, beginToken, beginParam, beginInitializers, endToken);
}
@override

View file

@ -747,8 +747,8 @@ class Listener implements UnescapeErrorListener {
/// - initializers
/// - async marker
/// - body
void endMethod(
Token getOrSet, Token beginToken, Token beginParam, Token endToken) {
void endMethod(Token getOrSet, Token beginToken, Token beginParam,
Token beginInitializers, Token endToken) {
logEvent("Method");
}

View file

@ -2516,7 +2516,7 @@ class Parser {
Token parseInitializersOpt(Token token) {
if (optional(':', token.next)) {
return parseInitializers(token);
return parseInitializers(token.next);
} else {
listener.handleNoInitializers();
return token;
@ -2529,7 +2529,7 @@ class Parser {
/// ;
/// ```
Token parseInitializers(Token token) {
Token begin = token.next;
Token begin = token;
assert(optional(':', begin));
listener.beginInitializers(begin);
int count = 0;
@ -3241,8 +3241,10 @@ class Parser {
? MemberKind.StaticMethod
: MemberKind.NonStaticMethod;
Token beforeParam = token;
token = parseGetterOrFormalParameters(token, name, isGetter, kind);
token = parseInitializersOpt(token);
Token beforeInitializers =
parseGetterOrFormalParameters(token, name, isGetter, kind);
token = parseInitializersOpt(beforeInitializers);
if (token == beforeInitializers) beforeInitializers = null;
AsyncModifier savedAsyncModifier = asyncState;
Token asyncToken = token.next;
@ -3264,7 +3266,8 @@ class Parser {
(staticToken == null || externalToken != null) && inPlainSync);
}
asyncState = savedAsyncModifier;
listener.endMethod(getOrSet, beforeStart.next, beforeParam.next, token);
listener.endMethod(getOrSet, beforeStart.next, beforeParam.next,
beforeInitializers?.next, token);
return token;
}

View file

@ -575,8 +575,8 @@ class DietListener extends StackListener {
}
@override
void endMethod(
Token getOrSet, Token beginToken, Token beginParam, Token endToken) {
void endMethod(Token getOrSet, Token beginToken, Token beginParam,
Token beginInitializers, Token endToken) {
debugEvent("Method");
// TODO(danrubel): Consider removing the beginParam parameter
// and using bodyToken, but pushing a NullValue on the stack

View file

@ -754,8 +754,8 @@ class OutlineBuilder extends StackListener {
}
@override
void endMethod(
Token getOrSet, Token beginToken, Token beginParam, Token endToken) {
void endMethod(Token getOrSet, Token beginToken, Token beginParam,
Token beginInitializers, Token endToken) {
debugEvent("Method");
MethodBody bodyKind = pop();
if (bodyKind == MethodBody.RedirectingFactoryBody) {
@ -871,7 +871,8 @@ class OutlineBuilder extends StackListener {
charOffset,
formalsOffset,
endToken.charOffset,
nativeMethodName);
nativeMethodName,
beginInitializers: beginInitializers);
} else {
if (isConst) {
addProblem(messageConstMethod, varFinalOrConstOffset, 5);

View file

@ -431,7 +431,8 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
int charOffset,
int charOpenParenOffset,
int charEndOffset,
String nativeMethodName);
String nativeMethodName,
{Token beginInitializers});
void addProcedure(
String documentationComment,

View file

@ -962,8 +962,8 @@ class TypePromotionLookAheadListener extends Listener {
}
@override
void endMethod(
Token getOrSet, Token beginToken, Token beginParam, Token endToken) {
void endMethod(Token getOrSet, Token beginToken, Token beginParam,
Token beginInitializers, Token endToken) {
debugEvent("endMethod", endToken);
state.pop(); // Method name.
state.checkEmpty(endToken);