| Index: src/compiler/common-operator.cc | 
| diff --git a/src/compiler/common-operator.cc b/src/compiler/common-operator.cc | 
| index b1a9d760603b16ae53b6075868cf671967d79854..f63c073c2c5c1aab55fa3fe903f82fdfa939cf99 100644 | 
| --- a/src/compiler/common-operator.cc | 
| +++ b/src/compiler/common-operator.cc | 
| @@ -35,10 +35,14 @@ BranchHint BranchHintOf(const Operator* const op) { | 
| return OpParameter<BranchHint>(op); | 
| } | 
|  | 
| +DeoptimizeReason DeoptimizeReasonOf(Operator const* const op) { | 
| +  DCHECK(op->opcode() == IrOpcode::kDeoptimizeIf || | 
| +         op->opcode() == IrOpcode::kDeoptimizeUnless); | 
| +  return OpParameter<DeoptimizeReason>(op); | 
| +} | 
|  | 
| size_t hash_value(DeoptimizeKind kind) { return static_cast<size_t>(kind); } | 
|  | 
| - | 
| std::ostream& operator<<(std::ostream& os, DeoptimizeKind kind) { | 
| switch (kind) { | 
| case DeoptimizeKind::kEager: | 
| @@ -50,12 +54,26 @@ std::ostream& operator<<(std::ostream& os, DeoptimizeKind kind) { | 
| return os; | 
| } | 
|  | 
| +bool operator==(DeoptimizeParameters lhs, DeoptimizeParameters rhs) { | 
| +  return lhs.kind() == rhs.kind() && lhs.reason() == rhs.reason(); | 
| +} | 
|  | 
| -DeoptimizeKind DeoptimizeKindOf(const Operator* const op) { | 
| -  DCHECK_EQ(IrOpcode::kDeoptimize, op->opcode()); | 
| -  return OpParameter<DeoptimizeKind>(op); | 
| +bool operator!=(DeoptimizeParameters lhs, DeoptimizeParameters rhs) { | 
| +  return !(lhs == rhs); | 
| } | 
|  | 
| +size_t hash_value(DeoptimizeParameters p) { | 
| +  return base::hash_combine(p.kind(), p.reason()); | 
| +} | 
| + | 
| +std::ostream& operator<<(std::ostream& os, DeoptimizeParameters p) { | 
| +  return os << p.kind() << ":" << p.reason(); | 
| +} | 
| + | 
| +DeoptimizeParameters const& DeoptimizeParametersOf(Operator const* const op) { | 
| +  DCHECK_EQ(IrOpcode::kDeoptimize, op->opcode()); | 
| +  return OpParameter<DeoptimizeParameters>(op); | 
| +} | 
|  | 
| size_t hash_value(IfExceptionHint hint) { return static_cast<size_t>(hint); } | 
|  | 
| @@ -203,8 +221,6 @@ std::ostream& operator<<(std::ostream& os, | 
|  | 
| #define CACHED_OP_LIST(V)                                    \ | 
| V(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1)             \ | 
| -  V(DeoptimizeIf, Operator::kFoldable, 2, 1, 1, 0, 1, 1)     \ | 
| -  V(DeoptimizeUnless, Operator::kFoldable, 2, 1, 1, 0, 1, 1) \ | 
| V(IfTrue, Operator::kKontrol, 0, 0, 1, 0, 0, 1)            \ | 
| V(IfFalse, Operator::kKontrol, 0, 0, 1, 0, 0, 1)           \ | 
| V(IfSuccess, Operator::kKontrol, 0, 0, 1, 0, 0, 1)         \ | 
| @@ -320,18 +336,6 @@ struct CommonOperatorGlobalCache final { | 
| CACHED_OP_LIST(CACHED) | 
| #undef CACHED | 
|  | 
| -  template <DeoptimizeKind kKind> | 
| -  struct DeoptimizeOperator final : public Operator1<DeoptimizeKind> { | 
| -    DeoptimizeOperator() | 
| -        : Operator1<DeoptimizeKind>(                      // -- | 
| -              IrOpcode::kDeoptimize, Operator::kNoThrow,  // opcode | 
| -              "Deoptimize",                               // name | 
| -              1, 1, 1, 0, 0, 1,                           // counts | 
| -              kKind) {}                                   // parameter | 
| -  }; | 
| -  DeoptimizeOperator<DeoptimizeKind::kEager> kDeoptimizeEagerOperator; | 
| -  DeoptimizeOperator<DeoptimizeKind::kSoft> kDeoptimizeSoftOperator; | 
| - | 
| template <IfExceptionHint kCaughtLocally> | 
| struct IfExceptionOperator final : public Operator1<IfExceptionHint> { | 
| IfExceptionOperator() | 
| @@ -563,19 +567,39 @@ const Operator* CommonOperatorBuilder::Branch(BranchHint hint) { | 
| return nullptr; | 
| } | 
|  | 
| - | 
| -const Operator* CommonOperatorBuilder::Deoptimize(DeoptimizeKind kind) { | 
| -  switch (kind) { | 
| -    case DeoptimizeKind::kEager: | 
| -      return &cache_.kDeoptimizeEagerOperator; | 
| -    case DeoptimizeKind::kSoft: | 
| -      return &cache_.kDeoptimizeSoftOperator; | 
| -  } | 
| -  UNREACHABLE(); | 
| -  return nullptr; | 
| +const Operator* CommonOperatorBuilder::Deoptimize(DeoptimizeKind kind, | 
| +                                                  DeoptimizeReason reason) { | 
| +  // TODO(turbofan): Cache the most common versions of this. | 
| +  DeoptimizeParameters parameter(kind, reason); | 
| +  return new (zone()) Operator1<DeoptimizeParameters>(  // -- | 
| +      IrOpcode::kDeoptimize,                            // opcodes | 
| +      Operator::kFoldable | Operator::kNoThrow,         // properties | 
| +      "Deoptimize",                                     // name | 
| +      1, 1, 1, 0, 0, 1,                                 // counts | 
| +      parameter);                                       // parameter | 
| +} | 
| + | 
| +const Operator* CommonOperatorBuilder::DeoptimizeIf(DeoptimizeReason reason) { | 
| +  // TODO(turbofan): Cache the most common versions of this. | 
| +  return new (zone()) Operator1<DeoptimizeReason>(  // -- | 
| +      IrOpcode::kDeoptimizeIf,                      // opcode | 
| +      Operator::kFoldable | Operator::kNoThrow,     // properties | 
| +      "DeoptimizeIf",                               // name | 
| +      2, 1, 1, 0, 1, 1,                             // counts | 
| +      reason);                                      // parameter | 
| +} | 
| + | 
| +const Operator* CommonOperatorBuilder::DeoptimizeUnless( | 
| +    DeoptimizeReason reason) { | 
| +  // TODO(turbofan): Cache the most common versions of this. | 
| +  return new (zone()) Operator1<DeoptimizeReason>(  // -- | 
| +      IrOpcode::kDeoptimizeUnless,                  // opcode | 
| +      Operator::kFoldable | Operator::kNoThrow,     // properties | 
| +      "DeoptimizeUnless",                           // name | 
| +      2, 1, 1, 0, 1, 1,                             // counts | 
| +      reason);                                      // parameter | 
| } | 
|  | 
| - | 
| const Operator* CommonOperatorBuilder::IfException(IfExceptionHint hint) { | 
| switch (hint) { | 
| case IfExceptionHint::kLocallyCaught: | 
|  |