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 #include "vm/flags.h" | 6 #include "vm/flags.h" |
7 | 7 |
8 #ifndef DART_PRECOMPILED_RUNTIME | 8 #ifndef DART_PRECOMPILED_RUNTIME |
9 | 9 |
10 #include "lib/invocation_mirror.h" | 10 #include "lib/invocation_mirror.h" |
(...skipping 2712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2723 receiver->set_invisible(false); | 2723 receiver->set_invisible(false); |
2724 SetAllowFunctionLiterals(saved_mode); | 2724 SetAllowFunctionLiterals(saved_mode); |
2725 if (current_function().is_const()) { | 2725 if (current_function().is_const()) { |
2726 if (!init_expr->IsPotentiallyConst()) { | 2726 if (!init_expr->IsPotentiallyConst()) { |
2727 ReportError(expr_pos, | 2727 ReportError(expr_pos, |
2728 "initializer expression must be compile time constant."); | 2728 "initializer expression must be compile time constant."); |
2729 } | 2729 } |
2730 if (init_expr->EvalConstExpr() != NULL) { | 2730 if (init_expr->EvalConstExpr() != NULL) { |
2731 // If the expression is a compile-time constant, ensure that it | 2731 // If the expression is a compile-time constant, ensure that it |
2732 // is evaluated and canonicalized. See issue 27164. | 2732 // is evaluated and canonicalized. See issue 27164. |
2733 Instance& const_instance = Instance::ZoneHandle(Z); | 2733 init_expr = FoldConstExpr(expr_pos, init_expr); |
2734 if (!GetCachedConstant(expr_pos, &const_instance)) { | |
2735 const_instance = EvaluateConstExpr(expr_pos, init_expr).raw(); | |
2736 CacheConstantValue(expr_pos, const_instance); | |
2737 } | |
2738 init_expr = new(Z) LiteralNode(expr_pos, const_instance); | |
2739 } | 2734 } |
2740 } | 2735 } |
2741 Field& field = Field::ZoneHandle(Z, cls.LookupInstanceField(field_name)); | 2736 Field& field = Field::ZoneHandle(Z, cls.LookupInstanceField(field_name)); |
2742 if (field.IsNull()) { | 2737 if (field.IsNull()) { |
2743 ReportError(field_pos, "unresolved reference to instance field '%s'", | 2738 ReportError(field_pos, "unresolved reference to instance field '%s'", |
2744 field_name.ToCString()); | 2739 field_name.ToCString()); |
2745 } | 2740 } |
2746 EnsureExpressionTemp(); | 2741 EnsureExpressionTemp(); |
2747 AstNode* instance = new(Z) LoadLocalNode(field_pos, receiver); | 2742 AstNode* instance = new(Z) LoadLocalNode(field_pos, receiver); |
2748 AstNode* initializer = CheckDuplicateFieldInit(field_pos, | 2743 AstNode* initializer = CheckDuplicateFieldInit(field_pos, |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2805 ASSERT(IsIdentifier()); | 2800 ASSERT(IsIdentifier()); |
2806 ConsumeToken(); | 2801 ConsumeToken(); |
2807 ExpectToken(Token::kASSIGN); | 2802 ExpectToken(Token::kASSIGN); |
2808 AstNode* init_expr = NULL; | 2803 AstNode* init_expr = NULL; |
2809 TokenPosition expr_pos = TokenPos(); | 2804 TokenPosition expr_pos = TokenPos(); |
2810 if (field.is_const()) { | 2805 if (field.is_const()) { |
2811 init_expr = ParseConstExpr(); | 2806 init_expr = ParseConstExpr(); |
2812 } else { | 2807 } else { |
2813 init_expr = ParseExpr(kAllowConst, kConsumeCascades); | 2808 init_expr = ParseExpr(kAllowConst, kConsumeCascades); |
2814 if (init_expr->EvalConstExpr() != NULL) { | 2809 if (init_expr->EvalConstExpr() != NULL) { |
2815 Instance& expr_value = Instance::ZoneHandle(Z); | 2810 init_expr = FoldConstExpr(expr_pos, init_expr); |
2816 if (!GetCachedConstant(expr_pos, &expr_value)) { | |
2817 expr_value = EvaluateConstExpr(expr_pos, init_expr).raw(); | |
2818 CacheConstantValue(expr_pos, expr_value); | |
2819 } | |
2820 init_expr = new(Z) LiteralNode(field.token_pos(), expr_value); | |
2821 } | 2811 } |
2822 } | 2812 } |
2823 set_library(saved_library); | 2813 set_library(saved_library); |
2824 SetScript(saved_script, saved_token_pos); | 2814 SetScript(saved_script, saved_token_pos); |
2825 return init_expr; | 2815 return init_expr; |
2826 } | 2816 } |
2827 | 2817 |
2828 | 2818 |
2829 void Parser::ParseInitializedInstanceFields(const Class& cls, | 2819 void Parser::ParseInitializedInstanceFields(const Class& cls, |
2830 LocalVariable* receiver, | 2820 LocalVariable* receiver, |
(...skipping 22 matching lines...) Expand all Loading... |
2853 ConsumeToken(); | 2843 ConsumeToken(); |
2854 ExpectToken(Token::kASSIGN); | 2844 ExpectToken(Token::kASSIGN); |
2855 if (current_class().is_const()) { | 2845 if (current_class().is_const()) { |
2856 // If the class has a const contructor, the initializer | 2846 // If the class has a const contructor, the initializer |
2857 // expression must be a compile-time constant. | 2847 // expression must be a compile-time constant. |
2858 init_expr = ParseConstExpr(); | 2848 init_expr = ParseConstExpr(); |
2859 } else { | 2849 } else { |
2860 TokenPosition expr_pos = TokenPos(); | 2850 TokenPosition expr_pos = TokenPos(); |
2861 init_expr = ParseExpr(kAllowConst, kConsumeCascades); | 2851 init_expr = ParseExpr(kAllowConst, kConsumeCascades); |
2862 if (init_expr->EvalConstExpr() != NULL) { | 2852 if (init_expr->EvalConstExpr() != NULL) { |
2863 Instance& expr_value = Instance::ZoneHandle(Z); | 2853 init_expr = FoldConstExpr(expr_pos, init_expr); |
2864 if (!GetCachedConstant(expr_pos, &expr_value)) { | |
2865 expr_value = EvaluateConstExpr(expr_pos, init_expr).raw(); | |
2866 CacheConstantValue(expr_pos, expr_value); | |
2867 } | |
2868 init_expr = new(Z) LiteralNode(field.token_pos(), expr_value); | |
2869 } | 2854 } |
2870 } | 2855 } |
2871 } | 2856 } |
2872 ASSERT(init_expr != NULL); | 2857 ASSERT(init_expr != NULL); |
2873 AstNode* instance = new LoadLocalNode(field.token_pos(), receiver); | 2858 AstNode* instance = new LoadLocalNode(field.token_pos(), receiver); |
2874 EnsureExpressionTemp(); | 2859 EnsureExpressionTemp(); |
2875 AstNode* field_init = | 2860 AstNode* field_init = |
2876 new StoreInstanceFieldNode(field.token_pos(), | 2861 new StoreInstanceFieldNode(field.token_pos(), |
2877 instance, | 2862 instance, |
2878 field, | 2863 field, |
(...skipping 8147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11026 if ((rhs_literal == NULL) && (lhs_literal != NULL)) { | 11011 if ((rhs_literal == NULL) && (lhs_literal != NULL)) { |
11027 // Swap. | 11012 // Swap. |
11028 LiteralNode* temp = rhs_literal; | 11013 LiteralNode* temp = rhs_literal; |
11029 rhs_literal = lhs_literal; | 11014 rhs_literal = lhs_literal; |
11030 lhs_literal = temp; | 11015 lhs_literal = temp; |
11031 } | 11016 } |
11032 } | 11017 } |
11033 if (binary_op == Token::kIFNULL) { | 11018 if (binary_op == Token::kIFNULL) { |
11034 // Handle a ?? b. | 11019 // Handle a ?? b. |
11035 if ((lhs->EvalConstExpr() != NULL) && (rhs->EvalConstExpr() != NULL)) { | 11020 if ((lhs->EvalConstExpr() != NULL) && (rhs->EvalConstExpr() != NULL)) { |
11036 Instance& expr_value = Instance::ZoneHandle(Z); | 11021 Instance& expr_value = Instance::ZoneHandle(Z, |
11037 if (!GetCachedConstant(op_pos, &expr_value)) { | 11022 EvaluateConstExpr(lhs->token_pos(), lhs).raw()); |
11038 expr_value = EvaluateConstExpr(lhs->token_pos(), lhs).raw(); | 11023 if (expr_value.IsNull()) { |
11039 if (expr_value.IsNull()) { | 11024 expr_value = EvaluateConstExpr(rhs->token_pos(), rhs).raw(); |
11040 expr_value = EvaluateConstExpr(rhs->token_pos(), rhs).raw(); | |
11041 } | |
11042 CacheConstantValue(op_pos, expr_value); | |
11043 } | 11025 } |
11044 return new(Z) LiteralNode(op_pos, expr_value); | 11026 return new(Z) LiteralNode(op_pos, expr_value); |
11045 } | 11027 } |
11046 | 11028 |
11047 LetNode* result = new(Z) LetNode(op_pos); | 11029 LetNode* result = new(Z) LetNode(op_pos); |
11048 LocalVariable* left_temp = result->AddInitializer(lhs); | 11030 LocalVariable* left_temp = result->AddInitializer(lhs); |
11049 left_temp->set_is_final(); | 11031 left_temp->set_is_final(); |
11050 const TokenPosition no_pos = TokenPosition::kNoSource; | 11032 const TokenPosition no_pos = TokenPosition::kNoSource; |
11051 LiteralNode* null_operand = | 11033 LiteralNode* null_operand = |
11052 new(Z) LiteralNode(no_pos, Object::null_instance()); | 11034 new(Z) LiteralNode(no_pos, Object::null_instance()); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11110 | 11092 |
11111 // Evaluates the value of the compile time constant expression | 11093 // Evaluates the value of the compile time constant expression |
11112 // and returns a literal node for the value. | 11094 // and returns a literal node for the value. |
11113 LiteralNode* Parser::FoldConstExpr(TokenPosition expr_pos, AstNode* expr) { | 11095 LiteralNode* Parser::FoldConstExpr(TokenPosition expr_pos, AstNode* expr) { |
11114 if (expr->IsLiteralNode()) { | 11096 if (expr->IsLiteralNode()) { |
11115 return expr->AsLiteralNode(); | 11097 return expr->AsLiteralNode(); |
11116 } | 11098 } |
11117 if (expr->EvalConstExpr() == NULL) { | 11099 if (expr->EvalConstExpr() == NULL) { |
11118 ReportError(expr_pos, "expression is not a valid compile-time constant"); | 11100 ReportError(expr_pos, "expression is not a valid compile-time constant"); |
11119 } | 11101 } |
11120 return new(Z) LiteralNode( | 11102 return new(Z) LiteralNode(expr_pos, EvaluateConstExpr(expr_pos, expr)); |
11121 expr_pos, EvaluateConstExpr(expr_pos, expr)); | |
11122 } | 11103 } |
11123 | 11104 |
11124 | 11105 |
11125 LetNode* Parser::PrepareCompoundAssignmentNodes(AstNode** expr) { | 11106 LetNode* Parser::PrepareCompoundAssignmentNodes(AstNode** expr) { |
11126 AstNode* node = *expr; | 11107 AstNode* node = *expr; |
11127 TokenPosition token_pos = node->token_pos(); | 11108 TokenPosition token_pos = node->token_pos(); |
11128 LetNode* result = new(Z) LetNode(token_pos); | 11109 LetNode* result = new(Z) LetNode(token_pos); |
11129 if (node->IsLoadIndexedNode()) { | 11110 if (node->IsLoadIndexedNode()) { |
11130 LoadIndexedNode* load_indexed = node->AsLoadIndexedNode(); | 11111 LoadIndexedNode* load_indexed = node->AsLoadIndexedNode(); |
11131 AstNode* array = load_indexed->array(); | 11112 AstNode* array = load_indexed->array(); |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11372 return new(Z) LiteralNode(expr_pos, existing_const); | 11353 return new(Z) LiteralNode(expr_pos, existing_const); |
11373 } | 11354 } |
11374 } | 11355 } |
11375 | 11356 |
11376 AstNode* expr = ParseConditionalExpr(); | 11357 AstNode* expr = ParseConditionalExpr(); |
11377 if (!Token::IsAssignmentOperator(CurrentToken())) { | 11358 if (!Token::IsAssignmentOperator(CurrentToken())) { |
11378 if ((CurrentToken() == Token::kCASCADE) && consume_cascades) { | 11359 if ((CurrentToken() == Token::kCASCADE) && consume_cascades) { |
11379 return ParseCascades(expr); | 11360 return ParseCascades(expr); |
11380 } | 11361 } |
11381 if (require_compiletime_const) { | 11362 if (require_compiletime_const) { |
11382 const bool use_cache = !expr->IsLiteralNode(); | 11363 expr = FoldConstExpr(expr_pos, expr); |
11383 LiteralNode* const_value = FoldConstExpr(expr_pos, expr); | |
11384 if (use_cache) CacheConstantValue(expr_pos, const_value->literal()); | |
11385 expr = const_value; | |
11386 } else { | 11364 } else { |
11387 expr = LiteralIfStaticConst(Z, expr); | 11365 expr = LiteralIfStaticConst(Z, expr); |
11388 } | 11366 } |
11389 return expr; | 11367 return expr; |
11390 } | 11368 } |
11391 // Assignment expressions. | 11369 // Assignment expressions. |
11392 if (!IsLegalAssignableSyntax(expr, TokenPos())) { | 11370 if (!IsLegalAssignableSyntax(expr, TokenPos())) { |
11393 ReportError(expr_pos, "expression is not assignable"); | 11371 ReportError(expr_pos, "expression is not assignable"); |
11394 } | 11372 } |
11395 const Token::Kind assignment_op = CurrentToken(); | 11373 const Token::Kind assignment_op = CurrentToken(); |
(...skipping 1074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12470 | 12448 |
12471 | 12449 |
12472 void Parser::CacheConstantValue(TokenPosition token_pos, | 12450 void Parser::CacheConstantValue(TokenPosition token_pos, |
12473 const Instance& value) { | 12451 const Instance& value) { |
12474 if (current_function().kind() == RawFunction::kImplicitStaticFinalGetter) { | 12452 if (current_function().kind() == RawFunction::kImplicitStaticFinalGetter) { |
12475 // Don't cache constants in initializer expressions. They get | 12453 // Don't cache constants in initializer expressions. They get |
12476 // evaluated only once. | 12454 // evaluated only once. |
12477 return; | 12455 return; |
12478 } | 12456 } |
12479 InsertCachedConstantValue(script_, token_pos, value); | 12457 InsertCachedConstantValue(script_, token_pos, value); |
| 12458 INC_STAT(thread_, num_cached_consts, 1); |
12480 } | 12459 } |
12481 | 12460 |
12482 | 12461 |
12483 bool Parser::GetCachedConstant(TokenPosition token_pos, Instance* value) { | 12462 bool Parser::GetCachedConstant(TokenPosition token_pos, Instance* value) { |
12484 bool is_present = false; | 12463 bool is_present = false; |
12485 ASSERT(!script_.InVMHeap()); | 12464 ASSERT(!script_.InVMHeap()); |
12486 if (script_.compile_time_constants() == Array::null()) { | 12465 if (script_.compile_time_constants() == Array::null()) { |
12487 return false; | 12466 return false; |
12488 } | 12467 } |
12489 ConstantsMap constants(script_.compile_time_constants()); | 12468 ConstantsMap constants(script_.compile_time_constants()); |
(...skipping 1983 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14473 expr->AsLoadLocalNode()->local().IsConst()) { | 14452 expr->AsLoadLocalNode()->local().IsConst()) { |
14474 return *expr->AsLoadLocalNode()->local().ConstValue(); | 14453 return *expr->AsLoadLocalNode()->local().ConstValue(); |
14475 } else if (expr->IsLoadStaticFieldNode()) { | 14454 } else if (expr->IsLoadStaticFieldNode()) { |
14476 const Field& field = expr->AsLoadStaticFieldNode()->field(); | 14455 const Field& field = expr->AsLoadStaticFieldNode()->field(); |
14477 // We already checked that this field is const and has been | 14456 // We already checked that this field is const and has been |
14478 // initialized. | 14457 // initialized. |
14479 ASSERT(field.is_const()); | 14458 ASSERT(field.is_const()); |
14480 ASSERT(field.StaticValue() != Object::sentinel().raw()); | 14459 ASSERT(field.StaticValue() != Object::sentinel().raw()); |
14481 ASSERT(field.StaticValue() != Object::transition_sentinel().raw()); | 14460 ASSERT(field.StaticValue() != Object::transition_sentinel().raw()); |
14482 return Instance::ZoneHandle(Z, field.StaticValue()); | 14461 return Instance::ZoneHandle(Z, field.StaticValue()); |
| 14462 } else if (expr->IsTypeNode()) { |
| 14463 AbstractType& type = |
| 14464 AbstractType::ZoneHandle(Z, expr->AsTypeNode()->type().raw()); |
| 14465 ASSERT(type.IsInstantiated() && !type.IsMalformedOrMalbounded()); |
| 14466 return type; |
| 14467 } else if (expr->IsClosureNode()) { |
| 14468 const Function& func = expr->AsClosureNode()->function(); |
| 14469 ASSERT((func.IsImplicitStaticClosureFunction())); |
| 14470 Instance& closure = Instance::ZoneHandle(Z, func.ImplicitStaticClosure()); |
| 14471 closure = TryCanonicalize(closure, expr_pos); |
| 14472 return closure; |
14483 } else { | 14473 } else { |
14484 ASSERT(expr->EvalConstExpr() != NULL); | 14474 ASSERT(expr->EvalConstExpr() != NULL); |
14485 ReturnNode* ret = new(Z) ReturnNode(expr->token_pos(), expr); | 14475 Instance& value = Instance::ZoneHandle(Z); |
| 14476 if (GetCachedConstant(expr_pos, &value)) { |
| 14477 return value; |
| 14478 } |
| 14479 ReturnNode* ret = new(Z) ReturnNode(expr_pos, expr); |
14486 // Compile time constant expressions cannot reference anything from a | 14480 // Compile time constant expressions cannot reference anything from a |
14487 // local scope. | 14481 // local scope. |
14488 LocalScope* empty_scope = new(Z) LocalScope(NULL, 0, 0); | 14482 LocalScope* empty_scope = new(Z) LocalScope(NULL, 0, 0); |
14489 SequenceNode* seq = new(Z) SequenceNode(expr->token_pos(), empty_scope); | 14483 SequenceNode* seq = new(Z) SequenceNode(expr_pos, empty_scope); |
14490 seq->Add(ret); | 14484 seq->Add(ret); |
14491 | 14485 |
| 14486 INC_STAT(thread_, num_execute_const, 1); |
14492 Object& result = Object::Handle(Z, Compiler::ExecuteOnce(seq)); | 14487 Object& result = Object::Handle(Z, Compiler::ExecuteOnce(seq)); |
14493 if (result.IsError()) { | 14488 if (result.IsError()) { |
14494 ReportErrors(Error::Cast(result), | 14489 ReportErrors(Error::Cast(result), |
14495 script_, expr_pos, | 14490 script_, expr_pos, |
14496 "error evaluating constant expression"); | 14491 "error evaluating constant expression"); |
14497 } | 14492 } |
14498 ASSERT(result.IsInstance() || result.IsNull()); | 14493 ASSERT(result.IsInstance() || result.IsNull()); |
14499 Instance& value = Instance::ZoneHandle(Z); | |
14500 value ^= result.raw(); | 14494 value ^= result.raw(); |
14501 value = TryCanonicalize(value, TokenPos()); | 14495 value = TryCanonicalize(value, expr_pos); |
| 14496 CacheConstantValue(expr_pos, value); |
14502 return value; | 14497 return value; |
14503 } | 14498 } |
14504 } | 14499 } |
14505 | 14500 |
14506 | 14501 |
14507 void Parser::SkipFunctionLiteral() { | 14502 void Parser::SkipFunctionLiteral() { |
14508 if (IsIdentifier()) { | 14503 if (IsIdentifier()) { |
14509 if (LookaheadToken(1) != Token::kLPAREN) { | 14504 if (LookaheadToken(1) != Token::kLPAREN) { |
14510 SkipType(true); | 14505 SkipType(true); |
14511 } | 14506 } |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14958 const ArgumentListNode& function_args, | 14953 const ArgumentListNode& function_args, |
14959 const LocalVariable* temp_for_last_arg, | 14954 const LocalVariable* temp_for_last_arg, |
14960 bool is_super_invocation) { | 14955 bool is_super_invocation) { |
14961 UNREACHABLE(); | 14956 UNREACHABLE(); |
14962 return NULL; | 14957 return NULL; |
14963 } | 14958 } |
14964 | 14959 |
14965 } // namespace dart | 14960 } // namespace dart |
14966 | 14961 |
14967 #endif // DART_PRECOMPILED_RUNTIME | 14962 #endif // DART_PRECOMPILED_RUNTIME |
OLD | NEW |