17d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Copyright 2014 the V8 project authors. All rights reserved.
27d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be
37d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// found in the LICENSE file.
47d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org#include "src/compiler/access-builder.h"
67d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/graph-inl.h"
7a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org#include "src/compiler/js-builtin-reducer.h"
87d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/js-typed-lowering.h"
97d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/node-aux-data-inl.h"
107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/node-properties-inl.h"
117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/types.h"
127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace v8 {
147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace internal {
157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace compiler {
167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// TODO(turbofan): js-typed-lowering improvements possible
187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// - immediately put in type bounds for all new nodes
197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// - relax effects from generic but not-side-effecting operations
207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// - relax effects for ToNumber(mixed)
217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Relax the effects of {node} by immediately replacing effect uses of {node}
247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// with the effect input to {node}.
257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// TODO(turbofan): replace the effect input to {node} with {graph->start()}.
267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// TODO(titzer): move into a GraphEditor?
27e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.orgstatic void RelaxEffects(Node* node) {
28e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org  NodeProperties::ReplaceWithValue(node, node, NULL);
29e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org}
307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
322c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgJSTypedLowering::~JSTypedLowering() {}
332c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
342c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgReduction JSTypedLowering::ReplaceEagerly(Node* old, Node* node) {
36e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org  NodeProperties::ReplaceWithValue(old, node, node);
372c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  return Changed(node);
387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// A helper class to simplify the process of reducing a single binop node with a
427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// JSOperator. This class manages the rewriting of context, control, and effect
437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// dependencies during lowering of a binop and contains numerous helper
447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// functions for matching the types of inputs to an operation.
457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass JSBinopReduction {
467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  JSBinopReduction(JSTypedLowering* lowering, Node* node)
487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : lowering_(lowering),
497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        node_(node),
507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        left_type_(NodeProperties::GetBounds(node->InputAt(0)).upper),
517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        right_type_(NodeProperties::GetBounds(node->InputAt(1)).upper) {}
527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void ConvertInputsToNumber() {
547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    node_->ReplaceInput(0, ConvertToNumber(left()));
557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    node_->ReplaceInput(1, ConvertToNumber(right()));
567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void ConvertInputsToInt32(bool left_signed, bool right_signed) {
597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    node_->ReplaceInput(0, ConvertToI32(left_signed, left()));
607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    node_->ReplaceInput(1, ConvertToI32(right_signed, right()));
617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void ConvertInputsToString() {
647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    node_->ReplaceInput(0, ConvertToString(left()));
657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    node_->ReplaceInput(1, ConvertToString(right()));
667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Convert inputs for bitwise shift operation (ES5 spec 11.7).
697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void ConvertInputsForShift(bool left_signed) {
707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    node_->ReplaceInput(0, ConvertToI32(left_signed, left()));
717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Node* rnum = ConvertToI32(false, right());
727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    node_->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rnum,
737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                            jsgraph()->Int32Constant(0x1F)));
747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void SwapInputs() {
777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Node* l = left();
787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Node* r = right();
797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    node_->ReplaceInput(0, r);
807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    node_->ReplaceInput(1, l);
817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    std::swap(left_type_, right_type_);
827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Remove all effect and control inputs and outputs to this node and change
857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // to the pure operator {op}, possibly inserting a boolean inversion.
862c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  Reduction ChangeToPureOperator(const Operator* op, bool invert = false) {
87e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(0, OperatorProperties::GetEffectInputCount(op));
88e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(false, OperatorProperties::HasContextInput(op));
89e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(0, OperatorProperties::GetControlInputCount(op));
90e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(2, OperatorProperties::GetValueInputCount(op));
917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Remove the effects from the node, if any, and update its effect usages.
937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (OperatorProperties::GetEffectInputCount(node_->op()) > 0) {
947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      RelaxEffects(node_);
957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Remove the inputs corresponding to context, effect, and control.
977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    NodeProperties::RemoveNonValueInputs(node_);
987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Finally, update the operator to the new one.
997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    node_->set_op(op);
1007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (invert) {
1027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // Insert an boolean not to invert the value.
1037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Node* value = graph()->NewNode(simplified()->BooleanNot(), node_);
1047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      node_->ReplaceUses(value);
1057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // Note: ReplaceUses() smashes all uses, so smash it back here.
1067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      value->ReplaceInput(0, node_);
1077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return lowering_->ReplaceWith(value);
1087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
1097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return lowering_->Changed(node_);
1107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool OneInputIs(Type* t) { return left_type_->Is(t) || right_type_->Is(t); }
1137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool BothInputsAre(Type* t) {
1157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return left_type_->Is(t) && right_type_->Is(t);
1167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool OneInputCannotBe(Type* t) {
1197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return !left_type_->Maybe(t) || !right_type_->Maybe(t);
1207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool NeitherInputCanBe(Type* t) {
1237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return !left_type_->Maybe(t) && !right_type_->Maybe(t);
1247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* effect() { return NodeProperties::GetEffectInput(node_); }
1277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* control() { return NodeProperties::GetControlInput(node_); }
1287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* context() { return NodeProperties::GetContextInput(node_); }
1297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* left() { return NodeProperties::GetValueInput(node_, 0); }
1307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* right() { return NodeProperties::GetValueInput(node_, 1); }
1317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Type* left_type() { return left_type_; }
1327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Type* right_type() { return right_type_; }
1337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  SimplifiedOperatorBuilder* simplified() { return lowering_->simplified(); }
1357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Graph* graph() { return lowering_->graph(); }
1367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  JSGraph* jsgraph() { return lowering_->jsgraph(); }
1377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  JSOperatorBuilder* javascript() { return lowering_->javascript(); }
1387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  MachineOperatorBuilder* machine() { return lowering_->machine(); }
1397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
1417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  JSTypedLowering* lowering_;  // The containing lowering instance.
1427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* node_;                 // The original node.
1437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Type* left_type_;            // Cache of the left input's type.
1447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Type* right_type_;           // Cache of the right input's type.
1457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* ConvertToString(Node* node) {
1477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Avoid introducing too many eager ToString() operations.
1487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Reduction reduced = lowering_->ReduceJSToStringInput(node);
1497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (reduced.Changed()) return reduced.replacement();
1507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Node* n = graph()->NewNode(javascript()->ToString(), node, context(),
1517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               effect(), control());
1527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    update_effect(n);
1537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return n;
1547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* ConvertToNumber(Node* node) {
1577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Avoid introducing too many eager ToNumber() operations.
1587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Reduction reduced = lowering_->ReduceJSToNumberInput(node);
1597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (reduced.Changed()) return reduced.replacement();
1607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Node* n = graph()->NewNode(javascript()->ToNumber(), node, context(),
1617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                               effect(), control());
1627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    update_effect(n);
1637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return n;
1647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Try to narrowing a double or number operation to an Int32 operation.
1677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool TryNarrowingToI32(Type* type, Node* node) {
1687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    switch (node->opcode()) {
1697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kFloat64Add:
1707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kNumberAdd: {
1717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        JSBinopReduction r(lowering_, node);
1727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        if (r.BothInputsAre(Type::Integral32())) {
1737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          node->set_op(lowering_->machine()->Int32Add());
1747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          // TODO(titzer): narrow bounds instead of overwriting.
1757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          NodeProperties::SetBounds(node, Bounds(type));
1767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          return true;
1777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        }
1787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
1797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kFloat64Sub:
1807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kNumberSubtract: {
1817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        JSBinopReduction r(lowering_, node);
1827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        if (r.BothInputsAre(Type::Integral32())) {
1837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          node->set_op(lowering_->machine()->Int32Sub());
1847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          // TODO(titzer): narrow bounds instead of overwriting.
1857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          NodeProperties::SetBounds(node, Bounds(type));
1867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          return true;
1877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        }
1887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
1897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      default:
1907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return false;
1917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
1927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Node* ConvertToI32(bool is_signed, Node* node) {
1957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Type* type = is_signed ? Type::Signed32() : Type::Unsigned32();
1967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (node->OwnedBy(node_)) {
1977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // If this node {node_} has the only edge to {node}, then try narrowing
1987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // its operation to an Int32 add or subtract.
1997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (TryNarrowingToI32(type, node)) return node;
2007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else {
2017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // Otherwise, {node} has multiple uses. Leave it as is and let the
2027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // further lowering passes deal with it, which use a full backwards
2037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // fixpoint.
2047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
2057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Avoid introducing too many eager NumberToXXnt32() operations.
2077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    node = ConvertToNumber(node);
2087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Type* input_type = NodeProperties::GetBounds(node).upper;
2097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (input_type->Is(type)) return node;  // already in the value range.
2117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2122c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    const Operator* op = is_signed ? simplified()->NumberToInt32()
2132c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                                   : simplified()->NumberToUint32();
2147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Node* n = graph()->NewNode(op, node);
2157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return n;
2167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void update_effect(Node* effect) {
2197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    NodeProperties::ReplaceEffectInput(node_, effect);
2207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
2227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgReduction JSTypedLowering::ReduceJSAdd(Node* node) {
2257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  JSBinopReduction r(this, node);
2266313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  if (r.BothInputsAre(Type::Number())) {
2276313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    // JSAdd(x:number, y:number) => NumberAdd(x, y)
2286313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    return r.ChangeToPureOperator(simplified()->NumberAdd());
22921d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  }
2306313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone());
2316313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  if (r.NeitherInputCanBe(maybe_string)) {
2326313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
2337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    r.ConvertInputsToNumber();
2347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(simplified()->NumberAdd());
2357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
236d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org#if 0
237d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  // TODO(turbofan): Lowering of StringAdd is disabled for now because:
238d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  //   a) The inserted ToString operation screws up valueOf vs. toString order.
239d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  //   b) Deoptimization at ToString doesn't have corresponding bailout id.
240d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  //   c) Our current StringAddStub is actually non-pure and requires context.
2416313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  if (r.OneInputIs(Type::String())) {
2426313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    // JSAdd(x:string, y:string) => StringAdd(x, y)
2436313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    // JSAdd(x:string, y) => StringAdd(x, ToString(y))
2446313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    // JSAdd(x, y:string) => StringAdd(ToString(x), y)
2456313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    r.ConvertInputsToString();
2466313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    return r.ChangeToPureOperator(simplified()->StringAdd());
2476313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  }
248d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org#endif
2497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return NoChange();
2507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2532c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgReduction JSTypedLowering::ReduceNumberBinop(Node* node,
2542c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                                             const Operator* numberOp) {
2557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  JSBinopReduction r(this, node);
2567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.OneInputIs(Type::Primitive())) {
2577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // If at least one input is a primitive, then insert appropriate conversions
2587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // to number and reduce this operator to the given numeric one.
2597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(turbofan): make this heuristic configurable for code size.
2607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    r.ConvertInputsToNumber();
2617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(numberOp);
2627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): relax/remove the effects of this operator in other cases.
2647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return NoChange();
2657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgReduction JSTypedLowering::ReduceI32Binop(Node* node, bool left_signed,
2692c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                                          bool right_signed,
2702c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                                          const Operator* intOp) {
2717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  JSBinopReduction r(this, node);
2727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(titzer): some Smi bitwise operations don't really require going
2737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // all the way to int32, which can save tagging/untagging for some operations
2747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // on some platforms.
2757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): make this heuristic configurable for code size.
2767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  r.ConvertInputsToInt32(left_signed, right_signed);
2777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return r.ChangeToPureOperator(intOp);
2787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgReduction JSTypedLowering::ReduceI32Shift(Node* node, bool left_signed,
2822c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                                          const Operator* shift_op) {
2837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  JSBinopReduction r(this, node);
2847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  r.ConvertInputsForShift(left_signed);
2857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return r.ChangeToPureOperator(shift_op);
2867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
2877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgReduction JSTypedLowering::ReduceJSComparison(Node* node) {
2907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  JSBinopReduction r(this, node);
2917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.BothInputsAre(Type::String())) {
2927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // If both inputs are definitely strings, perform a string comparison.
2932c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    const Operator* stringOp;
2947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    switch (node->opcode()) {
2957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kJSLessThan:
2967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        stringOp = simplified()->StringLessThan();
2977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        break;
2987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kJSGreaterThan:
2997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        stringOp = simplified()->StringLessThan();
3007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        r.SwapInputs();  // a > b => b < a
3017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        break;
3027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kJSLessThanOrEqual:
3037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        stringOp = simplified()->StringLessThanOrEqual();
3047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        break;
3057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kJSGreaterThanOrEqual:
3067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        stringOp = simplified()->StringLessThanOrEqual();
3077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        r.SwapInputs();  // a >= b => b <= a
3087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        break;
3097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      default:
3107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return NoChange();
3117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
3127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(stringOp);
313d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  }
314d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  Type* maybe_string = Type::Union(Type::String(), Type::Receiver(), zone());
315d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  if (r.OneInputCannotBe(maybe_string)) {
3167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // If one input cannot be a string, then emit a number comparison.
3172c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    const Operator* less_than;
3182c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    const Operator* less_than_or_equal;
3197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (r.BothInputsAre(Type::Unsigned32())) {
3207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      less_than = machine()->Uint32LessThan();
3217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      less_than_or_equal = machine()->Uint32LessThanOrEqual();
3227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else if (r.BothInputsAre(Type::Signed32())) {
3237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      less_than = machine()->Int32LessThan();
3247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      less_than_or_equal = machine()->Int32LessThanOrEqual();
3257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    } else {
3267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // TODO(turbofan): mixed signed/unsigned int32 comparisons.
3277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      r.ConvertInputsToNumber();
3287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      less_than = simplified()->NumberLessThan();
3297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      less_than_or_equal = simplified()->NumberLessThanOrEqual();
3307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
3312c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    const Operator* comparison;
3327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    switch (node->opcode()) {
3337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kJSLessThan:
3347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        comparison = less_than;
3357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        break;
3367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kJSGreaterThan:
3377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        comparison = less_than;
3387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        r.SwapInputs();  // a > b => b < a
3397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        break;
3407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kJSLessThanOrEqual:
3417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        comparison = less_than_or_equal;
3427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        break;
3437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      case IrOpcode::kJSGreaterThanOrEqual:
3447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        comparison = less_than_or_equal;
3457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        r.SwapInputs();  // a >= b => b <= a
3467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        break;
3477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      default:
3487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return NoChange();
3497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
3507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(comparison);
3517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): relax/remove effects of this operator in other cases.
3537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return NoChange();  // Keep a generic comparison.
3547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgReduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
3587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  JSBinopReduction r(this, node);
3597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.BothInputsAre(Type::Number())) {
3617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
3627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.BothInputsAre(Type::String())) {
3647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
3657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.BothInputsAre(Type::Receiver())) {
3677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(
3687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        simplified()->ReferenceEqual(Type::Receiver()), invert);
3697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): js-typed-lowering of Equal(undefined)
3717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): js-typed-lowering of Equal(null)
3727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): js-typed-lowering of Equal(boolean)
3737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return NoChange();
3747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
3757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgReduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
3787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  JSBinopReduction r(this, node);
3797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.left() == r.right()) {
3807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // x === x is always true if x != NaN
3817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (!r.left_type()->Maybe(Type::NaN())) {
3827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReplaceEagerly(node, invert ? jsgraph()->FalseConstant()
3837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                         : jsgraph()->TrueConstant());
3847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
3857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (!r.left_type()->Maybe(r.right_type())) {
3877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Type intersection is empty; === is always false unless both
3887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // inputs could be strings (one internalized and one not).
3897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (r.OneInputCannotBe(Type::String())) {
3907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReplaceEagerly(node, invert ? jsgraph()->TrueConstant()
3917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                         : jsgraph()->FalseConstant());
3927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
3937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.OneInputIs(Type::Undefined())) {
3957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(
3967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        simplified()->ReferenceEqual(Type::Undefined()), invert);
3977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.OneInputIs(Type::Null())) {
3997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Null()),
4007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                  invert);
4017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.OneInputIs(Type::Boolean())) {
4037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Boolean()),
4047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                  invert);
4057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.OneInputIs(Type::Object())) {
4077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Object()),
4087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                  invert);
4097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.OneInputIs(Type::Receiver())) {
4117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(
4127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        simplified()->ReferenceEqual(Type::Receiver()), invert);
4137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.BothInputsAre(Type::String())) {
4157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
4167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (r.BothInputsAre(Type::Number())) {
4187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
4197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): js-typed-lowering of StrictEqual(mixed types)
4217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return NoChange();
4227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgReduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
4267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input->opcode() == IrOpcode::kJSToNumber) {
4277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Recursively try to reduce the input first.
4287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Reduction result = ReduceJSToNumberInput(input->InputAt(0));
4297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (result.Changed()) {
4307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      RelaxEffects(input);
4317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return result;
4327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
4337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return Changed(input);  // JSToNumber(JSToNumber(x)) => JSToNumber(x)
4347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Type* input_type = NodeProperties::GetBounds(input).upper;
4367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input_type->Is(Type::Number())) {
4376313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    // JSToNumber(x:number) => x
4387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return Changed(input);
4397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input_type->Is(Type::Undefined())) {
4417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // JSToNumber(undefined) => #NaN
4427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return ReplaceWith(jsgraph()->NaNConstant());
4437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input_type->Is(Type::Null())) {
4457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // JSToNumber(null) => #0
4467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return ReplaceWith(jsgraph()->ZeroConstant());
4477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
448a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  if (input_type->Is(Type::Boolean())) {
449a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    // JSToNumber(x:boolean) => BooleanToNumber(x)
450a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    return ReplaceWith(
451a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        graph()->NewNode(simplified()->BooleanToNumber(), input));
452a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  }
4536313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  // TODO(turbofan): js-typed-lowering of ToNumber(x:string)
4547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return NoChange();
4557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgReduction JSTypedLowering::ReduceJSToStringInput(Node* input) {
4597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input->opcode() == IrOpcode::kJSToString) {
4607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Recursively try to reduce the input first.
4617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Reduction result = ReduceJSToStringInput(input->InputAt(0));
4627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (result.Changed()) {
4637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      RelaxEffects(input);
4647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return result;
4657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
4667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return Changed(input);  // JSToString(JSToString(x)) => JSToString(x)
4677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Type* input_type = NodeProperties::GetBounds(input).upper;
4697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input_type->Is(Type::String())) {
4706313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    return Changed(input);  // JSToString(x:string) => x
4717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input_type->Is(Type::Undefined())) {
4737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return ReplaceWith(jsgraph()->HeapConstant(
4747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        graph()->zone()->isolate()->factory()->undefined_string()));
4757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input_type->Is(Type::Null())) {
4777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return ReplaceWith(jsgraph()->HeapConstant(
4787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        graph()->zone()->isolate()->factory()->null_string()));
4797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4806313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  // TODO(turbofan): js-typed-lowering of ToString(x:boolean)
4816313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  // TODO(turbofan): js-typed-lowering of ToString(x:number)
4827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return NoChange();
4837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
4847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgReduction JSTypedLowering::ReduceJSToBooleanInput(Node* input) {
4877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input->opcode() == IrOpcode::kJSToBoolean) {
4887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // Recursively try to reduce the input first.
4897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Reduction result = ReduceJSToBooleanInput(input->InputAt(0));
4907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (result.Changed()) {
4917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      RelaxEffects(input);
4927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return result;
4937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
4947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return Changed(input);  // JSToBoolean(JSToBoolean(x)) => JSToBoolean(x)
4957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Type* input_type = NodeProperties::GetBounds(input).upper;
4977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input_type->Is(Type::Boolean())) {
4986313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    return Changed(input);  // JSToBoolean(x:boolean) => x
4997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input_type->Is(Type::Undefined())) {
5017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // JSToBoolean(undefined) => #false
5027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return ReplaceWith(jsgraph()->FalseConstant());
5037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input_type->Is(Type::Null())) {
5057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // JSToBoolean(null) => #false
5067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return ReplaceWith(jsgraph()->FalseConstant());
5077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input_type->Is(Type::DetectableReceiver())) {
5096313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    // JSToBoolean(x:detectable) => #true
5107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return ReplaceWith(jsgraph()->TrueConstant());
5117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (input_type->Is(Type::Undetectable())) {
5136313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    // JSToBoolean(x:undetectable) => #false
5147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return ReplaceWith(jsgraph()->FalseConstant());
5157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5166313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  if (input_type->Is(Type::OrderedNumber())) {
5176313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    // JSToBoolean(x:ordered-number) => BooleanNot(NumberEqual(x, #0))
5187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Node* cmp = graph()->NewNode(simplified()->NumberEqual(), input,
5197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                 jsgraph()->ZeroConstant());
5207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Node* inv = graph()->NewNode(simplified()->BooleanNot(), cmp);
5219aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    return ReplaceWith(inv);
5227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(turbofan): js-typed-lowering of ToBoolean(string)
5247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return NoChange();
5257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
5267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5282c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgReduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
529c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org  Node* key = NodeProperties::GetValueInput(node, 1);
530c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org  Node* base = NodeProperties::GetValueInput(node, 0);
531c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org  Type* key_type = NodeProperties::GetBounds(key).upper;
532c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org  Type* base_type = NodeProperties::GetBounds(base).upper;
533c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org  // TODO(mstarzinger): This lowering is not correct if:
534c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org  //   a) The typed array turns external (i.e. MaterializeArrayBuffer)
535c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org  //   b) The typed array or it's buffer is neutered.
536c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org  //   c) The index is out of bounds.
537c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org  if (base_type->IsConstant() && key_type->Is(Type::Integral32()) &&
538c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org      base_type->AsConstant()->Value()->IsJSTypedArray()) {
539c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    // JSLoadProperty(typed-array, int32)
540c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    JSTypedArray* array = JSTypedArray::cast(*base_type->AsConstant()->Value());
541c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    ElementsKind elements_kind = array->map()->elements_kind();
542c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    ExternalArrayType type = array->type();
543b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    uint32_t length;
544b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    CHECK(array->length()->ToUint32(&length));
545c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    ElementAccess element_access;
546c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    Node* elements = graph()->NewNode(
547c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org        simplified()->LoadField(AccessBuilder::ForJSObjectElements()), base,
548c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org        NodeProperties::GetEffectInput(node));
549c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    if (IsExternalArrayElementsKind(elements_kind)) {
550c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org      elements = graph()->NewNode(
551c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org          simplified()->LoadField(AccessBuilder::ForExternalArrayPointer()),
552c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org          elements, NodeProperties::GetEffectInput(node));
553c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org      element_access = AccessBuilder::ForTypedArrayElement(type, true);
554c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    } else {
555c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org      DCHECK(IsFixedTypedArrayElementsKind(elements_kind));
556c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org      element_access = AccessBuilder::ForTypedArrayElement(type, false);
557c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    }
558c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    Node* value =
559c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org        graph()->NewNode(simplified()->LoadElement(element_access), elements,
560b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org                         key, jsgraph()->Uint32Constant(length),
561b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org                         NodeProperties::GetEffectInput(node));
562c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    return ReplaceEagerly(node, value);
563c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org  }
564c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org  return NoChange();
565c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org}
566c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org
567c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org
5682c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgReduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
5692c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  Node* key = NodeProperties::GetValueInput(node, 1);
5702c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  Node* base = NodeProperties::GetValueInput(node, 0);
5712c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  Node* value = NodeProperties::GetValueInput(node, 2);
5722c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  Type* key_type = NodeProperties::GetBounds(key).upper;
5732c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  Type* base_type = NodeProperties::GetBounds(base).upper;
5742c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // TODO(mstarzinger): This lowering is not correct if:
5752c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  //   a) The typed array turns external (i.e. MaterializeArrayBuffer)
5762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  //   b) The typed array or it's buffer is neutered.
5772c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  if (key_type->Is(Type::Integral32()) && base_type->IsConstant() &&
5782c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      base_type->AsConstant()->Value()->IsJSTypedArray()) {
5792c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    // JSStoreProperty(typed-array, int32, value)
5802c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    JSTypedArray* array = JSTypedArray::cast(*base_type->AsConstant()->Value());
5812c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    ElementsKind elements_kind = array->map()->elements_kind();
5822c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    ExternalArrayType type = array->type();
58306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    uint32_t length;
58406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    CHECK(array->length()->ToUint32(&length));
5852c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    ElementAccess element_access;
5862c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    Node* elements = graph()->NewNode(
5872c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org        simplified()->LoadField(AccessBuilder::ForJSObjectElements()), base,
5882c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org        NodeProperties::GetEffectInput(node));
5892c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (IsExternalArrayElementsKind(elements_kind)) {
5902c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      elements = graph()->NewNode(
5912c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org          simplified()->LoadField(AccessBuilder::ForExternalArrayPointer()),
5922c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org          elements, NodeProperties::GetEffectInput(node));
5932c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      element_access = AccessBuilder::ForTypedArrayElement(type, true);
5942c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    } else {
5952c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      DCHECK(IsFixedTypedArrayElementsKind(elements_kind));
5962c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      element_access = AccessBuilder::ForTypedArrayElement(type, false);
5972c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    }
59806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
59906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Node* check = graph()->NewNode(machine()->Uint32LessThan(), key,
60006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                   jsgraph()->Uint32Constant(length));
60106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Node* branch = graph()->NewNode(common()->Branch(), check,
60206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                    NodeProperties::GetControlInput(node));
60306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
60406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
605b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    Node* store =
606b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org        graph()->NewNode(simplified()->StoreElement(element_access), elements,
607b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org                         key, jsgraph()->Uint32Constant(length), value,
608b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org                         NodeProperties::GetEffectInput(node), if_true);
60906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
61006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
61106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
61206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
61306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Node* phi = graph()->NewNode(common()->EffectPhi(2), store,
61406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                 NodeProperties::GetEffectInput(node), merge);
61506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
61606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    return ReplaceWith(phi);
6172c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  }
6182c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  return NoChange();
6192c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org}
6202c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
6212c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
6227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgstatic Reduction ReplaceWithReduction(Node* node, Reduction reduction) {
6237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  if (reduction.Changed()) {
624e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org    NodeProperties::ReplaceWithValue(node, reduction.replacement());
6257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return reduction;
6267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return Reducer::NoChange();
6287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
6297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgReduction JSTypedLowering::Reduce(Node* node) {
6327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  switch (node->opcode()) {
6337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSEqual:
6347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceJSEqual(node, false);
6357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSNotEqual:
6367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceJSEqual(node, true);
6377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSStrictEqual:
6387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceJSStrictEqual(node, false);
6397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSStrictNotEqual:
6407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceJSStrictEqual(node, true);
6417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSLessThan:         // fall through
6427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSGreaterThan:      // fall through
6437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSLessThanOrEqual:  // fall through
6447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSGreaterThanOrEqual:
6457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceJSComparison(node);
6467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSBitwiseOr:
6477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceI32Binop(node, true, true, machine()->Word32Or());
6487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSBitwiseXor:
6497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceI32Binop(node, true, true, machine()->Word32Xor());
6507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSBitwiseAnd:
6517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceI32Binop(node, true, true, machine()->Word32And());
6527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSShiftLeft:
6537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceI32Shift(node, true, machine()->Word32Shl());
6547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSShiftRight:
6557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceI32Shift(node, true, machine()->Word32Sar());
6567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSShiftRightLogical:
6577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceI32Shift(node, false, machine()->Word32Shr());
6587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSAdd:
6597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceJSAdd(node);
6607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSSubtract:
6617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceNumberBinop(node, simplified()->NumberSubtract());
6627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSMultiply:
6637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceNumberBinop(node, simplified()->NumberMultiply());
6647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSDivide:
6657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceNumberBinop(node, simplified()->NumberDivide());
6667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSModulus:
6677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReduceNumberBinop(node, simplified()->NumberModulus());
6687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSUnaryNot: {
6697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Reduction result = ReduceJSToBooleanInput(node->InputAt(0));
6707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Node* value;
6717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      if (result.Changed()) {
6726313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org        // JSUnaryNot(x:boolean) => BooleanNot(x)
6737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        value =
6747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org            graph()->NewNode(simplified()->BooleanNot(), result.replacement());
675e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org        NodeProperties::ReplaceWithValue(node, value);
6767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        return Changed(value);
6777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      } else {
678ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org        // JSUnaryNot(x) => BooleanNot(JSToBoolean(x))
6797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        value = graph()->NewNode(simplified()->BooleanNot(), node);
6807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        node->set_op(javascript()->ToBoolean());
681e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org        NodeProperties::ReplaceWithValue(node, value, node);
6827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        // Note: ReplaceUses() smashes all uses, so smash it back here.
6837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        value->ReplaceInput(0, node);
684ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org        return Changed(node);
6857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      }
6867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
6877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSToBoolean:
6887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReplaceWithReduction(node,
6897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                  ReduceJSToBooleanInput(node->InputAt(0)));
6907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSToNumber:
6917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReplaceWithReduction(node,
6927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                  ReduceJSToNumberInput(node->InputAt(0)));
6937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    case IrOpcode::kJSToString:
6947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      return ReplaceWithReduction(node,
6957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                  ReduceJSToStringInput(node->InputAt(0)));
696c6509d2e0fb825426296fbc357cf89f2c77ff434machenbach@chromium.org    case IrOpcode::kJSLoadProperty:
6972c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      return ReduceJSLoadProperty(node);
6982c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    case IrOpcode::kJSStoreProperty:
6992c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      return ReduceJSStoreProperty(node);
700a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    case IrOpcode::kJSCallFunction:
701a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      return JSBuiltinReducer(jsgraph()).Reduce(node);
7027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    default:
7037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      break;
7047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
7057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  return NoChange();
7067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}
7072c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
7082c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org}  // namespace compiler
7092c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org}  // namespace internal
7102c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org}  // namespace v8
711