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

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

Issue 8678031: Optimize type checks of list and map literals. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years 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
« no previous file with comments | « runtime/vm/object.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) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 6562 matching lines...) Expand 10 before | Expand all | Expand 10 after
6573 AstNode* Parser::ParseListLiteral(intptr_t type_pos, 6573 AstNode* Parser::ParseListLiteral(intptr_t type_pos,
6574 bool is_const, 6574 bool is_const,
6575 const TypeArguments& type_arguments) { 6575 const TypeArguments& type_arguments) {
6576 TRACE_PARSER("ParseListLiteral"); 6576 TRACE_PARSER("ParseListLiteral");
6577 ASSERT(type_pos >= 0); 6577 ASSERT(type_pos >= 0);
6578 ASSERT(CurrentToken() == Token::kLBRACK || CurrentToken() == Token::kINDEX); 6578 ASSERT(CurrentToken() == Token::kLBRACK || CurrentToken() == Token::kINDEX);
6579 const intptr_t literal_pos = token_index_; 6579 const intptr_t literal_pos = token_index_;
6580 bool is_empty_literal = CurrentToken() == Token::kINDEX; 6580 bool is_empty_literal = CurrentToken() == Token::kINDEX;
6581 ConsumeToken(); 6581 ConsumeToken();
6582 6582
6583 Type& element_type = Type::Handle(Type::DynamicType()); 6583 Type& element_type = Type::ZoneHandle(Type::DynamicType());
6584 // If no type argument vector is provided, leave it as null, which is 6584 // If no type argument vector is provided, leave it as null, which is
6585 // equivalent to using Dynamic as the type argument for the element type. 6585 // equivalent to using Dynamic as the type argument for the element type.
6586 if (!type_arguments.IsNull()) { 6586 if (!type_arguments.IsNull()) {
6587 ASSERT(type_arguments.Length() > 0); 6587 ASSERT(type_arguments.Length() > 0);
6588 // List literals take a single type argument. 6588 // List literals take a single type argument.
6589 element_type = type_arguments.TypeAt(0); 6589 element_type = type_arguments.TypeAt(0);
6590 if (type_arguments.Length() != 1) { 6590 if (type_arguments.Length() != 1) {
6591 ErrorMsg(type_pos, 6591 ErrorMsg(type_pos,
6592 "a list literal takes one type argument specifying " 6592 "a list literal takes one type argument specifying "
6593 "the element type"); 6593 "the element type");
6594 } 6594 }
6595 if (is_const && !element_type.IsInstantiated()) { 6595 if (is_const && !element_type.IsInstantiated()) {
6596 ErrorMsg(type_pos, 6596 ErrorMsg(type_pos,
6597 "the type argument of a constant list literal cannot include " 6597 "the type argument of a constant list literal cannot include "
6598 "a type variable"); 6598 "a type variable");
6599 } 6599 }
6600 } 6600 }
6601 ASSERT(type_arguments.IsNull() || (type_arguments.Length() == 1)); 6601 ASSERT(type_arguments.IsNull() || (type_arguments.Length() == 1));
6602 6602
6603 // Parse the list elements. Note: there may be an optional extra 6603 // Parse the list elements. Note: there may be an optional extra
6604 // comma after the last element. 6604 // comma after the last element.
6605 ArrayNode* list = new ArrayNode(token_index_, TypeArguments::ZoneHandle()); 6605 ArrayNode* list = new ArrayNode(token_index_, TypeArguments::ZoneHandle());
6606 if (!is_empty_literal) { 6606 if (!is_empty_literal) {
6607 const bool saved_mode = SetAllowFunctionLiterals(true); 6607 const bool saved_mode = SetAllowFunctionLiterals(true);
6608 const String& dst_name = String::ZoneHandle(
6609 String::NewSymbol("list literal element"));
6608 while (CurrentToken() != Token::kRBRACK) { 6610 while (CurrentToken() != Token::kRBRACK) {
6609 list->AddElement(ParseExpr(is_const)); 6611 const intptr_t element_pos = token_index_;
6612 AstNode* element = ParseExpr(is_const);
6613 if (FLAG_enable_type_checks &&
6614 !is_const &&
6615 !element_type.IsDynamicType()) {
6616 // The expression needs to be type checked at runtime.
6617 // Eliminate the type check if it can be performed at compile time and
6618 // if it succeeds.
6619 if (!element_type.IsInstantiated() ||
6620 !element->IsLiteralNode() ||
6621 !element->AsLiteralNode()->literal().
6622 IsAssignableTo(element_type, TypeArguments::Handle())) {
6623 element = new AssignableNode(element_pos,
6624 element,
6625 element_type,
6626 dst_name);
6627 }
6628 }
6629 list->AddElement(element);
6610 if (CurrentToken() == Token::kCOMMA) { 6630 if (CurrentToken() == Token::kCOMMA) {
6611 ConsumeToken(); 6631 ConsumeToken();
6612 } else if (CurrentToken() != Token::kRBRACK) { 6632 } else if (CurrentToken() != Token::kRBRACK) {
6613 ErrorMsg("comma or ']' expected"); 6633 ErrorMsg("comma or ']' expected");
6614 } 6634 }
6615 } 6635 }
6616 ExpectToken(Token::kRBRACK); 6636 ExpectToken(Token::kRBRACK);
6617 SetAllowFunctionLiterals(saved_mode); 6637 SetAllowFunctionLiterals(saved_mode);
6618 } 6638 }
6619 6639
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
6654 const Function& literal_list_factory = Function::ZoneHandle( 6674 const Function& literal_list_factory = Function::ZoneHandle(
6655 literal_factory_class.LookupFactory(literal_list_factory_name)); 6675 literal_factory_class.LookupFactory(literal_list_factory_name));
6656 ASSERT(!literal_list_factory.IsNull()); 6676 ASSERT(!literal_list_factory.IsNull());
6657 if (!type_arguments.IsNull() && 6677 if (!type_arguments.IsNull() &&
6658 !type_arguments.IsInstantiated() && 6678 !type_arguments.IsInstantiated() &&
6659 (current_block_->scope->function_level() > 0)) { 6679 (current_block_->scope->function_level() > 0)) {
6660 // Make sure that the instantiator is captured. 6680 // Make sure that the instantiator is captured.
6661 CaptureReceiver(); 6681 CaptureReceiver();
6662 } 6682 }
6663 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); 6683 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos);
6664 factory_param->Add(
6665 new LiteralNode(literal_pos, Smi::ZoneHandle(Smi::New(literal_pos))));
6666 factory_param->Add(
6667 new LiteralNode(literal_pos, String::ZoneHandle(element_type.Name())));
6668 factory_param->Add(list); 6684 factory_param->Add(list);
6669 return new ConstructorCallNode( 6685 return new ConstructorCallNode(
6670 literal_pos, type_arguments, literal_list_factory, factory_param); 6686 literal_pos, type_arguments, literal_list_factory, factory_param);
6671 } 6687 }
6672 } 6688 }
6673 6689
6674 6690
6675 static void AddKeyValuePair(ArrayNode* pairs, 6691 static void AddKeyValuePair(ArrayNode* pairs,
6676 bool is_const, 6692 bool is_const,
6677 AstNode* key, 6693 AstNode* key,
(...skipping 21 matching lines...) Expand all
6699 6715
6700 AstNode* Parser::ParseMapLiteral(intptr_t type_pos, 6716 AstNode* Parser::ParseMapLiteral(intptr_t type_pos,
6701 bool is_const, 6717 bool is_const,
6702 const TypeArguments& type_arguments) { 6718 const TypeArguments& type_arguments) {
6703 TRACE_PARSER("ParseMapLiteral"); 6719 TRACE_PARSER("ParseMapLiteral");
6704 ASSERT(type_pos >= 0); 6720 ASSERT(type_pos >= 0);
6705 ASSERT(CurrentToken() == Token::kLBRACE); 6721 ASSERT(CurrentToken() == Token::kLBRACE);
6706 const intptr_t literal_pos = token_index_; 6722 const intptr_t literal_pos = token_index_;
6707 ConsumeToken(); 6723 ConsumeToken();
6708 6724
6709 Type& value_type = Type::Handle(Type::DynamicType()); 6725 Type& value_type = Type::ZoneHandle(Type::DynamicType());
6710 TypeArguments& map_type_arguments = 6726 TypeArguments& map_type_arguments =
6711 TypeArguments::ZoneHandle(type_arguments.raw()); 6727 TypeArguments::ZoneHandle(type_arguments.raw());
6712 // If no type argument vector is provided, leave it as null, which is 6728 // If no type argument vector is provided, leave it as null, which is
6713 // equivalent to using Dynamic as the type argument for the value type. 6729 // equivalent to using Dynamic as the type argument for the value type.
6714 if (!map_type_arguments.IsNull()) { 6730 if (!map_type_arguments.IsNull()) {
6715 ASSERT(map_type_arguments.Length() > 0); 6731 ASSERT(map_type_arguments.Length() > 0);
6716 // Map literals take a single type argument. 6732 // Map literals take a single type argument.
6717 value_type = map_type_arguments.TypeAt(0); 6733 value_type = map_type_arguments.TypeAt(0);
6718 if (map_type_arguments.Length() > 1) { 6734 if (map_type_arguments.Length() > 1) {
6719 // We temporarily accept two type arguments, as long as the first one is 6735 // We temporarily accept two type arguments, as long as the first one is
(...skipping 22 matching lines...) Expand all
6742 "the type argument of a constant map literal cannot include " 6758 "the type argument of a constant map literal cannot include "
6743 "a type variable"); 6759 "a type variable");
6744 } 6760 }
6745 } 6761 }
6746 ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2)); 6762 ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2));
6747 6763
6748 // Parse the map entries. Note: there may be an optional extra 6764 // Parse the map entries. Note: there may be an optional extra
6749 // comma after the last entry. 6765 // comma after the last entry.
6750 ArrayNode* kv_pairs = 6766 ArrayNode* kv_pairs =
6751 new ArrayNode(token_index_, TypeArguments::ZoneHandle()); 6767 new ArrayNode(token_index_, TypeArguments::ZoneHandle());
6768 const String& dst_name = String::ZoneHandle(
6769 String::NewSymbol("list literal element"));
6752 while (CurrentToken() != Token::kRBRACE) { 6770 while (CurrentToken() != Token::kRBRACE) {
6753 AstNode* key = NULL; 6771 AstNode* key = NULL;
6754 if (CurrentToken() == Token::kSTRING) { 6772 if (CurrentToken() == Token::kSTRING) {
6755 key = ParseStringLiteral(); 6773 key = ParseStringLiteral();
6756 } 6774 }
6757 if (key == NULL) { 6775 if (key == NULL) {
6758 ErrorMsg("map entry key must be string literal"); 6776 ErrorMsg("map entry key must be string literal");
6759 } else if (is_const && !key->IsLiteralNode()) { 6777 } else if (is_const && !key->IsLiteralNode()) {
6760 ErrorMsg("map entry key must be compile time constant string"); 6778 ErrorMsg("map entry key must be compile time constant string");
6761 } 6779 }
6762 ExpectToken(Token::kCOLON); 6780 ExpectToken(Token::kCOLON);
6763 const bool saved_mode = SetAllowFunctionLiterals(true); 6781 const bool saved_mode = SetAllowFunctionLiterals(true);
6782 const intptr_t value_pos = token_index_;
6764 AstNode* value = ParseExpr(is_const); 6783 AstNode* value = ParseExpr(is_const);
6765 SetAllowFunctionLiterals(saved_mode); 6784 SetAllowFunctionLiterals(saved_mode);
6766 6785 if (FLAG_enable_type_checks &&
6786 !is_const &&
6787 !value_type.IsDynamicType()) {
6788 // The expression needs to be type checked at runtime.
6789 // Eliminate the type check if it can be performed at compile time and
6790 // if it succeeds.
6791 if (!value_type.IsInstantiated() ||
6792 !value->IsLiteralNode() ||
6793 !value->AsLiteralNode()->literal().
6794 IsAssignableTo(value_type, TypeArguments::Handle())) {
6795 value = new AssignableNode(value_pos,
6796 value,
6797 value_type,
6798 dst_name);
6799 }
6800 }
6767 AddKeyValuePair(kv_pairs, is_const, key, value); 6801 AddKeyValuePair(kv_pairs, is_const, key, value);
6768 6802
6769 if (CurrentToken() == Token::kCOMMA) { 6803 if (CurrentToken() == Token::kCOMMA) {
6770 ConsumeToken(); 6804 ConsumeToken();
6771 } else if (CurrentToken() != Token::kRBRACE) { 6805 } else if (CurrentToken() != Token::kRBRACE) {
6772 ErrorMsg("comma or '}' expected"); 6806 ErrorMsg("comma or '}' expected");
6773 } 6807 }
6774 } 6808 }
6775 ASSERT(kv_pairs->length() % 2 == 0); 6809 ASSERT(kv_pairs->length() % 2 == 0);
6776 ExpectToken(Token::kRBRACE); 6810 ExpectToken(Token::kRBRACE);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
6838 const Function& literal_map_factory = Function::ZoneHandle( 6872 const Function& literal_map_factory = Function::ZoneHandle(
6839 literal_factory_class.LookupFactory(literal_map_factory_name)); 6873 literal_factory_class.LookupFactory(literal_map_factory_name));
6840 ASSERT(!literal_map_factory.IsNull()); 6874 ASSERT(!literal_map_factory.IsNull());
6841 if (!map_type_arguments.IsNull() && 6875 if (!map_type_arguments.IsNull() &&
6842 !map_type_arguments.IsInstantiated() && 6876 !map_type_arguments.IsInstantiated() &&
6843 (current_block_->scope->function_level() > 0)) { 6877 (current_block_->scope->function_level() > 0)) {
6844 // Make sure that the instantiator is captured. 6878 // Make sure that the instantiator is captured.
6845 CaptureReceiver(); 6879 CaptureReceiver();
6846 } 6880 }
6847 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); 6881 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos);
6848 factory_param->Add(
6849 new LiteralNode(literal_pos, Smi::ZoneHandle(Smi::New(literal_pos))));
6850 factory_param->Add(
6851 new LiteralNode(literal_pos, String::ZoneHandle(value_type.Name())));
6852 factory_param->Add(kv_pairs); 6882 factory_param->Add(kv_pairs);
6853 return new ConstructorCallNode( 6883 return new ConstructorCallNode(
6854 literal_pos, map_type_arguments, literal_map_factory, factory_param); 6884 literal_pos, map_type_arguments, literal_map_factory, factory_param);
6855 } 6885 }
6856 } 6886 }
6857 6887
6858 6888
6859 AstNode* Parser::ParseCompoundLiteral() { 6889 AstNode* Parser::ParseCompoundLiteral() {
6860 bool is_const = false; 6890 bool is_const = false;
6861 if (CurrentToken() == Token::kCONST) { 6891 if (CurrentToken() == Token::kCONST) {
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after
7521 } 7551 }
7522 7552
7523 7553
7524 void Parser::SkipNestedExpr() { 7554 void Parser::SkipNestedExpr() {
7525 const bool saved_mode = SetAllowFunctionLiterals(true); 7555 const bool saved_mode = SetAllowFunctionLiterals(true);
7526 SkipExpr(); 7556 SkipExpr();
7527 SetAllowFunctionLiterals(saved_mode); 7557 SetAllowFunctionLiterals(saved_mode);
7528 } 7558 }
7529 7559
7530 } // namespace dart 7560 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698