Merge V8 5.3.332.45.  DO NOT MERGE

Test: Manual

FPIIM-449

Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/compiler/representation-change.cc b/src/compiler/representation-change.cc
index 180355d..d1aa5af 100644
--- a/src/compiler/representation-change.cc
+++ b/src/compiler/representation-change.cc
@@ -105,46 +105,55 @@
 
 }  // namespace
 
-
 // Changes representation from {output_rep} to {use_rep}. The {truncation}
 // parameter is only used for sanity checking - if the changer cannot figure
 // out signedness for the word32->float64 conversion, then we check that the
 // uses truncate to word32 (so they do not care about signedness).
 Node* RepresentationChanger::GetRepresentationFor(
     Node* node, MachineRepresentation output_rep, Type* output_type,
-    MachineRepresentation use_rep, Truncation truncation) {
+    Node* use_node, UseInfo use_info) {
   if (output_rep == MachineRepresentation::kNone) {
     // The output representation should be set.
-    return TypeError(node, output_rep, output_type, use_rep);
+    return TypeError(node, output_rep, output_type, use_info.representation());
   }
-  if (use_rep == output_rep) {
-    // Representations are the same. That's a no-op.
-    return node;
+
+  // Handle the no-op shortcuts when no checking is necessary.
+  if (use_info.type_check() == TypeCheckKind::kNone ||
+      output_rep != MachineRepresentation::kWord32) {
+    if (use_info.representation() == output_rep) {
+      // Representations are the same. That's a no-op.
+      return node;
+    }
+    if (IsWord(use_info.representation()) && IsWord(output_rep)) {
+      // Both are words less than or equal to 32-bits.
+      // Since loads of integers from memory implicitly sign or zero extend the
+      // value to the full machine word size and stores implicitly truncate,
+      // no representation change is necessary.
+      return node;
+    }
   }
-  if (IsWord(use_rep) && IsWord(output_rep)) {
-    // Both are words less than or equal to 32-bits.
-    // Since loads of integers from memory implicitly sign or zero extend the
-    // value to the full machine word size and stores implicitly truncate,
-    // no representation change is necessary.
-    return node;
-  }
-  switch (use_rep) {
+
+  switch (use_info.representation()) {
     case MachineRepresentation::kTagged:
+      DCHECK(use_info.type_check() == TypeCheckKind::kNone);
       return GetTaggedRepresentationFor(node, output_rep, output_type);
     case MachineRepresentation::kFloat32:
+      DCHECK(use_info.type_check() == TypeCheckKind::kNone);
       return GetFloat32RepresentationFor(node, output_rep, output_type,
-                                         truncation);
+                                         use_info.truncation());
     case MachineRepresentation::kFloat64:
       return GetFloat64RepresentationFor(node, output_rep, output_type,
-                                         truncation);
+                                         use_node, use_info);
     case MachineRepresentation::kBit:
+      DCHECK(use_info.type_check() == TypeCheckKind::kNone);
       return GetBitRepresentationFor(node, output_rep, output_type);
     case MachineRepresentation::kWord8:
     case MachineRepresentation::kWord16:
     case MachineRepresentation::kWord32:
-      return GetWord32RepresentationFor(node, output_rep, output_type,
-                                        truncation);
+      return GetWord32RepresentationFor(node, output_rep, output_type, use_node,
+                                        use_info);
     case MachineRepresentation::kWord64:
+      DCHECK(use_info.type_check() == TypeCheckKind::kNone);
       return GetWord64RepresentationFor(node, output_rep, output_type);
     case MachineRepresentation::kSimd128:  // Fall through.
       // TODO(bbudge) Handle conversions between tagged and untagged.
@@ -156,7 +165,6 @@
   return nullptr;
 }
 
-
 Node* RepresentationChanger::GetTaggedRepresentationFor(
     Node* node, MachineRepresentation output_rep, Type* output_type) {
   // Eagerly fold representation changes for constants.
@@ -271,8 +279,12 @@
     }
   } else if (output_rep == MachineRepresentation::kTagged) {
     if (output_type->Is(Type::NumberOrUndefined())) {
-      op = simplified()
-               ->ChangeTaggedToFloat64();  // tagged -> float64 -> float32
+      // tagged -> float64 -> float32
+      if (output_type->Is(Type::Number())) {
+        op = simplified()->ChangeTaggedToFloat64();
+      } else {
+        op = simplified()->TruncateTaggedToFloat64();
+      }
       node = jsgraph()->graph()->NewNode(op, node);
       op = machine()->TruncateFloat64ToFloat32();
     }
@@ -286,29 +298,31 @@
   return jsgraph()->graph()->NewNode(op, node);
 }
 
-
 Node* RepresentationChanger::GetFloat64RepresentationFor(
     Node* node, MachineRepresentation output_rep, Type* output_type,
-    Truncation truncation) {
+    Node* use_node, UseInfo use_info) {
   // Eagerly fold representation changes for constants.
-  switch (node->opcode()) {
-    case IrOpcode::kNumberConstant:
-      return jsgraph()->Float64Constant(OpParameter<double>(node));
-    case IrOpcode::kInt32Constant:
-      if (output_type->Is(Type::Signed32())) {
-        int32_t value = OpParameter<int32_t>(node);
-        return jsgraph()->Float64Constant(value);
-      } else {
-        DCHECK(output_type->Is(Type::Unsigned32()));
-        uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
-        return jsgraph()->Float64Constant(static_cast<double>(value));
-      }
-    case IrOpcode::kFloat64Constant:
-      return node;  // No change necessary.
-    case IrOpcode::kFloat32Constant:
-      return jsgraph()->Float64Constant(OpParameter<float>(node));
-    default:
-      break;
+  if ((use_info.type_check() == TypeCheckKind::kNone)) {
+    // TODO(jarin) Handle checked constant conversions.
+    switch (node->opcode()) {
+      case IrOpcode::kNumberConstant:
+        return jsgraph()->Float64Constant(OpParameter<double>(node));
+      case IrOpcode::kInt32Constant:
+        if (output_type->Is(Type::Signed32())) {
+          int32_t value = OpParameter<int32_t>(node);
+          return jsgraph()->Float64Constant(value);
+        } else {
+          DCHECK(output_type->Is(Type::Unsigned32()));
+          uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
+          return jsgraph()->Float64Constant(static_cast<double>(value));
+        }
+      case IrOpcode::kFloat64Constant:
+        return node;  // No change necessary.
+      case IrOpcode::kFloat32Constant:
+        return jsgraph()->Float64Constant(OpParameter<float>(node));
+      default:
+        break;
+    }
   }
   // Select the correct X -> Float64 operator.
   const Operator* op = nullptr;
@@ -316,7 +330,7 @@
     if (output_type->Is(Type::Signed32())) {
       op = machine()->ChangeInt32ToFloat64();
     } else if (output_type->Is(Type::Unsigned32()) ||
-               truncation.TruncatesToWord32()) {
+               use_info.truncation().TruncatesToWord32()) {
       // Either the output is uint32 or the uses only care about the
       // low 32 bits (so we can pick uint32 safely).
       op = machine()->ChangeUint32ToFloat64();
@@ -328,8 +342,13 @@
     } else if (output_type->Is(Type::TaggedSigned())) {
       node = InsertChangeTaggedSignedToInt32(node);
       op = machine()->ChangeInt32ToFloat64();
-    } else if (output_type->Is(Type::NumberOrUndefined())) {
+    } else if (output_type->Is(Type::Number())) {
       op = simplified()->ChangeTaggedToFloat64();
+    } else if (output_type->Is(Type::NumberOrUndefined())) {
+      // TODO(jarin) Here we should check that truncation is Number.
+      op = simplified()->TruncateTaggedToFloat64();
+    } else if (use_info.type_check() == TypeCheckKind::kNumberOrUndefined) {
+      op = simplified()->CheckedTaggedToFloat64();
     }
   } else if (output_rep == MachineRepresentation::kFloat32) {
     op = machine()->ChangeFloat32ToFloat64();
@@ -338,29 +357,43 @@
     return TypeError(node, output_rep, output_type,
                      MachineRepresentation::kFloat64);
   }
-  return jsgraph()->graph()->NewNode(op, node);
+  return InsertConversion(node, op, use_node);
 }
 
