| 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/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 } | 154 } |
| 155 } | 155 } |
| 156 | 156 |
| 157 | 157 |
| 158 // TODO(srdjan): Test/support other number types as well. | 158 // TODO(srdjan): Test/support other number types as well. |
| 159 static bool IsNumberCid(intptr_t cid) { | 159 static bool IsNumberCid(intptr_t cid) { |
| 160 return (cid == kSmiCid) || (cid == kDoubleCid); | 160 return (cid == kSmiCid) || (cid == kDoubleCid); |
| 161 } | 161 } |
| 162 | 162 |
| 163 | 163 |
| 164 // Attempt to build ICData for call using propagated class-ids. | |
| 165 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { | 164 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { |
| 166 ASSERT(call->HasICData()); | 165 ASSERT(call->HasICData()); |
| 167 if (call->ic_data()->NumberOfChecks() > 0) { | 166 if (call->ic_data()->NumberOfUsedChecks() > 0) { |
| 168 // This occurs when an instance call has too many checks, will be converted | 167 // This occurs when an instance call has too many checks, will be converted |
| 169 // to megamorphic call. | 168 // to megamorphic call. |
| 170 return false; | 169 return false; |
| 171 } | 170 } |
| 172 if (FLAG_warn_on_javascript_compatibility) { | 171 if (FLAG_warn_on_javascript_compatibility) { |
| 173 // Do not make the instance call megamorphic if the callee needs to decode | 172 // Do not make the instance call megamorphic if the callee needs to decode |
| 174 // the calling code sequence to lookup the ic data and verify if a warning | 173 // the calling code sequence to lookup the ic data and verify if a warning |
| 175 // has already been issued or not. | 174 // has already been issued or not. |
| 176 // TryCreateICData is only invoked if the ic_data target has not been called | 175 // TryCreateICData is only invoked if the ic_data target has not been called |
| 177 // yet, so no warning can possibly have been issued. | 176 // yet, so no warning can possibly have been issued. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 197 const intptr_t cid_0 = class_ids[0]; | 196 const intptr_t cid_0 = class_ids[0]; |
| 198 const intptr_t cid_1 = class_ids[1]; | 197 const intptr_t cid_1 = class_ids[1]; |
| 199 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) { | 198 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) { |
| 200 class_ids[0] = cid_1; | 199 class_ids[0] = cid_1; |
| 201 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) { | 200 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) { |
| 202 class_ids[1] = cid_0; | 201 class_ids[1] = cid_0; |
| 203 } | 202 } |
| 204 } | 203 } |
| 205 } | 204 } |
| 206 | 205 |
| 207 bool all_cids_known = true; | |
| 208 for (intptr_t i = 0; i < class_ids.length(); i++) { | 206 for (intptr_t i = 0; i < class_ids.length(); i++) { |
| 209 if (class_ids[i] == kDynamicCid) { | 207 if (class_ids[i] == kDynamicCid) { |
| 210 // Not all cid-s known. | 208 // Not all cid-s known. |
| 211 all_cids_known = false; | 209 return false; |
| 212 break; | |
| 213 } | 210 } |
| 214 } | 211 } |
| 215 | 212 |
| 216 if (all_cids_known) { | 213 const Array& args_desc_array = Array::Handle(Z, |
| 217 const Array& args_desc_array = Array::Handle(Z, | 214 ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names())); |
| 218 ArgumentsDescriptor::New(call->ArgumentCount(), | 215 ArgumentsDescriptor args_desc(args_desc_array); |
| 219 call->argument_names())); | 216 const Class& receiver_class = Class::Handle(Z, |
| 220 ArgumentsDescriptor args_desc(args_desc_array); | 217 isolate()->class_table()->At(class_ids[0])); |
| 221 const Class& receiver_class = Class::Handle(Z, | 218 const Function& function = Function::Handle(Z, |
| 222 isolate()->class_table()->At(class_ids[0])); | 219 Resolver::ResolveDynamicForReceiverClass( |
| 223 const Function& function = Function::Handle(Z, | 220 receiver_class, |
| 224 Resolver::ResolveDynamicForReceiverClass( | 221 call->function_name(), |
| 225 receiver_class, | 222 args_desc)); |
| 226 call->function_name(), | 223 if (function.IsNull()) { |
| 227 args_desc)); | 224 return false; |
| 228 if (function.IsNull()) { | |
| 229 return false; | |
| 230 } | |
| 231 if (class_ids.length() > 1) { | |
| 232 call->ic_data()->AddCheck(class_ids, function); | |
| 233 } else { | |
| 234 ASSERT(class_ids.length() == 1); | |
| 235 call->ic_data()->AddReceiverCheck(class_ids[0], function); | |
| 236 } | |
| 237 return true; | |
| 238 } | 225 } |
| 239 | 226 // Create new ICData, do not modify the one attached to the instruction |
| 240 // Check if getter or setter | 227 // since it is attached to the assembly instruction itself. |
| 241 if ((call->token_kind() == Token::kGET) || | 228 // TODO(srdjan): Prevent modification of ICData object that is |
| 242 (call->token_kind() == Token::kSET)) { | 229 // referenced in assembly code. |
| 243 const Class& owner_class = Class::Handle(Z, function().Owner()); | 230 ICData& ic_data = ICData::ZoneHandle(Z, ICData::New( |
| 244 if (!owner_class.is_abstract() && | 231 flow_graph_->function(), |
| 245 !CHA::HasSubclasses(owner_class) && | 232 call->function_name(), |
| 246 !CHA::IsImplemented(owner_class)) { | 233 args_desc_array, |
| 247 // Quite aggressive: if functions's owner has a a getter/setter of that | 234 call->deopt_id(), |
| 248 // name we add a check and call the setter directly. Considerable | 235 class_ids.length())); |
| 249 // performance improvement, some increase in code space. | 236 if (class_ids.length() > 1) { |
| 250 // TODO(srdjan): Make sure the getter/setters can be inlined. | 237 ic_data.AddCheck(class_ids, function); |
| 251 const Array& args_desc_array = Array::Handle(Z, | 238 } else { |
| 252 ArgumentsDescriptor::New(call->ArgumentCount(), | 239 ASSERT(class_ids.length() == 1); |
| 253 call->argument_names())); | 240 ic_data.AddReceiverCheck(class_ids[0], function); |
| 254 ArgumentsDescriptor args_desc(args_desc_array); | |
| 255 const Function& function = Function::Handle(Z, | |
| 256 Resolver::ResolveDynamicForReceiverClass(owner_class, | |
| 257 call->function_name(), | |
| 258 args_desc)); | |
| 259 if (!function.IsNull()) { | |
| 260 call->ic_data()->AddReceiverCheck(owner_class.id(), function); | |
| 261 return true; | |
| 262 } | |
| 263 } | |
| 264 } | 241 } |
| 265 | 242 call->set_ic_data(&ic_data); |
| 266 return false; | 243 return true; |
| 267 } | 244 } |
| 268 | 245 |
| 269 | 246 |
| 270 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, | 247 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, |
| 271 intptr_t cid) { | 248 intptr_t cid) { |
| 272 ASSERT(ic_data.NumArgsTested() == 1); | 249 ASSERT(ic_data.NumArgsTested() == 1); |
| 273 | 250 |
| 274 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) { | 251 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) { |
| 275 return ic_data; // Nothing to do | 252 return ic_data; // Nothing to do |
| 276 } | 253 } |
| (...skipping 8444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8721 | 8698 |
| 8722 // Insert materializations at environment uses. | 8699 // Insert materializations at environment uses. |
| 8723 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8700 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 8724 CreateMaterializationAt( | 8701 CreateMaterializationAt( |
| 8725 exits_collector_.exits()[i], alloc, *slots); | 8702 exits_collector_.exits()[i], alloc, *slots); |
| 8726 } | 8703 } |
| 8727 } | 8704 } |
| 8728 | 8705 |
| 8729 | 8706 |
| 8730 } // namespace dart | 8707 } // namespace dart |
| OLD | NEW |