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

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

Issue 10933043: Use ICData to collect type feedback on instance setter value. If value is always Smi, insert a smi … (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
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 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 return false; 296 return false;
297 } 297 }
298 } 298 }
299 return true; 299 return true;
300 } 300 }
301 301
302 302
303 static intptr_t ReceiverClassId(InstanceCallInstr* call) { 303 static intptr_t ReceiverClassId(InstanceCallInstr* call) {
304 if (!call->HasICData()) return kIllegalCid; 304 if (!call->HasICData()) return kIllegalCid;
305 305
306 const ICData& ic_data = *call->ic_data(); 306 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks());
307 307
308 if (ic_data.NumberOfChecks() == 0) return kIllegalCid; 308 if (ic_data.NumberOfChecks() == 0) return kIllegalCid;
309 // TODO(vegorov): Add multiple receiver type support. 309 // TODO(vegorov): Add multiple receiver type support.
310 if (ic_data.NumberOfChecks() != 1) return kIllegalCid; 310 if (ic_data.NumberOfChecks() != 1) return kIllegalCid;
311 ASSERT(HasOneTarget(ic_data)); 311 ASSERT(HasOneTarget(ic_data));
312 312
313 Function& target = Function::Handle(); 313 Function& target = Function::Handle();
314 intptr_t class_id; 314 intptr_t class_id;
315 ic_data.GetOneClassCheckAt(0, &class_id, &target); 315 ic_data.GetOneClassCheckAt(0, &class_id, &target);
316 return class_id; 316 return class_id;
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 MethodRecognizer::Kind recognized_kind = 788 MethodRecognizer::Kind recognized_kind =
789 MethodRecognizer::RecognizeKind(call->function()); 789 MethodRecognizer::RecognizeKind(call->function());
790 if (recognized_kind == MethodRecognizer::kMathSqrt) { 790 if (recognized_kind == MethodRecognizer::kMathSqrt) {
791 MathSqrtInstr* sqrt = new MathSqrtInstr(call->ArgumentAt(0)->value(), call); 791 MathSqrtInstr* sqrt = new MathSqrtInstr(call->ArgumentAt(0)->value(), call);
792 call->ReplaceWith(sqrt, current_iterator()); 792 call->ReplaceWith(sqrt, current_iterator());
793 RemovePushArguments(call); 793 RemovePushArguments(call);
794 } 794 }
795 } 795 }
796 796
797 797
798 static bool ArgIsAlwaysSmi(const ICData& ic_data, intptr_t arg_n) {
799 ASSERT(ic_data.num_args_tested() > arg_n);
800 if (ic_data.NumberOfChecks() == 0) return false;
801 GrowableArray<intptr_t> class_ids;
802 Function& target = Function::Handle();
803 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
804 ic_data.GetCheckAt(i, &class_ids, &target);
805 if (class_ids[arg_n] != kSmiCid) return false;
806 }
807 return true;
808 }
809
810
798 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr) { 811 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr) {
799 if (FLAG_enable_type_checks) { 812 if (FLAG_enable_type_checks) {
800 // TODO(srdjan): Add assignable check node if --enable_type_checks. 813 // TODO(srdjan): Add assignable check node if --enable_type_checks.
801 return false; 814 return false;
802 } 815 }
803 816
804 ASSERT(instr->HasICData()); 817 ASSERT(instr->HasICData());
805 const ICData& ic_data = *instr->ic_data(); 818 const ICData& unary_ic_data =
806 if (ic_data.NumberOfChecks() == 0) { 819 ICData::Handle(instr->ic_data()->AsUnaryClassChecks());
820 if (unary_ic_data.NumberOfChecks() == 0) {
807 // No type feedback collected. 821 // No type feedback collected.
808 return false; 822 return false;
809 } 823 }
810 if (!HasOneTarget(ic_data)) { 824 if (!HasOneTarget(unary_ic_data)) {
811 // TODO(srdjan): Implement when not all targets are the same. 825 // TODO(srdjan): Implement when not all targets are the same.
812 return false; 826 return false;
813 } 827 }
814 Function& target = Function::Handle(); 828 Function& target = Function::Handle();
815 intptr_t class_id; 829 intptr_t class_id;
816 ic_data.GetOneClassCheckAt(0, &class_id, &target); 830 unary_ic_data.GetOneClassCheckAt(0, &class_id, &target);
817 if (target.kind() != RawFunction::kImplicitSetter) { 831 if (target.kind() != RawFunction::kImplicitSetter) {
818 // Not an implicit setter. 832 // Not an implicit setter.
819 // TODO(srdjan): Inline special setters. 833 // TODO(srdjan): Inline special setters.
820 return false; 834 return false;
821 } 835 }
822 // Inline implicit instance setter. 836 // Inline implicit instance setter.
823 const String& field_name = 837 const String& field_name =
824 String::Handle(Field::NameFromSetter(instr->function_name())); 838 String::Handle(Field::NameFromSetter(instr->function_name()));
825 const Field& field = Field::Handle(GetField(class_id, field_name)); 839 const Field& field = Field::Handle(GetField(class_id, field_name));
826 ASSERT(!field.IsNull()); 840 ASSERT(!field.IsNull());
827 841
828 if (InstanceCallNeedsClassCheck(instr)) { 842 if (InstanceCallNeedsClassCheck(instr)) {
829 AddCheckClass(instr, instr->ArgumentAt(0)->value()->Copy()); 843 AddCheckClass(instr, instr->ArgumentAt(0)->value()->Copy());
830 } 844 }
845 bool needs_store_barrier = true;
846 if (ArgIsAlwaysSmi(*instr->ic_data(), 1)) {
847 InsertBefore(instr,
848 new CheckSmiInstr(instr->ArgumentAt(1)->value()->Copy(),
849 instr->deopt_id()),
850 instr->env(),
851 Definition::kEffect);
852 needs_store_barrier = false;
853 }
831 // Detach environment from the original instruction because it can't 854 // Detach environment from the original instruction because it can't
832 // deoptimize. 855 // deoptimize.
833 instr->set_env(NULL); 856 instr->set_env(NULL);
834 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( 857 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr(
835 field, 858 field,
836 instr->ArgumentAt(0)->value(), 859 instr->ArgumentAt(0)->value(),
837 instr->ArgumentAt(1)->value()); 860 instr->ArgumentAt(1)->value());
861 store->set_may_need_store_barrier(needs_store_barrier);
838 instr->ReplaceWith(store, current_iterator()); 862 instr->ReplaceWith(store, current_iterator());
839 RemovePushArguments(instr); 863 RemovePushArguments(instr);
840 return true; 864 return true;
841 } 865 }
842 866
843 867
844 // TODO(fschneider): Once we get rid of the distinction between Instruction 868 // TODO(fschneider): Once we get rid of the distinction between Instruction
845 // and computation, this helper can go away. 869 // and computation, this helper can go away.
846 static void HandleRelationalOp(FlowGraphOptimizer* optimizer, 870 static void HandleRelationalOp(FlowGraphOptimizer* optimizer,
847 RelationalOpInstr* comp, 871 RelationalOpInstr* comp,
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after
1378 DirectChainedHashMap<Definition*> child_map(*map); // Copy map. 1402 DirectChainedHashMap<Definition*> child_map(*map); // Copy map.
1379 OptimizeRecursive(child, &child_map); 1403 OptimizeRecursive(child, &child_map);
1380 } else { 1404 } else {
1381 OptimizeRecursive(child, map); // Reuse map for the last child. 1405 OptimizeRecursive(child, map); // Reuse map for the last child.
1382 } 1406 }
1383 } 1407 }
1384 } 1408 }
1385 1409
1386 1410
1387 } // namespace dart 1411 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698