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

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

Issue 2055263002: VM: Improve specialization of calls on receiver in AOT mode. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 6 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 | « no previous file | runtime/vm/intermediate_language.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 2447 matching lines...) Expand 10 before | Expand all | Expand 10 after
2458 } 2458 }
2459 } 2459 }
2460 } 2460 }
2461 2461
2462 Definition* callee_receiver = instr->ArgumentAt(0); 2462 Definition* callee_receiver = instr->ArgumentAt(0);
2463 const Function& function = flow_graph_->function(); 2463 const Function& function = flow_graph_->function();
2464 if (function.IsDynamicFunction() && 2464 if (function.IsDynamicFunction() &&
2465 flow_graph_->IsReceiver(callee_receiver)) { 2465 flow_graph_->IsReceiver(callee_receiver)) {
2466 // Call receiver is method receiver. 2466 // Call receiver is method receiver.
2467 Class& receiver_class = Class::Handle(Z, function.Owner()); 2467 Class& receiver_class = Class::Handle(Z, function.Owner());
2468
2468 GrowableArray<intptr_t> class_ids(6); 2469 GrowableArray<intptr_t> class_ids(6);
2469 if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) { 2470 if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) {
2470 if (class_ids.length() <= FLAG_max_exhaustive_polymorphic_checks) { 2471 // First check if all subclasses end up calling the same method.
2471 if (FLAG_trace_cha) { 2472 // If this is the case we will replace instance call with a direct
2472 THR_Print(" **(CHA) Only %" Pd " concrete subclasses of %s for %s\n", 2473 // static call.
2473 class_ids.length(), 2474 // Otherwise we will try to create ICData that contains all possible
2474 receiver_class.ToCString(), 2475 // targets with appropriate checks.
2475 instr->function_name().ToCString()); 2476 Function& single_target = Function::Handle(Z);
2477 ICData& ic_data = ICData::Handle(Z);
2478
2479 const Array& args_desc_array = Array::Handle(Z,
2480 ArgumentsDescriptor::New(instr->ArgumentCount(),
2481 instr->argument_names()));
2482 ArgumentsDescriptor args_desc(args_desc_array);
2483
2484 Function& target = Function::Handle(Z);
2485 Class& cls = Class::Handle(Z);
2486 for (intptr_t i = 0; i < class_ids.length(); i++) {
2487 const intptr_t cid = class_ids[i];
2488 cls = isolate()->class_table()->At(cid);
2489 target = Resolver::ResolveDynamicForReceiverClass(
2490 cls,
2491 instr->function_name(),
2492 args_desc);
2493
2494 if (target.IsNull()) {
2495 // Can't resolve the target. It might be a noSuchMethod,
2496 // call through getter or closurization.
2497 single_target = Function::null();
2498 ic_data = ICData::null();
2499 break;
2500 } else if (ic_data.IsNull()) {
2501 // First we are trying to compute a single target for all subclasses.
2502 if (single_target.IsNull()) {
2503 ASSERT(i == 0);
2504 single_target = target.raw();
2505 continue;
2506 } else if (single_target.raw() == target.raw()) {
2507 continue;
2508 }
2509
2510 // The call does not resolve to a single target within the hierarchy.
2511 // If we have too many subclasses abort the optimization.
2512 if (class_ids.length() > FLAG_max_exhaustive_polymorphic_checks) {
2513 single_target = Function::null();
2514 break;
2515 }
2516
2517 // Create an ICData and map all previously seen classes (< i) to
2518 // the computed single_target.
2519 ic_data = ICData::New(function,
2520 instr->function_name(),
2521 args_desc_array,
2522 Thread::kNoDeoptId,
2523 /* args_tested = */ 1);
2524 for (intptr_t j = 0; j < i; j++) {
2525 ic_data.AddReceiverCheck(class_ids[j], single_target);
2526 }
2527
2528 single_target = Function::null();
2476 } 2529 }
2477 2530
2478 const Array& args_desc_array = Array::Handle(Z, 2531 ASSERT(ic_data.raw() != ICData::null());
2479 ArgumentsDescriptor::New(instr->ArgumentCount(), 2532 ASSERT(single_target.raw() == Function::null());
2480 instr->argument_names())); 2533 ic_data.AddReceiverCheck(cid, target);
2481 ArgumentsDescriptor args_desc(args_desc_array); 2534 }
2482 2535
2483 const ICData& ic_data = ICData::Handle( 2536 if (single_target.raw() != Function::null()) {
2484 ICData::New(function, 2537 // We have computed that there is only a single target for this call
2485 instr->function_name(), 2538 // within the whole hierarchy. Replace InstanceCall with StaticCall.
2486 args_desc_array, 2539 ZoneGrowableArray<PushArgumentInstr*>* args =
2487 Thread::kNoDeoptId, 2540 new (Z) ZoneGrowableArray<PushArgumentInstr*>(
2488 /* args_tested = */ 1)); 2541 instr->ArgumentCount());
2489 2542 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) {
2490 Function& target = Function::Handle(Z); 2543 args->Add(instr->PushArgumentAt(i));
2491 Class& cls = Class::Handle(Z);
2492 bool includes_dispatcher_case = false;
2493 for (intptr_t i = 0; i < class_ids.length(); i++) {
2494 intptr_t cid = class_ids[i];
2495 cls = isolate()->class_table()->At(cid);
2496 target = Resolver::ResolveDynamicForReceiverClass(
2497 cls,
2498 instr->function_name(),
2499 args_desc);
2500 if (target.IsNull()) {
2501 // noSuchMethod, call through getter or closurization
2502 includes_dispatcher_case = true;
2503 } else {
2504 ic_data.AddReceiverCheck(cid, target);
2505 }
2506 } 2544 }
2507 if (!includes_dispatcher_case && (ic_data.NumberOfChecks() > 0)) { 2545 StaticCallInstr* call = new (Z) StaticCallInstr(
Florian Schneider 2016/06/10 15:30:18 Alternatively, maybe you can combine this with the
Vyacheslav Egorov (Google) 2016/06/10 16:05:06 I considered combining it - but then I need to cre
2508 PolymorphicInstanceCallInstr* call = 2546 instr->token_pos(),
2509 new(Z) PolymorphicInstanceCallInstr(instr, ic_data, 2547 Function::ZoneHandle(Z, single_target.raw()),
2510 /* with_checks = */ true, 2548 instr->argument_names(),
2511 /* complete = */ true); 2549 args,
2512 instr->ReplaceWith(call, current_iterator()); 2550 instr->deopt_id());
2513 return; 2551 instr->ReplaceWith(call, current_iterator());
2514 } 2552 return;
2553 } else if ((ic_data.raw() != ICData::null()) &&
2554 (ic_data.NumberOfChecks() > 0)) {
2555 PolymorphicInstanceCallInstr* call =
2556 new(Z) PolymorphicInstanceCallInstr(instr, ic_data,
2557 /* with_checks = */ true,
2558 /* complete = */ true);
2559 instr->ReplaceWith(call, current_iterator());
2560 return;
2515 } 2561 }
2516 } 2562 }
2517 } 2563 }
2518 2564
2519 // More than one targets. Generate generic polymorphic call without 2565 // More than one target. Generate generic polymorphic call without
2520 // deoptimization. 2566 // deoptimization.
2521 if (instr->ic_data()->NumberOfUsedChecks() > 0) { 2567 if (instr->ic_data()->NumberOfUsedChecks() > 0) {
2522 ASSERT(!FLAG_polymorphic_with_deopt); 2568 ASSERT(!FLAG_polymorphic_with_deopt);
2523 // OK to use checks with PolymorphicInstanceCallInstr since no 2569 // OK to use checks with PolymorphicInstanceCallInstr since no
2524 // deoptimization is allowed. 2570 // deoptimization is allowed.
2525 PolymorphicInstanceCallInstr* call = 2571 PolymorphicInstanceCallInstr* call =
2526 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, 2572 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
2527 /* with_checks = */ true, 2573 /* with_checks = */ true,
2528 /* complete = */ false); 2574 /* complete = */ false);
2529 instr->ReplaceWith(call, current_iterator()); 2575 instr->ReplaceWith(call, current_iterator());
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
2753 2799
2754 // Discard the environment from the original instruction because the store 2800 // Discard the environment from the original instruction because the store
2755 // can't deoptimize. 2801 // can't deoptimize.
2756 instr->RemoveEnvironment(); 2802 instr->RemoveEnvironment();
2757 ReplaceCall(instr, store); 2803 ReplaceCall(instr, store);
2758 return true; 2804 return true;
2759 } 2805 }
2760 2806
2761 2807
2762 } // namespace dart 2808 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698