Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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. |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 19 | BinaryOperationHints::Hint ToBinaryOperationHint(Type* type) { |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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; |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 23 | if (type->Is(Type::Number())) return BinaryOperationHints::kNumberOrUndefined; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 24 | if (type->Is(Type::String())) return BinaryOperationHints::kString; |
| 25 | return BinaryOperationHints::kAny; |
| 26 | } |
| 27 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 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 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 54 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 55 | } // namespace |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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()); |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 64 | *hints = BinaryOperationHints(ToBinaryOperationHint(state.GetLeftType()), |
| 65 | ToBinaryOperationHint(state.GetRightType()), |
| 66 | ToBinaryOperationHint(state.GetResultType())); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 67 | return true; |
| 68 | } |
| 69 | |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 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 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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()); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 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 == \ |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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: |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 124 | case Code::COMPARE_IC: |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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 | } |
Ben Murdoch | 61f157c | 2016-09-16 13:49:30 +0100 | [diff] [blame] | 136 | return new (zone()) TypeHintAnalysis(infos, zone()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 137 | } |
| 138 | |
| 139 | } // namespace compiler |
| 140 | } // namespace internal |
| 141 | } // namespace v8 |