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 // Externalization of strings via the API can change the class-id. | |
| 157 const bool externalizable = | |
| 158 cid_ == kOneByteStringCid || cid_ == kTwoByteStringCid; | |
| 159 return externalizable ? EffectSet::Externalization() : EffectSet::None(); | |
| 160 } | |
| 161 | |
| 162 | |
| 143 bool CheckClassInstr::IsNullCheck() const { | 163 bool CheckClassInstr::IsNullCheck() const { |
| 144 if (unary_checks().NumberOfChecks() != 1) { | 164 if (unary_checks().NumberOfChecks() != 1) { |
| 145 return false; | 165 return false; |
| 146 } | 166 } |
| 147 CompileType* in_type = value()->Type(); | 167 CompileType* in_type = value()->Type(); |
| 148 const intptr_t cid = unary_checks().GetCidAt(0); | 168 const intptr_t cid = unary_checks().GetCidAt(0); |
| 149 // Performance check: use CheckSmiInstr instead. | 169 // Performance check: use CheckSmiInstr instead. |
| 150 ASSERT(cid != kSmiCid); | 170 ASSERT(cid != kSmiCid); |
| 151 return in_type->is_nullable() && (in_type->ToNullableCid() == cid); | 171 return in_type->is_nullable() && (in_type->ToNullableCid() == cid); |
| 152 } | 172 } |
| 153 | 173 |
| 154 | 174 |
| 175 bool CheckClassInstr::IsDenseSwitch() const { | |
| 176 if (unary_checks().GetReceiverClassIdAt(0) == kSmiCid) return false; | |
| 177 if (cids_.length() > 2 && | |
| 178 cids_[cids_.length() - 1] - cids_[0] < kBitsPerWord) { | |
| 179 return true; | |
| 180 } | |
| 181 return false; | |
| 182 } | |
| 183 | |
| 184 | |
| 185 intptr_t CheckClassInstr::ComputeCidMask() const { | |
| 186 ASSERT(IsDenseSwitch()); | |
| 187 intptr_t mask = 0; | |
| 188 for (intptr_t i = 0; i < cids_.length(); ++i) { | |
| 189 mask |= 1 << (cids_[i] - cids_[0]); | |
| 190 } | |
| 191 return mask; | |
| 192 } | |
| 193 | |
| 194 | |
| 195 bool CheckClassInstr::IsDenseMask(intptr_t mask) { | |
| 196 // Returns true if the mask is a continuos sequence of ones in its binary | |
| 197 // representation (i.e. no holes) | |
| 198 return mask == -1 || Utils::IsPowerOfTwo(mask + 1); | |
| 199 } | |
| 200 | |
| 201 | |
| 155 bool LoadFieldInstr::IsUnboxedLoad() const { | 202 bool LoadFieldInstr::IsUnboxedLoad() const { |
| 156 return FLAG_unbox_numeric_fields | 203 return FLAG_unbox_numeric_fields |
| 157 && (field() != NULL) | 204 && (field() != NULL) |
| 158 && field()->IsUnboxedField(); | 205 && field()->IsUnboxedField(); |
| 159 } | 206 } |
| 160 | 207 |
| 161 | 208 |
| 162 bool LoadFieldInstr::IsPotentialUnboxedLoad() const { | 209 bool LoadFieldInstr::IsPotentialUnboxedLoad() const { |
| 163 return FLAG_unbox_numeric_fields | 210 return FLAG_unbox_numeric_fields |
| 164 && (field() != NULL) | 211 && (field() != NULL) |
| (...skipping 1791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1956 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) { | 2003 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1957 const intptr_t value_cid = value()->Type()->ToCid(); | 2004 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1958 if (value_cid == kDynamicCid) { | 2005 if (value_cid == kDynamicCid) { |
| 1959 return this; | 2006 return this; |
| 1960 } | 2007 } |
| 1961 | 2008 |
| 1962 return unary_checks().HasReceiverClassId(value_cid) ? NULL : this; | 2009 return unary_checks().HasReceiverClassId(value_cid) ? NULL : this; |
| 1963 } | 2010 } |
| 1964 | 2011 |
| 1965 | 2012 |
| 2013 Instruction* CheckClassIdInstr::Canonicalize(FlowGraph* flow_graph) { | |
| 2014 if (value()->BindsToConstant()) { | |
|
Vyacheslav Egorov (Google)
2014/07/11 11:50:24
does BindsToConstant() see through to OriginalDefi
Florian Schneider
2014/07/14 12:13:46
No, we run Canonicalize after removing Redefinitio
| |
| 2015 const Object& constant_value = value()->BoundConstant(); | |
| 2016 if (constant_value.IsSmi() && | |
| 2017 Smi::Cast(constant_value).Value() == cid_) { | |
| 2018 return NULL; | |
| 2019 } | |
| 2020 } | |
| 2021 return this; | |
| 2022 } | |
| 2023 | |
| 2024 | |
| 1966 Instruction* GuardFieldClassInstr::Canonicalize(FlowGraph* flow_graph) { | 2025 Instruction* GuardFieldClassInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1967 if (field().guarded_cid() == kDynamicCid) { | 2026 if (field().guarded_cid() == kDynamicCid) { |
| 1968 return NULL; // Nothing to guard. | 2027 return NULL; // Nothing to guard. |
| 1969 } | 2028 } |
| 1970 | 2029 |
| 1971 if (field().is_nullable() && value()->Type()->IsNull()) { | 2030 if (field().is_nullable() && value()->Type()->IsNull()) { |
| 1972 return NULL; | 2031 return NULL; |
| 1973 } | 2032 } |
| 1974 | 2033 |
| 1975 const intptr_t cid = field().is_nullable() ? value()->Type()->ToNullableCid() | 2034 const intptr_t cid = field().is_nullable() ? value()->Type()->ToNullableCid() |
| (...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2478 if (IsConstant()) return *this; | 2537 if (IsConstant()) return *this; |
| 2479 return Add(Range::ConstantMax(symbol()->range()), | 2538 return Add(Range::ConstantMax(symbol()->range()), |
| 2480 RangeBoundary::FromConstant(offset_), | 2539 RangeBoundary::FromConstant(offset_), |
| 2481 PositiveInfinity()); | 2540 PositiveInfinity()); |
| 2482 } | 2541 } |
| 2483 | 2542 |
| 2484 | 2543 |
| 2485 RangeBoundary RangeBoundary::Add(const RangeBoundary& a, | 2544 RangeBoundary RangeBoundary::Add(const RangeBoundary& a, |
| 2486 const RangeBoundary& b, | 2545 const RangeBoundary& b, |
| 2487 const RangeBoundary& overflow) { | 2546 const RangeBoundary& overflow) { |
| 2547 if (a.IsInfinity() || b.IsInfinity()) return overflow; | |
| 2548 | |
| 2488 ASSERT(a.IsConstant() && b.IsConstant()); | 2549 ASSERT(a.IsConstant() && b.IsConstant()); |
| 2489 | |
| 2490 if (Utils::WillAddOverflow(a.ConstantValue(), b.ConstantValue())) { | 2550 if (Utils::WillAddOverflow(a.ConstantValue(), b.ConstantValue())) { |
| 2491 return overflow; | 2551 return overflow; |
| 2492 } | 2552 } |
| 2493 | 2553 |
| 2494 int64_t result = a.ConstantValue() + b.ConstantValue(); | 2554 int64_t result = a.ConstantValue() + b.ConstantValue(); |
| 2495 | 2555 |
| 2496 return RangeBoundary::FromConstant(result); | 2556 return RangeBoundary::FromConstant(result); |
| 2497 } | 2557 } |
| 2498 | 2558 |
| 2499 | 2559 |
| 2500 RangeBoundary RangeBoundary::Sub(const RangeBoundary& a, | 2560 RangeBoundary RangeBoundary::Sub(const RangeBoundary& a, |
| 2501 const RangeBoundary& b, | 2561 const RangeBoundary& b, |
| 2502 const RangeBoundary& overflow) { | 2562 const RangeBoundary& overflow) { |
| 2563 if (a.IsInfinity() || b.IsInfinity()) return overflow; | |
| 2503 ASSERT(a.IsConstant() && b.IsConstant()); | 2564 ASSERT(a.IsConstant() && b.IsConstant()); |
| 2504 | |
| 2505 if (Utils::WillSubOverflow(a.ConstantValue(), b.ConstantValue())) { | 2565 if (Utils::WillSubOverflow(a.ConstantValue(), b.ConstantValue())) { |
| 2506 return overflow; | 2566 return overflow; |
| 2507 } | 2567 } |
| 2508 | 2568 |
| 2509 int64_t result = a.ConstantValue() - b.ConstantValue(); | 2569 int64_t result = a.ConstantValue() - b.ConstantValue(); |
| 2510 | 2570 |
| 2511 return RangeBoundary::FromConstant(result); | 2571 return RangeBoundary::FromConstant(result); |
| 2512 } | 2572 } |
| 2513 | 2573 |
| 2514 | 2574 |
| (...skipping 1460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3975 case Token::kTRUNCDIV: return 0; | 4035 case Token::kTRUNCDIV: return 0; |
| 3976 case Token::kMOD: return 1; | 4036 case Token::kMOD: return 1; |
| 3977 default: UNIMPLEMENTED(); return -1; | 4037 default: UNIMPLEMENTED(); return -1; |
| 3978 } | 4038 } |
| 3979 } | 4039 } |
| 3980 | 4040 |
| 3981 | 4041 |
| 3982 #undef __ | 4042 #undef __ |
| 3983 | 4043 |
| 3984 } // namespace dart | 4044 } // namespace dart |
| OLD | NEW |