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

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

Issue 160613002: Inline polymorphic typed array view stores (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1343 matching lines...) Expand 10 before | Expand all | Expand 10 after
1354 case MethodRecognizer::kByteArrayBaseGetFloat32x4: 1354 case MethodRecognizer::kByteArrayBaseGetFloat32x4:
1355 if (!ShouldInlineSimd()) return false; 1355 if (!ShouldInlineSimd()) return false;
1356 return InlineByteArrayViewLoad(call, receiver, receiver_cid, 1356 return InlineByteArrayViewLoad(call, receiver, receiver_cid,
1357 kTypedDataFloat32x4ArrayCid, 1357 kTypedDataFloat32x4ArrayCid,
1358 ic_data, entry, last); 1358 ic_data, entry, last);
1359 case MethodRecognizer::kByteArrayBaseGetInt32x4: 1359 case MethodRecognizer::kByteArrayBaseGetInt32x4:
1360 if (!ShouldInlineSimd()) return false; 1360 if (!ShouldInlineSimd()) return false;
1361 return InlineByteArrayViewLoad(call, receiver, receiver_cid, 1361 return InlineByteArrayViewLoad(call, receiver, receiver_cid,
1362 kTypedDataInt32x4ArrayCid, 1362 kTypedDataInt32x4ArrayCid,
1363 ic_data, entry, last); 1363 ic_data, entry, last);
1364 case MethodRecognizer::kByteArrayBaseSetInt8:
1365 return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
1366 kTypedDataInt8ArrayCid,
1367 ic_data, entry, last);
1368 case MethodRecognizer::kByteArrayBaseSetUint8:
1369 return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
1370 kTypedDataUint8ArrayCid,
1371 ic_data, entry, last);
1372 case MethodRecognizer::kByteArrayBaseSetInt16:
1373 return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
1374 kTypedDataInt16ArrayCid,
1375 ic_data, entry, last);
1376 case MethodRecognizer::kByteArrayBaseSetUint16:
1377 return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
1378 kTypedDataUint16ArrayCid,
1379 ic_data, entry, last);
1380 case MethodRecognizer::kByteArrayBaseSetInt32:
1381 return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
1382 kTypedDataInt32ArrayCid,
1383 ic_data, entry, last);
1384 case MethodRecognizer::kByteArrayBaseSetUint32:
1385 return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
1386 kTypedDataUint32ArrayCid,
1387 ic_data, entry, last);
1388 case MethodRecognizer::kByteArrayBaseSetFloat32:
1389 return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
1390 kTypedDataFloat32ArrayCid,
1391 ic_data, entry, last);
1392 case MethodRecognizer::kByteArrayBaseSetFloat64:
1393 return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
1394 kTypedDataFloat64ArrayCid,
1395 ic_data, entry, last);
1396 case MethodRecognizer::kByteArrayBaseSetFloat32x4:
1397 if (!ShouldInlineSimd()) return false;
1398 return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
1399 kTypedDataFloat32x4ArrayCid,
1400 ic_data, entry, last);
1401 case MethodRecognizer::kByteArrayBaseSetInt32x4:
1402 if (!ShouldInlineSimd()) return false;
1403 return InlineByteArrayViewStore(target, call, receiver, receiver_cid,
1404 kTypedDataInt32x4ArrayCid,
1405 ic_data, entry, last);
1364 default: 1406 default:
1365 return false; 1407 return false;
1366 } 1408 }
1367 } 1409 }
1368 1410
1369 1411
1370 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, 1412 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call,
1371 intptr_t array_cid, 1413 intptr_t array_cid,
1372 Definition** array, 1414 Definition** array,
1373 Definition* index, 1415 Definition* index,
(...skipping 1658 matching lines...) Expand 10 before | Expand all | Expand 10 after
3032 view_cid, 3074 view_cid,
3033 deopt_id); 3075 deopt_id);
3034 flow_graph()->AppendTo(cursor, 3076 flow_graph()->AppendTo(cursor,
3035 *last, 3077 *last,
3036 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, 3078 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL,
3037 Definition::kValue); 3079 Definition::kValue);
3038 return true; 3080 return true;
3039 } 3081 }
3040 3082
3041 3083
3084 bool FlowGraphOptimizer::InlineByteArrayViewStore(const Function& target,
3085 Instruction* call,
3086 Definition* receiver,
3087 intptr_t array_cid,
3088 intptr_t view_cid,
3089 const ICData& ic_data,
3090 TargetEntryInstr** entry,
3091 Definition** last) {
3092 ASSERT(array_cid != kIllegalCid);
3093 Definition* array = receiver;
3094 Definition* index = call->ArgumentAt(1);
3095 *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(),
3096 call->GetBlock()->try_index());
3097 (*entry)->InheritDeoptTarget(call);
3098 Instruction* cursor = *entry;
3099
3100 array_cid = PrepareInlineByteArrayViewOp(call,
3101 array_cid,
3102 view_cid,
3103 &array,
3104 index,
3105 &cursor);
3106
3107 // Extract the instance call so we can use the function_name in the stored
3108 // value check ICData.
3109 InstanceCallInstr* i_call = NULL;
3110 if (call->IsPolymorphicInstanceCall()) {
3111 i_call = call->AsPolymorphicInstanceCall()->instance_call();
3112 } else {
3113 ASSERT(call->IsInstanceCall());
3114 i_call = call->AsInstanceCall();
3115 }
3116 ASSERT(i_call != NULL);
3117 ICData& value_check = ICData::ZoneHandle();
3118 switch (view_cid) {
3119 case kTypedDataInt8ArrayCid:
3120 case kTypedDataUint8ArrayCid:
3121 case kTypedDataUint8ClampedArrayCid:
3122 case kExternalTypedDataUint8ArrayCid:
3123 case kExternalTypedDataUint8ClampedArrayCid:
3124 case kTypedDataInt16ArrayCid:
3125 case kTypedDataUint16ArrayCid: {
3126 // Check that value is always smi.
3127 value_check = ICData::New(flow_graph_->parsed_function().function(),
3128 i_call->function_name(),
3129 Object::empty_array(), // Dummy args. descr.
3130 Isolate::kNoDeoptId,
3131 1);
3132 value_check.AddReceiverCheck(kSmiCid, target);
3133 break;
3134 }
3135 case kTypedDataInt32ArrayCid:
3136 case kTypedDataUint32ArrayCid:
3137 // We don't have ICData for the value stored, so we optimistically assume
3138 // smis first. If we ever deoptimized here, we require to unbox the value
3139 // before storing to handle the mint case, too.
3140 if (i_call->ic_data()->deopt_reason() == kDeoptUnknown) {
3141 value_check = ICData::New(flow_graph_->parsed_function().function(),
3142 i_call->function_name(),
3143 Object::empty_array(), // Dummy args. descr.
3144 Isolate::kNoDeoptId,
3145 1);
3146 value_check.AddReceiverCheck(kSmiCid, target);
3147 }
3148 break;
3149 case kTypedDataFloat32ArrayCid:
3150 case kTypedDataFloat64ArrayCid: {
3151 // Check that value is always double.
3152 value_check = ICData::New(flow_graph_->parsed_function().function(),
3153 i_call->function_name(),
3154 Object::empty_array(), // Dummy args. descr.
3155 Isolate::kNoDeoptId,
3156 1);
3157 value_check.AddReceiverCheck(kDoubleCid, target);
3158 break;
3159 }
3160 case kTypedDataInt32x4ArrayCid: {
3161 // Check that value is always Int32x4.
3162 value_check = ICData::New(flow_graph_->parsed_function().function(),
3163 i_call->function_name(),
3164 Object::empty_array(), // Dummy args. descr.
3165 Isolate::kNoDeoptId,
3166 1);
3167 value_check.AddReceiverCheck(kInt32x4Cid, target);
3168 break;
3169 }
3170 case kTypedDataFloat32x4ArrayCid: {
3171 // Check that value is always Float32x4.
3172 value_check = ICData::New(flow_graph_->parsed_function().function(),
3173 i_call->function_name(),
3174 Object::empty_array(), // Dummy args. descr.
3175 Isolate::kNoDeoptId,
3176 1);
3177 value_check.AddReceiverCheck(kFloat32x4Cid, target);
3178 break;
3179 }
3180 default:
3181 // Array cids are already checked in the caller.
3182 UNREACHABLE();
3183 }
3184
3185 Definition* stored_value = call->ArgumentAt(2);
3186 if (!value_check.IsNull()) {
3187 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(),
3188 call);
3189 }
3190 StoreBarrierType needs_store_barrier = kNoStoreBarrier;
3191 *last = new StoreIndexedInstr(new Value(array),
3192 new Value(index),
3193 new Value(stored_value),
3194 needs_store_barrier,
3195 1, // Index scale
3196 view_cid,
3197 call->deopt_id());
3198
3199 flow_graph()->AppendTo(cursor,
3200 *last,
3201 call->deopt_id() != Isolate::kNoDeoptId ?
3202 call->env() : NULL,
3203 Definition::kEffect);
3204 return true;
3205 }
3206
3207
3208
3042 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp( 3209 intptr_t FlowGraphOptimizer::PrepareInlineByteArrayViewOp(
3043 Instruction* call, 3210 Instruction* call,
3044 intptr_t array_cid, 3211 intptr_t array_cid,
3045 intptr_t view_cid, 3212 intptr_t view_cid,
3046 Definition** array, 3213 Definition** array,
3047 Definition* byte_index, 3214 Definition* byte_index,
3048 Instruction** cursor) { 3215 Instruction** cursor) {
3049 // Insert byte_index smi check. 3216 // Insert byte_index smi check.
3050 *cursor = flow_graph()->AppendTo(*cursor, 3217 *cursor = flow_graph()->AppendTo(*cursor,
3051 new CheckSmiInstr(new Value(byte_index), 3218 new CheckSmiInstr(new Value(byte_index),
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
3178 (view_cid == kTypedDataInt32x4ArrayCid); 3345 (view_cid == kTypedDataInt32x4ArrayCid);
3179 if (simd_view && !ShouldInlineSimd()) { 3346 if (simd_view && !ShouldInlineSimd()) {
3180 return false; 3347 return false;
3181 } 3348 }
3182 ASSERT(call->HasICData()); 3349 ASSERT(call->HasICData());
3183 Function& target = Function::Handle(); 3350 Function& target = Function::Handle();
3184 GrowableArray<intptr_t> class_ids; 3351 GrowableArray<intptr_t> class_ids;
3185 call->ic_data()->GetCheckAt(0, &class_ids, &target); 3352 call->ic_data()->GetCheckAt(0, &class_ids, &target);
3186 const intptr_t receiver_cid = class_ids[0]; 3353 const intptr_t receiver_cid = class_ids[0];
3187 3354
3188 Definition* array = call->ArgumentAt(0); 3355 TargetEntryInstr* entry;
3189 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array); 3356 Definition* last;
3190 ICData& value_check = ICData::ZoneHandle(); 3357 if (!TryInlineRecognizedMethod(receiver_cid,
3191 switch (view_cid) { 3358 target,
3192 case kTypedDataInt8ArrayCid: 3359 call,
3193 case kTypedDataUint8ArrayCid: 3360 call->ArgumentAt(0),
3194 case kTypedDataUint8ClampedArrayCid: 3361 call->token_pos(),
3195 case kExternalTypedDataUint8ArrayCid: 3362 *call->ic_data(),
3196 case kExternalTypedDataUint8ClampedArrayCid: 3363 &entry, &last)) {
3197 case kTypedDataInt16ArrayCid: 3364 return false;
3198 case kTypedDataUint16ArrayCid: {
3199 // Check that value is always smi.
3200 value_check = ICData::New(flow_graph_->parsed_function().function(),
3201 call->function_name(),
3202 Object::empty_array(), // Dummy args. descr.
3203 Isolate::kNoDeoptId,
3204 1);
3205 value_check.AddReceiverCheck(kSmiCid, target);
3206 break;
3207 }
3208 case kTypedDataInt32ArrayCid:
3209 case kTypedDataUint32ArrayCid:
3210 // We don't have ICData for the value stored, so we optimistically assume
3211 // smis first. If we ever deoptimized here, we require to unbox the value
3212 // before storing to handle the mint case, too.
3213 if (call->ic_data()->deopt_reason() == kDeoptUnknown) {
3214 value_check = ICData::New(flow_graph_->parsed_function().function(),
3215 call->function_name(),
3216 Object::empty_array(), // Dummy args. descr.
3217 Isolate::kNoDeoptId,
3218 1);
3219 value_check.AddReceiverCheck(kSmiCid, target);
3220 }
3221 break;
3222 case kTypedDataFloat32ArrayCid:
3223 case kTypedDataFloat64ArrayCid: {
3224 // Check that value is always double.
3225 value_check = ICData::New(flow_graph_->parsed_function().function(),
3226 call->function_name(),
3227 Object::empty_array(), // Dummy args. descr.
3228 Isolate::kNoDeoptId,
3229 1);
3230 value_check.AddReceiverCheck(kDoubleCid, target);
3231 break;
3232 }
3233 case kTypedDataInt32x4ArrayCid: {
3234 // Check that value is always Int32x4.
3235 value_check = ICData::New(flow_graph_->parsed_function().function(),
3236 call->function_name(),
3237 Object::empty_array(), // Dummy args. descr.
3238 Isolate::kNoDeoptId,
3239 1);
3240 value_check.AddReceiverCheck(kInt32x4Cid, target);
3241 break;
3242 }
3243 case kTypedDataFloat32x4ArrayCid: {
3244 // Check that value is always Float32x4.
3245 value_check = ICData::New(flow_graph_->parsed_function().function(),
3246 call->function_name(),
3247 Object::empty_array(), // Dummy args. descr.
3248 Isolate::kNoDeoptId,
3249 1);
3250 value_check.AddReceiverCheck(kFloat32x4Cid, target);
3251 break;
3252 }
3253 default:
3254 // Array cids are already checked in the caller.
3255 UNREACHABLE();
3256 } 3365 }
3257 3366
3258 Definition* index = call->ArgumentAt(1); 3367 // Insert receiver class check.
3259 Definition* stored_value = call->ArgumentAt(2); 3368 AddReceiverCheck(call);
3260 if (!value_check.IsNull()) { 3369 // Remove the original push arguments.
3261 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), 3370 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
3262 call); 3371 PushArgumentInstr* push = call->PushArgumentAt(i);
3372 push->ReplaceUsesWith(push->value()->definition());
3373 push->RemoveFromGraph();
3263 } 3374 }
3264 StoreBarrierType needs_store_barrier = kNoStoreBarrier; 3375 // Replace all uses of this definition with the result.
3265 StoreIndexedInstr* array_op = new StoreIndexedInstr(new Value(array), 3376 call->ReplaceUsesWith(last);
3266 new Value(index), 3377 // Finally insert the sequence other definition in place of this one in the
3267 new Value(stored_value), 3378 // graph.
3268 needs_store_barrier, 3379 call->previous()->LinkTo(entry->next());
3269 1, // Index scale 3380 entry->UnuseAllInputs(); // Entry block is not in the graph.
3270 view_cid, 3381 last->LinkTo(call);
3271 call->deopt_id()); 3382 // Remove through the iterator.
3272 ReplaceCall(call, array_op); 3383 ASSERT(current_iterator()->Current() == call);
3384 current_iterator()->RemoveCurrentFromGraph();
3385 call->set_previous(NULL);
3386 call->set_next(NULL);
3273 return true; 3387 return true;
3274 } 3388 }
3275 3389
3276 3390
3277 void FlowGraphOptimizer::PrepareByteArrayViewOp( 3391 void FlowGraphOptimizer::PrepareByteArrayViewOp(
3278 InstanceCallInstr* call, 3392 InstanceCallInstr* call,
3279 intptr_t receiver_cid, 3393 intptr_t receiver_cid,
3280 intptr_t view_cid, 3394 intptr_t view_cid,
3281 Definition** array) { 3395 Definition** array) {
3282 Definition* byte_index = call->ArgumentAt(1); 3396 Definition* byte_index = call->ArgumentAt(1);
(...skipping 5213 matching lines...) Expand 10 before | Expand all | Expand 10 after
8496 } 8610 }
8497 8611
8498 // Insert materializations at environment uses. 8612 // Insert materializations at environment uses.
8499 for (intptr_t i = 0; i < exits.length(); i++) { 8613 for (intptr_t i = 0; i < exits.length(); i++) {
8500 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); 8614 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
8501 } 8615 }
8502 } 8616 }
8503 8617
8504 8618
8505 } // namespace dart 8619 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698