| OLD | NEW |
| 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/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/hash_map.h" | 10 #include "vm/hash_map.h" |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 } | 461 } |
| 462 break; | 462 break; |
| 463 case Token::kDIV: | 463 case Token::kDIV: |
| 464 if (ShouldSpecializeForDouble(ic_data)) { | 464 if (ShouldSpecializeForDouble(ic_data)) { |
| 465 operands_type = kDoubleCid; | 465 operands_type = kDoubleCid; |
| 466 } else { | 466 } else { |
| 467 return false; | 467 return false; |
| 468 } | 468 } |
| 469 break; | 469 break; |
| 470 case Token::kMOD: | 470 case Token::kMOD: |
| 471 // TODO(vegorov): implement fast path code for modulo. | 471 if (HasOnlyTwoSmi(ic_data)) { |
| 472 return false; | 472 operands_type = kSmiCid; |
| 473 } else { |
| 474 return false; |
| 475 } |
| 476 break; |
| 473 case Token::kBIT_AND: | 477 case Token::kBIT_AND: |
| 474 if (HasOnlyTwoSmi(ic_data)) { | 478 if (HasOnlyTwoSmi(ic_data)) { |
| 475 operands_type = kSmiCid; | 479 operands_type = kSmiCid; |
| 476 } else if (HasTwoMintOrSmi(ic_data)) { | 480 } else if (HasTwoMintOrSmi(ic_data)) { |
| 477 operands_type = kMintCid; | 481 operands_type = kMintCid; |
| 478 } else { | 482 } else { |
| 479 return false; | 483 return false; |
| 480 } | 484 } |
| 481 break; | 485 break; |
| 482 case Token::kBIT_OR: | 486 case Token::kBIT_OR: |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 RemovePushArguments(call); | 521 RemovePushArguments(call); |
| 518 } else if (operands_type == kMintCid) { | 522 } else if (operands_type == kMintCid) { |
| 519 Value* left = call->ArgumentAt(0)->value(); | 523 Value* left = call->ArgumentAt(0)->value(); |
| 520 Value* right = call->ArgumentAt(1)->value(); | 524 Value* right = call->ArgumentAt(1)->value(); |
| 521 BinaryMintOpInstr* bin_op = new BinaryMintOpInstr(op_kind, | 525 BinaryMintOpInstr* bin_op = new BinaryMintOpInstr(op_kind, |
| 522 call, | 526 call, |
| 523 left, | 527 left, |
| 524 right); | 528 right); |
| 525 call->ReplaceWith(bin_op, current_iterator()); | 529 call->ReplaceWith(bin_op, current_iterator()); |
| 526 RemovePushArguments(call); | 530 RemovePushArguments(call); |
| 531 } else if (op_kind == Token::kMOD) { |
| 532 // TODO(vegorov): implement fast path code for modulo. |
| 533 ASSERT(operands_type == kSmiCid); |
| 534 if (!call->ArgumentAt(1)->value()->BindsToConstant()) return false; |
| 535 const Object& obj = call->ArgumentAt(1)->value()->BoundConstant(); |
| 536 if (!obj.IsSmi()) return false; |
| 537 const intptr_t value = Smi::Cast(obj).Value(); |
| 538 if ((value > 0) && Utils::IsPowerOfTwo(value)) { |
| 539 Value* left = call->ArgumentAt(0)->value(); |
| 540 // Insert smi check and attach a copy of the original |
| 541 // environment because the smi operation can still deoptimize. |
| 542 InsertBefore(call, |
| 543 new CheckSmiInstr(left->Copy(), call->deopt_id()), |
| 544 call->env(), |
| 545 Definition::kEffect); |
| 546 ConstantInstr* c = new ConstantInstr(Smi::Handle(Smi::New(value - 1))); |
| 547 InsertBefore(call, c, NULL, Definition::kValue); |
| 548 BinarySmiOpInstr* bin_op = |
| 549 new BinarySmiOpInstr(Token::kBIT_AND, call, left, new Value(c)); |
| 550 call->ReplaceWith(bin_op, current_iterator()); |
| 551 RemovePushArguments(call); |
| 552 } |
| 527 } else { | 553 } else { |
| 528 ASSERT(operands_type == kSmiCid); | 554 ASSERT(operands_type == kSmiCid); |
| 529 Value* left = call->ArgumentAt(0)->value(); | 555 Value* left = call->ArgumentAt(0)->value(); |
| 530 Value* right = call->ArgumentAt(1)->value(); | 556 Value* right = call->ArgumentAt(1)->value(); |
| 531 // Insert two smi checks and attach a copy of the original | 557 // Insert two smi checks and attach a copy of the original |
| 532 // environment because the smi operation can still deoptimize. | 558 // environment because the smi operation can still deoptimize. |
| 533 InsertBefore(call, | 559 InsertBefore(call, |
| 534 new CheckSmiInstr(left->Copy(), call->deopt_id()), | 560 new CheckSmiInstr(left->Copy(), call->deopt_id()), |
| 535 call->env(), | 561 call->env(), |
| 536 Definition::kEffect); | 562 Definition::kEffect); |
| (...skipping 2554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3091 | 3117 |
| 3092 if (FLAG_trace_constant_propagation) { | 3118 if (FLAG_trace_constant_propagation) { |
| 3093 OS::Print("\n==== After constant propagation ====\n"); | 3119 OS::Print("\n==== After constant propagation ====\n"); |
| 3094 FlowGraphPrinter printer(*graph_); | 3120 FlowGraphPrinter printer(*graph_); |
| 3095 printer.PrintBlocks(); | 3121 printer.PrintBlocks(); |
| 3096 } | 3122 } |
| 3097 } | 3123 } |
| 3098 | 3124 |
| 3099 | 3125 |
| 3100 } // namespace dart | 3126 } // namespace dart |
| OLD | NEW |