-
 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
   return jsgraph()->Int32Constant(DoubleToInt32(value));
 }
 
 Node* RepresentationChanger::GetWord32RepresentationFor(
     Node* node, MachineRepresentation output_rep, Type* output_type,
-    Truncation truncation) {
+    Node* use_node, UseInfo use_info) {
   // Eagerly fold representation changes for constants.
   switch (node->opcode()) {
     case IrOpcode::kInt32Constant:
       return node;  // No change necessary.
-    case IrOpcode::kFloat32Constant:
-      return MakeTruncatedInt32Constant(OpParameter<float>(node));
+    case IrOpcode::kFloat32Constant: {
+      float const fv = OpParameter<float>(node);
+      if (use_info.type_check() == TypeCheckKind::kNone ||
+          (use_info.type_check() == TypeCheckKind::kSigned32 &&
+           IsInt32Double(fv))) {
+        return MakeTruncatedInt32Constant(fv);
+      }
+      break;
+    }
     case IrOpcode::kNumberConstant:
-    case IrOpcode::kFloat64Constant:
-      return MakeTruncatedInt32Constant(OpParameter<double>(node));
+    case IrOpcode::kFloat64Constant: {
+      double const fv = OpParameter<double>(node);
+      if (use_info.type_check() == TypeCheckKind::kNone ||
+          (use_info.type_check() == TypeCheckKind::kSigned32 &&
+           IsInt32Double(fv))) {
+        return MakeTruncatedInt32Constant(fv);
+      }
+      break;
+    }
     default:
       break;
   }
+
   // Select the correct X -> Word32 operator.
   const Operator* op = nullptr;
   if (output_rep == MachineRepresentation::kBit) {
@@ -370,8 +403,10 @@
       op = machine()->ChangeFloat64ToUint32();
     } else if (output_type->Is(Type::Signed32())) {
       op = machine()->ChangeFloat64ToInt32();
-    } else if (truncation.TruncatesToWord32()) {
+    } else if (use_info.truncation().TruncatesToWord32()) {
       op = machine()->TruncateFloat64ToWord32();
+    } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
+      op = simplified()->CheckedFloat64ToInt32();
     }
   } else if (output_rep == MachineRepresentation::kFloat32) {
     node = InsertChangeFloat32ToFloat64(node);  // float32 -> float64 -> int32
@@ -379,8 +414,10 @@
       op = machine()->ChangeFloat64ToUint32();
     } else if (output_type->Is(Type::Signed32())) {
       op = machine()->ChangeFloat64ToInt32();
-    } else if (truncation.TruncatesToWord32()) {
+    } else if (use_info.truncation().TruncatesToWord32()) {
       op = machine()->TruncateFloat64ToWord32();
+    } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
+      op = simplified()->CheckedFloat64ToInt32();
     }
   } else if (output_rep == MachineRepresentation::kTagged) {
     if (output_type->Is(Type::TaggedSigned())) {
@@ -389,14 +426,45 @@
       op = simplified()->ChangeTaggedToUint32();
     } else if (output_type->Is(Type::Signed32())) {
       op = simplified()->ChangeTaggedToInt32();
-    } else if (truncation.TruncatesToWord32()) {
+    } else if (use_info.truncation().TruncatesToWord32()) {
       op = simplified()->TruncateTaggedToWord32();
+    } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
+      op = simplified()->CheckedTaggedToInt32();
     }
