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

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

Issue 11092090: Inline indexed load and store of typed array float64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 GrowableArray<intptr_t> class_ids; 367 GrowableArray<intptr_t> class_ids;
368 Function& target = Function::Handle(); 368 Function& target = Function::Handle();
369 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 369 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
370 ic_data.GetCheckAt(i, &class_ids, &target); 370 ic_data.GetCheckAt(i, &class_ids, &target);
371 if (class_ids[arg_n] != kSmiCid) return false; 371 if (class_ids[arg_n] != kSmiCid) return false;
372 } 372 }
373 return true; 373 return true;
374 } 374 }
375 375
376 376
377 bool FlowGraphOptimizer::TryReplaceWithArrayOp(InstanceCallInstr* call, 377 // Returns array to load from.
378 Token::Kind op_kind) { 378 Value* FlowGraphOptimizer::PrepareIndexedOp(InstanceCallInstr* call,
379 intptr_t class_id) {
380 Value* array = call->ArgumentAt(0)->value();
381 Value* index = call->ArgumentAt(1)->value();
382 // Insert class check and index smi checks and attach a copy of the
383 // original environment because the operation can still deoptimize.
384 AddCheckClass(call, array->Copy());
385 InsertBefore(call,
386 new CheckSmiInstr(index->Copy(), call->deopt_id()),
387 call->env(),
388 Definition::kEffect);
389 // If both index and array are constants, then the bound check always
390 // succeeded.
391 // TODO(srdjan): Remove once constant propagation lands.
392 if (!(array->BindsToConstant() && index->BindsToConstant())) {
393 // Insert array bounds check.
394 InsertBefore(call,
395 new CheckArrayBoundInstr(array->Copy(),
396 index->Copy(),
397 class_id,
398 call),
399 call->env(),
400 Definition::kEffect);
401 }
402 if (class_id == kGrowableObjectArrayCid) {
403 // Insert data elements load.
404 LoadFieldInstr* elements =
405 new LoadFieldInstr(array->Copy(),
406 GrowableObjectArray::data_offset(),
407 Type::ZoneHandle(Type::DynamicType()));
408 elements->set_result_cid(kArrayCid);
409 InsertBefore(call, elements, NULL, Definition::kValue);
410 array = new Value(elements);
411 }
412 return array;
413 }
414
415
416 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) {
379 // TODO(fschneider): Optimize []= operator in checked mode as well. 417 // TODO(fschneider): Optimize []= operator in checked mode as well.
380 if (op_kind == Token::kASSIGN_INDEX && FLAG_enable_type_checks) return false; 418 if (FLAG_enable_type_checks) return false;
381
382 const intptr_t class_id = ReceiverClassId(call); 419 const intptr_t class_id = ReceiverClassId(call);
383 switch (class_id) { 420 switch (class_id) {
384 case kImmutableArrayCid:
385 // Stores are only specialized for Array and GrowableObjectArray,
386 // not for ImmutableArray.
387 if (op_kind == Token::kASSIGN_INDEX) return false;
388 // Fall through.
389 case kArrayCid: 421 case kArrayCid:
390 case kGrowableObjectArrayCid: { 422 case kGrowableObjectArrayCid:
391 Value* array = call->ArgumentAt(0)->value(); 423 case kFloat64ArrayCid:
392 Value* index = call->ArgumentAt(1)->value(); 424 // Acceptable store index classes.
393 // Insert class check and index smi checks and attach a copy of the 425 break;
394 // original environment because the operation can still deoptimize.
395 AddCheckClass(call, array->Copy());
396 InsertBefore(call,
397 new CheckSmiInstr(index->Copy(), call->deopt_id()),
398 call->env(),
399 Definition::kEffect);
400 // If both index and array are constants, then the bound check always
401 // succeeded.
402 // TODO(srdjan): Remove once constant propagation lands.
403 if (!(array->BindsToConstant() && index->BindsToConstant())) {
404 // Insert array bounds check.
405 InsertBefore(call,
406 new CheckArrayBoundInstr(array->Copy(),
407 index->Copy(),
408 class_id,
409 call),
410 call->env(),
411 Definition::kEffect);
412 }
413 if (class_id == kGrowableObjectArrayCid) {
414 // Insert data elements load.
415 LoadFieldInstr* elements =
416 new LoadFieldInstr(array->Copy(),
417 GrowableObjectArray::data_offset(),
418 Type::ZoneHandle(Type::DynamicType()));
419 elements->set_result_cid(kArrayCid);
420 InsertBefore(call, elements, NULL, Definition::kValue);
421 array = new Value(elements);
422 }
423 Definition* array_op = NULL;
424 if (op_kind == Token::kINDEX) {
425 array_op = new LoadIndexedInstr(array, index);
426 } else {
427 bool needs_store_barrier = true;
428 if (ArgIsAlwaysSmi(*call->ic_data(), 2)) {
429 InsertBefore(call,
430 new CheckSmiInstr(call->ArgumentAt(2)->value()->Copy(),
431 call->deopt_id()),
432 call->env(),
433 Definition::kEffect);
434 needs_store_barrier = false;
435 }
436 Value* value = call->ArgumentAt(2)->value();
437 array_op =
438 new StoreIndexedInstr(array, index, value, needs_store_barrier);
439 }
440 call->ReplaceWith(array_op, current_iterator());
441 RemovePushArguments(call);
442 return true;
443 }
444 default: 426 default:
445 return false; 427 return false;
446 } 428 }
429 Value* array = PrepareIndexedOp(call, class_id);
430 // Check if store barrier is needed.
431 bool needs_store_barrier = true;
432 if (ArgIsAlwaysSmi(*call->ic_data(), 2)) {
433 InsertBefore(call,
434 new CheckSmiInstr(call->ArgumentAt(2)->value()->Copy(),
435 call->deopt_id()),
436 call->env(),
437 Definition::kEffect);
438 needs_store_barrier = false;
439 }
440
441 Value* index = call->ArgumentAt(1)->value();
442 Value* value = call->ArgumentAt(2)->value();
443 Definition* array_op =
444 new StoreIndexedInstr(array, index, value,
445 needs_store_barrier, class_id, call->deopt_id());
446 call->ReplaceWith(array_op, current_iterator());
447 RemovePushArguments(call);
448 return true;
447 } 449 }
448 450
449 451
452
453 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) {
454 const intptr_t class_id = ReceiverClassId(call);
455 switch (class_id) {
456 case kArrayCid:
457 case kImmutableArrayCid:
458 case kGrowableObjectArrayCid:
459 case kFloat64ArrayCid:
460 // Acceptable load index classes.
461 break;
462 default:
463 return false;
464 }
465 Value* array = PrepareIndexedOp(call, class_id);
466 Value* index = call->ArgumentAt(1)->value();
467 Definition* array_op = new LoadIndexedInstr(array, index, class_id);
468 call->ReplaceWith(array_op, current_iterator());
469 RemovePushArguments(call);
470 return true;
471 }
472
473
450 void FlowGraphOptimizer::InsertBefore(Instruction* next, 474 void FlowGraphOptimizer::InsertBefore(Instruction* next,
451 Instruction* instr, 475 Instruction* instr,
452 Environment* env, 476 Environment* env,
453 Definition::UseKind use_kind) { 477 Definition::UseKind use_kind) {
454 if (env != NULL) env->DeepCopyTo(instr); 478 if (env != NULL) env->DeepCopyTo(instr);
455 if (use_kind == Definition::kValue) { 479 if (use_kind == Definition::kValue) {
456 ASSERT(instr->IsDefinition()); 480 ASSERT(instr->IsDefinition());
457 instr->AsDefinition()->set_ssa_temp_index( 481 instr->AsDefinition()->set_ssa_temp_index(
458 flow_graph_->alloc_ssa_temp_index()); 482 flow_graph_->alloc_ssa_temp_index());
459 } 483 }
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 977
954 return false; 978 return false;
955 } 979 }
956 980
957 981
958 // Tries to optimize instance call by replacing it with a faster instruction 982 // Tries to optimize instance call by replacing it with a faster instruction
959 // (e.g, binary op, field load, ..). 983 // (e.g, binary op, field load, ..).
960 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { 984 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
961 if (instr->HasICData() && (instr->ic_data()->NumberOfChecks() > 0)) { 985 if (instr->HasICData() && (instr->ic_data()->NumberOfChecks() > 0)) {
962 const Token::Kind op_kind = instr->token_kind(); 986 const Token::Kind op_kind = instr->token_kind();
963 if (Token::IsIndexOperator(op_kind) && 987 if ((op_kind == Token::kASSIGN_INDEX) &&
964 TryReplaceWithArrayOp(instr, op_kind)) { 988 TryReplaceWithStoreIndexed(instr)) {
989 return;
990 }
991 if ((op_kind == Token::kINDEX) && TryReplaceWithLoadIndexed(instr)) {
965 return; 992 return;
966 } 993 }
967 if (Token::IsBinaryToken(op_kind) && 994 if (Token::IsBinaryToken(op_kind) &&
968 TryReplaceWithBinaryOp(instr, op_kind)) { 995 TryReplaceWithBinaryOp(instr, op_kind)) {
969 return; 996 return;
970 } 997 }
971 if (Token::IsUnaryToken(op_kind) && 998 if (Token::IsUnaryToken(op_kind) &&
972 TryReplaceWithUnaryOp(instr, op_kind)) { 999 TryReplaceWithUnaryOp(instr, op_kind)) {
973 return; 1000 return;
974 } 1001 }
(...skipping 2303 matching lines...) Expand 10 before | Expand all | Expand 10 after
3278 3305
3279 if (FLAG_trace_constant_propagation) { 3306 if (FLAG_trace_constant_propagation) {
3280 OS::Print("\n==== After constant propagation ====\n"); 3307 OS::Print("\n==== After constant propagation ====\n");
3281 FlowGraphPrinter printer(*graph_); 3308 FlowGraphPrinter printer(*graph_);
3282 printer.PrintBlocks(); 3309 printer.PrintBlocks();
3283 } 3310 }
3284 } 3311 }
3285 3312
3286 3313
3287 } // namespace dart 3314 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698