| OLD | NEW |
| 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 5435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5446 | 5446 |
| 5447 static bool IsLocalOrLiteralNode(AstNode* node) { | 5447 static bool IsLocalOrLiteralNode(AstNode* node) { |
| 5448 return node->IsLoadLocalNode() || node->IsLiteralNode(); | 5448 return node->IsLoadLocalNode() || node->IsLiteralNode(); |
| 5449 } | 5449 } |
| 5450 | 5450 |
| 5451 | 5451 |
| 5452 LocalVariable* Parser::CreateTempConstVariable(intptr_t token_index, | 5452 LocalVariable* Parser::CreateTempConstVariable(intptr_t token_index, |
| 5453 intptr_t token_id, | 5453 intptr_t token_id, |
| 5454 const char* s) { | 5454 const char* s) { |
| 5455 char name[64]; | 5455 char name[64]; |
| 5456 OS::SNPrint(name, 64, "%s%d", s, token_id); | 5456 OS::SNPrint(name, 64, ":%s%d", s, token_id); |
| 5457 LocalVariable* temp = | 5457 LocalVariable* temp = |
| 5458 new LocalVariable(token_index, | 5458 new LocalVariable(token_index, |
| 5459 String::ZoneHandle(String::NewSymbol(name)), | 5459 String::ZoneHandle(String::NewSymbol(name)), |
| 5460 Type::ZoneHandle(Type::DynamicType())); | 5460 Type::ZoneHandle(Type::DynamicType())); |
| 5461 temp->set_is_final(); | 5461 temp->set_is_final(); |
| 5462 current_block_->scope->AddVariable(temp); | 5462 current_block_->scope->AddVariable(temp); |
| 5463 return temp; | 5463 return temp; |
| 5464 } | 5464 } |
| 5465 | 5465 |
| 5466 | 5466 |
| 5467 // If 'node' can create side effects, store its result in a temporary variable | 5467 // If 'node' can create side effects, store its result in a temporary variable |
| 5468 // and return a LoadLocalNode instead. | 5468 // and return a LoadLocalNode instead. |
| 5469 // Side effect free nodes are LoadLocalNode and LiteralNode. | 5469 // Side effect free nodes are LoadLocalNode and LiteralNode. |
| 5470 AstNode* Parser::AsSideEffectFreeNode(AstNode* node) { | 5470 AstNode* Parser::AsSideEffectFreeNode(AstNode* node) { |
| 5471 if (node->IsLoadIndexedNode()) { | 5471 if (node->IsLoadIndexedNode()) { |
| 5472 LoadIndexedNode* load_indexed = node->AsLoadIndexedNode(); | 5472 LoadIndexedNode* load_indexed = node->AsLoadIndexedNode(); |
| 5473 intptr_t token_id = node->id(); | 5473 intptr_t token_id = node->id(); |
| 5474 intptr_t token_index = node->token_index(); | 5474 intptr_t token_index = node->token_index(); |
| 5475 node = NULL; // Do not use it. | 5475 node = NULL; // Do not use it. |
| 5476 // The array object access may not have side effects. |
| 5477 // First, evaluate the array object expression if it might have side |
| 5478 // effects. |
| 5479 if (!IsLocalOrLiteralNode(load_indexed->array())) { |
| 5480 LocalVariable* temp = |
| 5481 CreateTempConstVariable(token_index, token_id, "lia"); |
| 5482 AstNode* save = |
| 5483 new StoreLocalNode(token_index, *temp, load_indexed->array()); |
| 5484 current_block_->statements->Add(save); |
| 5485 AstNode* load = new LoadLocalNode(token_index, *temp); |
| 5486 load_indexed = new LoadIndexedNode(token_index, |
| 5487 load, |
| 5488 load_indexed->index_expr()); |
| 5489 } |
| 5490 // Second, evaluate the index expression and store in a temporary |
| 5491 // variable if it might have side effects. |
| 5476 if (!IsLocalOrLiteralNode(load_indexed->index_expr())) { | 5492 if (!IsLocalOrLiteralNode(load_indexed->index_expr())) { |
| 5477 LocalVariable* temp = | 5493 LocalVariable* temp = |
| 5478 CreateTempConstVariable(token_index, token_id, "lix"); | 5494 CreateTempConstVariable(token_index, token_id, "lix"); |
| 5479 AstNode* save = | 5495 AstNode* save = |
| 5480 new StoreLocalNode(token_index, *temp, load_indexed->index_expr()); | 5496 new StoreLocalNode(token_index, *temp, load_indexed->index_expr()); |
| 5481 current_block_->statements->Add(save); | 5497 current_block_->statements->Add(save); |
| 5482 AstNode* load = new LoadLocalNode(token_index, *temp); | 5498 AstNode* load = new LoadLocalNode(token_index, *temp); |
| 5483 load_indexed = new LoadIndexedNode(token_index, | 5499 load_indexed = new LoadIndexedNode(token_index, |
| 5484 load_indexed->array(), | 5500 load_indexed->array(), |
| 5485 load); | 5501 load); |
| 5486 } | 5502 } |
| 5487 // The array object access may not have side effects. | |
| 5488 if (!IsLocalOrLiteralNode(load_indexed->array())) { | |
| 5489 LocalVariable* temp = | |
| 5490 CreateTempConstVariable(token_index, token_id, "lia"); | |
| 5491 AstNode* save = | |
| 5492 new StoreLocalNode(token_index, *temp, load_indexed->array()); | |
| 5493 current_block_->statements->Add(save); | |
| 5494 AstNode* load = new LoadLocalNode(token_index, *temp); | |
| 5495 load_indexed = new LoadIndexedNode(token_index, | |
| 5496 load, | |
| 5497 load_indexed->index_expr()); | |
| 5498 } | |
| 5499 return load_indexed; | 5503 return load_indexed; |
| 5500 } | 5504 } |
| 5501 if (node->IsInstanceGetterNode()) { | 5505 if (node->IsInstanceGetterNode()) { |
| 5502 InstanceGetterNode* getter = node->AsInstanceGetterNode(); | 5506 InstanceGetterNode* getter = node->AsInstanceGetterNode(); |
| 5503 intptr_t token_index = node->token_index(); | 5507 intptr_t token_index = node->token_index(); |
| 5504 intptr_t token_id = node->id(); | 5508 intptr_t token_id = node->id(); |
| 5505 node = NULL; // Do not use it. | 5509 node = NULL; // Do not use it. |
| 5506 if (!IsLocalOrLiteralNode(getter->receiver())) { | 5510 if (!IsLocalOrLiteralNode(getter->receiver())) { |
| 5507 LocalVariable* temp = | 5511 LocalVariable* temp = |
| 5508 CreateTempConstVariable(token_index, token_id, "igr"); | 5512 CreateTempConstVariable(token_index, token_id, "igr"); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5636 return expr->AsLiteralNode(); | 5640 return expr->AsLiteralNode(); |
| 5637 } | 5641 } |
| 5638 | 5642 |
| 5639 | 5643 |
| 5640 AstNode* Parser::ParseConditionalExpr() { | 5644 AstNode* Parser::ParseConditionalExpr() { |
| 5641 TRACE_PARSER("ParseConditionalExpr"); | 5645 TRACE_PARSER("ParseConditionalExpr"); |
| 5642 const intptr_t expr_pos = token_index_; | 5646 const intptr_t expr_pos = token_index_; |
| 5643 AstNode* expr = ParseBinaryExpr(Token::Precedence(Token::kOR)); | 5647 AstNode* expr = ParseBinaryExpr(Token::Precedence(Token::kOR)); |
| 5644 if (CurrentToken() == Token::kCONDITIONAL) { | 5648 if (CurrentToken() == Token::kCONDITIONAL) { |
| 5645 ConsumeToken(); | 5649 ConsumeToken(); |
| 5646 AstNode* expr1 = ParseConditionalExpr(); | 5650 AstNode* expr1 = ParseExpr(kAllowConst); |
| 5647 ExpectToken(Token::kCOLON); | 5651 ExpectToken(Token::kCOLON); |
| 5648 AstNode* expr2 = ParseConditionalExpr(); | 5652 AstNode* expr2 = ParseExpr(kAllowConst); |
| 5649 expr = new ConditionalExprNode(expr_pos, expr, expr1, expr2); | 5653 expr = new ConditionalExprNode(expr_pos, expr, expr1, expr2); |
| 5650 } | 5654 } |
| 5651 return expr; | 5655 return expr; |
| 5652 } | 5656 } |
| 5653 | 5657 |
| 5654 | 5658 |
| 5655 AstNode* Parser::ParseUnaryExpr() { | 5659 AstNode* Parser::ParseUnaryExpr() { |
| 5656 TRACE_PARSER("ParseUnaryExpr"); | 5660 TRACE_PARSER("ParseUnaryExpr"); |
| 5657 AstNode* expr = NULL; | 5661 AstNode* expr = NULL; |
| 5658 const intptr_t op_pos = token_index_; | 5662 const intptr_t op_pos = token_index_; |
| (...skipping 2025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7684 ConsumeToken(); | 7688 ConsumeToken(); |
| 7685 SkipUnaryExpr(); | 7689 SkipUnaryExpr(); |
| 7686 } | 7690 } |
| 7687 } | 7691 } |
| 7688 | 7692 |
| 7689 | 7693 |
| 7690 void Parser::SkipConditionalExpr() { | 7694 void Parser::SkipConditionalExpr() { |
| 7691 SkipBinaryExpr(); | 7695 SkipBinaryExpr(); |
| 7692 if (CurrentToken() == Token::kCONDITIONAL) { | 7696 if (CurrentToken() == Token::kCONDITIONAL) { |
| 7693 ConsumeToken(); | 7697 ConsumeToken(); |
| 7694 SkipConditionalExpr(); | 7698 SkipExpr(); |
| 7695 ExpectToken(Token::kCOLON); | 7699 ExpectToken(Token::kCOLON); |
| 7696 SkipConditionalExpr(); | 7700 SkipExpr(); |
| 7697 } | 7701 } |
| 7698 } | 7702 } |
| 7699 | 7703 |
| 7700 | 7704 |
| 7701 void Parser::SkipExpr() { | 7705 void Parser::SkipExpr() { |
| 7702 SkipConditionalExpr(); | 7706 SkipConditionalExpr(); |
| 7703 if (Token::IsAssignmentOperator(CurrentToken())) { | 7707 if (Token::IsAssignmentOperator(CurrentToken())) { |
| 7704 ConsumeToken(); | 7708 ConsumeToken(); |
| 7705 SkipExpr(); | 7709 SkipExpr(); |
| 7706 } | 7710 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 7717 void Parser::SkipQualIdent() { | 7721 void Parser::SkipQualIdent() { |
| 7718 ASSERT(IsIdentifier()); | 7722 ASSERT(IsIdentifier()); |
| 7719 ConsumeToken(); | 7723 ConsumeToken(); |
| 7720 if (CurrentToken() == Token::kPERIOD) { | 7724 if (CurrentToken() == Token::kPERIOD) { |
| 7721 ConsumeToken(); // Consume the kPERIOD token. | 7725 ConsumeToken(); // Consume the kPERIOD token. |
| 7722 ExpectIdentifier("identifier expected after '.'"); | 7726 ExpectIdentifier("identifier expected after '.'"); |
| 7723 } | 7727 } |
| 7724 } | 7728 } |
| 7725 | 7729 |
| 7726 } // namespace dart | 7730 } // namespace dart |
| OLD | NEW |