+  } else if (output_rep == MachineRepresentation::kWord32) {
+    // Only the checked case should get here, the non-checked case is
+    // handled in GetRepresentationFor.
+    DCHECK(use_info.type_check() == TypeCheckKind::kSigned32);
+    if (output_type->Is(Type::Signed32())) {
+      return node;
+    } else if (output_type->Is(Type::Unsigned32())) {
+      op = simplified()->CheckedUint32ToInt32();
+    }
+  } else if (output_rep == MachineRepresentation::kWord8 ||
+             output_rep == MachineRepresentation::kWord16) {
+    DCHECK(use_info.representation() == MachineRepresentation::kWord32);
+    DCHECK(use_info.type_check() == TypeCheckKind::kSigned32);
+    return node;
   }
+
   if (op == nullptr) {
     return TypeError(node, output_rep, output_type,
                      MachineRepresentation::kWord32);
   }
+  return InsertConversion(node, op, use_node);
+}
+
+Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
+                                              Node* use_node) {
+  if (op->ControlInputCount() > 0) {
+    // If the operator can deoptimize (which means it has control
+    // input), we need to connect it to the effect and control chains.
+    Node* effect = NodeProperties::GetEffectInput(use_node);
+    Node* control = NodeProperties::GetControlInput(use_node);
+    Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
+    NodeProperties::ReplaceEffectInput(use_node, conversion);
+    return conversion;
+  }
   return jsgraph()->graph()->NewNode(op, node);
 }
 
@@ -426,7 +494,6 @@
   return jsgraph()->graph()->NewNode(op, node);
 }
 
-
 Node* RepresentationChanger::GetWord64RepresentationFor(
     Node* node, MachineRepresentation output_rep, Type* output_type) {
   if (output_rep == MachineRepresentation::kBit) {
@@ -437,18 +504,90 @@
                    MachineRepresentation::kWord64);
 }
 
