| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 return FLAG_enable_simd_inline; | 55 return FLAG_enable_simd_inline; |
| 56 } | 56 } |
| 57 | 57 |
| 58 | 58 |
| 59 // Optimize instance calls using ICData. | 59 // Optimize instance calls using ICData. |
| 60 void FlowGraphOptimizer::ApplyICData() { | 60 void FlowGraphOptimizer::ApplyICData() { |
| 61 VisitBlocks(); | 61 VisitBlocks(); |
| 62 } | 62 } |
| 63 | 63 |
| 64 | 64 |
| 65 // Optimize instance calls using cid. This is called after the optimizer which | 65 // Optimize instance calls using cid. |
| 66 // converts instance calls to instructions has been run. Any remaining | |
| 67 // instance calls probably do not have IC data. | |
| 68 // Attempts to convert an instance call (IC call) using propagated class-ids, | 66 // Attempts to convert an instance call (IC call) using propagated class-ids, |
| 69 // e.g., receiver class id, guarded-cid. | 67 // e.g., receiver class id, guarded-cid. |
| 70 void FlowGraphOptimizer::ApplyClassIds() { | 68 void FlowGraphOptimizer::ApplyClassIds() { |
| 71 ASSERT(current_iterator_ == NULL); | 69 ASSERT(current_iterator_ == NULL); |
| 72 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 70 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 73 BlockEntryInstr* entry = block_order_[i]; | 71 BlockEntryInstr* entry = block_order_[i]; |
| 74 ForwardInstructionIterator it(entry); | 72 ForwardInstructionIterator it(entry); |
| 75 current_iterator_ = ⁢ | 73 current_iterator_ = ⁢ |
| 76 for (; !it.Done(); it.Advance()) { | 74 for (; !it.Done(); it.Advance()) { |
| 77 Instruction* instr = it.Current(); | 75 Instruction* instr = it.Current(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 91 if (compare->IsStrictCompare()) { | 89 if (compare->IsStrictCompare()) { |
| 92 VisitStrictCompare(compare->AsStrictCompare()); | 90 VisitStrictCompare(compare->AsStrictCompare()); |
| 93 } | 91 } |
| 94 } | 92 } |
| 95 } | 93 } |
| 96 current_iterator_ = NULL; | 94 current_iterator_ = NULL; |
| 97 } | 95 } |
| 98 } | 96 } |
| 99 | 97 |
| 100 | 98 |
| 101 // TODO(srdjan): write tests for others. | |
| 102 static bool IsNumberCid(intptr_t cid) { | |
| 103 return (cid == kSmiCid) || (cid == kDoubleCid); | |
| 104 } | |
| 105 | |
| 106 static bool NoneIsDynamic(const GrowableArray<intptr_t>& cids) { | |
| 107 for (intptr_t i = 0; i < cids.length(); i++) { | |
| 108 if (cids[i] == kDynamicCid) { | |
| 109 return false; | |
| 110 } | |
| 111 } | |
| 112 return true; | |
| 113 } | |
| 114 | |
| 115 | |
| 116 // Attempt to build ICData for call using propagated class-ids. | 99 // Attempt to build ICData for call using propagated class-ids. |
| 117 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { | 100 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { |
| 118 ASSERT(call->HasICData()); | 101 ASSERT(call->HasICData()); |
| 119 if (call->ic_data()->NumberOfChecks() > 0) { | 102 if (call->ic_data()->NumberOfChecks() > 0) { |
| 120 // This occurs when an instance call has too many checks, will be | 103 // This occurs when an instance call has too many checks. |
| 121 // converted to megamorphic calls. | 104 // TODO(srdjan): Replace IC call with megamorphic call. |
| 122 return false; | 105 return false; |
| 123 } | 106 } |
| 124 // Empty IC data. | |
| 125 GrowableArray<intptr_t> class_ids(call->ic_data()->num_args_tested()); | 107 GrowableArray<intptr_t> class_ids(call->ic_data()->num_args_tested()); |
| 126 ASSERT(call->ic_data()->num_args_tested() <= call->ArgumentCount()); | 108 ASSERT(call->ic_data()->num_args_tested() <= call->ArgumentCount()); |
| 127 for (intptr_t i = 0; i < call->ic_data()->num_args_tested(); i++) { | 109 for (intptr_t i = 0; i < call->ic_data()->num_args_tested(); i++) { |
| 128 const intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid(); | 110 intptr_t cid = call->PushArgumentAt(i)->value()->Type()->ToCid(); |
| 129 class_ids.Add(cid); | 111 class_ids.Add(cid); |
| 130 } | 112 } |
| 131 // We guess that comparison and binary operations typically | 113 if (class_ids[0] != kDynamicCid) { |
| 132 // have both arguments of the same cid. If only one argument's cid is known, | |
| 133 // assume the other argument has the same cid. | |
| 134 const Token::Kind op_kind = call->token_kind(); | |
| 135 if (Token::IsRelationalOperator(op_kind) || | |
| 136 Token::IsEqualityOperator(op_kind) || | |
| 137 Token::IsBinaryOperator(op_kind)) { | |
| 138 // If left or right is a number -> make the other a number as well. | |
| 139 const intptr_t cid_0 = class_ids[0]; | |
| 140 const intptr_t cid_1 = class_ids[1]; | |
| 141 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) { | |
| 142 class_ids[0] = cid_1; | |
| 143 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) { | |
| 144 class_ids[1] = cid_0; | |
| 145 } | |
| 146 } | |
| 147 if (NoneIsDynamic(class_ids)) { | |
| 148 ArgumentsDescriptor args_desc( | 114 ArgumentsDescriptor args_desc( |
| 149 Array::Handle(ArgumentsDescriptor::New(call->ArgumentCount(), | 115 Array::Handle(ArgumentsDescriptor::New(call->ArgumentCount(), |
| 150 call->argument_names()))); | 116 call->argument_names()))); |
| 151 const Class& receiver_class = Class::Handle( | 117 const Class& receiver_class = Class::Handle( |
| 152 Isolate::Current()->class_table()->At(class_ids[0])); | 118 Isolate::Current()->class_table()->At(class_ids[0])); |
| 153 const Function& function = Function::Handle( | 119 const Function& function = Function::Handle( |
| 154 Resolver::ResolveDynamicForReceiverClass( | 120 Resolver::ResolveDynamicForReceiverClass( |
| 155 receiver_class, | 121 receiver_class, |
| 156 call->function_name(), | 122 call->function_name(), |
| 157 args_desc)); | 123 args_desc)); |
| 158 if (function.IsNull()) { | 124 if (function.IsNull()) { |
| 159 return false; | 125 return false; |
| 160 } | 126 } |
| 161 | 127 // Create new ICData, do not modify the one attached to the instruction |
| 128 // since it is attached to the assembly instruction itself. |
| 129 // TODO(srdjan): Prevent modification of ICData object that is |
| 130 // referenced in assembly code. |
| 162 ICData& ic_data = ICData::ZoneHandle(ICData::New( | 131 ICData& ic_data = ICData::ZoneHandle(ICData::New( |
| 163 flow_graph_->parsed_function().function(), | 132 flow_graph_->parsed_function().function(), |
| 164 call->function_name(), | 133 call->function_name(), |
| 165 Object::empty_array(), // Dummy argument descriptor. | 134 Object::empty_array(), // Dummy argument descriptor. |
| 166 call->deopt_id(), | 135 call->deopt_id(), |
| 167 class_ids.length())); | 136 class_ids.length())); |
| 168 if (class_ids.length() > 1) { | 137 if (class_ids.length() > 1) { |
| 169 ic_data.AddCheck(class_ids, function); | 138 ic_data.AddCheck(class_ids, function); |
| 170 } else { | 139 } else { |
| 171 ASSERT(class_ids.length() == 1); | 140 ASSERT(class_ids.length() == 1); |
| (...skipping 6758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6930 SetValue(instr, non_constant_); | 6899 SetValue(instr, non_constant_); |
| 6931 } | 6900 } |
| 6932 | 6901 |
| 6933 | 6902 |
| 6934 void ConstantPropagator::VisitUnboxInteger(UnboxIntegerInstr* instr) { | 6903 void ConstantPropagator::VisitUnboxInteger(UnboxIntegerInstr* instr) { |
| 6935 // TODO(kmillikin): Handle unbox operation. | 6904 // TODO(kmillikin): Handle unbox operation. |
| 6936 SetValue(instr, non_constant_); | 6905 SetValue(instr, non_constant_); |
| 6937 } | 6906 } |
| 6938 | 6907 |
| 6939 | 6908 |
| 6940 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { | 6909 void ConstantPropagator::VisitBinaryMintOp( |
| 6910 BinaryMintOpInstr* instr) { |
| 6941 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | 6911 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); |
| 6942 } | 6912 } |
| 6943 | 6913 |
| 6944 | 6914 |
| 6945 void ConstantPropagator::VisitShiftMintOp(ShiftMintOpInstr* instr) { | 6915 void ConstantPropagator::VisitShiftMintOp( |
| 6916 ShiftMintOpInstr* instr) { |
| 6946 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | 6917 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); |
| 6947 } | 6918 } |
| 6948 | 6919 |
| 6949 | 6920 |
| 6950 void ConstantPropagator::VisitUnaryMintOp(UnaryMintOpInstr* instr) { | 6921 void ConstantPropagator::VisitUnaryMintOp( |
| 6922 UnaryMintOpInstr* instr) { |
| 6951 // TODO(kmillikin): Handle unary operations. | 6923 // TODO(kmillikin): Handle unary operations. |
| 6952 SetValue(instr, non_constant_); | 6924 SetValue(instr, non_constant_); |
| 6953 } | 6925 } |
| 6954 | 6926 |
| 6955 | 6927 |
| 6956 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { | 6928 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { |
| 6957 const Object& value = instr->value()->definition()->constant_value(); | 6929 const Object& value = instr->value()->definition()->constant_value(); |
| 6958 if (IsNonConstant(value)) { | 6930 if (IsNonConstant(value)) { |
| 6959 SetValue(instr, non_constant_); | 6931 SetValue(instr, non_constant_); |
| 6960 } else if (IsConstant(value)) { | 6932 } else if (IsConstant(value)) { |
| (...skipping 1113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8074 } | 8046 } |
| 8075 | 8047 |
| 8076 // Insert materializations at environment uses. | 8048 // Insert materializations at environment uses. |
| 8077 for (intptr_t i = 0; i < exits.length(); i++) { | 8049 for (intptr_t i = 0; i < exits.length(); i++) { |
| 8078 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 8050 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 8079 } | 8051 } |
| 8080 } | 8052 } |
| 8081 | 8053 |
| 8082 | 8054 |
| 8083 } // namespace dart | 8055 } // namespace dart |
| OLD | NEW |