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/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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |