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/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 1542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1553 if (!ShouldInlineSimd()) { | 1553 if (!ShouldInlineSimd()) { |
1554 return false; | 1554 return false; |
1555 } | 1555 } |
1556 return InlineByteArrayViewStore(target, call, receiver, receiver_cid, | 1556 return InlineByteArrayViewStore(target, call, receiver, receiver_cid, |
1557 kTypedDataInt32x4ArrayCid, | 1557 kTypedDataInt32x4ArrayCid, |
1558 ic_data, entry, last); | 1558 ic_data, entry, last); |
1559 case MethodRecognizer::kStringBaseCodeUnitAt: | 1559 case MethodRecognizer::kStringBaseCodeUnitAt: |
1560 return InlineStringCodeUnitAt(call, receiver_cid, entry, last); | 1560 return InlineStringCodeUnitAt(call, receiver_cid, entry, last); |
1561 case MethodRecognizer::kStringBaseCharAt: | 1561 case MethodRecognizer::kStringBaseCharAt: |
1562 return InlineStringBaseCharAt(call, receiver_cid, entry, last); | 1562 return InlineStringBaseCharAt(call, receiver_cid, entry, last); |
1563 case MethodRecognizer::kDoubleAdd: | |
1564 return InlineDoubleOp(Token::kADD, call, receiver_cid, entry, last); | |
1565 case MethodRecognizer::kDoubleSub: | |
1566 return InlineDoubleOp(Token::kSUB, call, receiver_cid, entry, last); | |
1567 case MethodRecognizer::kDoubleMul: | |
1568 return InlineDoubleOp(Token::kMUL, call, receiver_cid, entry, last); | |
1569 case MethodRecognizer::kDoubleDiv: | |
1570 return InlineDoubleOp(Token::kDIV, call, receiver_cid, entry, last); | |
1563 default: | 1571 default: |
1564 return false; | 1572 return false; |
1565 } | 1573 } |
1566 } | 1574 } |
1567 | 1575 |
1568 | 1576 |
1569 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, | 1577 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, |
1570 intptr_t array_cid, | 1578 intptr_t array_cid, |
1571 Definition** array, | 1579 Definition** array, |
1572 Definition* index, | 1580 Definition* index, |
(...skipping 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2329 // Reset value types if guarded_cid was used. | 2337 // Reset value types if guarded_cid was used. |
2330 for (Value::Iterator it(load->input_use_list()); | 2338 for (Value::Iterator it(load->input_use_list()); |
2331 !it.Done(); | 2339 !it.Done(); |
2332 it.Advance()) { | 2340 it.Advance()) { |
2333 it.Current()->SetReachingType(NULL); | 2341 it.Current()->SetReachingType(NULL); |
2334 } | 2342 } |
2335 } | 2343 } |
2336 } | 2344 } |
2337 | 2345 |
2338 | 2346 |
2339 LoadFieldInstr* FlowGraphOptimizer::BuildLoadStringLength(Definition* str) { | |
2340 // Treat length loads as mutable (i.e. affected by side effects) to avoid | |
2341 // hoisting them since we can't hoist the preceding class-check. This | |
2342 // is because of externalization of strings that affects their class-id. | |
2343 LoadFieldInstr* load = new(I) LoadFieldInstr( | |
2344 new(I) Value(str), | |
2345 String::length_offset(), | |
2346 Type::ZoneHandle(I, Type::SmiType()), | |
2347 str->token_pos()); | |
2348 load->set_result_cid(kSmiCid); | |
2349 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); | |
2350 return load; | |
2351 } | |
2352 | |
2353 | |
2354 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, | 2347 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, |
2355 MethodRecognizer::Kind getter) { | 2348 MethodRecognizer::Kind getter) { |
2356 if (!ShouldInlineSimd()) { | 2349 if (!ShouldInlineSimd()) { |
2357 return false; | 2350 return false; |
2358 } | 2351 } |
2359 AddCheckClass(call->ArgumentAt(0), | 2352 AddCheckClass(call->ArgumentAt(0), |
2360 ICData::ZoneHandle( | 2353 ICData::ZoneHandle( |
2361 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2354 I, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2362 call->deopt_id(), | 2355 call->deopt_id(), |
2363 call->env(), | 2356 call->env(), |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2704 | 2697 |
2705 cursor = flow_graph()->AppendTo(cursor, | 2698 cursor = flow_graph()->AppendTo(cursor, |
2706 new(I) CheckSmiInstr( | 2699 new(I) CheckSmiInstr( |
2707 new(I) Value(index), | 2700 new(I) Value(index), |
2708 call->deopt_id(), | 2701 call->deopt_id(), |
2709 call->token_pos()), | 2702 call->token_pos()), |
2710 call->env(), | 2703 call->env(), |
2711 FlowGraph::kEffect); | 2704 FlowGraph::kEffect); |
2712 | 2705 |
2713 // Load the length of the string. | 2706 // Load the length of the string. |
2714 LoadFieldInstr* length = BuildLoadStringLength(str); | 2707 // Treat length loads as mutable (i.e. affected by side effects) to avoid |
2708 // hoisting them since we can't hoist the preceding class-check. This | |
2709 // is because of externalization of strings that affects their class-id. | |
2710 LoadFieldInstr* length = new(I) LoadFieldInstr( | |
2711 new(I) Value(str), | |
2712 String::length_offset(), | |
2713 Type::ZoneHandle(I, Type::SmiType()), | |
2714 str->token_pos()); | |
2715 length->set_result_cid(kSmiCid); | |
2716 length->set_recognized_kind(MethodRecognizer::kStringBaseLength); | |
2717 | |
2715 cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue); | 2718 cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue); |
2716 // Bounds check. | 2719 // Bounds check. |
2717 cursor = flow_graph()->AppendTo(cursor, | 2720 cursor = flow_graph()->AppendTo(cursor, |
2718 new(I) CheckArrayBoundInstr( | 2721 new(I) CheckArrayBoundInstr( |
2719 new(I) Value(length), | 2722 new(I) Value(length), |
2720 new(I) Value(index), | 2723 new(I) Value(index), |
2721 call->deopt_id()), | 2724 call->deopt_id()), |
2722 call->env(), | 2725 call->env(), |
2723 FlowGraph::kEffect); | 2726 FlowGraph::kEffect); |
2724 | 2727 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2783 StringFromCharCodeInstr* char_at = new(I) StringFromCharCodeInstr( | 2786 StringFromCharCodeInstr* char_at = new(I) StringFromCharCodeInstr( |
2784 new(I) Value(*last), cid); | 2787 new(I) Value(*last), cid); |
2785 | 2788 |
2786 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue); | 2789 flow_graph()->AppendTo(*last, char_at, NULL, FlowGraph::kValue); |
2787 *last = char_at; | 2790 *last = char_at; |
2788 | 2791 |
2789 return true; | 2792 return true; |
2790 } | 2793 } |
2791 | 2794 |
2792 | 2795 |
2796 bool FlowGraphOptimizer::InlineDoubleOp( | |
2797 Token::Kind op_kind, | |
2798 Instruction* call, | |
2799 intptr_t cid, // Not used. | |
srdjan
2014/08/18 18:04:49
Why pass if not used?
Florian Schneider
2014/08/18 18:22:57
Done.
| |
2800 TargetEntryInstr** entry, | |
2801 Definition** last) { | |
2802 Definition* left = call->ArgumentAt(0); | |
2803 Definition* right = call->ArgumentAt(1); | |
2804 | |
2805 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), | |
2806 call->GetBlock()->try_index()); | |
2807 (*entry)->InheritDeoptTarget(I, call); | |
2808 // Arguments are checked. No need for class check. | |
2809 BinaryDoubleOpInstr* double_bin_op = | |
2810 new(I) BinaryDoubleOpInstr(op_kind, | |
2811 new(I) Value(left), | |
2812 new(I) Value(right), | |
2813 call->deopt_id(), call->token_pos()); | |
2814 flow_graph()->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue); | |
2815 *last = double_bin_op; | |
2816 | |
2817 return true; | |
2818 } | |
2819 | |
2820 | |
2793 void FlowGraphOptimizer::ReplaceWithMathCFunction( | 2821 void FlowGraphOptimizer::ReplaceWithMathCFunction( |
2794 InstanceCallInstr* call, | 2822 InstanceCallInstr* call, |
2795 MethodRecognizer::Kind recognized_kind) { | 2823 MethodRecognizer::Kind recognized_kind) { |
2796 AddReceiverCheck(call); | 2824 AddReceiverCheck(call); |
2797 ZoneGrowableArray<Value*>* args = | 2825 ZoneGrowableArray<Value*>* args = |
2798 new(I) ZoneGrowableArray<Value*>(call->ArgumentCount()); | 2826 new(I) ZoneGrowableArray<Value*>(call->ArgumentCount()); |
2799 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 2827 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { |
2800 args->Add(new(I) Value(call->ArgumentAt(i))); | 2828 args->Add(new(I) Value(call->ArgumentAt(i))); |
2801 } | 2829 } |
2802 InvokeMathCFunctionInstr* invoke = | 2830 InvokeMathCFunctionInstr* invoke = |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2953 if (!TargetCPUFeatures::double_truncate_round_supported()) { | 2981 if (!TargetCPUFeatures::double_truncate_round_supported()) { |
2954 ReplaceWithMathCFunction(call, recognized_kind); | 2982 ReplaceWithMathCFunction(call, recognized_kind); |
2955 } else { | 2983 } else { |
2956 AddReceiverCheck(call); | 2984 AddReceiverCheck(call); |
2957 DoubleToDoubleInstr* d2d_instr = | 2985 DoubleToDoubleInstr* d2d_instr = |
2958 new(I) DoubleToDoubleInstr(new(I) Value(call->ArgumentAt(0)), | 2986 new(I) DoubleToDoubleInstr(new(I) Value(call->ArgumentAt(0)), |
2959 recognized_kind, call->deopt_id()); | 2987 recognized_kind, call->deopt_id()); |
2960 ReplaceCall(call, d2d_instr); | 2988 ReplaceCall(call, d2d_instr); |
2961 } | 2989 } |
2962 return true; | 2990 return true; |
2991 case MethodRecognizer::kDoubleAdd: | |
2992 case MethodRecognizer::kDoubleSub: | |
2993 case MethodRecognizer::kDoubleMul: | |
2994 case MethodRecognizer::kDoubleDiv: | |
2995 return TryReplaceInstanceCallWithInline(call); | |
2963 default: | 2996 default: |
2964 // Unsupported method. | 2997 // Unsupported method. |
2965 return false; | 2998 return false; |
2966 } | 2999 } |
2967 } | 3000 } |
2968 | 3001 |
2969 if (IsSupportedByteArrayViewCid(class_ids[0]) && | 3002 if (IsSupportedByteArrayViewCid(class_ids[0]) && |
2970 (ic_data.NumberOfChecks() == 1)) { | 3003 (ic_data.NumberOfChecks() == 1)) { |
2971 // For elements that may not fit into a smi on all platforms, check if | 3004 // For elements that may not fit into a smi on all platforms, check if |
2972 // elements fit into a smi or the platform supports unboxed mints. | 3005 // elements fit into a smi or the platform supports unboxed mints. |
(...skipping 1362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4335 call->deopt_id(), | 4368 call->deopt_id(), |
4336 recognized_kind, | 4369 recognized_kind, |
4337 call->token_pos()); | 4370 call->token_pos()); |
4338 ReplaceCall(call, invoke); | 4371 ReplaceCall(call, invoke); |
4339 } else if (recognized_kind == MethodRecognizer::kObjectArrayConstructor) { | 4372 } else if (recognized_kind == MethodRecognizer::kObjectArrayConstructor) { |
4340 Value* type = new(I) Value(call->ArgumentAt(0)); | 4373 Value* type = new(I) Value(call->ArgumentAt(0)); |
4341 Value* num_elements = new(I) Value(call->ArgumentAt(1)); | 4374 Value* num_elements = new(I) Value(call->ArgumentAt(1)); |
4342 CreateArrayInstr* create_array = | 4375 CreateArrayInstr* create_array = |
4343 new(I) CreateArrayInstr(call->token_pos(), type, num_elements); | 4376 new(I) CreateArrayInstr(call->token_pos(), type, num_elements); |
4344 ReplaceCall(call, create_array); | 4377 ReplaceCall(call, create_array); |
4378 } else if (recognized_kind == MethodRecognizer::kDoubleFromInteger) { | |
4379 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { | |
4380 const ICData& ic_data = *call->ic_data(); | |
4381 if (CanUnboxDouble() && ArgIsAlways(kSmiCid, ic_data, 0)) { | |
4382 Definition* arg = call->ArgumentAt(0); | |
4383 InsertBefore(call, | |
4384 new(I) CheckSmiInstr( | |
4385 new(I) Value(arg), | |
4386 call->deopt_id(), | |
4387 call->token_pos()), | |
4388 call->env(), | |
4389 FlowGraph::kEffect); | |
4390 ReplaceCall(call, | |
4391 new(I) SmiToDoubleInstr(new(I) Value(arg), | |
4392 call->token_pos())); | |
4393 } | |
4394 } | |
4345 } else if (call->function().IsFactory()) { | 4395 } else if (call->function().IsFactory()) { |
4346 const Class& function_class = | 4396 const Class& function_class = |
4347 Class::Handle(I, call->function().Owner()); | 4397 Class::Handle(I, call->function().Owner()); |
4348 if ((function_class.library() == Library::CoreLibrary()) || | 4398 if ((function_class.library() == Library::CoreLibrary()) || |
4349 (function_class.library() == Library::TypedDataLibrary())) { | 4399 (function_class.library() == Library::TypedDataLibrary())) { |
4350 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); | 4400 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); |
4351 switch (cid) { | 4401 switch (cid) { |
4352 case kArrayCid: { | 4402 case kArrayCid: { |
4353 Value* type = new(I) Value(call->ArgumentAt(0)); | 4403 Value* type = new(I) Value(call->ArgumentAt(0)); |
4354 Value* num_elements = new(I) Value(call->ArgumentAt(1)); | 4404 Value* num_elements = new(I) Value(call->ArgumentAt(1)); |
(...skipping 5187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9542 | 9592 |
9543 // Insert materializations at environment uses. | 9593 // Insert materializations at environment uses. |
9544 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 9594 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
9545 CreateMaterializationAt( | 9595 CreateMaterializationAt( |
9546 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 9596 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); |
9547 } | 9597 } |
9548 } | 9598 } |
9549 | 9599 |
9550 | 9600 |
9551 } // namespace dart | 9601 } // namespace dart |
OLD | NEW |