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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « runtime/vm/parser.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "platform/utils.h" 8 #include "platform/utils.h"
9 #include "vm/ast_transformer.h" 9 #include "vm/ast_transformer.h"
10 #include "vm/bootstrap.h" 10 #include "vm/bootstrap.h"
(...skipping 28 matching lines...) Expand all
39 namespace dart { 39 namespace dart {
40 40
41 DEFINE_FLAG(bool, enable_debug_break, false, "Allow use of break \"message\"."); 41 DEFINE_FLAG(bool, enable_debug_break, false, "Allow use of break \"message\".");
42 DEFINE_FLAG(bool, enable_mirrors, true, 42 DEFINE_FLAG(bool, enable_mirrors, true,
43 "Disable to make importing dart:mirrors an error."); 43 "Disable to make importing dart:mirrors an error.");
44 DEFINE_FLAG(bool, load_deferred_eagerly, false, 44 DEFINE_FLAG(bool, load_deferred_eagerly, false,
45 "Load deferred libraries eagerly."); 45 "Load deferred libraries eagerly.");
46 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); 46 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
47 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef."); 47 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef.");
48 DEFINE_FLAG(bool, link_natives_lazily, false, "Link native calls lazily"); 48 DEFINE_FLAG(bool, link_natives_lazily, false, "Link native calls lazily");
49 DEFINE_FLAG(bool, move_super, false, "Move super initializer to end of list");
49 50
50 DECLARE_FLAG(bool, lazy_dispatchers); 51 DECLARE_FLAG(bool, lazy_dispatchers);
51 DECLARE_FLAG(bool, load_deferred_eagerly); 52 DECLARE_FLAG(bool, load_deferred_eagerly);
52 DECLARE_FLAG(bool, profile_vm); 53 DECLARE_FLAG(bool, profile_vm);
53 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); 54 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
54 DECLARE_FLAG(bool, warn_on_javascript_compatibility); 55 DECLARE_FLAG(bool, warn_on_javascript_compatibility);
55 56
56 // Quick access to the current thread, isolate and zone. 57 // Quick access to the current thread, isolate and zone.
57 #define T (thread()) 58 #define T (thread())
58 #define I (isolate()) 59 #define I (isolate())
(...skipping 2262 matching lines...) Expand 10 before | Expand all | Expand 10 after
2321 } 2322 }
2322 // No function or field exists of the specified field_name. 2323 // No function or field exists of the specified field_name.
2323 // Emit a StaticGetterNode anyway, so that noSuchMethod gets called. 2324 // Emit a StaticGetterNode anyway, so that noSuchMethod gets called.
2324 } 2325 }
2325 } 2326 }
2326 return new(Z) StaticGetterNode( 2327 return new(Z) StaticGetterNode(
2327 field_pos, implicit_argument, super_class, field_name); 2328 field_pos, implicit_argument, super_class, field_name);
2328 } 2329 }
2329 2330
2330 2331
2331 void Parser::GenerateSuperConstructorCall(const Class& cls, 2332 StaticCallNode* Parser::GenerateSuperConstructorCall(
2332 intptr_t supercall_pos, 2333 const Class& cls,
2333 LocalVariable* receiver, 2334 intptr_t supercall_pos,
2334 AstNode* phase_parameter, 2335 LocalVariable* receiver,
2335 ArgumentListNode* forwarding_args) { 2336 AstNode* phase_parameter,
2337 ArgumentListNode* forwarding_args) {
2336 const Class& super_class = Class::Handle(Z, cls.SuperClass()); 2338 const Class& super_class = Class::Handle(Z, cls.SuperClass());
2337 // Omit the implicit super() if there is no super class (i.e. 2339 // Omit the implicit super() if there is no super class (i.e.
2338 // we're not compiling class Object), or if the super class is an 2340 // we're not compiling class Object), or if the super class is an
2339 // artificially generated "wrapper class" that has no constructor. 2341 // artificially generated "wrapper class" that has no constructor.
2340 if (super_class.IsNull() || 2342 if (super_class.IsNull() ||
2341 (super_class.num_native_fields() > 0 && 2343 (super_class.num_native_fields() > 0 &&
2342 Class::Handle(Z, super_class.SuperClass()).IsObjectClass())) { 2344 Class::Handle(Z, super_class.SuperClass()).IsObjectClass())) {
2343 return; 2345 return NULL;
2344 } 2346 }
2345 String& super_ctor_name = String::Handle(Z, super_class.Name()); 2347 String& super_ctor_name = String::Handle(Z, super_class.Name());
2346 super_ctor_name = Symbols::FromConcat(super_ctor_name, Symbols::Dot()); 2348 super_ctor_name = Symbols::FromConcat(super_ctor_name, Symbols::Dot());
2347 2349
2348 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); 2350 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos);
2349 // Implicit 'this' parameter is the first argument. 2351 // Implicit 'this' parameter is the first argument.
2350 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver); 2352 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver);
2351 arguments->Add(implicit_argument); 2353 arguments->Add(implicit_argument);
2352 // Implicit construction phase parameter is second argument. 2354 // Implicit construction phase parameter is second argument.
2353 arguments->Add(phase_parameter); 2355 arguments->Add(phase_parameter);
(...skipping 30 matching lines...) Expand all
2384 2386
2385 String& error_message = String::Handle(Z); 2387 String& error_message = String::Handle(Z);
2386 if (!super_ctor.AreValidArguments(arguments->length(), 2388 if (!super_ctor.AreValidArguments(arguments->length(),
2387 arguments->names(), 2389 arguments->names(),
2388 &error_message)) { 2390 &error_message)) {
2389 ReportError(supercall_pos, 2391 ReportError(supercall_pos,
2390 "invalid arguments passed to super constructor '%s()': %s", 2392 "invalid arguments passed to super constructor '%s()': %s",
2391 String::Handle(Z, super_class.Name()).ToCString(), 2393 String::Handle(Z, super_class.Name()).ToCString(),
2392 error_message.ToCString()); 2394 error_message.ToCString());
2393 } 2395 }
2394 current_block_->statements->Add( 2396 return new StaticCallNode(supercall_pos, super_ctor, arguments);
2395 new StaticCallNode(supercall_pos, super_ctor, arguments));
2396 } 2397 }
2397 2398
2398 2399
2399 AstNode* Parser::ParseSuperInitializer(const Class& cls, 2400 StaticCallNode* Parser::ParseSuperInitializer(const Class& cls,
2400 LocalVariable* receiver) { 2401 LocalVariable* receiver) {
2401 TRACE_PARSER("ParseSuperInitializer"); 2402 TRACE_PARSER("ParseSuperInitializer");
2402 ASSERT(CurrentToken() == Token::kSUPER); 2403 ASSERT(CurrentToken() == Token::kSUPER);
2403 const intptr_t supercall_pos = TokenPos(); 2404 const intptr_t supercall_pos = TokenPos();
2404 ConsumeToken(); 2405 ConsumeToken();
2405 const Class& super_class = Class::Handle(Z, cls.SuperClass()); 2406 const Class& super_class = Class::Handle(Z, cls.SuperClass());
2406 ASSERT(!super_class.IsNull()); 2407 ASSERT(!super_class.IsNull());
2407 String& ctor_name = String::Handle(Z, super_class.Name()); 2408 String& ctor_name = String::Handle(Z, super_class.Name());
2408 ctor_name = Symbols::FromConcat(ctor_name, Symbols::Dot()); 2409 ctor_name = Symbols::FromConcat(ctor_name, Symbols::Dot());
2409 if (CurrentToken() == Token::kPERIOD) { 2410 if (CurrentToken() == Token::kPERIOD) {
2410 ConsumeToken(); 2411 ConsumeToken();
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
2721 } 2722 }
2722 initialized_fields->Add(field); 2723 initialized_fields->Add(field);
2723 return result; 2724 return result;
2724 } 2725 }
2725 2726
2726 2727
2727 void Parser::ParseInitializers(const Class& cls, 2728 void Parser::ParseInitializers(const Class& cls,
2728 LocalVariable* receiver, 2729 LocalVariable* receiver,
2729 GrowableArray<Field*>* initialized_fields) { 2730 GrowableArray<Field*>* initialized_fields) {
2730 TRACE_PARSER("ParseInitializers"); 2731 TRACE_PARSER("ParseInitializers");
2731 bool super_init_seen = false; 2732 bool super_init_is_last = false;
2733 intptr_t super_init_index = -1;
2734 StaticCallNode* super_init_call = NULL;
2732 if (CurrentToken() == Token::kCOLON) { 2735 if (CurrentToken() == Token::kCOLON) {
2733 do { 2736 do {
2734 ConsumeToken(); // Colon or comma. 2737 ConsumeToken(); // Colon or comma.
2735 AstNode* init_statement;
2736 if (CurrentToken() == Token::kSUPER) { 2738 if (CurrentToken() == Token::kSUPER) {
2737 if (super_init_seen) { 2739 if (super_init_call != NULL) {
2738 ReportError("duplicate call to super constructor"); 2740 ReportError("duplicate call to super constructor");
2739 } 2741 }
2740 init_statement = ParseSuperInitializer(cls, receiver); 2742 super_init_call = ParseSuperInitializer(cls, receiver);
2741 super_init_seen = true; 2743 super_init_index = current_block_->statements->length();
2744 current_block_->statements->Add(super_init_call);
2745 super_init_is_last = true;
2742 } else { 2746 } else {
2743 init_statement = ParseInitializer(cls, receiver, initialized_fields); 2747 AstNode* init_statement =
2748 ParseInitializer(cls, receiver, initialized_fields);
2749 super_init_is_last = false;
2750 current_block_->statements->Add(init_statement);
2744 } 2751 }
2745 current_block_->statements->Add(init_statement);
2746 } while (CurrentToken() == Token::kCOMMA); 2752 } while (CurrentToken() == Token::kCOMMA);
2747 } 2753 }
2748 if (!super_init_seen) { 2754 if (super_init_call == NULL) {
2749 // Generate implicit super() if we haven't seen an explicit super call 2755 // Generate implicit super() if we haven't seen an explicit super call
2750 // or constructor redirection. 2756 // or constructor redirection.
2751 AstNode* phase_parameter = new LiteralNode( 2757 AstNode* phase_parameter = new LiteralNode(
2752 TokenPos(), Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseAll))); 2758 TokenPos(), Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseAll)));
2753 GenerateSuperConstructorCall( 2759 super_init_call = GenerateSuperConstructorCall(
2754 cls, TokenPos(), receiver, phase_parameter, NULL); 2760 cls, TokenPos(), receiver, phase_parameter, NULL);
2761 if (super_init_call != NULL) {
2762 super_init_index = current_block_->statements->length();
2763 current_block_->statements->Add(super_init_call);
2764 super_init_is_last = true;
2765 }
2766 }
2767 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.
2768 // If the super initializer call is not at the end of the initializer
2769 // list, implicitly move it to the end. The actual parameter values
2770 // are evaluated at the original position in the list and preserved
2771 // in temporary variables. (The following initializer expressions
2772 // could have side effects that alter the arguments to the super
2773 // initializer.) E.g:
2774 // A(x) : super(x), f = x++ { ... }
2775 // is transformed to:
2776 // A(x) : temp = x, f = x++, super(temp) { ... }
2777 ReportWarning("Super initizlizer not at end");
2778 ASSERT(super_init_index >= 0);
2779 ArgumentListNode* ctor_args = super_init_call->arguments();
2780 LetNode* saved_args = new(Z) LetNode(super_init_call->token_pos());
2781 // The super initializer call has at least 2 arguments: the
2782 // implicit receiver, and the hidden construction phase.
2783 ASSERT(ctor_args->length() >= 2);
2784 for (int i = 2; i < ctor_args->length(); i++) {
2785 AstNode* arg = ctor_args->NodeAt(i);
2786 LocalVariable* temp = CreateTempConstVariable(arg->token_pos(), "sca");
2787 AstNode* save_temp = new(Z) StoreLocalNode(arg->token_pos(), temp, arg);
2788 saved_args->AddNode(save_temp);
2789 ctor_args->SetNodeAt(i, new(Z) LoadLocalNode(arg->token_pos(), temp));
2790 }
2791 current_block_->statements->ReplaceNodeAt(super_init_index, saved_args);
2792 current_block_->statements->Add(super_init_call);
2755 } 2793 }
2756 CheckFieldsInitialized(cls); 2794 CheckFieldsInitialized(cls);
2757 } 2795 }
2758 2796
2759 2797
2760 void Parser::ParseConstructorRedirection(const Class& cls, 2798 void Parser::ParseConstructorRedirection(const Class& cls,
2761 LocalVariable* receiver) { 2799 LocalVariable* receiver) {
2762 TRACE_PARSER("ParseConstructorRedirection"); 2800 TRACE_PARSER("ParseConstructorRedirection");
2763 ExpectToken(Token::kCOLON); 2801 ExpectToken(Token::kCOLON);
2764 ASSERT(CurrentToken() == Token::kTHIS); 2802 ASSERT(CurrentToken() == Token::kTHIS);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2867 for (int i = 2; i < func.NumParameters(); i++) { 2905 for (int i = 2; i < func.NumParameters(); i++) {
2868 LocalVariable* param = new LocalVariable( 2906 LocalVariable* param = new LocalVariable(
2869 Scanner::kNoSourcePos, 2907 Scanner::kNoSourcePos,
2870 String::ZoneHandle(Z, func.ParameterNameAt(i)), 2908 String::ZoneHandle(Z, func.ParameterNameAt(i)),
2871 Type::ZoneHandle(Z, Type::DynamicType())); 2909 Type::ZoneHandle(Z, Type::DynamicType()));
2872 current_block_->scope->InsertParameterAt(i, param); 2910 current_block_->scope->InsertParameterAt(i, param);
2873 forwarding_args->Add(new LoadLocalNode(Scanner::kNoSourcePos, param)); 2911 forwarding_args->Add(new LoadLocalNode(Scanner::kNoSourcePos, param));
2874 } 2912 }
2875 } 2913 }
2876 2914
2877 GenerateSuperConstructorCall( 2915 AstNode* super_call = GenerateSuperConstructorCall(
2878 current_class(), 2916 current_class(),
2879 Scanner::kNoSourcePos, 2917 Scanner::kNoSourcePos,
2880 receiver, 2918 receiver,
2881 new LoadLocalNode(Scanner::kNoSourcePos, phase_parameter), 2919 new LoadLocalNode(Scanner::kNoSourcePos, phase_parameter),
2882 forwarding_args); 2920 forwarding_args);
2921 if (super_call != NULL) {
2922 current_block_->statements->Add(super_call);
2923 }
2883 CheckFieldsInitialized(current_class()); 2924 CheckFieldsInitialized(current_class());
2884 2925
2885 // Empty constructor body. 2926 // Empty constructor body.
2886 current_block_->statements->Add(new ReturnNode(Scanner::kNoSourcePos)); 2927 current_block_->statements->Add(new ReturnNode(Scanner::kNoSourcePos));
2887 SequenceNode* statements = CloseBlock(); 2928 SequenceNode* statements = CloseBlock();
2888 return statements; 2929 return statements;
2889 } 2930 }
2890 2931
2891 2932
2892 void Parser::CheckRecursiveInvocation() { 2933 void Parser::CheckRecursiveInvocation() {
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
3084 if (init_statements->NodeAt(i)->IsStaticCallNode()) { 3125 if (init_statements->NodeAt(i)->IsStaticCallNode()) {
3085 StaticCallNode* static_call = 3126 StaticCallNode* static_call =
3086 init_statements->NodeAt(i)->AsStaticCallNode(); 3127 init_statements->NodeAt(i)->AsStaticCallNode();
3087 if (static_call->function().IsGenerativeConstructor()) { 3128 if (static_call->function().IsGenerativeConstructor()) {
3088 super_call = static_call; 3129 super_call = static_call;
3089 break; 3130 break;
3090 } 3131 }
3091 } 3132 }
3092 } 3133 }
3093 if (super_call != NULL) { 3134 if (super_call != NULL) {
3135 ASSERT(!FLAG_move_super);
3094 // Generate an implicit call to the super constructor's body. 3136 // Generate an implicit call to the super constructor's body.
3095 // We need to patch the super _initializer_ call so that it 3137 // We need to patch the super _initializer_ call so that it
3096 // saves the evaluated actual arguments in temporary variables. 3138 // saves the evaluated actual arguments in temporary variables.
3097 // The temporary variables are necessary so that the argument 3139 // The temporary variables are necessary so that the argument
3098 // expressions are not evaluated twice. 3140 // expressions are not evaluated twice.
3099 // Note: we should never get here in the case of a redirecting 3141 // Note: we should never get here in the case of a redirecting
3100 // constructor. In that case, the call to the target constructor 3142 // constructor. In that case, the call to the target constructor
3101 // is the "super call" and is implicitly at the end of the 3143 // is the "super call" and is implicitly at the end of the
3102 // initializer list. 3144 // initializer list.
3103 ASSERT(!is_redirecting_constructor); 3145 ASSERT(!is_redirecting_constructor);
3104 ArgumentListNode* ctor_args = super_call->arguments(); 3146 ArgumentListNode* ctor_args = super_call->arguments();
3105 // The super initializer call has at least 2 arguments: the 3147 // The super initializer call has at least 2 arguments: the
3106 // implicit receiver, and the hidden construction phase. 3148 // implicit receiver, and the hidden construction phase.
3107 ASSERT(ctor_args->length() >= 2); 3149 ASSERT(ctor_args->length() >= 2);
3108 for (int i = 2; i < ctor_args->length(); i++) { 3150 for (int i = 2; i < ctor_args->length(); i++) {
3109 AstNode* arg = ctor_args->NodeAt(i); 3151 AstNode* arg = ctor_args->NodeAt(i);
3110 if (!IsSimpleLocalOrLiteralNode(arg)) { 3152 if (!IsSimpleLocalOrLiteralNode(arg)) {
3111 LocalVariable* temp = CreateTempConstVariable(arg->token_pos(), "sca"); 3153 LocalVariable* temp = CreateTempConstVariable(arg->token_pos(), "sca");
3112 AstNode* save_temp = new StoreLocalNode(arg->token_pos(), temp, arg); 3154 AstNode* save_temp = new StoreLocalNode(arg->token_pos(), temp, arg);
3113 ctor_args->SetNodeAt(i, save_temp); 3155 ctor_args->SetNodeAt(i, save_temp);
3114 } 3156 }
3115 } 3157 }
3116 } 3158 }
3117 OpenBlock(); // Block to collect constructor body nodes. 3159 OpenBlock(); // Block to collect constructor body nodes.
3118 intptr_t body_pos = TokenPos(); 3160 intptr_t body_pos = TokenPos();
3119 3161
3120 // Insert the implicit super call to the super constructor body. 3162 // Insert the implicit super call to the super constructor body.
3121 if (super_call != NULL) { 3163 if (super_call != NULL) {
3164 ASSERT(!FLAG_move_super);
3122 ArgumentListNode* initializer_args = super_call->arguments(); 3165 ArgumentListNode* initializer_args = super_call->arguments();
3123 const Function& super_ctor = super_call->function(); 3166 const Function& super_ctor = super_call->function();
3124 // Patch the initializer call so it only executes the super initializer. 3167 // Patch the initializer call so it only executes the super initializer.
3125 initializer_args->SetNodeAt(1, new LiteralNode( 3168 initializer_args->SetNodeAt(1, new LiteralNode(
3126 body_pos, Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseInit)))); 3169 body_pos, Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseInit))));
3127 3170
3128 ArgumentListNode* super_call_args = new ArgumentListNode(body_pos); 3171 ArgumentListNode* super_call_args = new ArgumentListNode(body_pos);
3129 // First argument is the receiver. 3172 // First argument is the receiver.
3130 super_call_args->Add(new LoadLocalNode(body_pos, receiver)); 3173 super_call_args->Add(new LoadLocalNode(body_pos, receiver));
3131 // Second argument is the construction phase argument. 3174 // Second argument is the construction phase argument.
(...skipping 11129 matching lines...) Expand 10 before | Expand all | Expand 10 after
14261 void Parser::SkipQualIdent() { 14304 void Parser::SkipQualIdent() {
14262 ASSERT(IsIdentifier()); 14305 ASSERT(IsIdentifier());
14263 ConsumeToken(); 14306 ConsumeToken();
14264 if (CurrentToken() == Token::kPERIOD) { 14307 if (CurrentToken() == Token::kPERIOD) {
14265 ConsumeToken(); // Consume the kPERIOD token. 14308 ConsumeToken(); // Consume the kPERIOD token.
14266 ExpectIdentifier("identifier expected after '.'"); 14309 ExpectIdentifier("identifier expected after '.'");
14267 } 14310 }
14268 } 14311 }
14269 14312
14270 } // namespace dart 14313 } // namespace dart
OLDNEW
« 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