| 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 10 matching lines...) Expand all Loading... |
| 21 #include "vm/precompiler.h" | 21 #include "vm/precompiler.h" |
| 22 #include "vm/resolver.h" | 22 #include "vm/resolver.h" |
| 23 #include "vm/scopes.h" | 23 #include "vm/scopes.h" |
| 24 #include "vm/stack_frame.h" | 24 #include "vm/stack_frame.h" |
| 25 #include "vm/symbols.h" | 25 #include "vm/symbols.h" |
| 26 | 26 |
| 27 namespace dart { | 27 namespace dart { |
| 28 | 28 |
| 29 DEFINE_FLAG(int, getter_setter_ratio, 13, | 29 DEFINE_FLAG(int, getter_setter_ratio, 13, |
| 30 "Ratio of getter/setter usage used for double field unboxing heuristics"); | 30 "Ratio of getter/setter usage used for double field unboxing heuristics"); |
| 31 DEFINE_FLAG(bool, guess_other_cid, true, | 31 DEFINE_FLAG(bool, guess_icdata_cid, true, |
| 32 "Artificially create type feedback for arithmetic etc. operations" | 32 "Artificially create type feedback for arithmetic etc. operations" |
| 33 " by guessing the other unknown argument cid"); | 33 " by guessing the other unknown argument cid"); |
| 34 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); | 34 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); |
| 35 DEFINE_FLAG(bool, dead_store_elimination, true, "Eliminate dead stores"); | 35 DEFINE_FLAG(bool, dead_store_elimination, true, "Eliminate dead stores"); |
| 36 DEFINE_FLAG(int, max_polymorphic_checks, 4, | 36 DEFINE_FLAG(int, max_polymorphic_checks, 4, |
| 37 "Maximum number of polymorphic check, otherwise it is megamorphic."); | 37 "Maximum number of polymorphic check, otherwise it is megamorphic."); |
| 38 DEFINE_FLAG(int, max_equality_polymorphic_checks, 32, | 38 DEFINE_FLAG(int, max_equality_polymorphic_checks, 32, |
| 39 "Maximum number of polymorphic checks in equality operator," | 39 "Maximum number of polymorphic checks in equality operator," |
| 40 " otherwise use megamorphic dispatch."); | 40 " otherwise use megamorphic dispatch."); |
| 41 DEFINE_FLAG(bool, merge_sin_cos, false, "Merge sin/cos into sincos"); | 41 DEFINE_FLAG(bool, merge_sin_cos, false, "Merge sin/cos into sincos"); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { | 189 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { |
| 190 class_ids.Add(call->PushArgumentAt(i)->value()->Type()->ToCid()); | 190 class_ids.Add(call->PushArgumentAt(i)->value()->Type()->ToCid()); |
| 191 } | 191 } |
| 192 | 192 |
| 193 const Token::Kind op_kind = call->token_kind(); | 193 const Token::Kind op_kind = call->token_kind(); |
| 194 if (Token::IsRelationalOperator(op_kind) || | 194 if (Token::IsRelationalOperator(op_kind) || |
| 195 Token::IsEqualityOperator(op_kind) || | 195 Token::IsEqualityOperator(op_kind) || |
| 196 Token::IsBinaryOperator(op_kind)) { | 196 Token::IsBinaryOperator(op_kind)) { |
| 197 // Guess cid: if one of the inputs is a number assume that the other | 197 // Guess cid: if one of the inputs is a number assume that the other |
| 198 // is a number of same type. | 198 // is a number of same type. |
| 199 if (FLAG_guess_other_cid) { | 199 if (FLAG_guess_icdata_cid) { |
| 200 const intptr_t cid_0 = class_ids[0]; | 200 const intptr_t cid_0 = class_ids[0]; |
| 201 const intptr_t cid_1 = class_ids[1]; | 201 const intptr_t cid_1 = class_ids[1]; |
| 202 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) { | 202 if ((cid_0 == kDynamicCid) && (IsNumberCid(cid_1))) { |
| 203 class_ids[0] = cid_1; | 203 class_ids[0] = cid_1; |
| 204 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) { | 204 } else if (IsNumberCid(cid_0) && (cid_1 == kDynamicCid)) { |
| 205 class_ids[1] = cid_0; | 205 class_ids[1] = cid_0; |
| 206 } | 206 } |
| 207 } | 207 } |
| 208 } | 208 } |
| 209 | 209 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 if (class_ids.length() > 1) { | 247 if (class_ids.length() > 1) { |
| 248 ic_data.AddCheck(class_ids, function); | 248 ic_data.AddCheck(class_ids, function); |
| 249 } else { | 249 } else { |
| 250 ASSERT(class_ids.length() == 1); | 250 ASSERT(class_ids.length() == 1); |
| 251 ic_data.AddReceiverCheck(class_ids[0], function); | 251 ic_data.AddReceiverCheck(class_ids[0], function); |
| 252 } | 252 } |
| 253 call->set_ic_data(&ic_data); | 253 call->set_ic_data(&ic_data); |
| 254 return true; | 254 return true; |
| 255 } | 255 } |
| 256 | 256 |
| 257 if (Compiler::always_optimize() && |
| 258 (isolate()->object_store()->unique_dynamic_targets() != Array::null())) { |
| 259 // Check if the target is unique. |
| 260 Function& target_function = Function::Handle(Z); |
| 261 Precompiler::GetUniqueDynamicTarget( |
| 262 isolate(), call->function_name(), &target_function); |
| 263 // Calls with named arguments must be resolved/checked at runtime. |
| 264 String& error_message = String::Handle(Z); |
| 265 if (!target_function.IsNull() && |
| 266 !target_function.HasOptionalNamedParameters() && |
| 267 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, |
| 268 &error_message)) { |
| 269 const intptr_t cid = Class::Handle(Z, target_function.Owner()).id(); |
| 270 const ICData& ic_data = ICData::ZoneHandle(Z, |
| 271 ICData::NewFrom(*call->ic_data(), 1)); |
| 272 ic_data.AddReceiverCheck(cid, target_function); |
| 273 call->set_ic_data(&ic_data); |
| 274 return true; |
| 275 } |
| 276 } |
| 277 |
| 257 // Check if getter or setter in function's class and class is currently leaf. | 278 // Check if getter or setter in function's class and class is currently leaf. |
| 258 if ((call->token_kind() == Token::kGET) || | 279 if (FLAG_guess_icdata_cid && |
| 259 (call->token_kind() == Token::kSET)) { | 280 ((call->token_kind() == Token::kGET) || |
| 281 (call->token_kind() == Token::kSET))) { |
| 260 const Class& owner_class = Class::Handle(Z, function().Owner()); | 282 const Class& owner_class = Class::Handle(Z, function().Owner()); |
| 261 if (!owner_class.is_abstract() && | 283 if (!owner_class.is_abstract() && |
| 262 !CHA::HasSubclasses(owner_class) && | 284 !CHA::HasSubclasses(owner_class) && |
| 263 !CHA::IsImplemented(owner_class)) { | 285 !CHA::IsImplemented(owner_class)) { |
| 264 const Array& args_desc_array = Array::Handle(Z, | 286 const Array& args_desc_array = Array::Handle(Z, |
| 265 ArgumentsDescriptor::New(call->ArgumentCount(), | 287 ArgumentsDescriptor::New(call->ArgumentCount(), |
| 266 call->argument_names())); | 288 call->argument_names())); |
| 267 ArgumentsDescriptor args_desc(args_desc_array); | 289 ArgumentsDescriptor args_desc(args_desc_array); |
| 268 const Function& function = Function::Handle(Z, | 290 const Function& function = Function::Handle(Z, |
| 269 Resolver::ResolveDynamicForReceiverClass(owner_class, | 291 Resolver::ResolveDynamicForReceiverClass(owner_class, |
| 270 call->function_name(), | 292 call->function_name(), |
| 271 args_desc)); | 293 args_desc)); |
| 272 if (!function.IsNull()) { | 294 if (!function.IsNull()) { |
| 273 const ICData& ic_data = ICData::ZoneHandle(Z, | 295 const ICData& ic_data = ICData::ZoneHandle(Z, |
| 274 ICData::NewFrom(*call->ic_data(), class_ids.length())); | 296 ICData::NewFrom(*call->ic_data(), class_ids.length())); |
| 275 ic_data.AddReceiverCheck(owner_class.id(), function); | 297 ic_data.AddReceiverCheck(owner_class.id(), function); |
| 276 call->set_ic_data(&ic_data); | 298 call->set_ic_data(&ic_data); |
| 277 return true; | 299 return true; |
| 278 } | 300 } |
| 279 } | 301 } |
| 280 } | 302 } |
| 281 | 303 |
| 282 if (FLAG_precompilation && | |
| 283 (isolate()->object_store()->unique_dynamic_targets() != Array::null())) { | |
| 284 // Check if the target is unique. | |
| 285 Function& target_function = Function::Handle(Z); | |
| 286 Precompiler::GetUniqueDynamicTarget( | |
| 287 isolate(), call->function_name(), &target_function); | |
| 288 // Calls with named arguments must be resolved/checked at runtime. | |
| 289 String& error_message = String::Handle(Z); | |
| 290 if (!target_function.IsNull() && | |
| 291 !target_function.HasOptionalNamedParameters() && | |
| 292 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, | |
| 293 &error_message)) { | |
| 294 const intptr_t cid = Class::Handle(Z, target_function.Owner()).id(); | |
| 295 const ICData& ic_data = ICData::ZoneHandle(Z, | |
| 296 ICData::NewFrom(*call->ic_data(), 1)); | |
| 297 ic_data.AddReceiverCheck(cid, target_function); | |
| 298 call->set_ic_data(&ic_data); | |
| 299 return true; | |
| 300 } | |
| 301 } | |
| 302 | |
| 303 return false; | 304 return false; |
| 304 } | 305 } |
| 305 | 306 |
| 306 | 307 |
| 307 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, | 308 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, |
| 308 intptr_t cid) { | 309 intptr_t cid) { |
| 309 ASSERT(ic_data.NumArgsTested() == 1); | 310 ASSERT(ic_data.NumArgsTested() == 1); |
| 310 | 311 |
| 311 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) { | 312 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) { |
| 312 return ic_data; // Nothing to do | 313 return ic_data; // Nothing to do |
| (...skipping 8540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8853 | 8854 |
| 8854 // Insert materializations at environment uses. | 8855 // Insert materializations at environment uses. |
| 8855 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8856 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 8856 CreateMaterializationAt( | 8857 CreateMaterializationAt( |
| 8857 exits_collector_.exits()[i], alloc, *slots); | 8858 exits_collector_.exits()[i], alloc, *slots); |
| 8858 } | 8859 } |
| 8859 } | 8860 } |
| 8860 | 8861 |
| 8861 | 8862 |
| 8862 } // namespace dart | 8863 } // namespace dart |
| OLD | NEW |