| 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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 } | 160 } |
| 161 | 161 |
| 162 | 162 |
| 163 // TODO(srdjan): Test/support other number types as well. | 163 // TODO(srdjan): Test/support other number types as well. |
| 164 static bool IsNumberCid(intptr_t cid) { | 164 static bool IsNumberCid(intptr_t cid) { |
| 165 return (cid == kSmiCid) || (cid == kDoubleCid); | 165 return (cid == kSmiCid) || (cid == kDoubleCid); |
| 166 } | 166 } |
| 167 | 167 |
| 168 | 168 |
| 169 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { | 169 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { |
| 170 // TODO(srdjan): Investigate failures in: | |
| 171 // corelib/big_integer_arith_vm_test | |
| 172 // dart2js/members_test | |
| 173 // language/try_catch_optimized1_test | |
| 174 ASSERT(call->HasICData()); | 170 ASSERT(call->HasICData()); |
| 175 if (call->ic_data()->NumberOfUsedChecks() > 0) { | 171 if (call->ic_data()->NumberOfUsedChecks() > 0) { |
| 176 // This occurs when an instance call has too many checks, will be converted | 172 // This occurs when an instance call has too many checks, will be converted |
| 177 // to megamorphic call. | 173 // to megamorphic call. |
| 178 return false; | 174 return false; |
| 179 } | 175 } |
| 180 if (FLAG_warn_on_javascript_compatibility) { | 176 if (FLAG_warn_on_javascript_compatibility) { |
| 181 // Do not make the instance call megamorphic if the callee needs to decode | 177 // Do not make the instance call megamorphic if the callee needs to decode |
| 182 // the calling code sequence to lookup the ic data and verify if a warning | 178 // the calling code sequence to lookup the ic data and verify if a warning |
| 183 // has already been issued or not. | 179 // has already been issued or not. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 207 const intptr_t cid_0 = class_ids[0]; | 203 const intptr_t cid_0 = class_ids[0]; |
| 208 const intptr_t cid_1 = class_ids[1]; | 204 const intptr_t cid_1 = class_ids[1]; |
| 209 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) { | 205 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) { |
| 210 class_ids[0] = cid_1; | 206 class_ids[0] = cid_1; |
| 211 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) { | 207 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) { |
| 212 class_ids[1] = cid_0; | 208 class_ids[1] = cid_0; |
| 213 } | 209 } |
| 214 } | 210 } |
| 215 } | 211 } |
| 216 | 212 |
| 213 bool all_cids_known = true; |
| 217 for (intptr_t i = 0; i < class_ids.length(); i++) { | 214 for (intptr_t i = 0; i < class_ids.length(); i++) { |
| 218 if (class_ids[i] == kDynamicCid) { | 215 if (class_ids[i] == kDynamicCid) { |
| 219 // Not all cid-s known. | 216 // Not all cid-s known. |
| 220 return false; | 217 all_cids_known = false; |
| 218 break; |
| 221 } | 219 } |
| 222 } | 220 } |
| 223 | 221 |
| 224 const Array& args_desc_array = Array::Handle(Z, | 222 if (all_cids_known) { |
| 225 ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names())); | 223 const Array& args_desc_array = Array::Handle(Z, |
| 226 ArgumentsDescriptor args_desc(args_desc_array); | 224 ArgumentsDescriptor::New(call->ArgumentCount(), |
| 227 const Class& receiver_class = Class::Handle(Z, | 225 call->argument_names())); |
| 228 isolate()->class_table()->At(class_ids[0])); | 226 ArgumentsDescriptor args_desc(args_desc_array); |
| 229 const Function& function = Function::Handle(Z, | 227 const Class& receiver_class = Class::Handle(Z, |
| 230 Resolver::ResolveDynamicForReceiverClass( | 228 isolate()->class_table()->At(class_ids[0])); |
| 231 receiver_class, | 229 const Function& function = Function::Handle(Z, |
| 232 call->function_name(), | 230 Resolver::ResolveDynamicForReceiverClass( |
| 233 args_desc)); | 231 receiver_class, |
| 234 if (function.IsNull()) { | 232 call->function_name(), |
| 235 return false; | 233 args_desc)); |
| 234 if (function.IsNull()) { |
| 235 return false; |
| 236 } |
| 237 |
| 238 // Create new ICData, do not modify the one attached to the instruction |
| 239 // since it is attached to the assembly instruction itself. |
| 240 // TODO(srdjan): Prevent modification of ICData object that is |
| 241 // referenced in assembly code. |
| 242 const ICData& ic_data = ICData::ZoneHandle(Z, |
| 243 ICData::NewFrom(*call->ic_data(), class_ids.length())); |
| 244 if (class_ids.length() > 1) { |
| 245 ic_data.AddCheck(class_ids, function); |
| 246 } else { |
| 247 ASSERT(class_ids.length() == 1); |
| 248 ic_data.AddReceiverCheck(class_ids[0], function); |
| 249 } |
| 250 call->set_ic_data(&ic_data); |
| 251 return true; |
| 236 } | 252 } |
| 237 // Create new ICData, do not modify the one attached to the instruction | 253 |
| 238 // since it is attached to the assembly instruction itself. | 254 // Check if getter or setter in function's class and class is currently leaf. |
| 239 // TODO(srdjan): Prevent modification of ICData object that is | 255 if ((call->token_kind() == Token::kGET) || |
| 240 // referenced in assembly code. | 256 (call->token_kind() == Token::kSET)) { |
| 241 ICData& ic_data = ICData::ZoneHandle(Z, ICData::New( | 257 const Class& owner_class = Class::Handle(Z, function().Owner()); |
| 242 flow_graph_->function(), | 258 if (!owner_class.is_abstract() && |
| 243 call->function_name(), | 259 !CHA::HasSubclasses(owner_class) && |
| 244 args_desc_array, | 260 !CHA::IsImplemented(owner_class)) { |
| 245 call->deopt_id(), | 261 const Array& args_desc_array = Array::Handle(Z, |
| 246 class_ids.length())); | 262 ArgumentsDescriptor::New(call->ArgumentCount(), |
| 247 if (class_ids.length() > 1) { | 263 call->argument_names())); |
| 248 ic_data.AddCheck(class_ids, function); | 264 ArgumentsDescriptor args_desc(args_desc_array); |
| 249 } else { | 265 const Function& function = Function::Handle(Z, |
| 250 ASSERT(class_ids.length() == 1); | 266 Resolver::ResolveDynamicForReceiverClass(owner_class, |
| 251 ic_data.AddReceiverCheck(class_ids[0], function); | 267 call->function_name(), |
| 268 args_desc)); |
| 269 if (function.IsNull()) { |
| 270 return false; |
| 271 } |
| 272 const ICData& ic_data = ICData::ZoneHandle(Z, |
| 273 ICData::NewFrom(*call->ic_data(), class_ids.length())); |
| 274 ic_data.AddReceiverCheck(owner_class.id(), function); |
| 275 call->set_ic_data(&ic_data); |
| 276 return true; |
| 277 } |
| 252 } | 278 } |
| 253 call->set_ic_data(&ic_data); | 279 |
| 254 return true; | 280 return false; |
| 255 } | 281 } |
| 256 | 282 |
| 257 | 283 |
| 258 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, | 284 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, |
| 259 intptr_t cid) { | 285 intptr_t cid) { |
| 260 ASSERT(ic_data.NumArgsTested() == 1); | 286 ASSERT(ic_data.NumArgsTested() == 1); |
| 261 | 287 |
| 262 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) { | 288 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) { |
| 263 return ic_data; // Nothing to do | 289 return ic_data; // Nothing to do |
| 264 } | 290 } |
| (...skipping 8444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8709 | 8735 |
| 8710 // Insert materializations at environment uses. | 8736 // Insert materializations at environment uses. |
| 8711 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8737 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 8712 CreateMaterializationAt( | 8738 CreateMaterializationAt( |
| 8713 exits_collector_.exits()[i], alloc, *slots); | 8739 exits_collector_.exits()[i], alloc, *slots); |
| 8714 } | 8740 } |
| 8715 } | 8741 } |
| 8716 | 8742 |
| 8717 | 8743 |
| 8718 } // namespace dart | 8744 } // namespace dart |
| OLD | NEW |