OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/bootstrap.h" | 8 #include "vm/bootstrap.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/constant_propagator.h" | 10 #include "vm/constant_propagator.h" |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 } | 137 } |
138 | 138 |
139 | 139 |
140 bool Value::Equals(Value* other) const { | 140 bool Value::Equals(Value* other) const { |
141 return definition() == other->definition(); | 141 return definition() == other->definition(); |
142 } | 142 } |
143 | 143 |
144 | 144 |
145 static int OrderById(CidRange* const* a, CidRange* const* b) { | 145 static int OrderById(CidRange* const* a, CidRange* const* b) { |
146 // Negative if 'a' should sort before 'b'. | 146 // Negative if 'a' should sort before 'b'. |
147 ASSERT((*a)->cid_start == (*a)->cid_end); | 147 ASSERT((*a)->IsSingleCid()); |
148 ASSERT((*b)->cid_start == (*b)->cid_end); | 148 ASSERT((*b)->IsSingleCid()); |
149 return (*a)->cid_start - (*b)->cid_start; | 149 return (*a)->cid_start - (*b)->cid_start; |
150 } | 150 } |
151 | 151 |
152 | 152 |
153 static int OrderByFrequency(CidRange* const* a, CidRange* const* b) { | 153 static int OrderByFrequency(CidRange* const* a, CidRange* const* b) { |
154 const TargetInfo* target_info_a = static_cast<const TargetInfo*>(*a); | 154 const TargetInfo* target_info_a = static_cast<const TargetInfo*>(*a); |
155 const TargetInfo* target_info_b = static_cast<const TargetInfo*>(*b); | 155 const TargetInfo* target_info_b = static_cast<const TargetInfo*>(*b); |
156 // Negative if 'a' should sort before 'b'. | 156 // Negative if 'a' should sort before 'b'. |
157 return target_info_b->count - target_info_a->count; | 157 return target_info_b->count - target_info_a->count; |
158 } | 158 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 intptr_t max = -1; | 196 intptr_t max = -1; |
197 for (intptr_t i = 0; i < cid_ranges_.length(); ++i) { | 197 for (intptr_t i = 0; i < cid_ranges_.length(); ++i) { |
198 max = Utils::Maximum(max, cid_ranges_[i]->cid_end); | 198 max = Utils::Maximum(max, cid_ranges_[i]->cid_end); |
199 } | 199 } |
200 return max; | 200 return max; |
201 } | 201 } |
202 | 202 |
203 | 203 |
204 bool Cids::HasClassId(intptr_t cid) const { | 204 bool Cids::HasClassId(intptr_t cid) const { |
205 for (int i = 0; i < length(); i++) { | 205 for (int i = 0; i < length(); i++) { |
206 if (cid_ranges_[i]->cid_start <= cid && cid <= cid_ranges_[i]->cid_end) { | 206 if (cid_ranges_[i]->Contains(cid)) { |
207 return true; | 207 return true; |
208 } | 208 } |
209 } | 209 } |
210 return false; | 210 return false; |
211 } | 211 } |
212 | 212 |
213 | 213 |
214 Cids* Cids::CreateMonomorphic(Zone* zone, intptr_t cid) { | 214 Cids* Cids::CreateMonomorphic(Zone* zone, intptr_t cid) { |
215 Cids* cids = new (zone) Cids(zone); | 215 Cids* cids = new (zone) Cids(zone); |
216 cids->Add(new (zone) CidRange(cid, cid)); | 216 cids->Add(new (zone) CidRange(cid, cid)); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 TargetInfo(id, id, &function, ic_data.GetCountAt(i))); | 270 TargetInfo(id, id, &function, ic_data.GetCountAt(i))); |
271 } else { | 271 } else { |
272 cid_ranges_.Add(new (zone) CidRange(id, id)); | 272 cid_ranges_.Add(new (zone) CidRange(id, id)); |
273 } | 273 } |
274 } | 274 } |
275 } | 275 } |
276 | 276 |
277 | 277 |
278 bool Cids::IsMonomorphic() const { | 278 bool Cids::IsMonomorphic() const { |
279 if (length() != 1) return false; | 279 if (length() != 1) return false; |
280 return cid_ranges_[0]->cid_start == cid_ranges_[0]->cid_end; | 280 return cid_ranges_[0]->IsSingleCid(); |
281 } | 281 } |
282 | 282 |
283 | 283 |
284 intptr_t Cids::MonomorphicReceiverCid() const { | 284 intptr_t Cids::MonomorphicReceiverCid() const { |
285 ASSERT(IsMonomorphic()); | 285 ASSERT(IsMonomorphic()); |
286 return cid_ranges_[0]->cid_start; | 286 return cid_ranges_[0]->cid_start; |
287 } | 287 } |
288 | 288 |
289 | 289 |
290 CheckClassInstr::CheckClassInstr(Value* value, | 290 CheckClassInstr::CheckClassInstr(Value* value, |
291 intptr_t deopt_id, | 291 intptr_t deopt_id, |
292 const Cids& cids, | 292 const Cids& cids, |
293 TokenPosition token_pos) | 293 TokenPosition token_pos) |
294 : TemplateInstruction(deopt_id), | 294 : TemplateInstruction(deopt_id), |
295 cids_(cids), | 295 cids_(cids), |
296 licm_hoisted_(false), | 296 licm_hoisted_(false), |
297 is_bit_test_(IsCompactCidRange(cids)), | 297 is_bit_test_(IsCompactCidRange(cids)), |
298 token_pos_(token_pos) { | 298 token_pos_(token_pos) { |
299 // Expected useful check data. | 299 // Expected useful check data. |
300 const intptr_t number_of_checks = cids.length(); | 300 const intptr_t number_of_checks = cids.length(); |
301 ASSERT(number_of_checks > 0); | 301 ASSERT(number_of_checks > 0); |
302 SetInputAt(0, value); | 302 SetInputAt(0, value); |
303 // Otherwise use CheckSmiInstr. | 303 // Otherwise use CheckSmiInstr. |
304 ASSERT(number_of_checks != 1 || cids[0].cid_start != cids[0].cid_end || | 304 ASSERT(number_of_checks != 1 || !cids[0].IsSingleCid() || |
305 cids[0].cid_start != kSmiCid); | 305 cids[0].cid_start != kSmiCid); |
306 } | 306 } |
307 | 307 |
308 | 308 |
309 bool CheckClassInstr::AttributesEqual(Instruction* other) const { | 309 bool CheckClassInstr::AttributesEqual(Instruction* other) const { |
310 CheckClassInstr* other_check = other->AsCheckClass(); | 310 CheckClassInstr* other_check = other->AsCheckClass(); |
311 ASSERT(other_check != NULL); | 311 ASSERT(other_check != NULL); |
312 return cids().Equals(other_check->cids()); | 312 return cids().Equals(other_check->cids()); |
313 } | 313 } |
314 | 314 |
315 | 315 |
316 EffectSet CheckClassInstr::Dependencies() const { | 316 EffectSet CheckClassInstr::Dependencies() const { |
317 // Externalization of strings via the API can change the class-id. | 317 // Externalization of strings via the API can change the class-id. |
318 return cids_.ContainsExternalizableCids() ? EffectSet::Externalization() | 318 return cids_.ContainsExternalizableCids() ? EffectSet::Externalization() |
319 : EffectSet::None(); | 319 : EffectSet::None(); |
320 } | 320 } |
321 | 321 |
322 | 322 |
323 EffectSet CheckClassIdInstr::Dependencies() const { | 323 EffectSet CheckClassIdInstr::Dependencies() const { |
324 // Externalization of strings via the API can change the class-id. | 324 // Externalization of strings via the API can change the class-id. |
325 return Field::IsExternalizableCid(cid_) ? EffectSet::Externalization() | 325 for (intptr_t i = cids_.cid_start; i <= cids_.cid_end; i++) { |
326 : EffectSet::None(); | 326 if (Field::IsExternalizableCid(i)) return EffectSet::Externalization(); |
| 327 } |
| 328 return EffectSet::None(); |
327 } | 329 } |
328 | 330 |
329 | 331 |
330 bool CheckClassInstr::IsDeoptIfNull() const { | 332 bool CheckClassInstr::IsDeoptIfNull() const { |
331 if (!cids().IsMonomorphic()) { | 333 if (!cids().IsMonomorphic()) { |
332 return false; | 334 return false; |
333 } | 335 } |
334 CompileType* in_type = value()->Type(); | 336 CompileType* in_type = value()->Type(); |
335 const intptr_t cid = cids().MonomorphicReceiverCid(); | 337 const intptr_t cid = cids().MonomorphicReceiverCid(); |
336 // Performance check: use CheckSmiInstr instead. | 338 // Performance check: use CheckSmiInstr instead. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 bool CheckClassInstr::IsBitTest() const { | 371 bool CheckClassInstr::IsBitTest() const { |
370 return is_bit_test_; | 372 return is_bit_test_; |
371 } | 373 } |
372 | 374 |
373 | 375 |
374 intptr_t CheckClassInstr::ComputeCidMask() const { | 376 intptr_t CheckClassInstr::ComputeCidMask() const { |
375 ASSERT(IsBitTest()); | 377 ASSERT(IsBitTest()); |
376 intptr_t min = cids_.ComputeLowestCid(); | 378 intptr_t min = cids_.ComputeLowestCid(); |
377 intptr_t mask = 0; | 379 intptr_t mask = 0; |
378 for (intptr_t i = 0; i < cids_.length(); ++i) { | 380 for (intptr_t i = 0; i < cids_.length(); ++i) { |
379 intptr_t cid_start = cids_[i].cid_start; | |
380 intptr_t cid_end = cids_[i].cid_end; | |
381 intptr_t run; | 381 intptr_t run; |
382 uintptr_t range = 1ul + cid_end - cid_start; | 382 uintptr_t range = 1ul + cids_[i].Extent(); |
383 if (range >= kBitsPerWord) { | 383 if (range >= kBitsPerWord) { |
384 run = -1; | 384 run = -1; |
385 } else { | 385 } else { |
386 run = (1 << range) - 1; | 386 run = (1 << range) - 1; |
387 } | 387 } |
388 mask |= run << (cid_start - min); | 388 mask |= run << (cids_[i].cid_start - min); |
389 } | 389 } |
390 return mask; | 390 return mask; |
391 } | 391 } |
392 | 392 |
393 | 393 |
394 bool LoadFieldInstr::IsUnboxedLoad() const { | 394 bool LoadFieldInstr::IsUnboxedLoad() const { |
395 return FLAG_unbox_numeric_fields && (field() != NULL) && | 395 return FLAG_unbox_numeric_fields && (field() != NULL) && |
396 FlowGraphCompiler::IsUnboxedField(*field()); | 396 FlowGraphCompiler::IsUnboxedField(*field()); |
397 } | 397 } |
398 | 398 |
(...skipping 2282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2681 return this; | 2681 return this; |
2682 } | 2682 } |
2683 | 2683 |
2684 return cids().HasClassId(value_cid) ? NULL : this; | 2684 return cids().HasClassId(value_cid) ? NULL : this; |
2685 } | 2685 } |
2686 | 2686 |
2687 | 2687 |
2688 Instruction* CheckClassIdInstr::Canonicalize(FlowGraph* flow_graph) { | 2688 Instruction* CheckClassIdInstr::Canonicalize(FlowGraph* flow_graph) { |
2689 if (value()->BindsToConstant()) { | 2689 if (value()->BindsToConstant()) { |
2690 const Object& constant_value = value()->BoundConstant(); | 2690 const Object& constant_value = value()->BoundConstant(); |
2691 if (constant_value.IsSmi() && Smi::Cast(constant_value).Value() == cid_) { | 2691 if (constant_value.IsSmi() && |
| 2692 cids_.Contains(Smi::Cast(constant_value).Value())) { |
2692 return NULL; | 2693 return NULL; |
2693 } | 2694 } |
2694 } | 2695 } |
2695 return this; | 2696 return this; |
2696 } | 2697 } |
2697 | 2698 |
2698 | 2699 |
2699 Definition* TestCidsInstr::Canonicalize(FlowGraph* flow_graph) { | 2700 Definition* TestCidsInstr::Canonicalize(FlowGraph* flow_graph) { |
2700 CompileType* in_type = left()->Type(); | 2701 CompileType* in_type = left()->Type(); |
2701 intptr_t cid = in_type->ToCid(); | 2702 intptr_t cid = in_type->ToCid(); |
(...skipping 1606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4308 "native function '%s' (%" Pd " arguments) cannot be found", | 4309 "native function '%s' (%" Pd " arguments) cannot be found", |
4309 native_name().ToCString(), function().NumParameters()); | 4310 native_name().ToCString(), function().NumParameters()); |
4310 } | 4311 } |
4311 set_is_auto_scope(auto_setup_scope); | 4312 set_is_auto_scope(auto_setup_scope); |
4312 set_native_c_function(native_function); | 4313 set_native_c_function(native_function); |
4313 } | 4314 } |
4314 | 4315 |
4315 #undef __ | 4316 #undef __ |
4316 | 4317 |
4317 } // namespace dart | 4318 } // namespace dart |
OLD | NEW |