| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/ic/ic.h" | 7 #include "src/ic/ic.h" |
| 8 #include "src/ic/ic-state.h" | 8 #include "src/ic/ic-state.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 | 38 |
| 39 // static | 39 // static |
| 40 STATIC_CONST_MEMBER_DEFINITION const int BinaryOpICState::FIRST_TOKEN; | 40 STATIC_CONST_MEMBER_DEFINITION const int BinaryOpICState::FIRST_TOKEN; |
| 41 | 41 |
| 42 | 42 |
| 43 // static | 43 // static |
| 44 STATIC_CONST_MEMBER_DEFINITION const int BinaryOpICState::LAST_TOKEN; | 44 STATIC_CONST_MEMBER_DEFINITION const int BinaryOpICState::LAST_TOKEN; |
| 45 | 45 |
| 46 | 46 |
| 47 BinaryOpICState::BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state) | 47 BinaryOpICState::BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state) |
| 48 : fixed_right_arg_(Nothing<int>()), isolate_(isolate) { | 48 : fixed_right_arg_( |
| 49 HasFixedRightArgField::decode(extra_ic_state) |
| 50 ? Just(1 << FixedRightArgValueField::decode(extra_ic_state)) |
| 51 : Nothing<int>()), |
| 52 isolate_(isolate) { |
| 49 op_ = | 53 op_ = |
| 50 static_cast<Token::Value>(FIRST_TOKEN + OpField::decode(extra_ic_state)); | 54 static_cast<Token::Value>(FIRST_TOKEN + OpField::decode(extra_ic_state)); |
| 51 fixed_right_arg_ = | |
| 52 Maybe<int>(HasFixedRightArgField::decode(extra_ic_state), | |
| 53 1 << FixedRightArgValueField::decode(extra_ic_state)); | |
| 54 left_kind_ = LeftKindField::decode(extra_ic_state); | 55 left_kind_ = LeftKindField::decode(extra_ic_state); |
| 55 if (fixed_right_arg_.has_value) { | 56 right_kind_ = fixed_right_arg_.IsJust() |
| 56 right_kind_ = Smi::IsValid(fixed_right_arg_.value) ? SMI : INT32; | 57 ? (Smi::IsValid(fixed_right_arg_.FromJust()) ? SMI : INT32) |
| 57 } else { | 58 : RightKindField::decode(extra_ic_state); |
| 58 right_kind_ = RightKindField::decode(extra_ic_state); | |
| 59 } | |
| 60 result_kind_ = ResultKindField::decode(extra_ic_state); | 59 result_kind_ = ResultKindField::decode(extra_ic_state); |
| 61 DCHECK_LE(FIRST_TOKEN, op_); | 60 DCHECK_LE(FIRST_TOKEN, op_); |
| 62 DCHECK_LE(op_, LAST_TOKEN); | 61 DCHECK_LE(op_, LAST_TOKEN); |
| 63 } | 62 } |
| 64 | 63 |
| 65 | 64 |
| 66 ExtraICState BinaryOpICState::GetExtraICState() const { | 65 ExtraICState BinaryOpICState::GetExtraICState() const { |
| 67 ExtraICState extra_ic_state = | 66 ExtraICState extra_ic_state = |
| 68 OpField::encode(op_ - FIRST_TOKEN) | LeftKindField::encode(left_kind_) | | 67 OpField::encode(op_ - FIRST_TOKEN) | LeftKindField::encode(left_kind_) | |
| 69 ResultKindField::encode(result_kind_) | | 68 ResultKindField::encode(result_kind_) | |
| 70 HasFixedRightArgField::encode(fixed_right_arg_.has_value); | 69 HasFixedRightArgField::encode(fixed_right_arg_.IsJust()); |
| 71 if (fixed_right_arg_.has_value) { | 70 if (fixed_right_arg_.IsJust()) { |
| 72 extra_ic_state = FixedRightArgValueField::update( | 71 extra_ic_state = FixedRightArgValueField::update( |
| 73 extra_ic_state, WhichPowerOf2(fixed_right_arg_.value)); | 72 extra_ic_state, WhichPowerOf2(fixed_right_arg_.FromJust())); |
| 74 } else { | 73 } else { |
| 75 extra_ic_state = RightKindField::update(extra_ic_state, right_kind_); | 74 extra_ic_state = RightKindField::update(extra_ic_state, right_kind_); |
| 76 } | 75 } |
| 77 return extra_ic_state; | 76 return extra_ic_state; |
| 78 } | 77 } |
| 79 | 78 |
| 80 | 79 |
| 81 // static | 80 // static |
| 82 void BinaryOpICState::GenerateAheadOfTime( | 81 void BinaryOpICState::GenerateAheadOfTime( |
| 83 Isolate* isolate, void (*Generate)(Isolate*, const BinaryOpICState&)) { | 82 Isolate* isolate, void (*Generate)(Isolate*, const BinaryOpICState&)) { |
| 84 // TODO(olivf) We should investigate why adding stubs to the snapshot is so | 83 // TODO(olivf) We should investigate why adding stubs to the snapshot is so |
| 85 // expensive at runtime. When solved we should be able to add most binops to | 84 // expensive at runtime. When solved we should be able to add most binops to |
| 86 // the snapshot instead of hand-picking them. | 85 // the snapshot instead of hand-picking them. |
| 87 // Generated list of commonly used stubs | 86 // Generated list of commonly used stubs |
| 88 #define GENERATE(op, left_kind, right_kind, result_kind) \ | 87 #define GENERATE(op, left_kind, right_kind, result_kind) \ |
| 89 do { \ | 88 do { \ |
| 90 BinaryOpICState state(isolate, op); \ | 89 BinaryOpICState state(isolate, op); \ |
| 91 state.left_kind_ = left_kind; \ | 90 state.left_kind_ = left_kind; \ |
| 92 state.fixed_right_arg_.has_value = false; \ | 91 state.fixed_right_arg_ = Nothing<int>(); \ |
| 93 state.right_kind_ = right_kind; \ | 92 state.right_kind_ = right_kind; \ |
| 94 state.result_kind_ = result_kind; \ | 93 state.result_kind_ = result_kind; \ |
| 95 Generate(isolate, state); \ | 94 Generate(isolate, state); \ |
| 96 } while (false) | 95 } while (false) |
| 97 GENERATE(Token::ADD, INT32, INT32, INT32); | 96 GENERATE(Token::ADD, INT32, INT32, INT32); |
| 98 GENERATE(Token::ADD, INT32, INT32, NUMBER); | 97 GENERATE(Token::ADD, INT32, INT32, NUMBER); |
| 99 GENERATE(Token::ADD, INT32, NUMBER, NUMBER); | 98 GENERATE(Token::ADD, INT32, NUMBER, NUMBER); |
| 100 GENERATE(Token::ADD, INT32, SMI, INT32); | 99 GENERATE(Token::ADD, INT32, SMI, INT32); |
| 101 GENERATE(Token::ADD, NUMBER, INT32, NUMBER); | 100 GENERATE(Token::ADD, NUMBER, INT32, NUMBER); |
| 102 GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER); | 101 GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER); | 183 GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER); |
| 185 GENERATE(Token::SUB, NUMBER, SMI, NUMBER); | 184 GENERATE(Token::SUB, NUMBER, SMI, NUMBER); |
| 186 GENERATE(Token::SUB, SMI, INT32, INT32); | 185 GENERATE(Token::SUB, SMI, INT32, INT32); |
| 187 GENERATE(Token::SUB, SMI, NUMBER, NUMBER); | 186 GENERATE(Token::SUB, SMI, NUMBER, NUMBER); |
| 188 GENERATE(Token::SUB, SMI, SMI, SMI); | 187 GENERATE(Token::SUB, SMI, SMI, SMI); |
| 189 #undef GENERATE | 188 #undef GENERATE |
| 190 #define GENERATE(op, left_kind, fixed_right_arg_value, result_kind) \ | 189 #define GENERATE(op, left_kind, fixed_right_arg_value, result_kind) \ |
| 191 do { \ | 190 do { \ |
| 192 BinaryOpICState state(isolate, op); \ | 191 BinaryOpICState state(isolate, op); \ |
| 193 state.left_kind_ = left_kind; \ | 192 state.left_kind_ = left_kind; \ |
| 194 state.fixed_right_arg_.has_value = true; \ | 193 state.fixed_right_arg_ = Just(fixed_right_arg_value); \ |
| 195 state.fixed_right_arg_.value = fixed_right_arg_value; \ | |
| 196 state.right_kind_ = SMI; \ | 194 state.right_kind_ = SMI; \ |
| 197 state.result_kind_ = result_kind; \ | 195 state.result_kind_ = result_kind; \ |
| 198 Generate(isolate, state); \ | 196 Generate(isolate, state); \ |
| 199 } while (false) | 197 } while (false) |
| 200 GENERATE(Token::MOD, SMI, 2, SMI); | 198 GENERATE(Token::MOD, SMI, 2, SMI); |
| 201 GENERATE(Token::MOD, SMI, 4, SMI); | 199 GENERATE(Token::MOD, SMI, 4, SMI); |
| 202 GENERATE(Token::MOD, SMI, 8, SMI); | 200 GENERATE(Token::MOD, SMI, 8, SMI); |
| 203 GENERATE(Token::MOD, SMI, 16, SMI); | 201 GENERATE(Token::MOD, SMI, 16, SMI); |
| 204 GENERATE(Token::MOD, SMI, 32, SMI); | 202 GENERATE(Token::MOD, SMI, 32, SMI); |
| 205 GENERATE(Token::MOD, SMI, 2048, SMI); | 203 GENERATE(Token::MOD, SMI, 2048, SMI); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 218 } | 216 } |
| 219 DCHECK_NE(GENERIC, result_kind); | 217 DCHECK_NE(GENERIC, result_kind); |
| 220 return KindToType(result_kind, zone); | 218 return KindToType(result_kind, zone); |
| 221 } | 219 } |
| 222 | 220 |
| 223 | 221 |
| 224 std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s) { | 222 std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s) { |
| 225 os << "(" << Token::Name(s.op_); | 223 os << "(" << Token::Name(s.op_); |
| 226 if (s.CouldCreateAllocationMementos()) os << "_CreateAllocationMementos"; | 224 if (s.CouldCreateAllocationMementos()) os << "_CreateAllocationMementos"; |
| 227 os << ":" << BinaryOpICState::KindToString(s.left_kind_) << "*"; | 225 os << ":" << BinaryOpICState::KindToString(s.left_kind_) << "*"; |
| 228 if (s.fixed_right_arg_.has_value) { | 226 if (s.fixed_right_arg_.IsJust()) { |
| 229 os << s.fixed_right_arg_.value; | 227 os << s.fixed_right_arg_.FromJust(); |
| 230 } else { | 228 } else { |
| 231 os << BinaryOpICState::KindToString(s.right_kind_); | 229 os << BinaryOpICState::KindToString(s.right_kind_); |
| 232 } | 230 } |
| 233 return os << "->" << BinaryOpICState::KindToString(s.result_kind_) << ")"; | 231 return os << "->" << BinaryOpICState::KindToString(s.result_kind_) << ")"; |
| 234 } | 232 } |
| 235 | 233 |
| 236 | 234 |
| 237 void BinaryOpICState::Update(Handle<Object> left, Handle<Object> right, | 235 void BinaryOpICState::Update(Handle<Object> left, Handle<Object> right, |
| 238 Handle<Object> result) { | 236 Handle<Object> result) { |
| 239 ExtraICState old_extra_ic_state = GetExtraICState(); | 237 ExtraICState old_extra_ic_state = GetExtraICState(); |
| 240 | 238 |
| 241 left_kind_ = UpdateKind(left, left_kind_); | 239 left_kind_ = UpdateKind(left, left_kind_); |
| 242 right_kind_ = UpdateKind(right, right_kind_); | 240 right_kind_ = UpdateKind(right, right_kind_); |
| 243 | 241 |
| 244 int32_t fixed_right_arg_value = 0; | 242 int32_t fixed_right_arg_value = 0; |
| 245 bool has_fixed_right_arg = | 243 bool has_fixed_right_arg = |
| 246 op_ == Token::MOD && right->ToInt32(&fixed_right_arg_value) && | 244 op_ == Token::MOD && right->ToInt32(&fixed_right_arg_value) && |
| 247 fixed_right_arg_value > 0 && | 245 fixed_right_arg_value > 0 && |
| 248 base::bits::IsPowerOfTwo32(fixed_right_arg_value) && | 246 base::bits::IsPowerOfTwo32(fixed_right_arg_value) && |
| 249 FixedRightArgValueField::is_valid(WhichPowerOf2(fixed_right_arg_value)) && | 247 FixedRightArgValueField::is_valid(WhichPowerOf2(fixed_right_arg_value)) && |
| 250 (left_kind_ == SMI || left_kind_ == INT32) && | 248 (left_kind_ == SMI || left_kind_ == INT32) && |
| 251 (result_kind_ == NONE || !fixed_right_arg_.has_value); | 249 (result_kind_ == NONE || !fixed_right_arg_.IsJust()); |
| 252 fixed_right_arg_ = Maybe<int32_t>(has_fixed_right_arg, fixed_right_arg_value); | 250 fixed_right_arg_ = |
| 253 | 251 has_fixed_right_arg ? Just(fixed_right_arg_value) : Nothing<int32_t>(); |
| 254 result_kind_ = UpdateKind(result, result_kind_); | 252 result_kind_ = UpdateKind(result, result_kind_); |
| 255 | 253 |
| 256 if (!Token::IsTruncatingBinaryOp(op_)) { | 254 if (!Token::IsTruncatingBinaryOp(op_)) { |
| 257 Kind input_kind = Max(left_kind_, right_kind_); | 255 Kind input_kind = Max(left_kind_, right_kind_); |
| 258 if (result_kind_ < input_kind && input_kind <= NUMBER) { | 256 if (result_kind_ < input_kind && input_kind <= NUMBER) { |
| 259 result_kind_ = input_kind; | 257 result_kind_ = input_kind; |
| 260 } | 258 } |
| 261 } | 259 } |
| 262 | 260 |
| 263 // We don't want to distinguish INT32 and NUMBER for string add (because | 261 // We don't want to distinguish INT32 and NUMBER for string add (because |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 case UNIQUE_NAME: | 504 case UNIQUE_NAME: |
| 507 case OBJECT: | 505 case OBJECT: |
| 508 case GENERIC: | 506 case GENERIC: |
| 509 return GENERIC; | 507 return GENERIC; |
| 510 } | 508 } |
| 511 UNREACHABLE(); | 509 UNREACHABLE(); |
| 512 return GENERIC; // Make the compiler happy. | 510 return GENERIC; // Make the compiler happy. |
| 513 } | 511 } |
| 514 } | 512 } |
| 515 } // namespace v8::internal | 513 } // namespace v8::internal |
| OLD | NEW |