| 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_inliner.h" | 5 #include "vm/flow_graph_inliner.h" |
| 6 | 6 |
| 7 #include "vm/aot_optimizer.h" | 7 #include "vm/aot_optimizer.h" |
| 8 #include "vm/block_scheduler.h" | 8 #include "vm/block_scheduler.h" |
| 9 #include "vm/branch_optimizer.h" | 9 #include "vm/branch_optimizer.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 2442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2453 new(Z) Value(left), | 2453 new(Z) Value(left), |
| 2454 new(Z) Value(right), | 2454 new(Z) Value(right), |
| 2455 call->deopt_id(), call->token_pos()); | 2455 call->deopt_id(), call->token_pos()); |
| 2456 flow_graph->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue); | 2456 flow_graph->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue); |
| 2457 *last = double_bin_op; | 2457 *last = double_bin_op; |
| 2458 | 2458 |
| 2459 return true; | 2459 return true; |
| 2460 } | 2460 } |
| 2461 | 2461 |
| 2462 | 2462 |
| 2463 static bool InlineGrowableArraySetter(FlowGraph* flow_graph, |
| 2464 intptr_t offset, |
| 2465 StoreBarrierType store_barrier_type, |
| 2466 Instruction* call, |
| 2467 TargetEntryInstr** entry, |
| 2468 Definition** last) { |
| 2469 Definition* array = call->ArgumentAt(0); |
| 2470 Definition* value = call->ArgumentAt(1); |
| 2471 |
| 2472 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2473 call->GetBlock()->try_index()); |
| 2474 (*entry)->InheritDeoptTarget(Z, call); |
| 2475 |
| 2476 // This is an internal method, no need to check argument types. |
| 2477 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( |
| 2478 offset, |
| 2479 new(Z) Value(array), |
| 2480 new(Z) Value(value), |
| 2481 store_barrier_type, |
| 2482 call->token_pos()); |
| 2483 flow_graph->AppendTo(*entry, store, call->env(), FlowGraph::kEffect); |
| 2484 *last = store; |
| 2485 |
| 2486 return true; |
| 2487 } |
| 2488 |
| 2489 |
| 2463 static intptr_t PrepareInlineByteArrayBaseOp( | 2490 static intptr_t PrepareInlineByteArrayBaseOp( |
| 2464 FlowGraph* flow_graph, | 2491 FlowGraph* flow_graph, |
| 2465 Instruction* call, | 2492 Instruction* call, |
| 2466 intptr_t array_cid, | 2493 intptr_t array_cid, |
| 2467 intptr_t view_cid, | 2494 intptr_t view_cid, |
| 2468 Definition** array, | 2495 Definition** array, |
| 2469 Definition* byte_index, | 2496 Definition* byte_index, |
| 2470 Instruction** cursor) { | 2497 Instruction** cursor) { |
| 2471 // Insert byte_index smi check. | 2498 // Insert byte_index smi check. |
| 2472 *cursor = flow_graph->AppendTo(*cursor, | 2499 *cursor = flow_graph->AppendTo(*cursor, |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2869 return true; | 2896 return true; |
| 2870 } | 2897 } |
| 2871 | 2898 |
| 2872 | 2899 |
| 2873 static bool InlineStringCodeUnitAt( | 2900 static bool InlineStringCodeUnitAt( |
| 2874 FlowGraph* flow_graph, | 2901 FlowGraph* flow_graph, |
| 2875 Instruction* call, | 2902 Instruction* call, |
| 2876 intptr_t cid, | 2903 intptr_t cid, |
| 2877 TargetEntryInstr** entry, | 2904 TargetEntryInstr** entry, |
| 2878 Definition** last) { | 2905 Definition** last) { |
| 2906 ASSERT((cid == kOneByteStringCid) || |
| 2907 (cid == kTwoByteStringCid) || |
| 2908 (cid == kExternalOneByteStringCid) || |
| 2909 (cid == kExternalTwoByteStringCid)); |
| 2879 Definition* str = call->ArgumentAt(0); | 2910 Definition* str = call->ArgumentAt(0); |
| 2880 Definition* index = call->ArgumentAt(1); | 2911 Definition* index = call->ArgumentAt(1); |
| 2881 | 2912 |
| 2882 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(), | 2913 *entry = new(Z) TargetEntryInstr(flow_graph->allocate_block_id(), |
| 2883 call->GetBlock()->try_index()); | 2914 call->GetBlock()->try_index()); |
| 2884 (*entry)->InheritDeoptTarget(Z, call); | 2915 (*entry)->InheritDeoptTarget(Z, call); |
| 2885 | 2916 |
| 2886 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry); | 2917 *last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry); |
| 2887 | 2918 |
| 2888 return true; | 2919 return true; |
| 2889 } | 2920 } |
| 2890 | 2921 |
| 2891 | 2922 |
| 2923 bool FlowGraphInliner::TryReplaceInstanceCallWithInline( |
| 2924 FlowGraph* flow_graph, |
| 2925 ForwardInstructionIterator* iterator, |
| 2926 InstanceCallInstr* call) { |
| 2927 Function& target = Function::Handle(Z); |
| 2928 GrowableArray<intptr_t> class_ids; |
| 2929 call->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 2930 const intptr_t receiver_cid = class_ids[0]; |
| 2931 |
| 2932 TargetEntryInstr* entry; |
| 2933 Definition* last; |
| 2934 if (!FlowGraphInliner::TryInlineRecognizedMethod(flow_graph, |
| 2935 receiver_cid, |
| 2936 target, |
| 2937 call, |
| 2938 call->ArgumentAt(0), |
| 2939 call->token_pos(), |
| 2940 *call->ic_data(), |
| 2941 &entry, &last)) { |
| 2942 return false; |
| 2943 } |
| 2944 |
| 2945 // Insert receiver class check if needed. |
| 2946 if (MethodRecognizer::PolymorphicTarget(target) || |
| 2947 flow_graph->InstanceCallNeedsClassCheck(call, target.kind())) { |
| 2948 Instruction* check = GetCheckClass( |
| 2949 flow_graph, |
| 2950 call->ArgumentAt(0), |
| 2951 ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks()), |
| 2952 call->deopt_id(), |
| 2953 call->token_pos()); |
| 2954 flow_graph->InsertBefore(call, check, call->env(), FlowGraph::kEffect); |
| 2955 } |
| 2956 |
| 2957 // Remove the original push arguments. |
| 2958 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 2959 PushArgumentInstr* push = call->PushArgumentAt(i); |
| 2960 push->ReplaceUsesWith(push->value()->definition()); |
| 2961 push->RemoveFromGraph(); |
| 2962 } |
| 2963 // Replace all uses of this definition with the result. |
| 2964 call->ReplaceUsesWith(last); |
| 2965 // Finally insert the sequence other definition in place of this one in the |
| 2966 // graph. |
| 2967 call->previous()->LinkTo(entry->next()); |
| 2968 entry->UnuseAllInputs(); // Entry block is not in the graph. |
| 2969 last->LinkTo(call); |
| 2970 // Remove through the iterator. |
| 2971 ASSERT(iterator->Current() == call); |
| 2972 iterator->RemoveCurrentFromGraph(); |
| 2973 call->set_previous(NULL); |
| 2974 call->set_next(NULL); |
| 2975 return true; |
| 2976 } |
| 2977 |
| 2978 |
| 2892 bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph, | 2979 bool FlowGraphInliner::TryInlineRecognizedMethod(FlowGraph* flow_graph, |
| 2893 intptr_t receiver_cid, | 2980 intptr_t receiver_cid, |
| 2894 const Function& target, | 2981 const Function& target, |
| 2895 Instruction* call, | 2982 Instruction* call, |
| 2896 Definition* receiver, | 2983 Definition* receiver, |
| 2897 TokenPosition token_pos, | 2984 TokenPosition token_pos, |
| 2898 const ICData& ic_data, | 2985 const ICData& ic_data, |
| 2899 TargetEntryInstr** entry, | 2986 TargetEntryInstr** entry, |
| 2900 Definition** last) { | 2987 Definition** last) { |
| 2901 ICData& value_check = ICData::ZoneHandle(Z); | 2988 ICData& value_check = ICData::ZoneHandle(Z); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3121 return InlineStringBaseCharAt( | 3208 return InlineStringBaseCharAt( |
| 3122 flow_graph, call, receiver_cid, entry, last); | 3209 flow_graph, call, receiver_cid, entry, last); |
| 3123 case MethodRecognizer::kDoubleAdd: | 3210 case MethodRecognizer::kDoubleAdd: |
| 3124 return InlineDoubleOp(flow_graph, Token::kADD, call, entry, last); | 3211 return InlineDoubleOp(flow_graph, Token::kADD, call, entry, last); |
| 3125 case MethodRecognizer::kDoubleSub: | 3212 case MethodRecognizer::kDoubleSub: |
| 3126 return InlineDoubleOp(flow_graph, Token::kSUB, call, entry, last); | 3213 return InlineDoubleOp(flow_graph, Token::kSUB, call, entry, last); |
| 3127 case MethodRecognizer::kDoubleMul: | 3214 case MethodRecognizer::kDoubleMul: |
| 3128 return InlineDoubleOp(flow_graph, Token::kMUL, call, entry, last); | 3215 return InlineDoubleOp(flow_graph, Token::kMUL, call, entry, last); |
| 3129 case MethodRecognizer::kDoubleDiv: | 3216 case MethodRecognizer::kDoubleDiv: |
| 3130 return InlineDoubleOp(flow_graph, Token::kDIV, call, entry, last); | 3217 return InlineDoubleOp(flow_graph, Token::kDIV, call, entry, last); |
| 3218 case MethodRecognizer::kGrowableArraySetData: |
| 3219 ASSERT(receiver_cid == kGrowableObjectArrayCid); |
| 3220 ASSERT(ic_data.NumberOfChecks() == 1); |
| 3221 return InlineGrowableArraySetter( |
| 3222 flow_graph, GrowableObjectArray::data_offset(), kEmitStoreBarrier, |
| 3223 call, entry, last); |
| 3224 case MethodRecognizer::kGrowableArraySetLength: |
| 3225 ASSERT(receiver_cid == kGrowableObjectArrayCid); |
| 3226 ASSERT(ic_data.NumberOfChecks() == 1); |
| 3227 return InlineGrowableArraySetter( |
| 3228 flow_graph, GrowableObjectArray::length_offset(), kNoStoreBarrier, |
| 3229 call, entry, last); |
| 3131 default: | 3230 default: |
| 3132 return false; | 3231 return false; |
| 3133 } | 3232 } |
| 3134 } | 3233 } |
| 3135 | 3234 |
| 3136 | 3235 |
| 3137 } // namespace dart | 3236 } // namespace dart |
| OLD | NEW |