• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ToBinaryOperationHint(Token::Value op,BinaryOpICState::Kind kind)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 
ToCompareOperationHint(Token::Value op,CompareICState::State state)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 
GetBinaryOperationHint(TypeFeedbackId id,BinaryOperationHint * hint) const66 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 
GetCompareOperationHint(TypeFeedbackId id,CompareOperationHint * hint) const77 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 
GetToBooleanHints(TypeFeedbackId id,ToBooleanHints * hints) const88 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 
Analyze(Handle<Code> code)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