Chromium Code Reviews| 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/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
| 8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 88 } | 88 } |
| 89 return AttributesEqual(other); | 89 return AttributesEqual(other); |
| 90 } | 90 } |
| 91 | 91 |
| 92 | 92 |
| 93 bool Value::Equals(Value* other) const { | 93 bool Value::Equals(Value* other) const { |
| 94 return definition() == other->definition(); | 94 return definition() == other->definition(); |
| 95 } | 95 } |
| 96 | 96 |
| 97 | 97 |
| 98 static int LowestFirst(const intptr_t* a, const intptr_t* b) { | |
| 99 return *a - *b; | |
| 100 } | |
| 101 | |
| 102 | |
| 98 CheckClassInstr::CheckClassInstr(Value* value, | 103 CheckClassInstr::CheckClassInstr(Value* value, |
| 99 intptr_t deopt_id, | 104 intptr_t deopt_id, |
| 100 const ICData& unary_checks, | 105 const ICData& unary_checks, |
| 101 intptr_t token_pos) | 106 intptr_t token_pos) |
| 102 : unary_checks_(unary_checks), licm_hoisted_(false), token_pos_(token_pos) { | 107 : unary_checks_(unary_checks), |
| 108 cids_(unary_checks.NumberOfChecks()), | |
| 109 licm_hoisted_(false), | |
| 110 token_pos_(token_pos) { | |
| 103 ASSERT(unary_checks.IsZoneHandle()); | 111 ASSERT(unary_checks.IsZoneHandle()); |
| 104 // Expected useful check data. | 112 // Expected useful check data. |
| 105 ASSERT(!unary_checks_.IsNull()); | 113 ASSERT(!unary_checks_.IsNull()); |
| 106 ASSERT(unary_checks_.NumberOfChecks() > 0); | 114 ASSERT(unary_checks_.NumberOfChecks() > 0); |
| 107 ASSERT(unary_checks_.NumArgsTested() == 1); | 115 ASSERT(unary_checks_.NumArgsTested() == 1); |
| 108 SetInputAt(0, value); | 116 SetInputAt(0, value); |
| 109 deopt_id_ = deopt_id; | 117 deopt_id_ = deopt_id; |
| 110 // Otherwise use CheckSmiInstr. | 118 // Otherwise use CheckSmiInstr. |
| 111 ASSERT((unary_checks_.NumberOfChecks() != 1) || | 119 ASSERT((unary_checks_.NumberOfChecks() != 1) || |
| 112 (unary_checks_.GetReceiverClassIdAt(0) != kSmiCid)); | 120 (unary_checks_.GetReceiverClassIdAt(0) != kSmiCid)); |
| 121 for (intptr_t i = 0; i < unary_checks.NumberOfChecks(); ++i) { | |
| 122 cids_.Add(unary_checks.GetReceiverClassIdAt(i)); | |
| 123 } | |
| 124 cids_.Sort(LowestFirst); | |
| 113 } | 125 } |
| 114 | 126 |
| 115 | 127 |
| 116 bool CheckClassInstr::AttributesEqual(Instruction* other) const { | 128 bool CheckClassInstr::AttributesEqual(Instruction* other) const { |
| 117 CheckClassInstr* other_check = other->AsCheckClass(); | 129 CheckClassInstr* other_check = other->AsCheckClass(); |
| 118 ASSERT(other_check != NULL); | 130 ASSERT(other_check != NULL); |
| 119 if (unary_checks().NumberOfChecks() != | 131 if (unary_checks().NumberOfChecks() != |
| 120 other_check->unary_checks().NumberOfChecks()) { | 132 other_check->unary_checks().NumberOfChecks()) { |
| 121 return false; | 133 return false; |
| 122 } | 134 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 133 | 145 |
| 134 EffectSet CheckClassInstr::Dependencies() const { | 146 EffectSet CheckClassInstr::Dependencies() const { |
| 135 // Externalization of strings via the API can change the class-id. | 147 // Externalization of strings via the API can change the class-id. |
| 136 const bool externalizable = | 148 const bool externalizable = |
| 137 unary_checks().HasReceiverClassId(kOneByteStringCid) || | 149 unary_checks().HasReceiverClassId(kOneByteStringCid) || |
| 138 unary_checks().HasReceiverClassId(kTwoByteStringCid); | 150 unary_checks().HasReceiverClassId(kTwoByteStringCid); |
| 139 return externalizable ? EffectSet::Externalization() : EffectSet::None(); | 151 return externalizable ? EffectSet::Externalization() : EffectSet::None(); |
| 140 } | 152 } |
| 141 | 153 |
| 142 | 154 |
| 155 EffectSet CheckClassIdInstr::Dependencies() const { | |
| 156 ASSERT(right()->BindsToConstant()); | |
| 157 ASSERT(right()->BoundConstant().IsSmi()); | |
| 158 // Externalization of strings via the API can change the class-id. | |
| 159 const intptr_t cid = Smi::Cast(right()->BoundConstant()).Value(); | |
| 160 const bool externalizable = | |
| 161 cid == kOneByteStringCid || cid == kTwoByteStringCid; | |
| 162 return externalizable ? EffectSet::Externalization() : EffectSet::None(); | |
| 163 } | |
| 164 | |
| 165 | |
| 143 bool CheckClassInstr::IsNullCheck() const { | 166 bool CheckClassInstr::IsNullCheck() const { |
| 144 if (unary_checks().NumberOfChecks() != 1) { | 167 if (unary_checks().NumberOfChecks() != 1) { |
| 145 return false; | 168 return false; |
| 146 } | 169 } |
| 147 CompileType* in_type = value()->Type(); | 170 CompileType* in_type = value()->Type(); |
| 148 const intptr_t cid = unary_checks().GetCidAt(0); | 171 const intptr_t cid = unary_checks().GetCidAt(0); |
| 149 // Performance check: use CheckSmiInstr instead. | 172 // Performance check: use CheckSmiInstr instead. |
| 150 ASSERT(cid != kSmiCid); | 173 ASSERT(cid != kSmiCid); |
| 151 return in_type->is_nullable() && (in_type->ToNullableCid() == cid); | 174 return in_type->is_nullable() && (in_type->ToNullableCid() == cid); |
| 152 } | 175 } |
| 153 | 176 |
| 154 | 177 |
| 178 bool CheckClassInstr::IsDenseSwitch() const { | |
| 179 if (unary_checks().GetReceiverClassIdAt(0) == kSmiCid) return false; | |
| 180 if (cids_.length() > 2 && | |
| 181 cids_[cids_.length() - 1] - cids_[0] < kBitsPerWord) { | |
| 182 return true; | |
| 183 } | |
| 184 return false; | |
| 185 } | |
| 186 | |
| 187 | |
| 188 intptr_t CheckClassInstr::ComputeCidMask() const { | |
| 189 ASSERT(IsDenseSwitch()); | |
| 190 intptr_t mask = 0; | |
| 191 for (intptr_t i = 0; i < cids_.length(); ++i) { | |
| 192 mask |= 1 << (cids_[i] - cids_[0]); | |
| 193 } | |
| 194 return mask; | |
| 195 } | |
| 196 | |
| 197 | |
| 198 bool CheckClassInstr::IsDenseMask(intptr_t mask) { | |
| 199 // Returns true if the mask is a continuos sequence of ones in its binary | |
| 200 // representation (i.e. no holes) | |
| 201 return mask == -1 || Utils::IsPowerOfTwo(mask + 1); | |
| 202 } | |
| 203 | |
| 204 | |
| 155 bool LoadFieldInstr::IsUnboxedLoad() const { | 205 bool LoadFieldInstr::IsUnboxedLoad() const { |
| 156 return FLAG_unbox_numeric_fields | 206 return FLAG_unbox_numeric_fields |
| 157 && (field() != NULL) | 207 && (field() != NULL) |
| 158 && field()->IsUnboxedField(); | 208 && field()->IsUnboxedField(); |
| 159 } | 209 } |
| 160 | 210 |
| 161 | 211 |
| 162 bool LoadFieldInstr::IsPotentialUnboxedLoad() const { | 212 bool LoadFieldInstr::IsPotentialUnboxedLoad() const { |
| 163 return FLAG_unbox_numeric_fields | 213 return FLAG_unbox_numeric_fields |
| 164 && (field() != NULL) | 214 && (field() != NULL) |
| (...skipping 2313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2478 if (IsConstant()) return *this; | 2528 if (IsConstant()) return *this; |
| 2479 return Add(Range::ConstantMax(symbol()->range()), | 2529 return Add(Range::ConstantMax(symbol()->range()), |
| 2480 RangeBoundary::FromConstant(offset_), | 2530 RangeBoundary::FromConstant(offset_), |
| 2481 PositiveInfinity()); | 2531 PositiveInfinity()); |
| 2482 } | 2532 } |
| 2483 | 2533 |
| 2484 | 2534 |
| 2485 RangeBoundary RangeBoundary::Add(const RangeBoundary& a, | 2535 RangeBoundary RangeBoundary::Add(const RangeBoundary& a, |
| 2486 const RangeBoundary& b, | 2536 const RangeBoundary& b, |
| 2487 const RangeBoundary& overflow) { | 2537 const RangeBoundary& overflow) { |
| 2538 if (a.IsInfinity() || b.IsInfinity()) return overflow; | |
|
Florian Schneider
2014/07/10 15:10:13
Handle infinity here in Add and Sub.
Cutch
2014/07/10 16:04:20
Why is this being added? I removed this from my 64
Vyacheslav Egorov (Google)
2014/07/10 16:34:56
When trying to Add ranges we sometimes pass infini
| |
| 2539 | |
| 2488 ASSERT(a.IsConstant() && b.IsConstant()); | 2540 ASSERT(a.IsConstant() && b.IsConstant()); |
| 2489 | |
| 2490 if (Utils::WillAddOverflow(a.ConstantValue(), b.ConstantValue())) { | 2541 if (Utils::WillAddOverflow(a.ConstantValue(), b.ConstantValue())) { |
| 2491 return overflow; | 2542 return overflow; |
| 2492 } | 2543 } |
| 2493 | 2544 |
| 2494 int64_t result = a.ConstantValue() + b.ConstantValue(); | 2545 int64_t result = a.ConstantValue() + b.ConstantValue(); |
| 2495 | 2546 |
| 2496 return RangeBoundary::FromConstant(result); | 2547 return RangeBoundary::FromConstant(result); |
| 2497 } | 2548 } |
| 2498 | 2549 |
| 2499 | 2550 |
| 2500 RangeBoundary RangeBoundary::Sub(const RangeBoundary& a, | 2551 RangeBoundary RangeBoundary::Sub(const RangeBoundary& a, |
| 2501 const RangeBoundary& b, | 2552 const RangeBoundary& b, |
| 2502 const RangeBoundary& overflow) { | 2553 const RangeBoundary& overflow) { |
| 2554 if (a.IsInfinity() || b.IsInfinity()) return overflow; | |
| 2503 ASSERT(a.IsConstant() && b.IsConstant()); | 2555 ASSERT(a.IsConstant() && b.IsConstant()); |
| 2504 | |
| 2505 if (Utils::WillSubOverflow(a.ConstantValue(), b.ConstantValue())) { | 2556 if (Utils::WillSubOverflow(a.ConstantValue(), b.ConstantValue())) { |
| 2506 return overflow; | 2557 return overflow; |
| 2507 } | 2558 } |
| 2508 | 2559 |
| 2509 int64_t result = a.ConstantValue() - b.ConstantValue(); | 2560 int64_t result = a.ConstantValue() - b.ConstantValue(); |
| 2510 | 2561 |
| 2511 return RangeBoundary::FromConstant(result); | 2562 return RangeBoundary::FromConstant(result); |
| 2512 } | 2563 } |
| 2513 | 2564 |
| 2514 | 2565 |
| (...skipping 1460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3975 case Token::kTRUNCDIV: return 0; | 4026 case Token::kTRUNCDIV: return 0; |
| 3976 case Token::kMOD: return 1; | 4027 case Token::kMOD: return 1; |
| 3977 default: UNIMPLEMENTED(); return -1; | 4028 default: UNIMPLEMENTED(); return -1; |
| 3978 } | 4029 } |
| 3979 } | 4030 } |
| 3980 | 4031 |
| 3981 | 4032 |
| 3982 #undef __ | 4033 #undef __ |
| 3983 | 4034 |
| 3984 } // namespace dart | 4035 } // namespace dart |
| OLD | NEW |