+Node* RepresentationChanger::GetCheckedWord32RepresentationFor(
+    Node* node, MachineRepresentation output_rep, Type* output_type,
+    Node* use_node, Truncation truncation, TypeCheckKind check) {
+  // TODO(jarin) Eagerly fold constants (or insert hard deopt if the constant
+  // does not pass the check).
+
+  // If the input is already Signed32 in Word32 representation, we do not
+  // have to do anything. (We could fold this into the big if below, but
+  // it feels nicer to have the shortcut return first).
+  if (output_rep == MachineRepresentation::kWord32 ||
+      output_type->Is(Type::Signed32())) {
+    return node;
+  }
+
+  // Select the correct X -> Word32 operator.
+  const Operator* op = nullptr;
+  if (output_rep == MachineRepresentation::kWord32) {
+    if (output_type->Is(Type::Unsigned32())) {
+      op = simplified()->CheckedUint32ToInt32();
+    }
+  } else if (output_rep == MachineRepresentation::kBit) {
+    return node;  // Sloppy comparison -> word32
+  } else if (output_rep == MachineRepresentation::kFloat64) {
+    if (output_type->Is(Type::Unsigned32())) {
+      op = machine()->ChangeFloat64ToUint32();
+    } else if (output_type->Is(Type::Signed32())) {
+      op = machine()->ChangeFloat64ToInt32();
+    } else if (truncation.TruncatesToWord32()) {
+      op = machine()->TruncateFloat64ToWord32();
+    } else if (check == TypeCheckKind::kSigned32) {
+      op = simplified()->CheckedFloat64ToInt32();
+    }
+  } else if (output_rep == MachineRepresentation::kFloat32) {
+    node = InsertChangeFloat32ToFloat64(node);  // float32 -> float64 -> int32
+    if (output_type->Is(Type::Unsigned32())) {
+      op = machine()->ChangeFloat64ToUint32();
+    } else if (output_type->Is(Type::Signed32())) {
+      op = machine()->ChangeFloat64ToInt32();
+    } else if (truncation.TruncatesToWord32()) {
+      op = machine()->TruncateFloat64ToWord32();
+    } else if (check == TypeCheckKind::kSigned32) {
+      op = simplified()->CheckedFloat64ToInt32();
+    }
+  } else if (output_rep == MachineRepresentation::kTagged) {
+    if (output_type->Is(Type::TaggedSigned())) {
+      op = simplified()->ChangeTaggedSignedToInt32();
+    } else if (output_type->Is(Type::Unsigned32())) {
+      op = simplified()->ChangeTaggedToUint32();
+    } else if (output_type->Is(Type::Signed32())) {
+      op = simplified()->ChangeTaggedToInt32();
+    } else if (truncation.TruncatesToWord32()) {
+      op = simplified()->TruncateTaggedToWord32();
+    } else if (check == TypeCheckKind::kSigned32) {
+      op = simplified()->CheckedTaggedToInt32();
+    }
+  }
+  if (op == nullptr) {
+    return TypeError(node, output_rep, output_type,
+                     MachineRepresentation::kWord32);
+  }
+  if (op->ControlInputCount() > 0) {
+    // If the operator can deoptimize (which means it has control
+    // input), we need to connect it to the effect and control chains.
+    UNIMPLEMENTED();
+  }
+  return jsgraph()->graph()->NewNode(op, node);
+}
 
 const Operator* RepresentationChanger::Int32OperatorFor(
     IrOpcode::Value opcode) {
   switch (opcode) {
+    case IrOpcode::kSpeculativeNumberAdd:  // Fall through.
     case IrOpcode::kNumberAdd:
       return machine()->Int32Add();
+    case IrOpcode::kSpeculativeNumberSubtract:  // Fall through.
     case IrOpcode::kNumberSubtract:
       return machine()->Int32Sub();
+    case IrOpcode::kSpeculativeNumberMultiply:
     case IrOpcode::kNumberMultiply:
       return machine()->Int32Mul();
+    case IrOpcode::kSpeculativeNumberDivide:
     case IrOpcode::kNumberDivide:
       return machine()->Int32Div();
+    case IrOpcode::kSpeculativeNumberModulus:
     case IrOpcode::kNumberModulus:
       return machine()->Int32Mod();
     case IrOpcode::kNumberBitwiseOr:
@@ -458,10 +597,13 @@
     case IrOpcode::kNumberBitwiseAnd:
       return machine()->Word32And();
     case IrOpcode::kNumberEqual:
+    case IrOpcode::kSpeculativeNumberEqual:
       return machine()->Word32Equal();
     case IrOpcode::kNumberLessThan:
+    case IrOpcode::kSpeculativeNumberLessThan:
       return machine()->Int32LessThan();
     case IrOpcode::kNumberLessThanOrEqual:
+    case IrOpcode::kSpeculativeNumberLessThanOrEqual:
       return machine()->Int32LessThanOrEqual();
     default:
       UNREACHABLE();
@@ -469,6 +611,18 @@
   }
 }
 
