Revision: 9688
Author:   [email protected]
Date:     Wed Oct 19 00:35:30 2011
Log: Recognize special comparisons via pattern matching on the hydrogen graph, 2nd attempt.

This time, we initially leave the HTypeof instruction in the Hydrogen graph,
even for the special cases. We later try to remove this instruction (and any
HConstant) in the canonicalization pass, if possible. Always removing the
HTypeof during the initial graph construction is wrong if e.g. it is used in an
HSimulate.

The removals can be generalized a bit, but this will happen in a separate CL.

TEST=mjsunit/optimized-typeof.js
Review URL: http://codereview.chromium.org/8334021
http://code.google.com/p/v8/source/detail?r=9688

Added:
 /branches/bleeding_edge/test/mjsunit/optimized-typeof.js
Modified:
 /branches/bleeding_edge/src/hydrogen-instructions.cc
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/hydrogen.h

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/optimized-typeof.js Wed Oct 19 00:35:30 2011
@@ -0,0 +1,47 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function typeofDirectly() {
+  return typeof({}) === "undefined";
+}
+
+typeofDirectly();
+typeofDirectly();
+%OptimizeFunctionOnNextCall(typeofDirectly);
+typeofDirectly();
+
+function typeofViaVariable() {
+  var foo = typeof({})
+  return foo === "undefined";
+}
+
+typeofViaVariable();
+typeofViaVariable();
+%OptimizeFunctionOnNextCall(typeofViaVariable);
+typeofViaVariable();
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Tue Oct 18 04:18:55 2011 +++ /branches/bleeding_edge/src/hydrogen-instructions.cc Wed Oct 19 00:35:30 2011
@@ -785,6 +785,16 @@
   stream->Add(" == %o", *type_literal_);
   HControlInstruction::PrintDataTo(stream);
 }
+
+
+HValue* HConstant::Canonicalize() {
+  return HasNoUses() && !IsBlockEntry() ? NULL : this;
+}
+
+
+HValue* HTypeof::Canonicalize() {
+  return HasNoUses() && !IsBlockEntry() ? NULL : this;
+}


 void HTypeof::PrintDataTo(StringStream* stream) {
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Fri Oct 14 00:45:18 2011 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Wed Oct 19 00:35:30 2011
@@ -2287,6 +2287,7 @@
   }

   virtual bool EmitAtUses() { return !representation().IsDouble(); }
+  virtual HValue* Canonicalize();
   virtual void PrintDataTo(StringStream* stream);
   virtual HType CalculateInferredType();
   bool IsInteger() const { return handle_->IsSmi(); }
@@ -4159,6 +4160,7 @@
   HValue* context() { return OperandAt(0); }
   HValue* value() { return OperandAt(1); }

+  virtual HValue* Canonicalize();
   virtual void PrintDataTo(StringStream* stream);

   virtual Representation RequiredInputRepresentation(int index) {
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Tue Oct 18 04:18:55 2011
+++ /branches/bleeding_edge/src/hydrogen.cc     Wed Oct 19 00:35:30 2011
@@ -5789,36 +5789,66 @@


 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
-                                               Expression* sub_expr,
+                                               HTypeof* typeof_expr,
                                                Handle<String> check) {
-  CHECK_ALIVE(VisitForTypeOf(sub_expr));
-  HValue* value = Pop();
+ // Note: The HTypeof itself is removed during canonicalization, if possible.
+  HValue* value = typeof_expr->value();
   HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check);
   instr->set_position(expr->position());
   return ast_context()->ReturnControl(instr, expr->id());
 }


-bool HGraphBuilder::TryLiteralCompare(CompareOperation* expr) {
-  Expression *sub_expr;
-  Handle<String> check;
-  if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
-    HandleLiteralCompareTypeof(expr, sub_expr, check);
+static bool MatchLiteralCompareNil(HValue* left,
+                                   Token::Value op,
+                                   HValue* right,
+                                   Handle<Object> nil,
+                                   HValue** expr) {
+  if (left->IsConstant() &&
+      HConstant::cast(left)->handle().is_identical_to(nil) &&
+      Token::IsEqualityOp(op)) {
+    *expr = right;
     return true;
   }
-
-  if (expr->IsLiteralCompareUndefined(&sub_expr)) {
-    HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
-    return true;
-  }
-
-  if (expr->IsLiteralCompareNull(&sub_expr)) {
-    HandleLiteralCompareNil(expr, sub_expr, kNullValue);
+  return false;
+}
+
+
+static bool MatchLiteralCompareTypeof(HValue* left,
+                                      Token::Value op,
+                                      HValue* right,
+                                      HTypeof** typeof_expr,
+                                      Handle<String>* check) {
+  if (left->IsTypeof() &&
+      Token::IsEqualityOp(op) &&
+      right->IsConstant() &&
+      HConstant::cast(right)->HasStringValue()) {
+    *typeof_expr = HTypeof::cast(left);
+    *check = Handle<String>::cast(HConstant::cast(right)->handle());
     return true;
   }
-
   return false;
 }
+
+
+static bool IsLiteralCompareTypeof(HValue* left,
+                                   Token::Value op,
+                                   HValue* right,
+                                   HTypeof** typeof_expr,
+                                   Handle<String>* 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<Object> nil,
+                                HValue** expr) {
+  return MatchLiteralCompareNil(left, op, right, nil, expr) ||
+      MatchLiteralCompareNil(right, op, left, nil, expr);
+}


 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
@@ -5837,12 +5867,10 @@
     instr->set_position(expr->position());
     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();
@@ -5856,6 +5884,20 @@
   HValue* right = Pop();
   HValue* left = Pop();
   Token::Value op = expr->op();
+
+  HTypeof* typeof_expr = NULL;
+  Handle<String> 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
@@ -5945,13 +5987,11 @@


 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);
=======================================
--- /branches/bleeding_edge/src/hydrogen.h      Fri Oct 14 08:02:19 2011
+++ /branches/bleeding_edge/src/hydrogen.h      Wed Oct 19 00:35:30 2011
@@ -912,12 +912,11 @@
                                   HValue* receiver,
                                   SmallMapList* types,
                                   Handle<String> name);
-  bool TryLiteralCompare(CompareOperation* expr);
   void HandleLiteralCompareTypeof(CompareOperation* expr,
-                                  Expression* sub_expr,
+                                  HTypeof* typeof_expr,
                                   Handle<String> check);
   void HandleLiteralCompareNil(CompareOperation* expr,
-                               Expression* sub_expr,
+                               HValue* value,
                                NilValue nil);

   HStringCharCodeAt* BuildStringCharCodeAt(HValue* context,

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to