| 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;
|
| }
|
| }
|
|
|