| Index: runtime/vm/parser.cc
|
| ===================================================================
|
| --- runtime/vm/parser.cc (revision 28079)
|
| +++ runtime/vm/parser.cc (working copy)
|
| @@ -1923,55 +1923,7 @@
|
| op_arguments = BuildNoSuchMethodArguments(
|
| operator_pos, operator_function_name, *op_arguments);
|
| }
|
| - if (super_operator.name() == Symbols::EqualOperator().raw()) {
|
| - // Expand super.== call to match correct == semantics into:
|
| - // Let t1 = left, t2 = right {
|
| - // (t1 === null || t2 === null) ? t1 === t2
|
| - // : static_call(super.==, t1, t2)
|
| - // }
|
| - // Normal == calls are not expanded at the AST level to produce
|
| - // more compact code and enable more optimization opportunities.
|
| - ASSERT(!is_no_such_method); // == is always found.
|
| - EnsureExpressionTemp(); // Needed for ConditionalExprNode.
|
| - LetNode* result = new LetNode(operator_pos);
|
| - AstNode* left =
|
| - new LoadLocalNode(operator_pos,
|
| - result->AddInitializer(op_arguments->NodeAt(0)));
|
| - AstNode* right =
|
| - new LoadLocalNode(operator_pos,
|
| - result->AddInitializer(op_arguments->NodeAt(1)));
|
| - LiteralNode* null_operand =
|
| - new LiteralNode(operator_pos, Instance::ZoneHandle());
|
| - ComparisonNode* is_left_null = new ComparisonNode(operator_pos,
|
| - Token::kEQ_STRICT,
|
| - left,
|
| - null_operand);
|
| - ComparisonNode* is_right_null = new ComparisonNode(operator_pos,
|
| - Token::kEQ_STRICT,
|
| - right,
|
| - null_operand);
|
| - BinaryOpNode* null_check = new BinaryOpNode(operator_pos,
|
| - Token::kOR,
|
| - is_left_null,
|
| - is_right_null);
|
| - ArgumentListNode* new_arguments = new ArgumentListNode(operator_pos);
|
| - new_arguments->Add(left);
|
| - new_arguments->Add(right);
|
| - StaticCallNode* call = new StaticCallNode(operator_pos,
|
| - super_operator,
|
| - new_arguments);
|
| - ComparisonNode* strict_eq = new ComparisonNode(operator_pos,
|
| - Token::kEQ_STRICT,
|
| - left,
|
| - right);
|
| - result->AddNode(new ConditionalExprNode(operator_pos,
|
| - null_check,
|
| - strict_eq,
|
| - call));
|
| - super_op = result;
|
| - } else {
|
| - super_op = new StaticCallNode(operator_pos, super_operator, op_arguments);
|
| - }
|
| + super_op = new StaticCallNode(operator_pos, super_operator, op_arguments);
|
| if (negate_result) {
|
| super_op = new UnaryOpNode(operator_pos, Token::kNOT, super_op);
|
| }
|
| @@ -2879,17 +2831,35 @@
|
| intptr_t end_token_pos = 0;
|
| if (CurrentToken() == Token::kLBRACE) {
|
| ConsumeToken();
|
| + if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) {
|
| + const Class& owner = Class::Handle(func.Owner());
|
| + if (!owner.IsObjectClass()) {
|
| + AddEqualityNullCheck();
|
| + }
|
| + }
|
| ParseStatementSequence();
|
| end_token_pos = TokenPos();
|
| ExpectToken(Token::kRBRACE);
|
| } else if (CurrentToken() == Token::kARROW) {
|
| ConsumeToken();
|
| + if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) {
|
| + const Class& owner = Class::Handle(func.Owner());
|
| + if (!owner.IsObjectClass()) {
|
| + AddEqualityNullCheck();
|
| + }
|
| + }
|
| const intptr_t expr_pos = TokenPos();
|
| AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
|
| ASSERT(expr != NULL);
|
| current_block_->statements->Add(new ReturnNode(expr_pos, expr));
|
| end_token_pos = TokenPos();
|
| } else if (IsLiteral("native")) {
|
| + if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) {
|
| + const Class& owner = Class::Handle(func.Owner());
|
| + if (!owner.IsObjectClass()) {
|
| + AddEqualityNullCheck();
|
| + }
|
| + }
|
| ParseNativeFunctionBlock(¶ms, func);
|
| end_token_pos = TokenPos();
|
| ExpectSemicolon();
|
| @@ -2924,6 +2894,31 @@
|
| }
|
|
|
|
|
| +void Parser::AddEqualityNullCheck() {
|
| + const intptr_t token_pos = Scanner::kDummyTokenIndex;
|
| + AstNode* argument =
|
| + new LoadLocalNode(token_pos,
|
| + current_block_->scope->parent()->VariableAt(1));
|
| + LiteralNode* null_operand =
|
| + new LiteralNode(token_pos, Instance::ZoneHandle());
|
| + ComparisonNode* check_arg = new ComparisonNode(token_pos,
|
| + Token::kEQ_STRICT,
|
| + argument,
|
| + null_operand);
|
| + ComparisonNode* result = new ComparisonNode(token_pos,
|
| + Token::kEQ_STRICT,
|
| + LoadReceiver(token_pos),
|
| + null_operand);
|
| + SequenceNode* arg_is_null = new SequenceNode(token_pos, NULL);
|
| + arg_is_null->Add(new ReturnNode(token_pos, result));
|
| + IfNode* if_arg_null = new IfNode(token_pos,
|
| + check_arg,
|
| + arg_is_null,
|
| + NULL);
|
| + current_block_->statements->Add(if_arg_null);
|
| +}
|
| +
|
| +
|
| void Parser::SkipIf(Token::Kind token) {
|
| if (CurrentToken() == token) {
|
| ConsumeToken();
|
|
|