Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: runtime/vm/intermediate_language.cc

Issue 381803005: Reland r38116: Improve receiver class check in polymorphic inlining. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698