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

Side by Side Diff: runtime/vm/parser.cc

Issue 51123003: VM: Fix checked mode crash (issue 13831). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
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 "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/bootstrap.h" 9 #include "vm/bootstrap.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 ASSERT(!func.is_static()); 774 ASSERT(!func.is_static());
775 node_sequence = parser.ParseInstanceGetter(func); 775 node_sequence = parser.ParseInstanceGetter(func);
776 break; 776 break;
777 case RawFunction::kImplicitSetter: 777 case RawFunction::kImplicitSetter:
778 ASSERT(!func.is_static()); 778 ASSERT(!func.is_static());
779 node_sequence = parser.ParseInstanceSetter(func); 779 node_sequence = parser.ParseInstanceSetter(func);
780 break; 780 break;
781 case RawFunction::kImplicitStaticFinalGetter: 781 case RawFunction::kImplicitStaticFinalGetter:
782 node_sequence = parser.ParseStaticFinalGetter(func); 782 node_sequence = parser.ParseStaticFinalGetter(func);
783 break; 783 break;
784 case RawFunction::kStaticInitializer:
785 node_sequence = parser.ParseStaticInitializer(func);
786 break;
784 case RawFunction::kMethodExtractor: 787 case RawFunction::kMethodExtractor:
785 node_sequence = parser.ParseMethodExtractor(func); 788 node_sequence = parser.ParseMethodExtractor(func);
786 break; 789 break;
787 case RawFunction::kNoSuchMethodDispatcher: 790 case RawFunction::kNoSuchMethodDispatcher:
788 node_sequence = 791 node_sequence =
789 parser.ParseNoSuchMethodDispatcher(func, default_parameter_values); 792 parser.ParseNoSuchMethodDispatcher(func, default_parameter_values);
790 break; 793 break;
791 case RawFunction::kInvokeFieldDispatcher: 794 case RawFunction::kInvokeFieldDispatcher:
792 node_sequence = 795 node_sequence =
793 parser.ParseInvokeFieldDispatcher(func, default_parameter_values); 796 parser.ParseInvokeFieldDispatcher(func, default_parameter_values);
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
900 // Build local scope for function and populate with the formal parameters. 903 // Build local scope for function and populate with the formal parameters.
901 OpenFunctionBlock(func); 904 OpenFunctionBlock(func);
902 AddFormalParamsToScope(&params, current_block_->scope); 905 AddFormalParamsToScope(&params, current_block_->scope);
903 906
904 intptr_t ident_pos = TokenPos(); 907 intptr_t ident_pos = TokenPos();
905 const String& field_name = *ExpectIdentifier("field name expected"); 908 const String& field_name = *ExpectIdentifier("field name expected");
906 const Class& field_class = Class::Handle(func.Owner()); 909 const Class& field_class = Class::Handle(func.Owner());
907 const Field& field = 910 const Field& field =
908 Field::ZoneHandle(field_class.LookupStaticField(field_name)); 911 Field::ZoneHandle(field_class.LookupStaticField(field_name));
909 912
910 if (!field.is_const() && 913 // Static final fields must have an initializer.
911 (field.value() != Object::transition_sentinel().raw()) &&
912 (field.value() != Object::sentinel().raw())) {
913 // The field has already been initialized at compile time (this can
914 // happen, e.g., if we are recompiling for optimization). There is no
915 // need to check for initialization and compile the potentially very
916 // large initialization code. By skipping this code, the deoptimization
917 // ids will not line up with the original code, but this is safe because
918 // LoadStaticField does not deoptimize.
919 LoadStaticFieldNode* load_node = new LoadStaticFieldNode(ident_pos, field);
920 ReturnNode* return_node = new ReturnNode(ident_pos, load_node);
921 current_block_->statements->Add(return_node);
922 return CloseBlock();
923 }
924
925 // Static const fields must have an initializer.
926 ExpectToken(Token::kASSIGN); 914 ExpectToken(Token::kASSIGN);
927 915
928 // We don't want to use ParseConstExpr() here because we don't want
929 // the constant folding code to create, compile and execute a code
930 // fragment to evaluate the expression. Instead, we just make sure
931 // the static const field initializer is a constant expression and
932 // leave the evaluation to the getter function.
933 const intptr_t expr_pos = TokenPos(); 916 const intptr_t expr_pos = TokenPos();
934 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
935
936 if (field.is_const()) { 917 if (field.is_const()) {
918 // We don't want to use ParseConstExpr() here because we don't want
919 // the constant folding code to create, compile and execute a code
920 // fragment to evaluate the expression. Instead, we just make sure
921 // the static const field initializer is a constant expression and
922 // leave the evaluation to the getter function.
923 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
937 // This getter will only be called once at compile time. 924 // This getter will only be called once at compile time.
938 if (expr->EvalConstExpr() == NULL) { 925 if (expr->EvalConstExpr() == NULL) {
939 ErrorMsg(expr_pos, "initializer is not a valid compile-time constant"); 926 ErrorMsg(expr_pos, "initializer is not a valid compile-time constant");
940 } 927 }
941 ReturnNode* return_node = new ReturnNode(ident_pos, expr); 928 ReturnNode* return_node = new ReturnNode(ident_pos, expr);
942 current_block_->statements->Add(return_node); 929 current_block_->statements->Add(return_node);
943 } else { 930 } else {
944 // This getter may be called each time the static field is accessed. 931 // This getter may be called each time the static field is accessed.
945 // The following generated code lazily initializes the field: 932 // The following generated code lazily initializes the field:
946 // if (field.value === transition_sentinel) { 933 // if (field.value === transition_sentinel) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
988 SequenceNode* initialize_field = new SequenceNode(ident_pos, NULL); 975 SequenceNode* initialize_field = new SequenceNode(ident_pos, NULL);
989 initialize_field->Add( 976 initialize_field->Add(
990 new StoreStaticFieldNode( 977 new StoreStaticFieldNode(
991 ident_pos, 978 ident_pos,
992 field, 979 field,
993 new LiteralNode(ident_pos, Object::transition_sentinel()))); 980 new LiteralNode(ident_pos, Object::transition_sentinel())));
994 // TODO(hausner): If evaluation of the field value throws an exception, 981 // TODO(hausner): If evaluation of the field value throws an exception,
995 // we leave the field value as 'transition_sentinel', which is wrong. 982 // we leave the field value as 'transition_sentinel', which is wrong.
996 // A second reference to the field later throws a circular dependency 983 // A second reference to the field later throws a circular dependency
997 // exception. The field should instead be set to null after an exception. 984 // exception. The field should instead be set to null after an exception.
998 initialize_field->Add(new StoreStaticFieldNode(ident_pos, field, expr)); 985 const String& init_name =
986 String::Handle(Symbols::New(String::Handle(
987 String::Concat(Symbols::InitPrefix(), String::Handle(field.name())))));
988 const Function& init_function = Function::ZoneHandle(
989 field_class.LookupStaticFunction(init_name));
990 ASSERT(!init_function.IsNull());
991 ArgumentListNode* arguments = new ArgumentListNode(expr_pos);
992 StaticCallNode* init_call =
993 new StaticCallNode(expr_pos, init_function, arguments);
994
995 initialize_field->Add(new StoreStaticFieldNode(ident_pos,
996 field,
997 init_call));
999 AstNode* uninitialized_check = 998 AstNode* uninitialized_check =
1000 new IfNode(ident_pos, compare_uninitialized, initialize_field, NULL); 999 new IfNode(ident_pos, compare_uninitialized, initialize_field, NULL);
1001 current_block_->statements->Add(uninitialized_check); 1000 current_block_->statements->Add(uninitialized_check);
1002 1001
1003 // Generate code returning the field value. 1002 // Generate code returning the field value.
1004 ReturnNode* return_node = 1003 ReturnNode* return_node =
1005 new ReturnNode(ident_pos, 1004 new ReturnNode(ident_pos,
1006 new LoadStaticFieldNode(ident_pos, field)); 1005 new LoadStaticFieldNode(ident_pos, field));
1007 current_block_->statements->Add(return_node); 1006 current_block_->statements->Add(return_node);
1008 } 1007 }
1009 return CloseBlock(); 1008 return CloseBlock();
1010 } 1009 }
1011 1010
1012 1011
1012 SequenceNode* Parser::ParseStaticInitializer(const Function& func) {
1013 TRACE_PARSER("ParseStaticInitializer");
1014 ParamList params;
1015 ASSERT(func.num_fixed_parameters() == 0); // static.
1016 ASSERT(!func.HasOptionalParameters());
1017 ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
1018
1019 // Build local scope for function and populate with the formal parameters.
1020 OpenFunctionBlock(func);
1021 AddFormalParamsToScope(&params, current_block_->scope);
1022
1023 intptr_t expr_pos = func.token_pos();
1024 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
1025 ReturnNode* return_node = new ReturnNode(expr_pos, expr);
1026 current_block_->statements->Add(return_node);
1027 return CloseBlock();
1028 }
1029
1030
1013 // Create AstNodes for an implicit instance getter method: 1031 // Create AstNodes for an implicit instance getter method:
1014 // LoadLocalNode 0 ('this'); 1032 // LoadLocalNode 0 ('this');
1015 // LoadInstanceFieldNode (field_name); 1033 // LoadInstanceFieldNode (field_name);
1016 // ReturnNode (field's value); 1034 // ReturnNode (field's value);
1017 SequenceNode* Parser::ParseInstanceGetter(const Function& func) { 1035 SequenceNode* Parser::ParseInstanceGetter(const Function& func) {
1018 TRACE_PARSER("ParseInstanceGetter"); 1036 TRACE_PARSER("ParseInstanceGetter");
1019 ParamList params; 1037 ParamList params;
1020 // func.token_pos() points to the name of the field. 1038 // func.token_pos() points to the name of the field.
1021 intptr_t ident_pos = func.token_pos(); 1039 intptr_t ident_pos = func.token_pos();
1022 ASSERT(current_class().raw() == func.Owner()); 1040 ASSERT(current_class().raw() == func.Owner());
(...skipping 2219 matching lines...) Expand 10 before | Expand all | Expand 10 after
3242 if (field->has_factory) { 3260 if (field->has_factory) {
3243 ErrorMsg("keyword 'factory' not allowed in field declaration"); 3261 ErrorMsg("keyword 'factory' not allowed in field declaration");
3244 } 3262 }
3245 if (!field->has_static && field->has_const) { 3263 if (!field->has_static && field->has_const) {
3246 ErrorMsg(field->name_pos, "instance field may not be 'const'"); 3264 ErrorMsg(field->name_pos, "instance field may not be 'const'");
3247 } 3265 }
3248 Function& getter = Function::Handle(); 3266 Function& getter = Function::Handle();
3249 Function& setter = Function::Handle(); 3267 Function& setter = Function::Handle();
3250 Field& class_field = Field::ZoneHandle(); 3268 Field& class_field = Field::ZoneHandle();
3251 Instance& init_value = Instance::Handle(); 3269 Instance& init_value = Instance::Handle();
3270 intptr_t expr_pos = -1;
3252 while (true) { 3271 while (true) {
3253 bool has_initializer = CurrentToken() == Token::kASSIGN; 3272 bool has_initializer = CurrentToken() == Token::kASSIGN;
3254 bool has_simple_literal = false; 3273 bool has_simple_literal = false;
3255 if (has_initializer) { 3274 if (has_initializer) {
3256 ConsumeToken(); 3275 ConsumeToken();
3257 init_value = Object::sentinel().raw(); 3276 init_value = Object::sentinel().raw();
3258 // For static const fields and static final non-const fields, the 3277 // For static const fields and static final non-const fields, the
3259 // initialization expression will be parsed through the 3278 // initialization expression will be parsed through the
3260 // kImplicitStaticFinalGetter method invocation/compilation. 3279 // kImplicitStaticFinalGetter method invocation/compilation.
3261 // For instance fields, the expression is parsed when a constructor 3280 // For instance fields, the expression is parsed when a constructor
3262 // is compiled. 3281 // is compiled.
3263 // For static const fields and static final non-const fields with very 3282 // For static const fields and static final non-const fields with very
3264 // simple initializer expressions (e.g. a literal number or string), we 3283 // simple initializer expressions (e.g. a literal number or string), we
3265 // optimize away the kImplicitStaticFinalGetter and initialize the field 3284 // optimize away the kImplicitStaticFinalGetter and initialize the field
3266 // here. However, the class finalizer will check the value type for 3285 // here. However, the class finalizer will check the value type for
3267 // assignability once the declared field type can be resolved. If the 3286 // assignability once the declared field type can be resolved. If the
3268 // value is not assignable (assuming checked mode and disregarding actual 3287 // value is not assignable (assuming checked mode and disregarding actual
3269 // mode), the field value is reset and a kImplicitStaticFinalGetter is 3288 // mode), the field value is reset and a kImplicitStaticFinalGetter is
3270 // created at finalization time. 3289 // created at finalization time.
3271 3290
3272 if (field->has_static && (field->has_const || field->has_final) && 3291 if (field->has_static && (field->has_const || field->has_final) &&
3273 (LookaheadToken(1) == Token::kSEMICOLON)) { 3292 (LookaheadToken(1) == Token::kSEMICOLON)) {
3274 has_simple_literal = IsSimpleLiteral(*field->type, &init_value); 3293 has_simple_literal = IsSimpleLiteral(*field->type, &init_value);
3275 } 3294 }
3295 expr_pos = TokenPos();
3276 SkipExpr(); 3296 SkipExpr();
3277 } else { 3297 } else {
3278 // Static const and static final fields must have an initializer. 3298 // Static const and static final fields must have an initializer.
3279 // Static const fields are implicitly final. 3299 // Static const fields are implicitly final.
3280 if (field->has_static && field->has_final) { 3300 if (field->has_static && field->has_final) {
3281 ErrorMsg(field->name_pos, 3301 ErrorMsg(field->name_pos,
3282 "static %s field '%s' must have an initializer expression", 3302 "static %s field '%s' must have an initializer expression",
3283 field->has_const ? "const" : "final", 3303 field->has_const ? "const" : "final",
3284 field->name->ToCString()); 3304 field->name->ToCString());
3285 } 3305 }
(...skipping 23 matching lines...) Expand all
3309 getter = Function::New(getter_name, 3329 getter = Function::New(getter_name,
3310 RawFunction::kImplicitStaticFinalGetter, 3330 RawFunction::kImplicitStaticFinalGetter,
3311 field->has_static, 3331 field->has_static,
3312 field->has_const, 3332 field->has_const,
3313 /* is_abstract = */ false, 3333 /* is_abstract = */ false,
3314 /* is_external = */ false, 3334 /* is_external = */ false,
3315 current_class(), 3335 current_class(),
3316 field->name_pos); 3336 field->name_pos);
3317 getter.set_result_type(*field->type); 3337 getter.set_result_type(*field->type);
3318 members->AddFunction(getter); 3338 members->AddFunction(getter);
3339
3340 // Create initializer function.
3341 const Function& init_function = Function::ZoneHandle(
3342 Function::NewStaticInitializer(*field->name,
3343 *field->type,
3344 current_class(),
3345 expr_pos));
3346 members->AddFunction(init_function);
3319 } 3347 }
3320 } 3348 }
3321 3349
3322 // For instance fields, we create implicit getter and setter methods. 3350 // For instance fields, we create implicit getter and setter methods.
3323 if (!field->has_static) { 3351 if (!field->has_static) {
3324 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); 3352 String& getter_name = String::Handle(Field::GetterSymbol(*field->name));
3325 getter = Function::New(getter_name, RawFunction::kImplicitGetter, 3353 getter = Function::New(getter_name, RawFunction::kImplicitGetter,
3326 field->has_static, 3354 field->has_static,
3327 field->has_final, 3355 field->has_final,
3328 /* is_abstract = */ false, 3356 /* is_abstract = */ false,
(...skipping 1088 matching lines...) Expand 10 before | Expand all | Expand 10 after
4417 if (metadata_pos >= 0) { 4445 if (metadata_pos >= 0) {
4418 library_.AddFieldMetadata(field, metadata_pos); 4446 library_.AddFieldMetadata(field, metadata_pos);
4419 } 4447 }
4420 if (CurrentToken() == Token::kASSIGN) { 4448 if (CurrentToken() == Token::kASSIGN) {
4421 ConsumeToken(); 4449 ConsumeToken();
4422 Instance& field_value = Instance::Handle(Object::sentinel().raw()); 4450 Instance& field_value = Instance::Handle(Object::sentinel().raw());
4423 bool has_simple_literal = false; 4451 bool has_simple_literal = false;
4424 if ((is_const || is_final) && (LookaheadToken(1) == Token::kSEMICOLON)) { 4452 if ((is_const || is_final) && (LookaheadToken(1) == Token::kSEMICOLON)) {
4425 has_simple_literal = IsSimpleLiteral(type, &field_value); 4453 has_simple_literal = IsSimpleLiteral(type, &field_value);
4426 } 4454 }
4455 const intptr_t expr_pos = TokenPos();
4427 SkipExpr(); 4456 SkipExpr();
4428 field.set_value(field_value); 4457 field.set_value(field_value);
4429 if (!has_simple_literal) { 4458 if (!has_simple_literal) {
4430 // Create a static final getter. 4459 // Create a static final getter.
4431 String& getter_name = String::Handle(Field::GetterSymbol(var_name)); 4460 String& getter_name = String::Handle(Field::GetterSymbol(var_name));
4432 getter = Function::New(getter_name, 4461 getter = Function::New(getter_name,
4433 RawFunction::kImplicitStaticFinalGetter, 4462 RawFunction::kImplicitStaticFinalGetter,
4434 is_static, 4463 is_static,
4435 is_const, 4464 is_const,
4436 /* is_abstract = */ false, 4465 /* is_abstract = */ false,
4437 /* is_external = */ false, 4466 /* is_external = */ false,
4438 current_class(), 4467 current_class(),
4439 name_pos); 4468 name_pos);
4440 getter.set_result_type(type); 4469 getter.set_result_type(type);
4441 top_level->functions.Add(getter); 4470 top_level->functions.Add(getter);
4471
4472 // Create initializer function.
4473 const Function& init_function = Function::ZoneHandle(
4474 Function::NewStaticInitializer(var_name,
4475 type,
4476 current_class(),
4477 expr_pos));
4478 top_level->functions.Add(init_function);
4442 } 4479 }
4443 } else if (is_final) { 4480 } else if (is_final) {
4444 ErrorMsg(name_pos, "missing initializer for final or const variable"); 4481 ErrorMsg(name_pos, "missing initializer for final or const variable");
4445 } 4482 }
4446 4483
4447 if (CurrentToken() == Token::kCOMMA) { 4484 if (CurrentToken() == Token::kCOMMA) {
4448 ConsumeToken(); 4485 ConsumeToken();
4449 } else if (CurrentToken() == Token::kSEMICOLON) { 4486 } else if (CurrentToken() == Token::kSEMICOLON) {
4450 ConsumeToken(); 4487 ConsumeToken();
4451 break; 4488 break;
(...skipping 6136 matching lines...) Expand 10 before | Expand all | Expand 10 after
10588 void Parser::SkipQualIdent() { 10625 void Parser::SkipQualIdent() {
10589 ASSERT(IsIdentifier()); 10626 ASSERT(IsIdentifier());
10590 ConsumeToken(); 10627 ConsumeToken();
10591 if (CurrentToken() == Token::kPERIOD) { 10628 if (CurrentToken() == Token::kPERIOD) {
10592 ConsumeToken(); // Consume the kPERIOD token. 10629 ConsumeToken(); // Consume the kPERIOD token.
10593 ExpectIdentifier("identifier expected after '.'"); 10630 ExpectIdentifier("identifier expected after '.'");
10594 } 10631 }
10595 } 10632 }
10596 10633
10597 } // namespace dart 10634 } // namespace dart
OLDNEW
« runtime/vm/object.cc ('K') | « runtime/vm/parser.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698