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

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

Issue 1867913004: Specialize instance calls when the call receiver is the method receiver and the method class has a … (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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
« no previous file with comments | « runtime/lib/string_patch.dart ('k') | runtime/vm/cha.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/aot_optimizer.h" 5 #include "vm/aot_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/branch_optimizer.h" 8 #include "vm/branch_optimizer.h"
9 #include "vm/cha.h" 9 #include "vm/cha.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 11 matching lines...) Expand all
22 #include "vm/object_store.h" 22 #include "vm/object_store.h"
23 #include "vm/parser.h" 23 #include "vm/parser.h"
24 #include "vm/precompiler.h" 24 #include "vm/precompiler.h"
25 #include "vm/resolver.h" 25 #include "vm/resolver.h"
26 #include "vm/scopes.h" 26 #include "vm/scopes.h"
27 #include "vm/stack_frame.h" 27 #include "vm/stack_frame.h"
28 #include "vm/symbols.h" 28 #include "vm/symbols.h"
29 29
30 namespace dart { 30 namespace dart {
31 31
32 DEFINE_FLAG(int, max_exhaustive_polymorphic_checks, 5,
33 "If a call receiver is known to be of at most this many classes, "
34 "generate exhaustive class tests instead of a megamorphic call");
35
32 // Quick access to the current isolate and zone. 36 // Quick access to the current isolate and zone.
33 #define I (isolate()) 37 #define I (isolate())
34 #define Z (zone()) 38 #define Z (zone())
35 39
36 static bool ShouldInlineSimd() { 40 static bool ShouldInlineSimd() {
37 return FlowGraphCompiler::SupportsUnboxedSimd128(); 41 return FlowGraphCompiler::SupportsUnboxedSimd128();
38 } 42 }
39 43
40 44
41 static bool CanUnboxDouble() { 45 static bool CanUnboxDouble() {
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 if (receiver_cid == kDynamicCid) { 278 if (receiver_cid == kDynamicCid) {
275 return; // No information about receiver was infered. 279 return; // No information about receiver was infered.
276 } 280 }
277 281
278 const ICData& ic_data = TrySpecializeICData(call->ic_data(), receiver_cid); 282 const ICData& ic_data = TrySpecializeICData(call->ic_data(), receiver_cid);
279 if (ic_data.raw() == call->ic_data().raw()) { 283 if (ic_data.raw() == call->ic_data().raw()) {
280 // No specialization. 284 // No specialization.
281 return; 285 return;
282 } 286 }
283 287
284 const bool with_checks = false;
285 PolymorphicInstanceCallInstr* specialized = 288 PolymorphicInstanceCallInstr* specialized =
286 new(Z) PolymorphicInstanceCallInstr(call->instance_call(), 289 new(Z) PolymorphicInstanceCallInstr(call->instance_call(),
287 ic_data, 290 ic_data,
288 with_checks); 291 /* with_checks = */ false,
292 /* complete = */ false);
289 call->ReplaceWith(specialized, current_iterator()); 293 call->ReplaceWith(specialized, current_iterator());
290 } 294 }
291 295
292 296
293 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) { 297 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) {
294 BinarySmiOpInstr* instr = d->AsBinarySmiOp(); 298 BinarySmiOpInstr* instr = d->AsBinarySmiOp();
295 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) { 299 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) {
296 return instr; 300 return instr;
297 } 301 }
298 return NULL; 302 return NULL;
(...skipping 2135 matching lines...) Expand 10 before | Expand all | Expand 10 after
2434 has_one_target = !polymorphic_target; 2438 has_one_target = !polymorphic_target;
2435 } 2439 }
2436 2440
2437 if (has_one_target) { 2441 if (has_one_target) {
2438 RawFunction::Kind function_kind = 2442 RawFunction::Kind function_kind =
2439 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind(); 2443 Function::Handle(Z, unary_checks.GetTargetAt(0)).kind();
2440 if (!flow_graph()->InstanceCallNeedsClassCheck( 2444 if (!flow_graph()->InstanceCallNeedsClassCheck(
2441 instr, function_kind)) { 2445 instr, function_kind)) {
2442 PolymorphicInstanceCallInstr* call = 2446 PolymorphicInstanceCallInstr* call =
2443 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, 2447 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
2444 /* with_checks = */ false); 2448 /* with_checks = */ false,
2449 /* complete = */ true);
2445 instr->ReplaceWith(call, current_iterator()); 2450 instr->ReplaceWith(call, current_iterator());
2446 return; 2451 return;
2447 } 2452 }
2448 } 2453 }
2449 switch (instr->token_kind()) { 2454 switch (instr->token_kind()) {
2450 case Token::kEQ: 2455 case Token::kEQ:
2451 case Token::kLT: 2456 case Token::kLT:
2452 case Token::kLTE: 2457 case Token::kLTE:
2453 case Token::kGT: 2458 case Token::kGT:
2454 case Token::kGTE: 2459 case Token::kGTE:
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2507 // Create fake IC data with the resolved target. 2512 // Create fake IC data with the resolved target.
2508 const ICData& ic_data = ICData::Handle( 2513 const ICData& ic_data = ICData::Handle(
2509 ICData::New(flow_graph_->function(), 2514 ICData::New(flow_graph_->function(),
2510 instr->function_name(), 2515 instr->function_name(),
2511 args_desc_array, 2516 args_desc_array,
2512 Thread::kNoDeoptId, 2517 Thread::kNoDeoptId,
2513 /* args_tested = */ 1)); 2518 /* args_tested = */ 1));
2514 ic_data.AddReceiverCheck(receiver_class.id(), function); 2519 ic_data.AddReceiverCheck(receiver_class.id(), function);
2515 PolymorphicInstanceCallInstr* call = 2520 PolymorphicInstanceCallInstr* call =
2516 new(Z) PolymorphicInstanceCallInstr(instr, ic_data, 2521 new(Z) PolymorphicInstanceCallInstr(instr, ic_data,
2517 /* with_checks = */ false); 2522 /* with_checks = */ false,
2523 /* complete = */ true);
2518 instr->ReplaceWith(call, current_iterator()); 2524 instr->ReplaceWith(call, current_iterator());
2519 return; 2525 return;
2520 } 2526 }
2521 } 2527 }
2522 } 2528 }
2523 2529
2530 Definition* callee_receiver = instr->ArgumentAt(0);
2531 const Function& function = flow_graph_->function();
2532 if (function.IsDynamicFunction() &&
2533 flow_graph_->IsReceiver(callee_receiver)) {
2534 // Call receiver is method receiver.
2535 Class& receiver_class = Class::Handle(Z, function.Owner());
2536 GrowableArray<intptr_t> class_ids(6);
2537 if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) {
2538 if (class_ids.length() <= FLAG_max_exhaustive_polymorphic_checks) {
2539 if (FLAG_trace_cha) {
2540 THR_Print(" **(CHA) Only %" Pd " concrete subclasses of %s for %s\n",
2541 class_ids.length(),
2542 receiver_class.ToCString(),
2543 instr->function_name().ToCString());
2544 }
2545
2546 const Array& args_desc_array = Array::Handle(Z,
2547 ArgumentsDescriptor::New(instr->ArgumentCount(),
2548 instr->argument_names()));
2549 ArgumentsDescriptor args_desc(args_desc_array);
2550
2551 const ICData& ic_data = ICData::Handle(
2552 ICData::New(function,
2553 instr->function_name(),
2554 args_desc_array,
2555 Thread::kNoDeoptId,
2556 /* args_tested = */ 1));
2557
2558 Function& target = Function::Handle(Z);
2559 Class& cls = Class::Handle(Z);
2560 bool includes_dispatcher_case = false;
2561 for (intptr_t i = 0; i < class_ids.length(); i++) {
2562 intptr_t cid = class_ids[i];
2563 cls = isolate()->class_table()->At(cid);
2564 target = Resolver::ResolveDynamicForReceiverClass(
2565 cls,
2566 instr->function_name(),
2567 args_desc);
2568 if (target.IsNull()) {
2569 // noSuchMethod, call through getter or closurization
2570 includes_dispatcher_case = true;
2571 } else {
2572 ic_data.AddReceiverCheck(cid, target);
2573 }
2574 }
2575 if (!includes_dispatcher_case && (ic_data.NumberOfChecks() > 0)) {
2576 PolymorphicInstanceCallInstr* call =
2577 new(Z) PolymorphicInstanceCallInstr(instr, ic_data,
2578 /* with_checks = */ true,
2579 /* complete = */ true);
2580 instr->ReplaceWith(call, current_iterator());
2581 return;
2582 }
2583 }
2584 }
2585 }
2586
2524 // More than one targets. Generate generic polymorphic call without 2587 // More than one targets. Generate generic polymorphic call without
2525 // deoptimization. 2588 // deoptimization.
2526 if (instr->ic_data()->NumberOfUsedChecks() > 0) { 2589 if (instr->ic_data()->NumberOfUsedChecks() > 0) {
2527 ASSERT(!FLAG_polymorphic_with_deopt); 2590 ASSERT(!FLAG_polymorphic_with_deopt);
2528 // OK to use checks with PolymorphicInstanceCallInstr since no 2591 // OK to use checks with PolymorphicInstanceCallInstr since no
2529 // deoptimization is allowed. 2592 // deoptimization is allowed.
2530 PolymorphicInstanceCallInstr* call = 2593 PolymorphicInstanceCallInstr* call =
2531 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, 2594 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
2532 /* with_checks = */ true); 2595 /* with_checks = */ true,
2596 /* complete = */ false);
2533 instr->ReplaceWith(call, current_iterator()); 2597 instr->ReplaceWith(call, current_iterator());
2534 return; 2598 return;
2535 } 2599 }
2536 } 2600 }
2537 2601
2538 2602
2539 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { 2603 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) {
2540 if (!CanUnboxDouble()) { 2604 if (!CanUnboxDouble()) {
2541 return; 2605 return;
2542 } 2606 }
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
2757 2821
2758 // Discard the environment from the original instruction because the store 2822 // Discard the environment from the original instruction because the store
2759 // can't deoptimize. 2823 // can't deoptimize.
2760 instr->RemoveEnvironment(); 2824 instr->RemoveEnvironment();
2761 ReplaceCall(instr, store); 2825 ReplaceCall(instr, store);
2762 return true; 2826 return true;
2763 } 2827 }
2764 2828
2765 2829
2766 } // namespace dart 2830 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/lib/string_patch.dart ('k') | runtime/vm/cha.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698