+const Operator* RepresentationChanger::Int32OverflowOperatorFor(
+    IrOpcode::Value opcode) {
+  switch (opcode) {
+    case IrOpcode::kSpeculativeNumberAdd:  // Fall through.
+      return simplified()->CheckedInt32Add();
+    case IrOpcode::kSpeculativeNumberSubtract:  // Fall through.
+      return simplified()->CheckedInt32Sub();
+    default:
+      UNREACHABLE();
+      return nullptr;
+  }
+}
 
 const Operator* RepresentationChanger::Uint32OperatorFor(
     IrOpcode::Value opcode) {
@@ -477,17 +631,23 @@
       return machine()->Int32Add();
     case IrOpcode::kNumberSubtract:
       return machine()->Int32Sub();
+    case IrOpcode::kSpeculativeNumberMultiply:
     case IrOpcode::kNumberMultiply:
       return machine()->Int32Mul();
+    case IrOpcode::kSpeculativeNumberDivide:
     case IrOpcode::kNumberDivide:
       return machine()->Uint32Div();
+    case IrOpcode::kSpeculativeNumberModulus:
     case IrOpcode::kNumberModulus:
       return machine()->Uint32Mod();
     case IrOpcode::kNumberEqual:
+    case IrOpcode::kSpeculativeNumberEqual:
       return machine()->Word32Equal();
     case IrOpcode::kNumberLessThan:
+    case IrOpcode::kSpeculativeNumberLessThan:
       return machine()->Uint32LessThan();
     case IrOpcode::kNumberLessThanOrEqual:
+    case IrOpcode::kSpeculativeNumberLessThanOrEqual:
       return machine()->Uint32LessThanOrEqual();
     case IrOpcode::kNumberClz32:
       return machine()->Word32Clz();
@@ -503,22 +663,64 @@
 const Operator* RepresentationChanger::Float64OperatorFor(
     IrOpcode::Value opcode) {
   switch (opcode) {
+    case IrOpcode::kSpeculativeNumberAdd:
     case IrOpcode::kNumberAdd:
       return machine()->Float64Add();
+    case IrOpcode::kSpeculativeNumberSubtract:
     case IrOpcode::kNumberSubtract:
       return machine()->Float64Sub();
+    case IrOpcode::kSpeculativeNumberMultiply:
     case IrOpcode::kNumberMultiply:
       return machine()->Float64Mul();
+    case IrOpcode::kSpeculativeNumberDivide:
     case IrOpcode::kNumberDivide:
       return machine()->Float64Div();
+    case IrOpcode::kSpeculativeNumberModulus:
     case IrOpcode::kNumberModulus:
       return machine()->Float64Mod();
     case IrOpcode::kNumberEqual:
+    case IrOpcode::kSpeculativeNumberEqual:
       return machine()->Float64Equal();
     case IrOpcode::kNumberLessThan:
+    case IrOpcode::kSpeculativeNumberLessThan:
       return machine()->Float64LessThan();
     case IrOpcode::kNumberLessThanOrEqual:
+    case IrOpcode::kSpeculativeNumberLessThanOrEqual:
       return machine()->Float64LessThanOrEqual();
+    case IrOpcode::kNumberAbs:
+      return machine()->Float64Abs();
+    case IrOpcode::kNumberAtan:
+      return machine()->Float64Atan();
+    case IrOpcode::kNumberAtan2:
+      return machine()->Float64Atan2();
+    case IrOpcode::kNumberCos:
+      return machine()->Float64Cos();
+    case IrOpcode::kNumberExp:
+      return machine()->Float64Exp();
+    case IrOpcode::kNumberFround:
+      return machine()->TruncateFloat64ToFloat32();
+    case IrOpcode::kNumberAtanh:
+      return machine()->Float64Atanh();
+    case IrOpcode::kNumberLog:
+      return machine()->Float64Log();
+    case IrOpcode::kNumberLog1p:
+      return machine()->Float64Log1p();
+    case IrOpcode::kNumberLog2:
+      return machine()->Float64Log2();
+    case IrOpcode::kNumberLog10:
+      return machine()->Float64Log10();
+    case IrOpcode::kNumberSin:
+      return machine()->Float64Sin();
+    case IrOpcode::kNumberTan:
+      return machine()->Float64Tan();
+    case IrOpcode::kNumberSqrt:
+      return machine()->Float64Sqrt();
+    case IrOpcode::kNumberCbrt:
+      return machine()->Float64Cbrt();
+    case IrOpcode::kNumberExpm1:
+      return machine()->Float64Expm1();
+    case IrOpcode::kNumberSilenceNaN:
+      return machine()->Float64SilenceNaN();
     default:
       UNREACHABLE();
       return nullptr;