From baa29ebafa1cee7853b7de933f2852e3912b1c66 Mon Sep 17 00:00:00 2001 From: "svenpanne@chromium.org" Date: Thu, 13 Oct 2011 15:07:28 +0000 Subject: [PATCH] Recognize special comparisons via pattern matching on the hydrogen graph. Previously, comparisons against null/undefined and comparisons of the result of typeof against a constant string were done syntactically. Now we do this via pattern matching on the hydrogen graph, which opens up more opportunities for better code generation, e.g. the following comparisons are now recognized to be special: var bar = typeof foo; var baz = "undefined"; if (bar == baz) ... var blah = undefined; if (hurz == blah) ... If we did this handling of special cases even later at lithium generation time, even more cases could be recognized, but this would involve bigger changes and this CL handles most common cases. Review URL: http://codereview.chromium.org/8242002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9612 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/hydrogen.cc | 84 ++++++++++++++++++++++++++++++++++++++++++--------------- src/hydrogen.h | 5 ++-- 2 files changed, 64 insertions(+), 25 deletions(-) diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 955c7e5..0cd0f97 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -5789,38 +5789,68 @@ Representation HGraphBuilder::ToRepresentation(TypeInfo info) { void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, - Expression* sub_expr, + HTypeof* typeof_expr, Handle check) { - CHECK_ALIVE(VisitForTypeOf(sub_expr)); - HValue* value = Pop(); + HValue* value = typeof_expr->value(); HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); instr->set_position(expr->position()); - return ast_context()->ReturnControl(instr, expr->id()); + ast_context()->ReturnControl(instr, expr->id()); + typeof_expr->DeleteAndReplaceWith(NULL); } -bool HGraphBuilder::TryLiteralCompare(CompareOperation* expr) { - Expression *sub_expr; - Handle check; - if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { - HandleLiteralCompareTypeof(expr, sub_expr, check); +static bool MatchLiteralCompareNil(HValue* left, + Token::Value op, + HValue* right, + Handle nil, + HValue** expr) { + if (left->IsConstant() && + HConstant::cast(left)->handle().is_identical_to(nil) && + Token::IsEqualityOp(op)) { + *expr = right; return true; } + return false; +} - if (expr->IsLiteralCompareUndefined(&sub_expr)) { - HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); - return true; - } - if (expr->IsLiteralCompareNull(&sub_expr)) { - HandleLiteralCompareNil(expr, sub_expr, kNullValue); +static bool MatchLiteralCompareTypeof(HValue* left, + Token::Value op, + HValue* right, + HTypeof** typeof_expr, + Handle* check) { + if (left->IsTypeof() && + Token::IsEqualityOp(op) && + right->IsConstant() && + HConstant::cast(right)->HasStringValue()) { + *typeof_expr = HTypeof::cast(left); + *check = Handle::cast(HConstant::cast(right)->handle()); return true; } - return false; } +static bool IsLiteralCompareTypeof(HValue* left, + Token::Value op, + HValue* right, + HTypeof** typeof_expr, + Handle* check) { + return MatchLiteralCompareTypeof(left, op, right, typeof_expr, check) || + MatchLiteralCompareTypeof(right, op, left, typeof_expr, check); +} + + +static bool IsLiteralCompareNil(HValue* left, + Token::Value op, + HValue* right, + Handle nil, + HValue** expr) { + return MatchLiteralCompareNil(left, op, right, nil, expr) || + MatchLiteralCompareNil(right, op, left, nil, expr); +} + + void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { ASSERT(!HasStackOverflow()); ASSERT(current_block() != NULL); @@ -5838,11 +5868,9 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { return ast_context()->ReturnControl(instr, expr->id()); } - // Check for special cases that compare against literals. - if (TryLiteralCompare(expr)) return; - TypeInfo type_info = oracle()->CompareType(expr); // Check if this expression was ever executed according to type feedback. + // Note that for the special typeof/null/undefined cases we get unknown here. if (type_info.IsUninitialized()) { AddInstruction(new(zone()) HSoftDeoptimize); current_block()->MarkAsDeoptimizing(); @@ -5857,6 +5885,20 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { HValue* left = Pop(); Token::Value op = expr->op(); + HTypeof* typeof_expr = NULL; + Handle check; + if (IsLiteralCompareTypeof(left, op, right, &typeof_expr, &check)) { + return HandleLiteralCompareTypeof(expr, typeof_expr, check); + } + HValue* sub_expr = NULL; + Factory* f = graph()->isolate()->factory(); + if (IsLiteralCompareNil(left, op, right, f->undefined_value(), &sub_expr)) { + return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); + } + if (IsLiteralCompareNil(left, op, right, f->null_value(), &sub_expr)) { + return HandleLiteralCompareNil(expr, sub_expr, kNullValue); + } + if (op == Token::INSTANCEOF) { // Check to see if the rhs of the instanceof is a global function not // residing in new space. If it is we assume that the function will stay the @@ -5945,13 +5987,11 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, - Expression* sub_expr, + HValue* value, NilValue nil) { ASSERT(!HasStackOverflow()); ASSERT(current_block() != NULL); ASSERT(current_block()->HasPredecessor()); - CHECK_ALIVE(VisitForValue(sub_expr)); - HValue* value = Pop(); EqualityKind kind = expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); diff --git a/src/hydrogen.h b/src/hydrogen.h index b66042c..c7155ad 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -912,12 +912,11 @@ class HGraphBuilder: public AstVisitor { HValue* receiver, SmallMapList* types, Handle name); - bool TryLiteralCompare(CompareOperation* expr); void HandleLiteralCompareTypeof(CompareOperation* expr, - Expression* sub_expr, + HTypeof* typeof_expr, Handle check); void HandleLiteralCompareNil(CompareOperation* expr, - Expression* sub_expr, + HValue* value, NilValue nil); HStringCharCodeAt* BuildStringCharCodeAt(HValue* context, -- 2.7.4