Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Unified Diff: runtime/vm/parser.cc

Issue 1382533003: Add flag which moves super initializer statement (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/parser.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/parser.cc
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index a33c4cce1f4400cb53017017785efef1431204ac..60ea0cf23ff39608ee98eda2c392156de778dd19 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -46,6 +46,7 @@ DEFINE_FLAG(bool, load_deferred_eagerly, false,
DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef.");
DEFINE_FLAG(bool, link_natives_lazily, false, "Link native calls lazily");
+DEFINE_FLAG(bool, move_super, false, "Move super initializer to end of list");
DECLARE_FLAG(bool, lazy_dispatchers);
DECLARE_FLAG(bool, load_deferred_eagerly);
@@ -2328,11 +2329,12 @@ AstNode* Parser::ParseSuperFieldAccess(const String& field_name,
}
-void Parser::GenerateSuperConstructorCall(const Class& cls,
- intptr_t supercall_pos,
- LocalVariable* receiver,
- AstNode* phase_parameter,
- ArgumentListNode* forwarding_args) {
+StaticCallNode* Parser::GenerateSuperConstructorCall(
+ const Class& cls,
+ intptr_t supercall_pos,
+ LocalVariable* receiver,
+ AstNode* phase_parameter,
+ ArgumentListNode* forwarding_args) {
const Class& super_class = Class::Handle(Z, cls.SuperClass());
// Omit the implicit super() if there is no super class (i.e.
// we're not compiling class Object), or if the super class is an
@@ -2340,7 +2342,7 @@ void Parser::GenerateSuperConstructorCall(const Class& cls,
if (super_class.IsNull() ||
(super_class.num_native_fields() > 0 &&
Class::Handle(Z, super_class.SuperClass()).IsObjectClass())) {
- return;
+ return NULL;
}
String& super_ctor_name = String::Handle(Z, super_class.Name());
super_ctor_name = Symbols::FromConcat(super_ctor_name, Symbols::Dot());
@@ -2391,13 +2393,12 @@ void Parser::GenerateSuperConstructorCall(const Class& cls,
String::Handle(Z, super_class.Name()).ToCString(),
error_message.ToCString());
}
- current_block_->statements->Add(
- new StaticCallNode(supercall_pos, super_ctor, arguments));
+ return new StaticCallNode(supercall_pos, super_ctor, arguments);
}
-AstNode* Parser::ParseSuperInitializer(const Class& cls,
- LocalVariable* receiver) {
+StaticCallNode* Parser::ParseSuperInitializer(const Class& cls,
+ LocalVariable* receiver) {
TRACE_PARSER("ParseSuperInitializer");
ASSERT(CurrentToken() == Token::kSUPER);
const intptr_t supercall_pos = TokenPos();
@@ -2728,30 +2729,67 @@ void Parser::ParseInitializers(const Class& cls,
LocalVariable* receiver,
GrowableArray<Field*>* initialized_fields) {
TRACE_PARSER("ParseInitializers");
- bool super_init_seen = false;
+ bool super_init_is_last = false;
+ intptr_t super_init_index = -1;
+ StaticCallNode* super_init_call = NULL;
if (CurrentToken() == Token::kCOLON) {
do {
ConsumeToken(); // Colon or comma.
- AstNode* init_statement;
if (CurrentToken() == Token::kSUPER) {
- if (super_init_seen) {
+ if (super_init_call != NULL) {
ReportError("duplicate call to super constructor");
}
- init_statement = ParseSuperInitializer(cls, receiver);
- super_init_seen = true;
+ super_init_call = ParseSuperInitializer(cls, receiver);
+ super_init_index = current_block_->statements->length();
+ current_block_->statements->Add(super_init_call);
+ super_init_is_last = true;
} else {
- init_statement = ParseInitializer(cls, receiver, initialized_fields);
+ AstNode* init_statement =
+ ParseInitializer(cls, receiver, initialized_fields);
+ super_init_is_last = false;
+ current_block_->statements->Add(init_statement);
}
- current_block_->statements->Add(init_statement);
} while (CurrentToken() == Token::kCOMMA);
}
- if (!super_init_seen) {
+ if (super_init_call == NULL) {
// Generate implicit super() if we haven't seen an explicit super call
// or constructor redirection.
AstNode* phase_parameter = new LiteralNode(
TokenPos(), Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseAll)));
- GenerateSuperConstructorCall(
+ super_init_call = GenerateSuperConstructorCall(
cls, TokenPos(), receiver, phase_parameter, NULL);
+ if (super_init_call != NULL) {
+ super_init_index = current_block_->statements->length();
+ current_block_->statements->Add(super_init_call);
+ super_init_is_last = true;
+ }
+ }
+ if (FLAG_move_super && super_init_call != NULL && !super_init_is_last) {
regis 2015/10/07 16:54:43 parenthesis missing
hausner 2015/10/07 17:27:22 Done.
+ // If the super initializer call is not at the end of the initializer
+ // list, implicitly move it to the end. The actual parameter values
+ // are evaluated at the original position in the list and preserved
+ // in temporary variables. (The following initializer expressions
+ // could have side effects that alter the arguments to the super
+ // initializer.) E.g:
+ // A(x) : super(x), f = x++ { ... }
+ // is transformed to:
+ // A(x) : temp = x, f = x++, super(temp) { ... }
+ ReportWarning("Super initizlizer not at end");
+ ASSERT(super_init_index >= 0);
+ ArgumentListNode* ctor_args = super_init_call->arguments();
+ LetNode* saved_args = new(Z) LetNode(super_init_call->token_pos());
+ // The super initializer call has at least 2 arguments: the
+ // implicit receiver, and the hidden construction phase.
+ ASSERT(ctor_args->length() >= 2);
+ for (int i = 2; i < ctor_args->length(); i++) {
+ AstNode* arg = ctor_args->NodeAt(i);
+ LocalVariable* temp = CreateTempConstVariable(arg->token_pos(), "sca");
+ AstNode* save_temp = new(Z) StoreLocalNode(arg->token_pos(), temp, arg);
+ saved_args->AddNode(save_temp);
+ ctor_args->SetNodeAt(i, new(Z) LoadLocalNode(arg->token_pos(), temp));
+ }
+ current_block_->statements->ReplaceNodeAt(super_init_index, saved_args);
+ current_block_->statements->Add(super_init_call);
}
CheckFieldsInitialized(cls);
}
@@ -2874,12 +2912,15 @@ SequenceNode* Parser::MakeImplicitConstructor(const Function& func) {
}
}
- GenerateSuperConstructorCall(
+ AstNode* super_call = GenerateSuperConstructorCall(
current_class(),
Scanner::kNoSourcePos,
receiver,
new LoadLocalNode(Scanner::kNoSourcePos, phase_parameter),
forwarding_args);
+ if (super_call != NULL) {
+ current_block_->statements->Add(super_call);
+ }
CheckFieldsInitialized(current_class());
// Empty constructor body.
@@ -3091,6 +3132,7 @@ SequenceNode* Parser::ParseConstructor(const Function& func) {
}
}
if (super_call != NULL) {
+ ASSERT(!FLAG_move_super);
// Generate an implicit call to the super constructor's body.
// We need to patch the super _initializer_ call so that it
// saves the evaluated actual arguments in temporary variables.
@@ -3119,6 +3161,7 @@ SequenceNode* Parser::ParseConstructor(const Function& func) {
// Insert the implicit super call to the super constructor body.
if (super_call != NULL) {
+ ASSERT(!FLAG_move_super);
ArgumentListNode* initializer_args = super_call->arguments();
const Function& super_ctor = super_call->function();
// Patch the initializer call so it only executes the super initializer.
« no previous file with comments | « runtime/vm/parser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698