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