| 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 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 case kFloat64x2Cid: | 212 case kFloat64x2Cid: |
| 213 return kUnboxedFloat64x2; | 213 return kUnboxedFloat64x2; |
| 214 default: | 214 default: |
| 215 UNREACHABLE(); | 215 UNREACHABLE(); |
| 216 } | 216 } |
| 217 } | 217 } |
| 218 return kTagged; | 218 return kTagged; |
| 219 } | 219 } |
| 220 | 220 |
| 221 | 221 |
| 222 bool GuardFieldInstr::AttributesEqual(Instruction* other) const { | 222 bool GuardFieldClassInstr::AttributesEqual(Instruction* other) const { |
| 223 return field().raw() == other->AsGuardField()->field().raw(); | 223 return field().raw() == other->AsGuardFieldClass()->field().raw(); |
| 224 } | 224 } |
| 225 | 225 |
| 226 | 226 |
| 227 bool GuardFieldLengthInstr::AttributesEqual(Instruction* other) const { |
| 228 return field().raw() == other->AsGuardFieldLength()->field().raw(); |
| 229 } |
| 230 |
| 231 |
| 227 bool AssertAssignableInstr::AttributesEqual(Instruction* other) const { | 232 bool AssertAssignableInstr::AttributesEqual(Instruction* other) const { |
| 228 AssertAssignableInstr* other_assert = other->AsAssertAssignable(); | 233 AssertAssignableInstr* other_assert = other->AsAssertAssignable(); |
| 229 ASSERT(other_assert != NULL); | 234 ASSERT(other_assert != NULL); |
| 230 // This predicate has to be commutative for DominatorBasedCSE to work. | 235 // This predicate has to be commutative for DominatorBasedCSE to work. |
| 231 // TODO(fschneider): Eliminate more asserts with subtype relation. | 236 // TODO(fschneider): Eliminate more asserts with subtype relation. |
| 232 return dst_type().raw() == other_assert->dst_type().raw(); | 237 return dst_type().raw() == other_assert->dst_type().raw(); |
| 233 } | 238 } |
| 234 | 239 |
| 235 | 240 |
| 236 bool StrictCompareInstr::AttributesEqual(Instruction* other) const { | 241 bool StrictCompareInstr::AttributesEqual(Instruction* other) const { |
| (...skipping 1710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1947 Definition* replacement = CanonicalizeStrictCompare(this, &negated); | 1952 Definition* replacement = CanonicalizeStrictCompare(this, &negated); |
| 1948 if (negated && replacement->IsComparison()) { | 1953 if (negated && replacement->IsComparison()) { |
| 1949 ASSERT(replacement != this); | 1954 ASSERT(replacement != this); |
| 1950 replacement->AsComparison()->NegateComparison(); | 1955 replacement->AsComparison()->NegateComparison(); |
| 1951 } | 1956 } |
| 1952 return replacement; | 1957 return replacement; |
| 1953 } | 1958 } |
| 1954 | 1959 |
| 1955 | 1960 |
| 1956 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) { | 1961 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1957 // TODO(vegorov): Replace class checks with null checks when ToNullableCid | |
| 1958 // matches. | |
| 1959 | |
| 1960 const intptr_t value_cid = value()->Type()->ToCid(); | 1962 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1961 if (value_cid == kDynamicCid) { | 1963 if (value_cid == kDynamicCid) { |
| 1962 return this; | 1964 return this; |
| 1963 } | 1965 } |
| 1964 | 1966 |
| 1965 return unary_checks().HasReceiverClassId(value_cid) ? NULL : this; | 1967 return unary_checks().HasReceiverClassId(value_cid) ? NULL : this; |
| 1966 } | 1968 } |
| 1967 | 1969 |
| 1968 | 1970 |
| 1969 Instruction* GuardFieldInstr::Canonicalize(FlowGraph* flow_graph) { | 1971 Instruction* GuardFieldClassInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1970 if (field().guarded_cid() == kDynamicCid) { | 1972 if (field().guarded_cid() == kDynamicCid) { |
| 1971 return NULL; // Nothing to guard. | 1973 return NULL; // Nothing to guard. |
| 1972 } | 1974 } |
| 1973 | 1975 |
| 1974 if (field().guarded_list_length() != Field::kNoFixedLength) { | |
| 1975 // We are still guarding the list length. Check if length is statically | |
| 1976 // known. | |
| 1977 StaticCallInstr* call = value()->definition()->AsStaticCall(); | |
| 1978 if (call != NULL) { | |
| 1979 ConstantInstr* length = NULL; | |
| 1980 if (call->is_known_list_constructor() && | |
| 1981 LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) { | |
| 1982 length = call->ArgumentAt(1)->AsConstant(); | |
| 1983 } | |
| 1984 if (call->is_native_list_factory()) { | |
| 1985 length = call->ArgumentAt(0)->AsConstant(); | |
| 1986 } | |
| 1987 if ((length != NULL) && length->value().IsSmi()) { | |
| 1988 intptr_t known_length = Smi::Cast(length->value()).Value(); | |
| 1989 return (known_length != field().guarded_list_length()) ? this : NULL; | |
| 1990 } | |
| 1991 } | |
| 1992 return this; | |
| 1993 } | |
| 1994 | |
| 1995 if (field().is_nullable() && value()->Type()->IsNull()) { | 1976 if (field().is_nullable() && value()->Type()->IsNull()) { |
| 1996 return NULL; | 1977 return NULL; |
| 1997 } | 1978 } |
| 1998 | 1979 |
| 1999 const intptr_t cid = field().is_nullable() ? value()->Type()->ToNullableCid() | 1980 const intptr_t cid = field().is_nullable() ? value()->Type()->ToNullableCid() |
| 2000 : value()->Type()->ToCid(); | 1981 : value()->Type()->ToCid(); |
| 2001 if (field().guarded_cid() == cid) { | 1982 if (field().guarded_cid() == cid) { |
| 2002 return NULL; // Value is guaranteed to have this cid. | 1983 return NULL; // Value is guaranteed to have this cid. |
| 2003 } | 1984 } |
| 2004 | 1985 |
| 2005 return this; | 1986 return this; |
| 2006 } | 1987 } |
| 2007 | 1988 |
| 2008 | 1989 |
| 1990 Instruction* GuardFieldLengthInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1991 if (!field().needs_length_check()) { |
| 1992 return NULL; // Nothing to guard. |
| 1993 } |
| 1994 |
| 1995 const intptr_t expected_length = field().guarded_list_length(); |
| 1996 if (expected_length == Field::kUnknownFixedLength) { |
| 1997 return this; |
| 1998 } |
| 1999 |
| 2000 // Check if length is statically known. |
| 2001 StaticCallInstr* call = value()->definition()->AsStaticCall(); |
| 2002 if (call == NULL) { |
| 2003 return this; |
| 2004 } |
| 2005 |
| 2006 ConstantInstr* length = NULL; |
| 2007 if (call->is_known_list_constructor() && |
| 2008 LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) { |
| 2009 length = call->ArgumentAt(1)->AsConstant(); |
| 2010 } |
| 2011 if (call->is_native_list_factory()) { |
| 2012 length = call->ArgumentAt(0)->AsConstant(); |
| 2013 } |
| 2014 if ((length != NULL) && |
| 2015 length->value().IsSmi() && |
| 2016 Smi::Cast(length->value()).Value() == expected_length) { |
| 2017 return NULL; // Expected length matched. |
| 2018 } |
| 2019 |
| 2020 return this; |
| 2021 } |
| 2022 |
| 2023 |
| 2009 Instruction* CheckSmiInstr::Canonicalize(FlowGraph* flow_graph) { | 2024 Instruction* CheckSmiInstr::Canonicalize(FlowGraph* flow_graph) { |
| 2010 return (value()->Type()->ToCid() == kSmiCid) ? NULL : this; | 2025 return (value()->Type()->ToCid() == kSmiCid) ? NULL : this; |
| 2011 } | 2026 } |
| 2012 | 2027 |
| 2013 | 2028 |
| 2014 Instruction* CheckEitherNonSmiInstr::Canonicalize(FlowGraph* flow_graph) { | 2029 Instruction* CheckEitherNonSmiInstr::Canonicalize(FlowGraph* flow_graph) { |
| 2015 if ((left()->Type()->ToCid() == kDoubleCid) || | 2030 if ((left()->Type()->ToCid() == kDoubleCid) || |
| 2016 (right()->Type()->ToCid() == kDoubleCid)) { | 2031 (right()->Type()->ToCid() == kDoubleCid)) { |
| 2017 return NULL; // Remove from the graph. | 2032 return NULL; // Remove from the graph. |
| 2018 } | 2033 } |
| (...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3455 case Token::kTRUNCDIV: return 0; | 3470 case Token::kTRUNCDIV: return 0; |
| 3456 case Token::kMOD: return 1; | 3471 case Token::kMOD: return 1; |
| 3457 default: UNIMPLEMENTED(); return -1; | 3472 default: UNIMPLEMENTED(); return -1; |
| 3458 } | 3473 } |
| 3459 } | 3474 } |
| 3460 | 3475 |
| 3461 | 3476 |
| 3462 #undef __ | 3477 #undef __ |
| 3463 | 3478 |
| 3464 } // namespace dart | 3479 } // namespace dart |
| OLD | NEW |