| 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 |