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