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

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
« 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) 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 classid to load from, array and idnex value
378 Token::Kind op_kind) { 378
379 intptr_t FlowGraphOptimizer::PrepareIndexedOp(InstanceCallInstr* call,
380 intptr_t class_id,
381 Value** array,
382 Value** index) {
383 *array = call->ArgumentAt(0)->value();
384 *index = call->ArgumentAt(1)->value();
385 // Insert class check and index smi checks and attach a copy of the
386 // original environment because the operation can still deoptimize.
387 AddCheckClass(call, (*array)->Copy());
388 InsertBefore(call,
389 new CheckSmiInstr((*index)->Copy(), call->deopt_id()),
390 call->env(),
391 Definition::kEffect);
392 // If both index and array are constants, then the bound check always
393 // succeeded.
394 // TODO(srdjan): Remove once constant propagation lands.
395 if (!((*array)->BindsToConstant() && (*index)->BindsToConstant())) {
396 // Insert array bounds check.
397 InsertBefore(call,
398 new CheckArrayBoundInstr((*array)->Copy(),
399 (*index)->Copy(),
400 class_id,
401 call),
402 call->env(),
403 Definition::kEffect);
404 }
405 if (class_id == kGrowableObjectArrayCid) {
406 // Insert data elements load.
407 LoadFieldInstr* elements =
408 new LoadFieldInstr((*array)->Copy(),
409 GrowableObjectArray::data_offset(),
410 Type::ZoneHandle(Type::DynamicType()));
411 elements->set_result_cid(kArrayCid);
412 InsertBefore(call, elements, NULL, Definition::kValue);
413 *array = new Value(elements);
414 return kArrayCid;
415 }
416 return class_id;
417 }
418
419
420 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) {
379 // TODO(fschneider): Optimize []= operator in checked mode as well. 421 // TODO(fschneider): Optimize []= operator in checked mode as well.
380 if (op_kind == Token::kASSIGN_INDEX && FLAG_enable_type_checks) return false; 422 if (FLAG_enable_type_checks) return false;
381
382 const intptr_t class_id = ReceiverClassId(call); 423 const intptr_t class_id = ReceiverClassId(call);
424 ICData& value_check = ICData::Handle();
383 switch (class_id) { 425 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: 426 case kArrayCid:
390 case kGrowableObjectArrayCid: { 427 case kGrowableObjectArrayCid:
391 Value* array = call->ArgumentAt(0)->value(); 428 // Acceptable store index classes.
392 Value* index = call->ArgumentAt(1)->value(); 429 break;
393 // Insert class check and index smi checks and attach a copy of the 430 case kFloat64ArrayCid: {
394 // original environment because the operation can still deoptimize. 431 // Check that value is always double.
395 AddCheckClass(call, array->Copy()); 432 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
396 InsertBefore(call, 433 if ((value_check.NumberOfChecks() != 1) ||
397 new CheckSmiInstr(index->Copy(), call->deopt_id()), 434 (value_check.GetReceiverClassIdAt(0) != kDoubleCid)) {
398 call->env(), 435 return false;
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 } 436 }
413 if (class_id == kGrowableObjectArrayCid) { 437 break;
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 } 438 }
444 default: 439 default:
445 return false; 440 return false;
446 } 441 }
442 Value* array = NULL;
443 Value* index = NULL;
444 intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index);
445 Value* value = call->ArgumentAt(2)->value();
446 // Check if store barrier is needed.
447 bool needs_store_barrier = true;
448 if (class_id == kFloat64ArrayCid) {
449 ASSERT(!value_check.IsNull());
450 InsertBefore(call,
451 new CheckClassInstr(value->Copy(),
452 call->deopt_id(),
453 value_check),
454 call->env(),
455 Definition::kEffect);
456 needs_store_barrier = false;
457 } else if (ArgIsAlwaysSmi(*call->ic_data(), 2)) {
458 InsertBefore(call,
459 new CheckSmiInstr(value->Copy(), call->deopt_id()),
460 call->env(),
461 Definition::kEffect);
462 needs_store_barrier = false;
463 }
464
465 Definition* array_op =
466 new StoreIndexedInstr(array, index, value,
467 needs_store_barrier, array_cid, call->deopt_id());
468 call->ReplaceWith(array_op, current_iterator());
469 RemovePushArguments(call);
470 return true;
471 }
472
473
474
475 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) {
476 const intptr_t class_id = ReceiverClassId(call);
477 switch (class_id) {
478 case kArrayCid:
479 case kImmutableArrayCid:
480 case kGrowableObjectArrayCid:
481 case kFloat64ArrayCid:
482 // Acceptable load index classes.
483 break;
484 default:
485 return false;
486 }
487 Value* array = NULL;
488 Value* index = NULL;
489 intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index);
490 Definition* array_op = new LoadIndexedInstr(array, index, array_cid);
491 call->ReplaceWith(array_op, current_iterator());
492 RemovePushArguments(call);
493 return true;
447 } 494 }
448 495
449 496
450 void FlowGraphOptimizer::InsertBefore(Instruction* next, 497 void FlowGraphOptimizer::InsertBefore(Instruction* next,
451 Instruction* instr, 498 Instruction* instr,
452 Environment* env, 499 Environment* env,
453 Definition::UseKind use_kind) { 500 Definition::UseKind use_kind) {
454 if (env != NULL) env->DeepCopyTo(instr); 501 if (env != NULL) env->DeepCopyTo(instr);
455 if (use_kind == Definition::kValue) { 502 if (use_kind == Definition::kValue) {
456 ASSERT(instr->IsDefinition()); 503 ASSERT(instr->IsDefinition());
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 1000
954 return false; 1001 return false;
955 } 1002 }
956 1003
957 1004
958 // Tries to optimize instance call by replacing it with a faster instruction 1005 // Tries to optimize instance call by replacing it with a faster instruction
959 // (e.g, binary op, field load, ..). 1006 // (e.g, binary op, field load, ..).
960 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { 1007 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
961 if (instr->HasICData() && (instr->ic_data()->NumberOfChecks() > 0)) { 1008 if (instr->HasICData() && (instr->ic_data()->NumberOfChecks() > 0)) {
962 const Token::Kind op_kind = instr->token_kind(); 1009 const Token::Kind op_kind = instr->token_kind();
963 if (Token::IsIndexOperator(op_kind) && 1010 if ((op_kind == Token::kASSIGN_INDEX) &&
964 TryReplaceWithArrayOp(instr, op_kind)) { 1011 TryReplaceWithStoreIndexed(instr)) {
1012 return;
1013 }
1014 if ((op_kind == Token::kINDEX) && TryReplaceWithLoadIndexed(instr)) {
965 return; 1015 return;
966 } 1016 }
967 if (Token::IsBinaryToken(op_kind) && 1017 if (Token::IsBinaryToken(op_kind) &&
968 TryReplaceWithBinaryOp(instr, op_kind)) { 1018 TryReplaceWithBinaryOp(instr, op_kind)) {
969 return; 1019 return;
970 } 1020 }
971 if (Token::IsUnaryToken(op_kind) && 1021 if (Token::IsUnaryToken(op_kind) &&
972 TryReplaceWithUnaryOp(instr, op_kind)) { 1022 TryReplaceWithUnaryOp(instr, op_kind)) {
973 return; 1023 return;
974 } 1024 }
(...skipping 2303 matching lines...) Expand 10 before | Expand all | Expand 10 after
3278 3328
3279 if (FLAG_trace_constant_propagation) { 3329 if (FLAG_trace_constant_propagation) {
3280 OS::Print("\n==== After constant propagation ====\n"); 3330 OS::Print("\n==== After constant propagation ====\n");
3281 FlowGraphPrinter printer(*graph_); 3331 FlowGraphPrinter printer(*graph_);
3282 printer.PrintBlocks(); 3332 printer.PrintBlocks();
3283 } 3333 }
3284 } 3334 }
3285 3335
3286 3336
3287 } // namespace dart 3337 } // 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