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

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

Issue 1732483002: Rename FlowGraphOptimizer -> JitOptimizer, clean up optimizer code. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 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/vm/aot_optimizer.h ('k') | runtime/vm/compiler.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) 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 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 return true; 253 return true;
254 } 254 }
255 } 255 }
256 } 256 }
257 257
258 return false; 258 return false;
259 } 259 }
260 260
261 261
262 const ICData& AotOptimizer::TrySpecializeICData(const ICData& ic_data, 262 const ICData& AotOptimizer::TrySpecializeICData(const ICData& ic_data,
263 intptr_t cid) { 263 intptr_t cid) {
264 ASSERT(ic_data.NumArgsTested() == 1); 264 ASSERT(ic_data.NumArgsTested() == 1);
265 265
266 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) { 266 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) {
267 return ic_data; // Nothing to do 267 return ic_data; // Nothing to do
268 } 268 }
269 269
270 const Function& function = 270 const Function& function =
271 Function::Handle(Z, ic_data.GetTargetForReceiverClassId(cid)); 271 Function::Handle(Z, ic_data.GetTargetForReceiverClassId(cid));
272 // TODO(fschneider): Try looking up the function on the class if it is 272 // TODO(fschneider): Try looking up the function on the class if it is
273 // not found in the ICData. 273 // not found in the ICData.
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 Token::kBIT_AND, 368 Token::kBIT_AND,
369 new(Z) Value(left_instr), 369 new(Z) Value(left_instr),
370 new(Z) Value(right_instr), 370 new(Z) Value(right_instr),
371 Thread::kNoDeoptId); // BIT_AND cannot deoptimize. 371 Thread::kNoDeoptId); // BIT_AND cannot deoptimize.
372 bit_and_instr->ReplaceWith(smi_op, current_iterator()); 372 bit_and_instr->ReplaceWith(smi_op, current_iterator());
373 } 373 }
374 } 374 }
375 375
376 376
377 void AotOptimizer::AppendExtractNthOutputForMerged(Definition* instr, 377 void AotOptimizer::AppendExtractNthOutputForMerged(Definition* instr,
378 intptr_t index, 378 intptr_t index,
379 Representation rep, 379 Representation rep,
380 intptr_t cid) { 380 intptr_t cid) {
381 ExtractNthOutputInstr* extract = 381 ExtractNthOutputInstr* extract =
382 new(Z) ExtractNthOutputInstr(new(Z) Value(instr), index, rep, cid); 382 new(Z) ExtractNthOutputInstr(new(Z) Value(instr), index, rep, cid);
383 instr->ReplaceUsesWith(extract); 383 instr->ReplaceUsesWith(extract);
384 flow_graph()->InsertAfter(instr, extract, NULL, FlowGraph::kValue); 384 flow_graph()->InsertAfter(instr, extract, NULL, FlowGraph::kValue);
385 } 385 }
386 386
387 387
388 // Dart: 388 // Dart:
389 // var x = d % 10; 389 // var x = d % 10;
390 // var y = d ~/ 10; 390 // var y = d ~/ 10;
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) { 704 if (ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid)) {
705 return false; 705 return false;
706 } 706 }
707 707
708 // Check that it have seen only smis and doubles. 708 // Check that it have seen only smis and doubles.
709 return HasTwoDoubleOrSmi(ic_data); 709 return HasTwoDoubleOrSmi(ic_data);
710 } 710 }
711 711
712 712
713 void AotOptimizer::ReplaceCall(Definition* call, 713 void AotOptimizer::ReplaceCall(Definition* call,
714 Definition* replacement) { 714 Definition* replacement) {
715 // Remove the original push arguments. 715 // Remove the original push arguments.
716 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 716 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
717 PushArgumentInstr* push = call->PushArgumentAt(i); 717 PushArgumentInstr* push = call->PushArgumentAt(i);
718 push->ReplaceUsesWith(push->value()->definition()); 718 push->ReplaceUsesWith(push->value()->definition());
719 push->RemoveFromGraph(); 719 push->RemoveFromGraph();
720 } 720 }
721 call->ReplaceWith(replacement, current_iterator()); 721 call->ReplaceWith(replacement, current_iterator());
722 } 722 }
723 723
724 724
725 void AotOptimizer::AddCheckSmi(Definition* to_check, 725 void AotOptimizer::AddCheckSmi(Definition* to_check,
726 intptr_t deopt_id, 726 intptr_t deopt_id,
727 Environment* deopt_environment, 727 Environment* deopt_environment,
728 Instruction* insert_before) { 728 Instruction* insert_before) {
729 if (to_check->Type()->ToCid() != kSmiCid) { 729 if (to_check->Type()->ToCid() != kSmiCid) {
730 InsertBefore(insert_before, 730 InsertBefore(insert_before,
731 new(Z) CheckSmiInstr(new(Z) Value(to_check), 731 new(Z) CheckSmiInstr(new(Z) Value(to_check),
732 deopt_id, 732 deopt_id,
733 insert_before->token_pos()), 733 insert_before->token_pos()),
734 deopt_environment, 734 deopt_environment,
735 FlowGraph::kEffect); 735 FlowGraph::kEffect);
736 } 736 }
737 } 737 }
738 738
739 739
740 Instruction* AotOptimizer::GetCheckClass(Definition* to_check, 740 Instruction* AotOptimizer::GetCheckClass(Definition* to_check,
741 const ICData& unary_checks, 741 const ICData& unary_checks,
742 intptr_t deopt_id, 742 intptr_t deopt_id,
743 TokenPosition token_pos) { 743 TokenPosition token_pos) {
744 if ((unary_checks.NumberOfUsedChecks() == 1) && 744 if ((unary_checks.NumberOfUsedChecks() == 1) &&
745 unary_checks.HasReceiverClassId(kSmiCid)) { 745 unary_checks.HasReceiverClassId(kSmiCid)) {
746 return new(Z) CheckSmiInstr(new(Z) Value(to_check), 746 return new(Z) CheckSmiInstr(new(Z) Value(to_check),
747 deopt_id, 747 deopt_id,
748 token_pos); 748 token_pos);
749 } 749 }
750 return new(Z) CheckClassInstr( 750 return new(Z) CheckClassInstr(
751 new(Z) Value(to_check), deopt_id, unary_checks, token_pos); 751 new(Z) Value(to_check), deopt_id, unary_checks, token_pos);
752 } 752 }
753 753
754 754
755 void AotOptimizer::AddCheckClass(Definition* to_check, 755 void AotOptimizer::AddCheckClass(Definition* to_check,
756 const ICData& unary_checks, 756 const ICData& unary_checks,
757 intptr_t deopt_id, 757 intptr_t deopt_id,
758 Environment* deopt_environment, 758 Environment* deopt_environment,
759 Instruction* insert_before) { 759 Instruction* insert_before) {
760 // Type propagation has not run yet, we cannot eliminate the check. 760 // Type propagation has not run yet, we cannot eliminate the check.
761 Instruction* check = GetCheckClass( 761 Instruction* check = GetCheckClass(
762 to_check, unary_checks, deopt_id, insert_before->token_pos()); 762 to_check, unary_checks, deopt_id, insert_before->token_pos());
763 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect); 763 InsertBefore(insert_before, check, deopt_environment, FlowGraph::kEffect);
764 } 764 }
765 765
766 766
767 void AotOptimizer::AddReceiverCheck(InstanceCallInstr* call) { 767 void AotOptimizer::AddReceiverCheck(InstanceCallInstr* call) {
768 AddCheckClass(call->ArgumentAt(0), 768 AddCheckClass(call->ArgumentAt(0),
769 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()), 769 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()),
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
816 return d->IsStringFromCharCode(); 816 return d->IsStringFromCharCode();
817 } 817 }
818 } 818 }
819 819
820 820
821 // Returns true if the string comparison was converted into char-code 821 // Returns true if the string comparison was converted into char-code
822 // comparison. Conversion is only possible for strings of length one. 822 // comparison. Conversion is only possible for strings of length one.
823 // E.g., detect str[x] == "x"; and use an integer comparison of char-codes. 823 // E.g., detect str[x] == "x"; and use an integer comparison of char-codes.
824 // TODO(srdjan): Expand for two-byte and external strings. 824 // TODO(srdjan): Expand for two-byte and external strings.
825 bool AotOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call, 825 bool AotOptimizer::TryStringLengthOneEquality(InstanceCallInstr* call,
826 Token::Kind op_kind) { 826 Token::Kind op_kind) {
827 ASSERT(HasOnlyTwoOf(*call->ic_data(), kOneByteStringCid)); 827 ASSERT(HasOnlyTwoOf(*call->ic_data(), kOneByteStringCid));
828 // Check that left and right are length one strings (either string constants 828 // Check that left and right are length one strings (either string constants
829 // or results of string-from-char-code. 829 // or results of string-from-char-code.
830 Definition* left = call->ArgumentAt(0); 830 Definition* left = call->ArgumentAt(0);
831 Definition* right = call->ArgumentAt(1); 831 Definition* right = call->ArgumentAt(1);
832 Value* left_val = NULL; 832 Value* left_val = NULL;
833 Definition* to_remove_left = NULL; 833 Definition* to_remove_left = NULL;
834 if (IsLengthOneString(right)) { 834 if (IsLengthOneString(right)) {
835 // Swap, since we know that both arguments are strings 835 // Swap, since we know that both arguments are strings
836 Definition* temp = left; 836 Definition* temp = left;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 } 903 }
904 return true; 904 return true;
905 } 905 }
906 return false; 906 return false;
907 } 907 }
908 908
909 909
910 static bool SmiFitsInDouble() { return kSmiBits < 53; } 910 static bool SmiFitsInDouble() { return kSmiBits < 53; }
911 911
912 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, 912 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
913 Token::Kind op_kind) { 913 Token::Kind op_kind) {
914 const ICData& ic_data = *call->ic_data(); 914 const ICData& ic_data = *call->ic_data();
915 ASSERT(ic_data.NumArgsTested() == 2); 915 ASSERT(ic_data.NumArgsTested() == 2);
916 916
917 ASSERT(call->ArgumentCount() == 2); 917 ASSERT(call->ArgumentCount() == 2);
918 Definition* left = call->ArgumentAt(0); 918 Definition* left = call->ArgumentAt(0);
919 Definition* right = call->ArgumentAt(1); 919 Definition* right = call->ArgumentAt(1);
920 920
921 intptr_t cid = kIllegalCid; 921 intptr_t cid = kIllegalCid;
922 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { 922 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) {
923 if (TryStringLengthOneEquality(call, op_kind)) { 923 if (TryStringLengthOneEquality(call, op_kind)) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 new(Z) Value(left), 1012 new(Z) Value(left),
1013 new(Z) Value(right), 1013 new(Z) Value(right),
1014 cid, 1014 cid,
1015 call->deopt_id()); 1015 call->deopt_id());
1016 ReplaceCall(call, comp); 1016 ReplaceCall(call, comp);
1017 return true; 1017 return true;
1018 } 1018 }
1019 1019
1020 1020
1021 bool AotOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call, 1021 bool AotOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call,
1022 Token::Kind op_kind) { 1022 Token::Kind op_kind) {
1023 const ICData& ic_data = *call->ic_data(); 1023 const ICData& ic_data = *call->ic_data();
1024 ASSERT(ic_data.NumArgsTested() == 2); 1024 ASSERT(ic_data.NumArgsTested() == 2);
1025 1025
1026 ASSERT(call->ArgumentCount() == 2); 1026 ASSERT(call->ArgumentCount() == 2);
1027 Definition* left = call->ArgumentAt(0); 1027 Definition* left = call->ArgumentAt(0);
1028 Definition* right = call->ArgumentAt(1); 1028 Definition* right = call->ArgumentAt(1);
1029 1029
1030 intptr_t cid = kIllegalCid; 1030 intptr_t cid = kIllegalCid;
1031 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 1031 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1032 InsertBefore(call, 1032 InsertBefore(call,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1074 new(Z) Value(left), 1074 new(Z) Value(left),
1075 new(Z) Value(right), 1075 new(Z) Value(right),
1076 cid, 1076 cid,
1077 call->deopt_id()); 1077 call->deopt_id());
1078 ReplaceCall(call, comp); 1078 ReplaceCall(call, comp);
1079 return true; 1079 return true;
1080 } 1080 }
1081 1081
1082 1082
1083 bool AotOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, 1083 bool AotOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
1084 Token::Kind op_kind) { 1084 Token::Kind op_kind) {
1085 intptr_t operands_type = kIllegalCid; 1085 intptr_t operands_type = kIllegalCid;
1086 ASSERT(call->HasICData()); 1086 ASSERT(call->HasICData());
1087 const ICData& ic_data = *call->ic_data(); 1087 const ICData& ic_data = *call->ic_data();
1088 switch (op_kind) { 1088 switch (op_kind) {
1089 case Token::kADD: 1089 case Token::kADD:
1090 case Token::kSUB: 1090 case Token::kSUB:
1091 case Token::kMUL: 1091 case Token::kMUL:
1092 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 1092 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
1093 // Don't generate smi code if the IC data is marked because 1093 // Don't generate smi code if the IC data is marked because
1094 // of an overflow. 1094 // of an overflow.
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
1283 new(Z) Value(left), 1283 new(Z) Value(left),
1284 new(Z) Value(right), 1284 new(Z) Value(right),
1285 call->deopt_id()); 1285 call->deopt_id());
1286 ReplaceCall(call, bin_op); 1286 ReplaceCall(call, bin_op);
1287 } 1287 }
1288 return true; 1288 return true;
1289 } 1289 }
1290 1290
1291 1291
1292 bool AotOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, 1292 bool AotOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call,
1293 Token::Kind op_kind) { 1293 Token::Kind op_kind) {
1294 ASSERT(call->ArgumentCount() == 1); 1294 ASSERT(call->ArgumentCount() == 1);
1295 Definition* input = call->ArgumentAt(0); 1295 Definition* input = call->ArgumentAt(0);
1296 Definition* unary_op = NULL; 1296 Definition* unary_op = NULL;
1297 if (HasOnlyOneSmi(*call->ic_data())) { 1297 if (HasOnlyOneSmi(*call->ic_data())) {
1298 InsertBefore(call, 1298 InsertBefore(call,
1299 new(Z) CheckSmiInstr(new(Z) Value(input), 1299 new(Z) CheckSmiInstr(new(Z) Value(input),
1300 call->deopt_id(), 1300 call->deopt_id(),
1301 call->token_pos()), 1301 call->token_pos()),
1302 call->env(), 1302 call->env(),
1303 FlowGraph::kEffect); 1303 FlowGraph::kEffect);
(...skipping 14 matching lines...) Expand all
1318 return false; 1318 return false;
1319 } 1319 }
1320 ASSERT(unary_op != NULL); 1320 ASSERT(unary_op != NULL);
1321 ReplaceCall(call, unary_op); 1321 ReplaceCall(call, unary_op);
1322 return true; 1322 return true;
1323 } 1323 }
1324 1324
1325 1325
1326 // Using field class 1326 // Using field class
1327 RawField* AotOptimizer::GetField(intptr_t class_id, 1327 RawField* AotOptimizer::GetField(intptr_t class_id,
1328 const String& field_name) { 1328 const String& field_name) {
1329 Class& cls = Class::Handle(Z, isolate()->class_table()->At(class_id)); 1329 Class& cls = Class::Handle(Z, isolate()->class_table()->At(class_id));
1330 Field& field = Field::Handle(Z); 1330 Field& field = Field::Handle(Z);
1331 while (!cls.IsNull()) { 1331 while (!cls.IsNull()) {
1332 field = cls.LookupInstanceField(field_name); 1332 field = cls.LookupInstanceField(field_name);
1333 if (!field.IsNull()) { 1333 if (!field.IsNull()) {
1334 return field.raw(); 1334 return field.raw();
1335 } 1335 }
1336 cls = cls.SuperClass(); 1336 cls = cls.SuperClass();
1337 } 1337 }
1338 return Field::null(); 1338 return Field::null();
(...skipping 27 matching lines...) Expand all
1366 name.ToCString(), cls.ToCString()); 1366 name.ToCString(), cls.ToCString());
1367 } 1367 }
1368 thread()->cha()->AddToLeafClasses(cls); 1368 thread()->cha()->AddToLeafClasses(cls);
1369 return false; 1369 return false;
1370 } 1370 }
1371 } 1371 }
1372 return true; 1372 return true;
1373 } 1373 }
1374 1374
1375 1375
1376 bool AotOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call, 1376 bool AotOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) {
1377 bool allow_check) {
1378 ASSERT(call->HasICData()); 1377 ASSERT(call->HasICData());
1379 const ICData& ic_data = *call->ic_data(); 1378 const ICData& ic_data = *call->ic_data();
1380 ASSERT(ic_data.HasOneTarget()); 1379 ASSERT(ic_data.HasOneTarget());
1381 GrowableArray<intptr_t> class_ids; 1380 GrowableArray<intptr_t> class_ids;
1382 ic_data.GetClassIdsAt(0, &class_ids); 1381 ic_data.GetClassIdsAt(0, &class_ids);
1383 ASSERT(class_ids.length() == 1); 1382 ASSERT(class_ids.length() == 1);
1384 // Inline implicit instance getter. 1383 // Inline implicit instance getter.
1385 const String& field_name = 1384 const String& field_name =
1386 String::Handle(Z, Field::NameFromGetter(call->function_name())); 1385 String::Handle(Z, Field::NameFromGetter(call->function_name()));
1387 const Field& field = 1386 const Field& field =
1388 Field::ZoneHandle(Z, GetField(class_ids[0], field_name)); 1387 Field::ZoneHandle(Z, GetField(class_ids[0], field_name));
1389 ASSERT(!field.IsNull()); 1388 ASSERT(!field.IsNull());
1390 1389
1391 if (InstanceCallNeedsClassCheck(call, RawFunction::kImplicitGetter)) { 1390 if (InstanceCallNeedsClassCheck(call, RawFunction::kImplicitGetter)) {
1392 if (!allow_check) { 1391 return false;
1393 return false;
1394 }
1395 AddReceiverCheck(call);
1396 } 1392 }
1397 LoadFieldInstr* load = new(Z) LoadFieldInstr( 1393 LoadFieldInstr* load = new(Z) LoadFieldInstr(
1398 new(Z) Value(call->ArgumentAt(0)), 1394 new(Z) Value(call->ArgumentAt(0)),
1399 &field, 1395 &field,
1400 AbstractType::ZoneHandle(Z, field.type()), 1396 AbstractType::ZoneHandle(Z, field.type()),
1401 call->token_pos()); 1397 call->token_pos());
1402 load->set_is_immutable(field.is_final()); 1398 load->set_is_immutable(field.is_final());
1403 1399
1404 // No guarded cid in precompiled mode. 1400 // No guarded cid in precompiled mode.
1405 ASSERT(field.guarded_cid() == kDynamicCid); 1401 ASSERT(field.guarded_cid() == kDynamicCid);
1406 1402
1407 // Discard the environment from the original instruction because the load 1403 // Discard the environment from the original instruction because the load
1408 // can't deoptimize. 1404 // can't deoptimize.
1409 call->RemoveEnvironment(); 1405 call->RemoveEnvironment();
1410 ReplaceCall(call, load); 1406 ReplaceCall(call, load);
1411 1407
1412 if (load->result_cid() != kDynamicCid) { 1408 if (load->result_cid() != kDynamicCid) {
1413 // Reset value types if guarded_cid was used. 1409 // Reset value types if guarded_cid was used.
1414 for (Value::Iterator it(load->input_use_list()); 1410 for (Value::Iterator it(load->input_use_list());
1415 !it.Done(); 1411 !it.Done();
1416 it.Advance()) { 1412 it.Advance()) {
1417 it.Current()->SetReachingType(NULL); 1413 it.Current()->SetReachingType(NULL);
1418 } 1414 }
1419 } 1415 }
1420 return true; 1416 return true;
1421 } 1417 }
1422 1418
1423 1419
1424 bool AotOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, 1420 bool AotOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
1425 MethodRecognizer::Kind getter) { 1421 MethodRecognizer::Kind getter) {
1426 if (!ShouldInlineSimd()) { 1422 if (!ShouldInlineSimd()) {
1427 return false; 1423 return false;
1428 } 1424 }
1429 AddCheckClass(call->ArgumentAt(0), 1425 AddCheckClass(call->ArgumentAt(0),
1430 ICData::ZoneHandle( 1426 ICData::ZoneHandle(
1431 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1427 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1432 call->deopt_id(), 1428 call->deopt_id(),
1433 call->env(), 1429 call->env(),
1434 call); 1430 call);
1435 intptr_t mask = 0; 1431 intptr_t mask = 0;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1490 call->deopt_id()); 1486 call->deopt_id());
1491 ReplaceCall(call, instr); 1487 ReplaceCall(call, instr);
1492 return true; 1488 return true;
1493 } 1489 }
1494 UNREACHABLE(); 1490 UNREACHABLE();
1495 return false; 1491 return false;
1496 } 1492 }
1497 1493
1498 1494
1499 bool AotOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call, 1495 bool AotOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call,
1500 MethodRecognizer::Kind getter) { 1496 MethodRecognizer::Kind getter) {
1501 if (!ShouldInlineSimd()) { 1497 if (!ShouldInlineSimd()) {
1502 return false; 1498 return false;
1503 } 1499 }
1504 AddCheckClass(call->ArgumentAt(0), 1500 AddCheckClass(call->ArgumentAt(0),
1505 ICData::ZoneHandle( 1501 ICData::ZoneHandle(
1506 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1502 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1507 call->deopt_id(), 1503 call->deopt_id(),
1508 call->env(), 1504 call->env(),
1509 call); 1505 call);
1510 if ((getter == MethodRecognizer::kFloat64x2GetX) || 1506 if ((getter == MethodRecognizer::kFloat64x2GetX) ||
1511 (getter == MethodRecognizer::kFloat64x2GetY)) { 1507 (getter == MethodRecognizer::kFloat64x2GetY)) {
1512 Simd64x2ShuffleInstr* instr = new(Z) Simd64x2ShuffleInstr( 1508 Simd64x2ShuffleInstr* instr = new(Z) Simd64x2ShuffleInstr(
1513 getter, 1509 getter,
1514 new(Z) Value(call->ArgumentAt(0)), 1510 new(Z) Value(call->ArgumentAt(0)),
1515 0, 1511 0,
1516 call->deopt_id()); 1512 call->deopt_id());
1517 ReplaceCall(call, instr); 1513 ReplaceCall(call, instr);
1518 return true; 1514 return true;
1519 } 1515 }
1520 UNREACHABLE(); 1516 UNREACHABLE();
1521 return false; 1517 return false;
1522 } 1518 }
1523 1519
1524 1520
1525 bool AotOptimizer::InlineInt32x4Getter(InstanceCallInstr* call, 1521 bool AotOptimizer::InlineInt32x4Getter(InstanceCallInstr* call,
1526 MethodRecognizer::Kind getter) { 1522 MethodRecognizer::Kind getter) {
1527 if (!ShouldInlineSimd()) { 1523 if (!ShouldInlineSimd()) {
1528 return false; 1524 return false;
1529 } 1525 }
1530 AddCheckClass(call->ArgumentAt(0), 1526 AddCheckClass(call->ArgumentAt(0),
1531 ICData::ZoneHandle( 1527 ICData::ZoneHandle(
1532 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1528 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1533 call->deopt_id(), 1529 call->deopt_id(),
1534 call->env(), 1530 call->env(),
1535 call); 1531 call);
1536 intptr_t mask = 0; 1532 intptr_t mask = 0;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1591 getter, 1587 getter,
1592 new(Z) Value(call->ArgumentAt(0)), 1588 new(Z) Value(call->ArgumentAt(0)),
1593 call->deopt_id()); 1589 call->deopt_id());
1594 ReplaceCall(call, instr); 1590 ReplaceCall(call, instr);
1595 return true; 1591 return true;
1596 } 1592 }
1597 } 1593 }
1598 1594
1599 1595
1600 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, 1596 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
1601 Token::Kind op_kind) { 1597 Token::Kind op_kind) {
1602 if (!ShouldInlineSimd()) { 1598 if (!ShouldInlineSimd()) {
1603 return false; 1599 return false;
1604 } 1600 }
1605 ASSERT(call->ArgumentCount() == 2); 1601 ASSERT(call->ArgumentCount() == 2);
1606 Definition* left = call->ArgumentAt(0); 1602 Definition* left = call->ArgumentAt(0);
1607 Definition* right = call->ArgumentAt(1); 1603 Definition* right = call->ArgumentAt(1);
1608 // Type check left. 1604 // Type check left.
1609 AddCheckClass(left, 1605 AddCheckClass(left,
1610 ICData::ZoneHandle( 1606 ICData::ZoneHandle(
1611 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1607 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
(...skipping 12 matching lines...) Expand all
1624 new(Z) BinaryFloat32x4OpInstr( 1620 new(Z) BinaryFloat32x4OpInstr(
1625 op_kind, new(Z) Value(left), new(Z) Value(right), 1621 op_kind, new(Z) Value(left), new(Z) Value(right),
1626 call->deopt_id()); 1622 call->deopt_id());
1627 ReplaceCall(call, float32x4_bin_op); 1623 ReplaceCall(call, float32x4_bin_op);
1628 1624
1629 return true; 1625 return true;
1630 } 1626 }
1631 1627
1632 1628
1633 bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, 1629 bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call,
1634 Token::Kind op_kind) { 1630 Token::Kind op_kind) {
1635 if (!ShouldInlineSimd()) { 1631 if (!ShouldInlineSimd()) {
1636 return false; 1632 return false;
1637 } 1633 }
1638 ASSERT(call->ArgumentCount() == 2); 1634 ASSERT(call->ArgumentCount() == 2);
1639 Definition* left = call->ArgumentAt(0); 1635 Definition* left = call->ArgumentAt(0);
1640 Definition* right = call->ArgumentAt(1); 1636 Definition* right = call->ArgumentAt(1);
1641 // Type check left. 1637 // Type check left.
1642 AddCheckClass(left, 1638 AddCheckClass(left,
1643 ICData::ZoneHandle( 1639 ICData::ZoneHandle(
1644 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1640 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
(...skipping 11 matching lines...) Expand all
1656 BinaryInt32x4OpInstr* int32x4_bin_op = 1652 BinaryInt32x4OpInstr* int32x4_bin_op =
1657 new(Z) BinaryInt32x4OpInstr( 1653 new(Z) BinaryInt32x4OpInstr(
1658 op_kind, new(Z) Value(left), new(Z) Value(right), 1654 op_kind, new(Z) Value(left), new(Z) Value(right),
1659 call->deopt_id()); 1655 call->deopt_id());
1660 ReplaceCall(call, int32x4_bin_op); 1656 ReplaceCall(call, int32x4_bin_op);
1661 return true; 1657 return true;
1662 } 1658 }
1663 1659
1664 1660
1665 bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, 1661 bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call,
1666 Token::Kind op_kind) { 1662 Token::Kind op_kind) {
1667 if (!ShouldInlineSimd()) { 1663 if (!ShouldInlineSimd()) {
1668 return false; 1664 return false;
1669 } 1665 }
1670 ASSERT(call->ArgumentCount() == 2); 1666 ASSERT(call->ArgumentCount() == 2);
1671 Definition* left = call->ArgumentAt(0); 1667 Definition* left = call->ArgumentAt(0);
1672 Definition* right = call->ArgumentAt(1); 1668 Definition* right = call->ArgumentAt(1);
1673 // Type check left. 1669 // Type check left.
1674 AddCheckClass(left, 1670 AddCheckClass(left,
1675 ICData::ZoneHandle( 1671 ICData::ZoneHandle(
1676 call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1672 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
(...skipping 11 matching lines...) Expand all
1688 BinaryFloat64x2OpInstr* float64x2_bin_op = 1684 BinaryFloat64x2OpInstr* float64x2_bin_op =
1689 new(Z) BinaryFloat64x2OpInstr( 1685 new(Z) BinaryFloat64x2OpInstr(
1690 op_kind, new(Z) Value(left), new(Z) Value(right), 1686 op_kind, new(Z) Value(left), new(Z) Value(right),
1691 call->deopt_id()); 1687 call->deopt_id());
1692 ReplaceCall(call, float64x2_bin_op); 1688 ReplaceCall(call, float64x2_bin_op);
1693 return true; 1689 return true;
1694 } 1690 }
1695 1691
1696 1692
1697 // Only unique implicit instance getters can be currently handled. 1693 // Only unique implicit instance getters can be currently handled.
1698 // Returns false if 'allow_check' is false and a check is needed. 1694 bool AotOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) {
1699 bool AotOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call,
1700 bool allow_check) {
1701 ASSERT(call->HasICData()); 1695 ASSERT(call->HasICData());
1702 const ICData& ic_data = *call->ic_data(); 1696 const ICData& ic_data = *call->ic_data();
1703 if (ic_data.NumberOfUsedChecks() == 0) { 1697 if (ic_data.NumberOfUsedChecks() == 0) {
1704 // No type feedback collected. 1698 // No type feedback collected.
1705 return false; 1699 return false;
1706 } 1700 }
1707 1701
1708 if (!ic_data.HasOneTarget()) { 1702 if (!ic_data.HasOneTarget()) {
1709 // Polymorphic sites are inlined like normal methods by conventional 1703 // Polymorphic sites are inlined like normal methods by conventional
1710 // inlining in FlowGraphInliner. 1704 // inlining in FlowGraphInliner.
1711 return false; 1705 return false;
1712 } 1706 }
1713 1707
1714 const Function& target = Function::Handle(Z, ic_data.GetTargetAt(0)); 1708 const Function& target = Function::Handle(Z, ic_data.GetTargetAt(0));
1715 if (target.kind() != RawFunction::kImplicitGetter) { 1709 if (target.kind() != RawFunction::kImplicitGetter) {
1716 // Non-implicit getters are inlined like normal methods by conventional 1710 // Non-implicit getters are inlined like normal methods by conventional
1717 // inlining in FlowGraphInliner. 1711 // inlining in FlowGraphInliner.
1718 return false; 1712 return false;
1719 } 1713 }
1720 return InlineImplicitInstanceGetter(call, allow_check); 1714 return InlineImplicitInstanceGetter(call);
1721 } 1715 }
1722 1716
1723 1717
1724 bool AotOptimizer::TryReplaceInstanceCallWithInline( 1718 bool AotOptimizer::TryReplaceInstanceCallWithInline(
1725 InstanceCallInstr* call) { 1719 InstanceCallInstr* call) {
1726 Function& target = Function::Handle(Z); 1720 Function& target = Function::Handle(Z);
1727 GrowableArray<intptr_t> class_ids; 1721 GrowableArray<intptr_t> class_ids;
1728 call->ic_data()->GetCheckAt(0, &class_ids, &target); 1722 call->ic_data()->GetCheckAt(0, &class_ids, &target);
1729 const intptr_t receiver_cid = class_ids[0]; 1723 const intptr_t receiver_cid = class_ids[0];
1730 1724
(...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after
2427 if (Token::IsTypeTestOperator(op_kind)) { 2421 if (Token::IsTypeTestOperator(op_kind)) {
2428 ReplaceWithInstanceOf(instr); 2422 ReplaceWithInstanceOf(instr);
2429 return; 2423 return;
2430 } 2424 }
2431 if (Token::IsTypeCastOperator(op_kind)) { 2425 if (Token::IsTypeCastOperator(op_kind)) {
2432 ReplaceWithTypeCast(instr); 2426 ReplaceWithTypeCast(instr);
2433 return; 2427 return;
2434 } 2428 }
2435 2429
2436 if ((op_kind == Token::kGET) && 2430 if ((op_kind == Token::kGET) &&
2437 TryInlineInstanceGetter(instr, false /* no checks allowed */)) { 2431 TryInlineInstanceGetter(instr)) {
2438 return; 2432 return;
2439 } 2433 }
2440 const ICData& unary_checks = 2434 const ICData& unary_checks =
2441 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); 2435 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks());
2442 if ((unary_checks.NumberOfChecks() > 0) && 2436 if ((unary_checks.NumberOfChecks() > 0) &&
2443 (op_kind == Token::kSET) && 2437 (op_kind == Token::kSET) &&
2444 TryInlineInstanceSetter(instr, unary_checks, false /* no checks */)) { 2438 TryInlineInstanceSetter(instr, unary_checks)) {
2445 return; 2439 return;
2446 } 2440 }
2447 2441
2448 if (use_speculative_inlining_ && 2442 if (use_speculative_inlining_ &&
2449 !IsBlackListedForInlining(instr->deopt_id()) && 2443 !IsBlackListedForInlining(instr->deopt_id()) &&
2450 (unary_checks.NumberOfChecks() > 0)) { 2444 (unary_checks.NumberOfChecks() > 0)) {
2451 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) { 2445 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) {
2452 return; 2446 return;
2453 } 2447 }
2454 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { 2448 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) {
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
2761 void AotOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { 2755 void AotOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) {
2762 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized. 2756 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized.
2763 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) 2757 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
2764 if (!instr->can_pack_into_smi()) 2758 if (!instr->can_pack_into_smi())
2765 instr->set_representation(kUnboxedMint); 2759 instr->set_representation(kUnboxedMint);
2766 #endif 2760 #endif
2767 } 2761 }
2768 2762
2769 2763
2770 bool AotOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, 2764 bool AotOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr,
2771 const ICData& unary_ic_data, 2765 const ICData& unary_ic_data) {
2772 bool allow_checks) {
2773 ASSERT((unary_ic_data.NumberOfChecks() > 0) && 2766 ASSERT((unary_ic_data.NumberOfChecks() > 0) &&
2774 (unary_ic_data.NumArgsTested() == 1)); 2767 (unary_ic_data.NumArgsTested() == 1));
2775 if (I->flags().type_checks()) { 2768 if (I->flags().type_checks()) {
2776 // Checked mode setters are inlined like normal methods by conventional 2769 // Checked mode setters are inlined like normal methods by conventional
2777 // inlining. 2770 // inlining.
2778 return false; 2771 return false;
2779 } 2772 }
2780 2773
2781 ASSERT(instr->HasICData()); 2774 ASSERT(instr->HasICData());
2782 if (unary_ic_data.NumberOfChecks() == 0) { 2775 if (unary_ic_data.NumberOfChecks() == 0) {
(...skipping 13 matching lines...) Expand all
2796 return false; 2789 return false;
2797 } 2790 }
2798 // Inline implicit instance setter. 2791 // Inline implicit instance setter.
2799 const String& field_name = 2792 const String& field_name =
2800 String::Handle(Z, Field::NameFromSetter(instr->function_name())); 2793 String::Handle(Z, Field::NameFromSetter(instr->function_name()));
2801 const Field& field = 2794 const Field& field =
2802 Field::ZoneHandle(Z, GetField(class_id, field_name)); 2795 Field::ZoneHandle(Z, GetField(class_id, field_name));
2803 ASSERT(!field.IsNull()); 2796 ASSERT(!field.IsNull());
2804 2797
2805 if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) { 2798 if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) {
2806 if (!allow_checks) { 2799 return false;
2807 return false;
2808 }
2809 AddReceiverCheck(instr);
2810 }
2811 if (field.guarded_cid() != kDynamicCid) {
2812 if (!allow_checks) {
2813 return false;
2814 }
2815 InsertBefore(instr,
2816 new(Z) GuardFieldClassInstr(
2817 new(Z) Value(instr->ArgumentAt(1)),
2818 field,
2819 instr->deopt_id()),
2820 instr->env(),
2821 FlowGraph::kEffect);
2822 }
2823
2824 if (field.needs_length_check()) {
2825 if (!allow_checks) {
2826 return false;
2827 }
2828 InsertBefore(instr,
2829 new(Z) GuardFieldLengthInstr(
2830 new(Z) Value(instr->ArgumentAt(1)),
2831 field,
2832 instr->deopt_id()),
2833 instr->env(),
2834 FlowGraph::kEffect);
2835 } 2800 }
2836 2801
2837 // Field guard was detached. 2802 // Field guard was detached.
2838 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( 2803 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr(
2839 field, 2804 field,
2840 new(Z) Value(instr->ArgumentAt(0)), 2805 new(Z) Value(instr->ArgumentAt(0)),
2841 new(Z) Value(instr->ArgumentAt(1)), 2806 new(Z) Value(instr->ArgumentAt(1)),
2842 kEmitStoreBarrier, 2807 kEmitStoreBarrier,
2843 instr->token_pos()); 2808 instr->token_pos());
2844 2809
2845 // No unboxed stores in precompiled code. 2810 // No unboxed stores in precompiled code.
2846 ASSERT(!store->IsUnboxedStore()); 2811 ASSERT(!store->IsUnboxedStore());
2847 2812
2848 // Discard the environment from the original instruction because the store 2813 // Discard the environment from the original instruction because the store
2849 // can't deoptimize. 2814 // can't deoptimize.
2850 instr->RemoveEnvironment(); 2815 instr->RemoveEnvironment();
2851 ReplaceCall(instr, store); 2816 ReplaceCall(instr, store);
2852 return true; 2817 return true;
2853 } 2818 }
2854 2819
2855 2820
2856 } // namespace dart 2821 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/aot_optimizer.h ('k') | runtime/vm/compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698