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

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

Issue 11642003: Create and cache method extraction stub in the ICData. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: lazyly inject extractors as getters into class Created 7 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/il_printer.cc » ('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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 type_arguments_field_offset, 596 type_arguments_field_offset,
597 Type::ZoneHandle()); // No type. 597 Type::ZoneHandle()); // No type.
598 InsertBefore(call, load_type_args, NULL, Definition::kValue); 598 InsertBefore(call, load_type_args, NULL, Definition::kValue);
599 instantiator = array->Copy(); 599 instantiator = array->Copy();
600 type_args = new Value(load_type_args); 600 type_args = new Value(load_type_args);
601 break; 601 break;
602 } 602 }
603 case kUint8ArrayCid: 603 case kUint8ArrayCid:
604 case kFloat32ArrayCid: 604 case kFloat32ArrayCid:
605 case kFloat64ArrayCid: { 605 case kFloat64ArrayCid: {
606 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle()); 606 instantiator = new Value(flow_graph_->constant_null());
607 InsertBefore(call, null_constant, NULL, Definition::kValue); 607 type_args = new Value(flow_graph_->constant_null());
608 instantiator = new Value(null_constant);
609 type_args = new Value(null_constant);
610 ASSERT((class_id != kUint8ArrayCid) || value_type.IsIntType()); 608 ASSERT((class_id != kUint8ArrayCid) || value_type.IsIntType());
611 ASSERT((class_id != kFloat32ArrayCid && class_id != kFloat64ArrayCid) || 609 ASSERT((class_id != kFloat32ArrayCid && class_id != kFloat64ArrayCid) ||
612 value_type.IsDoubleType()); 610 value_type.IsDoubleType());
613 ASSERT(value_type.IsInstantiated()); 611 ASSERT(value_type.IsInstantiated());
614 break; 612 break;
615 } 613 }
616 default: 614 default:
617 // TODO(fschneider): Add support for other array types. 615 // TODO(fschneider): Add support for other array types.
618 UNREACHABLE(); 616 UNREACHABLE();
619 } 617 }
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
957 if (function.IsDynamicFunction() && 955 if (function.IsDynamicFunction() &&
958 callee_receiver->IsParameter() && 956 callee_receiver->IsParameter() &&
959 (callee_receiver->AsParameter()->index() == 0)) { 957 (callee_receiver->AsParameter()->index() == 0)) {
960 return CHA::HasOverride(Class::Handle(function.Owner()), 958 return CHA::HasOverride(Class::Handle(function.Owner()),
961 call->function_name()); 959 call->function_name());
962 } 960 }
963 return true; 961 return true;
964 } 962 }
965 963
966 964
965 bool FlowGraphOptimizer::MethodExtractorNeedsClassCheck(
966 InstanceCallInstr* call) const {
967 if (!FLAG_use_cha) return true;
968 Definition* callee_receiver = call->ArgumentAt(0)->value()->definition();
969 ASSERT(callee_receiver != NULL);
970 const Function& function = flow_graph_->parsed_function().function();
971 if (function.IsDynamicFunction() &&
972 callee_receiver->IsParameter() &&
973 (callee_receiver->AsParameter()->index() == 0)) {
974 const String& field_name =
975 String::Handle(Field::NameFromGetter(call->function_name()));
976 return CHA::HasOverride(Class::Handle(function.Owner()), field_name);
977 }
978 return true;
979 }
980
981
967 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { 982 void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) {
968 ASSERT(call->HasICData()); 983 ASSERT(call->HasICData());
969 const ICData& ic_data = *call->ic_data(); 984 const ICData& ic_data = *call->ic_data();
970 Function& target = Function::Handle(); 985 Function& target = Function::Handle();
971 GrowableArray<intptr_t> class_ids; 986 GrowableArray<intptr_t> class_ids;
972 ic_data.GetCheckAt(0, &class_ids, &target); 987 ic_data.GetCheckAt(0, &class_ids, &target);
973 ASSERT(class_ids.length() == 1); 988 ASSERT(class_ids.length() == 1);
974 // Inline implicit instance getter. 989 // Inline implicit instance getter.
975 const String& field_name = 990 const String& field_name =
976 String::Handle(Field::NameFromGetter(call->function_name())); 991 String::Handle(Field::NameFromGetter(call->function_name()));
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1104 return false; 1119 return false;
1105 } 1120 }
1106 Function& target = Function::Handle(ic_data.GetTargetAt(0)); 1121 Function& target = Function::Handle(ic_data.GetTargetAt(0));
1107 if (target.kind() == RawFunction::kImplicitGetter) { 1122 if (target.kind() == RawFunction::kImplicitGetter) {
1108 if (!ic_data.HasOneTarget()) { 1123 if (!ic_data.HasOneTarget()) {
1109 // TODO(srdjan): Implement for mutiple targets. 1124 // TODO(srdjan): Implement for mutiple targets.
1110 return false; 1125 return false;
1111 } 1126 }
1112 InlineImplicitInstanceGetter(call); 1127 InlineImplicitInstanceGetter(call);
1113 return true; 1128 return true;
1129 } else if (target.kind() == RawFunction::kMethodExtractor) {
1130 return false;
1114 } 1131 }
1115 1132
1116 // Not an implicit getter. 1133 // Not an implicit getter.
1117 MethodRecognizer::Kind recognized_kind = 1134 MethodRecognizer::Kind recognized_kind =
1118 MethodRecognizer::RecognizeKind(target); 1135 MethodRecognizer::RecognizeKind(target);
1119 1136
1120 // VM objects length getter. 1137 // VM objects length getter.
1121 switch (recognized_kind) { 1138 switch (recognized_kind) {
1122 case MethodRecognizer::kObjectArrayLength: 1139 case MethodRecognizer::kObjectArrayLength:
1123 case MethodRecognizer::kImmutableArrayLength: 1140 case MethodRecognizer::kImmutableArrayLength:
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
1356 1373
1357 const Token::Kind op_kind = instr->token_kind(); 1374 const Token::Kind op_kind = instr->token_kind();
1358 // Type test is special as it always gets converted into inlined code. 1375 // Type test is special as it always gets converted into inlined code.
1359 if (Token::IsTypeTestOperator(op_kind)) { 1376 if (Token::IsTypeTestOperator(op_kind)) {
1360 ReplaceWithInstanceOf(instr); 1377 ReplaceWithInstanceOf(instr);
1361 return; 1378 return;
1362 } 1379 }
1363 1380
1364 const ICData& unary_checks = 1381 const ICData& unary_checks =
1365 ICData::ZoneHandle(instr->ic_data()->AsUnaryClassChecks()); 1382 ICData::ZoneHandle(instr->ic_data()->AsUnaryClassChecks());
1383
1366 if ((unary_checks.NumberOfChecks() > FLAG_max_polymorphic_checks) && 1384 if ((unary_checks.NumberOfChecks() > FLAG_max_polymorphic_checks) &&
1367 InstanceCallNeedsClassCheck(instr)) { 1385 InstanceCallNeedsClassCheck(instr)) {
1368 // Too many checks, it will be megamorphic which needs unary checks. 1386 // Too many checks, it will be megamorphic which needs unary checks.
1369 instr->set_ic_data(&unary_checks); 1387 instr->set_ic_data(&unary_checks);
1370 return; 1388 return;
1371 } 1389 }
1372 1390
1373 if ((op_kind == Token::kASSIGN_INDEX) && 1391 if ((op_kind == Token::kASSIGN_INDEX) &&
1374 TryReplaceWithStoreIndexed(instr)) { 1392 TryReplaceWithStoreIndexed(instr)) {
1375 return; 1393 return;
(...skipping 12 matching lines...) Expand all
1388 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr)) { 1406 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr)) {
1389 return; 1407 return;
1390 } 1408 }
1391 if ((op_kind == Token::kSET) && 1409 if ((op_kind == Token::kSET) &&
1392 TryInlineInstanceSetter(instr, unary_checks)) { 1410 TryInlineInstanceSetter(instr, unary_checks)) {
1393 return; 1411 return;
1394 } 1412 }
1395 if (TryInlineInstanceMethod(instr)) { 1413 if (TryInlineInstanceMethod(instr)) {
1396 return; 1414 return;
1397 } 1415 }
1398 if (!InstanceCallNeedsClassCheck(instr)) { 1416
1399 const bool call_with_checks = false; 1417 const bool has_one_target = unary_checks.HasOneTarget();
1400 PolymorphicInstanceCallInstr* call = 1418
1401 new PolymorphicInstanceCallInstr(instr, unary_checks, 1419 if (has_one_target) {
1402 call_with_checks); 1420 const bool is_method_extraction =
1403 instr->ReplaceWith(call, current_iterator()); 1421 Function::Handle(unary_checks.GetTargetAt(0)).IsMethodExtractor();
1404 return; 1422
1423 if ((is_method_extraction && !MethodExtractorNeedsClassCheck(instr)) ||
1424 (!is_method_extraction && !InstanceCallNeedsClassCheck(instr))) {
1425 const bool call_with_checks = false;
1426 PolymorphicInstanceCallInstr* call =
1427 new PolymorphicInstanceCallInstr(instr, unary_checks,
1428 call_with_checks);
1429 instr->ReplaceWith(call, current_iterator());
1430 return;
1431 }
1405 } 1432 }
1433
1406 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { 1434 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
1407 bool call_with_checks; 1435 bool call_with_checks;
1408 if (unary_checks.HasOneTarget()) { 1436 if (has_one_target) {
1409 // Type propagation has not run yet, we cannot eliminate the check. 1437 // Type propagation has not run yet, we cannot eliminate the check.
1410 AddCheckClass(instr, instr->ArgumentAt(0)->value()->Copy()); 1438 AddCheckClass(instr, instr->ArgumentAt(0)->value()->Copy());
1411 // Call can still deoptimize, do not detach environment from instr. 1439 // Call can still deoptimize, do not detach environment from instr.
1412 call_with_checks = false; 1440 call_with_checks = false;
1413 } else { 1441 } else {
1414 call_with_checks = true; 1442 call_with_checks = true;
1415 } 1443 }
1416 PolymorphicInstanceCallInstr* call = 1444 PolymorphicInstanceCallInstr* call =
1417 new PolymorphicInstanceCallInstr(instr, unary_checks, 1445 new PolymorphicInstanceCallInstr(instr, unary_checks,
1418 call_with_checks); 1446 call_with_checks);
(...skipping 3031 matching lines...) Expand 10 before | Expand all | Expand 10 after
4450 4478
4451 if (FLAG_trace_constant_propagation) { 4479 if (FLAG_trace_constant_propagation) {
4452 OS::Print("\n==== After constant propagation ====\n"); 4480 OS::Print("\n==== After constant propagation ====\n");
4453 FlowGraphPrinter printer(*graph_); 4481 FlowGraphPrinter printer(*graph_);
4454 printer.PrintBlocks(); 4482 printer.PrintBlocks();
4455 } 4483 }
4456 } 4484 }
4457 4485
4458 4486
4459 } // namespace dart 4487 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/il_printer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698