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

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 794 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 return kTypedDataInt32ArrayCid; 805 return kTypedDataInt32ArrayCid;
806 806
807 case MethodRecognizer::kUint32ArrayGetIndexed: 807 case MethodRecognizer::kUint32ArrayGetIndexed:
808 case MethodRecognizer::kUint32ArraySetIndexed: 808 case MethodRecognizer::kUint32ArraySetIndexed:
809 return kTypedDataUint32ArrayCid; 809 return kTypedDataUint32ArrayCid;
810 810
811 case MethodRecognizer::kFloat32x4ArrayGetIndexed: 811 case MethodRecognizer::kFloat32x4ArrayGetIndexed:
812 case MethodRecognizer::kFloat32x4ArraySetIndexed: 812 case MethodRecognizer::kFloat32x4ArraySetIndexed:
813 return kTypedDataFloat32x4ArrayCid; 813 return kTypedDataFloat32x4ArrayCid;
814 814
815 case MethodRecognizer::kUint8ArrayGetUint8:
816 return kTypedDataUint8ArrayCid;
817
818 case MethodRecognizer::kExternalUint8ArrayGetUint8:
819 return kExternalTypedDataUint8ArrayCid;
820
815 default: 821 default:
816 break; 822 break;
817 } 823 }
818 return kIllegalCid; 824 return kIllegalCid;
819 } 825 }
820 826
821 827
822 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { 828 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) {
823 // Check for monomorphic IC data. 829 // Check for monomorphic IC data.
824 if (!call->HasICData()) return false; 830 if (!call->HasICData()) return false;
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 value_check = ic_data.AsUnaryClassChecksForArgNr(2); 1073 value_check = ic_data.AsUnaryClassChecksForArgNr(2);
1068 return InlineSetIndexed(kind, target, call, token_pos, 1074 return InlineSetIndexed(kind, target, call, token_pos,
1069 &ic_data, value_check, entry, last); 1075 &ic_data, value_check, entry, last);
1070 case MethodRecognizer::kFloat32x4ArraySetIndexed: 1076 case MethodRecognizer::kFloat32x4ArraySetIndexed:
1071 if (!ShouldInlineSimd()) return false; 1077 if (!ShouldInlineSimd()) return false;
1072 // Check that value is always a Float32x4. 1078 // Check that value is always a Float32x4.
1073 if (!ArgIsAlways(kFloat32x4Cid, ic_data, 2)) return false; 1079 if (!ArgIsAlways(kFloat32x4Cid, ic_data, 2)) return false;
1074 value_check = ic_data.AsUnaryClassChecksForArgNr(2); 1080 value_check = ic_data.AsUnaryClassChecksForArgNr(2);
1075 return InlineSetIndexed(kind, target, call, token_pos, 1081 return InlineSetIndexed(kind, target, call, token_pos,
1076 &ic_data, value_check, entry, last); 1082 &ic_data, value_check, entry, last);
1083 case MethodRecognizer::kByteArrayBaseGetInt8:
1084 return InlineByteArrayViewLoad(kind, call, kTypedDataInt8ArrayCid,
1085 ic_data, entry, last);
1086 case MethodRecognizer::kUint8ArrayGetUint8:
1087 case MethodRecognizer::kExternalUint8ArrayGetUint8:
1088 case MethodRecognizer::kByteArrayBaseGetUint8:
1089 return InlineByteArrayViewLoad(kind, call, kTypedDataUint8ArrayCid,
1090 ic_data, entry, last);
1091 case MethodRecognizer::kByteArrayBaseGetInt16:
1092 return InlineByteArrayViewLoad(kind, call, kTypedDataInt16ArrayCid,
1093 ic_data, entry, last);
1094 case MethodRecognizer::kByteArrayBaseGetUint16:
1095 return InlineByteArrayViewLoad(kind, call, kTypedDataUint16ArrayCid,
1096 ic_data, entry, last);
1097 case MethodRecognizer::kByteArrayBaseGetInt32:
1098 if (!CanUnboxInt32()) return false;
1099 return InlineByteArrayViewLoad(kind, call, kTypedDataInt32ArrayCid,
1100 ic_data, entry, last);
1101 case MethodRecognizer::kByteArrayBaseGetUint32:
1102 if (!CanUnboxInt32()) return false;
1103 return InlineByteArrayViewLoad(kind, call, kTypedDataUint32ArrayCid,
1104 ic_data, entry, last);
1105 case MethodRecognizer::kByteArrayBaseGetFloat32:
1106 return InlineByteArrayViewLoad(kind, call, kTypedDataFloat32ArrayCid,
1107 ic_data, entry, last);
1108 case MethodRecognizer::kByteArrayBaseGetFloat64:
1109 return InlineByteArrayViewLoad(kind, call, kTypedDataFloat64ArrayCid,
1110 ic_data, entry, last);
1111 case MethodRecognizer::kByteArrayBaseGetFloat32x4:
1112 return InlineByteArrayViewLoad(kind, call, kTypedDataFloat32x4ArrayCid,
1113 ic_data, entry, last);
1077 default: 1114 default:
1078 return false; 1115 return false;
1079 } 1116 }
1080 } 1117 }
1081 1118
1082 1119
1083 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, 1120 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call,
1084 intptr_t array_cid, 1121 intptr_t array_cid,
1085 Definition** array, 1122 Definition** array,
1086 Definition* index, 1123 Definition* index,
(...skipping 931 matching lines...) Expand 10 before | Expand all | Expand 10 after
2018 // elements fit into a smi or the platform supports unboxed mints. 2055 // elements fit into a smi or the platform supports unboxed mints.
2019 if ((recognized_kind == MethodRecognizer::kByteArrayBaseGetInt32) || 2056 if ((recognized_kind == MethodRecognizer::kByteArrayBaseGetInt32) ||
2020 (recognized_kind == MethodRecognizer::kByteArrayBaseGetUint32) || 2057 (recognized_kind == MethodRecognizer::kByteArrayBaseGetUint32) ||
2021 (recognized_kind == MethodRecognizer::kByteArrayBaseSetInt32) || 2058 (recognized_kind == MethodRecognizer::kByteArrayBaseSetInt32) ||
2022 (recognized_kind == MethodRecognizer::kByteArrayBaseSetUint32)) { 2059 (recognized_kind == MethodRecognizer::kByteArrayBaseSetUint32)) {
2023 if (!CanUnboxInt32()) return false; 2060 if (!CanUnboxInt32()) return false;
2024 } 2061 }
2025 2062
2026 switch (recognized_kind) { 2063 switch (recognized_kind) {
2027 // ByteArray getters. 2064 // ByteArray getters.
2065 case MethodRecognizer::kUint8ArrayGetUint8:
2066 case MethodRecognizer::kExternalUint8ArrayGetUint8:
2028 case MethodRecognizer::kByteArrayBaseGetInt8: 2067 case MethodRecognizer::kByteArrayBaseGetInt8:
2029 return BuildByteArrayViewLoad( 2068 return BuildByteArrayViewLoad(
2030 call, class_ids[0], kTypedDataInt8ArrayCid); 2069 recognized_kind, call, class_ids[0], kTypedDataInt8ArrayCid);
2031 case MethodRecognizer::kByteArrayBaseGetUint8: 2070 case MethodRecognizer::kByteArrayBaseGetUint8:
2032 return BuildByteArrayViewLoad( 2071 return BuildByteArrayViewLoad(
2033 call, class_ids[0], kTypedDataUint8ArrayCid); 2072 recognized_kind, call, class_ids[0], kTypedDataUint8ArrayCid);
2034 case MethodRecognizer::kByteArrayBaseGetInt16: 2073 case MethodRecognizer::kByteArrayBaseGetInt16:
2035 return BuildByteArrayViewLoad( 2074 return BuildByteArrayViewLoad(
2036 call, class_ids[0], kTypedDataInt16ArrayCid); 2075 recognized_kind, call, class_ids[0], kTypedDataInt16ArrayCid);
2037 case MethodRecognizer::kByteArrayBaseGetUint16: 2076 case MethodRecognizer::kByteArrayBaseGetUint16:
2038 return BuildByteArrayViewLoad( 2077 return BuildByteArrayViewLoad(
2039 call, class_ids[0], kTypedDataUint16ArrayCid); 2078 recognized_kind, call, class_ids[0], kTypedDataUint16ArrayCid);
2040 case MethodRecognizer::kByteArrayBaseGetInt32: 2079 case MethodRecognizer::kByteArrayBaseGetInt32:
2041 return BuildByteArrayViewLoad( 2080 return BuildByteArrayViewLoad(
2042 call, class_ids[0], kTypedDataInt32ArrayCid); 2081 recognized_kind, call, class_ids[0], kTypedDataInt32ArrayCid);
2043 case MethodRecognizer::kByteArrayBaseGetUint32: 2082 case MethodRecognizer::kByteArrayBaseGetUint32:
2044 return BuildByteArrayViewLoad( 2083 return BuildByteArrayViewLoad(
2045 call, class_ids[0], kTypedDataUint32ArrayCid); 2084 recognized_kind, call, class_ids[0], kTypedDataUint32ArrayCid);
2046 case MethodRecognizer::kByteArrayBaseGetFloat32: 2085 case MethodRecognizer::kByteArrayBaseGetFloat32:
2047 return BuildByteArrayViewLoad( 2086 return BuildByteArrayViewLoad(
2048 call, class_ids[0], kTypedDataFloat32ArrayCid); 2087 recognized_kind, call, class_ids[0], kTypedDataFloat32ArrayCid);
2049 case MethodRecognizer::kByteArrayBaseGetFloat64: 2088 case MethodRecognizer::kByteArrayBaseGetFloat64:
2050 return BuildByteArrayViewLoad( 2089 return BuildByteArrayViewLoad(
2051 call, class_ids[0], kTypedDataFloat64ArrayCid); 2090 recognized_kind, call, class_ids[0], kTypedDataFloat64ArrayCid);
2052 case MethodRecognizer::kByteArrayBaseGetFloat32x4: 2091 case MethodRecognizer::kByteArrayBaseGetFloat32x4:
2053 return BuildByteArrayViewLoad( 2092 return BuildByteArrayViewLoad(
2054 call, class_ids[0], kTypedDataFloat32x4ArrayCid); 2093 recognized_kind, call, class_ids[0], kTypedDataFloat32x4ArrayCid);
2055 2094
2056 // ByteArray setters. 2095 // ByteArray setters.
2057 case MethodRecognizer::kByteArrayBaseSetInt8: 2096 case MethodRecognizer::kByteArrayBaseSetInt8:
2058 return BuildByteArrayViewStore(call, kTypedDataInt8ArrayCid); 2097 return BuildByteArrayViewStore(call, kTypedDataInt8ArrayCid);
2059 case MethodRecognizer::kByteArrayBaseSetUint8: 2098 case MethodRecognizer::kByteArrayBaseSetUint8:
2060 return BuildByteArrayViewStore(call, kTypedDataUint8ArrayCid); 2099 return BuildByteArrayViewStore(call, kTypedDataUint8ArrayCid);
2061 case MethodRecognizer::kByteArrayBaseSetInt16: 2100 case MethodRecognizer::kByteArrayBaseSetInt16:
2062 return BuildByteArrayViewStore(call, kTypedDataInt16ArrayCid); 2101 return BuildByteArrayViewStore(call, kTypedDataInt16ArrayCid);
2063 case MethodRecognizer::kByteArrayBaseSetUint16: 2102 case MethodRecognizer::kByteArrayBaseSetUint16:
2064 return BuildByteArrayViewStore(call, kTypedDataUint16ArrayCid); 2103 return BuildByteArrayViewStore(call, kTypedDataUint16ArrayCid);
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
2442 call->deopt_id()); 2481 call->deopt_id());
2443 ReplaceCall(call, setFlag); 2482 ReplaceCall(call, setFlag);
2444 return true; 2483 return true;
2445 } 2484 }
2446 default: 2485 default:
2447 return false; 2486 return false;
2448 } 2487 }
2449 } 2488 }
2450 2489
2451 2490
2452 bool FlowGraphOptimizer::BuildByteArrayViewLoad( 2491 bool FlowGraphOptimizer::InlineByteArrayViewLoad(MethodRecognizer::Kind kind,
2453 InstanceCallInstr* call, 2492 Instruction* call,
2454 intptr_t receiver_cid, 2493 intptr_t view_cid,
2455 intptr_t view_cid) { 2494 const ICData& ic_data,
2495 TargetEntryInstr** entry,
2496 Definition** last) {
2497 intptr_t array_cid = MethodKindToCid(kind);
2498 if (array_cid == kIllegalCid) {
2499 // XXX.
2500 Function& target = Function::Handle();
2501 GrowableArray<intptr_t> class_ids;
2502 ic_data.GetCheckAt(0, &class_ids, &target);
2503 array_cid = class_ids[0];
2504 }
2505 ASSERT(array_cid != kIllegalCid);
2506
2507 Definition* array = call->ArgumentAt(0);
2508 Definition* index = call->ArgumentAt(1);
2509 *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(),
2510 call->GetBlock()->try_index());
2511 (*entry)->InheritDeoptTarget(call);
2512 Instruction* cursor = *entry;
2513
2514 array_cid = PrepareInlineByteArrayViewOp(call,
2515 array_cid,
2516 view_cid,
2517 &array,
2518 index,
2519 &cursor);
2520
2521 intptr_t deopt_id = Isolate::kNoDeoptId;
2522 if ((array_cid == kTypedDataInt32ArrayCid) ||
2523 (array_cid == kTypedDataUint32ArrayCid)) {
2524 // Set deopt_id if we can optimistically assume that the result is Smi.
2525 // Assume mixed Mint/Smi if this instruction caused deoptimization once.
2526 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ?
2527 call->deopt_id() : Isolate::kNoDeoptId;
2528 }
2529
2530 *last = new LoadIndexedInstr(new Value(array),
2531 new Value(index),
2532 1,
2533 array_cid,
2534 deopt_id);
2535 flow_graph()->AppendTo(cursor,
2536 *last,
2537 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL,
2538 Definition::kValue);
2539 return true;
2540 }
2541
2542
2543 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp(
2544 Instruction* call,
2545 intptr_t array_cid,
2546 intptr_t view_cid,
2547 Definition** array,
2548 Definition* byte_index,
2549 Instruction** cursor) {
2550 // Insert byte_index smi check.
2551 *cursor = flow_graph()->AppendTo(*cursor,
2552 new CheckSmiInstr(new Value(byte_index),
2553 call->deopt_id()),
2554 call->env(),
2555 Definition::kEffect);
2556
2557 const bool is_immutable = true;
2558 LoadFieldInstr* length =
2559 new LoadFieldInstr(new Value(*array),
2560 CheckArrayBoundInstr::LengthOffsetFor(array_cid),
2561 Type::ZoneHandle(Type::SmiType()),
2562 is_immutable);
2563 length->set_result_cid(kSmiCid);
2564 length->set_recognized_kind(
2565 LoadFieldInstr::RecognizedKindFromArrayCid(array_cid));
2566 *cursor = flow_graph()->AppendTo(*cursor,
2567 length,
2568 NULL,
2569 Definition::kValue);
2570
2571 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(array_cid);
2572 ConstantInstr* bytes_per_element =
2573 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size)));
2574 BinarySmiOpInstr* len_in_bytes =
2575 new BinarySmiOpInstr(Token::kMUL,
2576 new Value(length),
2577 new Value(bytes_per_element),
2578 call->deopt_id());
2579 *cursor = flow_graph()->AppendTo(*cursor, len_in_bytes, call->env(),
2580 Definition::kValue);
2581
2582 ConstantInstr* length_adjustment =
2583 flow_graph()->GetConstant(Smi::Handle(Smi::New(
2584 FlowGraphCompiler::ElementSizeFor(view_cid) - 1)));
2585 // adjusted_length = len_in_bytes - (element_size - 1).
2586 BinarySmiOpInstr* adjusted_length =
2587 new BinarySmiOpInstr(Token::kSUB,
2588 new Value(len_in_bytes),
2589 new Value(length_adjustment),
2590 call->deopt_id());
2591 *cursor = flow_graph()->AppendTo(*cursor, adjusted_length, call->env(),
2592 Definition::kValue);
2593
2594 // Check adjusted_length > 0.
2595 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0)));
2596 *cursor = flow_graph()->AppendTo(*cursor,
2597 new CheckArrayBoundInstr(
2598 new Value(adjusted_length),
2599 new Value(zero),
2600 call->deopt_id()),
2601 call->env(),
2602 Definition::kEffect);
2603 // Check 0 <= byte_index < adjusted_length.
2604 *cursor = flow_graph()->AppendTo(*cursor,
2605 new CheckArrayBoundInstr(
2606 new Value(adjusted_length),
2607 new Value(byte_index),
2608 call->deopt_id()),
2609 call->env(),
2610 Definition::kEffect);
2611
2612 if (RawObject::IsExternalTypedDataClassId(array_cid)) {
2613 LoadUntaggedInstr* elements =
2614 new LoadUntaggedInstr(new Value(*array),
2615 ExternalTypedData::data_offset());
2616 *cursor = flow_graph()->AppendTo(*cursor,
2617 elements,
2618 NULL,
2619 Definition::kValue);
2620 *array = elements;
2621 }
2622 return array_cid;
2623 }
2624
2625
2626 bool FlowGraphOptimizer::BuildByteArrayViewLoad(MethodRecognizer::Kind kind,
2627 InstanceCallInstr* call,
2628 intptr_t receiver_cid,
2629 intptr_t view_cid) {
2456 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) { 2630 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) {
2457 return false; 2631 return false;
2458 } 2632 }
2459 2633
2460 Definition* array = call->ArgumentAt(0); 2634 // Check for monomorphic IC data.
2461 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array); 2635 if (!call->HasICData()) return false;
2636 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks());
2637 if (ic_data.NumberOfChecks() != 1) return false;
2638 ASSERT(ic_data.HasOneTarget());
2639 const Function& target = Function::Handle(ic_data.GetTargetAt(0));
2640 TargetEntryInstr* entry;
2641 Definition* last;
2642 if (!TryInlineRecognizedMethod(target,
2643 call,
2644 call->token_pos(),
2645 *call->ic_data(),
2646 &entry, &last)) {
2647 return false;
2648 }
2462 2649
2463 // Optimistically build a smi-checked load for Int32 and Uint32 2650 // Insert receiver class check.
2464 // loads on ia32 like we do for normal array loads, and only revert to 2651 AddReceiverCheck(call);
2465 // mint case after deoptimizing here. 2652 // Remove the original push arguments.
2466 intptr_t deopt_id = Isolate::kNoDeoptId; 2653 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
2467 if ((view_cid == kTypedDataInt32ArrayCid || 2654 PushArgumentInstr* push = call->PushArgumentAt(i);
2468 view_cid == kTypedDataUint32ArrayCid) && 2655 push->ReplaceUsesWith(push->value()->definition());
2469 call->ic_data()->deopt_reason() == kDeoptUnknown) { 2656 push->RemoveFromGraph();
2470 deopt_id = call->deopt_id();
2471 } 2657 }
2472 Definition* byte_index = call->ArgumentAt(1); 2658 // Replace all uses of this definition with the result.
2473 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array), 2659 call->ReplaceUsesWith(last);
2474 new Value(byte_index), 2660 // Finally insert the sequence other definition in place of this one in the
2475 1, // Index scale. 2661 // graph.
2476 view_cid, 2662 call->previous()->LinkTo(entry->next());
2477 deopt_id); 2663 entry->UnuseAllInputs(); // Entry block is not in the graph.
2478 ReplaceCall(call, array_op); 2664 last->LinkTo(call);
2665 // Remove through the iterator.
2666 ASSERT(current_iterator()->Current() == call);
2667 current_iterator()->RemoveCurrentFromGraph();
2668 call->set_previous(NULL);
2669 call->set_next(NULL);
2479 return true; 2670 return true;
2480 } 2671 }
2481 2672
2482 2673
2483 bool FlowGraphOptimizer::BuildByteArrayViewStore(InstanceCallInstr* call, 2674 bool FlowGraphOptimizer::BuildByteArrayViewStore(InstanceCallInstr* call,
2484 intptr_t view_cid) { 2675 intptr_t view_cid) {
2485 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) { 2676 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) {
2486 return false; 2677 return false;
2487 } 2678 }
2488 ASSERT(call->HasICData()); 2679 ASSERT(call->HasICData());
(...skipping 5278 matching lines...) Expand 10 before | Expand all | Expand 10 after
7767 } 7958 }
7768 7959
7769 // Insert materializations at environment uses. 7960 // Insert materializations at environment uses.
7770 for (intptr_t i = 0; i < exits.length(); i++) { 7961 for (intptr_t i = 0; i < exits.length(); i++) {
7771 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); 7962 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
7772 } 7963 }
7773 } 7964 }
7774 7965
7775 7966
7776 } // namespace dart 7967 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698