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/compiler/type-hints.h"
     10 #include "src/ic/ic-state.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 namespace compiler {
     15 
     16 namespace {
     17 
     18 // TODO(bmeurer): This detour via types is ugly.
     19 BinaryOperationHints::Hint ToBinaryOperationHint(Type* type) {
     20   if (type->Is(Type::None())) return BinaryOperationHints::kNone;
     21   if (type->Is(Type::SignedSmall())) return BinaryOperationHints::kSignedSmall;
     22   if (type->Is(Type::Signed32())) return BinaryOperationHints::kSigned32;
     23   if (type->Is(Type::Number())) return BinaryOperationHints::kNumberOrUndefined;
     24   if (type->Is(Type::String())) return BinaryOperationHints::kString;
     25   return BinaryOperationHints::kAny;
     26 }
     27 
     28 CompareOperationHints::Hint ToCompareOperationHint(
     29     CompareICState::State state) {
     30   switch (state) {
     31     case CompareICState::UNINITIALIZED:
     32       return CompareOperationHints::kNone;
     33     case CompareICState::BOOLEAN:
     34       return CompareOperationHints::kBoolean;
     35     case CompareICState::SMI:
     36       return CompareOperationHints::kSignedSmall;
     37     case CompareICState::NUMBER:
     38       return CompareOperationHints::kNumber;
     39     case CompareICState::STRING:
     40       return CompareOperationHints::kString;
     41     case CompareICState::INTERNALIZED_STRING:
     42       return CompareOperationHints::kInternalizedString;
     43     case CompareICState::UNIQUE_NAME:
     44       return CompareOperationHints::kUniqueName;
     45     case CompareICState::RECEIVER:
     46     case CompareICState::KNOWN_RECEIVER:
     47       return CompareOperationHints::kReceiver;
     48     case CompareICState::GENERIC:
     49       return CompareOperationHints::kAny;
     50   }
     51   UNREACHABLE();
     52   return CompareOperationHints::kAny;
     53 }
     54 
     55 }  // namespace
     56 
     57 bool TypeHintAnalysis::GetBinaryOperationHints(
     58     TypeFeedbackId id, BinaryOperationHints* hints) const {
     59   auto i = infos_.find(id);
     60   if (i == infos_.end()) return false;
     61   Handle<Code> code = i->second;
     62   DCHECK_EQ(Code::BINARY_OP_IC, code->kind());
     63   BinaryOpICState state(code->GetIsolate(), code->extra_ic_state());
     64   *hints = BinaryOperationHints(ToBinaryOperationHint(state.GetLeftType()),
     65                                 ToBinaryOperationHint(state.GetRightType()),
     66                                 ToBinaryOperationHint(state.GetResultType()));
     67   return true;
     68 }
     69 
     70 bool TypeHintAnalysis::GetCompareOperationHints(
     71     TypeFeedbackId id, CompareOperationHints* hints) const {
     72   auto i = infos_.find(id);
     73   if (i == infos_.end()) return false;
     74   Handle<Code> code = i->second;
     75   DCHECK_EQ(Code::COMPARE_IC, code->kind());
     76 
     77   Handle<Map> map;
     78   Map* raw_map = code->FindFirstMap();
     79   if (raw_map != nullptr) Map::TryUpdate(handle(raw_map)).ToHandle(&map);
     80 
     81   CompareICStub stub(code->stub_key(), code->GetIsolate());
     82   *hints = CompareOperationHints(ToCompareOperationHint(stub.left()),
     83                                  ToCompareOperationHint(stub.right()),
     84                                  ToCompareOperationHint(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 // TODO(bmeurer): Replace ToBooleanICStub::Types with ToBooleanHints.
     96 #define ASSERT_COMPATIBLE(NAME, Name)         \
     97   STATIC_ASSERT(1 << ToBooleanICStub::NAME == \
     98                 static_cast<int>(ToBooleanHint::k##Name))
     99   ASSERT_COMPATIBLE(UNDEFINED, Undefined);
    100   ASSERT_COMPATIBLE(BOOLEAN, Boolean);
    101   ASSERT_COMPATIBLE(NULL_TYPE, Null);
    102   ASSERT_COMPATIBLE(SMI, SmallInteger);
    103   ASSERT_COMPATIBLE(SPEC_OBJECT, Receiver);
    104   ASSERT_COMPATIBLE(STRING, String);
    105   ASSERT_COMPATIBLE(SYMBOL, Symbol);
    106   ASSERT_COMPATIBLE(HEAP_NUMBER, HeapNumber);
    107   ASSERT_COMPATIBLE(SIMD_VALUE, SimdValue);
    108 #undef ASSERT_COMPATIBLE
    109   *hints = ToBooleanHints(stub.types().ToIntegral());
    110   return true;
    111 }
    112 
    113 TypeHintAnalysis* TypeHintAnalyzer::Analyze(Handle<Code> code) {
    114   DisallowHeapAllocation no_gc;
    115   TypeHintAnalysis::Infos infos(zone());
    116   Isolate* const isolate = code->GetIsolate();
    117   int const mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
    118   for (RelocIterator it(*code, mask); !it.done(); it.next()) {
    119     RelocInfo* rinfo = it.rinfo();
    120     Address target_address = rinfo->target_address();
    121     Code* target = Code::GetCodeFromTargetAddress(target_address);
    122     switch (target->kind()) {
    123       case Code::BINARY_OP_IC:
    124       case Code::COMPARE_IC:
    125       case Code::TO_BOOLEAN_IC: {
    126         // Add this feedback to the {infos}.
    127         TypeFeedbackId id(static_cast<unsigned>(rinfo->data()));
    128         infos.insert(std::make_pair(id, handle(target, isolate)));
    129         break;
    130       }
    131       default:
    132         // Ignore the remaining code objects.
    133         break;
    134     }
    135   }
    136   return new (zone()) TypeHintAnalysis(infos, zone());
    137 }
    138 
    139 }  // namespace compiler
    140 }  // namespace internal
    141 }  // namespace v8
    142