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 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 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 66 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 77 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 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 *hints = stub.hints(); 96 return true; 97 } 98 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