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

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

Issue 14942010: Eliminate temporary locals for some expressions (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: cleaned up Created 7 years, 6 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 "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/class_finalizer.h" 9 #include "vm/class_finalizer.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 } 109 }
110 110
111 111
112 LocalVariable* ParsedFunction::CreateExpressionTempVar(intptr_t token_pos) { 112 LocalVariable* ParsedFunction::CreateExpressionTempVar(intptr_t token_pos) {
113 return new LocalVariable(token_pos, 113 return new LocalVariable(token_pos,
114 Symbols::ExprTemp(), 114 Symbols::ExprTemp(),
115 Type::ZoneHandle(Type::DynamicType())); 115 Type::ZoneHandle(Type::DynamicType()));
116 } 116 }
117 117
118 118
119 LocalVariable* ParsedFunction::CreateArrayLiteralVar(intptr_t token_pos) {
120 return new LocalVariable(token_pos,
121 Symbols::ArrayLiteralVar(),
122 Type::ZoneHandle(Type::ArrayType()));
123 }
124
125
126 void ParsedFunction::SetNodeSequence(SequenceNode* node_sequence) { 119 void ParsedFunction::SetNodeSequence(SequenceNode* node_sequence) {
127 ASSERT(node_sequence_ == NULL); 120 ASSERT(node_sequence_ == NULL);
128 ASSERT(node_sequence != NULL); 121 ASSERT(node_sequence != NULL);
129 node_sequence_ = node_sequence; 122 node_sequence_ = node_sequence;
130 } 123 }
131 124
132 125
133 LocalVariable* ParsedFunction::GetSavedArgumentsDescriptorVar() const { 126 LocalVariable* ParsedFunction::GetSavedArgumentsDescriptorVar() const {
134 const int num_parameters = function().NumParameters(); 127 const int num_parameters = function().NumParameters();
135 LocalScope* scope = node_sequence()->scope(); 128 LocalScope* scope = node_sequence()->scope();
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 case RawFunction::kConstImplicitGetter: 774 case RawFunction::kConstImplicitGetter:
782 node_sequence = parser.ParseStaticConstGetter(func); 775 node_sequence = parser.ParseStaticConstGetter(func);
783 break; 776 break;
784 case RawFunction::kMethodExtractor: 777 case RawFunction::kMethodExtractor:
785 node_sequence = parser.ParseMethodExtractor(func); 778 node_sequence = parser.ParseMethodExtractor(func);
786 break; 779 break;
787 default: 780 default:
788 UNREACHABLE(); 781 UNREACHABLE();
789 } 782 }
790 783
791 parsed_function->set_array_literal_var(
792 ParsedFunction::CreateArrayLiteralVar(func.token_pos()));
793 node_sequence->scope()->AddVariable(parsed_function->array_literal_var());
794
795 if (!HasReturnNode(node_sequence)) { 784 if (!HasReturnNode(node_sequence)) {
796 // Add implicit return node. 785 // Add implicit return node.
797 node_sequence->Add(new ReturnNode(func.end_token_pos())); 786 node_sequence->Add(new ReturnNode(func.end_token_pos()));
798 } 787 }
799 if (parsed_function->has_expression_temp_var()) { 788 if (parsed_function->has_expression_temp_var()) {
800 node_sequence->scope()->AddVariable(parsed_function->expression_temp_var()); 789 node_sequence->scope()->AddVariable(parsed_function->expression_temp_var());
801 } 790 }
802 if (parsed_function->has_saved_current_context_var()) { 791 if (parsed_function->has_saved_current_context_var()) {
803 node_sequence->scope()->AddVariable( 792 node_sequence->scope()->AddVariable(
804 parsed_function->saved_current_context_var()); 793 parsed_function->saved_current_context_var());
(...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 } 1391 }
1403 1392
1404 1393
1405 static const String& PrivateCoreLibName(const String& str) { 1394 static const String& PrivateCoreLibName(const String& str) {
1406 const Library& core_lib = Library::Handle(Library::CoreLibrary()); 1395 const Library& core_lib = Library::Handle(Library::CoreLibrary());
1407 const String& private_name = String::ZoneHandle(core_lib.PrivateName(str)); 1396 const String& private_name = String::ZoneHandle(core_lib.PrivateName(str));
1408 return private_name; 1397 return private_name;
1409 } 1398 }
1410 1399
1411 1400
1412 LocalVariable* Parser::BuildArrayTempLocal(intptr_t token_pos) {
1413 char name[64];
1414 OS::SNPrint(name, 64, ":arrlit%"Pd, token_pos);
1415 LocalVariable* temp =
1416 new LocalVariable(token_pos,
1417 String::ZoneHandle(Symbols::New(name)),
1418 Type::ZoneHandle(Type::ArrayType()));
1419 current_block_->scope->AddVariable(temp);
1420 return temp;
1421 }
1422
1423
1424 StaticCallNode* Parser::BuildInvocationMirrorAllocation( 1401 StaticCallNode* Parser::BuildInvocationMirrorAllocation(
1425 intptr_t call_pos, 1402 intptr_t call_pos,
1426 const String& function_name, 1403 const String& function_name,
1427 const ArgumentListNode& function_args) { 1404 const ArgumentListNode& function_args) {
1428 const intptr_t args_pos = function_args.token_pos(); 1405 const intptr_t args_pos = function_args.token_pos();
1429 // Build arguments to the call to the static 1406 // Build arguments to the call to the static
1430 // InvocationMirror._allocateInvocationMirror method. 1407 // InvocationMirror._allocateInvocationMirror method.
1431 ArgumentListNode* arguments = new ArgumentListNode(args_pos); 1408 ArgumentListNode* arguments = new ArgumentListNode(args_pos);
1432 // The first argument is the original function name. 1409 // The first argument is the original function name.
1433 arguments->Add(new LiteralNode(args_pos, function_name)); 1410 arguments->Add(new LiteralNode(args_pos, function_name));
1434 // The second argument is the arguments descriptor of the original function. 1411 // The second argument is the arguments descriptor of the original function.
1435 const Array& args_descriptor = 1412 const Array& args_descriptor =
1436 Array::ZoneHandle(ArgumentsDescriptor::New(function_args.length(), 1413 Array::ZoneHandle(ArgumentsDescriptor::New(function_args.length(),
1437 function_args.names())); 1414 function_args.names()));
1438 arguments->Add(new LiteralNode(args_pos, args_descriptor)); 1415 arguments->Add(new LiteralNode(args_pos, args_descriptor));
1439 // The third argument is an array containing the original function arguments, 1416 // The third argument is an array containing the original function arguments,
1440 // including the receiver. 1417 // including the receiver.
1441 ArrayNode* args_array = new ArrayNode( 1418 ArrayNode* args_array =
1442 args_pos, Type::ZoneHandle(Type::ArrayType()), 1419 new ArrayNode(args_pos, Type::ZoneHandle(Type::ArrayType()));
1443 *BuildArrayTempLocal(call_pos));
1444 for (intptr_t i = 0; i < function_args.length(); i++) { 1420 for (intptr_t i = 0; i < function_args.length(); i++) {
1445 args_array->AddElement(function_args.NodeAt(i)); 1421 args_array->AddElement(function_args.NodeAt(i));
1446 } 1422 }
1447 arguments->Add(args_array); 1423 arguments->Add(args_array);
1448 // Lookup the static InvocationMirror._allocateInvocationMirror method. 1424 // Lookup the static InvocationMirror._allocateInvocationMirror method.
1449 const Class& mirror_class = 1425 const Class& mirror_class =
1450 Class::Handle(LookupCoreClass(Symbols::InvocationMirror())); 1426 Class::Handle(LookupCoreClass(Symbols::InvocationMirror()));
1451 ASSERT(!mirror_class.IsNull()); 1427 ASSERT(!mirror_class.IsNull());
1452 const Function& allocation_function = Function::ZoneHandle( 1428 const Function& allocation_function = Function::ZoneHandle(
1453 mirror_class.LookupStaticFunction( 1429 mirror_class.LookupStaticFunction(
(...skipping 6298 matching lines...) Expand 10 before | Expand all | Expand 10 after
7752 return left; 7728 return left;
7753 } 7729 }
7754 ASSERT(selector != NULL); 7730 ASSERT(selector != NULL);
7755 left = selector; 7731 left = selector;
7756 } 7732 }
7757 } 7733 }
7758 7734
7759 7735
7760 AstNode* Parser::ParsePostfixExpr() { 7736 AstNode* Parser::ParsePostfixExpr() {
7761 TRACE_PARSER("ParsePostfixExpr"); 7737 TRACE_PARSER("ParsePostfixExpr");
7762 const intptr_t postfix_expr_pos = TokenPos(); 7738 const intptr_t token_pos = TokenPos();
hausner 2013/05/28 17:00:47 Why are you renaming this? The old name expresses
Florian Schneider 2013/05/30 09:29:31 I found it too long so that it caused some ugly li
7763 AstNode* postfix_expr = ParsePrimary(); 7739 AstNode* postfix_expr = ParsePrimary();
7764 postfix_expr = ParseSelectors(postfix_expr, false); 7740 postfix_expr = ParseSelectors(postfix_expr, false);
7765 if (IsIncrementOperator(CurrentToken())) { 7741 if (IsIncrementOperator(CurrentToken())) {
7766 TRACE_PARSER("IncrementOperator"); 7742 TRACE_PARSER("IncrementOperator");
7767 Token::Kind incr_op = CurrentToken(); 7743 Token::Kind incr_op = CurrentToken();
7768 if (!IsAssignableExpr(postfix_expr)) { 7744 if (!IsAssignableExpr(postfix_expr)) {
7769 ErrorMsg("expression is not assignable"); 7745 ErrorMsg("expression is not assignable");
7770 } 7746 }
7771 ConsumeToken(); 7747 ConsumeToken();
7772 // Not prefix. 7748 // Not prefix.
7749 if (postfix_expr->IsInstanceGetterNode()) {
hausner 2013/05/28 17:00:47 I think this special case needs to be handled in P
Florian Schneider 2013/05/30 09:29:31 Yes, I'll handle this and the other cases in Prepa
7750 InstanceGetterNode* getter = postfix_expr->AsInstanceGetterNode();
7751 Token::Kind binary_op =
7752 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB;
7753 if (!IsSimpleLocalOrLiteralNode(getter->receiver())) {
7754 LetNode* result = new LetNode(token_pos, 2);
7755 result->SetTempExpression(0, getter->receiver());
7756 result->SetTempExpression(
7757 1,
7758 new InstanceGetterNode(
7759 token_pos,
7760 new LoadLocalNode(token_pos, result->temp(0)),
7761 getter->field_name()));
7762 BinaryOpNode* add = new BinaryOpNode(
7763 token_pos,
7764 binary_op,
7765 new LoadLocalNode(token_pos, result->temp(1)),
7766 new LiteralNode(token_pos, Smi::ZoneHandle(Smi::New(1))));
7767 InstanceSetterNode* store = new InstanceSetterNode(
7768 token_pos,
7769 new LoadLocalNode(token_pos, result->temp(0)),
7770 getter->field_name(),
7771 add);
7772 CommaNode* body = new CommaNode(
7773 token_pos,
7774 store,
7775 new LoadLocalNode(token_pos, result->temp(1))); // Result value.
7776 result->set_body(body);
7777 return result;
7778 } else {
7779 LetNode* result = new LetNode(token_pos, 1);
7780 result->SetTempExpression(
7781 0,
7782 new InstanceGetterNode(
7783 token_pos,
7784 getter->receiver(),
7785 getter->field_name()));
7786 BinaryOpNode* add = new BinaryOpNode(
7787 token_pos,
7788 binary_op,
7789 new LoadLocalNode(token_pos, result->temp(0)),
7790 new LiteralNode(token_pos, Smi::ZoneHandle(Smi::New(1))));
7791 InstanceSetterNode* store = new InstanceSetterNode(
7792 token_pos,
7793 getter->receiver(),
7794 getter->field_name(),
7795 add);
7796 CommaNode* body = new CommaNode(
7797 token_pos,
7798 store,
7799 new LoadLocalNode(token_pos, result->temp(0))); // Result value.
7800 result->set_body(body);
7801 return result;
7802 }
7803 }
7773 AstNode* left_expr = PrepareCompoundAssignmentNodes(&postfix_expr); 7804 AstNode* left_expr = PrepareCompoundAssignmentNodes(&postfix_expr);
7774 const LocalVariable* temp = GetIncrementTempLocal(); 7805 const LocalVariable* temp = GetIncrementTempLocal();
hausner 2013/05/28 17:00:47 Can this temporary local variable be handled with
Florian Schneider 2013/05/30 09:29:31 Yes, definitely. The plan is to replace it here as
7775 AstNode* save = 7806 AstNode* save =
7776 new StoreLocalNode(postfix_expr_pos, temp, postfix_expr); 7807 new StoreLocalNode(token_pos, temp, postfix_expr);
7777 Token::Kind binary_op = 7808 Token::Kind binary_op =
7778 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB; 7809 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB;
7779 BinaryOpNode* add = new BinaryOpNode( 7810 BinaryOpNode* add = new BinaryOpNode(
7780 postfix_expr_pos, 7811 token_pos,
7781 binary_op, 7812 binary_op,
7782 save, 7813 save,
7783 new LiteralNode(postfix_expr_pos, Smi::ZoneHandle(Smi::New(1)))); 7814 new LiteralNode(token_pos, Smi::ZoneHandle(Smi::New(1))));
7784 AstNode* store = CreateAssignmentNode(left_expr, add); 7815 AstNode* store = CreateAssignmentNode(left_expr, add);
7785 // The result is a pair of the (side effects of the) store followed by 7816 // The result is a pair of the (side effects of the) store followed by
7786 // the (value of the) initial value temp variable load. 7817 // the (value of the) initial value temp variable load.
7787 return new CommaNode( 7818 return new CommaNode(
7788 postfix_expr_pos, 7819 token_pos,
7789 store, 7820 store,
7790 new LoadLocalNode(postfix_expr_pos, temp)); 7821 new LoadLocalNode(token_pos, temp));
7791 } 7822 }
7792 return postfix_expr; 7823 return postfix_expr;
7793 } 7824 }
7794 7825
7795 7826
7796 // Resolve the given type and its type arguments from the given scope class 7827 // Resolve the given type and its type arguments from the given scope class
7797 // according to the given type finalization mode. 7828 // according to the given type finalization mode.
7798 // If the given scope class is null, use the current library, but do not try to 7829 // If the given scope class is null, use the current library, but do not try to
7799 // resolve type parameters. 7830 // resolve type parameters.
7800 // Not all involved type classes may get resolved yet, but at least the type 7831 // Not all involved type classes may get resolved yet, but at least the type
(...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after
8855 } 8886 }
8856 factory_type_args = factory_type_args.Canonicalize(); 8887 factory_type_args = factory_type_args.Canonicalize();
8857 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); 8888 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos);
8858 if (element_list.length() == 0) { 8889 if (element_list.length() == 0) {
8859 // TODO(srdjan): Use Object::empty_array once issue 9871 has been fixed. 8890 // TODO(srdjan): Use Object::empty_array once issue 9871 has been fixed.
8860 Array& empty_array = Array::ZoneHandle(Object::empty_array().raw()); 8891 Array& empty_array = Array::ZoneHandle(Object::empty_array().raw());
8861 LiteralNode* empty_array_literal = 8892 LiteralNode* empty_array_literal =
8862 new LiteralNode(TokenPos(), empty_array); 8893 new LiteralNode(TokenPos(), empty_array);
8863 factory_param->Add(empty_array_literal); 8894 factory_param->Add(empty_array_literal);
8864 } else { 8895 } else {
8865 const LocalVariable& temp_local = *BuildArrayTempLocal(type_pos); 8896 ArrayNode* list = new ArrayNode(TokenPos(), type, element_list);
8866 ArrayNode* list =
8867 new ArrayNode(TokenPos(), type, temp_local, element_list);
8868 factory_param->Add(list); 8897 factory_param->Add(list);
8869 } 8898 }
8870 return CreateConstructorCallNode(literal_pos, 8899 return CreateConstructorCallNode(literal_pos,
8871 factory_type_args, 8900 factory_type_args,
8872 factory_method, 8901 factory_method,
8873 factory_param); 8902 factory_param);
8874 } 8903 }
8875 } 8904 }
8876 8905
8877 8906
8878 ConstructorCallNode* Parser::CreateConstructorCallNode( 8907 ConstructorCallNode* Parser::CreateConstructorCallNode(
8879 intptr_t token_pos, 8908 intptr_t token_pos,
8880 const AbstractTypeArguments& type_arguments, 8909 const AbstractTypeArguments& type_arguments,
8881 const Function& constructor, 8910 const Function& constructor,
8882 ArgumentListNode* arguments) { 8911 ArgumentListNode* arguments) {
8883 if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) { 8912 if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) {
8884 EnsureExpressionTemp(); 8913 EnsureExpressionTemp();
8885 } 8914 }
8886 LocalVariable* allocated =
8887 CreateTempConstVariable(token_pos, "alloc");
8888 return new ConstructorCallNode(token_pos, 8915 return new ConstructorCallNode(token_pos,
8889 type_arguments, 8916 type_arguments,
8890 constructor, 8917 constructor,
8891 arguments, 8918 arguments);
8892 allocated);
8893 } 8919 }
8894 8920
8895 8921
8896 static void AddKeyValuePair(GrowableArray<AstNode*>* pairs, 8922 static void AddKeyValuePair(GrowableArray<AstNode*>* pairs,
8897 bool is_const, 8923 bool is_const,
8898 AstNode* key, 8924 AstNode* key,
8899 AstNode* value) { 8925 AstNode* value) {
8900 if (is_const) { 8926 if (is_const) {
8901 ASSERT(key->IsLiteralNode()); 8927 ASSERT(key->IsLiteralNode());
8902 ASSERT(key->AsLiteralNode()->literal().IsString()); 8928 ASSERT(key->AsLiteralNode()->literal().IsString());
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
9080 factory_type_args = factory_type.arguments(); 9106 factory_type_args = factory_type.arguments();
9081 ASSERT(factory_type_args.Length() == factory_class.NumTypeArguments()); 9107 ASSERT(factory_type_args.Length() == factory_class.NumTypeArguments());
9082 } 9108 }
9083 factory_type_args = factory_type_args.Canonicalize(); 9109 factory_type_args = factory_type_args.Canonicalize();
9084 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos); 9110 ArgumentListNode* factory_param = new ArgumentListNode(literal_pos);
9085 // The kv_pair array is temporary and of element type dynamic. It is passed 9111 // The kv_pair array is temporary and of element type dynamic. It is passed
9086 // to the factory to initialize a properly typed map. 9112 // to the factory to initialize a properly typed map.
9087 ArrayNode* kv_pairs = new ArrayNode( 9113 ArrayNode* kv_pairs = new ArrayNode(
9088 TokenPos(), 9114 TokenPos(),
9089 Type::ZoneHandle(Type::ArrayType()), 9115 Type::ZoneHandle(Type::ArrayType()),
9090 *BuildArrayTempLocal(type_pos),
9091 kv_pairs_list); 9116 kv_pairs_list);
9092 factory_param->Add(kv_pairs); 9117 factory_param->Add(kv_pairs);
9093 return CreateConstructorCallNode(literal_pos, 9118 return CreateConstructorCallNode(literal_pos,
9094 factory_type_args, 9119 factory_type_args,
9095 factory_method, 9120 factory_method,
9096 factory_param); 9121 factory_param);
9097 } 9122 }
9098 } 9123 }
9099 9124
9100 9125
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
9467 values_list.Add(expr); 9492 values_list.Add(expr);
9468 } 9493 }
9469 } 9494 }
9470 if (is_compiletime_const) { 9495 if (is_compiletime_const) {
9471 primary = new LiteralNode(literal_start, Interpolate(values_list)); 9496 primary = new LiteralNode(literal_start, Interpolate(values_list));
9472 } else { 9497 } else {
9473 ArgumentListNode* interpolate_arg = new ArgumentListNode(TokenPos()); 9498 ArgumentListNode* interpolate_arg = new ArgumentListNode(TokenPos());
9474 ArrayNode* values = new ArrayNode( 9499 ArrayNode* values = new ArrayNode(
9475 TokenPos(), 9500 TokenPos(),
9476 Type::ZoneHandle(Type::ArrayType()), 9501 Type::ZoneHandle(Type::ArrayType()),
9477 *BuildArrayTempLocal(TokenPos()),
9478 values_list); 9502 values_list);
9479 interpolate_arg->Add(values); 9503 interpolate_arg->Add(values);
9480 primary = MakeStaticCall(Symbols::StringBase(), 9504 primary = MakeStaticCall(Symbols::StringBase(),
9481 PrivateCoreLibName(Symbols::Interpolate()), 9505 PrivateCoreLibName(Symbols::Interpolate()),
9482 interpolate_arg); 9506 interpolate_arg);
9483 } 9507 }
9484 return primary; 9508 return primary;
9485 } 9509 }
9486 9510
9487 9511
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
9988 void Parser::SkipQualIdent() { 10012 void Parser::SkipQualIdent() {
9989 ASSERT(IsIdentifier()); 10013 ASSERT(IsIdentifier());
9990 ConsumeToken(); 10014 ConsumeToken();
9991 if (CurrentToken() == Token::kPERIOD) { 10015 if (CurrentToken() == Token::kPERIOD) {
9992 ConsumeToken(); // Consume the kPERIOD token. 10016 ConsumeToken(); // Consume the kPERIOD token.
9993 ExpectIdentifier("identifier expected after '.'"); 10017 ExpectIdentifier("identifier expected after '.'");
9994 } 10018 }
9995 } 10019 }
9996 10020
9997 } // namespace dart 10021 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698