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 |