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

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

Issue 10594002: More ICData cleanups: try to use ICData instead of converting it to another intermediate representa… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/il_printer.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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/flow_graph_builder.h" 7 #include "vm/flow_graph_builder.h"
8 #include "vm/il_printer.h" 8 #include "vm/il_printer.h"
9 #include "vm/object_store.h" 9 #include "vm/object_store.h"
10 10
(...skipping 17 matching lines...) Expand all
28 for (intptr_t i = 0; i < block_order_.length(); ++i) { 28 for (intptr_t i = 0; i < block_order_.length(); ++i) {
29 Instruction* instr = block_order_[i]->Accept(this); 29 Instruction* instr = block_order_[i]->Accept(this);
30 // Optimize all successors until an exit, branch, or a block entry. 30 // Optimize all successors until an exit, branch, or a block entry.
31 while ((instr != NULL) && !instr->IsBlockEntry()) { 31 while ((instr != NULL) && !instr->IsBlockEntry()) {
32 instr = instr->Accept(this); 32 instr = instr->Accept(this);
33 } 33 }
34 } 34 }
35 } 35 }
36 36
37 37
38 static bool ICDataHasReceiverClass(const ICData& ic_data, intptr_t class_id) { 38 static bool ICDataHasReceiverClassId(const ICData& ic_data, intptr_t class_id) {
39 ASSERT(ic_data.num_args_tested() > 0); 39 ASSERT(ic_data.num_args_tested() > 0);
40 Function& target = Function::Handle();
41 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 40 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
42 intptr_t test_class_id; 41 const intptr_t test_class_id = ic_data.GetReceiverClassIdAt(i);
43 ic_data.GetOneClassCheckAt(i, &test_class_id, &target);
44 if (test_class_id == class_id) { 42 if (test_class_id == class_id) {
45 return true; 43 return true;
46 } 44 }
47 } 45 }
48 return false; 46 return false;
49 } 47 }
50 48
51 49
52 static bool ICDataHasReceiverArgumentClasses(const ICData& ic_data, 50 static bool ICDataHasReceiverArgumentClasses(const ICData& ic_data,
53 intptr_t receiver_class_id, 51 intptr_t receiver_class_id,
54 intptr_t argument_class_id) { 52 intptr_t argument_class_id) {
55 if (ic_data.num_args_tested() != 2) { 53 ASSERT(receiver_class_id != kIllegalObjectKind);
56 return false; 54 ASSERT(argument_class_id != kIllegalObjectKind);
57 } 55 if (ic_data.num_args_tested() != 2) return false;
56
58 Function& target = Function::Handle(); 57 Function& target = Function::Handle();
59 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 58 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
60 GrowableArray<intptr_t> class_ids; 59 GrowableArray<intptr_t> class_ids;
61 ic_data.GetCheckAt(i, &class_ids, &target); 60 ic_data.GetCheckAt(i, &class_ids, &target);
62 ASSERT(class_ids.length() == 2); 61 ASSERT(class_ids.length() == 2);
63 if (class_ids[0] == receiver_class_id) { 62 if ((class_ids[0] == receiver_class_id) &&
64 if (class_ids[1] == argument_class_id) { 63 (class_ids[1] == argument_class_id)) {
65 return true; 64 return true;
66 }
67 } 65 }
68 } 66 }
69 return false; 67 return false;
70 } 68 }
71 69
72 70
73 static bool HasOneSmi(const ICData& ic_data) { 71 static bool HasOneSmi(const ICData& ic_data) {
74 return ICDataHasReceiverClass(ic_data, kSmi); 72 return ICDataHasReceiverClassId(ic_data, kSmi);
75 } 73 }
76 74
77 75
78 static bool HasTwoSmi(const ICData& ic_data) { 76 static bool HasTwoSmi(const ICData& ic_data) {
79 return ICDataHasReceiverArgumentClasses(ic_data, kSmi, kSmi); 77 return ICDataHasReceiverArgumentClasses(ic_data, kSmi, kSmi);
80 } 78 }
81 79
82 80
83 static bool HasMintSmi(const ICData& ic_data) { 81 static bool HasMintSmi(const ICData& ic_data) {
84 return ICDataHasReceiverArgumentClasses(ic_data, kMint, kSmi); 82 return ICDataHasReceiverArgumentClasses(ic_data, kMint, kSmi);
85 } 83 }
86 84
87 85
88 static bool HasOneDouble(const ICData& ic_data) { 86 static bool HasOneDouble(const ICData& ic_data) {
89 return ICDataHasReceiverClass(ic_data, kDouble); 87 return ICDataHasReceiverClassId(ic_data, kDouble);
90 } 88 }
91 89
92 90
93 static bool HasTwoDouble(const ICData& ic_data) { 91 static bool HasTwoDouble(const ICData& ic_data) {
94 return ICDataHasReceiverArgumentClasses(ic_data, kDouble, kDouble); 92 return ICDataHasReceiverArgumentClasses(ic_data, kDouble, kDouble);
95 } 93 }
96 94
97 95
98 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallComp* comp, 96 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallComp* comp,
99 Token::Kind op_kind) { 97 Token::Kind op_kind) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 return true; 172 return true;
175 } 173 }
176 return false; 174 return false;
177 } 175 }
178 176
179 177
180 // Returns true if all targets are the same. 178 // Returns true if all targets are the same.
181 // TODO(srdjan): if targets are native use their C_function to compare. 179 // TODO(srdjan): if targets are native use their C_function to compare.
182 static bool HasOneTarget(const ICData& ic_data) { 180 static bool HasOneTarget(const ICData& ic_data) {
183 ASSERT(ic_data.NumberOfChecks() > 0); 181 ASSERT(ic_data.NumberOfChecks() > 0);
184 Function& prev_target = Function::Handle(); 182 const Function& first_target = Function::Handle(ic_data.GetTargetAt(0));
185 GrowableArray<intptr_t> class_ids; 183 Function& test_target = Function::Handle();
186 ic_data.GetCheckAt(0, &class_ids, &prev_target);
187 ASSERT(!prev_target.IsNull());
188 Function& target = Function::Handle();
189 for (intptr_t i = 1; i < ic_data.NumberOfChecks(); i++) { 184 for (intptr_t i = 1; i < ic_data.NumberOfChecks(); i++) {
190 ic_data.GetCheckAt(i, &class_ids, &target); 185 test_target = ic_data.GetTargetAt(i);
191 ASSERT(!target.IsNull()); 186 if (first_target.raw() != test_target.raw()) {
192 if (prev_target.raw() != target.raw()) {
193 return false; 187 return false;
194 } 188 }
195 prev_target = target.raw();
196 } 189 }
197 return true; 190 return true;
198 } 191 }
199 192
200 193
201 // Using field class 194 // Using field class
202 static RawField* GetField(intptr_t class_id, const String& field_name) { 195 static RawField* GetField(intptr_t class_id, const String& field_name) {
203 Class& cls = Class::Handle(Isolate::Current()->class_table()->At(class_id)); 196 Class& cls = Class::Handle(Isolate::Current()->class_table()->At(class_id));
204 Field& field = Field::Handle(); 197 Field& field = Field::Handle();
205 while (!cls.IsNull()) { 198 while (!cls.IsNull()) {
206 field = cls.LookupInstanceField(field_name); 199 field = cls.LookupInstanceField(field_name);
207 if (!field.IsNull()) { 200 if (!field.IsNull()) {
208 return field.raw(); 201 return field.raw();
209 } 202 }
210 cls = cls.SuperClass(); 203 cls = cls.SuperClass();
211 } 204 }
212 return Field::null(); 205 return Field::null();
213 } 206 }
214 207
215 208
216 // Returns all receiver class-ids and corresponding tagets for the given 209 // Returns ICData with num_args_checked == 1. If necessary creates a new ICData
217 // 'ic_data', sorted so that a smi class id is at index[0] if it exists. 210 // object that contains unique receiver class-ids
218 // 'targets' can be NULL in which case it is not collected, 211 static RawICData* ToUnaryClassChecks(const ICData& ic_data) {
219 static void ExtractClassIdsAndTargets(const ICData& ic_data, 212 ASSERT(!ic_data.IsNull());
220 ZoneGrowableArray<intptr_t>* class_ids, 213 ASSERT(ic_data.num_args_tested() != 0);
221 ZoneGrowableArray<Function*>* targets) { 214 if (ic_data.num_args_tested() == 1) return ic_data.raw();
222 ASSERT(class_ids != NULL); 215 const intptr_t kNumArgsTested = 1;
223 class_ids->Clear(); 216 ICData& result = ICData::Handle(ICData::New(
224 if (targets != NULL) { 217 Function::Handle(ic_data.function()),
225 targets->Clear(); 218 String::Handle(ic_data.target_name()),
226 } 219 ic_data.id(),
227 intptr_t smi_index = -1; 220 kNumArgsTested));
228 Function& target = Function::Handle();
229 GrowableArray<intptr_t> unsorted_class_ids;
230 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 221 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
231 ic_data.GetCheckAt(i, &unsorted_class_ids, &target); 222 const intptr_t class_id = ic_data.GetReceiverClassIdAt(i);
232 // Collect receiver class only. 223 intptr_t duplicate_class_id = -1;
233 const intptr_t class_id = unsorted_class_ids[0]; 224 for (intptr_t k = 0; k < result.NumberOfChecks(); k++) {
234 if (ic_data.num_args_tested() > 1) { 225 if (class_id == result.GetReceiverClassIdAt(k)) {
235 // Check if we have not already entered the class-id. 226 duplicate_class_id = k;
236 intptr_t duplicate_class_id = -1; 227 break;
237 for (intptr_t k = 0; k < class_ids->length(); k++) {
238 if ((*class_ids)[k] == class_id) {
239 duplicate_class_id = k;
240 break;
241 }
242 }
243 if (duplicate_class_id >= 0) {
244 ASSERT((targets == NULL) ||
245 ((*targets)[duplicate_class_id]->raw() == target.raw()));
246 continue;
247 } 228 }
248 } 229 }
249 if (class_id == kSmi) { 230 if (duplicate_class_id >= 0) {
250 ASSERT(smi_index < 0); // Classes entered only once in ic_data. 231 ASSERT(result.GetTargetAt(duplicate_class_id) == ic_data.GetTargetAt(i));
251 smi_index = class_ids->length(); 232 } else {
252 } 233 // This will make sure that Smi is first if it exists.
253 class_ids->Add(class_id); 234 result.AddReceiverCheck(class_id,
254 if (targets != NULL) { 235 Function::Handle(ic_data.GetTargetAt(i)));
255 targets->Add(&Function::ZoneHandle(target.raw()));
256 } 236 }
257 } 237 }
258 if (smi_index >= 0) { 238 return result.raw();
259 // Smi class id must be at index 0.
260 intptr_t temp_id = (*class_ids)[0];
261 (*class_ids)[0] = (*class_ids)[smi_index];
262 (*class_ids)[smi_index] = temp_id;
263 if (targets != NULL) {
264 Function* temp_func = (*targets)[0];
265 (*targets)[0] = (*targets)[smi_index];
266 (*targets)[smi_index] = temp_func;
267 }
268 }
269 }
270
271
272 // Returns array of all class ids that are in ic_data. The result is
273 // normalized so that a smi class is at index 0 if it exists in the ic_data.
274 static ZoneGrowableArray<intptr_t>* ExtractClassIds(const ICData& ic_data) {
275 if (ic_data.NumberOfChecks() == 0) return NULL;
276 ZoneGrowableArray<intptr_t>* result =
277 new ZoneGrowableArray<intptr_t>(ic_data.NumberOfChecks());
278 ExtractClassIdsAndTargets(ic_data, result, NULL);
279 return result;
280 } 239 }
281 240
282 241
283 // Only unique implicit instance getters can be currently handled. 242 // Only unique implicit instance getters can be currently handled.
284 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallComp* comp) { 243 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallComp* comp) {
285 ASSERT(comp->HasICData()); 244 ASSERT(comp->HasICData());
286 const ICData& ic_data = *comp->ic_data(); 245 const ICData& ic_data = *comp->ic_data();
287 if (ic_data.NumberOfChecks() == 0) { 246 if (ic_data.NumberOfChecks() == 0) {
288 // No type feedback collected. 247 // No type feedback collected.
289 return false; 248 return false;
290 } 249 }
291 Function& target = Function::Handle(); 250 Function& target = Function::Handle();
292 GrowableArray<intptr_t> class_ids; 251 GrowableArray<intptr_t> class_ids;
293 ic_data.GetCheckAt(0, &class_ids, &target); 252 ic_data.GetCheckAt(0, &class_ids, &target);
294 ASSERT(class_ids.length() == 1); 253 ASSERT(class_ids.length() == 1);
295 254
296 if (target.kind() == RawFunction::kImplicitGetter) { 255 if (target.kind() == RawFunction::kImplicitGetter) {
297 if (!HasOneTarget(ic_data)) { 256 if (!HasOneTarget(ic_data)) {
298 // TODO(srdjan): Implement for mutiple targets. 257 // TODO(srdjan): Implement for mutiple targets.
299 return false; 258 return false;
300 } 259 }
301 // Inline implicit instance getter. 260 // Inline implicit instance getter.
302 const String& field_name = 261 const String& field_name =
303 String::Handle(Field::NameFromGetter(comp->function_name())); 262 String::Handle(Field::NameFromGetter(comp->function_name()));
304 const Field& field = Field::Handle(GetField(class_ids[0], field_name)); 263 const Field& field = Field::Handle(GetField(class_ids[0], field_name));
305 ASSERT(!field.IsNull()); 264 ASSERT(!field.IsNull());
306 LoadInstanceFieldComp* load = new LoadInstanceFieldComp( 265 LoadInstanceFieldComp* load = new LoadInstanceFieldComp(
307 field, comp->InputAt(0), comp, ExtractClassIds(ic_data)); 266 field, comp->InputAt(0), comp);
267 load->set_ic_data(comp->ic_data());
308 comp->ReplaceWith(load); 268 comp->ReplaceWith(load);
309 return true; 269 return true;
310 } 270 }
311 271
312 // Not an implicit getter. 272 // Not an implicit getter.
313 MethodRecognizer::Kind recognized_kind = 273 MethodRecognizer::Kind recognized_kind =
314 MethodRecognizer::RecognizeKind(target); 274 MethodRecognizer::RecognizeKind(target);
315 275
316 // VM objects length getter. 276 // VM objects length getter.
317 if ((recognized_kind == MethodRecognizer::kObjectArrayLength) || 277 if ((recognized_kind == MethodRecognizer::kObjectArrayLength) ||
(...skipping 11 matching lines...) Expand all
329 break; 289 break;
330 case MethodRecognizer::kGrowableArrayLength: 290 case MethodRecognizer::kGrowableArrayLength:
331 length_offset = GrowableObjectArray::length_offset(); 291 length_offset = GrowableObjectArray::length_offset();
332 break; 292 break;
333 default: 293 default:
334 UNREACHABLE(); 294 UNREACHABLE();
335 } 295 }
336 LoadVMFieldComp* load = new LoadVMFieldComp( 296 LoadVMFieldComp* load = new LoadVMFieldComp(
337 comp->InputAt(0), 297 comp->InputAt(0),
338 length_offset, 298 length_offset,
339 Type::ZoneHandle(Type::IntInterface()), 299 Type::ZoneHandle(Type::IntInterface()));
340 comp, 300 load->set_original(comp);
341 ExtractClassIds(ic_data)); 301 load->set_ic_data(comp->ic_data());
342 comp->ReplaceWith(load); 302 comp->ReplaceWith(load);
343 return true; 303 return true;
344 } 304 }
345 305
346 if (recognized_kind == MethodRecognizer::kStringBaseLength) { 306 if (recognized_kind == MethodRecognizer::kStringBaseLength) {
347 ASSERT(HasOneTarget(ic_data)); 307 ASSERT(HasOneTarget(ic_data));
348 LoadVMFieldComp* load = new LoadVMFieldComp( 308 LoadVMFieldComp* load = new LoadVMFieldComp(
349 comp->InputAt(0), 309 comp->InputAt(0),
350 String::length_offset(), 310 String::length_offset(),
351 Type::ZoneHandle(Type::IntInterface()), 311 Type::ZoneHandle(Type::IntInterface()));
352 comp, 312 load->set_original(comp);
353 ExtractClassIds(ic_data)); 313 load->set_ic_data(comp->ic_data());
354 comp->ReplaceWith(load); 314 comp->ReplaceWith(load);
355 return true; 315 return true;
356 } 316 }
357 return false; 317 return false;
358 } 318 }
359 319
360 320
361 // Inline only simple, frequently called core library methods. 321 // Inline only simple, frequently called core library methods.
362 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallComp* comp) { 322 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallComp* comp) {
363 ASSERT(comp->HasICData()); 323 ASSERT(comp->HasICData());
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 return; 365 return;
406 } 366 }
407 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(comp)) { 367 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(comp)) {
408 return; 368 return;
409 } 369 }
410 if (TryInlineInstanceMethod(comp)) { 370 if (TryInlineInstanceMethod(comp)) {
411 return; 371 return;
412 } 372 }
413 const intptr_t kMaxChecks = 4; 373 const intptr_t kMaxChecks = 4;
414 if (comp->ic_data()->num_args_tested() <= kMaxChecks) { 374 if (comp->ic_data()->num_args_tested() <= kMaxChecks) {
415 ZoneGrowableArray<intptr_t>* class_ids = 375 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp);
416 new ZoneGrowableArray<intptr_t>(); 376 ICData& unary_checks =
417 ZoneGrowableArray<Function*>* targets = 377 ICData::Handle(ToUnaryClassChecks(*comp->ic_data()));
418 new ZoneGrowableArray<Function*>(); 378 call->set_ic_data(&unary_checks);
419 ExtractClassIdsAndTargets(*comp->ic_data(), class_ids, targets);
420 PolymorphicInstanceCallComp* call =
421 new PolymorphicInstanceCallComp(comp, *class_ids, *targets);
422 comp->ReplaceWith(call); 379 comp->ReplaceWith(call);
423 } 380 }
424 } 381 }
425 } 382 }
426 383
427 384
428 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp) { 385 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp) {
429 MethodRecognizer::Kind recognized_kind = 386 MethodRecognizer::Kind recognized_kind =
430 MethodRecognizer::RecognizeKind(comp->function()); 387 MethodRecognizer::RecognizeKind(comp->function());
431 if (recognized_kind == MethodRecognizer::kMathSqrt) { 388 if (recognized_kind == MethodRecognizer::kMathSqrt) {
(...skipping 21 matching lines...) Expand all
453 // TODO(srdjan): Inline special setters. 410 // TODO(srdjan): Inline special setters.
454 return false; 411 return false;
455 } 412 }
456 // Inline implicit instance setter. 413 // Inline implicit instance setter.
457 const Field& field = Field::Handle(GetField(class_id, comp->field_name())); 414 const Field& field = Field::Handle(GetField(class_id, comp->field_name()));
458 ASSERT(!field.IsNull()); 415 ASSERT(!field.IsNull());
459 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( 416 StoreInstanceFieldComp* store = new StoreInstanceFieldComp(
460 field, 417 field,
461 comp->InputAt(0), 418 comp->InputAt(0),
462 comp->InputAt(1), 419 comp->InputAt(1),
463 comp, 420 comp);
464 ExtractClassIds(ic_data)); 421 store->set_ic_data(comp->ic_data());
465 comp->ReplaceWith(store); 422 comp->ReplaceWith(store);
466 return true; 423 return true;
467 } 424 }
468 425
469 426
470 427
471 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) { 428 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) {
472 // TODO(srdjan): Add assigneable check node if --enable_type_checks. 429 // TODO(srdjan): Add assigneable check node if --enable_type_checks.
473 if (comp->HasICData() && !FLAG_enable_type_checks) { 430 if (comp->HasICData() && !FLAG_enable_type_checks) {
474 TryInlineInstanceSetter(comp); 431 TryInlineInstanceSetter(comp);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 521
565 void FlowGraphOptimizer::VisitStrictCompareComp(StrictCompareComp* comp) { 522 void FlowGraphOptimizer::VisitStrictCompareComp(StrictCompareComp* comp) {
566 // TODO(vegorov): recognize the pattern with BooleanNegate between comparsion 523 // TODO(vegorov): recognize the pattern with BooleanNegate between comparsion
567 // and a branch. 524 // and a branch.
568 TryFuseComparisonWithBranch(comp); 525 TryFuseComparisonWithBranch(comp);
569 } 526 }
570 527
571 528
572 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp) { 529 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp) {
573 const intptr_t kMaxChecks = 4; 530 const intptr_t kMaxChecks = 4;
574 if (comp->ic_data()->num_args_tested() <= kMaxChecks) { 531 if (comp->HasICData() && (comp->ic_data()->num_args_tested() <= kMaxChecks)) {
575 ZoneGrowableArray<intptr_t>* class_ids = 532 // Replace binary checks with unary ones.
576 new ZoneGrowableArray<intptr_t>(); 533 ICData& unary_checks =
577 ZoneGrowableArray<Function*>* targets = 534 ICData::Handle(ToUnaryClassChecks(*comp->ic_data()));
578 new ZoneGrowableArray<Function*>(); 535 comp->set_ic_data(&unary_checks);
579 ExtractClassIdsAndTargets(*comp->ic_data(), class_ids, targets);
580 comp->SetPolymorphicTargets(class_ids, targets);
581 } 536 }
582 537
583 // TODO(vegorov): recognize the pattern with BooleanNegate between comparsion 538 // TODO(vegorov): recognize the pattern with BooleanNegate between comparsion
584 // and a branch. 539 // and a branch.
585 TryFuseComparisonWithBranch(comp); 540 TryFuseComparisonWithBranch(comp);
586 } 541 }
587 542
588 543
589 void FlowGraphOptimizer::VisitDo(DoInstr* instr) { 544 void FlowGraphOptimizer::VisitDo(DoInstr* instr) {
590 instr->computation()->Accept(this); 545 instr->computation()->Accept(this);
591 } 546 }
592 547
593 548
594 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { 549 void FlowGraphOptimizer::VisitBind(BindInstr* instr) {
595 instr->computation()->Accept(this); 550 instr->computation()->Accept(this);
596 } 551 }
597 552
598 553
599 } // namespace dart 554 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/il_printer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698