Home | History | Annotate | Download | only in compiler
      1 // Copyright 2015 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/compiler/type-hint-analyzer.h"
      6 
      7 #include "src/assembler.h"
      8 #include "src/code-stubs.h"
      9 #include "src/ic/ic-state.h"
     10 #include "src/type-hints.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 namespace compiler {
     15 
     16 namespace {
     17 
     18 BinaryOperationHint ToBinaryOperationHint(Token::Value op,
     19                                           BinaryOpICState::Kind kind) {
     20   switch (kind) {
     21     case BinaryOpICState::NONE:
     22       return BinaryOperationHint::kNone;
     23     case BinaryOpICState::SMI:
     24       return BinaryOperationHint::kSignedSmall;
     25     case BinaryOpICState::INT32:
     26       return (Token::IsTruncatingBinaryOp(op) && SmiValuesAre31Bits())
     27                  ? BinaryOperationHint::kNumberOrOddball
     28                  : BinaryOperationHint::kSigned32;
     29     case BinaryOpICState::NUMBER:
     30       return BinaryOperationHint::kNumberOrOddball;
     31     case BinaryOpICState::STRING:
     32       return BinaryOperationHint::kString;
     33     case BinaryOpICState::GENERIC:
     34       return BinaryOperationHint::kAny;
     35   }
     36   UNREACHABLE();
     37   return BinaryOperationHint::kNone;
     38 }
     39 
     40 CompareOperationHint ToCompareOperationHint(Token::Value op,
     41                                             CompareICState::State state) {
     42   switch (state) {
     43     case CompareICState::UNINITIALIZED:
     44       return CompareOperationHint::kNone;
     45     case CompareICState::SMI:
     46       return CompareOperationHint::kSignedSmall;
     47     case CompareICState::NUMBER:
     48       return Token::IsOrderedRelationalCompareOp(op)
     49                  ? CompareOperationHint::kNumberOrOddball
     50                  : CompareOperationHint::kNumber;
     51     case CompareICState::STRING:
     52     case CompareICState::INTERNALIZED_STRING:
     53     case CompareICState::UNIQUE_NAME:
     54     case CompareICState::RECEIVER:
     55     case CompareICState::KNOWN_RECEIVER:
     56     case CompareICState::BOOLEAN:
     57     case CompareICState::GENERIC:
     58       return CompareOperationHint::kAny;
     59   }
     60   UNREACHABLE();
     61   return CompareOperationHint::kNone;
     62 }
     63 
     64 }  // namespace
     65 
     66 bool TypeHintAnalysis::GetBinaryOperationHint(TypeFeedbackId id,
     67                                               BinaryOperationHint* hint) const {
     68   auto i = infos_.find(id);
     69   if (i == infos_.end()) return false;
     70   Handle<Code> code = i->second;
     71   DCHECK_EQ(Code::BINARY_OP_IC, code->kind());
     72   BinaryOpICState state(code->GetIsolate(), code->extra_ic_state());
     73   *hint = ToBinaryOperationHint(state.op(), state.kind());
     74   return true;
     75 }
     76 
     77 bool TypeHintAnalysis::GetCompareOperationHint(
     78     TypeFeedbackId id, CompareOperationHint* hint) const {
     79   auto i = infos_.find(id);
     80   if (i == infos_.end()) return false;
     81   Handle<Code> code = i->second;
     82   DCHECK_EQ(Code::COMPARE_IC, code->kind());
     83   CompareICStub stub(code->stub_key(), code->GetIsolate());
     84   *hint = ToCompareOperationHint(stub.op(), stub.state());
     85   return true;
     86 }
     87 
     88 bool TypeHintAnalysis::GetToBooleanHints(TypeFeedbackId id,
     89                                          ToBooleanHints* hints) const {
     90   auto i = infos_.find(id);
     91   if (i == infos_.end()) return false;
     92   Handle<Code> code = i->second;
     93   DCHECK_EQ(Code::TO_BOOLEAN_IC, code->kind());
     94   ToBooleanICStub stub(code->GetIsolate(), code->extra_ic_state());
     95   *hints = stub.hints();
     96   return true;
     97 }
     98 
     99 TypeHintAnalysis* TypeHintAnalyzer::Analyze(Handle<Code> code) {
    100   DisallowHeapAllocation no_gc;
    101   TypeHintAnalysis::Infos infos(zone());
    102   Isolate* const isolate = code->GetIsolate();
    103   int const mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
    104   for (RelocIterator it(*code, mask); !it.done(); it.next()) {
    105     RelocInfo* rinfo = it.rinfo();
    106     Address target_address = rinfo->target_address();
    107     Code* target = Code::GetCodeFromTargetAddress(target_address);
    108     switch (target->kind()) {
    109       case Code::BINARY_OP_IC:
    110       case Code::COMPARE_IC:
    111       case Code::TO_BOOLEAN_IC: {
    112         // Add this feedback to the {infos}.
    113         TypeFeedbackId id(static_cast<unsigned>(rinfo->data()));
    114         infos.insert(std::make_pair(id, handle(target, isolate)));
    115         break;
    116       }
    117       default:
    118         // Ignore the remaining code objects.
    119         break;
    120     }
    121   }
    122   return new (zone()) TypeHintAnalysis(infos, zone());
    123 }
    124 
    125 
    126 }  // namespace compiler
    127 }  // namespace internal
    128 }  // namespace v8
    129