Index: runtime/vm/parser.cc |
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
index 4134d2b372207b21b0bd4239a895b599a22d61b5..7c5eefc23cf71e9f26f2671a059eb86940ddaf34 100644 |
--- a/runtime/vm/parser.cc |
+++ b/runtime/vm/parser.cc |
@@ -2730,12 +2730,7 @@ AstNode* Parser::ParseInitializer(const Class& cls, |
if (init_expr->EvalConstExpr() != NULL) { |
// If the expression is a compile-time constant, ensure that it |
// is evaluated and canonicalized. See issue 27164. |
- Instance& const_instance = Instance::ZoneHandle(Z); |
- if (!GetCachedConstant(expr_pos, &const_instance)) { |
- const_instance = EvaluateConstExpr(expr_pos, init_expr).raw(); |
- CacheConstantValue(expr_pos, const_instance); |
- } |
- init_expr = new(Z) LiteralNode(expr_pos, const_instance); |
+ init_expr = FoldConstExpr(expr_pos, init_expr); |
} |
} |
Field& field = Field::ZoneHandle(Z, cls.LookupInstanceField(field_name)); |
@@ -2812,12 +2807,7 @@ AstNode* Parser::ParseExternalInitializedField(const Field& field) { |
} else { |
init_expr = ParseExpr(kAllowConst, kConsumeCascades); |
if (init_expr->EvalConstExpr() != NULL) { |
- Instance& expr_value = Instance::ZoneHandle(Z); |
- if (!GetCachedConstant(expr_pos, &expr_value)) { |
- expr_value = EvaluateConstExpr(expr_pos, init_expr).raw(); |
- CacheConstantValue(expr_pos, expr_value); |
- } |
- init_expr = new(Z) LiteralNode(field.token_pos(), expr_value); |
+ init_expr = FoldConstExpr(expr_pos, init_expr); |
} |
} |
set_library(saved_library); |
@@ -2860,12 +2850,7 @@ void Parser::ParseInitializedInstanceFields(const Class& cls, |
TokenPosition expr_pos = TokenPos(); |
init_expr = ParseExpr(kAllowConst, kConsumeCascades); |
if (init_expr->EvalConstExpr() != NULL) { |
- Instance& expr_value = Instance::ZoneHandle(Z); |
- if (!GetCachedConstant(expr_pos, &expr_value)) { |
- expr_value = EvaluateConstExpr(expr_pos, init_expr).raw(); |
- CacheConstantValue(expr_pos, expr_value); |
- } |
- init_expr = new(Z) LiteralNode(field.token_pos(), expr_value); |
+ init_expr = FoldConstExpr(expr_pos, init_expr); |
} |
} |
} |
@@ -11033,13 +11018,10 @@ AstNode* Parser::OptimizeBinaryOpNode(TokenPosition op_pos, |
if (binary_op == Token::kIFNULL) { |
// Handle a ?? b. |
if ((lhs->EvalConstExpr() != NULL) && (rhs->EvalConstExpr() != NULL)) { |
- Instance& expr_value = Instance::ZoneHandle(Z); |
- if (!GetCachedConstant(op_pos, &expr_value)) { |
- expr_value = EvaluateConstExpr(lhs->token_pos(), lhs).raw(); |
- if (expr_value.IsNull()) { |
- expr_value = EvaluateConstExpr(rhs->token_pos(), rhs).raw(); |
- } |
- CacheConstantValue(op_pos, expr_value); |
+ Instance& expr_value = Instance::ZoneHandle(Z, |
+ EvaluateConstExpr(lhs->token_pos(), lhs).raw()); |
+ if (expr_value.IsNull()) { |
+ expr_value = EvaluateConstExpr(rhs->token_pos(), rhs).raw(); |
} |
return new(Z) LiteralNode(op_pos, expr_value); |
} |
@@ -11117,8 +11099,7 @@ LiteralNode* Parser::FoldConstExpr(TokenPosition expr_pos, AstNode* expr) { |
if (expr->EvalConstExpr() == NULL) { |
ReportError(expr_pos, "expression is not a valid compile-time constant"); |
} |
- return new(Z) LiteralNode( |
- expr_pos, EvaluateConstExpr(expr_pos, expr)); |
+ return new(Z) LiteralNode(expr_pos, EvaluateConstExpr(expr_pos, expr)); |
} |
@@ -11379,10 +11360,7 @@ AstNode* Parser::ParseExpr(bool require_compiletime_const, |
return ParseCascades(expr); |
} |
if (require_compiletime_const) { |
- const bool use_cache = !expr->IsLiteralNode(); |
- LiteralNode* const_value = FoldConstExpr(expr_pos, expr); |
- if (use_cache) CacheConstantValue(expr_pos, const_value->literal()); |
- expr = const_value; |
+ expr = FoldConstExpr(expr_pos, expr); |
} else { |
expr = LiteralIfStaticConst(Z, expr); |
} |
@@ -12477,6 +12455,7 @@ void Parser::CacheConstantValue(TokenPosition token_pos, |
return; |
} |
InsertCachedConstantValue(script_, token_pos, value); |
+ INC_STAT(thread_, num_cached_consts, 1); |
} |
@@ -14480,15 +14459,31 @@ const Instance& Parser::EvaluateConstExpr(TokenPosition expr_pos, |
ASSERT(field.StaticValue() != Object::sentinel().raw()); |
ASSERT(field.StaticValue() != Object::transition_sentinel().raw()); |
return Instance::ZoneHandle(Z, field.StaticValue()); |
+ } else if (expr->IsTypeNode()) { |
+ AbstractType& type = |
+ AbstractType::ZoneHandle(Z, expr->AsTypeNode()->type().raw()); |
+ ASSERT(type.IsInstantiated() && !type.IsMalformedOrMalbounded()); |
+ return type; |
+ } else if (expr->IsClosureNode()) { |
+ const Function& func = expr->AsClosureNode()->function(); |
+ ASSERT((func.IsImplicitStaticClosureFunction())); |
+ Instance& closure = Instance::ZoneHandle(Z, func.ImplicitStaticClosure()); |
+ closure = TryCanonicalize(closure, expr_pos); |
+ return closure; |
} else { |
ASSERT(expr->EvalConstExpr() != NULL); |
- ReturnNode* ret = new(Z) ReturnNode(expr->token_pos(), expr); |
+ Instance& value = Instance::ZoneHandle(Z); |
+ if (GetCachedConstant(expr_pos, &value)) { |
+ return value; |
+ } |
+ ReturnNode* ret = new(Z) ReturnNode(expr_pos, expr); |
// Compile time constant expressions cannot reference anything from a |
// local scope. |
LocalScope* empty_scope = new(Z) LocalScope(NULL, 0, 0); |
- SequenceNode* seq = new(Z) SequenceNode(expr->token_pos(), empty_scope); |
+ SequenceNode* seq = new(Z) SequenceNode(expr_pos, empty_scope); |
seq->Add(ret); |
+ INC_STAT(thread_, num_execute_const, 1); |
Object& result = Object::Handle(Z, Compiler::ExecuteOnce(seq)); |
if (result.IsError()) { |
ReportErrors(Error::Cast(result), |
@@ -14496,9 +14491,9 @@ const Instance& Parser::EvaluateConstExpr(TokenPosition expr_pos, |
"error evaluating constant expression"); |
} |
ASSERT(result.IsInstance() || result.IsNull()); |
- Instance& value = Instance::ZoneHandle(Z); |
value ^= result.raw(); |
- value = TryCanonicalize(value, TokenPos()); |
+ value = TryCanonicalize(value, expr_pos); |
+ CacheConstantValue(expr_pos, value); |
return value; |
} |
} |