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

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

Issue 10824349: Implement class id checks as a separate instruction and add a local CSE optimization pass. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 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_optimizer.h ('k') | runtime/vm/hash_map.h » ('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/hash_map.h"
8 #include "vm/il_printer.h" 9 #include "vm/il_printer.h"
9 #include "vm/object_store.h" 10 #include "vm/object_store.h"
10 #include "vm/parser.h" 11 #include "vm/parser.h"
11 #include "vm/scopes.h" 12 #include "vm/scopes.h"
12 #include "vm/symbols.h" 13 #include "vm/symbols.h"
13 14
14 namespace dart { 15 namespace dart {
15 16
16 DECLARE_FLAG(bool, eliminate_type_checks); 17 DECLARE_FLAG(bool, eliminate_type_checks);
17 DECLARE_FLAG(bool, enable_type_checks); 18 DECLARE_FLAG(bool, enable_type_checks);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 if ((class_ids[0] == receiver_class_id) && 75 if ((class_ids[0] == receiver_class_id) &&
75 (class_ids[1] == argument_class_id)) { 76 (class_ids[1] == argument_class_id)) {
76 return true; 77 return true;
77 } 78 }
78 } 79 }
79 return false; 80 return false;
80 } 81 }
81 82
82 83
83 static bool ClassIdIsOneOf(intptr_t class_id, 84 static bool ClassIdIsOneOf(intptr_t class_id,
84 GrowableArray<intptr_t>* class_ids) { 85 const GrowableArray<intptr_t>& class_ids) {
85 for (intptr_t i = 0; i < class_ids->length(); i++) { 86 for (intptr_t i = 0; i < class_ids.length(); i++) {
86 if ((*class_ids)[i] == class_id) { 87 if (class_ids[i] == class_id) {
87 return true; 88 return true;
88 } 89 }
89 } 90 }
90 return false; 91 return false;
91 } 92 }
92 93
93 94
94 static bool ICDataHasOnlyReceiverArgumentClassIds( 95 static bool ICDataHasOnlyReceiverArgumentClassIds(
95 const ICData& ic_data, 96 const ICData& ic_data,
96 GrowableArray<intptr_t>* receiver_class_ids, 97 const GrowableArray<intptr_t>& receiver_class_ids,
97 GrowableArray<intptr_t>* argument_class_ids) { 98 const GrowableArray<intptr_t>& argument_class_ids) {
98 if (ic_data.num_args_tested() != 2) return false; 99 if (ic_data.num_args_tested() != 2) return false;
99 100
100 Function& target = Function::Handle(); 101 Function& target = Function::Handle();
101 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 102 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
102 GrowableArray<intptr_t> class_ids; 103 GrowableArray<intptr_t> class_ids;
103 ic_data.GetCheckAt(i, &class_ids, &target); 104 ic_data.GetCheckAt(i, &class_ids, &target);
104 ASSERT(class_ids.length() == 2); 105 ASSERT(class_ids.length() == 2);
105 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || 106 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) ||
106 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { 107 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) {
107 return false; 108 return false;
(...skipping 10 matching lines...) Expand all
118 119
119 static bool HasOnlyTwoSmi(const ICData& ic_data) { 120 static bool HasOnlyTwoSmi(const ICData& ic_data) {
120 return (ic_data.NumberOfChecks() == 1) && 121 return (ic_data.NumberOfChecks() == 1) &&
121 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); 122 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid);
122 } 123 }
123 124
124 125
125 // Returns false if the ICData contains anything other than the 4 combinations 126 // Returns false if the ICData contains anything other than the 4 combinations
126 // of Mint and Smi for the receiver and argument classes. 127 // of Mint and Smi for the receiver and argument classes.
127 static bool HasTwoMintOrSmi(const ICData& ic_data) { 128 static bool HasTwoMintOrSmi(const ICData& ic_data) {
128 GrowableArray<intptr_t> class_ids; 129 GrowableArray<intptr_t> class_ids(2);
129 class_ids.Add(kSmiCid); 130 class_ids.Add(kSmiCid);
130 class_ids.Add(kMintCid); 131 class_ids.Add(kMintCid);
131 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, &class_ids, &class_ids); 132 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids);
132 } 133 }
133 134
134 135
135 static bool HasOneDouble(const ICData& ic_data) { 136 static bool HasOneDouble(const ICData& ic_data) {
136 return ICDataHasReceiverClassId(ic_data, kDoubleCid); 137 return ICDataHasReceiverClassId(ic_data, kDoubleCid);
137 } 138 }
138 139
139 140
140 static bool HasOnlyTwoDouble(const ICData& ic_data) { 141 static bool HasOnlyTwoDouble(const ICData& ic_data) {
141 return (ic_data.NumberOfChecks() == 1) && 142 return (ic_data.NumberOfChecks() == 1) &&
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 if (target.kind() == RawFunction::kImplicitGetter) { 357 if (target.kind() == RawFunction::kImplicitGetter) {
357 if (!HasOneTarget(ic_data)) { 358 if (!HasOneTarget(ic_data)) {
358 // TODO(srdjan): Implement for mutiple targets. 359 // TODO(srdjan): Implement for mutiple targets.
359 return false; 360 return false;
360 } 361 }
361 // Inline implicit instance getter. 362 // Inline implicit instance getter.
362 const String& field_name = 363 const String& field_name =
363 String::Handle(Field::NameFromGetter(comp->function_name())); 364 String::Handle(Field::NameFromGetter(comp->function_name()));
364 const Field& field = Field::Handle(GetField(class_ids[0], field_name)); 365 const Field& field = Field::Handle(GetField(class_ids[0], field_name));
365 ASSERT(!field.IsNull()); 366 ASSERT(!field.IsNull());
366 LoadInstanceFieldComp* load = new LoadInstanceFieldComp( 367
367 field, comp->ArgumentAt(0)->value(), comp); 368 LoadInstanceFieldComp* load;
368 load->set_ic_data(comp->ic_data()); 369 if (!use_ssa_) {
370 load = new LoadInstanceFieldComp(field,
371 comp->ArgumentAt(0)->value(),
372 comp,
373 true); // Can deoptimize.
374 // TODO(fschneider): Remove the boolean parameter can_deoptimize once
375 // the non-SSA optimizer is removed.
376 load->set_ic_data(comp->ic_data());
377 } else {
378 // TODO(fschneider): Avoid generating redundant checks by checking the
379 // result-cid of the value.
380 CheckClassComp* check =
381 new CheckClassComp(comp->ArgumentAt(0)->value(), comp);
382 const ICData& unary_checks =
383 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
384 check->set_ic_data(&unary_checks);
385 BindInstr* check_instr = new BindInstr(BindInstr::kUnused, check);
386 ASSERT(instr->env() != NULL); // Always the case with SSA.
387 check_instr->set_env(
388 new Environment(instr->env()->values(),
389 instr->env()->fixed_parameter_count()));
390 check_instr->InsertBefore(instr);
391 load = new LoadInstanceFieldComp(field,
392 comp->ArgumentAt(0)->value(),
393 NULL,
394 false); // Can not deoptimize.
395 }
369 instr->set_computation(load); 396 instr->set_computation(load);
370 RemovePushArguments(comp); 397 RemovePushArguments(comp);
371 return true; 398 return true;
372 } 399 }
373 400
374 // Not an implicit getter. 401 // Not an implicit getter.
375 MethodRecognizer::Kind recognized_kind = 402 MethodRecognizer::Kind recognized_kind =
376 MethodRecognizer::RecognizeKind(target); 403 MethodRecognizer::RecognizeKind(target);
377 404
378 // VM objects length getter. 405 // VM objects length getter.
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 } 509 }
483 if ((op_kind == Token::kSET) && TryInlineInstanceSetter(instr, comp)) { 510 if ((op_kind == Token::kSET) && TryInlineInstanceSetter(instr, comp)) {
484 return; 511 return;
485 } 512 }
486 if (TryInlineInstanceMethod(instr, comp)) { 513 if (TryInlineInstanceMethod(instr, comp)) {
487 return; 514 return;
488 } 515 }
489 const intptr_t kMaxChecks = 4; 516 const intptr_t kMaxChecks = 4;
490 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) { 517 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) {
491 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); 518 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp);
492 ICData& unary_checks = 519 const ICData& unary_checks =
493 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); 520 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
494 call->set_ic_data(&unary_checks); 521 call->set_ic_data(&unary_checks);
495 instr->set_computation(call); 522 instr->set_computation(call);
496 } 523 }
497 } 524 }
498 // An instance call without ICData should continue calling via IC calls 525 // An instance call without ICData should continue calling via IC calls
499 // which should trigger reoptimization of optimized code. 526 // which should trigger reoptimization of optimized code.
500 } 527 }
501 528
502 529
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 888 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
862 LocationSummary* locs = it.Current()->locs(); 889 LocationSummary* locs = it.Current()->locs();
863 if ((locs != NULL) && locs->can_call()) { 890 if ((locs != NULL) && locs->can_call()) {
864 is_leaf_ = false; 891 is_leaf_ = false;
865 return; 892 return;
866 } 893 }
867 } 894 }
868 } 895 }
869 } 896 }
870 897
898
899 void LocalCSE::Optimize() {
900 for (intptr_t i = 0; i < blocks_.length(); ++i) {
901 BlockEntryInstr* entry = blocks_[i];
902 DirectChainedHashMap<BindInstr*> map;
903 ASSERT(map.IsEmpty());
904 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
905 BindInstr* instr = it.Current()->AsBind();
906 if (instr == NULL || instr->computation()->HasSideEffect()) continue;
907 BindInstr* result = map.Lookup(instr);
908 if (result == NULL) {
909 map.Insert(instr);
910 continue;
911 }
912 // Replace current with lookup result.
913 instr->ReplaceUsesWith(result);
914 it.RemoveCurrentFromGraph();
915 if (FLAG_trace_optimization) {
916 OS::Print("Replacing v%d with v%d\n",
917 instr->ssa_temp_index(),
918 result->ssa_temp_index());
919 }
920 }
921 }
922 }
923
924
871 } // namespace dart 925 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/hash_map.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698