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

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

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 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
« 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/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 26 matching lines...) Expand all
37 two_args_smi_icd, 37 two_args_smi_icd,
38 true, 38 true,
39 "Generate special IC stubs for two args Smi operations"); 39 "Generate special IC stubs for two args Smi operations");
40 DEFINE_FLAG(bool, 40 DEFINE_FLAG(bool,
41 unbox_numeric_fields, 41 unbox_numeric_fields,
42 !USING_DBC, 42 !USING_DBC,
43 "Support unboxed double and float32x4 fields."); 43 "Support unboxed double and float32x4 fields.");
44 DECLARE_FLAG(bool, eliminate_type_checks); 44 DECLARE_FLAG(bool, eliminate_type_checks);
45 DECLARE_FLAG(bool, support_externalizable_strings); 45 DECLARE_FLAG(bool, support_externalizable_strings);
46 46
47
48 #if defined(DEBUG) 47 #if defined(DEBUG)
49 void Instruction::CheckField(const Field& field) const { 48 void Instruction::CheckField(const Field& field) const {
50 ASSERT(field.IsZoneHandle()); 49 ASSERT(field.IsZoneHandle());
51 ASSERT(!Compiler::IsBackgroundCompilation() || !field.IsOriginal()); 50 ASSERT(!Compiler::IsBackgroundCompilation() || !field.IsOriginal());
52 } 51 }
53 #endif // DEBUG 52 #endif // DEBUG
54 53
55
56 Definition::Definition(intptr_t deopt_id) 54 Definition::Definition(intptr_t deopt_id)
57 : Instruction(deopt_id), 55 : Instruction(deopt_id),
58 range_(NULL), 56 range_(NULL),
59 type_(NULL), 57 type_(NULL),
60 temp_index_(-1), 58 temp_index_(-1),
61 ssa_temp_index_(-1), 59 ssa_temp_index_(-1),
62 input_use_list_(NULL), 60 input_use_list_(NULL),
63 env_use_list_(NULL), 61 env_use_list_(NULL),
64 constant_value_(NULL) {} 62 constant_value_(NULL) {}
65 63
66
67 // A value in the constant propagation lattice. 64 // A value in the constant propagation lattice.
68 // - non-constant sentinel 65 // - non-constant sentinel
69 // - a constant (any non-sentinel value) 66 // - a constant (any non-sentinel value)
70 // - unknown sentinel 67 // - unknown sentinel
71 Object& Definition::constant_value() { 68 Object& Definition::constant_value() {
72 if (constant_value_ == NULL) { 69 if (constant_value_ == NULL) {
73 constant_value_ = &Object::ZoneHandle(ConstantPropagator::Unknown()); 70 constant_value_ = &Object::ZoneHandle(ConstantPropagator::Unknown());
74 } 71 }
75 return *constant_value_; 72 return *constant_value_;
76 } 73 }
77 74
78
79 Definition* Definition::OriginalDefinition() { 75 Definition* Definition::OriginalDefinition() {
80 Definition* defn = this; 76 Definition* defn = this;
81 while (defn->IsRedefinition() || defn->IsAssertAssignable()) { 77 while (defn->IsRedefinition() || defn->IsAssertAssignable()) {
82 if (defn->IsRedefinition()) { 78 if (defn->IsRedefinition()) {
83 defn = defn->AsRedefinition()->value()->definition(); 79 defn = defn->AsRedefinition()->value()->definition();
84 } else { 80 } else {
85 defn = defn->AsAssertAssignable()->value()->definition(); 81 defn = defn->AsAssertAssignable()->value()->definition();
86 } 82 }
87 } 83 }
88 return defn; 84 return defn;
89 } 85 }
90 86
91
92 const ICData* Instruction::GetICData( 87 const ICData* Instruction::GetICData(
93 const ZoneGrowableArray<const ICData*>& ic_data_array) const { 88 const ZoneGrowableArray<const ICData*>& ic_data_array) const {
94 // The deopt_id can be outside the range of the IC data array for 89 // The deopt_id can be outside the range of the IC data array for
95 // computations added in the optimizing compiler. 90 // computations added in the optimizing compiler.
96 ASSERT(deopt_id_ != Thread::kNoDeoptId); 91 ASSERT(deopt_id_ != Thread::kNoDeoptId);
97 if (deopt_id_ < ic_data_array.length()) { 92 if (deopt_id_ < ic_data_array.length()) {
98 const ICData* result = ic_data_array[deopt_id_]; 93 const ICData* result = ic_data_array[deopt_id_];
99 #if defined(TAG_IC_DATA) 94 #if defined(TAG_IC_DATA)
100 if (result != NULL) { 95 if (result != NULL) {
101 if (result->tag() == -1) { 96 if (result->tag() == -1) {
102 result->set_tag(tag()); 97 result->set_tag(tag());
103 } else if (result->tag() != tag()) { 98 } else if (result->tag() != tag()) {
104 FATAL("ICData tag mismatch"); 99 FATAL("ICData tag mismatch");
105 } 100 }
106 } 101 }
107 #endif 102 #endif
108 return result; 103 return result;
109 } 104 }
110 return NULL; 105 return NULL;
111 } 106 }
112 107
113
114 intptr_t Instruction::Hashcode() const { 108 intptr_t Instruction::Hashcode() const {
115 intptr_t result = tag(); 109 intptr_t result = tag();
116 for (intptr_t i = 0; i < InputCount(); ++i) { 110 for (intptr_t i = 0; i < InputCount(); ++i) {
117 Value* value = InputAt(i); 111 Value* value = InputAt(i);
118 intptr_t j = value->definition()->ssa_temp_index(); 112 intptr_t j = value->definition()->ssa_temp_index();
119 result = result * 31 + j; 113 result = result * 31 + j;
120 } 114 }
121 return result; 115 return result;
122 } 116 }
123 117
124
125 bool Instruction::Equals(Instruction* other) const { 118 bool Instruction::Equals(Instruction* other) const {
126 if (tag() != other->tag()) return false; 119 if (tag() != other->tag()) return false;
127 for (intptr_t i = 0; i < InputCount(); ++i) { 120 for (intptr_t i = 0; i < InputCount(); ++i) {
128 if (!InputAt(i)->Equals(other->InputAt(i))) return false; 121 if (!InputAt(i)->Equals(other->InputAt(i))) return false;
129 } 122 }
130 return AttributesEqual(other); 123 return AttributesEqual(other);
131 } 124 }
132 125
133
134 void Instruction::Unsupported(FlowGraphCompiler* compiler) { 126 void Instruction::Unsupported(FlowGraphCompiler* compiler) {
135 compiler->Bailout(ToCString()); 127 compiler->Bailout(ToCString());
136 UNREACHABLE(); 128 UNREACHABLE();
137 } 129 }
138 130
139
140 bool Value::Equals(Value* other) const { 131 bool Value::Equals(Value* other) const {
141 return definition() == other->definition(); 132 return definition() == other->definition();
142 } 133 }
143 134
144
145 static int OrderById(CidRange* const* a, CidRange* const* b) { 135 static int OrderById(CidRange* const* a, CidRange* const* b) {
146 // Negative if 'a' should sort before 'b'. 136 // Negative if 'a' should sort before 'b'.
147 ASSERT((*a)->IsSingleCid()); 137 ASSERT((*a)->IsSingleCid());
148 ASSERT((*b)->IsSingleCid()); 138 ASSERT((*b)->IsSingleCid());
149 return (*a)->cid_start - (*b)->cid_start; 139 return (*a)->cid_start - (*b)->cid_start;
150 } 140 }
151 141
152
153 static int OrderByFrequency(CidRange* const* a, CidRange* const* b) { 142 static int OrderByFrequency(CidRange* const* a, CidRange* const* b) {
154 const TargetInfo* target_info_a = static_cast<const TargetInfo*>(*a); 143 const TargetInfo* target_info_a = static_cast<const TargetInfo*>(*a);
155 const TargetInfo* target_info_b = static_cast<const TargetInfo*>(*b); 144 const TargetInfo* target_info_b = static_cast<const TargetInfo*>(*b);
156 // Negative if 'a' should sort before 'b'. 145 // Negative if 'a' should sort before 'b'.
157 return target_info_b->count - target_info_a->count; 146 return target_info_b->count - target_info_a->count;
158 } 147 }
159 148
160
161 bool Cids::ContainsExternalizableCids() const { 149 bool Cids::ContainsExternalizableCids() const {
162 for (intptr_t i = 0; i < length(); i++) { 150 for (intptr_t i = 0; i < length(); i++) {
163 for (intptr_t cid = cid_ranges_[i]->cid_start; 151 for (intptr_t cid = cid_ranges_[i]->cid_start;
164 cid <= cid_ranges_[i]->cid_end; cid++) { 152 cid <= cid_ranges_[i]->cid_end; cid++) {
165 if (Field::IsExternalizableCid(cid)) { 153 if (Field::IsExternalizableCid(cid)) {
166 return true; 154 return true;
167 } 155 }
168 } 156 }
169 } 157 }
170 return false; 158 return false;
171 } 159 }
172 160
173
174 bool Cids::Equals(const Cids& other) const { 161 bool Cids::Equals(const Cids& other) const {
175 if (length() != other.length()) return false; 162 if (length() != other.length()) return false;
176 for (int i = 0; i < length(); i++) { 163 for (int i = 0; i < length(); i++) {
177 if (cid_ranges_[i]->cid_start != other.cid_ranges_[i]->cid_start || 164 if (cid_ranges_[i]->cid_start != other.cid_ranges_[i]->cid_start ||
178 cid_ranges_[i]->cid_end != other.cid_ranges_[i]->cid_end) { 165 cid_ranges_[i]->cid_end != other.cid_ranges_[i]->cid_end) {
179 return false; 166 return false;
180 } 167 }
181 } 168 }
182 return true; 169 return true;
183 } 170 }
184 171
185
186 intptr_t Cids::ComputeLowestCid() const { 172 intptr_t Cids::ComputeLowestCid() const {
187 intptr_t min = kIntptrMax; 173 intptr_t min = kIntptrMax;
188 for (intptr_t i = 0; i < cid_ranges_.length(); ++i) { 174 for (intptr_t i = 0; i < cid_ranges_.length(); ++i) {
189 min = Utils::Minimum(min, cid_ranges_[i]->cid_start); 175 min = Utils::Minimum(min, cid_ranges_[i]->cid_start);
190 } 176 }
191 return min; 177 return min;
192 } 178 }
193 179
194
195 intptr_t Cids::ComputeHighestCid() const { 180 intptr_t Cids::ComputeHighestCid() const {
196 intptr_t max = -1; 181 intptr_t max = -1;
197 for (intptr_t i = 0; i < cid_ranges_.length(); ++i) { 182 for (intptr_t i = 0; i < cid_ranges_.length(); ++i) {
198 max = Utils::Maximum(max, cid_ranges_[i]->cid_end); 183 max = Utils::Maximum(max, cid_ranges_[i]->cid_end);
199 } 184 }
200 return max; 185 return max;
201 } 186 }
202 187
203
204 bool Cids::HasClassId(intptr_t cid) const { 188 bool Cids::HasClassId(intptr_t cid) const {
205 for (int i = 0; i < length(); i++) { 189 for (int i = 0; i < length(); i++) {
206 if (cid_ranges_[i]->Contains(cid)) { 190 if (cid_ranges_[i]->Contains(cid)) {
207 return true; 191 return true;
208 } 192 }
209 } 193 }
210 return false; 194 return false;
211 } 195 }
212 196
213
214 Cids* Cids::CreateMonomorphic(Zone* zone, intptr_t cid) { 197 Cids* Cids::CreateMonomorphic(Zone* zone, intptr_t cid) {
215 Cids* cids = new (zone) Cids(zone); 198 Cids* cids = new (zone) Cids(zone);
216 cids->Add(new (zone) CidRange(cid, cid)); 199 cids->Add(new (zone) CidRange(cid, cid));
217 return cids; 200 return cids;
218 } 201 }
219 202
220
221 Cids* Cids::Create(Zone* zone, const ICData& ic_data, int argument_number) { 203 Cids* Cids::Create(Zone* zone, const ICData& ic_data, int argument_number) {
222 Cids* cids = new (zone) Cids(zone); 204 Cids* cids = new (zone) Cids(zone);
223 cids->CreateHelper(zone, ic_data, argument_number, 205 cids->CreateHelper(zone, ic_data, argument_number,
224 /* include_targets = */ false); 206 /* include_targets = */ false);
225 cids->Sort(OrderById); 207 cids->Sort(OrderById);
226 208
227 // Merge adjacent class id ranges. 209 // Merge adjacent class id ranges.
228 int dest = 0; 210 int dest = 0;
229 for (int src = 1; src < cids->length(); src++) { 211 for (int src = 1; src < cids->length(); src++) {
230 if (cids->cid_ranges_[dest]->cid_end + 1 >= 212 if (cids->cid_ranges_[dest]->cid_end + 1 >=
231 cids->cid_ranges_[src]->cid_start) { 213 cids->cid_ranges_[src]->cid_start) {
232 cids->cid_ranges_[dest]->cid_end = cids->cid_ranges_[src]->cid_end; 214 cids->cid_ranges_[dest]->cid_end = cids->cid_ranges_[src]->cid_end;
233 } else { 215 } else {
234 dest++; 216 dest++;
235 if (src != dest) cids->cid_ranges_[dest] = cids->cid_ranges_[src]; 217 if (src != dest) cids->cid_ranges_[dest] = cids->cid_ranges_[src];
236 } 218 }
237 } 219 }
238 cids->SetLength(dest + 1); 220 cids->SetLength(dest + 1);
239 221
240 return cids; 222 return cids;
241 } 223 }
242 224
243
244 void Cids::CreateHelper(Zone* zone, 225 void Cids::CreateHelper(Zone* zone,
245 const ICData& ic_data, 226 const ICData& ic_data,
246 int argument_number, 227 int argument_number,
247 bool include_targets) { 228 bool include_targets) {
248 ASSERT(argument_number < ic_data.NumArgsTested()); 229 ASSERT(argument_number < ic_data.NumArgsTested());
249 230
250 if (ic_data.NumberOfChecks() == 0) return; 231 if (ic_data.NumberOfChecks() == 0) return;
251 232
252 Function& dummy = Function::Handle(zone); 233 Function& dummy = Function::Handle(zone);
253 234
(...skipping 13 matching lines...) Expand all
267 if (include_targets) { 248 if (include_targets) {
268 Function& function = Function::ZoneHandle(zone, ic_data.GetTargetAt(i)); 249 Function& function = Function::ZoneHandle(zone, ic_data.GetTargetAt(i));
269 cid_ranges_.Add(new (zone) 250 cid_ranges_.Add(new (zone)
270 TargetInfo(id, id, &function, ic_data.GetCountAt(i))); 251 TargetInfo(id, id, &function, ic_data.GetCountAt(i)));
271 } else { 252 } else {
272 cid_ranges_.Add(new (zone) CidRange(id, id)); 253 cid_ranges_.Add(new (zone) CidRange(id, id));
273 } 254 }
274 } 255 }
275 } 256 }
276 257
277
278 bool Cids::IsMonomorphic() const { 258 bool Cids::IsMonomorphic() const {
279 if (length() != 1) return false; 259 if (length() != 1) return false;
280 return cid_ranges_[0]->IsSingleCid(); 260 return cid_ranges_[0]->IsSingleCid();
281 } 261 }
282 262
283
284 intptr_t Cids::MonomorphicReceiverCid() const { 263 intptr_t Cids::MonomorphicReceiverCid() const {
285 ASSERT(IsMonomorphic()); 264 ASSERT(IsMonomorphic());
286 return cid_ranges_[0]->cid_start; 265 return cid_ranges_[0]->cid_start;
287 } 266 }
288 267
289
290 CheckClassInstr::CheckClassInstr(Value* value, 268 CheckClassInstr::CheckClassInstr(Value* value,
291 intptr_t deopt_id, 269 intptr_t deopt_id,
292 const Cids& cids, 270 const Cids& cids,
293 TokenPosition token_pos) 271 TokenPosition token_pos)
294 : TemplateInstruction(deopt_id), 272 : TemplateInstruction(deopt_id),
295 cids_(cids), 273 cids_(cids),
296 licm_hoisted_(false), 274 licm_hoisted_(false),
297 is_bit_test_(IsCompactCidRange(cids)), 275 is_bit_test_(IsCompactCidRange(cids)),
298 token_pos_(token_pos) { 276 token_pos_(token_pos) {
299 // Expected useful check data. 277 // Expected useful check data.
300 const intptr_t number_of_checks = cids.length(); 278 const intptr_t number_of_checks = cids.length();
301 ASSERT(number_of_checks > 0); 279 ASSERT(number_of_checks > 0);
302 SetInputAt(0, value); 280 SetInputAt(0, value);
303 // Otherwise use CheckSmiInstr. 281 // Otherwise use CheckSmiInstr.
304 ASSERT(number_of_checks != 1 || !cids[0].IsSingleCid() || 282 ASSERT(number_of_checks != 1 || !cids[0].IsSingleCid() ||
305 cids[0].cid_start != kSmiCid); 283 cids[0].cid_start != kSmiCid);
306 } 284 }
307 285
308
309 bool CheckClassInstr::AttributesEqual(Instruction* other) const { 286 bool CheckClassInstr::AttributesEqual(Instruction* other) const {
310 CheckClassInstr* other_check = other->AsCheckClass(); 287 CheckClassInstr* other_check = other->AsCheckClass();
311 ASSERT(other_check != NULL); 288 ASSERT(other_check != NULL);
312 return cids().Equals(other_check->cids()); 289 return cids().Equals(other_check->cids());
313 } 290 }
314 291
315
316 EffectSet CheckClassInstr::Dependencies() const { 292 EffectSet CheckClassInstr::Dependencies() const {
317 // Externalization of strings via the API can change the class-id. 293 // Externalization of strings via the API can change the class-id.
318 return cids_.ContainsExternalizableCids() ? EffectSet::Externalization() 294 return cids_.ContainsExternalizableCids() ? EffectSet::Externalization()
319 : EffectSet::None(); 295 : EffectSet::None();
320 } 296 }
321 297
322
323 EffectSet CheckClassIdInstr::Dependencies() const { 298 EffectSet CheckClassIdInstr::Dependencies() const {
324 // Externalization of strings via the API can change the class-id. 299 // Externalization of strings via the API can change the class-id.
325 for (intptr_t i = cids_.cid_start; i <= cids_.cid_end; i++) { 300 for (intptr_t i = cids_.cid_start; i <= cids_.cid_end; i++) {
326 if (Field::IsExternalizableCid(i)) return EffectSet::Externalization(); 301 if (Field::IsExternalizableCid(i)) return EffectSet::Externalization();
327 } 302 }
328 return EffectSet::None(); 303 return EffectSet::None();
329 } 304 }
330 305
331
332 bool CheckClassInstr::IsDeoptIfNull() const { 306 bool CheckClassInstr::IsDeoptIfNull() const {
333 if (!cids().IsMonomorphic()) { 307 if (!cids().IsMonomorphic()) {
334 return false; 308 return false;
335 } 309 }
336 CompileType* in_type = value()->Type(); 310 CompileType* in_type = value()->Type();
337 const intptr_t cid = cids().MonomorphicReceiverCid(); 311 const intptr_t cid = cids().MonomorphicReceiverCid();
338 // Performance check: use CheckSmiInstr instead. 312 // Performance check: use CheckSmiInstr instead.
339 ASSERT(cid != kSmiCid); 313 ASSERT(cid != kSmiCid);
340 return in_type->is_nullable() && (in_type->ToNullableCid() == cid); 314 return in_type->is_nullable() && (in_type->ToNullableCid() == cid);
341 } 315 }
342 316
343
344 // Null object is a singleton of null-class (except for some sentinel, 317 // Null object is a singleton of null-class (except for some sentinel,
345 // transitional temporaries). Instead of checking against the null class only 318 // transitional temporaries). Instead of checking against the null class only
346 // we can check against null instance instead. 319 // we can check against null instance instead.
347 bool CheckClassInstr::IsDeoptIfNotNull() const { 320 bool CheckClassInstr::IsDeoptIfNotNull() const {
348 if (!cids().IsMonomorphic()) { 321 if (!cids().IsMonomorphic()) {
349 return false; 322 return false;
350 } 323 }
351 const intptr_t cid = cids().MonomorphicReceiverCid(); 324 const intptr_t cid = cids().MonomorphicReceiverCid();
352 return cid == kNullCid; 325 return cid == kNullCid;
353 } 326 }
354 327
355
356 bool CheckClassInstr::IsCompactCidRange(const Cids& cids) { 328 bool CheckClassInstr::IsCompactCidRange(const Cids& cids) {
357 const intptr_t number_of_checks = cids.length(); 329 const intptr_t number_of_checks = cids.length();
358 // If there are only two checks, the extra register pressure needed for the 330 // If there are only two checks, the extra register pressure needed for the
359 // dense-cid-range code is not justified. 331 // dense-cid-range code is not justified.
360 if (number_of_checks <= 2) return false; 332 if (number_of_checks <= 2) return false;
361 333
362 // TODO(fschneider): Support smis in dense cid checks. 334 // TODO(fschneider): Support smis in dense cid checks.
363 if (cids.HasClassId(kSmiCid)) return false; 335 if (cids.HasClassId(kSmiCid)) return false;
364 336
365 intptr_t min = cids.ComputeLowestCid(); 337 intptr_t min = cids.ComputeLowestCid();
366 intptr_t max = cids.ComputeHighestCid(); 338 intptr_t max = cids.ComputeHighestCid();
367 return (max - min) < kBitsPerWord; 339 return (max - min) < kBitsPerWord;
368 } 340 }
369 341
370
371 bool CheckClassInstr::IsBitTest() const { 342 bool CheckClassInstr::IsBitTest() const {
372 return is_bit_test_; 343 return is_bit_test_;
373 } 344 }
374 345
375
376 intptr_t CheckClassInstr::ComputeCidMask() const { 346 intptr_t CheckClassInstr::ComputeCidMask() const {
377 ASSERT(IsBitTest()); 347 ASSERT(IsBitTest());
378 intptr_t min = cids_.ComputeLowestCid(); 348 intptr_t min = cids_.ComputeLowestCid();
379 intptr_t mask = 0; 349 intptr_t mask = 0;
380 for (intptr_t i = 0; i < cids_.length(); ++i) { 350 for (intptr_t i = 0; i < cids_.length(); ++i) {
381 intptr_t run; 351 intptr_t run;
382 uintptr_t range = 1ul + cids_[i].Extent(); 352 uintptr_t range = 1ul + cids_[i].Extent();
383 if (range >= static_cast<uintptr_t>(kBitsPerWord)) { 353 if (range >= static_cast<uintptr_t>(kBitsPerWord)) {
384 run = -1; 354 run = -1;
385 } else { 355 } else {
386 run = (1 << range) - 1; 356 run = (1 << range) - 1;
387 } 357 }
388 mask |= run << (cids_[i].cid_start - min); 358 mask |= run << (cids_[i].cid_start - min);
389 } 359 }
390 return mask; 360 return mask;
391 } 361 }
392 362
393
394 bool LoadFieldInstr::IsUnboxedLoad() const { 363 bool LoadFieldInstr::IsUnboxedLoad() const {
395 return FLAG_unbox_numeric_fields && (field() != NULL) && 364 return FLAG_unbox_numeric_fields && (field() != NULL) &&
396 FlowGraphCompiler::IsUnboxedField(*field()); 365 FlowGraphCompiler::IsUnboxedField(*field());
397 } 366 }
398 367
399
400 bool LoadFieldInstr::IsPotentialUnboxedLoad() const { 368 bool LoadFieldInstr::IsPotentialUnboxedLoad() const {
401 return FLAG_unbox_numeric_fields && (field() != NULL) && 369 return FLAG_unbox_numeric_fields && (field() != NULL) &&
402 FlowGraphCompiler::IsPotentialUnboxedField(*field()); 370 FlowGraphCompiler::IsPotentialUnboxedField(*field());
403 } 371 }
404 372
405
406 Representation LoadFieldInstr::representation() const { 373 Representation LoadFieldInstr::representation() const {
407 if (IsUnboxedLoad()) { 374 if (IsUnboxedLoad()) {
408 const intptr_t cid = field()->UnboxedFieldCid(); 375 const intptr_t cid = field()->UnboxedFieldCid();
409 switch (cid) { 376 switch (cid) {
410 case kDoubleCid: 377 case kDoubleCid:
411 return kUnboxedDouble; 378 return kUnboxedDouble;
412 case kFloat32x4Cid: 379 case kFloat32x4Cid:
413 return kUnboxedFloat32x4; 380 return kUnboxedFloat32x4;
414 case kFloat64x2Cid: 381 case kFloat64x2Cid:
415 return kUnboxedFloat64x2; 382 return kUnboxedFloat64x2;
416 default: 383 default:
417 UNREACHABLE(); 384 UNREACHABLE();
418 } 385 }
419 } 386 }
420 return kTagged; 387 return kTagged;
421 } 388 }
422 389
423
424 bool StoreInstanceFieldInstr::IsUnboxedStore() const { 390 bool StoreInstanceFieldInstr::IsUnboxedStore() const {
425 return FLAG_unbox_numeric_fields && !field().IsNull() && 391 return FLAG_unbox_numeric_fields && !field().IsNull() &&
426 FlowGraphCompiler::IsUnboxedField(field()); 392 FlowGraphCompiler::IsUnboxedField(field());
427 } 393 }
428 394
429
430 bool StoreInstanceFieldInstr::IsPotentialUnboxedStore() const { 395 bool StoreInstanceFieldInstr::IsPotentialUnboxedStore() const {
431 return FLAG_unbox_numeric_fields && !field().IsNull() && 396 return FLAG_unbox_numeric_fields && !field().IsNull() &&
432 FlowGraphCompiler::IsPotentialUnboxedField(field()); 397 FlowGraphCompiler::IsPotentialUnboxedField(field());
433 } 398 }
434 399
435
436 Representation StoreInstanceFieldInstr::RequiredInputRepresentation( 400 Representation StoreInstanceFieldInstr::RequiredInputRepresentation(
437 intptr_t index) const { 401 intptr_t index) const {
438 ASSERT((index == 0) || (index == 1)); 402 ASSERT((index == 0) || (index == 1));
439 if ((index == 1) && IsUnboxedStore()) { 403 if ((index == 1) && IsUnboxedStore()) {
440 const intptr_t cid = field().UnboxedFieldCid(); 404 const intptr_t cid = field().UnboxedFieldCid();
441 switch (cid) { 405 switch (cid) {
442 case kDoubleCid: 406 case kDoubleCid:
443 return kUnboxedDouble; 407 return kUnboxedDouble;
444 case kFloat32x4Cid: 408 case kFloat32x4Cid:
445 return kUnboxedFloat32x4; 409 return kUnboxedFloat32x4;
446 case kFloat64x2Cid: 410 case kFloat64x2Cid:
447 return kUnboxedFloat64x2; 411 return kUnboxedFloat64x2;
448 default: 412 default:
449 UNREACHABLE(); 413 UNREACHABLE();
450 } 414 }
451 } 415 }
452 return kTagged; 416 return kTagged;
453 } 417 }
454 418
455
456 bool GuardFieldClassInstr::AttributesEqual(Instruction* other) const { 419 bool GuardFieldClassInstr::AttributesEqual(Instruction* other) const {
457 return field().raw() == other->AsGuardFieldClass()->field().raw(); 420 return field().raw() == other->AsGuardFieldClass()->field().raw();
458 } 421 }
459 422
460
461 bool GuardFieldLengthInstr::AttributesEqual(Instruction* other) const { 423 bool GuardFieldLengthInstr::AttributesEqual(Instruction* other) const {
462 return field().raw() == other->AsGuardFieldLength()->field().raw(); 424 return field().raw() == other->AsGuardFieldLength()->field().raw();
463 } 425 }
464 426
465
466 bool AssertAssignableInstr::AttributesEqual(Instruction* other) const { 427 bool AssertAssignableInstr::AttributesEqual(Instruction* other) const {
467 AssertAssignableInstr* other_assert = other->AsAssertAssignable(); 428 AssertAssignableInstr* other_assert = other->AsAssertAssignable();
468 ASSERT(other_assert != NULL); 429 ASSERT(other_assert != NULL);
469 // This predicate has to be commutative for DominatorBasedCSE to work. 430 // This predicate has to be commutative for DominatorBasedCSE to work.
470 // TODO(fschneider): Eliminate more asserts with subtype relation. 431 // TODO(fschneider): Eliminate more asserts with subtype relation.
471 return dst_type().raw() == other_assert->dst_type().raw(); 432 return dst_type().raw() == other_assert->dst_type().raw();
472 } 433 }
473 434
474
475 bool StrictCompareInstr::AttributesEqual(Instruction* other) const { 435 bool StrictCompareInstr::AttributesEqual(Instruction* other) const {
476 StrictCompareInstr* other_op = other->AsStrictCompare(); 436 StrictCompareInstr* other_op = other->AsStrictCompare();
477 ASSERT(other_op != NULL); 437 ASSERT(other_op != NULL);
478 return ComparisonInstr::AttributesEqual(other) && 438 return ComparisonInstr::AttributesEqual(other) &&
479 (needs_number_check() == other_op->needs_number_check()); 439 (needs_number_check() == other_op->needs_number_check());
480 } 440 }
481 441
482
483 bool MathMinMaxInstr::AttributesEqual(Instruction* other) const { 442 bool MathMinMaxInstr::AttributesEqual(Instruction* other) const {
484 MathMinMaxInstr* other_op = other->AsMathMinMax(); 443 MathMinMaxInstr* other_op = other->AsMathMinMax();
485 ASSERT(other_op != NULL); 444 ASSERT(other_op != NULL);
486 return (op_kind() == other_op->op_kind()) && 445 return (op_kind() == other_op->op_kind()) &&
487 (result_cid() == other_op->result_cid()); 446 (result_cid() == other_op->result_cid());
488 } 447 }
489 448
490
491 bool BinaryIntegerOpInstr::AttributesEqual(Instruction* other) const { 449 bool BinaryIntegerOpInstr::AttributesEqual(Instruction* other) const {
492 ASSERT(other->tag() == tag()); 450 ASSERT(other->tag() == tag());
493 BinaryIntegerOpInstr* other_op = other->AsBinaryIntegerOp(); 451 BinaryIntegerOpInstr* other_op = other->AsBinaryIntegerOp();
494 return (op_kind() == other_op->op_kind()) && 452 return (op_kind() == other_op->op_kind()) &&
495 (can_overflow() == other_op->can_overflow()) && 453 (can_overflow() == other_op->can_overflow()) &&
496 (is_truncating() == other_op->is_truncating()); 454 (is_truncating() == other_op->is_truncating());
497 } 455 }
498 456
499
500 EffectSet LoadFieldInstr::Dependencies() const { 457 EffectSet LoadFieldInstr::Dependencies() const {
501 return immutable_ ? EffectSet::None() : EffectSet::All(); 458 return immutable_ ? EffectSet::None() : EffectSet::All();
502 } 459 }
503 460
504
505 bool LoadFieldInstr::AttributesEqual(Instruction* other) const { 461 bool LoadFieldInstr::AttributesEqual(Instruction* other) const {
506 LoadFieldInstr* other_load = other->AsLoadField(); 462 LoadFieldInstr* other_load = other->AsLoadField();
507 ASSERT(other_load != NULL); 463 ASSERT(other_load != NULL);
508 if (field() != NULL) { 464 if (field() != NULL) {
509 return (other_load->field() != NULL) && 465 return (other_load->field() != NULL) &&
510 (field()->raw() == other_load->field()->raw()); 466 (field()->raw() == other_load->field()->raw());
511 } 467 }
512 return (other_load->field() == NULL) && 468 return (other_load->field() == NULL) &&
513 (offset_in_bytes() == other_load->offset_in_bytes()); 469 (offset_in_bytes() == other_load->offset_in_bytes());
514 } 470 }
515 471
516
517 Instruction* InitStaticFieldInstr::Canonicalize(FlowGraph* flow_graph) { 472 Instruction* InitStaticFieldInstr::Canonicalize(FlowGraph* flow_graph) {
518 const bool is_initialized = 473 const bool is_initialized =
519 (field_.StaticValue() != Object::sentinel().raw()) && 474 (field_.StaticValue() != Object::sentinel().raw()) &&
520 (field_.StaticValue() != Object::transition_sentinel().raw()); 475 (field_.StaticValue() != Object::transition_sentinel().raw());
521 // When precompiling, the fact that a field is currently initialized does not 476 // When precompiling, the fact that a field is currently initialized does not
522 // make it safe to omit code that checks if the field needs initialization 477 // make it safe to omit code that checks if the field needs initialization
523 // because the field will be reset so it starts uninitialized in the process 478 // because the field will be reset so it starts uninitialized in the process
524 // running the precompiled code. We must be prepared to reinitialize fields. 479 // running the precompiled code. We must be prepared to reinitialize fields.
525 return is_initialized && !FLAG_fields_may_be_reset ? NULL : this; 480 return is_initialized && !FLAG_fields_may_be_reset ? NULL : this;
526 } 481 }
527 482
528
529 EffectSet LoadStaticFieldInstr::Dependencies() const { 483 EffectSet LoadStaticFieldInstr::Dependencies() const {
530 return (StaticField().is_final() && !FLAG_fields_may_be_reset) 484 return (StaticField().is_final() && !FLAG_fields_may_be_reset)
531 ? EffectSet::None() 485 ? EffectSet::None()
532 : EffectSet::All(); 486 : EffectSet::All();
533 } 487 }
534 488
535
536 bool LoadStaticFieldInstr::AttributesEqual(Instruction* other) const { 489 bool LoadStaticFieldInstr::AttributesEqual(Instruction* other) const {
537 LoadStaticFieldInstr* other_load = other->AsLoadStaticField(); 490 LoadStaticFieldInstr* other_load = other->AsLoadStaticField();
538 ASSERT(other_load != NULL); 491 ASSERT(other_load != NULL);
539 // Assert that the field is initialized. 492 // Assert that the field is initialized.
540 ASSERT(StaticField().StaticValue() != Object::sentinel().raw()); 493 ASSERT(StaticField().StaticValue() != Object::sentinel().raw());
541 ASSERT(StaticField().StaticValue() != Object::transition_sentinel().raw()); 494 ASSERT(StaticField().StaticValue() != Object::transition_sentinel().raw());
542 return StaticField().raw() == other_load->StaticField().raw(); 495 return StaticField().raw() == other_load->StaticField().raw();
543 } 496 }
544 497
545
546 const Field& LoadStaticFieldInstr::StaticField() const { 498 const Field& LoadStaticFieldInstr::StaticField() const {
547 Field& field = Field::ZoneHandle(); 499 Field& field = Field::ZoneHandle();
548 field ^= field_value()->BoundConstant().raw(); 500 field ^= field_value()->BoundConstant().raw();
549 return field; 501 return field;
550 } 502 }
551 503
552
553 ConstantInstr::ConstantInstr(const Object& value, TokenPosition token_pos) 504 ConstantInstr::ConstantInstr(const Object& value, TokenPosition token_pos)
554 : value_(value), token_pos_(token_pos) { 505 : value_(value), token_pos_(token_pos) {
555 // Check that the value is not an incorrect Integer representation. 506 // Check that the value is not an incorrect Integer representation.
556 ASSERT(!value.IsBigint() || !Bigint::Cast(value).FitsIntoSmi()); 507 ASSERT(!value.IsBigint() || !Bigint::Cast(value).FitsIntoSmi());
557 ASSERT(!value.IsBigint() || !Bigint::Cast(value).FitsIntoInt64()); 508 ASSERT(!value.IsBigint() || !Bigint::Cast(value).FitsIntoInt64());
558 ASSERT(!value.IsMint() || !Smi::IsValid(Mint::Cast(value).AsInt64Value())); 509 ASSERT(!value.IsMint() || !Smi::IsValid(Mint::Cast(value).AsInt64Value()));
559 ASSERT(!value.IsField() || Field::Cast(value).IsOriginal()); 510 ASSERT(!value.IsField() || Field::Cast(value).IsOriginal());
560 } 511 }
561 512
562
563 bool ConstantInstr::AttributesEqual(Instruction* other) const { 513 bool ConstantInstr::AttributesEqual(Instruction* other) const {
564 ConstantInstr* other_constant = other->AsConstant(); 514 ConstantInstr* other_constant = other->AsConstant();
565 ASSERT(other_constant != NULL); 515 ASSERT(other_constant != NULL);
566 return (value().raw() == other_constant->value().raw()); 516 return (value().raw() == other_constant->value().raw());
567 } 517 }
568 518
569
570 UnboxedConstantInstr::UnboxedConstantInstr(const Object& value, 519 UnboxedConstantInstr::UnboxedConstantInstr(const Object& value,
571 Representation representation) 520 Representation representation)
572 : ConstantInstr(value), 521 : ConstantInstr(value),
573 representation_(representation), 522 representation_(representation),
574 constant_address_(0) { 523 constant_address_(0) {
575 if (representation_ == kUnboxedDouble) { 524 if (representation_ == kUnboxedDouble) {
576 ASSERT(value.IsDouble()); 525 ASSERT(value.IsDouble());
577 constant_address_ = 526 constant_address_ =
578 FlowGraphBuilder::FindDoubleConstant(Double::Cast(value).value()); 527 FlowGraphBuilder::FindDoubleConstant(Double::Cast(value).value());
579 } 528 }
580 } 529 }
581 530
582
583 // Returns true if the value represents a constant. 531 // Returns true if the value represents a constant.
584 bool Value::BindsToConstant() const { 532 bool Value::BindsToConstant() const {
585 return definition()->IsConstant(); 533 return definition()->IsConstant();
586 } 534 }
587 535
588
589 // Returns true if the value represents constant null. 536 // Returns true if the value represents constant null.
590 bool Value::BindsToConstantNull() const { 537 bool Value::BindsToConstantNull() const {
591 ConstantInstr* constant = definition()->AsConstant(); 538 ConstantInstr* constant = definition()->AsConstant();
592 return (constant != NULL) && constant->value().IsNull(); 539 return (constant != NULL) && constant->value().IsNull();
593 } 540 }
594 541
595
596 const Object& Value::BoundConstant() const { 542 const Object& Value::BoundConstant() const {
597 ASSERT(BindsToConstant()); 543 ASSERT(BindsToConstant());
598 ConstantInstr* constant = definition()->AsConstant(); 544 ConstantInstr* constant = definition()->AsConstant();
599 ASSERT(constant != NULL); 545 ASSERT(constant != NULL);
600 return constant->value(); 546 return constant->value();
601 } 547 }
602 548
603
604 GraphEntryInstr::GraphEntryInstr(const ParsedFunction& parsed_function, 549 GraphEntryInstr::GraphEntryInstr(const ParsedFunction& parsed_function,
605 TargetEntryInstr* normal_entry, 550 TargetEntryInstr* normal_entry,
606 intptr_t osr_id) 551 intptr_t osr_id)
607 : BlockEntryInstr(0, 552 : BlockEntryInstr(0,
608 CatchClauseNode::kInvalidTryIndex, 553 CatchClauseNode::kInvalidTryIndex,
609 Thread::Current()->GetNextDeoptId()), 554 Thread::Current()->GetNextDeoptId()),
610 parsed_function_(parsed_function), 555 parsed_function_(parsed_function),
611 normal_entry_(normal_entry), 556 normal_entry_(normal_entry),
612 catch_entries_(), 557 catch_entries_(),
613 indirect_entries_(), 558 indirect_entries_(),
614 initial_definitions_(), 559 initial_definitions_(),
615 osr_id_(osr_id), 560 osr_id_(osr_id),
616 entry_count_(0), 561 entry_count_(0),
617 spill_slot_count_(0), 562 spill_slot_count_(0),
618 fixed_slot_count_(0) {} 563 fixed_slot_count_(0) {}
619 564
620
621 ConstantInstr* GraphEntryInstr::constant_null() { 565 ConstantInstr* GraphEntryInstr::constant_null() {
622 ASSERT(initial_definitions_.length() > 0); 566 ASSERT(initial_definitions_.length() > 0);
623 for (intptr_t i = 0; i < initial_definitions_.length(); ++i) { 567 for (intptr_t i = 0; i < initial_definitions_.length(); ++i) {
624 ConstantInstr* defn = initial_definitions_[i]->AsConstant(); 568 ConstantInstr* defn = initial_definitions_[i]->AsConstant();
625 if (defn != NULL && defn->value().IsNull()) return defn; 569 if (defn != NULL && defn->value().IsNull()) return defn;
626 } 570 }
627 UNREACHABLE(); 571 UNREACHABLE();
628 return NULL; 572 return NULL;
629 } 573 }
630 574
631
632 CatchBlockEntryInstr* GraphEntryInstr::GetCatchEntry(intptr_t index) { 575 CatchBlockEntryInstr* GraphEntryInstr::GetCatchEntry(intptr_t index) {
633 // TODO(fschneider): Sort the catch entries by catch_try_index to avoid 576 // TODO(fschneider): Sort the catch entries by catch_try_index to avoid
634 // searching. 577 // searching.
635 for (intptr_t i = 0; i < catch_entries_.length(); ++i) { 578 for (intptr_t i = 0; i < catch_entries_.length(); ++i) {
636 if (catch_entries_[i]->catch_try_index() == index) return catch_entries_[i]; 579 if (catch_entries_[i]->catch_try_index() == index) return catch_entries_[i];
637 } 580 }
638 return NULL; 581 return NULL;
639 } 582 }
640 583
641
642 bool GraphEntryInstr::IsCompiledForOsr() const { 584 bool GraphEntryInstr::IsCompiledForOsr() const {
643 return osr_id_ != Compiler::kNoOSRDeoptId; 585 return osr_id_ != Compiler::kNoOSRDeoptId;
644 } 586 }
645 587
646
647 // ==== Support for visiting flow graphs. 588 // ==== Support for visiting flow graphs.
648 589
649 #define DEFINE_ACCEPT(ShortName) \ 590 #define DEFINE_ACCEPT(ShortName) \
650 void ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \ 591 void ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \
651 visitor->Visit##ShortName(this); \ 592 visitor->Visit##ShortName(this); \
652 } 593 }
653 594
654 FOR_EACH_INSTRUCTION(DEFINE_ACCEPT) 595 FOR_EACH_INSTRUCTION(DEFINE_ACCEPT)
655 596
656 #undef DEFINE_ACCEPT 597 #undef DEFINE_ACCEPT
657 598
658
659 void Instruction::SetEnvironment(Environment* deopt_env) { 599 void Instruction::SetEnvironment(Environment* deopt_env) {
660 intptr_t use_index = 0; 600 intptr_t use_index = 0;
661 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) { 601 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
662 Value* use = it.CurrentValue(); 602 Value* use = it.CurrentValue();
663 use->set_instruction(this); 603 use->set_instruction(this);
664 use->set_use_index(use_index++); 604 use->set_use_index(use_index++);
665 } 605 }
666 env_ = deopt_env; 606 env_ = deopt_env;
667 } 607 }
668 608
669
670 void Instruction::RemoveEnvironment() { 609 void Instruction::RemoveEnvironment() {
671 for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) { 610 for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) {
672 it.CurrentValue()->RemoveFromUseList(); 611 it.CurrentValue()->RemoveFromUseList();
673 } 612 }
674 env_ = NULL; 613 env_ = NULL;
675 } 614 }
676 615
677
678 Instruction* Instruction::RemoveFromGraph(bool return_previous) { 616 Instruction* Instruction::RemoveFromGraph(bool return_previous) {
679 ASSERT(!IsBlockEntry()); 617 ASSERT(!IsBlockEntry());
680 ASSERT(!IsBranch()); 618 ASSERT(!IsBranch());
681 ASSERT(!IsThrow()); 619 ASSERT(!IsThrow());
682 ASSERT(!IsReturn()); 620 ASSERT(!IsReturn());
683 ASSERT(!IsReThrow()); 621 ASSERT(!IsReThrow());
684 ASSERT(!IsGoto()); 622 ASSERT(!IsGoto());
685 ASSERT(previous() != NULL); 623 ASSERT(previous() != NULL);
686 // We cannot assert that the instruction, if it is a definition, has no 624 // We cannot assert that the instruction, if it is a definition, has no
687 // uses. This function is used to remove instructions from the graph and 625 // uses. This function is used to remove instructions from the graph and
688 // reinsert them elsewhere (e.g., hoisting). 626 // reinsert them elsewhere (e.g., hoisting).
689 Instruction* prev_instr = previous(); 627 Instruction* prev_instr = previous();
690 Instruction* next_instr = next(); 628 Instruction* next_instr = next();
691 ASSERT(next_instr != NULL); 629 ASSERT(next_instr != NULL);
692 ASSERT(!next_instr->IsBlockEntry()); 630 ASSERT(!next_instr->IsBlockEntry());
693 prev_instr->LinkTo(next_instr); 631 prev_instr->LinkTo(next_instr);
694 UnuseAllInputs(); 632 UnuseAllInputs();
695 // Reset the successor and previous instruction to indicate that the 633 // Reset the successor and previous instruction to indicate that the
696 // instruction is removed from the graph. 634 // instruction is removed from the graph.
697 set_previous(NULL); 635 set_previous(NULL);
698 set_next(NULL); 636 set_next(NULL);
699 return return_previous ? prev_instr : next_instr; 637 return return_previous ? prev_instr : next_instr;
700 } 638 }
701 639
702
703 void Instruction::InsertAfter(Instruction* prev) { 640 void Instruction::InsertAfter(Instruction* prev) {
704 ASSERT(previous_ == NULL); 641 ASSERT(previous_ == NULL);
705 ASSERT(next_ == NULL); 642 ASSERT(next_ == NULL);
706 previous_ = prev; 643 previous_ = prev;
707 next_ = prev->next_; 644 next_ = prev->next_;
708 next_->previous_ = this; 645 next_->previous_ = this;
709 previous_->next_ = this; 646 previous_->next_ = this;
710 647
711 // Update def-use chains whenever instructions are added to the graph 648 // Update def-use chains whenever instructions are added to the graph
712 // after initial graph construction. 649 // after initial graph construction.
713 for (intptr_t i = InputCount() - 1; i >= 0; --i) { 650 for (intptr_t i = InputCount() - 1; i >= 0; --i) {
714 Value* input = InputAt(i); 651 Value* input = InputAt(i);
715 input->definition()->AddInputUse(input); 652 input->definition()->AddInputUse(input);
716 } 653 }
717 } 654 }
718 655
719
720 Instruction* Instruction::AppendInstruction(Instruction* tail) { 656 Instruction* Instruction::AppendInstruction(Instruction* tail) {
721 LinkTo(tail); 657 LinkTo(tail);
722 // Update def-use chains whenever instructions are added to the graph 658 // Update def-use chains whenever instructions are added to the graph
723 // after initial graph construction. 659 // after initial graph construction.
724 for (intptr_t i = tail->InputCount() - 1; i >= 0; --i) { 660 for (intptr_t i = tail->InputCount() - 1; i >= 0; --i) {
725 Value* input = tail->InputAt(i); 661 Value* input = tail->InputAt(i);
726 input->definition()->AddInputUse(input); 662 input->definition()->AddInputUse(input);
727 } 663 }
728 return tail; 664 return tail;
729 } 665 }
730 666
731
732 BlockEntryInstr* Instruction::GetBlock() { 667 BlockEntryInstr* Instruction::GetBlock() {
733 // TODO(fschneider): Implement a faster way to get the block of an 668 // TODO(fschneider): Implement a faster way to get the block of an
734 // instruction. 669 // instruction.
735 ASSERT(previous() != NULL); 670 ASSERT(previous() != NULL);
736 Instruction* result = previous(); 671 Instruction* result = previous();
737 while (!result->IsBlockEntry()) 672 while (!result->IsBlockEntry())
738 result = result->previous(); 673 result = result->previous();
739 return result->AsBlockEntry(); 674 return result->AsBlockEntry();
740 } 675 }
741 676
742
743 void ForwardInstructionIterator::RemoveCurrentFromGraph() { 677 void ForwardInstructionIterator::RemoveCurrentFromGraph() {
744 current_ = current_->RemoveFromGraph(true); // Set current_ to previous. 678 current_ = current_->RemoveFromGraph(true); // Set current_ to previous.
745 } 679 }
746 680
747
748 void BackwardInstructionIterator::RemoveCurrentFromGraph() { 681 void BackwardInstructionIterator::RemoveCurrentFromGraph() {
749 current_ = current_->RemoveFromGraph(false); // Set current_ to next. 682 current_ = current_->RemoveFromGraph(false); // Set current_ to next.
750 } 683 }
751 684
752
753 // Default implementation of visiting basic blocks. Can be overridden. 685 // Default implementation of visiting basic blocks. Can be overridden.
754 void FlowGraphVisitor::VisitBlocks() { 686 void FlowGraphVisitor::VisitBlocks() {
755 ASSERT(current_iterator_ == NULL); 687 ASSERT(current_iterator_ == NULL);
756 for (intptr_t i = 0; i < block_order_.length(); ++i) { 688 for (intptr_t i = 0; i < block_order_.length(); ++i) {
757 BlockEntryInstr* entry = block_order_[i]; 689 BlockEntryInstr* entry = block_order_[i];
758 entry->Accept(this); 690 entry->Accept(this);
759 ForwardInstructionIterator it(entry); 691 ForwardInstructionIterator it(entry);
760 current_iterator_ = &it; 692 current_iterator_ = &it;
761 for (; !it.Done(); it.Advance()) { 693 for (; !it.Done(); it.Advance()) {
762 it.Current()->Accept(this); 694 it.Current()->Accept(this);
763 } 695 }
764 current_iterator_ = NULL; 696 current_iterator_ = NULL;
765 } 697 }
766 } 698 }
767 699
768
769 bool Value::NeedsStoreBuffer() { 700 bool Value::NeedsStoreBuffer() {
770 if (Type()->IsNull() || (Type()->ToNullableCid() == kSmiCid) || 701 if (Type()->IsNull() || (Type()->ToNullableCid() == kSmiCid) ||
771 (Type()->ToNullableCid() == kBoolCid)) { 702 (Type()->ToNullableCid() == kBoolCid)) {
772 return false; 703 return false;
773 } 704 }
774 705
775 return !BindsToConstant(); 706 return !BindsToConstant();
776 } 707 }
777 708
778
779 void JoinEntryInstr::AddPredecessor(BlockEntryInstr* predecessor) { 709 void JoinEntryInstr::AddPredecessor(BlockEntryInstr* predecessor) {
780 // Require the predecessors to be sorted by block_id to make managing 710 // Require the predecessors to be sorted by block_id to make managing
781 // their corresponding phi inputs simpler. 711 // their corresponding phi inputs simpler.
782 intptr_t pred_id = predecessor->block_id(); 712 intptr_t pred_id = predecessor->block_id();
783 intptr_t index = 0; 713 intptr_t index = 0;
784 while ((index < predecessors_.length()) && 714 while ((index < predecessors_.length()) &&
785 (predecessors_[index]->block_id() < pred_id)) { 715 (predecessors_[index]->block_id() < pred_id)) {
786 ++index; 716 ++index;
787 } 717 }
788 #if defined(DEBUG) 718 #if defined(DEBUG)
789 for (intptr_t i = index; i < predecessors_.length(); ++i) { 719 for (intptr_t i = index; i < predecessors_.length(); ++i) {
790 ASSERT(predecessors_[i]->block_id() != pred_id); 720 ASSERT(predecessors_[i]->block_id() != pred_id);
791 } 721 }
792 #endif 722 #endif
793 predecessors_.InsertAt(index, predecessor); 723 predecessors_.InsertAt(index, predecessor);
794 } 724 }
795 725
796
797 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { 726 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const {
798 for (intptr_t i = 0; i < predecessors_.length(); ++i) { 727 for (intptr_t i = 0; i < predecessors_.length(); ++i) {
799 if (predecessors_[i] == pred) return i; 728 if (predecessors_[i] == pred) return i;
800 } 729 }
801 return -1; 730 return -1;
802 } 731 }
803 732
804
805 void Value::AddToList(Value* value, Value** list) { 733 void Value::AddToList(Value* value, Value** list) {
806 Value* next = *list; 734 Value* next = *list;
807 *list = value; 735 *list = value;
808 value->set_next_use(next); 736 value->set_next_use(next);
809 value->set_previous_use(NULL); 737 value->set_previous_use(NULL);
810 if (next != NULL) next->set_previous_use(value); 738 if (next != NULL) next->set_previous_use(value);
811 } 739 }
812 740
813
814 void Value::RemoveFromUseList() { 741 void Value::RemoveFromUseList() {
815 Definition* def = definition(); 742 Definition* def = definition();
816 Value* next = next_use(); 743 Value* next = next_use();
817 if (this == def->input_use_list()) { 744 if (this == def->input_use_list()) {
818 def->set_input_use_list(next); 745 def->set_input_use_list(next);
819 if (next != NULL) next->set_previous_use(NULL); 746 if (next != NULL) next->set_previous_use(NULL);
820 } else if (this == def->env_use_list()) { 747 } else if (this == def->env_use_list()) {
821 def->set_env_use_list(next); 748 def->set_env_use_list(next);
822 if (next != NULL) next->set_previous_use(NULL); 749 if (next != NULL) next->set_previous_use(NULL);
823 } else { 750 } else {
824 Value* prev = previous_use(); 751 Value* prev = previous_use();
825 prev->set_next_use(next); 752 prev->set_next_use(next);
826 if (next != NULL) next->set_previous_use(prev); 753 if (next != NULL) next->set_previous_use(prev);
827 } 754 }
828 755
829 set_previous_use(NULL); 756 set_previous_use(NULL);
830 set_next_use(NULL); 757 set_next_use(NULL);
831 } 758 }
832 759
833
834 // True if the definition has a single input use and is used only in 760 // True if the definition has a single input use and is used only in
835 // environments at the same instruction as that input use. 761 // environments at the same instruction as that input use.
836 bool Definition::HasOnlyUse(Value* use) const { 762 bool Definition::HasOnlyUse(Value* use) const {
837 if (!HasOnlyInputUse(use)) { 763 if (!HasOnlyInputUse(use)) {
838 return false; 764 return false;
839 } 765 }
840 766
841 Instruction* target = use->instruction(); 767 Instruction* target = use->instruction();
842 for (Value::Iterator it(env_use_list()); !it.Done(); it.Advance()) { 768 for (Value::Iterator it(env_use_list()); !it.Done(); it.Advance()) {
843 if (it.Current()->instruction() != target) return false; 769 if (it.Current()->instruction() != target) return false;
844 } 770 }
845 return true; 771 return true;
846 } 772 }
847 773
848
849 bool Definition::HasOnlyInputUse(Value* use) const { 774 bool Definition::HasOnlyInputUse(Value* use) const {
850 return (input_use_list() == use) && (use->next_use() == NULL); 775 return (input_use_list() == use) && (use->next_use() == NULL);
851 } 776 }
852 777
853
854 void Definition::ReplaceUsesWith(Definition* other) { 778 void Definition::ReplaceUsesWith(Definition* other) {
855 ASSERT(other != NULL); 779 ASSERT(other != NULL);
856 ASSERT(this != other); 780 ASSERT(this != other);
857 781
858 Value* current = NULL; 782 Value* current = NULL;
859 Value* next = input_use_list(); 783 Value* next = input_use_list();
860 if (next != NULL) { 784 if (next != NULL) {
861 // Change all the definitions. 785 // Change all the definitions.
862 while (next != NULL) { 786 while (next != NULL) {
863 current = next; 787 current = next;
(...skipping 19 matching lines...) Expand all
883 next = current->next_use(); 807 next = current->next_use();
884 } 808 }
885 next = other->env_use_list(); 809 next = other->env_use_list();
886 current->set_next_use(next); 810 current->set_next_use(next);
887 if (next != NULL) next->set_previous_use(current); 811 if (next != NULL) next->set_previous_use(current);
888 other->set_env_use_list(env_use_list()); 812 other->set_env_use_list(env_use_list());
889 set_env_use_list(NULL); 813 set_env_use_list(NULL);
890 } 814 }
891 } 815 }
892 816
893
894 void Instruction::UnuseAllInputs() { 817 void Instruction::UnuseAllInputs() {
895 for (intptr_t i = InputCount() - 1; i >= 0; --i) { 818 for (intptr_t i = InputCount() - 1; i >= 0; --i) {
896 InputAt(i)->RemoveFromUseList(); 819 InputAt(i)->RemoveFromUseList();
897 } 820 }
898 for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) { 821 for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) {
899 it.CurrentValue()->RemoveFromUseList(); 822 it.CurrentValue()->RemoveFromUseList();
900 } 823 }
901 } 824 }
902 825
903
904 void Instruction::InheritDeoptTargetAfter(FlowGraph* flow_graph, 826 void Instruction::InheritDeoptTargetAfter(FlowGraph* flow_graph,
905 Definition* call, 827 Definition* call,
906 Definition* result) { 828 Definition* result) {
907 ASSERT(call->env() != NULL); 829 ASSERT(call->env() != NULL);
908 deopt_id_ = Thread::ToDeoptAfter(call->deopt_id_); 830 deopt_id_ = Thread::ToDeoptAfter(call->deopt_id_);
909 call->env()->DeepCopyAfterTo( 831 call->env()->DeepCopyAfterTo(
910 flow_graph->zone(), this, call->ArgumentCount(), 832 flow_graph->zone(), this, call->ArgumentCount(),
911 flow_graph->constant_dead(), 833 flow_graph->constant_dead(),
912 result != NULL ? result : flow_graph->constant_dead()); 834 result != NULL ? result : flow_graph->constant_dead());
913 env()->set_deopt_id(deopt_id_); 835 env()->set_deopt_id(deopt_id_);
914 } 836 }
915 837
916
917 void Instruction::InheritDeoptTarget(Zone* zone, Instruction* other) { 838 void Instruction::InheritDeoptTarget(Zone* zone, Instruction* other) {
918 ASSERT(other->env() != NULL); 839 ASSERT(other->env() != NULL);
919 CopyDeoptIdFrom(*other); 840 CopyDeoptIdFrom(*other);
920 other->env()->DeepCopyTo(zone, this); 841 other->env()->DeepCopyTo(zone, this);
921 env()->set_deopt_id(deopt_id_); 842 env()->set_deopt_id(deopt_id_);
922 } 843 }
923 844
924
925 void BranchInstr::InheritDeoptTarget(Zone* zone, Instruction* other) { 845 void BranchInstr::InheritDeoptTarget(Zone* zone, Instruction* other) {
926 ASSERT(env() == NULL); 846 ASSERT(env() == NULL);
927 Instruction::InheritDeoptTarget(zone, other); 847 Instruction::InheritDeoptTarget(zone, other);
928 comparison()->SetDeoptId(*this); 848 comparison()->SetDeoptId(*this);
929 } 849 }
930 850
931
932 bool Instruction::IsDominatedBy(Instruction* dom) { 851 bool Instruction::IsDominatedBy(Instruction* dom) {
933 BlockEntryInstr* block = GetBlock(); 852 BlockEntryInstr* block = GetBlock();
934 BlockEntryInstr* dom_block = dom->GetBlock(); 853 BlockEntryInstr* dom_block = dom->GetBlock();
935 854
936 if (dom->IsPhi()) { 855 if (dom->IsPhi()) {
937 dom = dom_block; 856 dom = dom_block;
938 } 857 }
939 858
940 if (block == dom_block) { 859 if (block == dom_block) {
941 if ((block == dom) || (this == block->last_instruction())) { 860 if ((block == dom) || (this == block->last_instruction())) {
942 return true; 861 return true;
943 } 862 }
944 863
945 if (IsPhi()) { 864 if (IsPhi()) {
946 return false; 865 return false;
947 } 866 }
948 867
949 for (Instruction* curr = dom->next(); curr != NULL; curr = curr->next()) { 868 for (Instruction* curr = dom->next(); curr != NULL; curr = curr->next()) {
950 if (curr == this) return true; 869 if (curr == this) return true;
951 } 870 }
952 871
953 return false; 872 return false;
954 } 873 }
955 874
956 return dom_block->Dominates(block); 875 return dom_block->Dominates(block);
957 } 876 }
958 877
959
960 bool Instruction::HasUnmatchedInputRepresentations() const { 878 bool Instruction::HasUnmatchedInputRepresentations() const {
961 for (intptr_t i = 0; i < InputCount(); i++) { 879 for (intptr_t i = 0; i < InputCount(); i++) {
962 Definition* input = InputAt(i)->definition(); 880 Definition* input = InputAt(i)->definition();
963 if (RequiredInputRepresentation(i) != input->representation()) { 881 if (RequiredInputRepresentation(i) != input->representation()) {
964 return true; 882 return true;
965 } 883 }
966 } 884 }
967 885
968 return false; 886 return false;
969 } 887 }
970 888
971
972 void Definition::ReplaceWith(Definition* other, 889 void Definition::ReplaceWith(Definition* other,
973 ForwardInstructionIterator* iterator) { 890 ForwardInstructionIterator* iterator) {
974 // Record other's input uses. 891 // Record other's input uses.
975 for (intptr_t i = other->InputCount() - 1; i >= 0; --i) { 892 for (intptr_t i = other->InputCount() - 1; i >= 0; --i) {
976 Value* input = other->InputAt(i); 893 Value* input = other->InputAt(i);
977 input->definition()->AddInputUse(input); 894 input->definition()->AddInputUse(input);
978 } 895 }
979 // Take other's environment from this definition. 896 // Take other's environment from this definition.
980 ASSERT(other->env() == NULL); 897 ASSERT(other->env() == NULL);
981 other->SetEnvironment(env()); 898 other->SetEnvironment(env());
(...skipping 14 matching lines...) Expand all
996 iterator->RemoveCurrentFromGraph(); 913 iterator->RemoveCurrentFromGraph();
997 } else { 914 } else {
998 other->LinkTo(next()); 915 other->LinkTo(next());
999 // Remove this definition's input uses. 916 // Remove this definition's input uses.
1000 UnuseAllInputs(); 917 UnuseAllInputs();
1001 } 918 }
1002 set_previous(NULL); 919 set_previous(NULL);
1003 set_next(NULL); 920 set_next(NULL);
1004 } 921 }
1005 922
1006
1007 void BranchInstr::SetComparison(ComparisonInstr* new_comparison) { 923 void BranchInstr::SetComparison(ComparisonInstr* new_comparison) {
1008 for (intptr_t i = new_comparison->InputCount() - 1; i >= 0; --i) { 924 for (intptr_t i = new_comparison->InputCount() - 1; i >= 0; --i) {
1009 Value* input = new_comparison->InputAt(i); 925 Value* input = new_comparison->InputAt(i);
1010 input->definition()->AddInputUse(input); 926 input->definition()->AddInputUse(input);
1011 input->set_instruction(this); 927 input->set_instruction(this);
1012 } 928 }
1013 // There should be no need to copy or unuse an environment. 929 // There should be no need to copy or unuse an environment.
1014 ASSERT(comparison()->env() == NULL); 930 ASSERT(comparison()->env() == NULL);
1015 ASSERT(new_comparison->env() == NULL); 931 ASSERT(new_comparison->env() == NULL);
1016 // Remove the current comparison's input uses. 932 // Remove the current comparison's input uses.
1017 comparison()->UnuseAllInputs(); 933 comparison()->UnuseAllInputs();
1018 ASSERT(!new_comparison->HasUses()); 934 ASSERT(!new_comparison->HasUses());
1019 comparison_ = new_comparison; 935 comparison_ = new_comparison;
1020 } 936 }
1021 937
1022
1023 // ==== Postorder graph traversal. 938 // ==== Postorder graph traversal.
1024 static bool IsMarked(BlockEntryInstr* block, 939 static bool IsMarked(BlockEntryInstr* block,
1025 GrowableArray<BlockEntryInstr*>* preorder) { 940 GrowableArray<BlockEntryInstr*>* preorder) {
1026 // Detect that a block has been visited as part of the current 941 // Detect that a block has been visited as part of the current
1027 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block 942 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block
1028 // will be 'marked' by (1) having a preorder number in the range of the 943 // will be 'marked' by (1) having a preorder number in the range of the
1029 // preorder array and (2) being in the preorder array at that index. 944 // preorder array and (2) being in the preorder array at that index.
1030 intptr_t i = block->preorder_number(); 945 intptr_t i = block->preorder_number();
1031 return (i >= 0) && (i < preorder->length()) && ((*preorder)[i] == block); 946 return (i >= 0) && (i < preorder->length()) && ((*preorder)[i] == block);
1032 } 947 }
1033 948
1034
1035 // Base class implementation used for JoinEntry and TargetEntry. 949 // Base class implementation used for JoinEntry and TargetEntry.
1036 bool BlockEntryInstr::DiscoverBlock(BlockEntryInstr* predecessor, 950 bool BlockEntryInstr::DiscoverBlock(BlockEntryInstr* predecessor,
1037 GrowableArray<BlockEntryInstr*>* preorder, 951 GrowableArray<BlockEntryInstr*>* preorder,
1038 GrowableArray<intptr_t>* parent) { 952 GrowableArray<intptr_t>* parent) {
1039 // If this block has a predecessor (i.e., is not the graph entry) we can 953 // If this block has a predecessor (i.e., is not the graph entry) we can
1040 // assume the preorder array is non-empty. 954 // assume the preorder array is non-empty.
1041 ASSERT((predecessor == NULL) || !preorder->is_empty()); 955 ASSERT((predecessor == NULL) || !preorder->is_empty());
1042 // Blocks with a single predecessor cannot have been reached before. 956 // Blocks with a single predecessor cannot have been reached before.
1043 ASSERT(IsJoinEntry() || !IsMarked(this, preorder)); 957 ASSERT(IsJoinEntry() || !IsMarked(this, preorder));
1044 958
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1076 Instruction* last = this; 990 Instruction* last = this;
1077 for (ForwardInstructionIterator it(this); !it.Done(); it.Advance()) { 991 for (ForwardInstructionIterator it(this); !it.Done(); it.Advance()) {
1078 last = it.Current(); 992 last = it.Current();
1079 } 993 }
1080 set_last_instruction(last); 994 set_last_instruction(last);
1081 if (last->IsGoto()) last->AsGoto()->set_block(this); 995 if (last->IsGoto()) last->AsGoto()->set_block(this);
1082 996
1083 return true; 997 return true;
1084 } 998 }
1085 999
1086
1087 void GraphEntryInstr::RelinkToOsrEntry(Zone* zone, intptr_t max_block_id) { 1000 void GraphEntryInstr::RelinkToOsrEntry(Zone* zone, intptr_t max_block_id) {
1088 ASSERT(osr_id_ != Compiler::kNoOSRDeoptId); 1001 ASSERT(osr_id_ != Compiler::kNoOSRDeoptId);
1089 BitVector* block_marks = new (zone) BitVector(zone, max_block_id + 1); 1002 BitVector* block_marks = new (zone) BitVector(zone, max_block_id + 1);
1090 bool found = FindOsrEntryAndRelink(this, /*parent=*/NULL, block_marks); 1003 bool found = FindOsrEntryAndRelink(this, /*parent=*/NULL, block_marks);
1091 ASSERT(found); 1004 ASSERT(found);
1092 } 1005 }
1093 1006
1094
1095 bool BlockEntryInstr::FindOsrEntryAndRelink(GraphEntryInstr* graph_entry, 1007 bool BlockEntryInstr::FindOsrEntryAndRelink(GraphEntryInstr* graph_entry,
1096 Instruction* parent, 1008 Instruction* parent,
1097 BitVector* block_marks) { 1009 BitVector* block_marks) {
1098 const intptr_t osr_id = graph_entry->osr_id(); 1010 const intptr_t osr_id = graph_entry->osr_id();
1099 1011
1100 // Search for the instruction with the OSR id. Use a depth first search 1012 // Search for the instruction with the OSR id. Use a depth first search
1101 // because basic blocks have not been discovered yet. Prune unreachable 1013 // because basic blocks have not been discovered yet. Prune unreachable
1102 // blocks by replacing the normal entry with a jump to the block 1014 // blocks by replacing the normal entry with a jump to the block
1103 // containing the OSR entry point. 1015 // containing the OSR entry point.
1104 1016
(...skipping 26 matching lines...) Expand all
1131 // Recursively search the successors. 1043 // Recursively search the successors.
1132 for (intptr_t i = instr->SuccessorCount() - 1; i >= 0; --i) { 1044 for (intptr_t i = instr->SuccessorCount() - 1; i >= 0; --i) {
1133 if (instr->SuccessorAt(i)->FindOsrEntryAndRelink(graph_entry, instr, 1045 if (instr->SuccessorAt(i)->FindOsrEntryAndRelink(graph_entry, instr,
1134 block_marks)) { 1046 block_marks)) {
1135 return true; 1047 return true;
1136 } 1048 }
1137 } 1049 }
1138 return false; 1050 return false;
1139 } 1051 }
1140 1052
1141
1142 bool BlockEntryInstr::Dominates(BlockEntryInstr* other) const { 1053 bool BlockEntryInstr::Dominates(BlockEntryInstr* other) const {
1143 // TODO(fschneider): Make this faster by e.g. storing dominators for each 1054 // TODO(fschneider): Make this faster by e.g. storing dominators for each
1144 // block while computing the dominator tree. 1055 // block while computing the dominator tree.
1145 ASSERT(other != NULL); 1056 ASSERT(other != NULL);
1146 BlockEntryInstr* current = other; 1057 BlockEntryInstr* current = other;
1147 while (current != NULL && current != this) { 1058 while (current != NULL && current != this) {
1148 current = current->dominator(); 1059 current = current->dominator();
1149 } 1060 }
1150 return current == this; 1061 return current == this;
1151 } 1062 }
1152 1063
1153
1154 BlockEntryInstr* BlockEntryInstr::ImmediateDominator() const { 1064 BlockEntryInstr* BlockEntryInstr::ImmediateDominator() const {
1155 Instruction* last = dominator()->last_instruction(); 1065 Instruction* last = dominator()->last_instruction();
1156 if ((last->SuccessorCount() == 1) && (last->SuccessorAt(0) == this)) { 1066 if ((last->SuccessorCount() == 1) && (last->SuccessorAt(0) == this)) {
1157 return dominator(); 1067 return dominator();
1158 } 1068 }
1159 return NULL; 1069 return NULL;
1160 } 1070 }
1161 1071
1162
1163 // Helper to mutate the graph during inlining. This block should be 1072 // Helper to mutate the graph during inlining. This block should be
1164 // replaced with new_block as a predecessor of all of this block's 1073 // replaced with new_block as a predecessor of all of this block's
1165 // successors. For each successor, the predecessors will be reordered 1074 // successors. For each successor, the predecessors will be reordered
1166 // to preserve block-order sorting of the predecessors as well as the 1075 // to preserve block-order sorting of the predecessors as well as the
1167 // phis if the successor is a join. 1076 // phis if the successor is a join.
1168 void BlockEntryInstr::ReplaceAsPredecessorWith(BlockEntryInstr* new_block) { 1077 void BlockEntryInstr::ReplaceAsPredecessorWith(BlockEntryInstr* new_block) {
1169 // Set the last instruction of the new block to that of the old block. 1078 // Set the last instruction of the new block to that of the old block.
1170 Instruction* last = last_instruction(); 1079 Instruction* last = last_instruction();
1171 new_block->set_last_instruction(last); 1080 new_block->set_last_instruction(last);
1172 // For each successor, update the predecessors. 1081 // For each successor, update the predecessors.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 for (intptr_t use_idx = old_index; use_idx != new_index; 1125 for (intptr_t use_idx = old_index; use_idx != new_index;
1217 use_idx += step) { 1126 use_idx += step) {
1218 phi->SetInputAt(use_idx, phi->InputAt(use_idx + step)); 1127 phi->SetInputAt(use_idx, phi->InputAt(use_idx + step));
1219 } 1128 }
1220 // Write the predecessor use. 1129 // Write the predecessor use.
1221 phi->SetInputAt(new_index, pred_use); 1130 phi->SetInputAt(new_index, pred_use);
1222 } 1131 }
1223 } 1132 }
1224 } 1133 }
1225 1134
1226
1227 void BlockEntryInstr::ClearAllInstructions() { 1135 void BlockEntryInstr::ClearAllInstructions() {
1228 JoinEntryInstr* join = this->AsJoinEntry(); 1136 JoinEntryInstr* join = this->AsJoinEntry();
1229 if (join != NULL) { 1137 if (join != NULL) {
1230 for (PhiIterator it(join); !it.Done(); it.Advance()) { 1138 for (PhiIterator it(join); !it.Done(); it.Advance()) {
1231 it.Current()->UnuseAllInputs(); 1139 it.Current()->UnuseAllInputs();
1232 } 1140 }
1233 } 1141 }
1234 UnuseAllInputs(); 1142 UnuseAllInputs();
1235 for (ForwardInstructionIterator it(this); !it.Done(); it.Advance()) { 1143 for (ForwardInstructionIterator it(this); !it.Done(); it.Advance()) {
1236 it.Current()->UnuseAllInputs(); 1144 it.Current()->UnuseAllInputs();
1237 } 1145 }
1238 } 1146 }
1239 1147
1240
1241 PhiInstr* JoinEntryInstr::InsertPhi(intptr_t var_index, intptr_t var_count) { 1148 PhiInstr* JoinEntryInstr::InsertPhi(intptr_t var_index, intptr_t var_count) {
1242 // Lazily initialize the array of phis. 1149 // Lazily initialize the array of phis.
1243 // Currently, phis are stored in a sparse array that holds the phi 1150 // Currently, phis are stored in a sparse array that holds the phi
1244 // for variable with index i at position i. 1151 // for variable with index i at position i.
1245 // TODO(fschneider): Store phis in a more compact way. 1152 // TODO(fschneider): Store phis in a more compact way.
1246 if (phis_ == NULL) { 1153 if (phis_ == NULL) {
1247 phis_ = new ZoneGrowableArray<PhiInstr*>(var_count); 1154 phis_ = new ZoneGrowableArray<PhiInstr*>(var_count);
1248 for (intptr_t i = 0; i < var_count; i++) { 1155 for (intptr_t i = 0; i < var_count; i++) {
1249 phis_->Add(NULL); 1156 phis_->Add(NULL);
1250 } 1157 }
1251 } 1158 }
1252 ASSERT((*phis_)[var_index] == NULL); 1159 ASSERT((*phis_)[var_index] == NULL);
1253 return (*phis_)[var_index] = new PhiInstr(this, PredecessorCount()); 1160 return (*phis_)[var_index] = new PhiInstr(this, PredecessorCount());
1254 } 1161 }
1255 1162
1256
1257 void JoinEntryInstr::InsertPhi(PhiInstr* phi) { 1163 void JoinEntryInstr::InsertPhi(PhiInstr* phi) {
1258 // Lazily initialize the array of phis. 1164 // Lazily initialize the array of phis.
1259 if (phis_ == NULL) { 1165 if (phis_ == NULL) {
1260 phis_ = new ZoneGrowableArray<PhiInstr*>(1); 1166 phis_ = new ZoneGrowableArray<PhiInstr*>(1);
1261 } 1167 }
1262 phis_->Add(phi); 1168 phis_->Add(phi);
1263 } 1169 }
1264 1170
1265 void JoinEntryInstr::RemovePhi(PhiInstr* phi) { 1171 void JoinEntryInstr::RemovePhi(PhiInstr* phi) {
1266 ASSERT(phis_ != NULL); 1172 ASSERT(phis_ != NULL);
(...skipping 24 matching lines...) Expand all
1291 } 1197 }
1292 } 1198 }
1293 } 1199 }
1294 if (to_index == 0) { 1200 if (to_index == 0) {
1295 phis_ = NULL; 1201 phis_ = NULL;
1296 } else { 1202 } else {
1297 phis_->TruncateTo(to_index); 1203 phis_->TruncateTo(to_index);
1298 } 1204 }
1299 } 1205 }
1300 1206
1301
1302 intptr_t Instruction::SuccessorCount() const { 1207 intptr_t Instruction::SuccessorCount() const {
1303 return 0; 1208 return 0;
1304 } 1209 }
1305 1210
1306
1307 BlockEntryInstr* Instruction::SuccessorAt(intptr_t index) const { 1211 BlockEntryInstr* Instruction::SuccessorAt(intptr_t index) const {
1308 // Called only if index is in range. Only control-transfer instructions 1212 // Called only if index is in range. Only control-transfer instructions
1309 // can have non-zero successor counts and they override this function. 1213 // can have non-zero successor counts and they override this function.
1310 UNREACHABLE(); 1214 UNREACHABLE();
1311 return NULL; 1215 return NULL;
1312 } 1216 }
1313 1217
1314
1315 intptr_t GraphEntryInstr::SuccessorCount() const { 1218 intptr_t GraphEntryInstr::SuccessorCount() const {
1316 return 1 + catch_entries_.length(); 1219 return 1 + catch_entries_.length();
1317 } 1220 }
1318 1221
1319
1320 BlockEntryInstr* GraphEntryInstr::SuccessorAt(intptr_t index) const { 1222 BlockEntryInstr* GraphEntryInstr::SuccessorAt(intptr_t index) const {
1321 if (index == 0) return normal_entry_; 1223 if (index == 0) return normal_entry_;
1322 return catch_entries_[index - 1]; 1224 return catch_entries_[index - 1];
1323 } 1225 }
1324 1226
1325
1326 intptr_t BranchInstr::SuccessorCount() const { 1227 intptr_t BranchInstr::SuccessorCount() const {
1327 return 2; 1228 return 2;
1328 } 1229 }
1329 1230
1330
1331 BlockEntryInstr* BranchInstr::SuccessorAt(intptr_t index) const { 1231 BlockEntryInstr* BranchInstr::SuccessorAt(intptr_t index) const {
1332 if (index == 0) return true_successor_; 1232 if (index == 0) return true_successor_;
1333 if (index == 1) return false_successor_; 1233 if (index == 1) return false_successor_;
1334 UNREACHABLE(); 1234 UNREACHABLE();
1335 return NULL; 1235 return NULL;
1336 } 1236 }
1337 1237
1338
1339 intptr_t GotoInstr::SuccessorCount() const { 1238 intptr_t GotoInstr::SuccessorCount() const {
1340 return 1; 1239 return 1;
1341 } 1240 }
1342 1241
1343
1344 BlockEntryInstr* GotoInstr::SuccessorAt(intptr_t index) const { 1242 BlockEntryInstr* GotoInstr::SuccessorAt(intptr_t index) const {
1345 ASSERT(index == 0); 1243 ASSERT(index == 0);
1346 return successor(); 1244 return successor();
1347 } 1245 }
1348 1246
1349
1350 void Instruction::Goto(JoinEntryInstr* entry) { 1247 void Instruction::Goto(JoinEntryInstr* entry) {
1351 LinkTo(new GotoInstr(entry, Thread::Current()->GetNextDeoptId())); 1248 LinkTo(new GotoInstr(entry, Thread::Current()->GetNextDeoptId()));
1352 } 1249 }
1353 1250
1354
1355 bool UnboxedIntConverterInstr::ComputeCanDeoptimize() const { 1251 bool UnboxedIntConverterInstr::ComputeCanDeoptimize() const {
1356 return (to() == kUnboxedInt32) && !is_truncating() && 1252 return (to() == kUnboxedInt32) && !is_truncating() &&
1357 !RangeUtils::Fits(value()->definition()->range(), 1253 !RangeUtils::Fits(value()->definition()->range(),
1358 RangeBoundary::kRangeBoundaryInt32); 1254 RangeBoundary::kRangeBoundaryInt32);
1359 } 1255 }
1360 1256
1361
1362 bool UnboxInt32Instr::ComputeCanDeoptimize() const { 1257 bool UnboxInt32Instr::ComputeCanDeoptimize() const {
1363 const intptr_t value_cid = value()->Type()->ToCid(); 1258 const intptr_t value_cid = value()->Type()->ToCid();
1364 if (value_cid == kSmiCid) { 1259 if (value_cid == kSmiCid) {
1365 return (kSmiBits > 32) && !is_truncating() && 1260 return (kSmiBits > 32) && !is_truncating() &&
1366 !RangeUtils::Fits(value()->definition()->range(), 1261 !RangeUtils::Fits(value()->definition()->range(),
1367 RangeBoundary::kRangeBoundaryInt32); 1262 RangeBoundary::kRangeBoundaryInt32);
1368 } else if (value_cid == kMintCid) { 1263 } else if (value_cid == kMintCid) {
1369 return !is_truncating() && 1264 return !is_truncating() &&
1370 !RangeUtils::Fits(value()->definition()->range(), 1265 !RangeUtils::Fits(value()->definition()->range(),
1371 RangeBoundary::kRangeBoundaryInt32); 1266 RangeBoundary::kRangeBoundaryInt32);
1372 } else if (is_truncating() && value()->definition()->IsBoxInteger()) { 1267 } else if (is_truncating() && value()->definition()->IsBoxInteger()) {
1373 return false; 1268 return false;
1374 } else if ((kSmiBits < 32) && value()->Type()->IsInt()) { 1269 } else if ((kSmiBits < 32) && value()->Type()->IsInt()) {
1375 // Note: we don't support truncation of Bigint values. 1270 // Note: we don't support truncation of Bigint values.
1376 return !RangeUtils::Fits(value()->definition()->range(), 1271 return !RangeUtils::Fits(value()->definition()->range(),
1377 RangeBoundary::kRangeBoundaryInt32); 1272 RangeBoundary::kRangeBoundaryInt32);
1378 } else { 1273 } else {
1379 return true; 1274 return true;
1380 } 1275 }
1381 } 1276 }
1382 1277
1383
1384 bool UnboxUint32Instr::ComputeCanDeoptimize() const { 1278 bool UnboxUint32Instr::ComputeCanDeoptimize() const {
1385 ASSERT(is_truncating()); 1279 ASSERT(is_truncating());
1386 if ((value()->Type()->ToCid() == kSmiCid) || 1280 if ((value()->Type()->ToCid() == kSmiCid) ||
1387 (value()->Type()->ToCid() == kMintCid)) { 1281 (value()->Type()->ToCid() == kMintCid)) {
1388 return false; 1282 return false;
1389 } 1283 }
1390 // Check input value's range. 1284 // Check input value's range.
1391 Range* value_range = value()->definition()->range(); 1285 Range* value_range = value()->definition()->range();
1392 return !RangeUtils::Fits(value_range, RangeBoundary::kRangeBoundaryInt64); 1286 return !RangeUtils::Fits(value_range, RangeBoundary::kRangeBoundaryInt64);
1393 } 1287 }
1394 1288
1395
1396 bool BinaryInt32OpInstr::ComputeCanDeoptimize() const { 1289 bool BinaryInt32OpInstr::ComputeCanDeoptimize() const {
1397 switch (op_kind()) { 1290 switch (op_kind()) {
1398 case Token::kBIT_AND: 1291 case Token::kBIT_AND:
1399 case Token::kBIT_OR: 1292 case Token::kBIT_OR:
1400 case Token::kBIT_XOR: 1293 case Token::kBIT_XOR:
1401 return false; 1294 return false;
1402 1295
1403 case Token::kSHR: 1296 case Token::kSHR:
1404 return false; 1297 return false;
1405 1298
1406 case Token::kSHL: 1299 case Token::kSHL:
1407 // Currently only shifts by in range constant are supported, see 1300 // Currently only shifts by in range constant are supported, see
1408 // BinaryInt32OpInstr::IsSupported. 1301 // BinaryInt32OpInstr::IsSupported.
1409 return can_overflow(); 1302 return can_overflow();
1410 1303
1411 case Token::kMOD: { 1304 case Token::kMOD: {
1412 UNREACHABLE(); 1305 UNREACHABLE();
1413 } 1306 }
1414 1307
1415 default: 1308 default:
1416 return can_overflow(); 1309 return can_overflow();
1417 } 1310 }
1418 } 1311 }
1419 1312
1420
1421 bool BinarySmiOpInstr::ComputeCanDeoptimize() const { 1313 bool BinarySmiOpInstr::ComputeCanDeoptimize() const {
1422 switch (op_kind()) { 1314 switch (op_kind()) {
1423 case Token::kBIT_AND: 1315 case Token::kBIT_AND:
1424 case Token::kBIT_OR: 1316 case Token::kBIT_OR:
1425 case Token::kBIT_XOR: 1317 case Token::kBIT_XOR:
1426 return false; 1318 return false;
1427 1319
1428 case Token::kSHR: 1320 case Token::kSHR:
1429 return !RangeUtils::IsPositive(right_range()); 1321 return !RangeUtils::IsPositive(right_range());
1430 1322
1431 case Token::kSHL: 1323 case Token::kSHL:
1432 return can_overflow() || !RangeUtils::IsPositive(right_range()); 1324 return can_overflow() || !RangeUtils::IsPositive(right_range());
1433 1325
1434 case Token::kMOD: 1326 case Token::kMOD:
1435 return RangeUtils::CanBeZero(right_range()); 1327 return RangeUtils::CanBeZero(right_range());
1436 1328
1437 default: 1329 default:
1438 return can_overflow(); 1330 return can_overflow();
1439 } 1331 }
1440 } 1332 }
1441 1333
1442
1443 bool ShiftMintOpInstr::IsShiftCountInRange() const { 1334 bool ShiftMintOpInstr::IsShiftCountInRange() const {
1444 return RangeUtils::IsWithin(shift_range(), 0, kMintShiftCountLimit); 1335 return RangeUtils::IsWithin(shift_range(), 0, kMintShiftCountLimit);
1445 } 1336 }
1446 1337
1447
1448 bool BinaryIntegerOpInstr::RightIsPowerOfTwoConstant() const { 1338 bool BinaryIntegerOpInstr::RightIsPowerOfTwoConstant() const {
1449 if (!right()->definition()->IsConstant()) return false; 1339 if (!right()->definition()->IsConstant()) return false;
1450 const Object& constant = right()->definition()->AsConstant()->value(); 1340 const Object& constant = right()->definition()->AsConstant()->value();
1451 if (!constant.IsSmi()) return false; 1341 if (!constant.IsSmi()) return false;
1452 const intptr_t int_value = Smi::Cast(constant).Value(); 1342 const intptr_t int_value = Smi::Cast(constant).Value();
1453 return Utils::IsPowerOfTwo(Utils::Abs(int_value)); 1343 return Utils::IsPowerOfTwo(Utils::Abs(int_value));
1454 } 1344 }
1455 1345
1456
1457 static intptr_t RepresentationBits(Representation r) { 1346 static intptr_t RepresentationBits(Representation r) {
1458 switch (r) { 1347 switch (r) {
1459 case kTagged: 1348 case kTagged:
1460 return kBitsPerWord - 1; 1349 return kBitsPerWord - 1;
1461 case kUnboxedInt32: 1350 case kUnboxedInt32:
1462 case kUnboxedUint32: 1351 case kUnboxedUint32:
1463 return 32; 1352 return 32;
1464 case kUnboxedMint: 1353 case kUnboxedMint:
1465 return 64; 1354 return 64;
1466 default: 1355 default:
1467 UNREACHABLE(); 1356 UNREACHABLE();
1468 return 0; 1357 return 0;
1469 } 1358 }
1470 } 1359 }
1471 1360
1472
1473 static int64_t RepresentationMask(Representation r) { 1361 static int64_t RepresentationMask(Representation r) {
1474 return static_cast<int64_t>(static_cast<uint64_t>(-1) >> 1362 return static_cast<int64_t>(static_cast<uint64_t>(-1) >>
1475 (64 - RepresentationBits(r))); 1363 (64 - RepresentationBits(r)));
1476 } 1364 }
1477 1365
1478
1479 static bool ToIntegerConstant(Value* value, int64_t* result) { 1366 static bool ToIntegerConstant(Value* value, int64_t* result) {
1480 if (!value->BindsToConstant()) { 1367 if (!value->BindsToConstant()) {
1481 UnboxInstr* unbox = value->definition()->AsUnbox(); 1368 UnboxInstr* unbox = value->definition()->AsUnbox();
1482 if (unbox != NULL) { 1369 if (unbox != NULL) {
1483 switch (unbox->representation()) { 1370 switch (unbox->representation()) {
1484 case kUnboxedDouble: 1371 case kUnboxedDouble:
1485 case kUnboxedMint: 1372 case kUnboxedMint:
1486 return ToIntegerConstant(unbox->value(), result); 1373 return ToIntegerConstant(unbox->value(), result);
1487 1374
1488 case kUnboxedUint32: 1375 case kUnboxedUint32:
(...skipping 22 matching lines...) Expand all
1511 *result = Smi::Cast(constant).Value(); 1398 *result = Smi::Cast(constant).Value();
1512 return true; 1399 return true;
1513 } else if (constant.IsMint()) { 1400 } else if (constant.IsMint()) {
1514 *result = Mint::Cast(constant).value(); 1401 *result = Mint::Cast(constant).value();
1515 return true; 1402 return true;
1516 } 1403 }
1517 1404
1518 return false; 1405 return false;
1519 } 1406 }
1520 1407
1521
1522 static Definition* CanonicalizeCommutativeDoubleArithmetic(Token::Kind op, 1408 static Definition* CanonicalizeCommutativeDoubleArithmetic(Token::Kind op,
1523 Value* left, 1409 Value* left,
1524 Value* right) { 1410 Value* right) {
1525 int64_t left_value; 1411 int64_t left_value;
1526 if (!ToIntegerConstant(left, &left_value)) { 1412 if (!ToIntegerConstant(left, &left_value)) {
1527 return NULL; 1413 return NULL;
1528 } 1414 }
1529 1415
1530 // Can't apply 0.0 * x -> 0.0 equivalence to double operation because 1416 // Can't apply 0.0 * x -> 0.0 equivalence to double operation because
1531 // 0.0 * NaN is NaN not 0.0. 1417 // 0.0 * NaN is NaN not 0.0.
(...skipping 12 matching lines...) Expand all
1544 } 1430 }
1545 } 1431 }
1546 break; 1432 break;
1547 default: 1433 default:
1548 break; 1434 break;
1549 } 1435 }
1550 1436
1551 return NULL; 1437 return NULL;
1552 } 1438 }
1553 1439
1554
1555 Definition* DoubleToFloatInstr::Canonicalize(FlowGraph* flow_graph) { 1440 Definition* DoubleToFloatInstr::Canonicalize(FlowGraph* flow_graph) {
1556 #ifdef DEBUG 1441 #ifdef DEBUG
1557 // Must only be used in Float32 StoreIndexedInstr or FloatToDoubleInstr or 1442 // Must only be used in Float32 StoreIndexedInstr or FloatToDoubleInstr or
1558 // Phis introduce by load forwarding. 1443 // Phis introduce by load forwarding.
1559 ASSERT(env_use_list() == NULL); 1444 ASSERT(env_use_list() == NULL);
1560 for (Value* use = input_use_list(); use != NULL; use = use->next_use()) { 1445 for (Value* use = input_use_list(); use != NULL; use = use->next_use()) {
1561 ASSERT(use->instruction()->IsPhi() || 1446 ASSERT(use->instruction()->IsPhi() ||
1562 use->instruction()->IsFloatToDouble() || 1447 use->instruction()->IsFloatToDouble() ||
1563 (use->instruction()->IsStoreIndexed() && 1448 (use->instruction()->IsStoreIndexed() &&
1564 (use->instruction()->AsStoreIndexed()->class_id() == 1449 (use->instruction()->AsStoreIndexed()->class_id() ==
1565 kTypedDataFloat32ArrayCid))); 1450 kTypedDataFloat32ArrayCid)));
1566 } 1451 }
1567 #endif 1452 #endif
1568 if (!HasUses()) return NULL; 1453 if (!HasUses()) return NULL;
1569 if (value()->definition()->IsFloatToDouble()) { 1454 if (value()->definition()->IsFloatToDouble()) {
1570 // F2D(D2F(v)) == v. 1455 // F2D(D2F(v)) == v.
1571 return value()->definition()->AsFloatToDouble()->value()->definition(); 1456 return value()->definition()->AsFloatToDouble()->value()->definition();
1572 } 1457 }
1573 return this; 1458 return this;
1574 } 1459 }
1575 1460
1576
1577 Definition* FloatToDoubleInstr::Canonicalize(FlowGraph* flow_graph) { 1461 Definition* FloatToDoubleInstr::Canonicalize(FlowGraph* flow_graph) {
1578 return HasUses() ? this : NULL; 1462 return HasUses() ? this : NULL;
1579 } 1463 }
1580 1464
1581
1582 Definition* BinaryDoubleOpInstr::Canonicalize(FlowGraph* flow_graph) { 1465 Definition* BinaryDoubleOpInstr::Canonicalize(FlowGraph* flow_graph) {
1583 if (!HasUses()) return NULL; 1466 if (!HasUses()) return NULL;
1584 1467
1585 Definition* result = NULL; 1468 Definition* result = NULL;
1586 1469
1587 result = CanonicalizeCommutativeDoubleArithmetic(op_kind(), left(), right()); 1470 result = CanonicalizeCommutativeDoubleArithmetic(op_kind(), left(), right());
1588 if (result != NULL) { 1471 if (result != NULL) {
1589 return result; 1472 return result;
1590 } 1473 }
1591 1474
1592 result = CanonicalizeCommutativeDoubleArithmetic(op_kind(), right(), left()); 1475 result = CanonicalizeCommutativeDoubleArithmetic(op_kind(), right(), left());
1593 if (result != NULL) { 1476 if (result != NULL) {
1594 return result; 1477 return result;
1595 } 1478 }
1596 1479
1597 if ((op_kind() == Token::kMUL) && 1480 if ((op_kind() == Token::kMUL) &&
1598 (left()->definition() == right()->definition())) { 1481 (left()->definition() == right()->definition())) {
1599 MathUnaryInstr* math_unary = new MathUnaryInstr( 1482 MathUnaryInstr* math_unary = new MathUnaryInstr(
1600 MathUnaryInstr::kDoubleSquare, new Value(left()->definition()), 1483 MathUnaryInstr::kDoubleSquare, new Value(left()->definition()),
1601 DeoptimizationTarget()); 1484 DeoptimizationTarget());
1602 flow_graph->InsertBefore(this, math_unary, env(), FlowGraph::kValue); 1485 flow_graph->InsertBefore(this, math_unary, env(), FlowGraph::kValue);
1603 return math_unary; 1486 return math_unary;
1604 } 1487 }
1605 1488
1606 return this; 1489 return this;
1607 } 1490 }
1608 1491
1609
1610 Definition* DoubleTestOpInstr::Canonicalize(FlowGraph* flow_graph) { 1492 Definition* DoubleTestOpInstr::Canonicalize(FlowGraph* flow_graph) {
1611 return HasUses() ? this : NULL; 1493 return HasUses() ? this : NULL;
1612 } 1494 }
1613 1495
1614
1615 static bool IsCommutative(Token::Kind op) { 1496 static bool IsCommutative(Token::Kind op) {
1616 switch (op) { 1497 switch (op) {
1617 case Token::kMUL: 1498 case Token::kMUL:
1618 case Token::kADD: 1499 case Token::kADD:
1619 case Token::kBIT_AND: 1500 case Token::kBIT_AND:
1620 case Token::kBIT_OR: 1501 case Token::kBIT_OR:
1621 case Token::kBIT_XOR: 1502 case Token::kBIT_XOR:
1622 return true; 1503 return true;
1623 default: 1504 default:
1624 return false; 1505 return false;
1625 } 1506 }
1626 } 1507 }
1627 1508
1628
1629 UnaryIntegerOpInstr* UnaryIntegerOpInstr::Make(Representation representation, 1509 UnaryIntegerOpInstr* UnaryIntegerOpInstr::Make(Representation representation,
1630 Token::Kind op_kind, 1510 Token::Kind op_kind,
1631 Value* value, 1511 Value* value,
1632 intptr_t deopt_id, 1512 intptr_t deopt_id,
1633 Range* range) { 1513 Range* range) {
1634 UnaryIntegerOpInstr* op = NULL; 1514 UnaryIntegerOpInstr* op = NULL;
1635 switch (representation) { 1515 switch (representation) {
1636 case kTagged: 1516 case kTagged:
1637 op = new UnarySmiOpInstr(op_kind, value, deopt_id); 1517 op = new UnarySmiOpInstr(op_kind, value, deopt_id);
1638 break; 1518 break;
(...skipping 15 matching lines...) Expand all
1654 } 1534 }
1655 1535
1656 if (!Range::IsUnknown(range)) { 1536 if (!Range::IsUnknown(range)) {
1657 op->set_range(*range); 1537 op->set_range(*range);
1658 } 1538 }
1659 1539
1660 ASSERT(op->representation() == representation); 1540 ASSERT(op->representation() == representation);
1661 return op; 1541 return op;
1662 } 1542 }
1663 1543
1664
1665 BinaryIntegerOpInstr* BinaryIntegerOpInstr::Make(Representation representation, 1544 BinaryIntegerOpInstr* BinaryIntegerOpInstr::Make(Representation representation,
1666 Token::Kind op_kind, 1545 Token::Kind op_kind,
1667 Value* left, 1546 Value* left,
1668 Value* right, 1547 Value* right,
1669 intptr_t deopt_id, 1548 intptr_t deopt_id,
1670 bool can_overflow, 1549 bool can_overflow,
1671 bool is_truncating, 1550 bool is_truncating,
1672 Range* range) { 1551 Range* range) {
1673 BinaryIntegerOpInstr* op = NULL; 1552 BinaryIntegerOpInstr* op = NULL;
1674 switch (representation) { 1553 switch (representation) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1706 1585
1707 op->set_can_overflow(can_overflow); 1586 op->set_can_overflow(can_overflow);
1708 if (is_truncating) { 1587 if (is_truncating) {
1709 op->mark_truncating(); 1588 op->mark_truncating();
1710 } 1589 }
1711 1590
1712 ASSERT(op->representation() == representation); 1591 ASSERT(op->representation() == representation);
1713 return op; 1592 return op;
1714 } 1593 }
1715 1594
1716
1717 static bool IsRepresentable(const Integer& value, Representation rep) { 1595 static bool IsRepresentable(const Integer& value, Representation rep) {
1718 switch (rep) { 1596 switch (rep) {
1719 case kTagged: // Smi case. 1597 case kTagged: // Smi case.
1720 return value.IsSmi(); 1598 return value.IsSmi();
1721 1599
1722 case kUnboxedInt32: 1600 case kUnboxedInt32:
1723 if (value.IsSmi() || value.IsMint()) { 1601 if (value.IsSmi() || value.IsMint()) {
1724 return Utils::IsInt(32, value.AsInt64Value()); 1602 return Utils::IsInt(32, value.AsInt64Value());
1725 } 1603 }
1726 return false; 1604 return false;
1727 1605
1728 case kUnboxedMint: 1606 case kUnboxedMint:
1729 return value.IsSmi() || value.IsMint(); 1607 return value.IsSmi() || value.IsMint();
1730 1608
1731 case kUnboxedUint32: // Only truncating Uint32 arithmetic is supported. 1609 case kUnboxedUint32: // Only truncating Uint32 arithmetic is supported.
1732 default: 1610 default:
1733 UNREACHABLE(); 1611 UNREACHABLE();
1734 } 1612 }
1735 1613
1736 return false; 1614 return false;
1737 } 1615 }
1738 1616
1739
1740 RawInteger* UnaryIntegerOpInstr::Evaluate(const Integer& value) const { 1617 RawInteger* UnaryIntegerOpInstr::Evaluate(const Integer& value) const {
1741 Thread* thread = Thread::Current(); 1618 Thread* thread = Thread::Current();
1742 Zone* zone = thread->zone(); 1619 Zone* zone = thread->zone();
1743 Integer& result = Integer::Handle(zone); 1620 Integer& result = Integer::Handle(zone);
1744 1621
1745 switch (op_kind()) { 1622 switch (op_kind()) {
1746 case Token::kNEGATE: 1623 case Token::kNEGATE:
1747 result = value.ArithmeticOp(Token::kMUL, Smi::Handle(zone, Smi::New(-1)), 1624 result = value.ArithmeticOp(Token::kMUL, Smi::Handle(zone, Smi::New(-1)),
1748 Heap::kOld); 1625 Heap::kOld);
1749 break; 1626 break;
(...skipping 17 matching lines...) Expand all
1767 // larger than something this operation can produce. We could have 1644 // larger than something this operation can produce. We could have
1768 // specialized instructions that use this value under this assumption. 1645 // specialized instructions that use this value under this assumption.
1769 return Integer::null(); 1646 return Integer::null();
1770 } 1647 }
1771 result ^= result.CheckAndCanonicalize(thread, NULL); 1648 result ^= result.CheckAndCanonicalize(thread, NULL);
1772 } 1649 }
1773 1650
1774 return result.raw(); 1651 return result.raw();
1775 } 1652 }
1776 1653
1777
1778 RawInteger* BinaryIntegerOpInstr::Evaluate(const Integer& left, 1654 RawInteger* BinaryIntegerOpInstr::Evaluate(const Integer& left,
1779 const Integer& right) const { 1655 const Integer& right) const {
1780 Thread* thread = Thread::Current(); 1656 Thread* thread = Thread::Current();
1781 Zone* zone = thread->zone(); 1657 Zone* zone = thread->zone();
1782 Integer& result = Integer::Handle(zone); 1658 Integer& result = Integer::Handle(zone);
1783 1659
1784 switch (op_kind()) { 1660 switch (op_kind()) {
1785 case Token::kTRUNCDIV: 1661 case Token::kTRUNCDIV:
1786 case Token::kMOD: 1662 case Token::kMOD:
1787 // Check right value for zero. 1663 // Check right value for zero.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1826 // larger than something this operation can produce. We could have 1702 // larger than something this operation can produce. We could have
1827 // specialized instructions that use this value under this assumption. 1703 // specialized instructions that use this value under this assumption.
1828 return Integer::null(); 1704 return Integer::null();
1829 } 1705 }
1830 result ^= result.CheckAndCanonicalize(thread, NULL); 1706 result ^= result.CheckAndCanonicalize(thread, NULL);
1831 } 1707 }
1832 1708
1833 return result.raw(); 1709 return result.raw();
1834 } 1710 }
1835 1711
1836
1837 Definition* BinaryIntegerOpInstr::CreateConstantResult(FlowGraph* flow_graph, 1712 Definition* BinaryIntegerOpInstr::CreateConstantResult(FlowGraph* flow_graph,
1838 const Integer& result) { 1713 const Integer& result) {
1839 Definition* result_defn = flow_graph->GetConstant(result); 1714 Definition* result_defn = flow_graph->GetConstant(result);
1840 if (representation() != kTagged) { 1715 if (representation() != kTagged) {
1841 result_defn = UnboxInstr::Create(representation(), new Value(result_defn), 1716 result_defn = UnboxInstr::Create(representation(), new Value(result_defn),
1842 GetDeoptId()); 1717 GetDeoptId());
1843 flow_graph->InsertBefore(this, result_defn, env(), FlowGraph::kValue); 1718 flow_graph->InsertBefore(this, result_defn, env(), FlowGraph::kValue);
1844 } 1719 }
1845 return result_defn; 1720 return result_defn;
1846 } 1721 }
1847 1722
1848
1849 Definition* CheckedSmiOpInstr::Canonicalize(FlowGraph* flow_graph) { 1723 Definition* CheckedSmiOpInstr::Canonicalize(FlowGraph* flow_graph) {
1850 if ((left()->Type()->ToCid() == kSmiCid) && 1724 if ((left()->Type()->ToCid() == kSmiCid) &&
1851 (right()->Type()->ToCid() == kSmiCid)) { 1725 (right()->Type()->ToCid() == kSmiCid)) {
1852 Definition* replacement = NULL; 1726 Definition* replacement = NULL;
1853 // Operations that can't deoptimize are specialized here: These include 1727 // Operations that can't deoptimize are specialized here: These include
1854 // bit-wise operators and comparisons. Other arithmetic operations can 1728 // bit-wise operators and comparisons. Other arithmetic operations can
1855 // overflow or divide by 0 and can't be specialized unless we have extra 1729 // overflow or divide by 0 and can't be specialized unless we have extra
1856 // range information. 1730 // range information.
1857 switch (op_kind()) { 1731 switch (op_kind()) {
1858 case Token::kBIT_AND: 1732 case Token::kBIT_AND:
1859 case Token::kBIT_OR: 1733 case Token::kBIT_OR:
1860 case Token::kBIT_XOR: 1734 case Token::kBIT_XOR:
1861 replacement = new BinarySmiOpInstr( 1735 replacement = new BinarySmiOpInstr(
1862 op_kind(), new Value(left()->definition()), 1736 op_kind(), new Value(left()->definition()),
1863 new Value(right()->definition()), Thread::kNoDeoptId); 1737 new Value(right()->definition()), Thread::kNoDeoptId);
1864 default: 1738 default:
1865 break; 1739 break;
1866 } 1740 }
1867 if (replacement != NULL) { 1741 if (replacement != NULL) {
1868 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue); 1742 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue);
1869 return replacement; 1743 return replacement;
1870 } 1744 }
1871 } 1745 }
1872 return this; 1746 return this;
1873 } 1747 }
1874 1748
1875
1876 ComparisonInstr* CheckedSmiComparisonInstr::CopyWithNewOperands(Value* left, 1749 ComparisonInstr* CheckedSmiComparisonInstr::CopyWithNewOperands(Value* left,
1877 Value* right) { 1750 Value* right) {
1878 UNREACHABLE(); 1751 UNREACHABLE();
1879 return NULL; 1752 return NULL;
1880 } 1753 }
1881 1754
1882
1883 Definition* CheckedSmiComparisonInstr::Canonicalize(FlowGraph* flow_graph) { 1755 Definition* CheckedSmiComparisonInstr::Canonicalize(FlowGraph* flow_graph) {
1884 if ((left()->Type()->ToCid() == kSmiCid) && 1756 if ((left()->Type()->ToCid() == kSmiCid) &&
1885 (right()->Type()->ToCid() == kSmiCid)) { 1757 (right()->Type()->ToCid() == kSmiCid)) {
1886 Definition* replacement = NULL; 1758 Definition* replacement = NULL;
1887 if (Token::IsRelationalOperator(kind())) { 1759 if (Token::IsRelationalOperator(kind())) {
1888 replacement = new RelationalOpInstr( 1760 replacement = new RelationalOpInstr(
1889 token_pos(), kind(), new Value(left()->definition()), 1761 token_pos(), kind(), new Value(left()->definition()),
1890 new Value(right()->definition()), kSmiCid, Thread::kNoDeoptId); 1762 new Value(right()->definition()), kSmiCid, Thread::kNoDeoptId);
1891 } else if (Token::IsEqualityOperator(kind())) { 1763 } else if (Token::IsEqualityOperator(kind())) {
1892 replacement = new EqualityCompareInstr( 1764 replacement = new EqualityCompareInstr(
1893 token_pos(), kind(), new Value(left()->definition()), 1765 token_pos(), kind(), new Value(left()->definition()),
1894 new Value(right()->definition()), kSmiCid, Thread::kNoDeoptId); 1766 new Value(right()->definition()), kSmiCid, Thread::kNoDeoptId);
1895 } 1767 }
1896 if (replacement != NULL) { 1768 if (replacement != NULL) {
1897 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue); 1769 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue);
1898 return replacement; 1770 return replacement;
1899 } 1771 }
1900 } 1772 }
1901 return this; 1773 return this;
1902 } 1774 }
1903 1775
1904
1905 Definition* BinaryIntegerOpInstr::Canonicalize(FlowGraph* flow_graph) { 1776 Definition* BinaryIntegerOpInstr::Canonicalize(FlowGraph* flow_graph) {
1906 // If both operands are constants evaluate this expression. Might 1777 // If both operands are constants evaluate this expression. Might
1907 // occur due to load forwarding after constant propagation pass 1778 // occur due to load forwarding after constant propagation pass
1908 // have already been run. 1779 // have already been run.
1909 if (left()->BindsToConstant() && left()->BoundConstant().IsInteger() && 1780 if (left()->BindsToConstant() && left()->BoundConstant().IsInteger() &&
1910 right()->BindsToConstant() && right()->BoundConstant().IsInteger()) { 1781 right()->BindsToConstant() && right()->BoundConstant().IsInteger()) {
1911 const Integer& result = 1782 const Integer& result =
1912 Integer::Handle(Evaluate(Integer::Cast(left()->BoundConstant()), 1783 Integer::Handle(Evaluate(Integer::Cast(left()->BoundConstant()),
1913 Integer::Cast(right()->BoundConstant()))); 1784 Integer::Cast(right()->BoundConstant())));
1914 if (!result.IsNull()) { 1785 if (!result.IsNull()) {
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
2044 break; 1915 break;
2045 } 1916 }
2046 1917
2047 default: 1918 default:
2048 break; 1919 break;
2049 } 1920 }
2050 1921
2051 return this; 1922 return this;
2052 } 1923 }
2053 1924
2054
2055 // Optimizations that eliminate or simplify individual instructions. 1925 // Optimizations that eliminate or simplify individual instructions.
2056 Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) { 1926 Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) {
2057 return this; 1927 return this;
2058 } 1928 }
2059 1929
2060
2061 Definition* Definition::Canonicalize(FlowGraph* flow_graph) { 1930 Definition* Definition::Canonicalize(FlowGraph* flow_graph) {
2062 return this; 1931 return this;
2063 } 1932 }
2064 1933
2065
2066 Definition* RedefinitionInstr::Canonicalize(FlowGraph* flow_graph) { 1934 Definition* RedefinitionInstr::Canonicalize(FlowGraph* flow_graph) {
2067 if (!HasUses()) { 1935 if (!HasUses()) {
2068 return NULL; 1936 return NULL;
2069 } 1937 }
2070 if ((constrained_type() != NULL) && 1938 if ((constrained_type() != NULL) &&
2071 Type()->IsEqualTo(value()->definition()->Type())) { 1939 Type()->IsEqualTo(value()->definition()->Type())) {
2072 return value()->definition(); 1940 return value()->definition();
2073 } 1941 }
2074 return this; 1942 return this;
2075 } 1943 }
2076 1944
2077
2078 Instruction* CheckStackOverflowInstr::Canonicalize(FlowGraph* flow_graph) { 1945 Instruction* CheckStackOverflowInstr::Canonicalize(FlowGraph* flow_graph) {
2079 switch (kind_) { 1946 switch (kind_) {
2080 case kOsrAndPreemption: 1947 case kOsrAndPreemption:
2081 return this; 1948 return this;
2082 case kOsrOnly: 1949 case kOsrOnly:
2083 // Don't need OSR entries in the optimized code. 1950 // Don't need OSR entries in the optimized code.
2084 return NULL; 1951 return NULL;
2085 } 1952 }
2086 1953
2087 // Switch above exhausts all possibilities but some compilers can't figure 1954 // Switch above exhausts all possibilities but some compilers can't figure
2088 // it out. 1955 // it out.
2089 UNREACHABLE(); 1956 UNREACHABLE();
2090 return this; 1957 return this;
2091 } 1958 }
2092 1959
2093
2094 bool LoadFieldInstr::IsImmutableLengthLoad() const { 1960 bool LoadFieldInstr::IsImmutableLengthLoad() const {
2095 switch (recognized_kind()) { 1961 switch (recognized_kind()) {
2096 case MethodRecognizer::kObjectArrayLength: 1962 case MethodRecognizer::kObjectArrayLength:
2097 case MethodRecognizer::kImmutableArrayLength: 1963 case MethodRecognizer::kImmutableArrayLength:
2098 case MethodRecognizer::kTypedDataLength: 1964 case MethodRecognizer::kTypedDataLength:
2099 case MethodRecognizer::kStringBaseLength: 1965 case MethodRecognizer::kStringBaseLength:
2100 return true; 1966 return true;
2101 default: 1967 default:
2102 return false; 1968 return false;
2103 } 1969 }
2104 } 1970 }
2105 1971
2106
2107 MethodRecognizer::Kind LoadFieldInstr::RecognizedKindFromArrayCid( 1972 MethodRecognizer::Kind LoadFieldInstr::RecognizedKindFromArrayCid(
2108 intptr_t cid) { 1973 intptr_t cid) {
2109 if (RawObject::IsTypedDataClassId(cid) || 1974 if (RawObject::IsTypedDataClassId(cid) ||
2110 RawObject::IsExternalTypedDataClassId(cid)) { 1975 RawObject::IsExternalTypedDataClassId(cid)) {
2111 return MethodRecognizer::kTypedDataLength; 1976 return MethodRecognizer::kTypedDataLength;
2112 } 1977 }
2113 switch (cid) { 1978 switch (cid) {
2114 case kArrayCid: 1979 case kArrayCid:
2115 return MethodRecognizer::kObjectArrayLength; 1980 return MethodRecognizer::kObjectArrayLength;
2116 case kImmutableArrayCid: 1981 case kImmutableArrayCid:
2117 return MethodRecognizer::kImmutableArrayLength; 1982 return MethodRecognizer::kImmutableArrayLength;
2118 case kGrowableObjectArrayCid: 1983 case kGrowableObjectArrayCid:
2119 return MethodRecognizer::kGrowableArrayLength; 1984 return MethodRecognizer::kGrowableArrayLength;
2120 default: 1985 default:
2121 UNREACHABLE(); 1986 UNREACHABLE();
2122 return MethodRecognizer::kUnknown; 1987 return MethodRecognizer::kUnknown;
2123 } 1988 }
2124 } 1989 }
2125 1990
2126
2127 bool LoadFieldInstr::IsFixedLengthArrayCid(intptr_t cid) { 1991 bool LoadFieldInstr::IsFixedLengthArrayCid(intptr_t cid) {
2128 if (RawObject::IsTypedDataClassId(cid) || 1992 if (RawObject::IsTypedDataClassId(cid) ||
2129 RawObject::IsExternalTypedDataClassId(cid)) { 1993 RawObject::IsExternalTypedDataClassId(cid)) {
2130 return true; 1994 return true;
2131 } 1995 }
2132 1996
2133 switch (cid) { 1997 switch (cid) {
2134 case kArrayCid: 1998 case kArrayCid:
2135 case kImmutableArrayCid: 1999 case kImmutableArrayCid:
2136 return true; 2000 return true;
2137 default: 2001 default:
2138 return false; 2002 return false;
2139 } 2003 }
2140 } 2004 }
2141 2005
2142
2143 Definition* ConstantInstr::Canonicalize(FlowGraph* flow_graph) { 2006 Definition* ConstantInstr::Canonicalize(FlowGraph* flow_graph) {
2144 return HasUses() ? this : NULL; 2007 return HasUses() ? this : NULL;
2145 } 2008 }
2146 2009
2147
2148 // A math unary instruction has a side effect (exception 2010 // A math unary instruction has a side effect (exception
2149 // thrown) if the argument is not a number. 2011 // thrown) if the argument is not a number.
2150 // TODO(srdjan): eliminate if has no uses and input is guaranteed to be number. 2012 // TODO(srdjan): eliminate if has no uses and input is guaranteed to be number.
2151 Definition* MathUnaryInstr::Canonicalize(FlowGraph* flow_graph) { 2013 Definition* MathUnaryInstr::Canonicalize(FlowGraph* flow_graph) {
2152 return this; 2014 return this;
2153 } 2015 }
2154 2016
2155
2156 bool LoadFieldInstr::Evaluate(const Object& instance, Object* result) { 2017 bool LoadFieldInstr::Evaluate(const Object& instance, Object* result) {
2157 if (field() == NULL || !field()->is_final() || !instance.IsInstance()) { 2018 if (field() == NULL || !field()->is_final() || !instance.IsInstance()) {
2158 return false; 2019 return false;
2159 } 2020 }
2160 2021
2161 // Check that instance really has the field which we 2022 // Check that instance really has the field which we
2162 // are trying to load from. 2023 // are trying to load from.
2163 Class& cls = Class::Handle(instance.clazz()); 2024 Class& cls = Class::Handle(instance.clazz());
2164 while (cls.raw() != Class::null() && cls.raw() != field()->Owner()) { 2025 while (cls.raw() != Class::null() && cls.raw() != field()->Owner()) {
2165 cls = cls.SuperClass(); 2026 cls = cls.SuperClass();
2166 } 2027 }
2167 if (cls.raw() != field()->Owner()) { 2028 if (cls.raw() != field()->Owner()) {
2168 // Failed to find the field in class or its superclasses. 2029 // Failed to find the field in class or its superclasses.
2169 return false; 2030 return false;
2170 } 2031 }
2171 2032
2172 // Object has the field: execute the load. 2033 // Object has the field: execute the load.
2173 *result = Instance::Cast(instance).GetField(*field()); 2034 *result = Instance::Cast(instance).GetField(*field());
2174 return true; 2035 return true;
2175 } 2036 }
2176 2037
2177
2178 Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) { 2038 Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) {
2179 if (!HasUses()) return NULL; 2039 if (!HasUses()) return NULL;
2180 2040
2181 if (IsImmutableLengthLoad()) { 2041 if (IsImmutableLengthLoad()) {
2182 // For fixed length arrays if the array is the result of a known constructor 2042 // For fixed length arrays if the array is the result of a known constructor
2183 // call we can replace the length load with the length argument passed to 2043 // call we can replace the length load with the length argument passed to
2184 // the constructor. 2044 // the constructor.
2185 StaticCallInstr* call = 2045 StaticCallInstr* call =
2186 instance()->definition()->OriginalDefinition()->AsStaticCall(); 2046 instance()->definition()->OriginalDefinition()->AsStaticCall();
2187 if (call != NULL) { 2047 if (call != NULL) {
(...skipping 27 matching lines...) Expand all
2215 if (instance()->BindsToConstant()) { 2075 if (instance()->BindsToConstant()) {
2216 Object& result = Object::Handle(); 2076 Object& result = Object::Handle();
2217 if (Evaluate(instance()->BoundConstant(), &result)) { 2077 if (Evaluate(instance()->BoundConstant(), &result)) {
2218 return flow_graph->GetConstant(result); 2078 return flow_graph->GetConstant(result);
2219 } 2079 }
2220 } 2080 }
2221 2081
2222 return this; 2082 return this;
2223 } 2083 }
2224 2084
2225
2226 Definition* AssertBooleanInstr::Canonicalize(FlowGraph* flow_graph) { 2085 Definition* AssertBooleanInstr::Canonicalize(FlowGraph* flow_graph) {
2227 if (FLAG_eliminate_type_checks && (value()->Type()->ToCid() == kBoolCid)) { 2086 if (FLAG_eliminate_type_checks && (value()->Type()->ToCid() == kBoolCid)) {
2228 return value()->definition(); 2087 return value()->definition();
2229 } 2088 }
2230 2089
2231 return this; 2090 return this;
2232 } 2091 }
2233 2092
2234
2235 Definition* AssertAssignableInstr::Canonicalize(FlowGraph* flow_graph) { 2093 Definition* AssertAssignableInstr::Canonicalize(FlowGraph* flow_graph) {
2236 if (FLAG_eliminate_type_checks && 2094 if (FLAG_eliminate_type_checks &&
2237 value()->Type()->IsAssignableTo(dst_type())) { 2095 value()->Type()->IsAssignableTo(dst_type())) {
2238 return value()->definition(); 2096 return value()->definition();
2239 } 2097 }
2240 if (dst_type().IsInstantiated()) { 2098 if (dst_type().IsInstantiated()) {
2241 return this; 2099 return this;
2242 } 2100 }
2243 // For uninstantiated target types: If the instantiator and function 2101 // For uninstantiated target types: If the instantiator and function
2244 // type arguments are constant, instantiate the target type here. 2102 // type arguments are constant, instantiate the target type here.
(...skipping 30 matching lines...) Expand all
2275 return value()->definition(); 2133 return value()->definition();
2276 } 2134 }
2277 2135
2278 ConstantInstr* null_constant = flow_graph->constant_null(); 2136 ConstantInstr* null_constant = flow_graph->constant_null();
2279 instantiator_type_arguments()->BindTo(null_constant); 2137 instantiator_type_arguments()->BindTo(null_constant);
2280 function_type_arguments()->BindTo(null_constant); 2138 function_type_arguments()->BindTo(null_constant);
2281 } 2139 }
2282 return this; 2140 return this;
2283 } 2141 }
2284 2142
2285
2286 Definition* InstantiateTypeArgumentsInstr::Canonicalize(FlowGraph* flow_graph) { 2143 Definition* InstantiateTypeArgumentsInstr::Canonicalize(FlowGraph* flow_graph) {
2287 return (Isolate::Current()->type_checks() || HasUses()) ? this : NULL; 2144 return (Isolate::Current()->type_checks() || HasUses()) ? this : NULL;
2288 } 2145 }
2289 2146
2290
2291 LocationSummary* DebugStepCheckInstr::MakeLocationSummary(Zone* zone, 2147 LocationSummary* DebugStepCheckInstr::MakeLocationSummary(Zone* zone,
2292 bool opt) const { 2148 bool opt) const {
2293 const intptr_t kNumInputs = 0; 2149 const intptr_t kNumInputs = 0;
2294 const intptr_t kNumTemps = 0; 2150 const intptr_t kNumTemps = 0;
2295 LocationSummary* locs = new (zone) 2151 LocationSummary* locs = new (zone)
2296 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); 2152 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
2297 return locs; 2153 return locs;
2298 } 2154 }
2299 2155
2300
2301 Instruction* DebugStepCheckInstr::Canonicalize(FlowGraph* flow_graph) { 2156 Instruction* DebugStepCheckInstr::Canonicalize(FlowGraph* flow_graph) {
2302 return NULL; 2157 return NULL;
2303 } 2158 }
2304 2159
2305
2306 static bool HasTryBlockUse(Value* use_list) { 2160 static bool HasTryBlockUse(Value* use_list) {
2307 for (Value::Iterator it(use_list); !it.Done(); it.Advance()) { 2161 for (Value::Iterator it(use_list); !it.Done(); it.Advance()) {
2308 Value* use = it.Current(); 2162 Value* use = it.Current();
2309 if (use->instruction()->MayThrow() && 2163 if (use->instruction()->MayThrow() &&
2310 use->instruction()->GetBlock()->InsideTryBlock()) { 2164 use->instruction()->GetBlock()->InsideTryBlock()) {
2311 return true; 2165 return true;
2312 } 2166 }
2313 } 2167 }
2314 return false; 2168 return false;
2315 } 2169 }
2316 2170
2317
2318 Definition* BoxInstr::Canonicalize(FlowGraph* flow_graph) { 2171 Definition* BoxInstr::Canonicalize(FlowGraph* flow_graph) {
2319 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { 2172 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
2320 // Environments can accommodate any representation. No need to box. 2173 // Environments can accommodate any representation. No need to box.
2321 return value()->definition(); 2174 return value()->definition();
2322 } 2175 }
2323 2176
2324 // Fold away Box<rep>(Unbox<rep>(v)) if value is known to be of the 2177 // Fold away Box<rep>(Unbox<rep>(v)) if value is known to be of the
2325 // right class. 2178 // right class.
2326 UnboxInstr* unbox_defn = value()->definition()->AsUnbox(); 2179 UnboxInstr* unbox_defn = value()->definition()->AsUnbox();
2327 if ((unbox_defn != NULL) && 2180 if ((unbox_defn != NULL) &&
2328 (unbox_defn->representation() == from_representation()) && 2181 (unbox_defn->representation() == from_representation()) &&
2329 (unbox_defn->value()->Type()->ToCid() == Type()->ToCid())) { 2182 (unbox_defn->value()->Type()->ToCid() == Type()->ToCid())) {
2330 return unbox_defn->value()->definition(); 2183 return unbox_defn->value()->definition();
2331 } 2184 }
2332 2185
2333 return this; 2186 return this;
2334 } 2187 }
2335 2188
2336
2337 bool BoxIntegerInstr::ValueFitsSmi() const { 2189 bool BoxIntegerInstr::ValueFitsSmi() const {
2338 Range* range = value()->definition()->range(); 2190 Range* range = value()->definition()->range();
2339 return RangeUtils::Fits(range, RangeBoundary::kRangeBoundarySmi); 2191 return RangeUtils::Fits(range, RangeBoundary::kRangeBoundarySmi);
2340 } 2192 }
2341 2193
2342
2343 Definition* BoxIntegerInstr::Canonicalize(FlowGraph* flow_graph) { 2194 Definition* BoxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
2344 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { 2195 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
2345 // Environments can accommodate any representation. No need to box. 2196 // Environments can accommodate any representation. No need to box.
2346 return value()->definition(); 2197 return value()->definition();
2347 } 2198 }
2348 2199
2349 return this; 2200 return this;
2350 } 2201 }
2351 2202
2352
2353 Definition* BoxInt64Instr::Canonicalize(FlowGraph* flow_graph) { 2203 Definition* BoxInt64Instr::Canonicalize(FlowGraph* flow_graph) {
2354 Definition* replacement = BoxIntegerInstr::Canonicalize(flow_graph); 2204 Definition* replacement = BoxIntegerInstr::Canonicalize(flow_graph);
2355 if (replacement != this) { 2205 if (replacement != this) {
2356 return replacement; 2206 return replacement;
2357 } 2207 }
2358 2208
2359 UnboxedIntConverterInstr* conv = 2209 UnboxedIntConverterInstr* conv =
2360 value()->definition()->AsUnboxedIntConverter(); 2210 value()->definition()->AsUnboxedIntConverter();
2361 if (conv != NULL) { 2211 if (conv != NULL) {
2362 Definition* replacement = this; 2212 Definition* replacement = this;
(...skipping 13 matching lines...) Expand all
2376 if (replacement != this) { 2226 if (replacement != this) {
2377 flow_graph->InsertBefore(this, replacement, NULL, FlowGraph::kValue); 2227 flow_graph->InsertBefore(this, replacement, NULL, FlowGraph::kValue);
2378 } 2228 }
2379 2229
2380 return replacement; 2230 return replacement;
2381 } 2231 }
2382 2232
2383 return this; 2233 return this;
2384 } 2234 }
2385 2235
2386
2387 Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) { 2236 Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) {
2388 if (!HasUses() && !CanDeoptimize()) return NULL; 2237 if (!HasUses() && !CanDeoptimize()) return NULL;
2389 2238
2390 // Fold away Unbox<rep>(Box<rep>(v)). 2239 // Fold away Unbox<rep>(Box<rep>(v)).
2391 BoxInstr* box_defn = value()->definition()->AsBox(); 2240 BoxInstr* box_defn = value()->definition()->AsBox();
2392 if ((box_defn != NULL) && 2241 if ((box_defn != NULL) &&
2393 (box_defn->from_representation() == representation())) { 2242 (box_defn->from_representation() == representation())) {
2394 return box_defn->value()->definition(); 2243 return box_defn->value()->definition();
2395 } 2244 }
2396 2245
(...skipping 12 matching lines...) Expand all
2409 2258
2410 if (uc != NULL) { 2259 if (uc != NULL) {
2411 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); 2260 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
2412 return uc; 2261 return uc;
2413 } 2262 }
2414 } 2263 }
2415 2264
2416 return this; 2265 return this;
2417 } 2266 }
2418 2267
2419
2420 Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) { 2268 Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
2421 if (!HasUses() && !CanDeoptimize()) return NULL; 2269 if (!HasUses() && !CanDeoptimize()) return NULL;
2422 2270
2423 // Fold away UnboxInteger<rep_to>(BoxInteger<rep_from>(v)). 2271 // Fold away UnboxInteger<rep_to>(BoxInteger<rep_from>(v)).
2424 BoxIntegerInstr* box_defn = value()->definition()->AsBoxInteger(); 2272 BoxIntegerInstr* box_defn = value()->definition()->AsBoxInteger();
2425 if (box_defn != NULL) { 2273 if (box_defn != NULL) {
2426 Representation from_representation = 2274 Representation from_representation =
2427 box_defn->value()->definition()->representation(); 2275 box_defn->value()->definition()->representation();
2428 if (from_representation == representation()) { 2276 if (from_representation == representation()) {
2429 return box_defn->value()->definition(); 2277 return box_defn->value()->definition();
(...skipping 13 matching lines...) Expand all
2443 converter->mark_truncating(); 2291 converter->mark_truncating();
2444 } 2292 }
2445 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue); 2293 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue);
2446 return converter; 2294 return converter;
2447 } 2295 }
2448 } 2296 }
2449 2297
2450 return this; 2298 return this;
2451 } 2299 }
2452 2300
2453
2454 Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) { 2301 Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) {
2455 Definition* replacement = UnboxIntegerInstr::Canonicalize(flow_graph); 2302 Definition* replacement = UnboxIntegerInstr::Canonicalize(flow_graph);
2456 if (replacement != this) { 2303 if (replacement != this) {
2457 return replacement; 2304 return replacement;
2458 } 2305 }
2459 2306
2460 ConstantInstr* c = value()->definition()->AsConstant(); 2307 ConstantInstr* c = value()->definition()->AsConstant();
2461 if ((c != NULL) && c->value().IsSmi()) { 2308 if ((c != NULL) && c->value().IsSmi()) {
2462 if (!is_truncating() && (kSmiBits > 32)) { 2309 if (!is_truncating() && (kSmiBits > 32)) {
2463 // Check that constant fits into 32-bit integer. 2310 // Check that constant fits into 32-bit integer.
2464 const int64_t value = static_cast<int64_t>(Smi::Cast(c->value()).Value()); 2311 const int64_t value = static_cast<int64_t>(Smi::Cast(c->value()).Value());
2465 if (!Utils::IsInt(32, value)) { 2312 if (!Utils::IsInt(32, value)) {
2466 return this; 2313 return this;
2467 } 2314 }
2468 } 2315 }
2469 2316
2470 UnboxedConstantInstr* uc = 2317 UnboxedConstantInstr* uc =
2471 new UnboxedConstantInstr(c->value(), kUnboxedInt32); 2318 new UnboxedConstantInstr(c->value(), kUnboxedInt32);
2472 if (c->range() != NULL) { 2319 if (c->range() != NULL) {
2473 uc->set_range(*c->range()); 2320 uc->set_range(*c->range());
2474 } 2321 }
2475 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); 2322 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
2476 return uc; 2323 return uc;
2477 } 2324 }
2478 2325
2479 return this; 2326 return this;
2480 } 2327 }
2481 2328
2482
2483 Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) { 2329 Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
2484 if (!HasUses()) return NULL; 2330 if (!HasUses()) return NULL;
2485 2331
2486 UnboxedIntConverterInstr* box_defn = 2332 UnboxedIntConverterInstr* box_defn =
2487 value()->definition()->AsUnboxedIntConverter(); 2333 value()->definition()->AsUnboxedIntConverter();
2488 if ((box_defn != NULL) && (box_defn->representation() == from())) { 2334 if ((box_defn != NULL) && (box_defn->representation() == from())) {
2489 if (box_defn->from() == to()) { 2335 if (box_defn->from() == to()) {
2490 // Do not erase truncating conversions from 64-bit value to 32-bit values 2336 // Do not erase truncating conversions from 64-bit value to 32-bit values
2491 // because such conversions erase upper 32 bits. 2337 // because such conversions erase upper 32 bits.
2492 if ((box_defn->from() == kUnboxedMint) && box_defn->is_truncating()) { 2338 if ((box_defn->from() == kUnboxedMint) && box_defn->is_truncating()) {
(...skipping 22 matching lines...) Expand all
2515 new UnboxInt32Instr(is_truncating() ? UnboxInt32Instr::kTruncate 2361 new UnboxInt32Instr(is_truncating() ? UnboxInt32Instr::kTruncate
2516 : UnboxInt32Instr::kNoTruncation, 2362 : UnboxInt32Instr::kNoTruncation,
2517 unbox_defn->value()->CopyWithType(), GetDeoptId()); 2363 unbox_defn->value()->CopyWithType(), GetDeoptId());
2518 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue); 2364 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue);
2519 return replacement; 2365 return replacement;
2520 } 2366 }
2521 2367
2522 return this; 2368 return this;
2523 } 2369 }
2524 2370
2525
2526 Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) { 2371 Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) {
2527 Definition* defn = value()->definition(); 2372 Definition* defn = value()->definition();
2528 if (defn->IsComparison() && defn->HasOnlyUse(value()) && 2373 if (defn->IsComparison() && defn->HasOnlyUse(value()) &&
2529 defn->Type()->ToCid() == kBoolCid) { 2374 defn->Type()->ToCid() == kBoolCid) {
2530 defn->AsComparison()->NegateComparison(); 2375 defn->AsComparison()->NegateComparison();
2531 return defn; 2376 return defn;
2532 } 2377 }
2533 return this; 2378 return this;
2534 } 2379 }
2535 2380
2536
2537 static bool MayBeBoxableNumber(intptr_t cid) { 2381 static bool MayBeBoxableNumber(intptr_t cid) {
2538 return (cid == kDynamicCid) || (cid == kMintCid) || (cid == kBigintCid) || 2382 return (cid == kDynamicCid) || (cid == kMintCid) || (cid == kBigintCid) ||
2539 (cid == kDoubleCid); 2383 (cid == kDoubleCid);
2540 } 2384 }
2541 2385
2542
2543 static bool MaybeNumber(CompileType* type) { 2386 static bool MaybeNumber(CompileType* type) {
2544 ASSERT(Type::Handle(Type::Number()) 2387 ASSERT(Type::Handle(Type::Number())
2545 .IsMoreSpecificThan(Type::Handle(Type::Number()), NULL, NULL, 2388 .IsMoreSpecificThan(Type::Handle(Type::Number()), NULL, NULL,
2546 Heap::kOld)); 2389 Heap::kOld));
2547 return type->ToAbstractType()->IsDynamicType() || 2390 return type->ToAbstractType()->IsDynamicType() ||
2548 type->ToAbstractType()->IsObjectType() || 2391 type->ToAbstractType()->IsObjectType() ||
2549 type->ToAbstractType()->IsTypeParameter() || 2392 type->ToAbstractType()->IsTypeParameter() ||
2550 type->IsMoreSpecificThan(Type::Handle(Type::Number())); 2393 type->IsMoreSpecificThan(Type::Handle(Type::Number()));
2551 } 2394 }
2552 2395
2553
2554 // Returns a replacement for a strict comparison and signals if the result has 2396 // Returns a replacement for a strict comparison and signals if the result has
2555 // to be negated. 2397 // to be negated.
2556 static Definition* CanonicalizeStrictCompare(StrictCompareInstr* compare, 2398 static Definition* CanonicalizeStrictCompare(StrictCompareInstr* compare,
2557 bool* negated, 2399 bool* negated,
2558 bool is_branch) { 2400 bool is_branch) {
2559 // Use propagated cid and type information to eliminate number checks. 2401 // Use propagated cid and type information to eliminate number checks.
2560 // If one of the inputs is not a boxable number (Mint, Double, Bigint), or 2402 // If one of the inputs is not a boxable number (Mint, Double, Bigint), or
2561 // is not a subtype of num, no need for number checks. 2403 // is not a subtype of num, no need for number checks.
2562 if (compare->needs_number_check()) { 2404 if (compare->needs_number_check()) {
2563 if (!MayBeBoxableNumber(compare->left()->Type()->ToCid()) || 2405 if (!MayBeBoxableNumber(compare->left()->Type()->ToCid()) ||
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2604 // Handle e === false. 2446 // Handle e === false.
2605 if ((kind == Token::kEQ_STRICT) && (constant.raw() == Bool::False().raw()) && 2447 if ((kind == Token::kEQ_STRICT) && (constant.raw() == Bool::False().raw()) &&
2606 other_defn->IsComparison() && can_merge && 2448 other_defn->IsComparison() && can_merge &&
2607 other_defn->HasOnlyUse(other)) { 2449 other_defn->HasOnlyUse(other)) {
2608 *negated = true; 2450 *negated = true;
2609 return other_defn; 2451 return other_defn;
2610 } 2452 }
2611 return compare; 2453 return compare;
2612 } 2454 }
2613 2455
2614
2615 static bool BindsToGivenConstant(Value* v, intptr_t expected) { 2456 static bool BindsToGivenConstant(Value* v, intptr_t expected) {
2616 return v->BindsToConstant() && v->BoundConstant().IsSmi() && 2457 return v->BindsToConstant() && v->BoundConstant().IsSmi() &&
2617 (Smi::Cast(v->BoundConstant()).Value() == expected); 2458 (Smi::Cast(v->BoundConstant()).Value() == expected);
2618 } 2459 }
2619 2460
2620
2621 // Recognize patterns (a & b) == 0 and (a & 2^n) != 2^n. 2461 // Recognize patterns (a & b) == 0 and (a & 2^n) != 2^n.
2622 static bool RecognizeTestPattern(Value* left, Value* right, bool* negate) { 2462 static bool RecognizeTestPattern(Value* left, Value* right, bool* negate) {
2623 if (!right->BindsToConstant() || !right->BoundConstant().IsSmi()) { 2463 if (!right->BindsToConstant() || !right->BoundConstant().IsSmi()) {
2624 return false; 2464 return false;
2625 } 2465 }
2626 2466
2627 const intptr_t value = Smi::Cast(right->BoundConstant()).Value(); 2467 const intptr_t value = Smi::Cast(right->BoundConstant()).Value();
2628 if ((value != 0) && !Utils::IsPowerOfTwo(value)) { 2468 if ((value != 0) && !Utils::IsPowerOfTwo(value)) {
2629 return false; 2469 return false;
2630 } 2470 }
2631 2471
2632
2633 BinarySmiOpInstr* mask_op = left->definition()->AsBinarySmiOp(); 2472 BinarySmiOpInstr* mask_op = left->definition()->AsBinarySmiOp();
2634 if ((mask_op == NULL) || (mask_op->op_kind() != Token::kBIT_AND) || 2473 if ((mask_op == NULL) || (mask_op->op_kind() != Token::kBIT_AND) ||
2635 !mask_op->HasOnlyUse(left)) { 2474 !mask_op->HasOnlyUse(left)) {
2636 return false; 2475 return false;
2637 } 2476 }
2638 2477
2639 if (value == 0) { 2478 if (value == 0) {
2640 // Recognized (a & b) == 0 pattern. 2479 // Recognized (a & b) == 0 pattern.
2641 *negate = false; 2480 *negate = false;
2642 return true; 2481 return true;
2643 } 2482 }
2644 2483
2645 // Recognize 2484 // Recognize
2646 if (BindsToGivenConstant(mask_op->left(), value) || 2485 if (BindsToGivenConstant(mask_op->left(), value) ||
2647 BindsToGivenConstant(mask_op->right(), value)) { 2486 BindsToGivenConstant(mask_op->right(), value)) {
2648 // Recognized (a & 2^n) == 2^n pattern. It's equivalent to (a & 2^n) != 0 2487 // Recognized (a & 2^n) == 2^n pattern. It's equivalent to (a & 2^n) != 0
2649 // so we need to negate original comparison. 2488 // so we need to negate original comparison.
2650 *negate = true; 2489 *negate = true;
2651 return true; 2490 return true;
2652 } 2491 }
2653 2492
2654 return false; 2493 return false;
2655 } 2494 }
2656 2495
2657
2658 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) { 2496 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) {
2659 Zone* zone = flow_graph->zone(); 2497 Zone* zone = flow_graph->zone();
2660 // Only handle strict-compares. 2498 // Only handle strict-compares.
2661 if (comparison()->IsStrictCompare()) { 2499 if (comparison()->IsStrictCompare()) {
2662 bool negated = false; 2500 bool negated = false;
2663 Definition* replacement = CanonicalizeStrictCompare( 2501 Definition* replacement = CanonicalizeStrictCompare(
2664 comparison()->AsStrictCompare(), &negated, /* is_branch = */ true); 2502 comparison()->AsStrictCompare(), &negated, /* is_branch = */ true);
2665 if (replacement == comparison()) { 2503 if (replacement == comparison()) {
2666 return this; 2504 return this;
2667 } 2505 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2718 ASSERT(!CanDeoptimize()); 2556 ASSERT(!CanDeoptimize());
2719 RemoveEnvironment(); 2557 RemoveEnvironment();
2720 flow_graph->CopyDeoptTarget(this, bit_and); 2558 flow_graph->CopyDeoptTarget(this, bit_and);
2721 SetComparison(test); 2559 SetComparison(test);
2722 bit_and->RemoveFromGraph(); 2560 bit_and->RemoveFromGraph();
2723 } 2561 }
2724 } 2562 }
2725 return this; 2563 return this;
2726 } 2564 }
2727 2565
2728
2729 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) { 2566 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) {
2730 if (!HasUses()) return NULL; 2567 if (!HasUses()) return NULL;
2731 bool negated = false; 2568 bool negated = false;
2732 Definition* replacement = CanonicalizeStrictCompare(this, &negated, 2569 Definition* replacement = CanonicalizeStrictCompare(this, &negated,
2733 /* is_branch = */ false); 2570 /* is_branch = */ false);
2734 if (negated && replacement->IsComparison()) { 2571 if (negated && replacement->IsComparison()) {
2735 ASSERT(replacement != this); 2572 ASSERT(replacement != this);
2736 replacement->AsComparison()->NegateComparison(); 2573 replacement->AsComparison()->NegateComparison();
2737 } 2574 }
2738 return replacement; 2575 return replacement;
2739 } 2576 }
2740 2577
2741
2742 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) { 2578 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) {
2743 const intptr_t value_cid = value()->Type()->ToCid(); 2579 const intptr_t value_cid = value()->Type()->ToCid();
2744 if (value_cid == kDynamicCid) { 2580 if (value_cid == kDynamicCid) {
2745 return this; 2581 return this;
2746 } 2582 }
2747 2583
2748 return cids().HasClassId(value_cid) ? NULL : this; 2584 return cids().HasClassId(value_cid) ? NULL : this;
2749 } 2585 }
2750 2586
2751
2752 Instruction* CheckClassIdInstr::Canonicalize(FlowGraph* flow_graph) { 2587 Instruction* CheckClassIdInstr::Canonicalize(FlowGraph* flow_graph) {
2753 if (value()->BindsToConstant()) { 2588 if (value()->BindsToConstant()) {
2754 const Object& constant_value = value()->BoundConstant(); 2589 const Object& constant_value = value()->BoundConstant();
2755 if (constant_value.IsSmi() && 2590 if (constant_value.IsSmi() &&
2756 cids_.Contains(Smi::Cast(constant_value).Value())) { 2591 cids_.Contains(Smi::Cast(constant_value).Value())) {
2757 return NULL; 2592 return NULL;
2758 } 2593 }
2759 } 2594 }
2760 return this; 2595 return this;
2761 } 2596 }
2762 2597
2763
2764 TestCidsInstr::TestCidsInstr(TokenPosition token_pos, 2598 TestCidsInstr::TestCidsInstr(TokenPosition token_pos,
2765 Token::Kind kind, 2599 Token::Kind kind,
2766 Value* value, 2600 Value* value,
2767 const ZoneGrowableArray<intptr_t>& cid_results, 2601 const ZoneGrowableArray<intptr_t>& cid_results,
2768 intptr_t deopt_id) 2602 intptr_t deopt_id)
2769 : TemplateComparison(token_pos, kind, deopt_id), 2603 : TemplateComparison(token_pos, kind, deopt_id),
2770 cid_results_(cid_results), 2604 cid_results_(cid_results),
2771 licm_hoisted_(false) { 2605 licm_hoisted_(false) {
2772 ASSERT((kind == Token::kIS) || (kind == Token::kISNOT)); 2606 ASSERT((kind == Token::kIS) || (kind == Token::kISNOT));
2773 SetInputAt(0, value); 2607 SetInputAt(0, value);
2774 set_operation_cid(kObjectCid); 2608 set_operation_cid(kObjectCid);
2775 #ifdef DEBUG 2609 #ifdef DEBUG
2776 ASSERT(cid_results[0] == kSmiCid); 2610 ASSERT(cid_results[0] == kSmiCid);
2777 if (deopt_id == Thread::kNoDeoptId) { 2611 if (deopt_id == Thread::kNoDeoptId) {
2778 // The entry for Smi can be special, but all other entries have 2612 // The entry for Smi can be special, but all other entries have
2779 // to match in the no-deopt case. 2613 // to match in the no-deopt case.
2780 for (intptr_t i = 4; i < cid_results.length(); i += 2) { 2614 for (intptr_t i = 4; i < cid_results.length(); i += 2) {
2781 ASSERT(cid_results[i + 1] == cid_results[3]); 2615 ASSERT(cid_results[i + 1] == cid_results[3]);
2782 } 2616 }
2783 } 2617 }
2784 #endif 2618 #endif
2785 } 2619 }
2786 2620
2787
2788 Definition* TestCidsInstr::Canonicalize(FlowGraph* flow_graph) { 2621 Definition* TestCidsInstr::Canonicalize(FlowGraph* flow_graph) {
2789 CompileType* in_type = left()->Type(); 2622 CompileType* in_type = left()->Type();
2790 intptr_t cid = in_type->ToCid(); 2623 intptr_t cid = in_type->ToCid();
2791 if (cid == kDynamicCid) return this; 2624 if (cid == kDynamicCid) return this;
2792 2625
2793 const ZoneGrowableArray<intptr_t>& data = cid_results(); 2626 const ZoneGrowableArray<intptr_t>& data = cid_results();
2794 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; 2627 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
2795 for (intptr_t i = 0; i < data.length(); i += 2) { 2628 for (intptr_t i = 0; i < data.length(); i += 2) {
2796 if (data[i] == cid) { 2629 if (data[i] == cid) {
2797 return (data[i + 1] == true_result) 2630 return (data[i + 1] == true_result)
2798 ? flow_graph->GetConstant(Bool::True()) 2631 ? flow_graph->GetConstant(Bool::True())
2799 : flow_graph->GetConstant(Bool::False()); 2632 : flow_graph->GetConstant(Bool::False());
2800 } 2633 }
2801 } 2634 }
2802 2635
2803 if (!CanDeoptimize()) { 2636 if (!CanDeoptimize()) {
2804 ASSERT(deopt_id() == Thread::kNoDeoptId); 2637 ASSERT(deopt_id() == Thread::kNoDeoptId);
2805 return (data[data.length() - 1] == true_result) 2638 return (data[data.length() - 1] == true_result)
2806 ? flow_graph->GetConstant(Bool::False()) 2639 ? flow_graph->GetConstant(Bool::False())
2807 : flow_graph->GetConstant(Bool::True()); 2640 : flow_graph->GetConstant(Bool::True());
2808 } 2641 }
2809 2642
2810 // TODO(sra): Handle nullable input, possibly canonicalizing to a compare 2643 // TODO(sra): Handle nullable input, possibly canonicalizing to a compare
2811 // against `null`. 2644 // against `null`.
2812 return this; 2645 return this;
2813 } 2646 }
2814 2647
2815
2816 Instruction* GuardFieldClassInstr::Canonicalize(FlowGraph* flow_graph) { 2648 Instruction* GuardFieldClassInstr::Canonicalize(FlowGraph* flow_graph) {
2817 if (field().guarded_cid() == kDynamicCid) { 2649 if (field().guarded_cid() == kDynamicCid) {
2818 return NULL; // Nothing to guard. 2650 return NULL; // Nothing to guard.
2819 } 2651 }
2820 2652
2821 if (field().is_nullable() && value()->Type()->IsNull()) { 2653 if (field().is_nullable() && value()->Type()->IsNull()) {
2822 return NULL; 2654 return NULL;
2823 } 2655 }
2824 2656
2825 const intptr_t cid = field().is_nullable() ? value()->Type()->ToNullableCid() 2657 const intptr_t cid = field().is_nullable() ? value()->Type()->ToNullableCid()
2826 : value()->Type()->ToCid(); 2658 : value()->Type()->ToCid();
2827 if (field().guarded_cid() == cid) { 2659 if (field().guarded_cid() == cid) {
2828 return NULL; // Value is guaranteed to have this cid. 2660 return NULL; // Value is guaranteed to have this cid.
2829 } 2661 }
2830 2662
2831 return this; 2663 return this;
2832 } 2664 }
2833 2665
2834
2835 Instruction* GuardFieldLengthInstr::Canonicalize(FlowGraph* flow_graph) { 2666 Instruction* GuardFieldLengthInstr::Canonicalize(FlowGraph* flow_graph) {
2836 if (!field().needs_length_check()) { 2667 if (!field().needs_length_check()) {
2837 return NULL; // Nothing to guard. 2668 return NULL; // Nothing to guard.
2838 } 2669 }
2839 2670
2840 const intptr_t expected_length = field().guarded_list_length(); 2671 const intptr_t expected_length = field().guarded_list_length();
2841 if (expected_length == Field::kUnknownFixedLength) { 2672 if (expected_length == Field::kUnknownFixedLength) {
2842 return this; 2673 return this;
2843 } 2674 }
2844 2675
2845 // Check if length is statically known. 2676 // Check if length is statically known.
2846 StaticCallInstr* call = value()->definition()->AsStaticCall(); 2677 StaticCallInstr* call = value()->definition()->AsStaticCall();
2847 if (call == NULL) { 2678 if (call == NULL) {
2848 return this; 2679 return this;
2849 } 2680 }
2850 2681
2851 ConstantInstr* length = NULL; 2682 ConstantInstr* length = NULL;
2852 if (call->is_known_list_constructor() && 2683 if (call->is_known_list_constructor() &&
2853 LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) { 2684 LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) {
2854 length = call->ArgumentAt(1)->AsConstant(); 2685 length = call->ArgumentAt(1)->AsConstant();
2855 } 2686 }
2856 if ((length != NULL) && length->value().IsSmi() && 2687 if ((length != NULL) && length->value().IsSmi() &&
2857 Smi::Cast(length->value()).Value() == expected_length) { 2688 Smi::Cast(length->value()).Value() == expected_length) {
2858 return NULL; // Expected length matched. 2689 return NULL; // Expected length matched.
2859 } 2690 }
2860 2691
2861 return this; 2692 return this;
2862 } 2693 }
2863 2694
2864
2865 Instruction* CheckSmiInstr::Canonicalize(FlowGraph* flow_graph) { 2695 Instruction* CheckSmiInstr::Canonicalize(FlowGraph* flow_graph) {
2866 return (value()->Type()->ToCid() == kSmiCid) ? NULL : this; 2696 return (value()->Type()->ToCid() == kSmiCid) ? NULL : this;
2867 } 2697 }
2868 2698
2869
2870 Instruction* CheckEitherNonSmiInstr::Canonicalize(FlowGraph* flow_graph) { 2699 Instruction* CheckEitherNonSmiInstr::Canonicalize(FlowGraph* flow_graph) {
2871 if ((left()->Type()->ToCid() == kDoubleCid) || 2700 if ((left()->Type()->ToCid() == kDoubleCid) ||
2872 (right()->Type()->ToCid() == kDoubleCid)) { 2701 (right()->Type()->ToCid() == kDoubleCid)) {
2873 return NULL; // Remove from the graph. 2702 return NULL; // Remove from the graph.
2874 } 2703 }
2875 return this; 2704 return this;
2876 } 2705 }
2877 2706
2878
2879 BoxInstr* BoxInstr::Create(Representation from, Value* value) { 2707 BoxInstr* BoxInstr::Create(Representation from, Value* value) {
2880 switch (from) { 2708 switch (from) {
2881 case kUnboxedInt32: 2709 case kUnboxedInt32:
2882 return new BoxInt32Instr(value); 2710 return new BoxInt32Instr(value);
2883 2711
2884 case kUnboxedUint32: 2712 case kUnboxedUint32:
2885 return new BoxUint32Instr(value); 2713 return new BoxUint32Instr(value);
2886 2714
2887 case kUnboxedMint: 2715 case kUnboxedMint:
2888 return new BoxInt64Instr(value); 2716 return new BoxInt64Instr(value);
2889 2717
2890 case kUnboxedDouble: 2718 case kUnboxedDouble:
2891 case kUnboxedFloat32x4: 2719 case kUnboxedFloat32x4:
2892 case kUnboxedFloat64x2: 2720 case kUnboxedFloat64x2:
2893 case kUnboxedInt32x4: 2721 case kUnboxedInt32x4:
2894 return new BoxInstr(from, value); 2722 return new BoxInstr(from, value);
2895 2723
2896 default: 2724 default:
2897 UNREACHABLE(); 2725 UNREACHABLE();
2898 return NULL; 2726 return NULL;
2899 } 2727 }
2900 } 2728 }
2901 2729
2902
2903 UnboxInstr* UnboxInstr::Create(Representation to, 2730 UnboxInstr* UnboxInstr::Create(Representation to,
2904 Value* value, 2731 Value* value,
2905 intptr_t deopt_id) { 2732 intptr_t deopt_id) {
2906 switch (to) { 2733 switch (to) {
2907 case kUnboxedInt32: 2734 case kUnboxedInt32:
2908 return new UnboxInt32Instr(UnboxInt32Instr::kNoTruncation, value, 2735 return new UnboxInt32Instr(UnboxInt32Instr::kNoTruncation, value,
2909 deopt_id); 2736 deopt_id);
2910 2737
2911 case kUnboxedUint32: 2738 case kUnboxedUint32:
2912 return new UnboxUint32Instr(value, deopt_id); 2739 return new UnboxUint32Instr(value, deopt_id);
2913 2740
2914 case kUnboxedMint: 2741 case kUnboxedMint:
2915 return new UnboxInt64Instr(value, deopt_id); 2742 return new UnboxInt64Instr(value, deopt_id);
2916 2743
2917 case kUnboxedDouble: 2744 case kUnboxedDouble:
2918 case kUnboxedFloat32x4: 2745 case kUnboxedFloat32x4:
2919 case kUnboxedFloat64x2: 2746 case kUnboxedFloat64x2:
2920 case kUnboxedInt32x4: 2747 case kUnboxedInt32x4:
2921 return new UnboxInstr(to, value, deopt_id); 2748 return new UnboxInstr(to, value, deopt_id);
2922 2749
2923 default: 2750 default:
2924 UNREACHABLE(); 2751 UNREACHABLE();
2925 return NULL; 2752 return NULL;
2926 } 2753 }
2927 } 2754 }
2928 2755
2929
2930 bool UnboxInstr::CanConvertSmi() const { 2756 bool UnboxInstr::CanConvertSmi() const {
2931 switch (representation()) { 2757 switch (representation()) {
2932 case kUnboxedDouble: 2758 case kUnboxedDouble:
2933 case kUnboxedMint: 2759 case kUnboxedMint:
2934 return true; 2760 return true;
2935 2761
2936 case kUnboxedFloat32x4: 2762 case kUnboxedFloat32x4:
2937 case kUnboxedFloat64x2: 2763 case kUnboxedFloat64x2:
2938 case kUnboxedInt32x4: 2764 case kUnboxedInt32x4:
2939 return false; 2765 return false;
2940 2766
2941 default: 2767 default:
2942 UNREACHABLE(); 2768 UNREACHABLE();
2943 return false; 2769 return false;
2944 } 2770 }
2945 } 2771 }
2946 2772
2947
2948 CallTargets* CallTargets::Create(Zone* zone, const ICData& ic_data) { 2773 CallTargets* CallTargets::Create(Zone* zone, const ICData& ic_data) {
2949 CallTargets* targets = new (zone) CallTargets(zone); 2774 CallTargets* targets = new (zone) CallTargets(zone);
2950 targets->CreateHelper(zone, ic_data, /* argument_number = */ 0, 2775 targets->CreateHelper(zone, ic_data, /* argument_number = */ 0,
2951 /* include_targets = */ true); 2776 /* include_targets = */ true);
2952 targets->Sort(OrderById); 2777 targets->Sort(OrderById);
2953 targets->MergeIntoRanges(); 2778 targets->MergeIntoRanges();
2954 return targets; 2779 return targets;
2955 } 2780 }
2956 2781
2957
2958 CallTargets* CallTargets::CreateAndExpand(Zone* zone, const ICData& ic_data) { 2782 CallTargets* CallTargets::CreateAndExpand(Zone* zone, const ICData& ic_data) {
2959 CallTargets& targets = *new (zone) CallTargets(zone); 2783 CallTargets& targets = *new (zone) CallTargets(zone);
2960 targets.CreateHelper(zone, ic_data, /* argument_number = */ 0, 2784 targets.CreateHelper(zone, ic_data, /* argument_number = */ 0,
2961 /* include_targets = */ true); 2785 /* include_targets = */ true);
2962 targets.Sort(OrderById); 2786 targets.Sort(OrderById);
2963 2787
2964 Array& args_desc_array = Array::Handle(zone, ic_data.arguments_descriptor()); 2788 Array& args_desc_array = Array::Handle(zone, ic_data.arguments_descriptor());
2965 ArgumentsDescriptor args_desc(args_desc_array); 2789 ArgumentsDescriptor args_desc(args_desc_array);
2966 String& name = String::Handle(zone, ic_data.target_name()); 2790 String& name = String::Handle(zone, ic_data.target_name());
2967 2791
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
3007 } 2831 }
3008 } else { 2832 } else {
3009 break; 2833 break;
3010 } 2834 }
3011 } 2835 }
3012 } 2836 }
3013 targets.MergeIntoRanges(); 2837 targets.MergeIntoRanges();
3014 return &targets; 2838 return &targets;
3015 } 2839 }
3016 2840
3017
3018 void CallTargets::MergeIntoRanges() { 2841 void CallTargets::MergeIntoRanges() {
3019 // Merge adjacent class id ranges. 2842 // Merge adjacent class id ranges.
3020 int dest = 0; 2843 int dest = 0;
3021 // We merge entries that dispatch to the same target, but polymorphic targets 2844 // We merge entries that dispatch to the same target, but polymorphic targets
3022 // are not really the same target since they depend on the class-id, so we 2845 // are not really the same target since they depend on the class-id, so we
3023 // don't merge them. 2846 // don't merge them.
3024 for (int src = 1; src < length(); src++) { 2847 for (int src = 1; src < length(); src++) {
3025 const Function& target = *TargetAt(dest)->target; 2848 const Function& target = *TargetAt(dest)->target;
3026 if (TargetAt(dest)->cid_end + 1 >= TargetAt(src)->cid_start && 2849 if (TargetAt(dest)->cid_end + 1 >= TargetAt(src)->cid_start &&
3027 target.raw() == TargetAt(src)->target->raw() && 2850 target.raw() == TargetAt(src)->target->raw() &&
3028 !MethodRecognizer::PolymorphicTarget(target)) { 2851 !MethodRecognizer::PolymorphicTarget(target)) {
3029 TargetAt(dest)->cid_end = TargetAt(src)->cid_end; 2852 TargetAt(dest)->cid_end = TargetAt(src)->cid_end;
3030 TargetAt(dest)->count += TargetAt(src)->count; 2853 TargetAt(dest)->count += TargetAt(src)->count;
3031 } else { 2854 } else {
3032 dest++; 2855 dest++;
3033 if (src != dest) { 2856 if (src != dest) {
3034 // Use cid_ranges_ instead of TargetAt when updating the pointer. 2857 // Use cid_ranges_ instead of TargetAt when updating the pointer.
3035 cid_ranges_[dest] = TargetAt(src); 2858 cid_ranges_[dest] = TargetAt(src);
3036 } 2859 }
3037 } 2860 }
3038 } 2861 }
3039 SetLength(dest + 1); 2862 SetLength(dest + 1);
3040 Sort(OrderByFrequency); 2863 Sort(OrderByFrequency);
3041 } 2864 }
3042 2865
3043
3044 // Shared code generation methods (EmitNativeCode and 2866 // Shared code generation methods (EmitNativeCode and
3045 // MakeLocationSummary). Only assembly code that can be shared across all 2867 // MakeLocationSummary). Only assembly code that can be shared across all
3046 // architectures can be used. Machine specific register allocation and code 2868 // architectures can be used. Machine specific register allocation and code
3047 // generation is located in intermediate_language_<arch>.cc 2869 // generation is located in intermediate_language_<arch>.cc
3048 2870
3049 #define __ compiler->assembler()-> 2871 #define __ compiler->assembler()->
3050 2872
3051 LocationSummary* GraphEntryInstr::MakeLocationSummary(Zone* zone, 2873 LocationSummary* GraphEntryInstr::MakeLocationSummary(Zone* zone,
3052 bool optimizing) const { 2874 bool optimizing) const {
3053 UNREACHABLE(); 2875 UNREACHABLE();
3054 return NULL; 2876 return NULL;
3055 } 2877 }
3056 2878
3057
3058 LocationSummary* JoinEntryInstr::MakeLocationSummary(Zone* zone, 2879 LocationSummary* JoinEntryInstr::MakeLocationSummary(Zone* zone,
3059 bool optimizing) const { 2880 bool optimizing) const {
3060 UNREACHABLE(); 2881 UNREACHABLE();
3061 return NULL; 2882 return NULL;
3062 } 2883 }
3063 2884
3064
3065 void JoinEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2885 void JoinEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3066 __ Bind(compiler->GetJumpLabel(this)); 2886 __ Bind(compiler->GetJumpLabel(this));
3067 if (!compiler->is_optimizing()) { 2887 if (!compiler->is_optimizing()) {
3068 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), 2888 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(),
3069 TokenPosition::kNoSource); 2889 TokenPosition::kNoSource);
3070 } 2890 }
3071 if (HasParallelMove()) { 2891 if (HasParallelMove()) {
3072 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); 2892 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
3073 } 2893 }
3074 } 2894 }
3075 2895
3076
3077 LocationSummary* TargetEntryInstr::MakeLocationSummary(Zone* zone, 2896 LocationSummary* TargetEntryInstr::MakeLocationSummary(Zone* zone,
3078 bool optimizing) const { 2897 bool optimizing) const {
3079 UNREACHABLE(); 2898 UNREACHABLE();
3080 return NULL; 2899 return NULL;
3081 } 2900 }
3082 2901
3083
3084 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2902 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3085 __ Bind(compiler->GetJumpLabel(this)); 2903 __ Bind(compiler->GetJumpLabel(this));
3086 if (!compiler->is_optimizing()) { 2904 if (!compiler->is_optimizing()) {
3087 #if !defined(TARGET_ARCH_DBC) 2905 #if !defined(TARGET_ARCH_DBC)
3088 // TODO(vegorov) re-enable edge counters on DBC if we consider them 2906 // TODO(vegorov) re-enable edge counters on DBC if we consider them
3089 // beneficial for the quality of the optimized bytecode. 2907 // beneficial for the quality of the optimized bytecode.
3090 if (compiler->NeedsEdgeCounter(this)) { 2908 if (compiler->NeedsEdgeCounter(this)) {
3091 compiler->EmitEdgeCounter(preorder_number()); 2909 compiler->EmitEdgeCounter(preorder_number());
3092 } 2910 }
3093 #endif 2911 #endif
3094 2912
3095 // The deoptimization descriptor points after the edge counter code for 2913 // The deoptimization descriptor points after the edge counter code for
3096 // uniformity with ARM, where we can reuse pattern matching code that 2914 // uniformity with ARM, where we can reuse pattern matching code that
3097 // matches backwards from the end of the pattern. 2915 // matches backwards from the end of the pattern.
3098 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), 2916 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(),
3099 TokenPosition::kNoSource); 2917 TokenPosition::kNoSource);
3100 } 2918 }
3101 if (HasParallelMove()) { 2919 if (HasParallelMove()) {
3102 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); 2920 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
3103 } 2921 }
3104 } 2922 }
3105 2923
3106
3107 void IndirectGotoInstr::ComputeOffsetTable() { 2924 void IndirectGotoInstr::ComputeOffsetTable() {
3108 if (GetBlock()->offset() < 0) { 2925 if (GetBlock()->offset() < 0) {
3109 // Don't generate a table when contained in an unreachable block. 2926 // Don't generate a table when contained in an unreachable block.
3110 return; 2927 return;
3111 } 2928 }
3112 ASSERT(SuccessorCount() == offsets_.Length()); 2929 ASSERT(SuccessorCount() == offsets_.Length());
3113 intptr_t element_size = offsets_.ElementSizeInBytes(); 2930 intptr_t element_size = offsets_.ElementSizeInBytes();
3114 for (intptr_t i = 0; i < SuccessorCount(); i++) { 2931 for (intptr_t i = 0; i < SuccessorCount(); i++) {
3115 TargetEntryInstr* target = SuccessorAt(i); 2932 TargetEntryInstr* target = SuccessorAt(i);
3116 intptr_t offset = target->offset(); 2933 intptr_t offset = target->offset();
(...skipping 13 matching lines...) Expand all
3130 ASSERT(ientry != NULL); 2947 ASSERT(ientry != NULL);
3131 ASSERT(ientry->indirect_id() == i); 2948 ASSERT(ientry->indirect_id() == i);
3132 offset = ientry->offset(); 2949 offset = ientry->offset();
3133 } 2950 }
3134 2951
3135 ASSERT(offset > 0); 2952 ASSERT(offset > 0);
3136 offsets_.SetInt32(i * element_size, offset); 2953 offsets_.SetInt32(i * element_size, offset);
3137 } 2954 }
3138 } 2955 }
3139 2956
3140
3141 LocationSummary* IndirectEntryInstr::MakeLocationSummary( 2957 LocationSummary* IndirectEntryInstr::MakeLocationSummary(
3142 Zone* zone, 2958 Zone* zone,
3143 bool optimizing) const { 2959 bool optimizing) const {
3144 return JoinEntryInstr::MakeLocationSummary(zone, optimizing); 2960 return JoinEntryInstr::MakeLocationSummary(zone, optimizing);
3145 } 2961 }
3146 2962
3147
3148 void IndirectEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2963 void IndirectEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3149 JoinEntryInstr::EmitNativeCode(compiler); 2964 JoinEntryInstr::EmitNativeCode(compiler);
3150 } 2965 }
3151 2966
3152
3153 LocationSummary* PhiInstr::MakeLocationSummary(Zone* zone, 2967 LocationSummary* PhiInstr::MakeLocationSummary(Zone* zone,
3154 bool optimizing) const { 2968 bool optimizing) const {
3155 UNREACHABLE(); 2969 UNREACHABLE();
3156 return NULL; 2970 return NULL;
3157 } 2971 }
3158 2972
3159
3160 void PhiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2973 void PhiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3161 UNREACHABLE(); 2974 UNREACHABLE();
3162 } 2975 }
3163 2976
3164
3165 LocationSummary* RedefinitionInstr::MakeLocationSummary(Zone* zone, 2977 LocationSummary* RedefinitionInstr::MakeLocationSummary(Zone* zone,
3166 bool optimizing) const { 2978 bool optimizing) const {
3167 UNREACHABLE(); 2979 UNREACHABLE();
3168 return NULL; 2980 return NULL;
3169 } 2981 }
3170 2982
3171
3172 void RedefinitionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2983 void RedefinitionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3173 UNREACHABLE(); 2984 UNREACHABLE();
3174 } 2985 }
3175 2986
3176
3177 LocationSummary* ParameterInstr::MakeLocationSummary(Zone* zone, 2987 LocationSummary* ParameterInstr::MakeLocationSummary(Zone* zone,
3178 bool optimizing) const { 2988 bool optimizing) const {
3179 UNREACHABLE(); 2989 UNREACHABLE();
3180 return NULL; 2990 return NULL;
3181 } 2991 }
3182 2992
3183
3184 void ParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2993 void ParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3185 UNREACHABLE(); 2994 UNREACHABLE();
3186 } 2995 }
3187 2996
3188
3189 bool ParallelMoveInstr::IsRedundant() const { 2997 bool ParallelMoveInstr::IsRedundant() const {
3190 for (intptr_t i = 0; i < moves_.length(); i++) { 2998 for (intptr_t i = 0; i < moves_.length(); i++) {
3191 if (!moves_[i]->IsRedundant()) { 2999 if (!moves_[i]->IsRedundant()) {
3192 return false; 3000 return false;
3193 } 3001 }
3194 } 3002 }
3195 return true; 3003 return true;
3196 } 3004 }
3197 3005
3198
3199 LocationSummary* ParallelMoveInstr::MakeLocationSummary(Zone* zone, 3006 LocationSummary* ParallelMoveInstr::MakeLocationSummary(Zone* zone,
3200 bool optimizing) const { 3007 bool optimizing) const {
3201 return NULL; 3008 return NULL;
3202 } 3009 }
3203 3010
3204
3205 void ParallelMoveInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3011 void ParallelMoveInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3206 UNREACHABLE(); 3012 UNREACHABLE();
3207 } 3013 }
3208 3014
3209
3210 LocationSummary* ConstraintInstr::MakeLocationSummary(Zone* zone, 3015 LocationSummary* ConstraintInstr::MakeLocationSummary(Zone* zone,
3211 bool optimizing) const { 3016 bool optimizing) const {
3212 UNREACHABLE(); 3017 UNREACHABLE();
3213 return NULL; 3018 return NULL;
3214 } 3019 }
3215 3020
3216
3217 void ConstraintInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3021 void ConstraintInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3218 UNREACHABLE(); 3022 UNREACHABLE();
3219 } 3023 }
3220 3024
3221
3222 LocationSummary* MaterializeObjectInstr::MakeLocationSummary( 3025 LocationSummary* MaterializeObjectInstr::MakeLocationSummary(
3223 Zone* zone, 3026 Zone* zone,
3224 bool optimizing) const { 3027 bool optimizing) const {
3225 UNREACHABLE(); 3028 UNREACHABLE();
3226 return NULL; 3029 return NULL;
3227 } 3030 }
3228 3031
3229
3230 void MaterializeObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3032 void MaterializeObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3231 UNREACHABLE(); 3033 UNREACHABLE();
3232 } 3034 }
3233 3035
3234
3235 // This function should be kept in sync with 3036 // This function should be kept in sync with
3236 // FlowGraphCompiler::SlowPathEnvironmentFor(). 3037 // FlowGraphCompiler::SlowPathEnvironmentFor().
3237 void MaterializeObjectInstr::RemapRegisters(intptr_t* cpu_reg_slots, 3038 void MaterializeObjectInstr::RemapRegisters(intptr_t* cpu_reg_slots,
3238 intptr_t* fpu_reg_slots) { 3039 intptr_t* fpu_reg_slots) {
3239 if (registers_remapped_) { 3040 if (registers_remapped_) {
3240 return; 3041 return;
3241 } 3042 }
3242 registers_remapped_ = true; 3043 registers_remapped_ = true;
3243 3044
3244 for (intptr_t i = 0; i < InputCount(); i++) { 3045 for (intptr_t i = 0; i < InputCount(); i++) {
3245 locations_[i] = LocationAt(i).RemapForSlowPath( 3046 locations_[i] = LocationAt(i).RemapForSlowPath(
3246 InputAt(i)->definition(), cpu_reg_slots, fpu_reg_slots); 3047 InputAt(i)->definition(), cpu_reg_slots, fpu_reg_slots);
3247 } 3048 }
3248 } 3049 }
3249 3050
3250
3251 LocationSummary* SpecialParameterInstr::MakeLocationSummary(Zone* zone, 3051 LocationSummary* SpecialParameterInstr::MakeLocationSummary(Zone* zone,
3252 bool opt) const { 3052 bool opt) const {
3253 // Only appears in initial definitions, never in normal code. 3053 // Only appears in initial definitions, never in normal code.
3254 UNREACHABLE(); 3054 UNREACHABLE();
3255 return NULL; 3055 return NULL;
3256 } 3056 }
3257 3057
3258
3259 void SpecialParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3058 void SpecialParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3260 // Only appears in initial definitions, never in normal code. 3059 // Only appears in initial definitions, never in normal code.
3261 UNREACHABLE(); 3060 UNREACHABLE();
3262 } 3061 }
3263 3062
3264
3265 LocationSummary* DropTempsInstr::MakeLocationSummary(Zone* zone, 3063 LocationSummary* DropTempsInstr::MakeLocationSummary(Zone* zone,
3266 bool optimizing) const { 3064 bool optimizing) const {
3267 return (InputCount() == 1) 3065 return (InputCount() == 1)
3268 ? LocationSummary::Make(zone, 1, Location::SameAsFirstInput(), 3066 ? LocationSummary::Make(zone, 1, Location::SameAsFirstInput(),
3269 LocationSummary::kNoCall) 3067 LocationSummary::kNoCall)
3270 : LocationSummary::Make(zone, 0, Location::NoLocation(), 3068 : LocationSummary::Make(zone, 0, Location::NoLocation(),
3271 LocationSummary::kNoCall); 3069 LocationSummary::kNoCall);
3272 } 3070 }
3273 3071
3274
3275 void DropTempsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3072 void DropTempsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3276 #if defined(TARGET_ARCH_DBC) 3073 #if defined(TARGET_ARCH_DBC)
3277 // On DBC the action of poping the TOS value and then pushing it 3074 // On DBC the action of poping the TOS value and then pushing it
3278 // after all intermediates are poped is folded into a special 3075 // after all intermediates are poped is folded into a special
3279 // bytecode (DropR). On other architectures this is handled by 3076 // bytecode (DropR). On other architectures this is handled by
3280 // instruction prologue/epilogues. 3077 // instruction prologue/epilogues.
3281 ASSERT(!compiler->is_optimizing()); 3078 ASSERT(!compiler->is_optimizing());
3282 if ((InputCount() != 0) && HasTemp()) { 3079 if ((InputCount() != 0) && HasTemp()) {
3283 __ DropR(num_temps()); 3080 __ DropR(num_temps());
3284 } else { 3081 } else {
3285 __ Drop(num_temps() + ((InputCount() != 0) ? 1 : 0)); 3082 __ Drop(num_temps() + ((InputCount() != 0) ? 1 : 0));
3286 } 3083 }
3287 #else 3084 #else
3288 ASSERT(!compiler->is_optimizing()); 3085 ASSERT(!compiler->is_optimizing());
3289 // Assert that register assignment is correct. 3086 // Assert that register assignment is correct.
3290 ASSERT((InputCount() == 0) || (locs()->out(0).reg() == locs()->in(0).reg())); 3087 ASSERT((InputCount() == 0) || (locs()->out(0).reg() == locs()->in(0).reg()));
3291 __ Drop(num_temps()); 3088 __ Drop(num_temps());
3292 #endif // defined(TARGET_ARCH_DBC) 3089 #endif // defined(TARGET_ARCH_DBC)
3293 } 3090 }
3294 3091
3295
3296 StrictCompareInstr::StrictCompareInstr(TokenPosition token_pos, 3092 StrictCompareInstr::StrictCompareInstr(TokenPosition token_pos,
3297 Token::Kind kind, 3093 Token::Kind kind,
3298 Value* left, 3094 Value* left,
3299 Value* right, 3095 Value* right,
3300 bool needs_number_check, 3096 bool needs_number_check,
3301 intptr_t deopt_id) 3097 intptr_t deopt_id)
3302 : TemplateComparison(token_pos, kind, deopt_id), 3098 : TemplateComparison(token_pos, kind, deopt_id),
3303 needs_number_check_(needs_number_check) { 3099 needs_number_check_(needs_number_check) {
3304 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT)); 3100 ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT));
3305 SetInputAt(0, left); 3101 SetInputAt(0, left);
3306 SetInputAt(1, right); 3102 SetInputAt(1, right);
3307 } 3103 }
3308 3104
3309
3310 LocationSummary* InstanceCallInstr::MakeLocationSummary(Zone* zone, 3105 LocationSummary* InstanceCallInstr::MakeLocationSummary(Zone* zone,
3311 bool optimizing) const { 3106 bool optimizing) const {
3312 return MakeCallSummary(zone); 3107 return MakeCallSummary(zone);
3313 } 3108 }
3314 3109
3315
3316 // DBC does not use specialized inline cache stubs for smi operations. 3110 // DBC does not use specialized inline cache stubs for smi operations.
3317 #if !defined(TARGET_ARCH_DBC) 3111 #if !defined(TARGET_ARCH_DBC)
3318 static const StubEntry* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) { 3112 static const StubEntry* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) {
3319 if (!FLAG_two_args_smi_icd) { 3113 if (!FLAG_two_args_smi_icd) {
3320 return 0; 3114 return 0;
3321 } 3115 }
3322 switch (kind) { 3116 switch (kind) {
3323 case Token::kADD: 3117 case Token::kADD:
3324 return StubCode::SmiAddInlineCache_entry(); 3118 return StubCode::SmiAddInlineCache_entry();
3325 case Token::kSUB: 3119 case Token::kSUB:
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3366 __ BitOrTOS(); 3160 __ BitOrTOS();
3367 } 3161 }
3368 } else if (name.raw() == Symbols::Star().raw()) { 3162 } else if (name.raw() == Symbols::Star().raw()) {
3369 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) { 3163 if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
3370 __ MulTOS(); 3164 __ MulTOS();
3371 } 3165 }
3372 } 3166 }
3373 } 3167 }
3374 #endif 3168 #endif
3375 3169
3376
3377 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3170 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3378 Zone* zone = compiler->zone(); 3171 Zone* zone = compiler->zone();
3379 const ICData* call_ic_data = NULL; 3172 const ICData* call_ic_data = NULL;
3380 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() || 3173 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() ||
3381 (ic_data() == NULL)) { 3174 (ic_data() == NULL)) {
3382 const Array& arguments_descriptor = 3175 const Array& arguments_descriptor =
3383 Array::Handle(zone, GetArgumentsDescriptor()); 3176 Array::Handle(zone, GetArgumentsDescriptor());
3384 call_ic_data = compiler->GetOrAddInstanceCallICData( 3177 call_ic_data = compiler->GetOrAddInstanceCallICData(
3385 deopt_id(), function_name(), arguments_descriptor, 3178 deopt_id(), function_name(), arguments_descriptor,
3386 checked_argument_count()); 3179 checked_argument_count());
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3457 compiler->AddCurrentDescriptor(RawPcDescriptors::kIcCall, deopt_id(), 3250 compiler->AddCurrentDescriptor(RawPcDescriptors::kIcCall, deopt_id(),
3458 token_pos()); 3251 token_pos());
3459 compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult); 3252 compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
3460 3253
3461 if (compiler->is_optimizing()) { 3254 if (compiler->is_optimizing()) {
3462 __ PopLocal(locs()->out(0).reg()); 3255 __ PopLocal(locs()->out(0).reg());
3463 } 3256 }
3464 #endif // !defined(TARGET_ARCH_DBC) 3257 #endif // !defined(TARGET_ARCH_DBC)
3465 } 3258 }
3466 3259
3467
3468 bool InstanceCallInstr::MatchesCoreName(const String& name) { 3260 bool InstanceCallInstr::MatchesCoreName(const String& name) {
3469 return function_name().raw() == Library::PrivateCoreLibName(name).raw(); 3261 return function_name().raw() == Library::PrivateCoreLibName(name).raw();
3470 } 3262 }
3471 3263
3472
3473 RawFunction* InstanceCallInstr::ResolveForReceiverClass(const Class& cls) { 3264 RawFunction* InstanceCallInstr::ResolveForReceiverClass(const Class& cls) {
3474 const Array& args_desc_array = Array::Handle(GetArgumentsDescriptor()); 3265 const Array& args_desc_array = Array::Handle(GetArgumentsDescriptor());
3475 ArgumentsDescriptor args_desc(args_desc_array); 3266 ArgumentsDescriptor args_desc(args_desc_array);
3476 return Resolver::ResolveDynamicForReceiverClass(cls, function_name(), 3267 return Resolver::ResolveDynamicForReceiverClass(cls, function_name(),
3477 args_desc); 3268 args_desc);
3478 } 3269 }
3479 3270
3480
3481 bool CallTargets::HasSingleRecognizedTarget() const { 3271 bool CallTargets::HasSingleRecognizedTarget() const {
3482 if (!HasSingleTarget()) return false; 3272 if (!HasSingleTarget()) return false;
3483 return MethodRecognizer::RecognizeKind(FirstTarget()) != 3273 return MethodRecognizer::RecognizeKind(FirstTarget()) !=
3484 MethodRecognizer::kUnknown; 3274 MethodRecognizer::kUnknown;
3485 } 3275 }
3486 3276
3487
3488 bool CallTargets::HasSingleTarget() const { 3277 bool CallTargets::HasSingleTarget() const {
3489 ASSERT(length() != 0); 3278 ASSERT(length() != 0);
3490 for (int i = 0; i < length(); i++) { 3279 for (int i = 0; i < length(); i++) {
3491 if (TargetAt(i)->target->raw() != TargetAt(0)->target->raw()) return false; 3280 if (TargetAt(i)->target->raw() != TargetAt(0)->target->raw()) return false;
3492 } 3281 }
3493 return true; 3282 return true;
3494 } 3283 }
3495 3284
3496
3497 const Function& CallTargets::FirstTarget() const { 3285 const Function& CallTargets::FirstTarget() const {
3498 ASSERT(length() != 0); 3286 ASSERT(length() != 0);
3499 ASSERT(TargetAt(0)->target->IsZoneHandle()); 3287 ASSERT(TargetAt(0)->target->IsZoneHandle());
3500 return *TargetAt(0)->target; 3288 return *TargetAt(0)->target;
3501 } 3289 }
3502 3290
3503
3504 const Function& CallTargets::MostPopularTarget() const { 3291 const Function& CallTargets::MostPopularTarget() const {
3505 ASSERT(length() != 0); 3292 ASSERT(length() != 0);
3506 ASSERT(TargetAt(0)->target->IsZoneHandle()); 3293 ASSERT(TargetAt(0)->target->IsZoneHandle());
3507 for (int i = 1; i < length(); i++) { 3294 for (int i = 1; i < length(); i++) {
3508 ASSERT(TargetAt(i)->count <= TargetAt(0)->count); 3295 ASSERT(TargetAt(i)->count <= TargetAt(0)->count);
3509 } 3296 }
3510 return *TargetAt(0)->target; 3297 return *TargetAt(0)->target;
3511 } 3298 }
3512 3299
3513
3514 intptr_t CallTargets::AggregateCallCount() const { 3300 intptr_t CallTargets::AggregateCallCount() const {
3515 intptr_t sum = 0; 3301 intptr_t sum = 0;
3516 for (int i = 0; i < length(); i++) { 3302 for (int i = 0; i < length(); i++) {
3517 sum += TargetAt(i)->count; 3303 sum += TargetAt(i)->count;
3518 } 3304 }
3519 return sum; 3305 return sum;
3520 } 3306 }
3521 3307
3522
3523 bool PolymorphicInstanceCallInstr::HasOnlyDispatcherOrImplicitAccessorTargets() 3308 bool PolymorphicInstanceCallInstr::HasOnlyDispatcherOrImplicitAccessorTargets()
3524 const { 3309 const {
3525 const intptr_t len = targets_.length(); 3310 const intptr_t len = targets_.length();
3526 Function& target = Function::Handle(); 3311 Function& target = Function::Handle();
3527 for (intptr_t i = 0; i < len; i++) { 3312 for (intptr_t i = 0; i < len; i++) {
3528 target ^= targets_.TargetAt(i)->target->raw(); 3313 target ^= targets_.TargetAt(i)->target->raw();
3529 if (!target.IsDispatcherOrImplicitAccessor()) { 3314 if (!target.IsDispatcherOrImplicitAccessor()) {
3530 return false; 3315 return false;
3531 } 3316 }
3532 } 3317 }
3533 return true; 3318 return true;
3534 } 3319 }
3535 3320
3536
3537 intptr_t PolymorphicInstanceCallInstr::CallCount() const { 3321 intptr_t PolymorphicInstanceCallInstr::CallCount() const {
3538 return targets().AggregateCallCount(); 3322 return targets().AggregateCallCount();
3539 } 3323 }
3540 3324
3541
3542 // DBC does not support optimizing compiler and thus doesn't emit 3325 // DBC does not support optimizing compiler and thus doesn't emit
3543 // PolymorphicInstanceCallInstr. 3326 // PolymorphicInstanceCallInstr.
3544 #if !defined(TARGET_ARCH_DBC) 3327 #if !defined(TARGET_ARCH_DBC)
3545 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3328 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3546 ArgumentsInfo args_info(instance_call()->type_args_len(), 3329 ArgumentsInfo args_info(instance_call()->type_args_len(),
3547 instance_call()->ArgumentCount(), 3330 instance_call()->ArgumentCount(),
3548 instance_call()->argument_names()); 3331 instance_call()->argument_names());
3549 compiler->EmitPolymorphicInstanceCall( 3332 compiler->EmitPolymorphicInstanceCall(
3550 targets_, *instance_call(), args_info, deopt_id(), 3333 targets_, *instance_call(), args_info, deopt_id(),
3551 instance_call()->token_pos(), locs(), complete(), total_call_count()); 3334 instance_call()->token_pos(), locs(), complete(), total_call_count());
3552 } 3335 }
3553 #endif 3336 #endif
3554 3337
3555
3556 RawType* PolymorphicInstanceCallInstr::ComputeRuntimeType( 3338 RawType* PolymorphicInstanceCallInstr::ComputeRuntimeType(
3557 const CallTargets& targets) { 3339 const CallTargets& targets) {
3558 bool is_string = true; 3340 bool is_string = true;
3559 bool is_integer = true; 3341 bool is_integer = true;
3560 bool is_double = true; 3342 bool is_double = true;
3561 3343
3562 const intptr_t num_checks = targets.length(); 3344 const intptr_t num_checks = targets.length();
3563 for (intptr_t i = 0; i < num_checks; i++) { 3345 for (intptr_t i = 0; i < num_checks; i++) {
3564 ASSERT(targets.TargetAt(i)->target->raw() == 3346 ASSERT(targets.TargetAt(i)->target->raw() ==
3565 targets.TargetAt(0)->target->raw()); 3347 targets.TargetAt(0)->target->raw());
(...skipping 13 matching lines...) Expand all
3579 } else if (is_integer) { 3361 } else if (is_integer) {
3580 ASSERT(!is_double); 3362 ASSERT(!is_double);
3581 return Type::IntType(); 3363 return Type::IntType();
3582 } else if (is_double) { 3364 } else if (is_double) {
3583 return Type::Double(); 3365 return Type::Double();
3584 } 3366 }
3585 3367
3586 return Type::null(); 3368 return Type::null();
3587 } 3369 }
3588 3370
3589
3590 Definition* InstanceCallInstr::Canonicalize(FlowGraph* flow_graph) { 3371 Definition* InstanceCallInstr::Canonicalize(FlowGraph* flow_graph) {
3591 const intptr_t receiver_cid = PushArgumentAt(0)->value()->Type()->ToCid(); 3372 const intptr_t receiver_cid = PushArgumentAt(0)->value()->Type()->ToCid();
3592 3373
3593 // TODO(erikcorry): Even for cold call sites we could still try to look up 3374 // TODO(erikcorry): Even for cold call sites we could still try to look up
3594 // methods when we know the receiver cid. We don't currently do this because 3375 // methods when we know the receiver cid. We don't currently do this because
3595 // it turns the InstanceCall into a PolymorphicInstanceCall which doesn't get 3376 // it turns the InstanceCall into a PolymorphicInstanceCall which doesn't get
3596 // recognized or inlined when it is cold. 3377 // recognized or inlined when it is cold.
3597 if (ic_data()->NumberOfUsedChecks() == 0) return this; 3378 if (ic_data()->NumberOfUsedChecks() == 0) return this;
3598 3379
3599 const CallTargets* new_target = 3380 const CallTargets* new_target =
3600 FlowGraphCompiler::ResolveCallTargetsForReceiverCid( 3381 FlowGraphCompiler::ResolveCallTargetsForReceiverCid(
3601 receiver_cid, 3382 receiver_cid,
3602 String::Handle(flow_graph->zone(), ic_data()->target_name()), 3383 String::Handle(flow_graph->zone(), ic_data()->target_name()),
3603 Array::Handle(flow_graph->zone(), ic_data()->arguments_descriptor())); 3384 Array::Handle(flow_graph->zone(), ic_data()->arguments_descriptor()));
3604 if (new_target == NULL) { 3385 if (new_target == NULL) {
3605 // No specialization. 3386 // No specialization.
3606 return this; 3387 return this;
3607 } 3388 }
3608 3389
3609 ASSERT(new_target->HasSingleTarget()); 3390 ASSERT(new_target->HasSingleTarget());
3610 const Function& target = new_target->FirstTarget(); 3391 const Function& target = new_target->FirstTarget();
3611 StaticCallInstr* specialized = 3392 StaticCallInstr* specialized =
3612 StaticCallInstr::FromCall(flow_graph->zone(), this, target); 3393 StaticCallInstr::FromCall(flow_graph->zone(), this, target);
3613 flow_graph->InsertBefore(this, specialized, env(), FlowGraph::kValue); 3394 flow_graph->InsertBefore(this, specialized, env(), FlowGraph::kValue);
3614 return specialized; 3395 return specialized;
3615 } 3396 }
3616 3397
3617
3618 Definition* PolymorphicInstanceCallInstr::Canonicalize(FlowGraph* flow_graph) { 3398 Definition* PolymorphicInstanceCallInstr::Canonicalize(FlowGraph* flow_graph) {
3619 if (!IsSureToCallSingleRecognizedTarget()) { 3399 if (!IsSureToCallSingleRecognizedTarget()) {
3620 return this; 3400 return this;
3621 } 3401 }
3622 3402
3623 const Function& target = targets().FirstTarget(); 3403 const Function& target = targets().FirstTarget();
3624 if (target.recognized_kind() == MethodRecognizer::kObjectRuntimeType) { 3404 if (target.recognized_kind() == MethodRecognizer::kObjectRuntimeType) {
3625 const AbstractType& type = 3405 const AbstractType& type =
3626 AbstractType::Handle(ComputeRuntimeType(targets_)); 3406 AbstractType::Handle(ComputeRuntimeType(targets_));
3627 if (!type.IsNull()) { 3407 if (!type.IsNull()) {
3628 return flow_graph->GetConstant(type); 3408 return flow_graph->GetConstant(type);
3629 } 3409 }
3630 } 3410 }
3631 3411
3632 return this; 3412 return this;
3633 } 3413 }
3634 3414
3635
3636 bool PolymorphicInstanceCallInstr::IsSureToCallSingleRecognizedTarget() const { 3415 bool PolymorphicInstanceCallInstr::IsSureToCallSingleRecognizedTarget() const {
3637 if (FLAG_precompiled_mode && !complete()) return false; 3416 if (FLAG_precompiled_mode && !complete()) return false;
3638 return targets_.HasSingleRecognizedTarget(); 3417 return targets_.HasSingleRecognizedTarget();
3639 } 3418 }
3640 3419
3641
3642 Definition* StaticCallInstr::Canonicalize(FlowGraph* flow_graph) { 3420 Definition* StaticCallInstr::Canonicalize(FlowGraph* flow_graph) {
3643 if (!FLAG_precompiled_mode) { 3421 if (!FLAG_precompiled_mode) {
3644 return this; 3422 return this;
3645 } 3423 }
3646 3424
3647 if (function().recognized_kind() == MethodRecognizer::kObjectRuntimeType) { 3425 if (function().recognized_kind() == MethodRecognizer::kObjectRuntimeType) {
3648 if (input_use_list() == NULL) { 3426 if (input_use_list() == NULL) {
3649 // This function has only environment uses. In precompiled mode it is 3427 // This function has only environment uses. In precompiled mode it is
3650 // fine to remove it - because we will never deoptimize. 3428 // fine to remove it - because we will never deoptimize.
3651 return flow_graph->constant_dead(); 3429 return flow_graph->constant_dead();
3652 } 3430 }
3653 } 3431 }
3654 3432
3655 return this; 3433 return this;
3656 } 3434 }
3657 3435
3658
3659 LocationSummary* StaticCallInstr::MakeLocationSummary(Zone* zone, 3436 LocationSummary* StaticCallInstr::MakeLocationSummary(Zone* zone,
3660 bool optimizing) const { 3437 bool optimizing) const {
3661 return MakeCallSummary(zone); 3438 return MakeCallSummary(zone);
3662 } 3439 }
3663 3440
3664
3665 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3441 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3666 Zone* zone = compiler->zone(); 3442 Zone* zone = compiler->zone();
3667 const ICData* call_ic_data = NULL; 3443 const ICData* call_ic_data = NULL;
3668 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() || 3444 if (!FLAG_propagate_ic_data || !compiler->is_optimizing() ||
3669 (ic_data() == NULL)) { 3445 (ic_data() == NULL)) {
3670 const Array& arguments_descriptor = 3446 const Array& arguments_descriptor =
3671 Array::Handle(zone, GetArgumentsDescriptor()); 3447 Array::Handle(zone, GetArgumentsDescriptor());
3672 MethodRecognizer::Kind recognized_kind = 3448 MethodRecognizer::Kind recognized_kind =
3673 MethodRecognizer::RecognizeKind(function()); 3449 MethodRecognizer::RecognizeKind(function());
3674 int num_args_checked = 0; 3450 int num_args_checked = 0;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
3710 const intptr_t ic_data_kidx = __ AddConstant(*call_ic_data); 3486 const intptr_t ic_data_kidx = __ AddConstant(*call_ic_data);
3711 __ PushConstant(ic_data_kidx); 3487 __ PushConstant(ic_data_kidx);
3712 __ IndirectStaticCall(ArgumentCount(), argdesc_kidx); 3488 __ IndirectStaticCall(ArgumentCount(), argdesc_kidx);
3713 compiler->AddCurrentDescriptor(RawPcDescriptors::kUnoptStaticCall, 3489 compiler->AddCurrentDescriptor(RawPcDescriptors::kUnoptStaticCall,
3714 deopt_id(), token_pos()); 3490 deopt_id(), token_pos());
3715 compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult); 3491 compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
3716 } 3492 }
3717 #endif // !defined(TARGET_ARCH_DBC) 3493 #endif // !defined(TARGET_ARCH_DBC)
3718 } 3494 }
3719 3495
3720
3721 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3496 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3722 compiler->GenerateAssertAssignable(token_pos(), deopt_id(), dst_type(), 3497 compiler->GenerateAssertAssignable(token_pos(), deopt_id(), dst_type(),
3723 dst_name(), locs()); 3498 dst_name(), locs());
3724 3499
3725 // DBC does not use LocationSummaries in the same way as other architectures. 3500 // DBC does not use LocationSummaries in the same way as other architectures.
3726 #if !defined(TARGET_ARCH_DBC) 3501 #if !defined(TARGET_ARCH_DBC)
3727 ASSERT(locs()->in(0).reg() == locs()->out(0).reg()); 3502 ASSERT(locs()->in(0).reg() == locs()->out(0).reg());
3728 #endif // !defined(TARGET_ARCH_DBC) 3503 #endif // !defined(TARGET_ARCH_DBC)
3729 } 3504 }
3730 3505
3731
3732 LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone, 3506 LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone,
3733 bool opt) const { 3507 bool opt) const {
3734 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); 3508 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall);
3735 } 3509 }
3736 3510
3737
3738 void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3511 void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3739 #if !defined(TARGET_ARCH_DBC) 3512 #if !defined(TARGET_ARCH_DBC)
3740 __ Jump(compiler->AddDeoptStub(deopt_id(), deopt_reason_)); 3513 __ Jump(compiler->AddDeoptStub(deopt_id(), deopt_reason_));
3741 #else 3514 #else
3742 compiler->EmitDeopt(deopt_id(), deopt_reason_); 3515 compiler->EmitDeopt(deopt_id(), deopt_reason_);
3743 #endif 3516 #endif
3744 } 3517 }
3745 3518
3746
3747 #if !defined(TARGET_ARCH_DBC) 3519 #if !defined(TARGET_ARCH_DBC)
3748 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3520 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3749 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, 3521 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass,
3750 licm_hoisted_ ? ICData::kHoisted : 0); 3522 licm_hoisted_ ? ICData::kHoisted : 0);
3751 if (IsNullCheck()) { 3523 if (IsNullCheck()) {
3752 EmitNullCheck(compiler, deopt); 3524 EmitNullCheck(compiler, deopt);
3753 return; 3525 return;
3754 } 3526 }
3755 3527
3756 ASSERT(!cids_.IsMonomorphic() || !cids_.HasClassId(kSmiCid)); 3528 ASSERT(!cids_.IsMonomorphic() || !cids_.HasClassId(kSmiCid));
(...skipping 26 matching lines...) Expand all
3783 (i == num_checks - 2 && cids_[i + 1].cid_start == kSmiCid && 3555 (i == num_checks - 2 && cids_[i + 1].cid_start == kSmiCid &&
3784 cids_[i + 1].cid_end == kSmiCid); 3556 cids_[i + 1].cid_end == kSmiCid);
3785 bias = EmitCheckCid(compiler, bias, cid_start, cid_end, is_last, &is_ok, 3557 bias = EmitCheckCid(compiler, bias, cid_start, cid_end, is_last, &is_ok,
3786 deopt, use_near_jump); 3558 deopt, use_near_jump);
3787 } 3559 }
3788 } 3560 }
3789 __ Bind(&is_ok); 3561 __ Bind(&is_ok);
3790 } 3562 }
3791 #endif 3563 #endif
3792 3564
3793
3794 Environment* Environment::From(Zone* zone, 3565 Environment* Environment::From(Zone* zone,
3795 const GrowableArray<Definition*>& definitions, 3566 const GrowableArray<Definition*>& definitions,
3796 intptr_t fixed_parameter_count, 3567 intptr_t fixed_parameter_count,
3797 const ParsedFunction& parsed_function) { 3568 const ParsedFunction& parsed_function) {
3798 Environment* env = 3569 Environment* env =
3799 new (zone) Environment(definitions.length(), fixed_parameter_count, 3570 new (zone) Environment(definitions.length(), fixed_parameter_count,
3800 Thread::kNoDeoptId, parsed_function, NULL); 3571 Thread::kNoDeoptId, parsed_function, NULL);
3801 for (intptr_t i = 0; i < definitions.length(); ++i) { 3572 for (intptr_t i = 0; i < definitions.length(); ++i) {
3802 env->values_.Add(new (zone) Value(definitions[i])); 3573 env->values_.Add(new (zone) Value(definitions[i]));
3803 } 3574 }
3804 return env; 3575 return env;
3805 } 3576 }
3806 3577
3807
3808 void Environment::PushValue(Value* value) { 3578 void Environment::PushValue(Value* value) {
3809 values_.Add(value); 3579 values_.Add(value);
3810 } 3580 }
3811 3581
3812
3813 Environment* Environment::DeepCopy(Zone* zone, intptr_t length) const { 3582 Environment* Environment::DeepCopy(Zone* zone, intptr_t length) const {
3814 ASSERT(length <= values_.length()); 3583 ASSERT(length <= values_.length());
3815 Environment* copy = new (zone) 3584 Environment* copy = new (zone)
3816 Environment(length, fixed_parameter_count_, deopt_id_, parsed_function_, 3585 Environment(length, fixed_parameter_count_, deopt_id_, parsed_function_,
3817 (outer_ == NULL) ? NULL : outer_->DeepCopy(zone)); 3586 (outer_ == NULL) ? NULL : outer_->DeepCopy(zone));
3818 if (locations_ != NULL) { 3587 if (locations_ != NULL) {
3819 Location* new_locations = zone->Alloc<Location>(length); 3588 Location* new_locations = zone->Alloc<Location>(length);
3820 copy->set_locations(new_locations); 3589 copy->set_locations(new_locations);
3821 } 3590 }
3822 for (intptr_t i = 0; i < length; ++i) { 3591 for (intptr_t i = 0; i < length; ++i) {
3823 copy->values_.Add(values_[i]->Copy(zone)); 3592 copy->values_.Add(values_[i]->Copy(zone));
3824 if (locations_ != NULL) { 3593 if (locations_ != NULL) {
3825 copy->locations_[i] = locations_[i].Copy(); 3594 copy->locations_[i] = locations_[i].Copy();
3826 } 3595 }
3827 } 3596 }
3828 return copy; 3597 return copy;
3829 } 3598 }
3830 3599
3831
3832 // Copies the environment and updates the environment use lists. 3600 // Copies the environment and updates the environment use lists.
3833 void Environment::DeepCopyTo(Zone* zone, Instruction* instr) const { 3601 void Environment::DeepCopyTo(Zone* zone, Instruction* instr) const {
3834 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) { 3602 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
3835 it.CurrentValue()->RemoveFromUseList(); 3603 it.CurrentValue()->RemoveFromUseList();
3836 } 3604 }
3837 3605
3838 Environment* copy = DeepCopy(zone); 3606 Environment* copy = DeepCopy(zone);
3839 instr->SetEnvironment(copy); 3607 instr->SetEnvironment(copy);
3840 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { 3608 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
3841 Value* value = it.CurrentValue(); 3609 Value* value = it.CurrentValue();
3842 value->definition()->AddEnvUse(value); 3610 value->definition()->AddEnvUse(value);
3843 } 3611 }
3844 } 3612 }
3845 3613
3846
3847 void Environment::DeepCopyAfterTo(Zone* zone, 3614 void Environment::DeepCopyAfterTo(Zone* zone,
3848 Instruction* instr, 3615 Instruction* instr,
3849 intptr_t argc, 3616 intptr_t argc,
3850 Definition* dead, 3617 Definition* dead,
3851 Definition* result) const { 3618 Definition* result) const {
3852 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) { 3619 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
3853 it.CurrentValue()->RemoveFromUseList(); 3620 it.CurrentValue()->RemoveFromUseList();
3854 } 3621 }
3855 3622
3856 Environment* copy = DeepCopy(zone, values_.length() - argc); 3623 Environment* copy = DeepCopy(zone, values_.length() - argc);
3857 for (intptr_t i = 0; i < argc; i++) { 3624 for (intptr_t i = 0; i < argc; i++) {
3858 copy->values_.Add(new (zone) Value(dead)); 3625 copy->values_.Add(new (zone) Value(dead));
3859 } 3626 }
3860 copy->values_.Add(new (zone) Value(result)); 3627 copy->values_.Add(new (zone) Value(result));
3861 3628
3862 instr->SetEnvironment(copy); 3629 instr->SetEnvironment(copy);
3863 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { 3630 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
3864 Value* value = it.CurrentValue(); 3631 Value* value = it.CurrentValue();
3865 value->definition()->AddEnvUse(value); 3632 value->definition()->AddEnvUse(value);
3866 } 3633 }
3867 } 3634 }
3868 3635
3869
3870 // Copies the environment as outer on an inlined instruction and updates the 3636 // Copies the environment as outer on an inlined instruction and updates the
3871 // environment use lists. 3637 // environment use lists.
3872 void Environment::DeepCopyToOuter(Zone* zone, Instruction* instr) const { 3638 void Environment::DeepCopyToOuter(Zone* zone, Instruction* instr) const {
3873 // Create a deep copy removing caller arguments from the environment. 3639 // Create a deep copy removing caller arguments from the environment.
3874 ASSERT(this != NULL); 3640 ASSERT(this != NULL);
3875 ASSERT(instr->env()->outer() == NULL); 3641 ASSERT(instr->env()->outer() == NULL);
3876 intptr_t argument_count = instr->env()->fixed_parameter_count(); 3642 intptr_t argument_count = instr->env()->fixed_parameter_count();
3877 Environment* copy = DeepCopy(zone, values_.length() - argument_count); 3643 Environment* copy = DeepCopy(zone, values_.length() - argument_count);
3878 instr->env()->outer_ = copy; 3644 instr->env()->outer_ = copy;
3879 intptr_t use_index = instr->env()->Length(); // Start index after inner. 3645 intptr_t use_index = instr->env()->Length(); // Start index after inner.
3880 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { 3646 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
3881 Value* value = it.CurrentValue(); 3647 Value* value = it.CurrentValue();
3882 value->set_instruction(instr); 3648 value->set_instruction(instr);
3883 value->set_use_index(use_index++); 3649 value->set_use_index(use_index++);
3884 value->definition()->AddEnvUse(value); 3650 value->definition()->AddEnvUse(value);
3885 } 3651 }
3886 } 3652 }
3887 3653
3888
3889 ComparisonInstr* DoubleTestOpInstr::CopyWithNewOperands(Value* new_left, 3654 ComparisonInstr* DoubleTestOpInstr::CopyWithNewOperands(Value* new_left,
3890 Value* new_right) { 3655 Value* new_right) {
3891 UNREACHABLE(); 3656 UNREACHABLE();
3892 return NULL; 3657 return NULL;
3893 } 3658 }
3894 3659
3895
3896 ComparisonInstr* EqualityCompareInstr::CopyWithNewOperands(Value* new_left, 3660 ComparisonInstr* EqualityCompareInstr::CopyWithNewOperands(Value* new_left,
3897 Value* new_right) { 3661 Value* new_right) {
3898 return new EqualityCompareInstr(token_pos(), kind(), new_left, new_right, 3662 return new EqualityCompareInstr(token_pos(), kind(), new_left, new_right,
3899 operation_cid(), deopt_id()); 3663 operation_cid(), deopt_id());
3900 } 3664 }
3901 3665
3902
3903 ComparisonInstr* RelationalOpInstr::CopyWithNewOperands(Value* new_left, 3666 ComparisonInstr* RelationalOpInstr::CopyWithNewOperands(Value* new_left,
3904 Value* new_right) { 3667 Value* new_right) {
3905 return new RelationalOpInstr(token_pos(), kind(), new_left, new_right, 3668 return new RelationalOpInstr(token_pos(), kind(), new_left, new_right,
3906 operation_cid(), deopt_id()); 3669 operation_cid(), deopt_id());
3907 } 3670 }
3908 3671
3909
3910 ComparisonInstr* StrictCompareInstr::CopyWithNewOperands(Value* new_left, 3672 ComparisonInstr* StrictCompareInstr::CopyWithNewOperands(Value* new_left,
3911 Value* new_right) { 3673 Value* new_right) {
3912 return new StrictCompareInstr(token_pos(), kind(), new_left, new_right, 3674 return new StrictCompareInstr(token_pos(), kind(), new_left, new_right,
3913 needs_number_check(), Thread::kNoDeoptId); 3675 needs_number_check(), Thread::kNoDeoptId);
3914 } 3676 }
3915 3677
3916
3917 ComparisonInstr* TestSmiInstr::CopyWithNewOperands(Value* new_left, 3678 ComparisonInstr* TestSmiInstr::CopyWithNewOperands(Value* new_left,
3918 Value* new_right) { 3679 Value* new_right) {
3919 return new TestSmiInstr(token_pos(), kind(), new_left, new_right); 3680 return new TestSmiInstr(token_pos(), kind(), new_left, new_right);
3920 } 3681 }
3921 3682
3922
3923 ComparisonInstr* TestCidsInstr::CopyWithNewOperands(Value* new_left, 3683 ComparisonInstr* TestCidsInstr::CopyWithNewOperands(Value* new_left,
3924 Value* new_right) { 3684 Value* new_right) {
3925 return new TestCidsInstr(token_pos(), kind(), new_left, cid_results(), 3685 return new TestCidsInstr(token_pos(), kind(), new_left, cid_results(),
3926 deopt_id()); 3686 deopt_id());
3927 } 3687 }
3928 3688
3929
3930 bool TestCidsInstr::AttributesEqual(Instruction* other) const { 3689 bool TestCidsInstr::AttributesEqual(Instruction* other) const {
3931 TestCidsInstr* other_instr = other->AsTestCids(); 3690 TestCidsInstr* other_instr = other->AsTestCids();
3932 if (!ComparisonInstr::AttributesEqual(other)) { 3691 if (!ComparisonInstr::AttributesEqual(other)) {
3933 return false; 3692 return false;
3934 } 3693 }
3935 if (cid_results().length() != other_instr->cid_results().length()) { 3694 if (cid_results().length() != other_instr->cid_results().length()) {
3936 return false; 3695 return false;
3937 } 3696 }
3938 for (intptr_t i = 0; i < cid_results().length(); i++) { 3697 for (intptr_t i = 0; i < cid_results().length(); i++) {
3939 if (cid_results()[i] != other_instr->cid_results()[i]) { 3698 if (cid_results()[i] != other_instr->cid_results()[i]) {
3940 return false; 3699 return false;
3941 } 3700 }
3942 } 3701 }
3943 return true; 3702 return true;
3944 } 3703 }
3945 3704
3946
3947 #if !defined(TARGET_ARCH_DBC) 3705 #if !defined(TARGET_ARCH_DBC)
3948 static bool BindsToSmiConstant(Value* value) { 3706 static bool BindsToSmiConstant(Value* value) {
3949 return value->BindsToConstant() && value->BoundConstant().IsSmi(); 3707 return value->BindsToConstant() && value->BoundConstant().IsSmi();
3950 } 3708 }
3951 #endif 3709 #endif
3952 3710
3953
3954 bool IfThenElseInstr::Supports(ComparisonInstr* comparison, 3711 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
3955 Value* v1, 3712 Value* v1,
3956 Value* v2) { 3713 Value* v2) {
3957 #if !defined(TARGET_ARCH_DBC) 3714 #if !defined(TARGET_ARCH_DBC)
3958 bool is_smi_result = BindsToSmiConstant(v1) && BindsToSmiConstant(v2); 3715 bool is_smi_result = BindsToSmiConstant(v1) && BindsToSmiConstant(v2);
3959 if (comparison->IsStrictCompare()) { 3716 if (comparison->IsStrictCompare()) {
3960 // Strict comparison with number checks calls a stub and is not supported 3717 // Strict comparison with number checks calls a stub and is not supported
3961 // by if-conversion. 3718 // by if-conversion.
3962 return is_smi_result && 3719 return is_smi_result &&
3963 !comparison->AsStrictCompare()->needs_number_check(); 3720 !comparison->AsStrictCompare()->needs_number_check();
3964 } 3721 }
3965 if (comparison->operation_cid() != kSmiCid) { 3722 if (comparison->operation_cid() != kSmiCid) {
3966 // Non-smi comparisons are not supported by if-conversion. 3723 // Non-smi comparisons are not supported by if-conversion.
3967 return false; 3724 return false;
3968 } 3725 }
3969 return is_smi_result; 3726 return is_smi_result;
3970 #else 3727 #else
3971 return false; 3728 return false;
3972 #endif // !defined(TARGET_ARCH_DBC) 3729 #endif // !defined(TARGET_ARCH_DBC)
3973 } 3730 }
3974 3731
3975
3976 bool PhiInstr::IsRedundant() const { 3732 bool PhiInstr::IsRedundant() const {
3977 ASSERT(InputCount() > 1); 3733 ASSERT(InputCount() > 1);
3978 Definition* first = InputAt(0)->definition(); 3734 Definition* first = InputAt(0)->definition();
3979 for (intptr_t i = 1; i < InputCount(); ++i) { 3735 for (intptr_t i = 1; i < InputCount(); ++i) {
3980 Definition* def = InputAt(i)->definition(); 3736 Definition* def = InputAt(i)->definition();
3981 if (def != first) return false; 3737 if (def != first) return false;
3982 } 3738 }
3983 return true; 3739 return true;
3984 } 3740 }
3985 3741
3986
3987 bool CheckArrayBoundInstr::IsFixedLengthArrayType(intptr_t cid) { 3742 bool CheckArrayBoundInstr::IsFixedLengthArrayType(intptr_t cid) {
3988 return LoadFieldInstr::IsFixedLengthArrayCid(cid); 3743 return LoadFieldInstr::IsFixedLengthArrayCid(cid);
3989 } 3744 }
3990 3745
3991
3992 Instruction* CheckArrayBoundInstr::Canonicalize(FlowGraph* flow_graph) { 3746 Instruction* CheckArrayBoundInstr::Canonicalize(FlowGraph* flow_graph) {
3993 return IsRedundant(RangeBoundary::FromDefinition(length()->definition())) 3747 return IsRedundant(RangeBoundary::FromDefinition(length()->definition()))
3994 ? NULL 3748 ? NULL
3995 : this; 3749 : this;
3996 } 3750 }
3997 3751
3998
3999 intptr_t CheckArrayBoundInstr::LengthOffsetFor(intptr_t class_id) { 3752 intptr_t CheckArrayBoundInstr::LengthOffsetFor(intptr_t class_id) {
4000 if (RawObject::IsExternalTypedDataClassId(class_id)) { 3753 if (RawObject::IsExternalTypedDataClassId(class_id)) {
4001 return ExternalTypedData::length_offset(); 3754 return ExternalTypedData::length_offset();
4002 } 3755 }
4003 if (RawObject::IsTypedDataClassId(class_id)) { 3756 if (RawObject::IsTypedDataClassId(class_id)) {
4004 return TypedData::length_offset(); 3757 return TypedData::length_offset();
4005 } 3758 }
4006 switch (class_id) { 3759 switch (class_id) {
4007 case kGrowableObjectArrayCid: 3760 case kGrowableObjectArrayCid:
4008 return GrowableObjectArray::length_offset(); 3761 return GrowableObjectArray::length_offset();
4009 case kOneByteStringCid: 3762 case kOneByteStringCid:
4010 case kTwoByteStringCid: 3763 case kTwoByteStringCid:
4011 return String::length_offset(); 3764 return String::length_offset();
4012 case kArrayCid: 3765 case kArrayCid:
4013 case kImmutableArrayCid: 3766 case kImmutableArrayCid:
4014 return Array::length_offset(); 3767 return Array::length_offset();
4015 default: 3768 default:
4016 UNREACHABLE(); 3769 UNREACHABLE();
4017 return -1; 3770 return -1;
4018 } 3771 }
4019 } 3772 }
4020 3773
4021
4022 const Function& StringInterpolateInstr::CallFunction() const { 3774 const Function& StringInterpolateInstr::CallFunction() const {
4023 if (function_.IsNull()) { 3775 if (function_.IsNull()) {
4024 const int kTypeArgsLen = 0; 3776 const int kTypeArgsLen = 0;
4025 const int kNumberOfArguments = 1; 3777 const int kNumberOfArguments = 1;
4026 const Array& kNoArgumentNames = Object::null_array(); 3778 const Array& kNoArgumentNames = Object::null_array();
4027 const Class& cls = 3779 const Class& cls =
4028 Class::Handle(Library::LookupCoreClass(Symbols::StringBase())); 3780 Class::Handle(Library::LookupCoreClass(Symbols::StringBase()));
4029 ASSERT(!cls.IsNull()); 3781 ASSERT(!cls.IsNull());
4030 function_ = Resolver::ResolveStatic( 3782 function_ = Resolver::ResolveStatic(
4031 cls, Library::PrivateCoreLibName(Symbols::Interpolate()), kTypeArgsLen, 3783 cls, Library::PrivateCoreLibName(Symbols::Interpolate()), kTypeArgsLen,
4032 kNumberOfArguments, kNoArgumentNames); 3784 kNumberOfArguments, kNoArgumentNames);
4033 } 3785 }
4034 ASSERT(!function_.IsNull()); 3786 ASSERT(!function_.IsNull());
4035 return function_; 3787 return function_;
4036 } 3788 }
4037 3789
4038
4039 // Replace StringInterpolateInstr with a constant string if all inputs are 3790 // Replace StringInterpolateInstr with a constant string if all inputs are
4040 // constant of [string, number, boolean, null]. 3791 // constant of [string, number, boolean, null].
4041 // Leave the CreateArrayInstr and StoreIndexedInstr in the stream in case 3792 // Leave the CreateArrayInstr and StoreIndexedInstr in the stream in case
4042 // deoptimization occurs. 3793 // deoptimization occurs.
4043 Definition* StringInterpolateInstr::Canonicalize(FlowGraph* flow_graph) { 3794 Definition* StringInterpolateInstr::Canonicalize(FlowGraph* flow_graph) {
4044 // The following graph structure is generated by the graph builder: 3795 // The following graph structure is generated by the graph builder:
4045 // v2 <- CreateArray(v0) 3796 // v2 <- CreateArray(v0)
4046 // StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value. 3797 // StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value.
4047 // .. 3798 // ..
4048 // v8 <- StringInterpolate(v2) 3799 // v8 <- StringInterpolate(v2)
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
4102 } else { 3853 } else {
4103 return this; 3854 return this;
4104 } 3855 }
4105 } 3856 }
4106 3857
4107 const String& concatenated = 3858 const String& concatenated =
4108 String::ZoneHandle(zone, Symbols::FromConcatAll(thread, pieces)); 3859 String::ZoneHandle(zone, Symbols::FromConcatAll(thread, pieces));
4109 return flow_graph->GetConstant(concatenated); 3860 return flow_graph->GetConstant(concatenated);
4110 } 3861 }
4111 3862
4112
4113 static AlignmentType StrengthenAlignment(intptr_t cid, 3863 static AlignmentType StrengthenAlignment(intptr_t cid,
4114 AlignmentType alignment) { 3864 AlignmentType alignment) {
4115 switch (cid) { 3865 switch (cid) {
4116 case kTypedDataInt8ArrayCid: 3866 case kTypedDataInt8ArrayCid:
4117 case kTypedDataUint8ArrayCid: 3867 case kTypedDataUint8ArrayCid:
4118 case kTypedDataUint8ClampedArrayCid: 3868 case kTypedDataUint8ClampedArrayCid:
4119 case kExternalTypedDataUint8ArrayCid: 3869 case kExternalTypedDataUint8ArrayCid:
4120 case kExternalTypedDataUint8ClampedArrayCid: 3870 case kExternalTypedDataUint8ClampedArrayCid:
4121 case kOneByteStringCid: 3871 case kOneByteStringCid:
4122 case kExternalOneByteStringCid: 3872 case kExternalOneByteStringCid:
4123 // Don't need to worry about alignment for accessing bytes. 3873 // Don't need to worry about alignment for accessing bytes.
4124 return kAlignedAccess; 3874 return kAlignedAccess;
4125 case kTypedDataFloat64x2ArrayCid: 3875 case kTypedDataFloat64x2ArrayCid:
4126 case kTypedDataInt32x4ArrayCid: 3876 case kTypedDataInt32x4ArrayCid:
4127 case kTypedDataFloat32x4ArrayCid: 3877 case kTypedDataFloat32x4ArrayCid:
4128 // TODO(rmacnak): Investigate alignment requirements of floating point 3878 // TODO(rmacnak): Investigate alignment requirements of floating point
4129 // loads. 3879 // loads.
4130 return kAlignedAccess; 3880 return kAlignedAccess;
4131 } 3881 }
4132 3882
4133 return alignment; 3883 return alignment;
4134 } 3884 }
4135 3885
4136
4137 LoadIndexedInstr::LoadIndexedInstr(Value* array, 3886 LoadIndexedInstr::LoadIndexedInstr(Value* array,
4138 Value* index, 3887 Value* index,
4139 intptr_t index_scale, 3888 intptr_t index_scale,
4140 intptr_t class_id, 3889 intptr_t class_id,
4141 AlignmentType alignment, 3890 AlignmentType alignment,
4142 intptr_t deopt_id, 3891 intptr_t deopt_id,
4143 TokenPosition token_pos) 3892 TokenPosition token_pos)
4144 : TemplateDefinition(deopt_id), 3893 : TemplateDefinition(deopt_id),
4145 index_scale_(index_scale), 3894 index_scale_(index_scale),
4146 class_id_(class_id), 3895 class_id_(class_id),
4147 alignment_(StrengthenAlignment(class_id, alignment)), 3896 alignment_(StrengthenAlignment(class_id, alignment)),
4148 token_pos_(token_pos) { 3897 token_pos_(token_pos) {
4149 SetInputAt(0, array); 3898 SetInputAt(0, array);
4150 SetInputAt(1, index); 3899 SetInputAt(1, index);
4151 } 3900 }
4152 3901
4153
4154 StoreIndexedInstr::StoreIndexedInstr(Value* array, 3902 StoreIndexedInstr::StoreIndexedInstr(Value* array,
4155 Value* index, 3903 Value* index,
4156 Value* value, 3904 Value* value,
4157 StoreBarrierType emit_store_barrier, 3905 StoreBarrierType emit_store_barrier,
4158 intptr_t index_scale, 3906 intptr_t index_scale,
4159 intptr_t class_id, 3907 intptr_t class_id,
4160 AlignmentType alignment, 3908 AlignmentType alignment,
4161 intptr_t deopt_id, 3909 intptr_t deopt_id,
4162 TokenPosition token_pos) 3910 TokenPosition token_pos)
4163 : TemplateDefinition(deopt_id), 3911 : TemplateDefinition(deopt_id),
4164 emit_store_barrier_(emit_store_barrier), 3912 emit_store_barrier_(emit_store_barrier),
4165 index_scale_(index_scale), 3913 index_scale_(index_scale),
4166 class_id_(class_id), 3914 class_id_(class_id),
4167 alignment_(StrengthenAlignment(class_id, alignment)), 3915 alignment_(StrengthenAlignment(class_id, alignment)),
4168 token_pos_(token_pos) { 3916 token_pos_(token_pos) {
4169 SetInputAt(kArrayPos, array); 3917 SetInputAt(kArrayPos, array);
4170 SetInputAt(kIndexPos, index); 3918 SetInputAt(kIndexPos, index);
4171 SetInputAt(kValuePos, value); 3919 SetInputAt(kValuePos, value);
4172 } 3920 }
4173 3921
4174
4175 InvokeMathCFunctionInstr::InvokeMathCFunctionInstr( 3922 InvokeMathCFunctionInstr::InvokeMathCFunctionInstr(
4176 ZoneGrowableArray<Value*>* inputs, 3923 ZoneGrowableArray<Value*>* inputs,
4177 intptr_t deopt_id, 3924 intptr_t deopt_id,
4178 MethodRecognizer::Kind recognized_kind, 3925 MethodRecognizer::Kind recognized_kind,
4179 TokenPosition token_pos) 3926 TokenPosition token_pos)
4180 : PureDefinition(deopt_id), 3927 : PureDefinition(deopt_id),
4181 inputs_(inputs), 3928 inputs_(inputs),
4182 recognized_kind_(recognized_kind), 3929 recognized_kind_(recognized_kind),
4183 token_pos_(token_pos) { 3930 token_pos_(token_pos) {
4184 ASSERT(inputs_->length() == ArgumentCountFor(recognized_kind_)); 3931 ASSERT(inputs_->length() == ArgumentCountFor(recognized_kind_));
4185 for (intptr_t i = 0; i < inputs_->length(); ++i) { 3932 for (intptr_t i = 0; i < inputs_->length(); ++i) {
4186 ASSERT((*inputs)[i] != NULL); 3933 ASSERT((*inputs)[i] != NULL);
4187 (*inputs)[i]->set_instruction(this); 3934 (*inputs)[i]->set_instruction(this);
4188 (*inputs)[i]->set_use_index(i); 3935 (*inputs)[i]->set_use_index(i);
4189 } 3936 }
4190 } 3937 }
4191 3938
4192
4193 intptr_t InvokeMathCFunctionInstr::ArgumentCountFor( 3939 intptr_t InvokeMathCFunctionInstr::ArgumentCountFor(
4194 MethodRecognizer::Kind kind) { 3940 MethodRecognizer::Kind kind) {
4195 switch (kind) { 3941 switch (kind) {
4196 case MethodRecognizer::kDoubleTruncate: 3942 case MethodRecognizer::kDoubleTruncate:
4197 case MethodRecognizer::kDoubleFloor: 3943 case MethodRecognizer::kDoubleFloor:
4198 case MethodRecognizer::kDoubleCeil: { 3944 case MethodRecognizer::kDoubleCeil: {
4199 ASSERT(!TargetCPUFeatures::double_truncate_round_supported()); 3945 ASSERT(!TargetCPUFeatures::double_truncate_round_supported());
4200 return 1; 3946 return 1;
4201 } 3947 }
4202 case MethodRecognizer::kDoubleRound: 3948 case MethodRecognizer::kDoubleRound:
4203 case MethodRecognizer::kMathAtan: 3949 case MethodRecognizer::kMathAtan:
4204 case MethodRecognizer::kMathTan: 3950 case MethodRecognizer::kMathTan:
4205 case MethodRecognizer::kMathAcos: 3951 case MethodRecognizer::kMathAcos:
4206 case MethodRecognizer::kMathAsin: 3952 case MethodRecognizer::kMathAsin:
4207 case MethodRecognizer::kMathSin: 3953 case MethodRecognizer::kMathSin:
4208 case MethodRecognizer::kMathCos: 3954 case MethodRecognizer::kMathCos:
4209 return 1; 3955 return 1;
4210 case MethodRecognizer::kDoubleMod: 3956 case MethodRecognizer::kDoubleMod:
4211 case MethodRecognizer::kMathDoublePow: 3957 case MethodRecognizer::kMathDoublePow:
4212 case MethodRecognizer::kMathAtan2: 3958 case MethodRecognizer::kMathAtan2:
4213 return 2; 3959 return 2;
4214 default: 3960 default:
4215 UNREACHABLE(); 3961 UNREACHABLE();
4216 } 3962 }
4217 return 0; 3963 return 0;
4218 } 3964 }
4219 3965
4220
4221 const RuntimeEntry& InvokeMathCFunctionInstr::TargetFunction() const { 3966 const RuntimeEntry& InvokeMathCFunctionInstr::TargetFunction() const {
4222 switch (recognized_kind_) { 3967 switch (recognized_kind_) {
4223 case MethodRecognizer::kDoubleTruncate: 3968 case MethodRecognizer::kDoubleTruncate:
4224 return kLibcTruncRuntimeEntry; 3969 return kLibcTruncRuntimeEntry;
4225 case MethodRecognizer::kDoubleRound: 3970 case MethodRecognizer::kDoubleRound:
4226 return kLibcRoundRuntimeEntry; 3971 return kLibcRoundRuntimeEntry;
4227 case MethodRecognizer::kDoubleFloor: 3972 case MethodRecognizer::kDoubleFloor:
4228 return kLibcFloorRuntimeEntry; 3973 return kLibcFloorRuntimeEntry;
4229 case MethodRecognizer::kDoubleCeil: 3974 case MethodRecognizer::kDoubleCeil:
4230 return kLibcCeilRuntimeEntry; 3975 return kLibcCeilRuntimeEntry;
(...skipping 14 matching lines...) Expand all
4245 case MethodRecognizer::kMathAtan: 3990 case MethodRecognizer::kMathAtan:
4246 return kLibcAtanRuntimeEntry; 3991 return kLibcAtanRuntimeEntry;
4247 case MethodRecognizer::kMathAtan2: 3992 case MethodRecognizer::kMathAtan2:
4248 return kLibcAtan2RuntimeEntry; 3993 return kLibcAtan2RuntimeEntry;
4249 default: 3994 default:
4250 UNREACHABLE(); 3995 UNREACHABLE();
4251 } 3996 }
4252 return kLibcPowRuntimeEntry; 3997 return kLibcPowRuntimeEntry;
4253 } 3998 }
4254 3999
4255
4256 const char* MathUnaryInstr::KindToCString(MathUnaryKind kind) { 4000 const char* MathUnaryInstr::KindToCString(MathUnaryKind kind) {
4257 switch (kind) { 4001 switch (kind) {
4258 case kIllegal: 4002 case kIllegal:
4259 return "illegal"; 4003 return "illegal";
4260 case kSqrt: 4004 case kSqrt:
4261 return "sqrt"; 4005 return "sqrt";
4262 case kDoubleSquare: 4006 case kDoubleSquare:
4263 return "double-square"; 4007 return "double-square";
4264 } 4008 }
4265 UNREACHABLE(); 4009 UNREACHABLE();
4266 return ""; 4010 return "";
4267 } 4011 }
4268 4012
4269
4270 const RuntimeEntry& CaseInsensitiveCompareUC16Instr::TargetFunction() const { 4013 const RuntimeEntry& CaseInsensitiveCompareUC16Instr::TargetFunction() const {
4271 return kCaseInsensitiveCompareUC16RuntimeEntry; 4014 return kCaseInsensitiveCompareUC16RuntimeEntry;
4272 } 4015 }
4273 4016
4274
4275 TruncDivModInstr::TruncDivModInstr(Value* lhs, Value* rhs, intptr_t deopt_id) 4017 TruncDivModInstr::TruncDivModInstr(Value* lhs, Value* rhs, intptr_t deopt_id)
4276 : TemplateDefinition(deopt_id) { 4018 : TemplateDefinition(deopt_id) {
4277 SetInputAt(0, lhs); 4019 SetInputAt(0, lhs);
4278 SetInputAt(1, rhs); 4020 SetInputAt(1, rhs);
4279 } 4021 }
4280 4022
4281
4282 intptr_t TruncDivModInstr::OutputIndexOf(Token::Kind token) { 4023 intptr_t TruncDivModInstr::OutputIndexOf(Token::Kind token) {
4283 switch (token) { 4024 switch (token) {
4284 case Token::kTRUNCDIV: 4025 case Token::kTRUNCDIV:
4285 return 0; 4026 return 0;
4286 case Token::kMOD: 4027 case Token::kMOD:
4287 return 1; 4028 return 1;
4288 default: 4029 default:
4289 UNIMPLEMENTED(); 4030 UNIMPLEMENTED();
4290 return -1; 4031 return -1;
4291 } 4032 }
4292 } 4033 }
4293 4034
4294
4295 void NativeCallInstr::SetupNative() { 4035 void NativeCallInstr::SetupNative() {
4296 if (link_lazily()) { 4036 if (link_lazily()) {
4297 // Resolution will happen during NativeEntry::LinkNativeCall. 4037 // Resolution will happen during NativeEntry::LinkNativeCall.
4298 return; 4038 return;
4299 } 4039 }
4300 4040
4301 Zone* zone = Thread::Current()->zone(); 4041 Zone* zone = Thread::Current()->zone();
4302 const Class& cls = Class::Handle(zone, function().Owner()); 4042 const Class& cls = Class::Handle(zone, function().Owner());
4303 const Library& library = Library::Handle(zone, cls.library()); 4043 const Library& library = Library::Handle(zone, cls.library());
4304 4044
(...skipping 12 matching lines...) Expand all
4317 "native function '%s' (%" Pd " arguments) cannot be found", 4057 "native function '%s' (%" Pd " arguments) cannot be found",
4318 native_name().ToCString(), function().NumParameters()); 4058 native_name().ToCString(), function().NumParameters());
4319 } 4059 }
4320 set_is_auto_scope(auto_setup_scope); 4060 set_is_auto_scope(auto_setup_scope);
4321 set_native_c_function(native_function); 4061 set_native_c_function(native_function);
4322 } 4062 }
4323 4063
4324 #undef __ 4064 #undef __
4325 4065
4326 } // namespace dart 4066 } // 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