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

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

Issue 2877713003: Eliminated with_checks variable (Closed)
Patch Set: Use return type from recognized methods for static calls Created 3 years, 7 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
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 #ifndef DART_PRECOMPILED_RUNTIME 4 #ifndef DART_PRECOMPILED_RUNTIME
5 #include "vm/jit_optimizer.h" 5 #include "vm/jit_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 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 return false; 192 return false;
193 } 193 }
194 194
195 195
196 void JitOptimizer::SpecializePolymorphicInstanceCall( 196 void JitOptimizer::SpecializePolymorphicInstanceCall(
197 PolymorphicInstanceCallInstr* call) { 197 PolymorphicInstanceCallInstr* call) {
198 if (!FLAG_polymorphic_with_deopt) { 198 if (!FLAG_polymorphic_with_deopt) {
199 // Specialization adds receiver checks which can lead to deoptimization. 199 // Specialization adds receiver checks which can lead to deoptimization.
200 return; 200 return;
201 } 201 }
202 if (!call->with_checks()) {
203 return; // Already specialized.
204 }
205 202
206 const intptr_t receiver_cid = 203 const intptr_t receiver_cid =
207 call->PushArgumentAt(0)->value()->Type()->ToCid(); 204 call->PushArgumentAt(0)->value()->Type()->ToCid();
208 if (receiver_cid == kDynamicCid) { 205 if (receiver_cid == kDynamicCid) {
209 return; // No information about receiver was infered. 206 return; // No information about receiver was infered.
210 } 207 }
211 208
212 const ICData& ic_data = *call->instance_call()->ic_data(); 209 const ICData& ic_data = *call->instance_call()->ic_data();
213 210
214 const CallTargets* targets = 211 const CallTargets* targets =
215 FlowGraphCompiler::ResolveCallTargetsForReceiverCid( 212 FlowGraphCompiler::ResolveCallTargetsForReceiverCid(
216 receiver_cid, String::Handle(zone(), ic_data.target_name()), 213 receiver_cid, String::Handle(zone(), ic_data.target_name()),
217 Array::Handle(zone(), ic_data.arguments_descriptor())); 214 Array::Handle(zone(), ic_data.arguments_descriptor()));
218 if (targets == NULL) { 215 if (targets == NULL) {
219 // No specialization. 216 // No specialization.
220 return; 217 return;
221 } 218 }
222 219
223 const bool with_checks = false; 220 ASSERT(targets->HasSingleTarget());
Vyacheslav Egorov (Google) 2017/05/18 07:03:11 ditto: abstract this pattern into a function
224 const bool complete = false; 221 const Function& target = targets->FirstTarget();
225 PolymorphicInstanceCallInstr* specialized = 222 ZoneGrowableArray<PushArgumentInstr*>* args =
226 new (Z) PolymorphicInstanceCallInstr(call->instance_call(), *targets, 223 new (Z) ZoneGrowableArray<PushArgumentInstr*>(
227 with_checks, complete); 224 call->instance_call()->ArgumentCount());
225 for (intptr_t i = 0; i < call->instance_call()->ArgumentCount(); i++) {
226 args->Add(call->instance_call()->PushArgumentAt(i));
227 }
228 StaticCallInstr* specialized = new (Z) StaticCallInstr(
229 call->token_pos(), target, call->instance_call()->argument_names(), args,
230 call->deopt_id(), call->CallCount());
228 call->ReplaceWith(specialized, current_iterator()); 231 call->ReplaceWith(specialized, current_iterator());
229 } 232 }
230 233
231 234
232 static bool ClassIdIsOneOf(intptr_t class_id, 235 static bool ClassIdIsOneOf(intptr_t class_id,
233 const GrowableArray<intptr_t>& class_ids) { 236 const GrowableArray<intptr_t>& class_ids) {
234 for (intptr_t i = 0; i < class_ids.length(); i++) { 237 for (intptr_t i = 0; i < class_ids.length(); i++) {
235 ASSERT(class_ids[i] != kIllegalCid); 238 ASSERT(class_ids[i] != kIllegalCid);
236 if (class_ids[i] == class_id) { 239 if (class_ids[i] == class_id) {
237 return true; 240 return true;
(...skipping 1286 matching lines...) Expand 10 before | Expand all | Expand 10 after
1524 const bool polymorphic_target = 1527 const bool polymorphic_target =
1525 MethodRecognizer::PolymorphicTarget(target); 1528 MethodRecognizer::PolymorphicTarget(target);
1526 has_one_target = !polymorphic_target; 1529 has_one_target = !polymorphic_target;
1527 } 1530 }
1528 } 1531 }
1529 1532
1530 if (has_one_target) { 1533 if (has_one_target) {
1531 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0)); 1534 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0));
1532 const RawFunction::Kind function_kind = target.kind(); 1535 const RawFunction::Kind function_kind = target.kind();
1533 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) { 1536 if (!flow_graph()->InstanceCallNeedsClassCheck(instr, function_kind)) {
1534 PolymorphicInstanceCallInstr* call = 1537 ZoneGrowableArray<PushArgumentInstr*>* args =
Vyacheslav Egorov (Google) 2017/05/18 07:03:11 ditto
1535 new (Z) PolymorphicInstanceCallInstr(instr, *targets, 1538 new (Z) ZoneGrowableArray<PushArgumentInstr*>(instr->ArgumentCount());
1536 /* call_with_checks = */ false, 1539 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) {
1537 /* complete = */ false); 1540 args->Add(instr->PushArgumentAt(i));
1541 }
1542 StaticCallInstr* call = new (Z)
1543 StaticCallInstr(instr->token_pos(), target, instr->argument_names(),
1544 args, instr->deopt_id(), instr->CallCount());
1538 instr->ReplaceWith(call, current_iterator()); 1545 instr->ReplaceWith(call, current_iterator());
1539 return; 1546 return;
1540 } 1547 }
1541 } 1548 }
1542 1549
1543 // If there is only one target we can make this into a deopting class check, 1550 // If there is only one target we can make this into a deopting class check,
1544 // followed by a call instruction that does not check the class of the 1551 // followed by a call instruction that does not check the class of the
1545 // receiver. This enables a lot of optimizations because after the class 1552 // receiver. This enables a lot of optimizations because after the class
1546 // check we can probably inline the call and not worry about side effects. 1553 // check we can probably inline the call and not worry about side effects.
1547 // However, this can fall down if new receiver classes arrive at this call 1554 // However, this can fall down if new receiver classes arrive at this call
1548 // site after we generated optimized code. This causes a deopt, and after a 1555 // site after we generated optimized code. This causes a deopt, and after a
1549 // few deopts we won't optimize this function any more at all. Therefore for 1556 // few deopts we won't optimize this function any more at all. Therefore for
1550 // very polymorphic sites we don't make this optimization, keeping it as a 1557 // very polymorphic sites we don't make this optimization, keeping it as a
1551 // regular checked PolymorphicInstanceCall, which falls back to the slow but 1558 // regular checked PolymorphicInstanceCall, which falls back to the slow but
1552 // non-deopting megamorphic call stub when it sees new receiver classes. 1559 // non-deopting megamorphic call stub when it sees new receiver classes.
1553 bool call_with_checks;
1554 if (has_one_target && FLAG_polymorphic_with_deopt && 1560 if (has_one_target && FLAG_polymorphic_with_deopt &&
1555 (!instr->ic_data()->HasDeoptReason(ICData::kDeoptCheckClass) || 1561 (!instr->ic_data()->HasDeoptReason(ICData::kDeoptCheckClass) ||
1556 unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) { 1562 unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks)) {
1557 // Type propagation has not run yet, we cannot eliminate the check. 1563 // Type propagation has not run yet, we cannot eliminate the check.
1558 // TODO(erikcorry): The receiver check should use the off-heap targets 1564 // TODO(erikcorry): The receiver check should use the off-heap targets
1559 // array, not the IC array. 1565 // array, not the IC array.
1560 AddReceiverCheck(instr); 1566 AddReceiverCheck(instr);
1561 // Call can still deoptimize, do not detach environment from instr. 1567 // Call can still deoptimize, do not detach environment from instr.
1562 call_with_checks = false; 1568 const Function& target = Function::Handle(Z, unary_checks.GetTargetAt(0));
1569 ZoneGrowableArray<PushArgumentInstr*>* args =
Vyacheslav Egorov (Google) 2017/05/18 07:03:11 ditto
1570 new (Z) ZoneGrowableArray<PushArgumentInstr*>(instr->ArgumentCount());
1571 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) {
1572 args->Add(instr->PushArgumentAt(i));
1573 }
1574 StaticCallInstr* call = new (Z)
1575 StaticCallInstr(instr->token_pos(), target, instr->argument_names(),
1576 args, instr->deopt_id(), instr->CallCount());
1577 instr->ReplaceWith(call, current_iterator());
1563 } else { 1578 } else {
1564 call_with_checks = true; 1579 PolymorphicInstanceCallInstr* call =
1580 new (Z) PolymorphicInstanceCallInstr(instr, *targets,
1581 /* complete = */ false);
1582 instr->ReplaceWith(call, current_iterator());
1565 } 1583 }
1566 PolymorphicInstanceCallInstr* call =
1567 new (Z) PolymorphicInstanceCallInstr(instr, *targets, call_with_checks,
1568 /* complete = */ false);
1569 instr->ReplaceWith(call, current_iterator());
1570 } 1584 }
1571 1585
1572 1586
1573 void JitOptimizer::VisitStaticCall(StaticCallInstr* call) { 1587 void JitOptimizer::VisitStaticCall(StaticCallInstr* call) {
1574 MethodRecognizer::Kind recognized_kind = 1588 MethodRecognizer::Kind recognized_kind =
1575 MethodRecognizer::RecognizeKind(call->function()); 1589 MethodRecognizer::RecognizeKind(call->function());
1576 switch (recognized_kind) { 1590 switch (recognized_kind) {
1577 case MethodRecognizer::kObjectConstructor: 1591 case MethodRecognizer::kObjectConstructor:
1578 case MethodRecognizer::kObjectArrayAllocate: 1592 case MethodRecognizer::kObjectArrayAllocate:
1579 case MethodRecognizer::kFloat32x4Zero: 1593 case MethodRecognizer::kFloat32x4Zero:
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
1813 // Discard the environment from the original instruction because the store 1827 // Discard the environment from the original instruction because the store
1814 // can't deoptimize. 1828 // can't deoptimize.
1815 instr->RemoveEnvironment(); 1829 instr->RemoveEnvironment();
1816 ReplaceCall(instr, store); 1830 ReplaceCall(instr, store);
1817 return true; 1831 return true;
1818 } 1832 }
1819 1833
1820 1834
1821 } // namespace dart 1835 } // namespace dart
1822 #endif // DART_PRECOMPILED_RUNTIME 1836 #endif // DART_PRECOMPILED_RUNTIME
OLDNEW
« runtime/vm/intermediate_language.cc ('K') | « runtime/vm/intermediate_language_dbc.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698