| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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: |
| 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: |
| 1114 if (!ShouldInlineSimd()) return false; |
| 1115 return InlineByteArrayViewLoad(call, receiver_cid, |
| 1116 kTypedDataFloat32x4ArrayCid, |
| 1117 ic_data, entry, last); |
| 1077 default: | 1118 default: |
| 1078 return false; | 1119 return false; |
| 1079 } | 1120 } |
| 1080 } | 1121 } |
| 1081 | 1122 |
| 1082 | 1123 |
| 1083 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, | 1124 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, |
| 1084 intptr_t array_cid, | 1125 intptr_t array_cid, |
| 1085 Definition** array, | 1126 Definition** array, |
| 1086 Definition* index, | 1127 Definition* index, |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { | 1232 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { |
| 1192 // Check for monomorphic IC data. | 1233 // Check for monomorphic IC data. |
| 1193 if (!call->HasICData()) return false; | 1234 if (!call->HasICData()) return false; |
| 1194 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); | 1235 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); |
| 1195 if (ic_data.NumberOfChecks() != 1) return false; | 1236 if (ic_data.NumberOfChecks() != 1) return false; |
| 1196 ASSERT(ic_data.HasOneTarget()); | 1237 ASSERT(ic_data.HasOneTarget()); |
| 1197 | 1238 |
| 1198 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); | 1239 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); |
| 1199 TargetEntryInstr* entry; | 1240 TargetEntryInstr* entry; |
| 1200 Definition* last; | 1241 Definition* last; |
| 1201 if (!TryInlineRecognizedMethod(target, | 1242 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), |
| 1243 target, |
| 1202 call, | 1244 call, |
| 1203 call->token_pos(), | 1245 call->token_pos(), |
| 1204 *call->ic_data(), | 1246 *call->ic_data(), |
| 1205 &entry, &last)) { | 1247 &entry, &last)) { |
| 1206 return false; | 1248 return false; |
| 1207 } | 1249 } |
| 1208 | 1250 |
| 1209 // Insert receiver class check. | 1251 // Insert receiver class check. |
| 1210 AddReceiverCheck(call); | 1252 AddReceiverCheck(call); |
| 1211 // Remove the original push arguments. | 1253 // Remove the original push arguments. |
| (...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2019 if ((recognized_kind == MethodRecognizer::kByteArrayBaseGetInt32) || | 2061 if ((recognized_kind == MethodRecognizer::kByteArrayBaseGetInt32) || |
| 2020 (recognized_kind == MethodRecognizer::kByteArrayBaseGetUint32) || | 2062 (recognized_kind == MethodRecognizer::kByteArrayBaseGetUint32) || |
| 2021 (recognized_kind == MethodRecognizer::kByteArrayBaseSetInt32) || | 2063 (recognized_kind == MethodRecognizer::kByteArrayBaseSetInt32) || |
| 2022 (recognized_kind == MethodRecognizer::kByteArrayBaseSetUint32)) { | 2064 (recognized_kind == MethodRecognizer::kByteArrayBaseSetUint32)) { |
| 2023 if (!CanUnboxInt32()) return false; | 2065 if (!CanUnboxInt32()) return false; |
| 2024 } | 2066 } |
| 2025 | 2067 |
| 2026 switch (recognized_kind) { | 2068 switch (recognized_kind) { |
| 2027 // ByteArray getters. | 2069 // ByteArray getters. |
| 2028 case MethodRecognizer::kByteArrayBaseGetInt8: | 2070 case MethodRecognizer::kByteArrayBaseGetInt8: |
| 2029 return BuildByteArrayViewLoad( | 2071 return BuildByteArrayViewLoad(call, kTypedDataInt8ArrayCid); |
| 2030 call, class_ids[0], kTypedDataInt8ArrayCid); | |
| 2031 case MethodRecognizer::kByteArrayBaseGetUint8: | 2072 case MethodRecognizer::kByteArrayBaseGetUint8: |
| 2032 return BuildByteArrayViewLoad( | 2073 return BuildByteArrayViewLoad(call, kTypedDataUint8ArrayCid); |
| 2033 call, class_ids[0], kTypedDataUint8ArrayCid); | |
| 2034 case MethodRecognizer::kByteArrayBaseGetInt16: | 2074 case MethodRecognizer::kByteArrayBaseGetInt16: |
| 2035 return BuildByteArrayViewLoad( | 2075 return BuildByteArrayViewLoad(call, kTypedDataInt16ArrayCid); |
| 2036 call, class_ids[0], kTypedDataInt16ArrayCid); | |
| 2037 case MethodRecognizer::kByteArrayBaseGetUint16: | 2076 case MethodRecognizer::kByteArrayBaseGetUint16: |
| 2038 return BuildByteArrayViewLoad( | 2077 return BuildByteArrayViewLoad(call, kTypedDataUint16ArrayCid); |
| 2039 call, class_ids[0], kTypedDataUint16ArrayCid); | |
| 2040 case MethodRecognizer::kByteArrayBaseGetInt32: | 2078 case MethodRecognizer::kByteArrayBaseGetInt32: |
| 2041 return BuildByteArrayViewLoad( | 2079 return BuildByteArrayViewLoad(call, kTypedDataInt32ArrayCid); |
| 2042 call, class_ids[0], kTypedDataInt32ArrayCid); | |
| 2043 case MethodRecognizer::kByteArrayBaseGetUint32: | 2080 case MethodRecognizer::kByteArrayBaseGetUint32: |
| 2044 return BuildByteArrayViewLoad( | 2081 return BuildByteArrayViewLoad(call, kTypedDataUint32ArrayCid); |
| 2045 call, class_ids[0], kTypedDataUint32ArrayCid); | |
| 2046 case MethodRecognizer::kByteArrayBaseGetFloat32: | 2082 case MethodRecognizer::kByteArrayBaseGetFloat32: |
| 2047 return BuildByteArrayViewLoad( | 2083 return BuildByteArrayViewLoad(call, kTypedDataFloat32ArrayCid); |
| 2048 call, class_ids[0], kTypedDataFloat32ArrayCid); | |
| 2049 case MethodRecognizer::kByteArrayBaseGetFloat64: | 2084 case MethodRecognizer::kByteArrayBaseGetFloat64: |
| 2050 return BuildByteArrayViewLoad( | 2085 return BuildByteArrayViewLoad(call, kTypedDataFloat64ArrayCid); |
| 2051 call, class_ids[0], kTypedDataFloat64ArrayCid); | |
| 2052 case MethodRecognizer::kByteArrayBaseGetFloat32x4: | 2086 case MethodRecognizer::kByteArrayBaseGetFloat32x4: |
| 2053 return BuildByteArrayViewLoad( | 2087 return BuildByteArrayViewLoad(call, kTypedDataFloat32x4ArrayCid); |
| 2054 call, class_ids[0], kTypedDataFloat32x4ArrayCid); | |
| 2055 | 2088 |
| 2056 // ByteArray setters. | 2089 // ByteArray setters. |
| 2057 case MethodRecognizer::kByteArrayBaseSetInt8: | 2090 case MethodRecognizer::kByteArrayBaseSetInt8: |
| 2058 return BuildByteArrayViewStore(call, kTypedDataInt8ArrayCid); | 2091 return BuildByteArrayViewStore(call, kTypedDataInt8ArrayCid); |
| 2059 case MethodRecognizer::kByteArrayBaseSetUint8: | 2092 case MethodRecognizer::kByteArrayBaseSetUint8: |
| 2060 return BuildByteArrayViewStore(call, kTypedDataUint8ArrayCid); | 2093 return BuildByteArrayViewStore(call, kTypedDataUint8ArrayCid); |
| 2061 case MethodRecognizer::kByteArrayBaseSetInt16: | 2094 case MethodRecognizer::kByteArrayBaseSetInt16: |
| 2062 return BuildByteArrayViewStore(call, kTypedDataInt16ArrayCid); | 2095 return BuildByteArrayViewStore(call, kTypedDataInt16ArrayCid); |
| 2063 case MethodRecognizer::kByteArrayBaseSetUint16: | 2096 case MethodRecognizer::kByteArrayBaseSetUint16: |
| 2064 return BuildByteArrayViewStore(call, kTypedDataUint16ArrayCid); | 2097 return BuildByteArrayViewStore(call, kTypedDataUint16ArrayCid); |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2442 call->deopt_id()); | 2475 call->deopt_id()); |
| 2443 ReplaceCall(call, setFlag); | 2476 ReplaceCall(call, setFlag); |
| 2444 return true; | 2477 return true; |
| 2445 } | 2478 } |
| 2446 default: | 2479 default: |
| 2447 return false; | 2480 return false; |
| 2448 } | 2481 } |
| 2449 } | 2482 } |
| 2450 | 2483 |
| 2451 | 2484 |
| 2452 bool FlowGraphOptimizer::BuildByteArrayViewLoad( | 2485 bool FlowGraphOptimizer::InlineByteArrayViewLoad(Instruction* call, |
| 2453 InstanceCallInstr* call, | 2486 intptr_t array_cid, |
| 2454 intptr_t receiver_cid, | 2487 intptr_t view_cid, |
| 2455 intptr_t view_cid) { | 2488 const ICData& ic_data, |
| 2489 TargetEntryInstr** entry, |
| 2490 Definition** last) { |
| 2491 ASSERT(array_cid != kIllegalCid); |
| 2492 Definition* array = call->ArgumentAt(0); |
| 2493 Definition* index = call->ArgumentAt(1); |
| 2494 *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(), |
| 2495 call->GetBlock()->try_index()); |
| 2496 (*entry)->InheritDeoptTarget(call); |
| 2497 Instruction* cursor = *entry; |
| 2498 |
| 2499 array_cid = PrepareInlineByteArrayViewOp(call, |
| 2500 array_cid, |
| 2501 view_cid, |
| 2502 &array, |
| 2503 index, |
| 2504 &cursor); |
| 2505 |
| 2506 intptr_t deopt_id = Isolate::kNoDeoptId; |
| 2507 if ((array_cid == kTypedDataInt32ArrayCid) || |
| 2508 (array_cid == kTypedDataUint32ArrayCid)) { |
| 2509 // Set deopt_id if we can optimistically assume that the result is Smi. |
| 2510 // Assume mixed Mint/Smi if this instruction caused deoptimization once. |
| 2511 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ? |
| 2512 call->deopt_id() : Isolate::kNoDeoptId; |
| 2513 } |
| 2514 |
| 2515 *last = new LoadIndexedInstr(new Value(array), |
| 2516 new Value(index), |
| 2517 1, |
| 2518 view_cid, |
| 2519 deopt_id); |
| 2520 flow_graph()->AppendTo(cursor, |
| 2521 *last, |
| 2522 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 2523 Definition::kValue); |
| 2524 return true; |
| 2525 } |
| 2526 |
| 2527 |
| 2528 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp( |
| 2529 Instruction* call, |
| 2530 intptr_t array_cid, |
| 2531 intptr_t view_cid, |
| 2532 Definition** array, |
| 2533 Definition* byte_index, |
| 2534 Instruction** cursor) { |
| 2535 // Insert byte_index smi check. |
| 2536 *cursor = flow_graph()->AppendTo(*cursor, |
| 2537 new CheckSmiInstr(new Value(byte_index), |
| 2538 call->deopt_id()), |
| 2539 call->env(), |
| 2540 Definition::kEffect); |
| 2541 |
| 2542 const bool is_immutable = true; |
| 2543 LoadFieldInstr* length = |
| 2544 new LoadFieldInstr(new Value(*array), |
| 2545 CheckArrayBoundInstr::LengthOffsetFor(array_cid), |
| 2546 Type::ZoneHandle(Type::SmiType()), |
| 2547 is_immutable); |
| 2548 length->set_result_cid(kSmiCid); |
| 2549 length->set_recognized_kind( |
| 2550 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid)); |
| 2551 *cursor = flow_graph()->AppendTo(*cursor, |
| 2552 length, |
| 2553 NULL, |
| 2554 Definition::kValue); |
| 2555 |
| 2556 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid); |
| 2557 ConstantInstr* bytes_per_element = |
| 2558 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size))); |
| 2559 BinarySmiOpInstr* len_in_bytes = |
| 2560 new BinarySmiOpInstr(Token::kMUL, |
| 2561 new Value(length), |
| 2562 new Value(bytes_per_element), |
| 2563 call->deopt_id()); |
| 2564 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(), |
| 2565 Definition::kValue); |
| 2566 |
| 2567 ConstantInstr* length_adjustment = |
| 2568 flow_graph()->GetConstant(Smi::Handle(Smi::New( |
| 2569 FlowGraphCompiler::ElementSizeFor(view_cid) - 1))); |
| 2570 // adjusted_length = len_in_bytes - (element_size - 1). |
| 2571 BinarySmiOpInstr* adjusted_length = |
| 2572 new BinarySmiOpInstr(Token::kSUB, |
| 2573 new Value(len_in_bytes), |
| 2574 new Value(length_adjustment), |
| 2575 call->deopt_id()); |
| 2576 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(), |
| 2577 Definition::kValue); |
| 2578 |
| 2579 // Check adjusted_length > 0. |
| 2580 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); |
| 2581 *cursor = flow_graph()->AppendTo(*cursor, |
| 2582 new CheckArrayBoundInstr( |
| 2583 new Value(adjusted_length), |
| 2584 new Value(zero), |
| 2585 call->deopt_id()), |
| 2586 call->env(), |
| 2587 Definition::kEffect); |
| 2588 // Check 0 <= byte_index < adjusted_length. |
| 2589 *cursor = flow_graph()->AppendTo(*cursor, |
| 2590 new CheckArrayBoundInstr( |
| 2591 new Value(adjusted_length), |
| 2592 new Value(byte_index), |
| 2593 call->deopt_id()), |
| 2594 call->env(), |
| 2595 Definition::kEffect); |
| 2596 |
| 2597 if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 2598 LoadUntaggedInstr* elements = |
| 2599 new LoadUntaggedInstr(new Value(*array), |
| 2600 ExternalTypedData::data_offset()); |
| 2601 *cursor = flow_graph()->AppendTo(*cursor, |
| 2602 elements, |
| 2603 NULL, |
| 2604 Definition::kValue); |
| 2605 *array = elements; |
| 2606 } |
| 2607 return array_cid; |
| 2608 } |
| 2609 |
| 2610 |
| 2611 bool FlowGraphOptimizer::BuildByteArrayViewLoad(InstanceCallInstr* call, |
| 2612 intptr_t view_cid) { |
| 2456 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) { | 2613 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) { |
| 2457 return false; | 2614 return false; |
| 2458 } | 2615 } |
| 2459 | 2616 |
| 2460 Definition* array = call->ArgumentAt(0); | 2617 ASSERT(call->HasICData()); |
| 2461 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array); | 2618 Function& target = Function::Handle(); |
| 2619 GrowableArray<intptr_t> class_ids; |
| 2620 call->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 2621 const intptr_t receiver_cid = class_ids[0]; |
| 2462 | 2622 |
| 2463 // Optimistically build a smi-checked load for Int32 and Uint32 | 2623 TargetEntryInstr* entry; |
| 2464 // loads on ia32 like we do for normal array loads, and only revert to | 2624 Definition* last; |
| 2465 // mint case after deoptimizing here. | 2625 if (!TryInlineRecognizedMethod(receiver_cid, |
| 2466 intptr_t deopt_id = Isolate::kNoDeoptId; | 2626 target, |
| 2467 if ((view_cid == kTypedDataInt32ArrayCid || | 2627 call, |
| 2468 view_cid == kTypedDataUint32ArrayCid) && | 2628 call->token_pos(), |
| 2469 call->ic_data()->deopt_reason() == kDeoptUnknown) { | 2629 *call->ic_data(), |
| 2470 deopt_id = call->deopt_id(); | 2630 &entry, &last)) { |
| 2631 return false; |
| 2471 } | 2632 } |
| 2472 Definition* byte_index = call->ArgumentAt(1); | 2633 |
| 2473 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array), | 2634 // Insert receiver class check. |
| 2474 new Value(byte_index), | 2635 AddReceiverCheck(call); |
| 2475 1, // Index scale. | 2636 // Remove the original push arguments. |
| 2476 view_cid, | 2637 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 2477 deopt_id); | 2638 PushArgumentInstr* push = call->PushArgumentAt(i); |
| 2478 ReplaceCall(call, array_op); | 2639 push->ReplaceUsesWith(push->value()->definition()); |
| 2640 push->RemoveFromGraph(); |
| 2641 } |
| 2642 // Replace all uses of this definition with the result. |
| 2643 call->ReplaceUsesWith(last); |
| 2644 // Finally insert the sequence other definition in place of this one in the |
| 2645 // graph. |
| 2646 call->previous()->LinkTo(entry->next()); |
| 2647 entry->UnuseAllInputs(); // Entry block is not in the graph. |
| 2648 last->LinkTo(call); |
| 2649 // Remove through the iterator. |
| 2650 ASSERT(current_iterator()->Current() == call); |
| 2651 current_iterator()->RemoveCurrentFromGraph(); |
| 2652 call->set_previous(NULL); |
| 2653 call->set_next(NULL); |
| 2479 return true; | 2654 return true; |
| 2480 } | 2655 } |
| 2481 | 2656 |
| 2482 | 2657 |
| 2483 bool FlowGraphOptimizer::BuildByteArrayViewStore(InstanceCallInstr* call, | 2658 bool FlowGraphOptimizer::BuildByteArrayViewStore(InstanceCallInstr* call, |
| 2484 intptr_t view_cid) { | 2659 intptr_t view_cid) { |
| 2485 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) { | 2660 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) { |
| 2486 return false; | 2661 return false; |
| 2487 } | 2662 } |
| 2488 ASSERT(call->HasICData()); | 2663 ASSERT(call->HasICData()); |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2818 return; | 2993 return; |
| 2819 } | 2994 } |
| 2820 if ((op_kind == Token::kSET) && | 2995 if ((op_kind == Token::kSET) && |
| 2821 TryInlineInstanceSetter(instr, unary_checks)) { | 2996 TryInlineInstanceSetter(instr, unary_checks)) { |
| 2822 return; | 2997 return; |
| 2823 } | 2998 } |
| 2824 if (TryInlineInstanceMethod(instr)) { | 2999 if (TryInlineInstanceMethod(instr)) { |
| 2825 return; | 3000 return; |
| 2826 } | 3001 } |
| 2827 | 3002 |
| 2828 const bool has_one_target = unary_checks.HasOneTarget(); | 3003 bool has_one_target = unary_checks.HasOneTarget(); |
| 3004 |
| 3005 if (has_one_target) { |
| 3006 // Check if the single target is a polymorphic target, if it is, |
| 3007 // we don't have one target. |
| 3008 const Function& target = Function::Handle(unary_checks.GetTargetAt(0)); |
| 3009 const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target); |
| 3010 has_one_target = !polymorphic_target; |
| 3011 } |
| 2829 | 3012 |
| 2830 if (has_one_target) { | 3013 if (has_one_target) { |
| 2831 const bool is_method_extraction = | 3014 const bool is_method_extraction = |
| 2832 Function::Handle(unary_checks.GetTargetAt(0)).IsMethodExtractor(); | 3015 Function::Handle(unary_checks.GetTargetAt(0)).IsMethodExtractor(); |
| 2833 | 3016 |
| 2834 if ((is_method_extraction && !MethodExtractorNeedsClassCheck(instr)) || | 3017 if ((is_method_extraction && !MethodExtractorNeedsClassCheck(instr)) || |
| 2835 (!is_method_extraction && !InstanceCallNeedsClassCheck(instr))) { | 3018 (!is_method_extraction && !InstanceCallNeedsClassCheck(instr))) { |
| 2836 const bool call_with_checks = false; | 3019 const bool call_with_checks = false; |
| 2837 PolymorphicInstanceCallInstr* call = | 3020 PolymorphicInstanceCallInstr* call = |
| 2838 new PolymorphicInstanceCallInstr(instr, unary_checks, | 3021 new PolymorphicInstanceCallInstr(instr, unary_checks, |
| (...skipping 4925 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7764 } | 7947 } |
| 7765 | 7948 |
| 7766 // Insert materializations at environment uses. | 7949 // Insert materializations at environment uses. |
| 7767 for (intptr_t i = 0; i < exits.length(); i++) { | 7950 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7768 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 7951 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 7769 } | 7952 } |
| 7770 } | 7953 } |
| 7771 | 7954 |
| 7772 | 7955 |
| 7773 } // namespace dart | 7956 } // namespace dart |
| OLD | NEW |