| 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 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 call->env(), | 341 call->env(), |
| 342 Definition::kEffect); | 342 Definition::kEffect); |
| 343 // Insert array bounds check. | 343 // Insert array bounds check. |
| 344 InsertBefore(call, | 344 InsertBefore(call, |
| 345 new CheckArrayBoundInstr(array->Copy(), | 345 new CheckArrayBoundInstr(array->Copy(), |
| 346 index->Copy(), | 346 index->Copy(), |
| 347 class_id, | 347 class_id, |
| 348 call), | 348 call), |
| 349 call->env(), | 349 call->env(), |
| 350 Definition::kEffect); | 350 Definition::kEffect); |
| 351 if (class_id == kGrowableObjectArrayCid) { |
| 352 // Insert data elements load. |
| 353 LoadVMFieldInstr* elements = |
| 354 new LoadVMFieldInstr(array->Copy(), |
| 355 GrowableObjectArray::data_offset(), |
| 356 Type::ZoneHandle(Type::DynamicType())); |
| 357 elements->set_result_cid(kArrayCid); |
| 358 InsertBefore(call, elements, NULL, Definition::kValue); |
| 359 array = new Value(elements); |
| 360 } |
| 351 Definition* array_op = NULL; | 361 Definition* array_op = NULL; |
| 352 if (op_kind == Token::kINDEX) { | 362 if (op_kind == Token::kINDEX) { |
| 353 array_op = new LoadIndexedInstr(array, index, class_id); | 363 array_op = new LoadIndexedInstr(array, index); |
| 354 } else { | 364 } else { |
| 355 Value* value = call->ArgumentAt(2)->value(); | 365 Value* value = call->ArgumentAt(2)->value(); |
| 356 array_op = new StoreIndexedInstr(array, index, value, class_id); | 366 array_op = new StoreIndexedInstr(array, index, value); |
| 357 } | 367 } |
| 358 call->ReplaceWith(array_op, current_iterator()); | 368 call->ReplaceWith(array_op, current_iterator()); |
| 359 RemovePushArguments(call); | 369 RemovePushArguments(call); |
| 360 return true; | 370 return true; |
| 361 } | 371 } |
| 362 default: | 372 default: |
| 363 return false; | 373 return false; |
| 364 } | 374 } |
| 365 } | 375 } |
| 366 | 376 |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 | 617 |
| 608 // VM objects length getter. | 618 // VM objects length getter. |
| 609 if ((recognized_kind == MethodRecognizer::kObjectArrayLength) || | 619 if ((recognized_kind == MethodRecognizer::kObjectArrayLength) || |
| 610 (recognized_kind == MethodRecognizer::kImmutableArrayLength) || | 620 (recognized_kind == MethodRecognizer::kImmutableArrayLength) || |
| 611 (recognized_kind == MethodRecognizer::kGrowableArrayLength)) { | 621 (recognized_kind == MethodRecognizer::kGrowableArrayLength)) { |
| 612 if (!HasOneTarget(ic_data)) { | 622 if (!HasOneTarget(ic_data)) { |
| 613 // TODO(srdjan): Implement for mutiple targets. | 623 // TODO(srdjan): Implement for mutiple targets. |
| 614 return false; | 624 return false; |
| 615 } | 625 } |
| 616 intptr_t length_offset = -1; | 626 intptr_t length_offset = -1; |
| 627 bool is_immutable = false; |
| 617 switch (recognized_kind) { | 628 switch (recognized_kind) { |
| 618 case MethodRecognizer::kObjectArrayLength: | 629 case MethodRecognizer::kObjectArrayLength: |
| 619 case MethodRecognizer::kImmutableArrayLength: | 630 case MethodRecognizer::kImmutableArrayLength: |
| 620 length_offset = Array::length_offset(); | 631 length_offset = Array::length_offset(); |
| 632 is_immutable = true; |
| 621 break; | 633 break; |
| 622 case MethodRecognizer::kGrowableArrayLength: | 634 case MethodRecognizer::kGrowableArrayLength: |
| 623 length_offset = GrowableObjectArray::length_offset(); | 635 length_offset = GrowableObjectArray::length_offset(); |
| 624 break; | 636 break; |
| 625 default: | 637 default: |
| 626 UNREACHABLE(); | 638 UNREACHABLE(); |
| 627 } | 639 } |
| 628 // Check receiver class. | 640 // Check receiver class. |
| 629 AddCheckClass(call, call->ArgumentAt(0)->value()->Copy()); | 641 AddCheckClass(call, call->ArgumentAt(0)->value()->Copy()); |
| 630 | 642 |
| 631 LoadVMFieldInstr* load = new LoadVMFieldInstr( | 643 LoadVMFieldInstr* load = new LoadVMFieldInstr( |
| 632 call->ArgumentAt(0)->value(), | 644 call->ArgumentAt(0)->value(), |
| 633 length_offset, | 645 length_offset, |
| 634 Type::ZoneHandle(Type::SmiType())); | 646 Type::ZoneHandle(Type::SmiType()), |
| 647 is_immutable); |
| 635 load->set_result_cid(kSmiCid); | 648 load->set_result_cid(kSmiCid); |
| 636 call->ReplaceWith(load, current_iterator()); | 649 call->ReplaceWith(load, current_iterator()); |
| 637 RemovePushArguments(call); | 650 RemovePushArguments(call); |
| 638 return true; | 651 return true; |
| 639 } | 652 } |
| 640 | 653 |
| 641 if (recognized_kind == MethodRecognizer::kGrowableArrayCapacity) { | 654 if (recognized_kind == MethodRecognizer::kGrowableArrayCapacity) { |
| 642 // Check receiver class. | 655 // Check receiver class. |
| 643 AddCheckClass(call, call->ArgumentAt(0)->value()->Copy()); | 656 AddCheckClass(call, call->ArgumentAt(0)->value()->Copy()); |
| 644 | 657 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 662 } | 675 } |
| 663 | 676 |
| 664 if (recognized_kind == MethodRecognizer::kStringBaseLength) { | 677 if (recognized_kind == MethodRecognizer::kStringBaseLength) { |
| 665 if (!HasOneTarget(ic_data)) { | 678 if (!HasOneTarget(ic_data)) { |
| 666 // Target is not only StringBase_get_length. | 679 // Target is not only StringBase_get_length. |
| 667 return false; | 680 return false; |
| 668 } | 681 } |
| 669 // Check receiver class. | 682 // Check receiver class. |
| 670 AddCheckClass(call, call->ArgumentAt(0)->value()->Copy()); | 683 AddCheckClass(call, call->ArgumentAt(0)->value()->Copy()); |
| 671 | 684 |
| 685 const bool is_immutable = true; // String length is immutable. |
| 672 LoadVMFieldInstr* load = new LoadVMFieldInstr( | 686 LoadVMFieldInstr* load = new LoadVMFieldInstr( |
| 673 call->ArgumentAt(0)->value(), | 687 call->ArgumentAt(0)->value(), |
| 674 String::length_offset(), | 688 String::length_offset(), |
| 675 Type::ZoneHandle(Type::SmiType())); | 689 Type::ZoneHandle(Type::SmiType()), |
| 690 is_immutable); |
| 676 load->set_result_cid(kSmiCid); | 691 load->set_result_cid(kSmiCid); |
| 677 call->ReplaceWith(load, current_iterator()); | 692 call->ReplaceWith(load, current_iterator()); |
| 678 RemovePushArguments(call); | 693 RemovePushArguments(call); |
| 679 return true; | 694 return true; |
| 680 } | 695 } |
| 681 return false; | 696 return false; |
| 682 } | 697 } |
| 683 | 698 |
| 684 | 699 |
| 685 // Inline only simple, frequently called core library methods. | 700 // Inline only simple, frequently called core library methods. |
| (...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1301 for (BitVector::Iterator loop_it(header->loop_info()); | 1316 for (BitVector::Iterator loop_it(header->loop_info()); |
| 1302 !loop_it.Done(); | 1317 !loop_it.Done(); |
| 1303 loop_it.Advance()) { | 1318 loop_it.Advance()) { |
| 1304 BlockEntryInstr* block = flow_graph->preorder()[loop_it.Current()]; | 1319 BlockEntryInstr* block = flow_graph->preorder()[loop_it.Current()]; |
| 1305 for (ForwardInstructionIterator it(block); | 1320 for (ForwardInstructionIterator it(block); |
| 1306 !it.Done(); | 1321 !it.Done(); |
| 1307 it.Advance()) { | 1322 it.Advance()) { |
| 1308 Definition* current = it.Current()->AsDefinition(); | 1323 Definition* current = it.Current()->AsDefinition(); |
| 1309 if (current != NULL && | 1324 if (current != NULL && |
| 1310 !current->IsPushArgument() && | 1325 !current->IsPushArgument() && |
| 1311 !current->HasSideEffect()) { | 1326 !current->AffectedBySideEffect()) { |
| 1312 bool inputs_loop_invariant = true; | 1327 bool inputs_loop_invariant = true; |
| 1313 for (int i = 0; i < current->InputCount(); ++i) { | 1328 for (int i = 0; i < current->InputCount(); ++i) { |
| 1314 Definition* input_def = current->InputAt(i)->definition(); | 1329 Definition* input_def = current->InputAt(i)->definition(); |
| 1315 if (!input_def->GetBlock()->Dominates(pre_header)) { | 1330 if (!input_def->GetBlock()->Dominates(pre_header)) { |
| 1316 inputs_loop_invariant = false; | 1331 inputs_loop_invariant = false; |
| 1317 break; | 1332 break; |
| 1318 } | 1333 } |
| 1319 } | 1334 } |
| 1320 if (inputs_loop_invariant) { | 1335 if (inputs_loop_invariant) { |
| 1321 Hoist(&it, pre_header, current); | 1336 Hoist(&it, pre_header, current); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1335 DirectChainedHashMap<Definition*> map; | 1350 DirectChainedHashMap<Definition*> map; |
| 1336 OptimizeRecursive(graph_entry, &map); | 1351 OptimizeRecursive(graph_entry, &map); |
| 1337 } | 1352 } |
| 1338 | 1353 |
| 1339 | 1354 |
| 1340 void DominatorBasedCSE::OptimizeRecursive( | 1355 void DominatorBasedCSE::OptimizeRecursive( |
| 1341 BlockEntryInstr* block, | 1356 BlockEntryInstr* block, |
| 1342 DirectChainedHashMap<Definition*>* map) { | 1357 DirectChainedHashMap<Definition*>* map) { |
| 1343 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 1358 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 1344 Definition* defn = it.Current()->AsDefinition(); | 1359 Definition* defn = it.Current()->AsDefinition(); |
| 1345 if ((defn == NULL) || defn->HasSideEffect()) continue; | 1360 if ((defn == NULL) || defn->AffectedBySideEffect()) continue; |
| 1346 Definition* result = map->Lookup(defn); | 1361 Definition* result = map->Lookup(defn); |
| 1347 if (result == NULL) { | 1362 if (result == NULL) { |
| 1348 map->Insert(defn); | 1363 map->Insert(defn); |
| 1349 continue; | 1364 continue; |
| 1350 } | 1365 } |
| 1351 // Replace current with lookup result. | 1366 // Replace current with lookup result. |
| 1352 defn->ReplaceUsesWith(result); | 1367 defn->ReplaceUsesWith(result); |
| 1353 it.RemoveCurrentFromGraph(); | 1368 it.RemoveCurrentFromGraph(); |
| 1354 if (FLAG_trace_optimization) { | 1369 if (FLAG_trace_optimization) { |
| 1355 OS::Print("Replacing v%"Pd" with v%"Pd"\n", | 1370 OS::Print("Replacing v%"Pd" with v%"Pd"\n", |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1366 DirectChainedHashMap<Definition*> child_map(*map); // Copy map. | 1381 DirectChainedHashMap<Definition*> child_map(*map); // Copy map. |
| 1367 OptimizeRecursive(child, &child_map); | 1382 OptimizeRecursive(child, &child_map); |
| 1368 } else { | 1383 } else { |
| 1369 OptimizeRecursive(child, map); // Reuse map for the last child. | 1384 OptimizeRecursive(child, map); // Reuse map for the last child. |
| 1370 } | 1385 } |
| 1371 } | 1386 } |
| 1372 } | 1387 } |
| 1373 | 1388 |
| 1374 | 1389 |
| 1375 } // namespace dart | 1390 } // namespace dart |
| OLD | NEW |