Home | History | Annotate | Download | only in ic
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/v8.h"
      6 
      7 #include "src/ic/ic.h"
      8 #include "src/ic/ic-state.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 
     13 void ICUtility::Clear(Isolate* isolate, Address address,
     14                       ConstantPoolArray* constant_pool) {
     15   IC::Clear(isolate, address, constant_pool);
     16 }
     17 
     18 
     19 CallICState::CallICState(ExtraICState extra_ic_state)
     20     : argc_(ArgcBits::decode(extra_ic_state)),
     21       call_type_(CallTypeBits::decode(extra_ic_state)) {}
     22 
     23 
     24 ExtraICState CallICState::GetExtraICState() const {
     25   ExtraICState extra_ic_state =
     26       ArgcBits::encode(argc_) | CallTypeBits::encode(call_type_);
     27   return extra_ic_state;
     28 }
     29 
     30 
     31 OStream& operator<<(OStream& os, const CallICState& s) {
     32   return os << "(args(" << s.arg_count() << "), "
     33             << (s.call_type() == CallICState::METHOD ? "METHOD" : "FUNCTION")
     34             << ", ";
     35 }
     36 
     37 
     38 BinaryOpICState::BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state)
     39     : isolate_(isolate) {
     40   op_ =
     41       static_cast<Token::Value>(FIRST_TOKEN + OpField::decode(extra_ic_state));
     42   mode_ = OverwriteModeField::decode(extra_ic_state);
     43   fixed_right_arg_ =
     44       Maybe<int>(HasFixedRightArgField::decode(extra_ic_state),
     45                  1 << FixedRightArgValueField::decode(extra_ic_state));
     46   left_kind_ = LeftKindField::decode(extra_ic_state);
     47   if (fixed_right_arg_.has_value) {
     48     right_kind_ = Smi::IsValid(fixed_right_arg_.value) ? SMI : INT32;
     49   } else {
     50     right_kind_ = RightKindField::decode(extra_ic_state);
     51   }
     52   result_kind_ = ResultKindField::decode(extra_ic_state);
     53   DCHECK_LE(FIRST_TOKEN, op_);
     54   DCHECK_LE(op_, LAST_TOKEN);
     55 }
     56 
     57 
     58 ExtraICState BinaryOpICState::GetExtraICState() const {
     59   ExtraICState extra_ic_state =
     60       OpField::encode(op_ - FIRST_TOKEN) | OverwriteModeField::encode(mode_) |
     61       LeftKindField::encode(left_kind_) |
     62       ResultKindField::encode(result_kind_) |
     63       HasFixedRightArgField::encode(fixed_right_arg_.has_value);
     64   if (fixed_right_arg_.has_value) {
     65     extra_ic_state = FixedRightArgValueField::update(
     66         extra_ic_state, WhichPowerOf2(fixed_right_arg_.value));
     67   } else {
     68     extra_ic_state = RightKindField::update(extra_ic_state, right_kind_);
     69   }
     70   return extra_ic_state;
     71 }
     72 
     73 
     74 // static
     75 void BinaryOpICState::GenerateAheadOfTime(
     76     Isolate* isolate, void (*Generate)(Isolate*, const BinaryOpICState&)) {
     77 // TODO(olivf) We should investigate why adding stubs to the snapshot is so
     78 // expensive at runtime. When solved we should be able to add most binops to
     79 // the snapshot instead of hand-picking them.
     80 // Generated list of commonly used stubs
     81 #define GENERATE(op, left_kind, right_kind, result_kind, mode) \
     82   do {                                                         \
     83     BinaryOpICState state(isolate, op, mode);                  \
     84     state.left_kind_ = left_kind;                              \
     85     state.fixed_right_arg_.has_value = false;                  \
     86     state.right_kind_ = right_kind;                            \
     87     state.result_kind_ = result_kind;                          \
     88     Generate(isolate, state);                                  \
     89   } while (false)
     90   GENERATE(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE);
     91   GENERATE(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT);
     92   GENERATE(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE);
     93   GENERATE(Token::ADD, INT32, INT32, NUMBER, OVERWRITE_LEFT);
     94   GENERATE(Token::ADD, INT32, NUMBER, NUMBER, NO_OVERWRITE);
     95   GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
     96   GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
     97   GENERATE(Token::ADD, INT32, SMI, INT32, NO_OVERWRITE);
     98   GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_LEFT);
     99   GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_RIGHT);
    100   GENERATE(Token::ADD, NUMBER, INT32, NUMBER, NO_OVERWRITE);
    101   GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
    102   GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT);
    103   GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
    104   GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
    105   GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
    106   GENERATE(Token::ADD, NUMBER, SMI, NUMBER, NO_OVERWRITE);
    107   GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
    108   GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
    109   GENERATE(Token::ADD, SMI, INT32, INT32, NO_OVERWRITE);
    110   GENERATE(Token::ADD, SMI, INT32, INT32, OVERWRITE_LEFT);
    111   GENERATE(Token::ADD, SMI, INT32, NUMBER, NO_OVERWRITE);
    112   GENERATE(Token::ADD, SMI, NUMBER, NUMBER, NO_OVERWRITE);
    113   GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
    114   GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
    115   GENERATE(Token::ADD, SMI, SMI, INT32, OVERWRITE_LEFT);
    116   GENERATE(Token::ADD, SMI, SMI, SMI, OVERWRITE_RIGHT);
    117   GENERATE(Token::BIT_AND, INT32, INT32, INT32, NO_OVERWRITE);
    118   GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_LEFT);
    119   GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_RIGHT);
    120   GENERATE(Token::BIT_AND, INT32, INT32, SMI, NO_OVERWRITE);
    121   GENERATE(Token::BIT_AND, INT32, INT32, SMI, OVERWRITE_RIGHT);
    122   GENERATE(Token::BIT_AND, INT32, SMI, INT32, NO_OVERWRITE);
    123   GENERATE(Token::BIT_AND, INT32, SMI, INT32, OVERWRITE_RIGHT);
    124   GENERATE(Token::BIT_AND, INT32, SMI, SMI, NO_OVERWRITE);
    125   GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_LEFT);
    126   GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_RIGHT);
    127   GENERATE(Token::BIT_AND, NUMBER, INT32, INT32, OVERWRITE_RIGHT);
    128   GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, NO_OVERWRITE);
    129   GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
    130   GENERATE(Token::BIT_AND, SMI, INT32, INT32, NO_OVERWRITE);
    131   GENERATE(Token::BIT_AND, SMI, INT32, SMI, OVERWRITE_RIGHT);
    132   GENERATE(Token::BIT_AND, SMI, NUMBER, SMI, OVERWRITE_RIGHT);
    133   GENERATE(Token::BIT_AND, SMI, SMI, SMI, NO_OVERWRITE);
    134   GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_LEFT);
    135   GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_RIGHT);
    136   GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_LEFT);
    137   GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_RIGHT);
    138   GENERATE(Token::BIT_OR, INT32, INT32, SMI, OVERWRITE_LEFT);
    139   GENERATE(Token::BIT_OR, INT32, SMI, INT32, NO_OVERWRITE);
    140   GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_LEFT);
    141   GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_RIGHT);
    142   GENERATE(Token::BIT_OR, INT32, SMI, SMI, NO_OVERWRITE);
    143   GENERATE(Token::BIT_OR, INT32, SMI, SMI, OVERWRITE_RIGHT);
    144   GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, NO_OVERWRITE);
    145   GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_LEFT);
    146   GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_RIGHT);
    147   GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, NO_OVERWRITE);
    148   GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, OVERWRITE_LEFT);
    149   GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_LEFT);
    150   GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_RIGHT);
    151   GENERATE(Token::BIT_OR, SMI, INT32, SMI, OVERWRITE_RIGHT);
    152   GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_LEFT);
    153   GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_RIGHT);
    154   GENERATE(Token::BIT_XOR, INT32, INT32, INT32, NO_OVERWRITE);
    155   GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_LEFT);
    156   GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_RIGHT);
    157   GENERATE(Token::BIT_XOR, INT32, INT32, SMI, NO_OVERWRITE);
    158   GENERATE(Token::BIT_XOR, INT32, INT32, SMI, OVERWRITE_LEFT);
    159   GENERATE(Token::BIT_XOR, INT32, NUMBER, SMI, NO_OVERWRITE);
    160   GENERATE(Token::BIT_XOR, INT32, SMI, INT32, NO_OVERWRITE);
    161   GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_LEFT);
    162   GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_RIGHT);
    163   GENERATE(Token::BIT_XOR, NUMBER, INT32, INT32, NO_OVERWRITE);
    164   GENERATE(Token::BIT_XOR, NUMBER, SMI, INT32, NO_OVERWRITE);
    165   GENERATE(Token::BIT_XOR, NUMBER, SMI, SMI, NO_OVERWRITE);
    166   GENERATE(Token::BIT_XOR, SMI, INT32, INT32, NO_OVERWRITE);
    167   GENERATE(Token::BIT_XOR, SMI, INT32, INT32, OVERWRITE_LEFT);
    168   GENERATE(Token::BIT_XOR, SMI, INT32, SMI, OVERWRITE_LEFT);
    169   GENERATE(Token::BIT_XOR, SMI, SMI, SMI, NO_OVERWRITE);
    170   GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_LEFT);
    171   GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_RIGHT);
    172   GENERATE(Token::DIV, INT32, INT32, INT32, NO_OVERWRITE);
    173   GENERATE(Token::DIV, INT32, INT32, NUMBER, NO_OVERWRITE);
    174   GENERATE(Token::DIV, INT32, NUMBER, NUMBER, NO_OVERWRITE);
    175   GENERATE(Token::DIV, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
    176   GENERATE(Token::DIV, INT32, SMI, INT32, NO_OVERWRITE);
    177   GENERATE(Token::DIV, INT32, SMI, NUMBER, NO_OVERWRITE);
    178   GENERATE(Token::DIV, NUMBER, INT32, NUMBER, NO_OVERWRITE);
    179   GENERATE(Token::DIV, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
    180   GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
    181   GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
    182   GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
    183   GENERATE(Token::DIV, NUMBER, SMI, NUMBER, NO_OVERWRITE);
    184   GENERATE(Token::DIV, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
    185   GENERATE(Token::DIV, SMI, INT32, INT32, NO_OVERWRITE);
    186   GENERATE(Token::DIV, SMI, INT32, NUMBER, NO_OVERWRITE);
    187   GENERATE(Token::DIV, SMI, INT32, NUMBER, OVERWRITE_LEFT);
    188   GENERATE(Token::DIV, SMI, NUMBER, NUMBER, NO_OVERWRITE);
    189   GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
    190   GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
    191   GENERATE(Token::DIV, SMI, SMI, NUMBER, NO_OVERWRITE);
    192   GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_LEFT);
    193   GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_RIGHT);
    194   GENERATE(Token::DIV, SMI, SMI, SMI, NO_OVERWRITE);
    195   GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_LEFT);
    196   GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_RIGHT);
    197   GENERATE(Token::MOD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
    198   GENERATE(Token::MOD, SMI, SMI, SMI, NO_OVERWRITE);
    199   GENERATE(Token::MOD, SMI, SMI, SMI, OVERWRITE_LEFT);
    200   GENERATE(Token::MUL, INT32, INT32, INT32, NO_OVERWRITE);
    201   GENERATE(Token::MUL, INT32, INT32, NUMBER, NO_OVERWRITE);
    202   GENERATE(Token::MUL, INT32, NUMBER, NUMBER, NO_OVERWRITE);
    203   GENERATE(Token::MUL, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
    204   GENERATE(Token::MUL, INT32, SMI, INT32, NO_OVERWRITE);
    205   GENERATE(Token::MUL, INT32, SMI, INT32, OVERWRITE_LEFT);
    206   GENERATE(Token::MUL, INT32, SMI, NUMBER, NO_OVERWRITE);
    207   GENERATE(Token::MUL, NUMBER, INT32, NUMBER, NO_OVERWRITE);
    208   GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
    209   GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT);
    210   GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
    211   GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
    212   GENERATE(Token::MUL, NUMBER, SMI, NUMBER, NO_OVERWRITE);
    213   GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
    214   GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
    215   GENERATE(Token::MUL, SMI, INT32, INT32, NO_OVERWRITE);
    216   GENERATE(Token::MUL, SMI, INT32, INT32, OVERWRITE_LEFT);
    217   GENERATE(Token::MUL, SMI, INT32, NUMBER, NO_OVERWRITE);
    218   GENERATE(Token::MUL, SMI, NUMBER, NUMBER, NO_OVERWRITE);
    219   GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
    220   GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
    221   GENERATE(Token::MUL, SMI, SMI, INT32, NO_OVERWRITE);
    222   GENERATE(Token::MUL, SMI, SMI, NUMBER, NO_OVERWRITE);
    223   GENERATE(Token::MUL, SMI, SMI, NUMBER, OVERWRITE_LEFT);
    224   GENERATE(Token::MUL, SMI, SMI, SMI, NO_OVERWRITE);
    225   GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_LEFT);
    226   GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_RIGHT);
    227   GENERATE(Token::SAR, INT32, SMI, INT32, OVERWRITE_RIGHT);
    228   GENERATE(Token::SAR, INT32, SMI, SMI, NO_OVERWRITE);
    229   GENERATE(Token::SAR, INT32, SMI, SMI, OVERWRITE_RIGHT);
    230   GENERATE(Token::SAR, NUMBER, SMI, SMI, NO_OVERWRITE);
    231   GENERATE(Token::SAR, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
    232   GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_LEFT);
    233   GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_RIGHT);
    234   GENERATE(Token::SHL, INT32, SMI, INT32, NO_OVERWRITE);
    235   GENERATE(Token::SHL, INT32, SMI, INT32, OVERWRITE_RIGHT);
    236   GENERATE(Token::SHL, INT32, SMI, SMI, NO_OVERWRITE);
    237   GENERATE(Token::SHL, INT32, SMI, SMI, OVERWRITE_RIGHT);
    238   GENERATE(Token::SHL, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
    239   GENERATE(Token::SHL, SMI, SMI, INT32, NO_OVERWRITE);
    240   GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_LEFT);
    241   GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_RIGHT);
    242   GENERATE(Token::SHL, SMI, SMI, SMI, NO_OVERWRITE);
    243   GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_LEFT);
    244   GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_RIGHT);
    245   GENERATE(Token::SHR, INT32, SMI, SMI, NO_OVERWRITE);
    246   GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_LEFT);
    247   GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_RIGHT);
    248   GENERATE(Token::SHR, NUMBER, SMI, SMI, NO_OVERWRITE);
    249   GENERATE(Token::SHR, NUMBER, SMI, SMI, OVERWRITE_LEFT);
    250   GENERATE(Token::SHR, NUMBER, SMI, INT32, OVERWRITE_RIGHT);
    251   GENERATE(Token::SHR, SMI, SMI, SMI, NO_OVERWRITE);
    252   GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_LEFT);
    253   GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_RIGHT);
    254   GENERATE(Token::SUB, INT32, INT32, INT32, NO_OVERWRITE);
    255   GENERATE(Token::SUB, INT32, INT32, INT32, OVERWRITE_LEFT);
    256   GENERATE(Token::SUB, INT32, NUMBER, NUMBER, NO_OVERWRITE);
    257   GENERATE(Token::SUB, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
    258   GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_LEFT);
    259   GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_RIGHT);
    260   GENERATE(Token::SUB, NUMBER, INT32, NUMBER, NO_OVERWRITE);
    261   GENERATE(Token::SUB, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
    262   GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
    263   GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
    264   GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
    265   GENERATE(Token::SUB, NUMBER, SMI, NUMBER, NO_OVERWRITE);
    266   GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
    267   GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
    268   GENERATE(Token::SUB, SMI, INT32, INT32, NO_OVERWRITE);
    269   GENERATE(Token::SUB, SMI, NUMBER, NUMBER, NO_OVERWRITE);
    270   GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
    271   GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
    272   GENERATE(Token::SUB, SMI, SMI, SMI, NO_OVERWRITE);
    273   GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_LEFT);
    274   GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_RIGHT);
    275 #undef GENERATE
    276 #define GENERATE(op, left_kind, fixed_right_arg_value, result_kind, mode) \
    277   do {                                                                    \
    278     BinaryOpICState state(isolate, op, mode);                             \
    279     state.left_kind_ = left_kind;                                         \
    280     state.fixed_right_arg_.has_value = true;                              \
    281     state.fixed_right_arg_.value = fixed_right_arg_value;                 \
    282     state.right_kind_ = SMI;                                              \
    283     state.result_kind_ = result_kind;                                     \
    284     Generate(isolate, state);                                             \
    285   } while (false)
    286   GENERATE(Token::MOD, SMI, 2, SMI, NO_OVERWRITE);
    287   GENERATE(Token::MOD, SMI, 4, SMI, NO_OVERWRITE);
    288   GENERATE(Token::MOD, SMI, 4, SMI, OVERWRITE_LEFT);
    289   GENERATE(Token::MOD, SMI, 8, SMI, NO_OVERWRITE);
    290   GENERATE(Token::MOD, SMI, 16, SMI, OVERWRITE_LEFT);
    291   GENERATE(Token::MOD, SMI, 32, SMI, NO_OVERWRITE);
    292   GENERATE(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE);
    293 #undef GENERATE
    294 }
    295 
    296 
    297 Type* BinaryOpICState::GetResultType(Zone* zone) const {
    298   Kind result_kind = result_kind_;
    299   if (HasSideEffects()) {
    300     result_kind = NONE;
    301   } else if (result_kind == GENERIC && op_ == Token::ADD) {
    302     return Type::Union(Type::Number(zone), Type::String(zone), zone);
    303   } else if (result_kind == NUMBER && op_ == Token::SHR) {
    304     return Type::Unsigned32(zone);
    305   }
    306   DCHECK_NE(GENERIC, result_kind);
    307   return KindToType(result_kind, zone);
    308 }
    309 
    310 
    311 OStream& operator<<(OStream& os, const BinaryOpICState& s) {
    312   os << "(" << Token::Name(s.op_);
    313   if (s.mode_ == OVERWRITE_LEFT)
    314     os << "_ReuseLeft";
    315   else if (s.mode_ == OVERWRITE_RIGHT)
    316     os << "_ReuseRight";
    317   if (s.CouldCreateAllocationMementos()) os << "_CreateAllocationMementos";
    318   os << ":" << BinaryOpICState::KindToString(s.left_kind_) << "*";
    319   if (s.fixed_right_arg_.has_value) {
    320     os << s.fixed_right_arg_.value;
    321   } else {
    322     os << BinaryOpICState::KindToString(s.right_kind_);
    323   }
    324   return os << "->" << BinaryOpICState::KindToString(s.result_kind_) << ")";
    325 }
    326 
    327 
    328 void BinaryOpICState::Update(Handle<Object> left, Handle<Object> right,
    329                              Handle<Object> result) {
    330   ExtraICState old_extra_ic_state = GetExtraICState();
    331 
    332   left_kind_ = UpdateKind(left, left_kind_);
    333   right_kind_ = UpdateKind(right, right_kind_);
    334 
    335   int32_t fixed_right_arg_value = 0;
    336   bool has_fixed_right_arg =
    337       op_ == Token::MOD && right->ToInt32(&fixed_right_arg_value) &&
    338       fixed_right_arg_value > 0 &&
    339       base::bits::IsPowerOfTwo32(fixed_right_arg_value) &&
    340       FixedRightArgValueField::is_valid(WhichPowerOf2(fixed_right_arg_value)) &&
    341       (left_kind_ == SMI || left_kind_ == INT32) &&
    342       (result_kind_ == NONE || !fixed_right_arg_.has_value);
    343   fixed_right_arg_ = Maybe<int32_t>(has_fixed_right_arg, fixed_right_arg_value);
    344 
    345   result_kind_ = UpdateKind(result, result_kind_);
    346 
    347   if (!Token::IsTruncatingBinaryOp(op_)) {
    348     Kind input_kind = Max(left_kind_, right_kind_);
    349     if (result_kind_ < input_kind && input_kind <= NUMBER) {
    350       result_kind_ = input_kind;
    351     }
    352   }
    353 
    354   // We don't want to distinguish INT32 and NUMBER for string add (because
    355   // NumberToString can't make use of this anyway).
    356   if (left_kind_ == STRING && right_kind_ == INT32) {
    357     DCHECK_EQ(STRING, result_kind_);
    358     DCHECK_EQ(Token::ADD, op_);
    359     right_kind_ = NUMBER;
    360   } else if (right_kind_ == STRING && left_kind_ == INT32) {
    361     DCHECK_EQ(STRING, result_kind_);
    362     DCHECK_EQ(Token::ADD, op_);
    363     left_kind_ = NUMBER;
    364   }
    365 
    366   // Reset overwrite mode unless we can actually make use of it, or may be able
    367   // to make use of it at some point in the future.
    368   if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) ||
    369       (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) ||
    370       result_kind_ > NUMBER) {
    371     mode_ = NO_OVERWRITE;
    372   }
    373 
    374   if (old_extra_ic_state == GetExtraICState()) {
    375     // Tagged operations can lead to non-truncating HChanges
    376     if (left->IsUndefined() || left->IsBoolean()) {
    377       left_kind_ = GENERIC;
    378     } else {
    379       DCHECK(right->IsUndefined() || right->IsBoolean());
    380       right_kind_ = GENERIC;
    381     }
    382   }
    383 }
    384 
    385 
    386 BinaryOpICState::Kind BinaryOpICState::UpdateKind(Handle<Object> object,
    387                                                   Kind kind) const {
    388   Kind new_kind = GENERIC;
    389   bool is_truncating = Token::IsTruncatingBinaryOp(op());
    390   if (object->IsBoolean() && is_truncating) {
    391     // Booleans will be automatically truncated by HChange.
    392     new_kind = INT32;
    393   } else if (object->IsUndefined()) {
    394     // Undefined will be automatically truncated by HChange.
    395     new_kind = is_truncating ? INT32 : NUMBER;
    396   } else if (object->IsSmi()) {
    397     new_kind = SMI;
    398   } else if (object->IsHeapNumber()) {
    399     double value = Handle<HeapNumber>::cast(object)->value();
    400     new_kind = IsInt32Double(value) ? INT32 : NUMBER;
    401   } else if (object->IsString() && op() == Token::ADD) {
    402     new_kind = STRING;
    403   }
    404   if (new_kind == INT32 && SmiValuesAre32Bits()) {
    405     new_kind = NUMBER;
    406   }
    407   if (kind != NONE && ((new_kind <= NUMBER && kind > NUMBER) ||
    408                        (new_kind > NUMBER && kind <= NUMBER))) {
    409     new_kind = GENERIC;
    410   }
    411   return Max(kind, new_kind);
    412 }
    413 
    414 
    415 // static
    416 const char* BinaryOpICState::KindToString(Kind kind) {
    417   switch (kind) {
    418     case NONE:
    419       return "None";
    420     case SMI:
    421       return "Smi";
    422     case INT32:
    423       return "Int32";
    424     case NUMBER:
    425       return "Number";
    426     case STRING:
    427       return "String";
    428     case GENERIC:
    429       return "Generic";
    430   }
    431   UNREACHABLE();
    432   return NULL;
    433 }
    434 
    435 
    436 // static
    437 Type* BinaryOpICState::KindToType(Kind kind, Zone* zone) {
    438   switch (kind) {
    439     case NONE:
    440       return Type::None(zone);
    441     case SMI:
    442       return Type::SignedSmall(zone);
    443     case INT32:
    444       return Type::Signed32(zone);
    445     case NUMBER:
    446       return Type::Number(zone);
    447     case STRING:
    448       return Type::String(zone);
    449     case GENERIC:
    450       return Type::Any(zone);
    451   }
    452   UNREACHABLE();
    453   return NULL;
    454 }
    455 
    456 
    457 const char* CompareICState::GetStateName(State state) {
    458   switch (state) {
    459     case UNINITIALIZED:
    460       return "UNINITIALIZED";
    461     case SMI:
    462       return "SMI";
    463     case NUMBER:
    464       return "NUMBER";
    465     case INTERNALIZED_STRING:
    466       return "INTERNALIZED_STRING";
    467     case STRING:
    468       return "STRING";
    469     case UNIQUE_NAME:
    470       return "UNIQUE_NAME";
    471     case OBJECT:
    472       return "OBJECT";
    473     case KNOWN_OBJECT:
    474       return "KNOWN_OBJECT";
    475     case GENERIC:
    476       return "GENERIC";
    477   }
    478   UNREACHABLE();
    479   return NULL;
    480 }
    481 
    482 
    483 Type* CompareICState::StateToType(Zone* zone, State state, Handle<Map> map) {
    484   switch (state) {
    485     case UNINITIALIZED:
    486       return Type::None(zone);
    487     case SMI:
    488       return Type::SignedSmall(zone);
    489     case NUMBER:
    490       return Type::Number(zone);
    491     case STRING:
    492       return Type::String(zone);
    493     case INTERNALIZED_STRING:
    494       return Type::InternalizedString(zone);
    495     case UNIQUE_NAME:
    496       return Type::UniqueName(zone);
    497     case OBJECT:
    498       return Type::Receiver(zone);
    499     case KNOWN_OBJECT:
    500       return map.is_null() ? Type::Receiver(zone) : Type::Class(map, zone);
    501     case GENERIC:
    502       return Type::Any(zone);
    503   }
    504   UNREACHABLE();
    505   return NULL;
    506 }
    507 
    508 
    509 CompareICState::State CompareICState::NewInputState(State old_state,
    510                                                     Handle<Object> value) {
    511   switch (old_state) {
    512     case UNINITIALIZED:
    513       if (value->IsSmi()) return SMI;
    514       if (value->IsHeapNumber()) return NUMBER;
    515       if (value->IsInternalizedString()) return INTERNALIZED_STRING;
    516       if (value->IsString()) return STRING;
    517       if (value->IsSymbol()) return UNIQUE_NAME;
    518       if (value->IsJSObject()) return OBJECT;
    519       break;
    520     case SMI:
    521       if (value->IsSmi()) return SMI;
    522       if (value->IsHeapNumber()) return NUMBER;
    523       break;
    524     case NUMBER:
    525       if (value->IsNumber()) return NUMBER;
    526       break;
    527     case INTERNALIZED_STRING:
    528       if (value->IsInternalizedString()) return INTERNALIZED_STRING;
    529       if (value->IsString()) return STRING;
    530       if (value->IsSymbol()) return UNIQUE_NAME;
    531       break;
    532     case STRING:
    533       if (value->IsString()) return STRING;
    534       break;
    535     case UNIQUE_NAME:
    536       if (value->IsUniqueName()) return UNIQUE_NAME;
    537       break;
    538     case OBJECT:
    539       if (value->IsJSObject()) return OBJECT;
    540       break;
    541     case GENERIC:
    542       break;
    543     case KNOWN_OBJECT:
    544       UNREACHABLE();
    545       break;
    546   }
    547   return GENERIC;
    548 }
    549 
    550 
    551 // static
    552 CompareICState::State CompareICState::TargetState(
    553     State old_state, State old_left, State old_right, Token::Value op,
    554     bool has_inlined_smi_code, Handle<Object> x, Handle<Object> y) {
    555   switch (old_state) {
    556     case UNINITIALIZED:
    557       if (x->IsSmi() && y->IsSmi()) return SMI;
    558       if (x->IsNumber() && y->IsNumber()) return NUMBER;
    559       if (Token::IsOrderedRelationalCompareOp(op)) {
    560         // Ordered comparisons treat undefined as NaN, so the
    561         // NUMBER stub will do the right thing.
    562         if ((x->IsNumber() && y->IsUndefined()) ||
    563             (y->IsNumber() && x->IsUndefined())) {
    564           return NUMBER;
    565         }
    566       }
    567       if (x->IsInternalizedString() && y->IsInternalizedString()) {
    568         // We compare internalized strings as plain ones if we need to determine
    569         // the order in a non-equality compare.
    570         return Token::IsEqualityOp(op) ? INTERNALIZED_STRING : STRING;
    571       }
    572       if (x->IsString() && y->IsString()) return STRING;
    573       if (!Token::IsEqualityOp(op)) return GENERIC;
    574       if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
    575       if (x->IsJSObject() && y->IsJSObject()) {
    576         if (Handle<JSObject>::cast(x)->map() ==
    577             Handle<JSObject>::cast(y)->map()) {
    578           return KNOWN_OBJECT;
    579         } else {
    580           return OBJECT;
    581         }
    582       }
    583       return GENERIC;
    584     case SMI:
    585       return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC;
    586     case INTERNALIZED_STRING:
    587       DCHECK(Token::IsEqualityOp(op));
    588       if (x->IsString() && y->IsString()) return STRING;
    589       if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
    590       return GENERIC;
    591     case NUMBER:
    592       // If the failure was due to one side changing from smi to heap number,
    593       // then keep the state (if other changed at the same time, we will get
    594       // a second miss and then go to generic).
    595       if (old_left == SMI && x->IsHeapNumber()) return NUMBER;
    596       if (old_right == SMI && y->IsHeapNumber()) return NUMBER;
    597       return GENERIC;
    598     case KNOWN_OBJECT:
    599       DCHECK(Token::IsEqualityOp(op));
    600       if (x->IsJSObject() && y->IsJSObject()) {
    601         return OBJECT;
    602       }
    603       return GENERIC;
    604     case STRING:
    605     case UNIQUE_NAME:
    606     case OBJECT:
    607     case GENERIC:
    608       return GENERIC;
    609   }
    610   UNREACHABLE();
    611   return GENERIC;  // Make the compiler happy.
    612 }
    613 }
    614 }  // namespace v8::internal
    615