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

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

Issue 10911214: Split array loads/stores for growable arrays into two IL instructions. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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 | « no previous file | runtime/vm/il_printer.cc » ('j') | runtime/vm/intermediate_language.h » ('J')
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/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
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 // TODO(fschneider): type of load should be GrowableObjectArrayType.
354 LoadVMFieldInstr* elements =
355 new LoadVMFieldInstr(array->Copy(),
356 GrowableObjectArray::data_offset(),
357 AbstractType::ZoneHandle());
srdjan 2012/09/12 07:06:40 Add: elements->set_result_cid(kArrayCid); As
Florian Schneider 2012/09/12 08:27:29 Done.
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, class_id);
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, class_id);
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;
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/il_printer.cc » ('j') | runtime/vm/intermediate_language.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698