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

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
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(
371 field, comp->ArgumentAt(0)->value(), comp);
372 load->set_ic_data(comp->ic_data());
373 } else {
srdjan 2012/08/17 22:30:22 The code below is probably going to be quite commo
Florian Schneider 2012/08/20 12:09:37 Yes, this will be similar for inserting other chec
374 CheckClassComp* check =
375 new CheckClassComp(comp->ArgumentAt(0)->value(), comp);
srdjan 2012/08/17 22:30:22 You may want to check if the CheckClassComp is nee
Florian Schneider 2012/08/20 12:09:37 I'll add a TODO. The only thing required for that
376 const ICData& unary_checks =
377 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
378 check->set_ic_data(&unary_checks);
379 BindInstr* check_instr = new BindInstr(BindInstr::kUnused, check);
380 ASSERT(instr->env() != NULL); // Always the case with SSA.
381 check_instr->set_env(
382 new Environment(instr->env()->values(),
383 instr->env()->fixed_parameter_count()));
384 check_instr->InsertBefore(instr);
385 load = new LoadInstanceFieldComp(
386 field, comp->ArgumentAt(0)->value(), NULL);
387 }
369 instr->set_computation(load); 388 instr->set_computation(load);
370 RemovePushArguments(comp); 389 RemovePushArguments(comp);
371 return true; 390 return true;
372 } 391 }
373 392
374 // Not an implicit getter. 393 // Not an implicit getter.
375 MethodRecognizer::Kind recognized_kind = 394 MethodRecognizer::Kind recognized_kind =
376 MethodRecognizer::RecognizeKind(target); 395 MethodRecognizer::RecognizeKind(target);
377 396
378 // VM objects length getter. 397 // VM objects length getter.
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 } 501 }
483 if ((op_kind == Token::kSET) && TryInlineInstanceSetter(instr, comp)) { 502 if ((op_kind == Token::kSET) && TryInlineInstanceSetter(instr, comp)) {
484 return; 503 return;
485 } 504 }
486 if (TryInlineInstanceMethod(instr, comp)) { 505 if (TryInlineInstanceMethod(instr, comp)) {
487 return; 506 return;
488 } 507 }
489 const intptr_t kMaxChecks = 4; 508 const intptr_t kMaxChecks = 4;
490 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) { 509 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) {
491 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); 510 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp);
492 ICData& unary_checks = 511 const ICData& unary_checks =
493 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); 512 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
494 call->set_ic_data(&unary_checks); 513 call->set_ic_data(&unary_checks);
495 instr->set_computation(call); 514 instr->set_computation(call);
496 } 515 }
497 } 516 }
498 // An instance call without ICData should continue calling via IC calls 517 // An instance call without ICData should continue calling via IC calls
499 // which should trigger reoptimization of optimized code. 518 // which should trigger reoptimization of optimized code.
500 } 519 }
501 520
502 521
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 880 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
862 LocationSummary* locs = it.Current()->locs(); 881 LocationSummary* locs = it.Current()->locs();
863 if ((locs != NULL) && locs->can_call()) { 882 if ((locs != NULL) && locs->can_call()) {
864 is_leaf_ = false; 883 is_leaf_ = false;
865 return; 884 return;
866 } 885 }
867 } 886 }
868 } 887 }
869 } 888 }
870 889
890
891 void LocalCSE::Optimize() {
892 for (intptr_t i = 0; i < blocks_.length(); ++i) {
893 BlockEntryInstr* entry = blocks_[i];
894 DirectChainedHashMap<BindInstr> map;
895 ASSERT(map.IsEmpty());
896 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
897 BindInstr* instr = it.Current()->AsBind();
898 if (instr == NULL || instr->computation()->HasSideEffect()) continue;
899 BindInstr* result = map.Lookup(instr);
900 if (result == NULL) {
901 map.Insert(instr);
902 continue;
903 }
904 // Replace current with lookup result.
905 instr->ReplaceUsesWith(result);
906 it.RemoveCurrentFromGraph();
907 if (FLAG_trace_optimization) {
908 OS::Print("Replacing v%d with v%d\n",
909 instr->ssa_temp_index(),
910 result->ssa_temp_index());
911 }
912 }
913 }
914 }
915
916
871 } // namespace dart 917 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698