Chromium Code Reviews| 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 5901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5912 intptr_t token_index = node->token_index(); | 5912 intptr_t token_index = node->token_index(); |
| 5913 node = NULL; // Do not use it. | 5913 node = NULL; // Do not use it. |
| 5914 // The array object access may not have side effects. | 5914 // The array object access may not have side effects. |
| 5915 // First, evaluate the array object expression if it might have side | 5915 // First, evaluate the array object expression if it might have side |
| 5916 // effects. | 5916 // effects. |
| 5917 if (!IsLocalOrLiteralNode(load_indexed->array())) { | 5917 if (!IsLocalOrLiteralNode(load_indexed->array())) { |
| 5918 LocalVariable* temp = | 5918 LocalVariable* temp = |
| 5919 CreateTempConstVariable(token_index, token_id, "lia"); | 5919 CreateTempConstVariable(token_index, token_id, "lia"); |
| 5920 AstNode* save = | 5920 AstNode* save = |
| 5921 new StoreLocalNode(token_index, *temp, load_indexed->array()); | 5921 new StoreLocalNode(token_index, *temp, load_indexed->array()); |
| 5922 current_block_->statements->Add(save); | |
| 5923 AstNode* load = new LoadLocalNode(token_index, *temp); | |
| 5924 load_indexed = new LoadIndexedNode(token_index, | 5922 load_indexed = new LoadIndexedNode(token_index, |
| 5925 load, | 5923 save, |
| 5926 load_indexed->index_expr()); | 5924 load_indexed->index_expr()); |
| 5927 } | 5925 } |
| 5928 // Second, evaluate the index expression and store in a temporary | 5926 // Second, evaluate the index expression and store in a temporary |
| 5929 // variable if it might have side effects. | 5927 // variable if it might have side effects. |
| 5930 if (!IsLocalOrLiteralNode(load_indexed->index_expr())) { | 5928 if (!IsLocalOrLiteralNode(load_indexed->index_expr())) { |
| 5931 LocalVariable* temp = | 5929 LocalVariable* temp = |
| 5932 CreateTempConstVariable(token_index, token_id, "lix"); | 5930 CreateTempConstVariable(token_index, token_id, "lix"); |
| 5933 AstNode* save = | 5931 AstNode* save = |
| 5934 new StoreLocalNode(token_index, *temp, load_indexed->index_expr()); | 5932 new StoreLocalNode(token_index, *temp, load_indexed->index_expr()); |
| 5935 current_block_->statements->Add(save); | |
| 5936 AstNode* load = new LoadLocalNode(token_index, *temp); | |
| 5937 load_indexed = new LoadIndexedNode(token_index, | 5933 load_indexed = new LoadIndexedNode(token_index, |
| 5938 load_indexed->array(), | 5934 load_indexed->array(), |
| 5939 load); | 5935 save); |
| 5940 } | 5936 } |
| 5941 return load_indexed; | 5937 return load_indexed; |
| 5942 } | 5938 } |
| 5943 if (node->IsInstanceGetterNode()) { | 5939 if (node->IsInstanceGetterNode()) { |
| 5944 InstanceGetterNode* getter = node->AsInstanceGetterNode(); | 5940 InstanceGetterNode* getter = node->AsInstanceGetterNode(); |
| 5945 intptr_t token_index = node->token_index(); | 5941 intptr_t token_index = node->token_index(); |
| 5946 intptr_t token_id = node->id(); | 5942 intptr_t token_id = node->id(); |
| 5947 node = NULL; // Do not use it. | 5943 node = NULL; // Do not use it. |
| 5948 if (!IsLocalOrLiteralNode(getter->receiver())) { | 5944 if (!IsLocalOrLiteralNode(getter->receiver())) { |
| 5949 LocalVariable* temp = | 5945 LocalVariable* temp = |
| 5950 CreateTempConstVariable(token_index, token_id, "igr"); | 5946 CreateTempConstVariable(token_index, token_id, "igr"); |
| 5951 AstNode* save = | 5947 AstNode* save = |
| 5952 new StoreLocalNode(token_index, *temp, getter->receiver()); | 5948 new StoreLocalNode(token_index, *temp, getter->receiver()); |
| 5953 current_block_->statements->Add(save); | 5949 getter = new InstanceGetterNode(token_index, save, getter->field_name()); |
| 5954 AstNode* load = new LoadLocalNode(token_index, *temp); | |
| 5955 getter = new InstanceGetterNode(token_index, load, getter->field_name()); | |
| 5956 } | 5950 } |
| 5957 return getter; | 5951 return getter; |
| 5958 } | 5952 } |
| 5959 return node; | 5953 return node; |
| 5960 } | 5954 } |
| 5961 | 5955 |
| 5962 | 5956 |
| 5963 // TODO(srdjan): Implement other optimizations. | 5957 // TODO(srdjan): Implement other optimizations. |
| 5964 AstNode* Parser::OptimizeBinaryOpNode(intptr_t op_pos, | 5958 AstNode* Parser::OptimizeBinaryOpNode(intptr_t op_pos, |
| 5965 Token::Kind binary_op, | 5959 Token::Kind binary_op, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6030 if (expr->IsLiteralNode()) { | 6024 if (expr->IsLiteralNode()) { |
| 6031 return expr; | 6025 return expr; |
| 6032 } | 6026 } |
| 6033 if (expr->EvalConstExpr() == NULL) { | 6027 if (expr->EvalConstExpr() == NULL) { |
| 6034 ErrorMsg(expr_pos, "expression must be a compile time constant"); | 6028 ErrorMsg(expr_pos, "expression must be a compile time constant"); |
| 6035 } | 6029 } |
| 6036 return new LiteralNode(expr_pos, EvaluateConstExpr(expr)); | 6030 return new LiteralNode(expr_pos, EvaluateConstExpr(expr)); |
| 6037 } | 6031 } |
| 6038 | 6032 |
| 6039 | 6033 |
| 6034 // A compound assignment consists of a store and a load part. In order | |
| 6035 // to control sideeffects, the store part stores any sideffect creating inputs | |
|
hausner
2012/05/01 00:31:14
inputs with potential side effects
srdjan
2012/05/01 00:35:24
Done.
| |
| 6036 // into locals. Here we convert the inputs if the load local from | |
| 6037 /// the StoreLocals to LoadLocals. | |
| 6038 static AstNode* ModifyCompoundAssignmentLoad(AstNode* node) { | |
| 6039 if (node->IsLoadIndexedNode()) { | |
| 6040 LoadIndexedNode* load_indexed = node->AsLoadIndexedNode(); | |
| 6041 if (load_indexed->array()->IsStoreLocalNode()) { | |
| 6042 StoreLocalNode* store = load_indexed->array()->AsStoreLocalNode(); | |
| 6043 LoadLocalNode* load = new LoadLocalNode(store->token_index(), | |
| 6044 store->local()); | |
| 6045 load_indexed = new LoadIndexedNode(load_indexed->token_index(), | |
| 6046 load, | |
| 6047 load_indexed->index_expr()); | |
| 6048 } | |
| 6049 if (load_indexed->index_expr()->IsStoreLocalNode()) { | |
| 6050 StoreLocalNode* store = load_indexed->index_expr()->AsStoreLocalNode(); | |
| 6051 LoadLocalNode* load = new LoadLocalNode(store->token_index(), | |
| 6052 store->local()); | |
| 6053 load_indexed = new LoadIndexedNode(load_indexed->token_index(), | |
| 6054 load_indexed->array(), | |
| 6055 load); | |
| 6056 } | |
| 6057 return load_indexed; | |
| 6058 } | |
| 6059 if (node->IsInstanceGetterNode()) { | |
| 6060 InstanceGetterNode* getter = node->AsInstanceGetterNode(); | |
| 6061 if (getter->receiver()->IsStoreLocalNode()) { | |
| 6062 StoreLocalNode* store = getter->receiver()->AsStoreLocalNode(); | |
| 6063 LoadLocalNode* load = new LoadLocalNode(store->token_index(), | |
| 6064 store->local()); | |
| 6065 getter = new InstanceGetterNode(getter->token_index(), | |
| 6066 load, | |
| 6067 getter->field_name()); | |
| 6068 } | |
| 6069 return getter; | |
| 6070 } | |
| 6071 return node; | |
| 6072 } | |
| 6073 | |
| 6074 | |
| 6040 AstNode* Parser::ParseExpr(bool require_compiletime_const) { | 6075 AstNode* Parser::ParseExpr(bool require_compiletime_const) { |
| 6041 TRACE_PARSER("ParseExpr"); | 6076 TRACE_PARSER("ParseExpr"); |
| 6042 const intptr_t expr_pos = token_index_; | 6077 const intptr_t expr_pos = token_index_; |
| 6043 AstNode* expr = ParseConditionalExpr(); | 6078 AstNode* expr = ParseConditionalExpr(); |
| 6044 if (!Token::IsAssignmentOperator(CurrentToken())) { | 6079 if (!Token::IsAssignmentOperator(CurrentToken())) { |
| 6045 if (require_compiletime_const) { | 6080 if (require_compiletime_const) { |
| 6046 expr = FoldConstExpr(expr_pos, expr); | 6081 expr = FoldConstExpr(expr_pos, expr); |
| 6047 } | 6082 } |
| 6048 return expr; | 6083 return expr; |
| 6049 } | 6084 } |
| 6050 // Assignment expressions. | 6085 // Assignment expressions. |
| 6051 Token::Kind assignment_op = CurrentToken(); | 6086 Token::Kind assignment_op = CurrentToken(); |
| 6052 const intptr_t assignment_pos = token_index_; | 6087 const intptr_t assignment_pos = token_index_; |
| 6053 ConsumeToken(); | 6088 ConsumeToken(); |
| 6054 const intptr_t right_expr_pos = token_index_; | 6089 const intptr_t right_expr_pos = token_index_; |
| 6055 if (require_compiletime_const && (assignment_op != Token::kASSIGN)) { | 6090 if (require_compiletime_const && (assignment_op != Token::kASSIGN)) { |
| 6056 ErrorMsg(right_expr_pos, "expression must be a compile time constant"); | 6091 ErrorMsg(right_expr_pos, "expression must be a compile time constant"); |
| 6057 } | 6092 } |
| 6058 AstNode* right_expr = ParseExpr(require_compiletime_const); | 6093 AstNode* right_expr = ParseExpr(require_compiletime_const); |
| 6094 AstNode* left_expr = expr; | |
| 6059 if (assignment_op != Token::kASSIGN) { | 6095 if (assignment_op != Token::kASSIGN) { |
| 6060 expr = AsSideEffectFreeNode(expr); | 6096 // Compound assignment: store inputs with sideffects into temporary locals. |
|
hausner
2012/05/01 00:31:14
side effect
srdjan
2012/05/01 00:35:24
Done.
| |
| 6097 left_expr = AsSideEffectFreeNode(expr); | |
| 6098 expr = ModifyCompoundAssignmentLoad(left_expr); | |
| 6061 } | 6099 } |
| 6062 right_expr = | 6100 right_expr = |
| 6063 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr); | 6101 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr); |
| 6064 AstNode* assign_expr = expr->MakeAssignmentNode(right_expr); | 6102 AstNode* assign_expr = left_expr->MakeAssignmentNode(right_expr); |
| 6065 if (assign_expr == NULL) { | 6103 if (assign_expr == NULL) { |
| 6066 ErrorMsg(assignment_pos, | 6104 ErrorMsg(assignment_pos, |
| 6067 "left hand side of '%s' is not assignable", | 6105 "left hand side of '%s' is not assignable", |
| 6068 Token::Str(assignment_op)); | 6106 Token::Str(assignment_op)); |
| 6069 } | 6107 } |
| 6070 return assign_expr; | 6108 return assign_expr; |
| 6071 } | 6109 } |
| 6072 | 6110 |
| 6073 | 6111 |
| 6074 LiteralNode* Parser::ParseConstExpr() { | 6112 LiteralNode* Parser::ParseConstExpr() { |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6284 const String& field_name) { | 6322 const String& field_name) { |
| 6285 TRACE_PARSER("ParseInstanceFieldAccess"); | 6323 TRACE_PARSER("ParseInstanceFieldAccess"); |
| 6286 AstNode* access = NULL; | 6324 AstNode* access = NULL; |
| 6287 const intptr_t call_pos = token_index_; | 6325 const intptr_t call_pos = token_index_; |
| 6288 if (Token::IsAssignmentOperator(CurrentToken())) { | 6326 if (Token::IsAssignmentOperator(CurrentToken())) { |
| 6289 Token::Kind assignment_op = CurrentToken(); | 6327 Token::Kind assignment_op = CurrentToken(); |
| 6290 ConsumeToken(); | 6328 ConsumeToken(); |
| 6291 AstNode* value = ParseExpr(kAllowConst); | 6329 AstNode* value = ParseExpr(kAllowConst); |
| 6292 AstNode* load_access = | 6330 AstNode* load_access = |
| 6293 new InstanceGetterNode(call_pos, receiver, field_name); | 6331 new InstanceGetterNode(call_pos, receiver, field_name); |
| 6332 AstNode* left_load_access = load_access; | |
| 6294 if (assignment_op != Token::kASSIGN) { | 6333 if (assignment_op != Token::kASSIGN) { |
| 6295 load_access = AsSideEffectFreeNode(load_access); | 6334 // Compound assignment: store inputs with sideffects into temp. locals. |
| 6335 left_load_access = AsSideEffectFreeNode(load_access); | |
| 6336 load_access = ModifyCompoundAssignmentLoad(left_load_access); | |
| 6296 } | 6337 } |
| 6297 value = ExpandAssignableOp(call_pos, assignment_op, load_access, value); | 6338 value = ExpandAssignableOp(call_pos, assignment_op, load_access, value); |
| 6298 access = load_access->MakeAssignmentNode(value); | 6339 access = left_load_access->MakeAssignmentNode(value); |
| 6299 } else { | 6340 } else { |
| 6300 access = CallGetter(call_pos, receiver, field_name); | 6341 access = CallGetter(call_pos, receiver, field_name); |
| 6301 } | 6342 } |
| 6302 return access; | 6343 return access; |
| 6303 } | 6344 } |
| 6304 | 6345 |
| 6305 | 6346 |
| 6306 AstNode* Parser::GenerateStaticFieldLookup(const Field& field, | 6347 AstNode* Parser::GenerateStaticFieldLookup(const Field& field, |
| 6307 intptr_t ident_pos) { | 6348 intptr_t ident_pos) { |
| 6308 // If the static field has an initializer, initialize the field at compile | 6349 // If the static field has an initializer, initialize the field at compile |
| (...skipping 2104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8413 void Parser::SkipQualIdent() { | 8454 void Parser::SkipQualIdent() { |
| 8414 ASSERT(IsIdentifier()); | 8455 ASSERT(IsIdentifier()); |
| 8415 ConsumeToken(); | 8456 ConsumeToken(); |
| 8416 if (CurrentToken() == Token::kPERIOD) { | 8457 if (CurrentToken() == Token::kPERIOD) { |
| 8417 ConsumeToken(); // Consume the kPERIOD token. | 8458 ConsumeToken(); // Consume the kPERIOD token. |
| 8418 ExpectIdentifier("identifier expected after '.'"); | 8459 ExpectIdentifier("identifier expected after '.'"); |
| 8419 } | 8460 } |
| 8420 } | 8461 } |
| 8421 | 8462 |
| 8422 } // namespace dart | 8463 } // namespace dart |
| OLD | NEW |