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

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

Issue 10272031: Merge two functions that create sideffect free compound load nodes. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 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
« no previous file with comments | « runtime/vm/parser.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) 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 5884 matching lines...) Expand 10 before | Expand all | Expand 10 after
5895 LocalVariable* temp = 5895 LocalVariable* temp =
5896 new LocalVariable(token_index, 5896 new LocalVariable(token_index,
5897 String::ZoneHandle(String::NewSymbol(name)), 5897 String::ZoneHandle(String::NewSymbol(name)),
5898 Type::ZoneHandle(Type::DynamicType())); 5898 Type::ZoneHandle(Type::DynamicType()));
5899 temp->set_is_final(); 5899 temp->set_is_final();
5900 current_block_->scope->AddVariable(temp); 5900 current_block_->scope->AddVariable(temp);
5901 return temp; 5901 return temp;
5902 } 5902 }
5903 5903
5904 5904
5905 // If 'node' can create side effects, store its result in a temporary variable
5906 // and return a LoadLocalNode instead.
5907 // Side effect free nodes are LoadLocalNode and LiteralNode.
5908 AstNode* Parser::AsSideEffectFreeNode(AstNode* node) {
5909 if (node->IsLoadIndexedNode()) {
5910 LoadIndexedNode* load_indexed = node->AsLoadIndexedNode();
5911 intptr_t token_id = node->id();
5912 intptr_t token_index = node->token_index();
5913 node = NULL; // Do not use it.
5914 // The array object access may not have side effects.
5915 // First, evaluate the array object expression if it might have side
5916 // effects.
5917 if (!IsLocalOrLiteralNode(load_indexed->array())) {
5918 LocalVariable* temp =
5919 CreateTempConstVariable(token_index, token_id, "lia");
5920 AstNode* save =
5921 new StoreLocalNode(token_index, *temp, load_indexed->array());
5922 load_indexed = new LoadIndexedNode(token_index,
5923 save,
5924 load_indexed->index_expr());
5925 }
5926 // Second, evaluate the index expression and store in a temporary
5927 // variable if it might have side effects.
5928 if (!IsLocalOrLiteralNode(load_indexed->index_expr())) {
5929 LocalVariable* temp =
5930 CreateTempConstVariable(token_index, token_id, "lix");
5931 AstNode* save =
5932 new StoreLocalNode(token_index, *temp, load_indexed->index_expr());
5933 load_indexed = new LoadIndexedNode(token_index,
5934 load_indexed->array(),
5935 save);
5936 }
5937 return load_indexed;
5938 }
5939 if (node->IsInstanceGetterNode()) {
5940 InstanceGetterNode* getter = node->AsInstanceGetterNode();
5941 intptr_t token_index = node->token_index();
5942 intptr_t token_id = node->id();
5943 node = NULL; // Do not use it.
5944 if (!IsLocalOrLiteralNode(getter->receiver())) {
5945 LocalVariable* temp =
5946 CreateTempConstVariable(token_index, token_id, "igr");
5947 AstNode* save =
5948 new StoreLocalNode(token_index, *temp, getter->receiver());
5949 getter = new InstanceGetterNode(token_index, save, getter->field_name());
5950 }
5951 return getter;
5952 }
5953 return node;
5954 }
5955
5956
5957 // TODO(srdjan): Implement other optimizations. 5905 // TODO(srdjan): Implement other optimizations.
5958 AstNode* Parser::OptimizeBinaryOpNode(intptr_t op_pos, 5906 AstNode* Parser::OptimizeBinaryOpNode(intptr_t op_pos,
5959 Token::Kind binary_op, 5907 Token::Kind binary_op,
5960 AstNode* lhs, 5908 AstNode* lhs,
5961 AstNode* rhs) { 5909 AstNode* rhs) {
5962 LiteralNode* lhs_literal = lhs->AsLiteralNode(); 5910 LiteralNode* lhs_literal = lhs->AsLiteralNode();
5963 LiteralNode* rhs_literal = rhs->AsLiteralNode(); 5911 LiteralNode* rhs_literal = rhs->AsLiteralNode();
5964 if ((lhs_literal != NULL) && (rhs_literal != NULL)) { 5912 if ((lhs_literal != NULL) && (rhs_literal != NULL)) {
5965 if (lhs_literal->literal().IsDouble() && 5913 if (lhs_literal->literal().IsDouble() &&
5966 rhs_literal->literal().IsDouble()) { 5914 rhs_literal->literal().IsDouble()) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
6026 } 5974 }
6027 if (expr->EvalConstExpr() == NULL) { 5975 if (expr->EvalConstExpr() == NULL) {
6028 ErrorMsg(expr_pos, "expression must be a compile time constant"); 5976 ErrorMsg(expr_pos, "expression must be a compile time constant");
6029 } 5977 }
6030 return new LiteralNode(expr_pos, EvaluateConstExpr(expr)); 5978 return new LiteralNode(expr_pos, EvaluateConstExpr(expr));
6031 } 5979 }
6032 5980
6033 5981
6034 // A compound assignment consists of a store and a load part. In order 5982 // A compound assignment consists of a store and a load part. In order
6035 // to control inputs with potential side effects, the store part stores any 5983 // to control inputs with potential side effects, the store part stores any
6036 // side effect creating inputs into locals. 5984 // side effect creating inputs into locals. The load part reads then from
6037 // Here we convert the inputs if the load local from the StoreLocals to 5985 // those locals. If expr may have side effects, it will be split into two new
6038 // LoadLocals. 5986 // left and right nodes. 'expr' becomes the right node, left node is returned as
6039 static AstNode* ModifyCompoundAssignmentLoad(AstNode* node) { 5987 // result.
5988 AstNode* Parser::PrepareCompoundAssignmentNodes(AstNode** expr) {
5989 AstNode* node = *expr;
6040 if (node->IsLoadIndexedNode()) { 5990 if (node->IsLoadIndexedNode()) {
6041 LoadIndexedNode* load_indexed = node->AsLoadIndexedNode(); 5991 LoadIndexedNode* left_node = node->AsLoadIndexedNode();
6042 if (load_indexed->array()->IsStoreLocalNode()) { 5992 LoadIndexedNode* right_node = left_node;
6043 StoreLocalNode* store = load_indexed->array()->AsStoreLocalNode(); 5993 intptr_t node_id = node->id();
6044 LoadLocalNode* load = new LoadLocalNode(store->token_index(), 5994 intptr_t token_index = node->token_index();
6045 store->local()); 5995 node = NULL; // Do not use it.
6046 load_indexed = new LoadIndexedNode(load_indexed->token_index(), 5996 if (!IsLocalOrLiteralNode(left_node->array())) {
6047 load, 5997 LocalVariable* temp =
6048 load_indexed->index_expr()); 5998 CreateTempConstVariable(token_index, node_id, "lia");
5999 StoreLocalNode* save =
6000 new StoreLocalNode(token_index, *temp, left_node->array());
6001 left_node =
6002 new LoadIndexedNode(token_index, save, left_node->index_expr());
6003 right_node = new LoadIndexedNode(token_index,
6004 new LoadLocalNode(token_index, *temp),
6005 right_node->index_expr());
6049 } 6006 }
6050 if (load_indexed->index_expr()->IsStoreLocalNode()) { 6007 if (!IsLocalOrLiteralNode(left_node->index_expr())) {
6051 StoreLocalNode* store = load_indexed->index_expr()->AsStoreLocalNode(); 6008 LocalVariable* temp =
6052 LoadLocalNode* load = new LoadLocalNode(store->token_index(), 6009 CreateTempConstVariable(token_index, node_id, "lix");
6053 store->local()); 6010 StoreLocalNode* save =
6054 load_indexed = new LoadIndexedNode(load_indexed->token_index(), 6011 new StoreLocalNode(token_index, *temp, left_node->index_expr());
6055 load_indexed->array(), 6012 left_node = new LoadIndexedNode(token_index,
6056 load); 6013 left_node->array(),
6014 save);
6015 right_node = new LoadIndexedNode(token_index,
6016 right_node->array(),
6017 new LoadLocalNode(token_index, *temp));
6057 } 6018 }
6058 return load_indexed; 6019 *expr = right_node;
6020 return left_node;
6059 } 6021 }
6060 if (node->IsInstanceGetterNode()) { 6022 if (node->IsInstanceGetterNode()) {
6061 InstanceGetterNode* getter = node->AsInstanceGetterNode(); 6023 InstanceGetterNode* left_node = node->AsInstanceGetterNode();
6062 if (getter->receiver()->IsStoreLocalNode()) { 6024 InstanceGetterNode* right_node = left_node;
6063 StoreLocalNode* store = getter->receiver()->AsStoreLocalNode(); 6025 intptr_t node_id = node->id();
6064 LoadLocalNode* load = new LoadLocalNode(store->token_index(), 6026 intptr_t token_index = node->token_index();
6065 store->local()); 6027 node = NULL; // Do not use it.
6066 getter = new InstanceGetterNode(getter->token_index(), 6028 if (!IsLocalOrLiteralNode(left_node->receiver())) {
6067 load, 6029 LocalVariable* temp =
6068 getter->field_name()); 6030 CreateTempConstVariable(token_index, node_id, "igr");
6031 StoreLocalNode* save =
6032 new StoreLocalNode(token_index, *temp, left_node->receiver());
6033 left_node = new InstanceGetterNode(token_index,
6034 save,
6035 left_node->field_name());
6036 right_node = new InstanceGetterNode(token_index,
6037 new LoadLocalNode(token_index, *temp),
6038 right_node->field_name());
6069 } 6039 }
6070 return getter; 6040 *expr = right_node;
6041 return left_node;
6071 } 6042 }
6072 return node; 6043 return *expr;
6073 } 6044 }
6074 6045
6075 6046
6076 AstNode* Parser::ParseExpr(bool require_compiletime_const) { 6047 AstNode* Parser::ParseExpr(bool require_compiletime_const) {
6077 TRACE_PARSER("ParseExpr"); 6048 TRACE_PARSER("ParseExpr");
6078 const intptr_t expr_pos = token_index_; 6049 const intptr_t expr_pos = token_index_;
6079 AstNode* expr = ParseConditionalExpr(); 6050 AstNode* expr = ParseConditionalExpr();
6080 if (!Token::IsAssignmentOperator(CurrentToken())) { 6051 if (!Token::IsAssignmentOperator(CurrentToken())) {
6081 if (require_compiletime_const) { 6052 if (require_compiletime_const) {
6082 expr = FoldConstExpr(expr_pos, expr); 6053 expr = FoldConstExpr(expr_pos, expr);
6083 } 6054 }
6084 return expr; 6055 return expr;
6085 } 6056 }
6086 // Assignment expressions. 6057 // Assignment expressions.
6087 Token::Kind assignment_op = CurrentToken(); 6058 Token::Kind assignment_op = CurrentToken();
6088 const intptr_t assignment_pos = token_index_; 6059 const intptr_t assignment_pos = token_index_;
6089 ConsumeToken(); 6060 ConsumeToken();
6090 const intptr_t right_expr_pos = token_index_; 6061 const intptr_t right_expr_pos = token_index_;
6091 if (require_compiletime_const && (assignment_op != Token::kASSIGN)) { 6062 if (require_compiletime_const && (assignment_op != Token::kASSIGN)) {
6092 ErrorMsg(right_expr_pos, "expression must be a compile time constant"); 6063 ErrorMsg(right_expr_pos, "expression must be a compile time constant");
6093 } 6064 }
6094 AstNode* right_expr = ParseExpr(require_compiletime_const); 6065 AstNode* right_expr = ParseExpr(require_compiletime_const);
6095 AstNode* left_expr = expr; 6066 AstNode* left_expr = expr;
6096 if (assignment_op != Token::kASSIGN) { 6067 if (assignment_op != Token::kASSIGN) {
6097 // Compound assignment: store inputs with side effects into temp. locals. 6068 // Compound assignment: store inputs with side effects into temp. locals.
6098 left_expr = AsSideEffectFreeNode(expr); 6069 left_expr = PrepareCompoundAssignmentNodes(&expr);
6099 expr = ModifyCompoundAssignmentLoad(left_expr);
6100 } 6070 }
6101 right_expr = 6071 right_expr =
6102 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr); 6072 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
6103 AstNode* assign_expr = left_expr->MakeAssignmentNode(right_expr); 6073 AstNode* assign_expr = left_expr->MakeAssignmentNode(right_expr);
6104 if (assign_expr == NULL) { 6074 if (assign_expr == NULL) {
6105 ErrorMsg(assignment_pos, 6075 ErrorMsg(assignment_pos,
6106 "left hand side of '%s' is not assignable", 6076 "left hand side of '%s' is not assignable",
6107 Token::Str(assignment_op)); 6077 Token::Str(assignment_op));
6108 } 6078 }
6109 return assign_expr; 6079 return assign_expr;
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
6326 const intptr_t call_pos = token_index_; 6296 const intptr_t call_pos = token_index_;
6327 if (Token::IsAssignmentOperator(CurrentToken())) { 6297 if (Token::IsAssignmentOperator(CurrentToken())) {
6328 Token::Kind assignment_op = CurrentToken(); 6298 Token::Kind assignment_op = CurrentToken();
6329 ConsumeToken(); 6299 ConsumeToken();
6330 AstNode* value = ParseExpr(kAllowConst); 6300 AstNode* value = ParseExpr(kAllowConst);
6331 AstNode* load_access = 6301 AstNode* load_access =
6332 new InstanceGetterNode(call_pos, receiver, field_name); 6302 new InstanceGetterNode(call_pos, receiver, field_name);
6333 AstNode* left_load_access = load_access; 6303 AstNode* left_load_access = load_access;
6334 if (assignment_op != Token::kASSIGN) { 6304 if (assignment_op != Token::kASSIGN) {
6335 // Compound assignment: store inputs with side effects into temp. locals. 6305 // Compound assignment: store inputs with side effects into temp. locals.
6336 left_load_access = AsSideEffectFreeNode(load_access); 6306 left_load_access = PrepareCompoundAssignmentNodes(&load_access);
6337 load_access = ModifyCompoundAssignmentLoad(left_load_access);
6338 } 6307 }
6339 value = ExpandAssignableOp(call_pos, assignment_op, load_access, value); 6308 value = ExpandAssignableOp(call_pos, assignment_op, load_access, value);
6340 access = left_load_access->MakeAssignmentNode(value); 6309 access = left_load_access->MakeAssignmentNode(value);
6341 } else { 6310 } else {
6342 access = CallGetter(call_pos, receiver, field_name); 6311 access = CallGetter(call_pos, receiver, field_name);
6343 } 6312 }
6344 return access; 6313 return access;
6345 } 6314 }
6346 6315
6347 6316
(...skipping 2107 matching lines...) Expand 10 before | Expand all | Expand 10 after
8455 void Parser::SkipQualIdent() { 8424 void Parser::SkipQualIdent() {
8456 ASSERT(IsIdentifier()); 8425 ASSERT(IsIdentifier());
8457 ConsumeToken(); 8426 ConsumeToken();
8458 if (CurrentToken() == Token::kPERIOD) { 8427 if (CurrentToken() == Token::kPERIOD) {
8459 ConsumeToken(); // Consume the kPERIOD token. 8428 ConsumeToken(); // Consume the kPERIOD token.
8460 ExpectIdentifier("identifier expected after '.'"); 8429 ExpectIdentifier("identifier expected after '.'");
8461 } 8430 }
8462 } 8431 }
8463 8432
8464 } // namespace dart 8433 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698