| 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/cha.h" | 7 #include "vm/cha.h" |
| 8 #include "vm/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
| 9 #include "vm/hash_map.h" | 9 #include "vm/hash_map.h" |
| 10 #include "vm/il_printer.h" | 10 #include "vm/il_printer.h" |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 static bool HasOnlyTwoDouble(const ICData& ic_data) { | 147 static bool HasOnlyTwoDouble(const ICData& ic_data) { |
| 148 return (ic_data.NumberOfChecks() == 1) && | 148 return (ic_data.NumberOfChecks() == 1) && |
| 149 ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, kDoubleCid); | 149 ICDataHasReceiverArgumentClassIds(ic_data, kDoubleCid, kDoubleCid); |
| 150 } | 150 } |
| 151 | 151 |
| 152 | 152 |
| 153 static void RemovePushArguments(InstanceCallComp* comp) { | 153 static void RemovePushArguments(InstanceCallComp* comp) { |
| 154 // Remove original push arguments. | 154 // Remove original push arguments. |
| 155 for (intptr_t i = 0; i < comp->ArgumentCount(); ++i) { | 155 for (intptr_t i = 0; i < comp->ArgumentCount(); ++i) { |
| 156 PushArgumentInstr* push = comp->ArgumentAt(i); | 156 PushArgumentInstr* push = comp->ArgumentAt(i); |
| 157 push->ReplaceUsesWith(push->value()->AsUse()->definition()); | 157 push->ReplaceUsesWith(push->value()->definition()); |
| 158 push->RemoveFromGraph(); | 158 push->RemoveFromGraph(); |
| 159 } | 159 } |
| 160 } | 160 } |
| 161 | 161 |
| 162 | 162 |
| 163 // Returns true if all targets are the same. | 163 // Returns true if all targets are the same. |
| 164 // TODO(srdjan): if targets are native use their C_function to compare. | 164 // TODO(srdjan): if targets are native use their C_function to compare. |
| 165 static bool HasOneTarget(const ICData& ic_data) { | 165 static bool HasOneTarget(const ICData& ic_data) { |
| 166 ASSERT(ic_data.NumberOfChecks() > 0); | 166 ASSERT(ic_data.NumberOfChecks() > 0); |
| 167 const Function& first_target = Function::Handle(ic_data.GetTargetAt(0)); | 167 const Function& first_target = Function::Handle(ic_data.GetTargetAt(0)); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 // Stores are only specialized for Array and GrowableObjectArray, | 217 // Stores are only specialized for Array and GrowableObjectArray, |
| 218 // not for ImmutableArray. | 218 // not for ImmutableArray. |
| 219 if (op_kind == Token::kASSIGN_INDEX) return false; | 219 if (op_kind == Token::kASSIGN_INDEX) return false; |
| 220 // Fall through. | 220 // Fall through. |
| 221 case kArrayCid: | 221 case kArrayCid: |
| 222 case kGrowableObjectArrayCid: { | 222 case kGrowableObjectArrayCid: { |
| 223 Value* array = comp->ArgumentAt(0)->value(); | 223 Value* array = comp->ArgumentAt(0)->value(); |
| 224 Value* index = comp->ArgumentAt(1)->value(); | 224 Value* index = comp->ArgumentAt(1)->value(); |
| 225 // Insert class check and index smi checks and attach a copy of the | 225 // Insert class check and index smi checks and attach a copy of the |
| 226 // original environment because the operation can still deoptimize. | 226 // original environment because the operation can still deoptimize. |
| 227 AddCheckClass(instr, comp, array->CopyValue()); | 227 AddCheckClass(instr, comp, array->Copy()); |
| 228 InsertBefore(instr, | 228 InsertBefore(instr, |
| 229 new CheckSmiComp(index->CopyValue(), comp), | 229 new CheckSmiComp(index->Copy(), comp), |
| 230 instr->env(), | 230 instr->env(), |
| 231 BindInstr::kUnused); | 231 BindInstr::kUnused); |
| 232 // Insert array bounds check. | 232 // Insert array bounds check. |
| 233 InsertBefore(instr, | 233 InsertBefore(instr, |
| 234 new CheckArrayBoundComp(array->CopyValue(), | 234 new CheckArrayBoundComp(array->Copy(), |
| 235 index->CopyValue(), | 235 index->Copy(), |
| 236 class_id, | 236 class_id, |
| 237 comp), | 237 comp), |
| 238 instr->env(), | 238 instr->env(), |
| 239 BindInstr::kUnused); | 239 BindInstr::kUnused); |
| 240 Computation* array_op = NULL; | 240 Computation* array_op = NULL; |
| 241 if (op_kind == Token::kINDEX) { | 241 if (op_kind == Token::kINDEX) { |
| 242 array_op = new LoadIndexedComp(array, index, class_id); | 242 array_op = new LoadIndexedComp(array, index, class_id); |
| 243 } else { | 243 } else { |
| 244 Value* value = comp->ArgumentAt(2)->value(); | 244 Value* value = comp->ArgumentAt(2)->value(); |
| 245 array_op = new StoreIndexedComp(array, index, value, class_id); | 245 array_op = new StoreIndexedComp(array, index, value, class_id); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 // Check that either left or right are not a smi. Result or a | 341 // Check that either left or right are not a smi. Result or a |
| 342 // binary operation with two smis is a smi not a double. | 342 // binary operation with two smis is a smi not a double. |
| 343 InsertBefore(instr, | 343 InsertBefore(instr, |
| 344 new CheckEitherNonSmiComp(left, right, comp), | 344 new CheckEitherNonSmiComp(left, right, comp), |
| 345 instr->env(), | 345 instr->env(), |
| 346 BindInstr::kUnused); | 346 BindInstr::kUnused); |
| 347 | 347 |
| 348 // Unbox operands. | 348 // Unbox operands. |
| 349 BindInstr* unbox_left = InsertBefore( | 349 BindInstr* unbox_left = InsertBefore( |
| 350 instr, | 350 instr, |
| 351 new UnboxDoubleComp(left->CopyValue(), comp), | 351 new UnboxDoubleComp(left->Copy(), comp), |
| 352 instr->env(), | 352 instr->env(), |
| 353 BindInstr::kUsed); | 353 BindInstr::kUsed); |
| 354 BindInstr* unbox_right = InsertBefore( | 354 BindInstr* unbox_right = InsertBefore( |
| 355 instr, | 355 instr, |
| 356 new UnboxDoubleComp(right->CopyValue(), comp), | 356 new UnboxDoubleComp(right->Copy(), comp), |
| 357 instr->env(), | 357 instr->env(), |
| 358 BindInstr::kUsed); | 358 BindInstr::kUsed); |
| 359 | 359 |
| 360 UnboxedDoubleBinaryOpComp* double_bin_op = | 360 UnboxedDoubleBinaryOpComp* double_bin_op = |
| 361 new UnboxedDoubleBinaryOpComp(op_kind, | 361 new UnboxedDoubleBinaryOpComp(op_kind, |
| 362 new UseVal(unbox_left), | 362 new Value(unbox_left), |
| 363 new UseVal(unbox_right)); | 363 new Value(unbox_right)); |
| 364 double_bin_op->set_ic_data(comp->ic_data()); | 364 double_bin_op->set_ic_data(comp->ic_data()); |
| 365 instr->set_computation(double_bin_op); | 365 instr->set_computation(double_bin_op); |
| 366 | 366 |
| 367 if (instr->is_used()) { | 367 if (instr->is_used()) { |
| 368 // Box result. | 368 // Box result. |
| 369 UseVal* use_val = new UseVal(instr); | 369 Value* value = new Value(instr); |
| 370 BindInstr* bind = InsertAfter(instr, | 370 BindInstr* bind = InsertAfter(instr, |
| 371 new BoxDoubleComp(use_val, comp), | 371 new BoxDoubleComp(value, comp), |
| 372 NULL, | 372 NULL, |
| 373 BindInstr::kUsed); | 373 BindInstr::kUsed); |
| 374 instr->ReplaceUsesWith(bind); | 374 instr->ReplaceUsesWith(bind); |
| 375 } | 375 } |
| 376 | 376 |
| 377 RemovePushArguments(comp); | 377 RemovePushArguments(comp); |
| 378 } else { | 378 } else { |
| 379 BinaryDoubleOpComp* double_bin_op = new BinaryDoubleOpComp(op_kind, comp); | 379 BinaryDoubleOpComp* double_bin_op = new BinaryDoubleOpComp(op_kind, comp); |
| 380 double_bin_op->set_ic_data(comp->ic_data()); | 380 double_bin_op->set_ic_data(comp->ic_data()); |
| 381 instr->set_computation(double_bin_op); | 381 instr->set_computation(double_bin_op); |
| 382 } | 382 } |
| 383 } else if (operands_type == kMintCid) { | 383 } else if (operands_type == kMintCid) { |
| 384 Value* left = comp->ArgumentAt(0)->value(); | 384 Value* left = comp->ArgumentAt(0)->value(); |
| 385 Value* right = comp->ArgumentAt(1)->value(); | 385 Value* right = comp->ArgumentAt(1)->value(); |
| 386 BinaryMintOpComp* bin_op = new BinaryMintOpComp(op_kind, | 386 BinaryMintOpComp* bin_op = new BinaryMintOpComp(op_kind, |
| 387 comp, | 387 comp, |
| 388 left, | 388 left, |
| 389 right); | 389 right); |
| 390 bin_op->set_ic_data(comp->ic_data()); | 390 bin_op->set_ic_data(comp->ic_data()); |
| 391 instr->set_computation(bin_op); | 391 instr->set_computation(bin_op); |
| 392 RemovePushArguments(comp); | 392 RemovePushArguments(comp); |
| 393 } else { | 393 } else { |
| 394 ASSERT(operands_type == kSmiCid); | 394 ASSERT(operands_type == kSmiCid); |
| 395 Value* left = comp->ArgumentAt(0)->value(); | 395 Value* left = comp->ArgumentAt(0)->value(); |
| 396 Value* right = comp->ArgumentAt(1)->value(); | 396 Value* right = comp->ArgumentAt(1)->value(); |
| 397 // Insert two smi checks and attach a copy of the original | 397 // Insert two smi checks and attach a copy of the original |
| 398 // environment because the smi operation can still deoptimize. | 398 // environment because the smi operation can still deoptimize. |
| 399 InsertBefore(instr, | 399 InsertBefore(instr, |
| 400 new CheckSmiComp(left->CopyValue(), comp), | 400 new CheckSmiComp(left->Copy(), comp), |
| 401 instr->env(), | 401 instr->env(), |
| 402 BindInstr::kUnused); | 402 BindInstr::kUnused); |
| 403 InsertBefore(instr, | 403 InsertBefore(instr, |
| 404 new CheckSmiComp(right->CopyValue(), comp), | 404 new CheckSmiComp(right->Copy(), comp), |
| 405 instr->env(), | 405 instr->env(), |
| 406 BindInstr::kUnused); | 406 BindInstr::kUnused); |
| 407 BinarySmiOpComp* bin_op = new BinarySmiOpComp(op_kind, | 407 BinarySmiOpComp* bin_op = new BinarySmiOpComp(op_kind, |
| 408 comp, | 408 comp, |
| 409 left, | 409 left, |
| 410 right); | 410 right); |
| 411 bin_op->set_ic_data(comp->ic_data()); | 411 bin_op->set_ic_data(comp->ic_data()); |
| 412 instr->set_computation(bin_op); | 412 instr->set_computation(bin_op); |
| 413 RemovePushArguments(comp); | 413 RemovePushArguments(comp); |
| 414 } | 414 } |
| 415 return true; | 415 return true; |
| 416 } | 416 } |
| 417 | 417 |
| 418 | 418 |
| 419 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(BindInstr* instr, | 419 bool FlowGraphOptimizer::TryReplaceWithUnaryOp(BindInstr* instr, |
| 420 InstanceCallComp* comp, | 420 InstanceCallComp* comp, |
| 421 Token::Kind op_kind) { | 421 Token::Kind op_kind) { |
| 422 if (comp->ic_data()->NumberOfChecks() != 1) { | 422 if (comp->ic_data()->NumberOfChecks() != 1) { |
| 423 // TODO(srdjan): Not yet supported. | 423 // TODO(srdjan): Not yet supported. |
| 424 return false; | 424 return false; |
| 425 } | 425 } |
| 426 ASSERT(comp->ArgumentCount() == 1); | 426 ASSERT(comp->ArgumentCount() == 1); |
| 427 Computation* unary_op = NULL; | 427 Computation* unary_op = NULL; |
| 428 if (HasOneSmi(*comp->ic_data())) { | 428 if (HasOneSmi(*comp->ic_data())) { |
| 429 Value* value = comp->ArgumentAt(0)->value(); | 429 Value* value = comp->ArgumentAt(0)->value(); |
| 430 InsertBefore(instr, | 430 InsertBefore(instr, |
| 431 new CheckSmiComp(value->CopyValue(), comp), | 431 new CheckSmiComp(value->Copy(), comp), |
| 432 instr->env(), | 432 instr->env(), |
| 433 BindInstr::kUnused); | 433 BindInstr::kUnused); |
| 434 unary_op = new UnarySmiOpComp(op_kind, | 434 unary_op = new UnarySmiOpComp(op_kind, |
| 435 (op_kind == Token::kNEGATE) ? comp : NULL, | 435 (op_kind == Token::kNEGATE) ? comp : NULL, |
| 436 value); | 436 value); |
| 437 } else if (HasOneDouble(*comp->ic_data()) && (op_kind == Token::kNEGATE)) { | 437 } else if (HasOneDouble(*comp->ic_data()) && (op_kind == Token::kNEGATE)) { |
| 438 unary_op = new NumberNegateComp(comp, comp->ArgumentAt(0)->value()); | 438 unary_op = new NumberNegateComp(comp, comp->ArgumentAt(0)->value()); |
| 439 } | 439 } |
| 440 if (unary_op == NULL) return false; | 440 if (unary_op == NULL) return false; |
| 441 | 441 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 if (!HasOneTarget(ic_data)) { | 479 if (!HasOneTarget(ic_data)) { |
| 480 // TODO(srdjan): Implement for mutiple targets. | 480 // TODO(srdjan): Implement for mutiple targets. |
| 481 return false; | 481 return false; |
| 482 } | 482 } |
| 483 // Inline implicit instance getter. | 483 // Inline implicit instance getter. |
| 484 const String& field_name = | 484 const String& field_name = |
| 485 String::Handle(Field::NameFromGetter(comp->function_name())); | 485 String::Handle(Field::NameFromGetter(comp->function_name())); |
| 486 const Field& field = Field::Handle(GetField(class_ids[0], field_name)); | 486 const Field& field = Field::Handle(GetField(class_ids[0], field_name)); |
| 487 ASSERT(!field.IsNull()); | 487 ASSERT(!field.IsNull()); |
| 488 | 488 |
| 489 AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->CopyValue()); | 489 AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->Copy()); |
| 490 // Detach environment from the original instruction because it can't | 490 // Detach environment from the original instruction because it can't |
| 491 // deoptimize. | 491 // deoptimize. |
| 492 instr->set_env(NULL); | 492 instr->set_env(NULL); |
| 493 LoadInstanceFieldComp* load = | 493 LoadInstanceFieldComp* load = |
| 494 new LoadInstanceFieldComp(field, comp->ArgumentAt(0)->value()); | 494 new LoadInstanceFieldComp(field, comp->ArgumentAt(0)->value()); |
| 495 instr->set_computation(load); | 495 instr->set_computation(load); |
| 496 RemovePushArguments(comp); | 496 RemovePushArguments(comp); |
| 497 return true; | 497 return true; |
| 498 } | 498 } |
| 499 | 499 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 616 } | 616 } |
| 617 const intptr_t kMaxChecks = 4; | 617 const intptr_t kMaxChecks = 4; |
| 618 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) { | 618 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) { |
| 619 const ICData& unary_checks = | 619 const ICData& unary_checks = |
| 620 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); | 620 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); |
| 621 bool call_with_checks; | 621 bool call_with_checks; |
| 622 // TODO(srdjan): Add check class comp for mixed smi/non-smi. | 622 // TODO(srdjan): Add check class comp for mixed smi/non-smi. |
| 623 if (HasOneTarget(unary_checks) && | 623 if (HasOneTarget(unary_checks) && |
| 624 (unary_checks.GetReceiverClassIdAt(0) != kSmiCid)) { | 624 (unary_checks.GetReceiverClassIdAt(0) != kSmiCid)) { |
| 625 // Type propagation has not run yet, we cannot eliminate the check. | 625 // Type propagation has not run yet, we cannot eliminate the check. |
| 626 AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->CopyValue()); | 626 AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->Copy()); |
| 627 // Call can still deoptimize, do not detach environment from instr. | 627 // Call can still deoptimize, do not detach environment from instr. |
| 628 call_with_checks = false; | 628 call_with_checks = false; |
| 629 } else { | 629 } else { |
| 630 call_with_checks = true; | 630 call_with_checks = true; |
| 631 } | 631 } |
| 632 PolymorphicInstanceCallComp* call = | 632 PolymorphicInstanceCallComp* call = |
| 633 new PolymorphicInstanceCallComp(comp, call_with_checks); | 633 new PolymorphicInstanceCallComp(comp, call_with_checks); |
| 634 call->set_ic_data(&unary_checks); | 634 call->set_ic_data(&unary_checks); |
| 635 instr->set_computation(call); | 635 instr->set_computation(call); |
| 636 } | 636 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 // Not an implicit setter. | 674 // Not an implicit setter. |
| 675 // TODO(srdjan): Inline special setters. | 675 // TODO(srdjan): Inline special setters. |
| 676 return false; | 676 return false; |
| 677 } | 677 } |
| 678 // Inline implicit instance setter. | 678 // Inline implicit instance setter. |
| 679 const String& field_name = | 679 const String& field_name = |
| 680 String::Handle(Field::NameFromSetter(comp->function_name())); | 680 String::Handle(Field::NameFromSetter(comp->function_name())); |
| 681 const Field& field = Field::Handle(GetField(class_id, field_name)); | 681 const Field& field = Field::Handle(GetField(class_id, field_name)); |
| 682 ASSERT(!field.IsNull()); | 682 ASSERT(!field.IsNull()); |
| 683 | 683 |
| 684 AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->CopyValue()); | 684 AddCheckClass(instr, comp, comp->ArgumentAt(0)->value()->Copy()); |
| 685 // Detach environment from the original instruction because it can't | 685 // Detach environment from the original instruction because it can't |
| 686 // deoptimize. | 686 // deoptimize. |
| 687 instr->set_env(NULL); | 687 instr->set_env(NULL); |
| 688 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( | 688 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( |
| 689 field, | 689 field, |
| 690 comp->ArgumentAt(0)->value(), | 690 comp->ArgumentAt(0)->value(), |
| 691 comp->ArgumentAt(1)->value()); | 691 comp->ArgumentAt(1)->value()); |
| 692 instr->set_computation(store); | 692 instr->set_computation(store); |
| 693 RemovePushArguments(comp); | 693 RemovePushArguments(comp); |
| 694 return true; | 694 return true; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 | 758 |
| 759 | 759 |
| 760 void FlowGraphTypePropagator::VisitAssertAssignable(AssertAssignableComp* comp, | 760 void FlowGraphTypePropagator::VisitAssertAssignable(AssertAssignableComp* comp, |
| 761 BindInstr* instr) { | 761 BindInstr* instr) { |
| 762 if (FLAG_eliminate_type_checks && | 762 if (FLAG_eliminate_type_checks && |
| 763 !comp->is_eliminated() && | 763 !comp->is_eliminated() && |
| 764 comp->value()->CompileTypeIsMoreSpecificThan(comp->dst_type())) { | 764 comp->value()->CompileTypeIsMoreSpecificThan(comp->dst_type())) { |
| 765 // TODO(regis): Remove is_eliminated_ field and support. | 765 // TODO(regis): Remove is_eliminated_ field and support. |
| 766 comp->eliminate(); | 766 comp->eliminate(); |
| 767 | 767 |
| 768 UseVal* use = comp->value()->AsUse(); | 768 Value* use = comp->value(); |
| 769 ASSERT(use != NULL); | 769 ASSERT(use != NULL); |
| 770 Definition* result = use->definition(); | 770 Definition* result = use->definition(); |
| 771 ASSERT(result != NULL); | 771 ASSERT(result != NULL); |
| 772 // Replace uses and remove the current instructions via the iterator. | 772 // Replace uses and remove the current instructions via the iterator. |
| 773 instr->ReplaceUsesWith(result); | 773 instr->ReplaceUsesWith(result); |
| 774 ASSERT(current_iterator()->Current() == instr); | 774 ASSERT(current_iterator()->Current() == instr); |
| 775 current_iterator()->RemoveCurrentFromGraph(); | 775 current_iterator()->RemoveCurrentFromGraph(); |
| 776 if (FLAG_trace_optimization) { | 776 if (FLAG_trace_optimization) { |
| 777 OS::Print("Replacing v%d with v%d\n", | 777 OS::Print("Replacing v%d with v%d\n", |
| 778 instr->ssa_temp_index(), | 778 instr->ssa_temp_index(), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 801 // type (bool) may still hold null at run time and therefore fail the test. | 801 // type (bool) may still hold null at run time and therefore fail the test. |
| 802 if (FLAG_eliminate_type_checks && | 802 if (FLAG_eliminate_type_checks && |
| 803 !comp->is_eliminated() && | 803 !comp->is_eliminated() && |
| 804 comp->value()->BindsToConstant() && | 804 comp->value()->BindsToConstant() && |
| 805 !comp->value()->BindsToConstantNull() && | 805 !comp->value()->BindsToConstantNull() && |
| 806 comp->value()->CompileTypeIsMoreSpecificThan( | 806 comp->value()->CompileTypeIsMoreSpecificThan( |
| 807 Type::Handle(Type::BoolType()))) { | 807 Type::Handle(Type::BoolType()))) { |
| 808 // TODO(regis): Remove is_eliminated_ field and support. | 808 // TODO(regis): Remove is_eliminated_ field and support. |
| 809 comp->eliminate(); | 809 comp->eliminate(); |
| 810 | 810 |
| 811 UseVal* use = comp->value()->AsUse(); | 811 Value* use = comp->value(); |
| 812 ASSERT(use != NULL); | |
| 813 Definition* result = use->definition(); | 812 Definition* result = use->definition(); |
| 814 ASSERT(result != NULL); | 813 ASSERT(result != NULL); |
| 815 // Replace uses and remove the current instructions via the iterator. | 814 // Replace uses and remove the current instructions via the iterator. |
| 816 instr->ReplaceUsesWith(result); | 815 instr->ReplaceUsesWith(result); |
| 817 ASSERT(current_iterator()->Current() == instr); | 816 ASSERT(current_iterator()->Current() == instr); |
| 818 current_iterator()->RemoveCurrentFromGraph(); | 817 current_iterator()->RemoveCurrentFromGraph(); |
| 819 if (FLAG_trace_optimization) { | 818 if (FLAG_trace_optimization) { |
| 820 OS::Print("Replacing v%d with v%d\n", | 819 OS::Print("Replacing v%d with v%d\n", |
| 821 instr->ssa_temp_index(), | 820 instr->ssa_temp_index(), |
| 822 result->ssa_temp_index()); | 821 result->ssa_temp_index()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 842 | 841 |
| 843 // We can only eliminate an 'instance of' test when the checked value is | 842 // We can only eliminate an 'instance of' test when the checked value is |
| 844 // a constant time constant. Indeed, a variable of the proper compile time | 843 // a constant time constant. Indeed, a variable of the proper compile time |
| 845 // type may still hold null at run time and therefore fail the test. | 844 // type may still hold null at run time and therefore fail the test. |
| 846 // We do not bother checking for Object destination type, since the graph | 845 // We do not bother checking for Object destination type, since the graph |
| 847 // builder did already. | 846 // builder did already. |
| 848 if (FLAG_eliminate_type_checks && | 847 if (FLAG_eliminate_type_checks && |
| 849 comp->value()->BindsToConstant() && | 848 comp->value()->BindsToConstant() && |
| 850 !comp->value()->BindsToConstantNull() && | 849 !comp->value()->BindsToConstantNull() && |
| 851 comp->value()->CompileTypeIsMoreSpecificThan(comp->type())) { | 850 comp->value()->CompileTypeIsMoreSpecificThan(comp->type())) { |
| 852 UseVal* use = comp->value()->AsUse(); | 851 Value* use = comp->value(); |
| 853 ASSERT(use != NULL); | |
| 854 Definition* result = use->definition(); | 852 Definition* result = use->definition(); |
| 855 ASSERT(result != NULL); | 853 ASSERT(result != NULL); |
| 856 // Replace uses and remove the current instructions via the iterator. | 854 // Replace uses and remove the current instructions via the iterator. |
| 857 instr->ReplaceUsesWith(result); | 855 instr->ReplaceUsesWith(result); |
| 858 ASSERT(current_iterator()->Current() == instr); | 856 ASSERT(current_iterator()->Current() == instr); |
| 859 current_iterator()->RemoveCurrentFromGraph(); | 857 current_iterator()->RemoveCurrentFromGraph(); |
| 860 if (FLAG_trace_optimization) { | 858 if (FLAG_trace_optimization) { |
| 861 OS::Print("Replacing v%d with v%d\n", | 859 OS::Print("Replacing v%d with v%d\n", |
| 862 instr->ssa_temp_index(), | 860 instr->ssa_temp_index(), |
| 863 result->ssa_temp_index()); | 861 result->ssa_temp_index()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 876 } | 874 } |
| 877 | 875 |
| 878 | 876 |
| 879 void FlowGraphTypePropagator::VisitGraphEntry(GraphEntryInstr* graph_entry) { | 877 void FlowGraphTypePropagator::VisitGraphEntry(GraphEntryInstr* graph_entry) { |
| 880 if (graph_entry->start_env() == NULL) { | 878 if (graph_entry->start_env() == NULL) { |
| 881 return; | 879 return; |
| 882 } | 880 } |
| 883 // Visit incoming parameters. | 881 // Visit incoming parameters. |
| 884 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { | 882 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { |
| 885 Value* val = graph_entry->start_env()->values()[i]; | 883 Value* val = graph_entry->start_env()->values()[i]; |
| 886 if (val->IsUse()) { | 884 ParameterInstr* param = val->definition()->AsParameter(); |
| 887 ParameterInstr* param = val->AsUse()->definition()->AsParameter(); | 885 if (param != NULL) { |
| 888 if (param != NULL) { | 886 ASSERT(param->index() == i); |
| 889 ASSERT(param->index() == i); | 887 VisitParameter(param); |
| 890 VisitParameter(param); | |
| 891 } | |
| 892 } | 888 } |
| 893 } | 889 } |
| 894 } | 890 } |
| 895 | 891 |
| 896 | 892 |
| 897 void FlowGraphTypePropagator::VisitJoinEntry(JoinEntryInstr* join_entry) { | 893 void FlowGraphTypePropagator::VisitJoinEntry(JoinEntryInstr* join_entry) { |
| 898 if (join_entry->phis() != NULL) { | 894 if (join_entry->phis() != NULL) { |
| 899 for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { | 895 for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { |
| 900 PhiInstr* phi = (*join_entry->phis())[i]; | 896 PhiInstr* phi = (*join_entry->phis())[i]; |
| 901 if (phi != NULL) { | 897 if (phi != NULL) { |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1069 DirectChainedHashMap<BindInstr*> child_map(*map); // Copy map. | 1065 DirectChainedHashMap<BindInstr*> child_map(*map); // Copy map. |
| 1070 OptimizeRecursive(child, &child_map); | 1066 OptimizeRecursive(child, &child_map); |
| 1071 } else { | 1067 } else { |
| 1072 OptimizeRecursive(child, map); // Reuse map for the last child. | 1068 OptimizeRecursive(child, map); // Reuse map for the last child. |
| 1073 } | 1069 } |
| 1074 } | 1070 } |
| 1075 } | 1071 } |
| 1076 | 1072 |
| 1077 | 1073 |
| 1078 } // namespace dart | 1074 } // namespace dart |
| OLD | NEW |