blob: 791aa9debee2a78a45a22f21b46ca53d3722462a [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
12namespace v8 {
13namespace internal {
14namespace compiler {
15
16namespace {
17
18// TODO(bmeurer): This detour via types is ugly.
Ben Murdoch61f157c2016-09-16 13:49:30 +010019BinaryOperationHints::Hint ToBinaryOperationHint(Type* type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020 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;
Ben Murdoch61f157c2016-09-16 13:49:30 +010023 if (type->Is(Type::Number())) return BinaryOperationHints::kNumberOrUndefined;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024 if (type->Is(Type::String())) return BinaryOperationHints::kString;
25 return BinaryOperationHints::kAny;
26}
27
Ben Murdoch61f157c2016-09-16 13:49:30 +010028CompareOperationHints::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}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054
Ben Murdoch61f157c2016-09-16 13:49:30 +010055} // namespace
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056
57bool 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());
Ben Murdoch61f157c2016-09-16 13:49:30 +010064 *hints = BinaryOperationHints(ToBinaryOperationHint(state.GetLeftType()),
65 ToBinaryOperationHint(state.GetRightType()),
66 ToBinaryOperationHint(state.GetResultType()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 return true;
68}
69
Ben Murdoch61f157c2016-09-16 13:49:30 +010070bool 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}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087
88bool 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());
Ben Murdochda12d292016-06-02 14:46:10 +010094 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 == \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113TypeHintAnalysis* 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:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100124 case Code::COMPARE_IC:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 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 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100136 return new (zone()) TypeHintAnalysis(infos, zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000137}
138
139} // namespace compiler
140} // namespace internal
141} // namespace v8