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

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

Issue 2235433002: VM: Add more array intrinsics. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 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
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 // Class for intrinsifying functions. 4 // Class for intrinsifying functions.
5 5
6 #include "vm/assembler.h" 6 #include "vm/assembler.h"
7 #include "vm/compiler.h" 7 #include "vm/compiler.h"
8 #include "vm/cpu.h" 8 #include "vm/cpu.h"
9 #include "vm/flags.h" 9 #include "vm/flags.h"
10 #include "vm/flow_graph.h" 10 #include "vm/flow_graph.h"
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 new LoadFieldInstr(new Value(array), 377 new LoadFieldInstr(new Value(array),
378 length_offset, 378 length_offset,
379 Type::ZoneHandle(Type::SmiType()), 379 Type::ZoneHandle(Type::SmiType()),
380 TokenPosition::kNoSource)); 380 TokenPosition::kNoSource));
381 builder->AddInstruction( 381 builder->AddInstruction(
382 new CheckArrayBoundInstr(new Value(length), 382 new CheckArrayBoundInstr(new Value(length),
383 new Value(index), 383 new Value(index),
384 Thread::kNoDeoptId)); 384 Thread::kNoDeoptId));
385 } 385 }
386 386
387 387 static bool IntrinsifyArrayGetIndexed(FlowGraph* flow_graph,
388 bool Intrinsifier::Build_ObjectArrayGetIndexed(FlowGraph* flow_graph) { 388 intptr_t array_cid) {
389 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); 389 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
390 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); 390 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
391 BlockBuilder builder(flow_graph, normal_entry); 391 BlockBuilder builder(flow_graph, normal_entry);
392
393 Definition* index = builder.AddParameter(1);
394 Definition* array = builder.AddParameter(2);
395
396 PrepareIndexedOp(&builder, array, index, Array::length_offset());
397
398 Definition* result = builder.AddDefinition(
399 new LoadIndexedInstr(new Value(array),
400 new Value(index),
401 Instance::ElementSizeFor(kArrayCid), // index scale
402 kArrayCid,
403 Thread::kNoDeoptId,
404 builder.TokenPos()));
405 builder.AddIntrinsicReturn(new Value(result));
406 return true;
407 }
408
409
410 bool Intrinsifier::Build_ImmutableArrayGetIndexed(FlowGraph* flow_graph) {
411 return Build_ObjectArrayGetIndexed(flow_graph);
412 }
413
414
415 bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) {
416 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
417 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
418 BlockBuilder builder(flow_graph, normal_entry);
419 392
420 Definition* index = builder.AddParameter(1); 393 Definition* index = builder.AddParameter(1);
421 Definition* array = builder.AddParameter(2); 394 Definition* array = builder.AddParameter(2);
422 395
423 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); 396 intptr_t length_offset = Array::length_offset();
397 if (RawObject::IsTypedDataClassId(array_cid)) {
398 length_offset = TypedData::length_offset();
399 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
400 length_offset = ExternalTypedData::length_offset();
401 }
402
403 PrepareIndexedOp(&builder, array, index, length_offset);
404
405 if (RawObject::IsExternalTypedDataClassId(array_cid)) {
406 array = builder.AddDefinition(
407 new LoadUntaggedInstr(new Value(array),
408 ExternalTypedData::data_offset()));
409 }
424 410
425 Definition* result = builder.AddDefinition( 411 Definition* result = builder.AddDefinition(
426 new LoadIndexedInstr(new Value(array), 412 new LoadIndexedInstr(new Value(array),
427 new Value(index), 413 new Value(index),
428 1, // index scale 414 Instance::ElementSizeFor(array_cid), // index scale
429 kTypedDataUint8ArrayCid, 415 array_cid,
430 Thread::kNoDeoptId, 416 Thread::kNoDeoptId,
431 builder.TokenPos())); 417 builder.TokenPos()));
418 // Box and/or convert result if necessary.
419 switch (array_cid) {
420 case kTypedDataInt32ArrayCid:
421 case kExternalTypedDataInt32ArrayCid:
422 result = builder.AddDefinition(
423 BoxInstr::Create(kUnboxedInt32, new Value(result)));
424 break;
425 case kTypedDataUint32ArrayCid:
426 case kExternalTypedDataUint32ArrayCid:
427 result = builder.AddDefinition(
428 BoxInstr::Create(kUnboxedUint32, new Value(result)));
429 break;
430 case kTypedDataFloat32ArrayCid:
431 result = builder.AddDefinition(
432 new FloatToDoubleInstr(new Value(result), Thread::kNoDeoptId));
433 // Fall through.
434 case kTypedDataFloat64ArrayCid:
435 result = builder.AddDefinition(
436 BoxInstr::Create(kUnboxedDouble, new Value(result)));
437 break;
438 default:
439 ASSERT(array_cid == kArrayCid ||
440 array_cid == kImmutableArrayCid ||
441 array_cid == kTypedDataUint8ArrayCid ||
442 array_cid == kExternalTypedDataUint8ArrayCid);
443 break;
444 }
432 builder.AddIntrinsicReturn(new Value(result)); 445 builder.AddIntrinsicReturn(new Value(result));
433 return true; 446 return true;
434 } 447 }
435 448
436 449
437 bool Intrinsifier::Build_ExternalUint8ArrayGetIndexed(FlowGraph* flow_graph) { 450 static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph,
451 intptr_t array_cid) {
438 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); 452 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
439 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); 453 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
440 BlockBuilder builder(flow_graph, normal_entry); 454 BlockBuilder builder(flow_graph, normal_entry);
441
442 Definition* index = builder.AddParameter(1);
443 Definition* array = builder.AddParameter(2);
444
445 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset());
446
447 Definition* elements = builder.AddDefinition(
448 new LoadUntaggedInstr(new Value(array),
449 ExternalTypedData::data_offset()));
450 Definition* result = builder.AddDefinition(
451 new LoadIndexedInstr(new Value(elements),
452 new Value(index),
453 1, // index scale
454 kExternalTypedDataUint8ArrayCid,
455 Thread::kNoDeoptId,
456 builder.TokenPos()));
457 builder.AddIntrinsicReturn(new Value(result));
458 return true;
459 }
460
461
462 bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) {
463 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
464 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
465 BlockBuilder builder(flow_graph, normal_entry);
466 455
467 Definition* value = builder.AddParameter(1); 456 Definition* value = builder.AddParameter(1);
468 Definition* index = builder.AddParameter(2); 457 Definition* index = builder.AddParameter(2);
469 Definition* array = builder.AddParameter(3); 458 Definition* array = builder.AddParameter(3);
470 459
471 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); 460 intptr_t length_offset = Array::length_offset();
461 if (RawObject::IsTypedDataClassId(array_cid)) {
462 length_offset = TypedData::length_offset();
463 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
464 length_offset = ExternalTypedData::length_offset();
465 }
472 466
473 builder.AddInstruction( 467 PrepareIndexedOp(&builder, array, index, length_offset);
474 new CheckSmiInstr(new Value(value),
475 Thread::kNoDeoptId,
476 builder.TokenPos()));
477 468
469 // Value check/conversion.
470 switch (array_cid) {
471 case kTypedDataUint8ArrayCid:
472 case kExternalTypedDataUint8ArrayCid:
473 builder.AddInstruction(new CheckSmiInstr(new Value(value),
474 Thread::kNoDeoptId,
475 builder.TokenPos()));
476 break;
477 case kTypedDataInt32ArrayCid:
478 case kExternalTypedDataInt32ArrayCid:
479 // Use same truncating unbox-instruction for int32 and uint32.
480 // Fall-through.
481 case kTypedDataUint32ArrayCid:
482 case kExternalTypedDataUint32ArrayCid:
483 // Supports smi and mint, slow-case for bigints.
484 value = builder.AddUnboxInstr(kUnboxedUint32,
485 new Value(value),
486 /* is_checked = */ false);
487 break;
488 case kTypedDataFloat32ArrayCid:
489 case kTypedDataFloat64ArrayCid: {
490 const ICData& value_check = ICData::ZoneHandle(ICData::New(
491 flow_graph->function(),
492 Symbols::Empty(), // Dummy function name.
493 Object::empty_array(), // Dummy args. descr.
494 Thread::kNoDeoptId,
495 1,
496 false));
497 value_check.AddReceiverCheck(kDoubleCid, flow_graph->function());
498 builder.AddInstruction(
499 new CheckClassInstr(new Value(value),
500 Thread::kNoDeoptId,
501 value_check,
502 builder.TokenPos()));
503 value = builder.AddUnboxInstr(kUnboxedDouble,
504 new Value(value),
505 /* is_checked = */ true);
506 if (array_cid == kTypedDataFloat32ArrayCid) {
507 value = builder.AddDefinition(
508 new DoubleToFloatInstr(new Value(value), Thread::kNoDeoptId));
509 }
510 break;
511 }
512 default:
513 UNREACHABLE();
514 }
515
516 if (RawObject::IsExternalTypedDataClassId(array_cid)) {
517 array = builder.AddDefinition(
518 new LoadUntaggedInstr(new Value(array),
519 ExternalTypedData::data_offset()));
520 }
521 // No store barrier.
522 ASSERT(RawObject::IsExternalTypedDataClassId(array_cid) ||
523 RawObject::IsTypedDataClassId(array_cid));
478 builder.AddInstruction( 524 builder.AddInstruction(
479 new StoreIndexedInstr(new Value(array), 525 new StoreIndexedInstr(new Value(array),
480 new Value(index), 526 new Value(index),
481 new Value(value), 527 new Value(value),
482 kNoStoreBarrier, 528 kNoStoreBarrier,
483 1, // index scale 529 Instance::ElementSizeFor(array_cid), // index scale
484 kTypedDataUint8ArrayCid, 530 array_cid,
485 Thread::kNoDeoptId, 531 Thread::kNoDeoptId,
486 builder.TokenPos())); 532 builder.TokenPos()));
487 // Return null. 533 // Return null.
488 Definition* null_def = builder.AddNullDefinition();
489 builder.AddIntrinsicReturn(new Value(null_def));
490 return true;
491 }
492
493
494 bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) {
495 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
496 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
497 BlockBuilder builder(flow_graph, normal_entry);
498
499 Definition* value = builder.AddParameter(1);
500 Definition* index = builder.AddParameter(2);
501 Definition* array = builder.AddParameter(3);
502
503 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset());
504
505 builder.AddInstruction(
506 new CheckSmiInstr(new Value(value),
507 Thread::kNoDeoptId,
508 builder.TokenPos()));
509 Definition* elements = builder.AddDefinition(
510 new LoadUntaggedInstr(new Value(array),
511 ExternalTypedData::data_offset()));
512 builder.AddInstruction(
513 new StoreIndexedInstr(new Value(elements),
514 new Value(index),
515 new Value(value),
516 kNoStoreBarrier,
517 1, // index scale
518 kExternalTypedDataUint8ArrayCid,
519 Thread::kNoDeoptId,
520 builder.TokenPos()));
521 // Return null.
522 Definition* null_def = builder.AddNullDefinition(); 534 Definition* null_def = builder.AddNullDefinition();
523 builder.AddIntrinsicReturn(new Value(null_def)); 535 builder.AddIntrinsicReturn(new Value(null_def));
524 return true; 536 return true;
525 } 537 }
526 538
527 539
528 bool Intrinsifier::Build_Uint32ArraySetIndexed(FlowGraph* flow_graph) { 540 #define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \
529 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); 541 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \
530 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); 542 return IntrinsifyArrayGetIndexed( \
531 BlockBuilder builder(flow_graph, normal_entry); 543 flow_graph, \
532 544 MethodRecognizer::MethodKindToCid( \
533 Definition* value = builder.AddParameter(1); 545 MethodRecognizer::k##enum_name##GetIndexed)); \
534 Definition* index = builder.AddParameter(2);
535 Definition* array = builder.AddParameter(3);
536
537 PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
538
539 Definition* unboxed_value =
540 builder.AddUnboxInstr(kUnboxedUint32,
541 new Value(value),
542 /* is_checked = */ true);
543
544 builder.AddInstruction(
545 new StoreIndexedInstr(new Value(array),
546 new Value(index),
547 new Value(unboxed_value),
548 kNoStoreBarrier,
549 4, // index scale
550 kTypedDataUint32ArrayCid,
551 Thread::kNoDeoptId,
552 builder.TokenPos()));
553 // Return null.
554 Definition* null_def = builder.AddNullDefinition();
555 builder.AddIntrinsicReturn(new Value(null_def));
556 return true;
557 } 546 }
558 547
559 548
560 bool Intrinsifier::Build_Uint32ArrayGetIndexed(FlowGraph* flow_graph) { 549 #define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) \
561 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); 550 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \
562 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); 551 return IntrinsifyArraySetIndexed( \
563 BlockBuilder builder(flow_graph, normal_entry); 552 flow_graph, \
553 MethodRecognizer::MethodKindToCid( \
554 MethodRecognizer::k##enum_name##SetIndexed)); \
555 }
564 556
565 Definition* index = builder.AddParameter(1); 557 DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray) // Setter in intrinsifier_<arch>.cc.
566 Definition* array = builder.AddParameter(2); 558 DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray)
567 559
568 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); 560 #define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \
561 DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \
562 DEFINE_ARRAY_SETTER_INTRINSIC(enum_name)
569 563
570 Definition* unboxed_value = builder.AddDefinition( 564 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array)
571 new LoadIndexedInstr(new Value(array), 565 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array)
572 new Value(index), 566 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array)
573 4, // index scale 567 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array)
574 kTypedDataUint32ArrayCid, 568
575 Thread::kNoDeoptId, 569 #undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS
576 builder.TokenPos())); 570 #undef DEFINE_ARRAY_GETTER_INTRINSIC
577 Definition* result = builder.AddDefinition( 571 #undef DEFINE_ARRAY_SETTER_INTRINSIC
578 BoxInstr::Create(kUnboxedUint32, new Value(unboxed_value))); 572
579 builder.AddIntrinsicReturn(new Value(result)); 573
580 return true; 574 #define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \
575 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \
576 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \
577 return false; \
578 } \
579 return IntrinsifyArrayGetIndexed( \
580 flow_graph, \
581 MethodRecognizer::MethodKindToCid( \
582 MethodRecognizer::k##enum_name##GetIndexed)); \
581 } 583 }
582 584
583 585
584 bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) { 586 #define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) \
585 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { 587 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \
586 return false; 588 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \
587 } 589 return false; \
588 590 } \
589 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); 591 return IntrinsifyArraySetIndexed( \
590 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); 592 flow_graph, \
591 BlockBuilder builder(flow_graph, normal_entry); 593 MethodRecognizer::MethodKindToCid( \
592 594 MethodRecognizer::k##enum_name##SetIndexed)); \
593 Definition* value = builder.AddParameter(1);
594 Definition* index = builder.AddParameter(2);
595 Definition* array = builder.AddParameter(3);
596
597 PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
598
599 const ICData& value_check = ICData::ZoneHandle(ICData::New(
600 flow_graph->function(),
601 String::Handle(flow_graph->function().name()),
602 Object::empty_array(), // Dummy args. descr.
603 Thread::kNoDeoptId,
604 1,
605 false));
606 value_check.AddReceiverCheck(kDoubleCid, flow_graph->function());
607 builder.AddInstruction(
608 new CheckClassInstr(new Value(value),
609 Thread::kNoDeoptId,
610 value_check,
611 builder.TokenPos()));
612 Definition* double_value =
613 builder.AddUnboxInstr(kUnboxedDouble,
614 new Value(value),
615 /* is_checked = */ true);
616
617 builder.AddInstruction(
618 new StoreIndexedInstr(new Value(array),
619 new Value(index),
620 new Value(double_value),
621 kNoStoreBarrier,
622 8, // index scale
623 kTypedDataFloat64ArrayCid,
624 Thread::kNoDeoptId,
625 builder.TokenPos()));
626 // Return null.
627 Definition* null_def = builder.AddNullDefinition();
628 builder.AddIntrinsicReturn(new Value(null_def));
629 return true;
630 } 595 }
631 596
597 #define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \
598 DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \
599 DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name)
632 600
633 bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) { 601 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array)
634 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { 602 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array)
635 return false;
636 }
637 603
638 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); 604 #undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS
639 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); 605 #undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC
640 BlockBuilder builder(flow_graph, normal_entry); 606 #undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC
641
642 Definition* index = builder.AddParameter(1);
643 Definition* array = builder.AddParameter(2);
644
645 PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
646
647 Definition* unboxed_value = builder.AddDefinition(
648 new LoadIndexedInstr(new Value(array),
649 new Value(index),
650 8, // index scale
651 kTypedDataFloat64ArrayCid,
652 Thread::kNoDeoptId,
653 builder.TokenPos()));
654 Definition* result = builder.AddDefinition(
655 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_value)));
656 builder.AddIntrinsicReturn(new Value(result));
657 return true;
658 }
659 607
660 608
661 static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) { 609 static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) {
662 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); 610 GraphEntryInstr* graph_entry = flow_graph->graph_entry();
663 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); 611 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
664 BlockBuilder builder(flow_graph, normal_entry); 612 BlockBuilder builder(flow_graph, normal_entry);
665 613
666 Definition* index = builder.AddParameter(1); 614 Definition* index = builder.AddParameter(1);
667 Definition* str = builder.AddParameter(2); 615 Definition* str = builder.AddParameter(2);
668 PrepareIndexedOp(&builder, str, index, String::length_offset()); 616 PrepareIndexedOp(&builder, str, index, String::length_offset());
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after
1227 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); 1175 TargetEntryInstr* normal_entry = graph_entry->normal_entry();
1228 BlockBuilder builder(flow_graph, normal_entry); 1176 BlockBuilder builder(flow_graph, normal_entry);
1229 1177
1230 return BuildInvokeMathCFunction(&builder, 1178 return BuildInvokeMathCFunction(&builder,
1231 MethodRecognizer::kDoubleRound); 1179 MethodRecognizer::kDoubleRound);
1232 } 1180 }
1233 #endif // !defined(TARGET_ARCH_DBC) 1181 #endif // !defined(TARGET_ARCH_DBC)
1234 1182
1235 1183
1236 } // namespace dart 1184 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698