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

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

Issue 10826090: Optimize away most implicit const getter functions (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 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 | 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 "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/class_finalizer.h" 8 #include "vm/class_finalizer.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/compiler_stats.h" 10 #include "vm/compiler_stats.h"
(...skipping 2511 matching lines...) Expand 10 before | Expand all | Expand 10 after
2522 if (field->has_factory) { 2522 if (field->has_factory) {
2523 ErrorMsg("keyword 'factory' not allowed in field declaration"); 2523 ErrorMsg("keyword 'factory' not allowed in field declaration");
2524 } 2524 }
2525 if (members->FieldNameExists(*field->name)) { 2525 if (members->FieldNameExists(*field->name)) {
2526 ErrorMsg(field->name_pos, 2526 ErrorMsg(field->name_pos,
2527 "'%s' field/method already defined\n", field->name->ToCString()); 2527 "'%s' field/method already defined\n", field->name->ToCString());
2528 } 2528 }
2529 Function& getter = Function::Handle(); 2529 Function& getter = Function::Handle();
2530 Function& setter = Function::Handle(); 2530 Function& setter = Function::Handle();
2531 Field& class_field = Field::Handle(); 2531 Field& class_field = Field::Handle();
2532 Instance& init_value = Instance::Handle();
2532 while (true) { 2533 while (true) {
2533 bool has_initializer = CurrentToken() == Token::kASSIGN; 2534 bool has_initializer = CurrentToken() == Token::kASSIGN;
2535 bool have_simple_literal = false;
regis 2012/07/31 23:19:54 has_simple_literal?
hausner 2012/07/31 23:34:03 Done.
2534 if (has_initializer) { 2536 if (has_initializer) {
2535 ConsumeToken(); 2537 ConsumeToken();
2538 init_value = Object::sentinel();
2536 // For static final fields, the initialization expression 2539 // For static final fields, the initialization expression
2537 // will be parsed through the kConstImplicitGetter method 2540 // will be parsed through the kConstImplicitGetter method
2538 // invocation/compilation. 2541 // invocation/compilation.
2539 // For instance fields, the expression is parsed when a constructor 2542 // For instance fields, the expression is parsed when a constructor
2540 // is compiled. 2543 // is compiled.
2544 // For static fields with very simple initializer expressions
2545 // (e.g. a literal number or string) we optimize away the
2546 // kConstImplicitGetter and initialize the field here.
2547
2548 if (field->has_static && (field->has_final || field->has_const) &&
2549 (LookaheadToken(1) == Token::kSEMICOLON)) {
2550 have_simple_literal = IsSimpleLiteral(*field->type, &init_value);
2551 }
2541 SkipExpr(); 2552 SkipExpr();
2542 } else { 2553 } else {
2543 if (field->has_const || (field->has_static && field->has_final)) { 2554 if (field->has_const || (field->has_static && field->has_final)) {
2544 ErrorMsg(field->name_pos, 2555 ErrorMsg(field->name_pos,
2545 "%s%s field '%s' must have an initializer expression", 2556 "%s%s field '%s' must have an initializer expression",
2546 field->has_static ? "static " : "", 2557 field->has_static ? "static " : "",
2547 field->has_const ? "const" : "final", 2558 field->has_const ? "const" : "final",
2548 field->name->ToCString()); 2559 field->name->ToCString());
2549 } 2560 }
2550 } 2561 }
2551 2562
2552 // Create the field object. 2563 // Create the field object.
2553 // TODO(hausner): For now, all static final fields are constant. Remove 2564 // TODO(hausner): For now, all static final fields are constant. Remove
2554 // this when lazy init of static variables is implemented. 2565 // this when lazy init of static variables is implemented.
2555 class_field = Field::New(*field->name, 2566 class_field = Field::New(*field->name,
2556 field->has_static, 2567 field->has_static,
2557 field->has_final, 2568 field->has_final,
2558 field->has_const || field->has_final, 2569 field->has_const || field->has_final,
2559 field->name_pos); 2570 field->name_pos);
2560 class_field.set_type(*field->type); 2571 class_field.set_type(*field->type);
2561 class_field.set_has_initializer(has_initializer); 2572 class_field.set_has_initializer(has_initializer);
2562 members->AddField(class_field); 2573 members->AddField(class_field);
2563 2574
2564 // For static final fields, set value to "uninitialized" and 2575 // For static final fields, set value to "uninitialized" and
2565 // create a kConstImplicitGetter getter method. 2576 // create a kConstImplicitGetter getter method.
2566 if (field->has_static && has_initializer) { 2577 if (field->has_static && has_initializer) {
2567 class_field.set_value(Instance::Handle(Object::sentinel())); 2578 class_field.set_value(init_value);
2568 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); 2579 if (!have_simple_literal) {
2569 getter = Function::New(getter_name, RawFunction::kConstImplicitGetter, 2580 String& getter_name = String::Handle(Field::GetterSymbol(*field->name));
2570 field->has_static, field->has_final, false, 2581 getter = Function::New(getter_name, RawFunction::kConstImplicitGetter,
2571 /* is_abstract */ false, 2582 field->has_static, field->has_final,
2572 field->name_pos); 2583 /* is_abstract */ false,
2573 getter.set_result_type(*field->type); 2584 /* is_external */ false,
2574 members->AddFunction(getter); 2585 field->name_pos);
2586 getter.set_result_type(*field->type);
2587 members->AddFunction(getter);
2588 }
2575 } 2589 }
2576 2590
2577 // For instance fields, we create implicit getter and setter methods. 2591 // For instance fields, we create implicit getter and setter methods.
2578 if (!field->has_static) { 2592 if (!field->has_static) {
2579 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); 2593 String& getter_name = String::Handle(Field::GetterSymbol(*field->name));
2580 getter = Function::New(getter_name, RawFunction::kImplicitGetter, 2594 getter = Function::New(getter_name, RawFunction::kImplicitGetter,
2581 field->has_static, field->has_final, false, 2595 field->has_static, field->has_final, false,
2582 /* is_abstract */ false, 2596 /* is_abstract */ false,
2583 field->name_pos); 2597 field->name_pos);
2584 ParamList params; 2598 ParamList params;
(...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after
3512 var_name.ToCString()); 3526 var_name.ToCString());
3513 } 3527 }
3514 3528
3515 field = Field::New(var_name, is_static, is_final, is_const, name_pos); 3529 field = Field::New(var_name, is_static, is_final, is_const, name_pos);
3516 field.set_type(type); 3530 field.set_type(type);
3517 field.set_value(Instance::Handle(Instance::null())); 3531 field.set_value(Instance::Handle(Instance::null()));
3518 top_level->fields.Add(field); 3532 top_level->fields.Add(field);
3519 library_.AddObject(field, var_name); 3533 library_.AddObject(field, var_name);
3520 if (CurrentToken() == Token::kASSIGN) { 3534 if (CurrentToken() == Token::kASSIGN) {
3521 ConsumeToken(); 3535 ConsumeToken();
3536 Instance& field_value = Instance::Handle(Object::sentinel());
3537 bool have_simple_literal = false;
3538 if ((is_final || is_const) && (LookaheadToken(1) == Token::kSEMICOLON)) {
3539 have_simple_literal = IsSimpleLiteral(type, &field_value);
3540 }
3522 SkipExpr(); 3541 SkipExpr();
3523 field.set_value(Instance::Handle(Object::sentinel())); 3542 field.set_value(field_value);
3524 // Create a static const getter. 3543 if (!have_simple_literal) {
3525 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name)); 3544 // Create a static const getter.
3526 getter = Function::New(getter_name, RawFunction::kConstImplicitGetter, 3545 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name));
3527 is_static, is_final, false, false, name_pos); 3546 getter = Function::New(getter_name, RawFunction::kConstImplicitGetter,
3528 getter.set_result_type(type); 3547 is_static, is_final, false, false, name_pos);
3529 top_level->functions.Add(getter); 3548 getter.set_result_type(type);
3549 top_level->functions.Add(getter);
3550 }
3551
3530 } else if (is_final || is_const) { 3552 } else if (is_final || is_const) {
3531 ErrorMsg(name_pos, "missing initializer for final or const variable"); 3553 ErrorMsg(name_pos, "missing initializer for final or const variable");
3532 } 3554 }
3533 3555
3534 if (CurrentToken() == Token::kCOMMA) { 3556 if (CurrentToken() == Token::kCOMMA) {
3535 ConsumeToken(); 3557 ConsumeToken();
3536 } else if (CurrentToken() == Token::kSEMICOLON) { 3558 } else if (CurrentToken() == Token::kSEMICOLON) {
3537 ConsumeToken(); 3559 ConsumeToken();
3538 break; 3560 break;
3539 } else { 3561 } else {
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after
4461 ConsumeToken(); 4483 ConsumeToken();
4462 } while (nesting_level > 0); 4484 } while (nesting_level > 0);
4463 if (nesting_level < 0) { 4485 if (nesting_level < 0) {
4464 return false; 4486 return false;
4465 } 4487 }
4466 } 4488 }
4467 return true; 4489 return true;
4468 } 4490 }
4469 4491
4470 4492
4493 bool Parser::IsSimpleLiteral(const AbstractType& type, Instance* value) {
4494 bool no_check = type.IsDynamicType();
4495 if ((CurrentToken() == Token::kINTEGER) &&
4496 (no_check || type.IsIntInterface() || type.IsNumberInterface())) {
4497 *value = CurrentIntegerLiteral();
4498 return true;
4499 } else if ((CurrentToken() == Token::kDOUBLE) &&
4500 (no_check || type.IsDoubleInterface() || type.IsNumberInterface())) {
4501 *value = CurrentDoubleLiteral();
4502 return true;
4503 } else if ((CurrentToken() == Token::kSTRING) &&
4504 (no_check || type.IsStringInterface())) {
4505 *value = CurrentLiteral()->raw();
regis 2012/07/31 23:19:54 Not specific to this change list, but it feels str
hausner 2012/07/31 23:34:03 True. CurrentLiteral used to return a pointer to a
4506 return true;
4507 } else if ((CurrentToken() == Token::kTRUE) &&
4508 (no_check || type.IsBoolInterface())) {
4509 *value = Bool::True();
4510 return true;
4511 } else if ((CurrentToken() == Token::kFALSE) &&
4512 (no_check || type.IsBoolInterface())) {
4513 *value = Bool::False();
4514 return true;
4515 } else if (CurrentToken() == Token::kNULL) {
4516 *value = Instance::null();
4517 return true;
4518 }
4519 return false;
4520 }
4521
4522
4471 // Returns true if the current token is kIDENT or a pseudo-keyword. 4523 // Returns true if the current token is kIDENT or a pseudo-keyword.
4472 bool Parser::IsIdentifier() { 4524 bool Parser::IsIdentifier() {
4473 return Token::IsIdentifier(CurrentToken()); 4525 return Token::IsIdentifier(CurrentToken());
4474 } 4526 }
4475 4527
4476 4528
4477 // Returns true if the next tokens can be parsed as a type with optional 4529 // Returns true if the next tokens can be parsed as a type with optional
4478 // type parameters. Current token position is not restored. 4530 // type parameters. Current token position is not restored.
4479 bool Parser::TryParseOptionalType() { 4531 bool Parser::TryParseOptionalType() {
4480 if (CurrentToken() == Token::kIDENT) { 4532 if (CurrentToken() == Token::kIDENT) {
(...skipping 4308 matching lines...) Expand 10 before | Expand all | Expand 10 after
8789 void Parser::SkipQualIdent() { 8841 void Parser::SkipQualIdent() {
8790 ASSERT(IsIdentifier()); 8842 ASSERT(IsIdentifier());
8791 ConsumeToken(); 8843 ConsumeToken();
8792 if (CurrentToken() == Token::kPERIOD) { 8844 if (CurrentToken() == Token::kPERIOD) {
8793 ConsumeToken(); // Consume the kPERIOD token. 8845 ConsumeToken(); // Consume the kPERIOD token.
8794 ExpectIdentifier("identifier expected after '.'"); 8846 ExpectIdentifier("identifier expected after '.'");
8795 } 8847 }
8796 } 8848 }
8797 8849
8798 } // namespace dart 8850 } // namespace dart
OLDNEW
« runtime/vm/object.cc ('K') | « runtime/vm/parser.h ('k') | runtime/vm/parser_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698