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

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

Issue 26191002: Hook ByteArrayViewLoad operations into polymorphic inliner (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 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
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/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/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { 822 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) {
823 // Check for monomorphic IC data. 823 // Check for monomorphic IC data.
824 if (!call->HasICData()) return false; 824 if (!call->HasICData()) return false;
825 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); 825 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks());
826 if (ic_data.NumberOfChecks() != 1) return false; 826 if (ic_data.NumberOfChecks() != 1) return false;
827 ASSERT(ic_data.HasOneTarget()); 827 ASSERT(ic_data.HasOneTarget());
828 828
829 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); 829 const Function& target = Function::Handle(ic_data.GetTargetAt(0));
830 TargetEntryInstr* entry; 830 TargetEntryInstr* entry;
831 Definition* last; 831 Definition* last;
832 if (!TryInlineRecognizedMethod(target, 832 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0),
833 target,
833 call, 834 call,
834 call->token_pos(), 835 call->token_pos(),
835 *call->ic_data(), 836 *call->ic_data(),
836 &entry, &last)) { 837 &entry, &last)) {
837 return false; 838 return false;
838 } 839 }
839 // Insert receiver class check. 840 // Insert receiver class check.
840 AddReceiverCheck(call); 841 AddReceiverCheck(call);
841 // Remove the original push arguments. 842 // Remove the original push arguments.
842 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 843 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
988 array_cid, 989 array_cid,
989 call->deopt_id()); 990 call->deopt_id());
990 flow_graph()->AppendTo(cursor, 991 flow_graph()->AppendTo(cursor,
991 *last, 992 *last,
992 call->env(), 993 call->env(),
993 Definition::kEffect); 994 Definition::kEffect);
994 return true; 995 return true;
995 } 996 }
996 997
997 998
998 bool FlowGraphOptimizer::TryInlineRecognizedMethod(const Function& target, 999 bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid,
1000 const Function& target,
999 Instruction* call, 1001 Instruction* call,
1000 intptr_t token_pos, 1002 intptr_t token_pos,
1001 const ICData& ic_data, 1003 const ICData& ic_data,
1002 TargetEntryInstr** entry, 1004 TargetEntryInstr** entry,
1003 Definition** last) { 1005 Definition** last) {
1004 ICData& value_check = ICData::ZoneHandle(); 1006 ICData& value_check = ICData::ZoneHandle();
1005 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target); 1007 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target);
1006 switch (kind) { 1008 switch (kind) {
1007 // Recognized [] operators. 1009 // Recognized [] operators.
1008 case MethodRecognizer::kImmutableArrayGetIndexed: 1010 case MethodRecognizer::kImmutableArrayGetIndexed:
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 value_check = ic_data.AsUnaryClassChecksForArgNr(2); 1069 value_check = ic_data.AsUnaryClassChecksForArgNr(2);
1068 return InlineSetIndexed(kind, target, call, token_pos, 1070 return InlineSetIndexed(kind, target, call, token_pos,
1069 &ic_data, value_check, entry, last); 1071 &ic_data, value_check, entry, last);
1070 case MethodRecognizer::kFloat32x4ArraySetIndexed: 1072 case MethodRecognizer::kFloat32x4ArraySetIndexed:
1071 if (!ShouldInlineSimd()) return false; 1073 if (!ShouldInlineSimd()) return false;
1072 // Check that value is always a Float32x4. 1074 // Check that value is always a Float32x4.
1073 if (!ArgIsAlways(kFloat32x4Cid, ic_data, 2)) return false; 1075 if (!ArgIsAlways(kFloat32x4Cid, ic_data, 2)) return false;
1074 value_check = ic_data.AsUnaryClassChecksForArgNr(2); 1076 value_check = ic_data.AsUnaryClassChecksForArgNr(2);
1075 return InlineSetIndexed(kind, target, call, token_pos, 1077 return InlineSetIndexed(kind, target, call, token_pos,
1076 &ic_data, value_check, entry, last); 1078 &ic_data, value_check, entry, last);
1079 case MethodRecognizer::kByteArrayBaseGetInt8:
Cutch 2013/10/22 03:46:16 We now support polymorphic inlining loads on byte
1080 return InlineByteArrayViewLoad(call, receiver_cid,
1081 kTypedDataInt8ArrayCid,
1082 ic_data, entry, last);
1083 case MethodRecognizer::kByteArrayBaseGetUint8:
1084 return InlineByteArrayViewLoad(call, receiver_cid,
1085 kTypedDataUint8ArrayCid,
1086 ic_data, entry, last);
1087 case MethodRecognizer::kByteArrayBaseGetInt16:
1088 return InlineByteArrayViewLoad(call, receiver_cid,
1089 kTypedDataInt16ArrayCid,
1090 ic_data, entry, last);
1091 case MethodRecognizer::kByteArrayBaseGetUint16:
1092 return InlineByteArrayViewLoad(call, receiver_cid,
1093 kTypedDataUint16ArrayCid,
1094 ic_data, entry, last);
1095 case MethodRecognizer::kByteArrayBaseGetInt32:
1096 if (!CanUnboxInt32()) return false;
1097 return InlineByteArrayViewLoad(call, receiver_cid,
1098 kTypedDataInt32ArrayCid,
1099 ic_data, entry, last);
1100 case MethodRecognizer::kByteArrayBaseGetUint32:
1101 if (!CanUnboxInt32()) return false;
1102 return InlineByteArrayViewLoad(call, receiver_cid,
1103 kTypedDataUint32ArrayCid,
1104 ic_data, entry, last);
1105 case MethodRecognizer::kByteArrayBaseGetFloat32:
1106 return InlineByteArrayViewLoad(call, receiver_cid,
1107 kTypedDataFloat32ArrayCid,
1108 ic_data, entry, last);
1109 case MethodRecognizer::kByteArrayBaseGetFloat64:
1110 return InlineByteArrayViewLoad(call, receiver_cid,
1111 kTypedDataFloat64ArrayCid,
1112 ic_data, entry, last);
1113 case MethodRecognizer::kByteArrayBaseGetFloat32x4:
Florian Schneider 2013/10/22 15:57:33 Do you need to check for ShouldInlineSimd() here?
Cutch 2013/10/23 09:19:52 Done.
1114 return InlineByteArrayViewLoad(call, receiver_cid,
1115 kTypedDataFloat32x4ArrayCid,
1116 ic_data, entry, last);
1077 default: 1117 default:
1078 return false; 1118 return false;
1079 } 1119 }
1080 } 1120 }
1081 1121
1082 1122
1083 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, 1123 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call,
1084 intptr_t array_cid, 1124 intptr_t array_cid,
1085 Definition** array, 1125 Definition** array,
1086 Definition* index, 1126 Definition* index,
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1191 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { 1231 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) {
1192 // Check for monomorphic IC data. 1232 // Check for monomorphic IC data.
1193 if (!call->HasICData()) return false; 1233 if (!call->HasICData()) return false;
1194 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); 1234 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks());
1195 if (ic_data.NumberOfChecks() != 1) return false; 1235 if (ic_data.NumberOfChecks() != 1) return false;
1196 ASSERT(ic_data.HasOneTarget()); 1236 ASSERT(ic_data.HasOneTarget());
1197 1237
1198 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); 1238 const Function& target = Function::Handle(ic_data.GetTargetAt(0));
1199 TargetEntryInstr* entry; 1239 TargetEntryInstr* entry;
1200 Definition* last; 1240 Definition* last;
1201 if (!TryInlineRecognizedMethod(target, 1241 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0),
1242 target,
1202 call, 1243 call,
1203 call->token_pos(), 1244 call->token_pos(),
1204 *call->ic_data(), 1245 *call->ic_data(),
1205 &entry, &last)) { 1246 &entry, &last)) {
1206 return false; 1247 return false;
1207 } 1248 }
1208 1249
1209 // Insert receiver class check. 1250 // Insert receiver class check.
1210 AddReceiverCheck(call); 1251 AddReceiverCheck(call);
1211 // Remove the original push arguments. 1252 // Remove the original push arguments.
(...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after
2019 if ((recognized_kind == MethodRecognizer::kByteArrayBaseGetInt32) || 2060 if ((recognized_kind == MethodRecognizer::kByteArrayBaseGetInt32) ||
2020 (recognized_kind == MethodRecognizer::kByteArrayBaseGetUint32) || 2061 (recognized_kind == MethodRecognizer::kByteArrayBaseGetUint32) ||
2021 (recognized_kind == MethodRecognizer::kByteArrayBaseSetInt32) || 2062 (recognized_kind == MethodRecognizer::kByteArrayBaseSetInt32) ||
2022 (recognized_kind == MethodRecognizer::kByteArrayBaseSetUint32)) { 2063 (recognized_kind == MethodRecognizer::kByteArrayBaseSetUint32)) {
2023 if (!CanUnboxInt32()) return false; 2064 if (!CanUnboxInt32()) return false;
2024 } 2065 }
2025 2066
2026 switch (recognized_kind) { 2067 switch (recognized_kind) {
2027 // ByteArray getters. 2068 // ByteArray getters.
2028 case MethodRecognizer::kByteArrayBaseGetInt8: 2069 case MethodRecognizer::kByteArrayBaseGetInt8:
2029 return BuildByteArrayViewLoad( 2070 return BuildByteArrayViewLoad(call, kTypedDataInt8ArrayCid);
2030 call, class_ids[0], kTypedDataInt8ArrayCid);
2031 case MethodRecognizer::kByteArrayBaseGetUint8: 2071 case MethodRecognizer::kByteArrayBaseGetUint8:
2032 return BuildByteArrayViewLoad( 2072 return BuildByteArrayViewLoad(call, kTypedDataUint8ArrayCid);
Cutch 2013/10/22 03:46:16 Cleanup so that signatures of BuildByteArrayViewLo
2033 call, class_ids[0], kTypedDataUint8ArrayCid);
2034 case MethodRecognizer::kByteArrayBaseGetInt16: 2073 case MethodRecognizer::kByteArrayBaseGetInt16:
2035 return BuildByteArrayViewLoad( 2074 return BuildByteArrayViewLoad(call, kTypedDataInt16ArrayCid);
2036 call, class_ids[0], kTypedDataInt16ArrayCid);
2037 case MethodRecognizer::kByteArrayBaseGetUint16: 2075 case MethodRecognizer::kByteArrayBaseGetUint16:
2038 return BuildByteArrayViewLoad( 2076 return BuildByteArrayViewLoad(call, kTypedDataUint16ArrayCid);
2039 call, class_ids[0], kTypedDataUint16ArrayCid);
2040 case MethodRecognizer::kByteArrayBaseGetInt32: 2077 case MethodRecognizer::kByteArrayBaseGetInt32:
2041 return BuildByteArrayViewLoad( 2078 return BuildByteArrayViewLoad(call, kTypedDataInt32ArrayCid);
2042 call, class_ids[0], kTypedDataInt32ArrayCid);
2043 case MethodRecognizer::kByteArrayBaseGetUint32: 2079 case MethodRecognizer::kByteArrayBaseGetUint32:
2044 return BuildByteArrayViewLoad( 2080 return BuildByteArrayViewLoad(call, kTypedDataUint32ArrayCid);
2045 call, class_ids[0], kTypedDataUint32ArrayCid);
2046 case MethodRecognizer::kByteArrayBaseGetFloat32: 2081 case MethodRecognizer::kByteArrayBaseGetFloat32:
2047 return BuildByteArrayViewLoad( 2082 return BuildByteArrayViewLoad(call, kTypedDataFloat32ArrayCid);
2048 call, class_ids[0], kTypedDataFloat32ArrayCid);
2049 case MethodRecognizer::kByteArrayBaseGetFloat64: 2083 case MethodRecognizer::kByteArrayBaseGetFloat64:
2050 return BuildByteArrayViewLoad( 2084 return BuildByteArrayViewLoad(call, kTypedDataFloat64ArrayCid);
2051 call, class_ids[0], kTypedDataFloat64ArrayCid);
2052 case MethodRecognizer::kByteArrayBaseGetFloat32x4: 2085 case MethodRecognizer::kByteArrayBaseGetFloat32x4:
2053 return BuildByteArrayViewLoad( 2086 return BuildByteArrayViewLoad(call, kTypedDataFloat32x4ArrayCid);
2054 call, class_ids[0], kTypedDataFloat32x4ArrayCid);
2055 2087
2056 // ByteArray setters. 2088 // ByteArray setters.
2057 case MethodRecognizer::kByteArrayBaseSetInt8: 2089 case MethodRecognizer::kByteArrayBaseSetInt8:
2058 return BuildByteArrayViewStore(call, kTypedDataInt8ArrayCid); 2090 return BuildByteArrayViewStore(call, kTypedDataInt8ArrayCid);
2059 case MethodRecognizer::kByteArrayBaseSetUint8: 2091 case MethodRecognizer::kByteArrayBaseSetUint8:
2060 return BuildByteArrayViewStore(call, kTypedDataUint8ArrayCid); 2092 return BuildByteArrayViewStore(call, kTypedDataUint8ArrayCid);
2061 case MethodRecognizer::kByteArrayBaseSetInt16: 2093 case MethodRecognizer::kByteArrayBaseSetInt16:
2062 return BuildByteArrayViewStore(call, kTypedDataInt16ArrayCid); 2094 return BuildByteArrayViewStore(call, kTypedDataInt16ArrayCid);
2063 case MethodRecognizer::kByteArrayBaseSetUint16: 2095 case MethodRecognizer::kByteArrayBaseSetUint16:
2064 return BuildByteArrayViewStore(call, kTypedDataUint16ArrayCid); 2096 return BuildByteArrayViewStore(call, kTypedDataUint16ArrayCid);
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
2442 call->deopt_id()); 2474 call->deopt_id());
2443 ReplaceCall(call, setFlag); 2475 ReplaceCall(call, setFlag);
2444 return true; 2476 return true;
2445 } 2477 }
2446 default: 2478 default:
2447 return false; 2479 return false;
2448 } 2480 }
2449 } 2481 }
2450 2482
2451 2483
2452 bool FlowGraphOptimizer::BuildByteArrayViewLoad( 2484 bool FlowGraphOptimizer::InlineByteArrayViewLoad(Instruction* call,
2453 InstanceCallInstr* call, 2485 intptr_t array_cid,
2454 intptr_t receiver_cid, 2486 intptr_t view_cid,
2455 intptr_t view_cid) { 2487 const ICData& ic_data,
2488 TargetEntryInstr** entry,
2489 Definition** last) {
2490 ASSERT(array_cid != kIllegalCid);
2491 Definition* array = call->ArgumentAt(0);
2492 Definition* index = call->ArgumentAt(1);
2493 *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(),
2494 call->GetBlock()->try_index());
2495 (*entry)->InheritDeoptTarget(call);
2496 Instruction* cursor = *entry;
2497
2498 array_cid = PrepareInlineByteArrayViewOp(call,
2499 array_cid,
2500 view_cid,
2501 &array,
2502 index,
2503 &cursor);
2504
2505 intptr_t deopt_id = Isolate::kNoDeoptId;
2506 if ((array_cid == kTypedDataInt32ArrayCid) ||
2507 (array_cid == kTypedDataUint32ArrayCid)) {
2508 // Set deopt_id if we can optimistically assume that the result is Smi.
2509 // Assume mixed Mint/Smi if this instruction caused deoptimization once.
2510 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ?
2511 call->deopt_id() : Isolate::kNoDeoptId;
2512 }
2513
2514 *last = new LoadIndexedInstr(new Value(array),
2515 new Value(index),
2516 1,
2517 view_cid,
2518 deopt_id);
2519 flow_graph()->AppendTo(cursor,
2520 *last,
2521 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL,
2522 Definition::kValue);
2523 return true;
2524 }
2525
2526
2527 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp(
2528 Instruction* call,
2529 intptr_t array_cid,
2530 intptr_t view_cid,
2531 Definition** array,
2532 Definition* byte_index,
2533 Instruction** cursor) {
2534 // Insert byte_index smi check.
2535 *cursor = flow_graph()->AppendTo(*cursor,
2536 new CheckSmiInstr(new Value(byte_index),
2537 call->deopt_id()),
2538 call->env(),
2539 Definition::kEffect);
2540
2541 const bool is_immutable = true;
2542 LoadFieldInstr* length =
2543 new LoadFieldInstr(new Value(*array),
2544 CheckArrayBoundInstr::LengthOffsetFor(array_cid),
2545 Type::ZoneHandle(Type::SmiType()),
2546 is_immutable);
2547 length->set_result_cid(kSmiCid);
2548 length->set_recognized_kind(
2549 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
2550 *cursor = flow_graph()->AppendTo(*cursor,
2551 length,
2552 NULL,
2553 Definition::kValue);
2554
2555 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid);
2556 ConstantInstr* bytes_per_element =
2557 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size)));
2558 BinarySmiOpInstr* len_in_bytes =
2559 new BinarySmiOpInstr(Token::kMUL,
2560 new Value(length),
2561 new Value(bytes_per_element),
2562 call->deopt_id());
2563 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(),
2564 Definition::kValue);
2565
2566 ConstantInstr* length_adjustment =
2567 flow_graph()->GetConstant(Smi::Handle(Smi::New(
2568 FlowGraphCompiler::ElementSizeFor(view_cid) - 1)));
2569 // adjusted_length = len_in_bytes - (element_size - 1).
2570 BinarySmiOpInstr* adjusted_length =
2571 new BinarySmiOpInstr(Token::kSUB,
2572 new Value(len_in_bytes),
2573 new Value(length_adjustment),
2574 call->deopt_id());
2575 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(),
2576 Definition::kValue);
2577
2578 // Check adjusted_length > 0.
2579 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0)));
2580 *cursor = flow_graph()->AppendTo(*cursor,
2581 new CheckArrayBoundInstr(
2582 new Value(adjusted_length),
2583 new Value(zero),
2584 call->deopt_id()),
2585 call->env(),
2586 Definition::kEffect);
2587 // Check 0 <= byte_index < adjusted_length.
2588 *cursor = flow_graph()->AppendTo(*cursor,
2589 new CheckArrayBoundInstr(
2590 new Value(adjusted_length),
2591 new Value(byte_index),
2592 call->deopt_id()),
2593 call->env(),
2594 Definition::kEffect);
2595
2596 if (RawObject::IsExternalTypedDataClassId(array_cid)) {
2597 LoadUntaggedInstr* elements =
2598 new LoadUntaggedInstr(new Value(*array),
2599 ExternalTypedData::data_offset());
2600 *cursor = flow_graph()->AppendTo(*cursor,
2601 elements,
2602 NULL,
2603 Definition::kValue);
2604 *array = elements;
2605 }
2606 return array_cid;
2607 }
2608
2609
2610 bool FlowGraphOptimizer::BuildByteArrayViewLoad(InstanceCallInstr* call,
2611 intptr_t view_cid) {
2456 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) { 2612 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) {
2457 return false; 2613 return false;
2458 } 2614 }
2459 2615
2460 Definition* array = call->ArgumentAt(0); 2616 ASSERT(call->HasICData());
2461 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array); 2617 Function& target = Function::Handle();
2618 GrowableArray<intptr_t> class_ids;
2619 call->ic_data()->GetCheckAt(0, &class_ids, &target);
2620 const intptr_t receiver_cid = class_ids[0];
2462 2621
2463 // Optimistically build a smi-checked load for Int32 and Uint32 2622 TargetEntryInstr* entry;
2464 // loads on ia32 like we do for normal array loads, and only revert to 2623 Definition* last;
2465 // mint case after deoptimizing here. 2624 if (!TryInlineRecognizedMethod(receiver_cid,
2466 intptr_t deopt_id = Isolate::kNoDeoptId; 2625 target,
2467 if ((view_cid == kTypedDataInt32ArrayCid || 2626 call,
2468 view_cid == kTypedDataUint32ArrayCid) && 2627 call->token_pos(),
2469 call->ic_data()->deopt_reason() == kDeoptUnknown) { 2628 *call->ic_data(),
2470 deopt_id = call->deopt_id(); 2629 &entry, &last)) {
2630 return false;
2471 } 2631 }
2472 Definition* byte_index = call->ArgumentAt(1); 2632
2473 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array), 2633 // Insert receiver class check.
2474 new Value(byte_index), 2634 AddReceiverCheck(call);
2475 1, // Index scale. 2635 // Remove the original push arguments.
2476 view_cid, 2636 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
2477 deopt_id); 2637 PushArgumentInstr* push = call->PushArgumentAt(i);
2478 ReplaceCall(call, array_op); 2638 push->ReplaceUsesWith(push->value()->definition());
2639 push->RemoveFromGraph();
2640 }
2641 // Replace all uses of this definition with the result.
2642 call->ReplaceUsesWith(last);
2643 // Finally insert the sequence other definition in place of this one in the
2644 // graph.
2645 call->previous()->LinkTo(entry->next());
2646 entry->UnuseAllInputs(); // Entry block is not in the graph.
2647 last->LinkTo(call);
2648 // Remove through the iterator.
2649 ASSERT(current_iterator()->Current() == call);
2650 current_iterator()->RemoveCurrentFromGraph();
2651 call->set_previous(NULL);
2652 call->set_next(NULL);
2479 return true; 2653 return true;
2480 } 2654 }
2481 2655
2482 2656
2483 bool FlowGraphOptimizer::BuildByteArrayViewStore(InstanceCallInstr* call, 2657 bool FlowGraphOptimizer::BuildByteArrayViewStore(InstanceCallInstr* call,
2484 intptr_t view_cid) { 2658 intptr_t view_cid) {
2485 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) { 2659 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) {
2486 return false; 2660 return false;
2487 } 2661 }
2488 ASSERT(call->HasICData()); 2662 ASSERT(call->HasICData());
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
2818 return; 2992 return;
2819 } 2993 }
2820 if ((op_kind == Token::kSET) && 2994 if ((op_kind == Token::kSET) &&
2821 TryInlineInstanceSetter(instr, unary_checks)) { 2995 TryInlineInstanceSetter(instr, unary_checks)) {
2822 return; 2996 return;
2823 } 2997 }
2824 if (TryInlineInstanceMethod(instr)) { 2998 if (TryInlineInstanceMethod(instr)) {
2825 return; 2999 return;
2826 } 3000 }
2827 3001
2828 const bool has_one_target = unary_checks.HasOneTarget(); 3002 bool has_one_target = unary_checks.HasOneTarget();
3003
3004 if (has_one_target) {
3005 // Check if the single target is a polymorphic target, if it is,
3006 // we don't have one target.
3007 const Function& target = Function::Handle(unary_checks.GetTargetAt(0));
3008 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target);
3009 has_one_target = !polymorphic_target;
3010 }
2829 3011
2830 if (has_one_target) { 3012 if (has_one_target) {
2831 const bool is_method_extraction = 3013 const bool is_method_extraction =
2832 Function::Handle(unary_checks.GetTargetAt(0)).IsMethodExtractor(); 3014 Function::Handle(unary_checks.GetTargetAt(0)).IsMethodExtractor();
2833 3015
2834 if ((is_method_extraction && !MethodExtractorNeedsClassCheck(instr)) || 3016 if ((is_method_extraction && !MethodExtractorNeedsClassCheck(instr)) ||
2835 (!is_method_extraction && !InstanceCallNeedsClassCheck(instr))) { 3017 (!is_method_extraction && !InstanceCallNeedsClassCheck(instr))) {
2836 const bool call_with_checks = false; 3018 const bool call_with_checks = false;
2837 PolymorphicInstanceCallInstr* call = 3019 PolymorphicInstanceCallInstr* call =
2838 new PolymorphicInstanceCallInstr(instr, unary_checks, 3020 new PolymorphicInstanceCallInstr(instr, unary_checks,
(...skipping 4914 matching lines...) Expand 10 before | Expand all | Expand 10 after
7753 } 7935 }
7754 7936
7755 // Insert materializations at environment uses. 7937 // Insert materializations at environment uses.
7756 for (intptr_t i = 0; i < exits.length(); i++) { 7938 for (intptr_t i = 0; i < exits.length(); i++) {
7757 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); 7939 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
7758 } 7940 }
7759 } 7941 }
7760 7942
7761 7943
7762 } // namespace dart 7944 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698