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

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

Issue 12317011: Inline ByteArray._setIndexed in the flow graph optimizer. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: fixed assert with ICData::New Created 7 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/intrinsifier_arm.cc ('k') | runtime/vm/intrinsifier_mips.cc » ('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 // The intrinsic code below is executed before a method has built its frame. 5 // The intrinsic code below is executed before a method has built its frame.
6 // The return address is on the stack and the arguments below it. 6 // The return address is on the stack and the arguments below it.
7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. 7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved.
8 // Each intrinsification method returns true if the corresponding 8 // Each intrinsification method returns true if the corresponding
9 // Dart method was intrinsified. 9 // Dart method was intrinsified.
10 10
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 ECX); 242 ECX);
243 // Caller is responsible of preserving the value if necessary. 243 // Caller is responsible of preserving the value if necessary.
244 __ ret(); 244 __ ret();
245 __ Bind(&fall_through); 245 __ Bind(&fall_through);
246 return false; 246 return false;
247 } 247 }
248 248
249 249
250 // Allocate a GrowableObjectArray using the backing array specified. 250 // Allocate a GrowableObjectArray using the backing array specified.
251 // On stack: type argument (+2), data (+1), return-address (+0). 251 // On stack: type argument (+2), data (+1), return-address (+0).
252 bool Intrinsifier::GArray_Allocate(Assembler* assembler) { 252 bool Intrinsifier::GrowableArray_Allocate(Assembler* assembler) {
253 // This snippet of inlined code uses the following registers: 253 // This snippet of inlined code uses the following registers:
254 // EAX, EBX 254 // EAX, EBX
255 // and the newly allocated object is returned in EAX. 255 // and the newly allocated object is returned in EAX.
256 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; 256 const intptr_t kTypeArgumentsOffset = 2 * kWordSize;
257 const intptr_t kArrayOffset = 1 * kWordSize; 257 const intptr_t kArrayOffset = 1 * kWordSize;
258 Label fall_through; 258 Label fall_through;
259 259
260 // Compute the size to be allocated, it is based on the array length 260 // Compute the size to be allocated, it is based on the array length
261 // and is computed as: 261 // and is computed as:
262 // RoundedAllocationSize(sizeof(RawGrowableObjectArray)) + 262 // RoundedAllocationSize(sizeof(RawGrowableObjectArray)) +
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 461
462 // Gets the length of a ByteArray. 462 // Gets the length of a ByteArray.
463 bool Intrinsifier::ByteArrayBase_getLength(Assembler* assembler) { 463 bool Intrinsifier::ByteArrayBase_getLength(Assembler* assembler) {
464 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 464 __ movl(EAX, Address(ESP, + 1 * kWordSize));
465 __ movl(EAX, FieldAddress(EAX, ByteArray::length_offset())); 465 __ movl(EAX, FieldAddress(EAX, ByteArray::length_offset()));
466 __ ret(); 466 __ ret();
467 return true; 467 return true;
468 } 468 }
469 469
470 470
471 // Tests if index is a valid length (Smi and within valid index range),
472 // jumps to fall_through if it is not.
473 // Returns index in EBX, array in EAX.
474 // This should be used only on getIndexed intrinsics.
475 static void TestByteArrayGetIndex(Assembler* assembler, Label* fall_through) {
476 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array.
477 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index.
478 __ testl(EBX, Immediate(kSmiTagMask));
479 __ j(NOT_ZERO, fall_through, Assembler::kNearJump); // Non-smi index.
480 // Range check.
481 __ cmpl(EBX, FieldAddress(EAX, ByteArray::length_offset()));
482 // Runtime throws exception.
483 __ j(ABOVE_EQUAL, fall_through, Assembler::kNearJump);
484 }
485
486
487 // Tests if index is a valid length (Smi and within valid index range),
488 // jumps to fall_through if it is not.
489 // Returns index in EBX, array in EAX.
490 // This should be used only for setIndexed intrinsics.
491 static void TestByteArraySetIndex(Assembler* assembler, Label* fall_through) {
492 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // Array.
493 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index.
494 __ testl(EBX, Immediate(kSmiTagMask));
495 __ j(NOT_ZERO, fall_through, Assembler::kNearJump); // Non-smi index.
496 // Range check.
497 __ cmpl(EBX, FieldAddress(EAX, ByteArray::length_offset()));
498 // Runtime throws exception.
499 __ j(ABOVE_EQUAL, fall_through, Assembler::kNearJump);
500 }
501
502
503 bool Intrinsifier::Int8Array_getIndexed(Assembler* assembler) {
504 Label fall_through;
505 TestByteArrayGetIndex(assembler, &fall_through);
506 // EBX: index as Smi.
507 // EAX: array.
508 __ SmiUntag(EBX);
509 __ movsxb(EAX, FieldAddress(EAX,
510 EBX,
511 TIMES_1,
512 Int8Array::data_offset()));
513 __ SmiTag(EAX);
514 __ ret();
515 __ Bind(&fall_through);
516 return false;
517 }
518
519
520 bool Intrinsifier::Int8Array_setIndexed(Assembler* assembler) {
521 Label fall_through;
522 TestByteArraySetIndex(assembler, &fall_through);
523 // EBX: index as Smi.
524 // EAX: array.
525 __ SmiUntag(EBX);
526 // Free EBX for the value since we want a byte register.
527 __ movl(EDI, EBX);
528 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Value.
529 __ testl(EBX, Immediate(kSmiTagMask));
530 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
531 __ SmiUntag(EBX);
532 // Check that the value is a byte. Add 128 to EBX to bring it into
533 // the range 0..FF.
534 __ addl(EBX, Immediate(128));
535 __ cmpl(EBX, Immediate(0xFF));
536 __ j(ABOVE, &fall_through, Assembler::kNearJump);
537 // Undo addition.
538 __ subl(EBX, Immediate(128));
539 __ movb(FieldAddress(EAX, EDI, TIMES_1, Int8Array::data_offset()), BL);
540 __ ret();
541 __ Bind(&fall_through);
542 return false;
543 }
544
545
546 #define TYPED_ARRAY_ALLOCATION(type_name, scale_factor) \ 471 #define TYPED_ARRAY_ALLOCATION(type_name, scale_factor) \
547 Label fall_through; \ 472 Label fall_through; \
548 const intptr_t kArrayLengthStackOffset = 1 * kWordSize; \ 473 const intptr_t kArrayLengthStackOffset = 1 * kWordSize; \
549 __ movl(EDI, Address(ESP, kArrayLengthStackOffset)); /* Array length. */ \ 474 __ movl(EDI, Address(ESP, kArrayLengthStackOffset)); /* Array length. */ \
550 /* Check that length is a positive Smi. */ \ 475 /* Check that length is a positive Smi. */ \
551 /* EDI: requested array length argument. */ \ 476 /* EDI: requested array length argument. */ \
552 __ testl(EDI, Immediate(kSmiTagSize)); \ 477 __ testl(EDI, Immediate(kSmiTagSize)); \
553 __ j(NOT_ZERO, &fall_through); \ 478 __ j(NOT_ZERO, &fall_through); \
554 __ cmpl(EDI, Immediate(0)); \ 479 __ cmpl(EDI, Immediate(0)); \
555 __ j(LESS, &fall_through); \ 480 __ j(LESS, &fall_through); \
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 __ ret(); \ 553 __ ret(); \
629 __ Bind(&fall_through); \ 554 __ Bind(&fall_through); \
630 555
631 556
632 bool Intrinsifier::Int8Array_new(Assembler* assembler) { 557 bool Intrinsifier::Int8Array_new(Assembler* assembler) {
633 TYPED_ARRAY_ALLOCATION(Int8Array, TIMES_1); 558 TYPED_ARRAY_ALLOCATION(Int8Array, TIMES_1);
634 return false; 559 return false;
635 } 560 }
636 561
637 562
638 bool Intrinsifier::Uint8Array_getIndexed(Assembler* assembler) {
639 Label fall_through;
640 TestByteArrayGetIndex(assembler, &fall_through);
641 // EBX: index as Smi.
642 // EAX: array.
643 __ SmiUntag(EBX);
644 __ movzxb(EAX, FieldAddress(EAX,
645 EBX,
646 TIMES_1,
647 Uint8Array::data_offset()));
648 __ SmiTag(EAX);
649 __ ret();
650 __ Bind(&fall_through);
651 return false;
652 }
653
654
655 bool Intrinsifier::Uint8Array_setIndexed(Assembler* assembler) {
656 Label fall_through;
657 TestByteArraySetIndex(assembler, &fall_through);
658 // EBX: index as Smi.
659 // EAX: array.
660 __ SmiUntag(EBX);
661 // Free EBX for the value since we want a byte register.
662 __ movl(EDI, EBX);
663 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Value.
664 __ testl(EBX, Immediate(kSmiTagMask));
665 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
666 __ SmiUntag(EBX);
667 // Check that the value is a byte.
668 __ cmpl(EBX, Immediate(0xFF));
669 __ j(ABOVE, &fall_through, Assembler::kNearJump);
670 __ movb(FieldAddress(EAX, EDI, TIMES_1, Uint8Array::data_offset()), BL);
671 __ ret();
672 __ Bind(&fall_through);
673 return false;
674 }
675
676
677 bool Intrinsifier::Uint8Array_new(Assembler* assembler) { 563 bool Intrinsifier::Uint8Array_new(Assembler* assembler) {
678 TYPED_ARRAY_ALLOCATION(Uint8Array, TIMES_1); 564 TYPED_ARRAY_ALLOCATION(Uint8Array, TIMES_1);
679 return false; 565 return false;
680 } 566 }
681 567
682 568
683 bool Intrinsifier::UintClamped8Array_getIndexed(Assembler* assembler) {
684 Label fall_through;
685 TestByteArrayGetIndex(assembler, &fall_through);
686 // EBX: index as Smi.
687 // EAX: array.
688 __ SmiUntag(EBX);
689 __ movzxb(EAX, FieldAddress(EAX,
690 EBX,
691 TIMES_1,
692 Uint8ClampedArray::data_offset()));
693 __ SmiTag(EAX);
694 __ ret();
695 __ Bind(&fall_through);
696 return false;
697 }
698
699
700 bool Intrinsifier::Uint8ClampedArray_setIndexed(Assembler* assembler) {
701 Label fall_through, store_value, load_0xff;
702 TestByteArraySetIndex(assembler, &fall_through);
703 // EBX: index as Smi.
704 // EAX: array.
705 __ SmiUntag(EBX);
706 // Free EBX for the value since we need a byte register.
707 __ leal(EAX, FieldAddress(EAX, EBX, TIMES_1,
708 Uint8ClampedArray::data_offset()));
709 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Value.
710 __ testl(EBX, Immediate(kSmiTagMask));
711 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
712
713 __ SmiUntag(EBX);
714 __ cmpl(EBX, Immediate(0xFF));
715 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump);
716 // Clamp to 0x00 or 0xFF respectively.
717 __ j(GREATER, &load_0xff, Assembler::kNearJump);
718 __ xorl(EBX, EBX); // Zero.
719 __ jmp(&store_value, Assembler::kNearJump);
720 __ Bind(&load_0xff);
721 __ movl(EBX, Immediate(0xFF));
722
723 __ Bind(&store_value);
724 __ movb(Address(EAX, 0), BL);
725 __ ret();
726 __ Bind(&fall_through);
727 return false;
728 }
729
730
731 bool Intrinsifier::Uint8ClampedArray_new(Assembler* assembler) { 569 bool Intrinsifier::Uint8ClampedArray_new(Assembler* assembler) {
732 TYPED_ARRAY_ALLOCATION(Uint8ClampedArray, TIMES_1); 570 TYPED_ARRAY_ALLOCATION(Uint8ClampedArray, TIMES_1);
733 return false; 571 return false;
734 } 572 }
735 573
736 574
737 bool Intrinsifier::Int16Array_getIndexed(Assembler* assembler) {
738 Label fall_through;
739 TestByteArrayGetIndex(assembler, &fall_through);
740 // EBX: index as Smi.
741 // EAX: array.
742 __ movsxw(EAX, FieldAddress(EAX,
743 EBX,
744 TIMES_1,
745 Int16Array::data_offset()));
746 __ SmiTag(EAX);
747 __ ret();
748 __ Bind(&fall_through);
749 return false;
750 }
751
752
753 bool Intrinsifier::Int16Array_new(Assembler* assembler) { 575 bool Intrinsifier::Int16Array_new(Assembler* assembler) {
754 TYPED_ARRAY_ALLOCATION(Int16Array, TIMES_2); 576 TYPED_ARRAY_ALLOCATION(Int16Array, TIMES_2);
755 return false; 577 return false;
756 } 578 }
757 579
758 580
759 bool Intrinsifier::Uint16Array_getIndexed(Assembler* assembler) {
760 Label fall_through;
761 TestByteArrayGetIndex(assembler, &fall_through);
762 // EBX: index as Smi.
763 // EAX: array.
764 __ movzxw(EAX, FieldAddress(EAX,
765 EBX,
766 TIMES_1,
767 Uint16Array::data_offset()));
768 __ SmiTag(EAX);
769 __ ret();
770 __ Bind(&fall_through);
771 return false;
772 }
773
774
775 bool Intrinsifier::Uint16Array_setIndexed(Assembler* assembler) {
776 Label fall_through;
777 TestByteArraySetIndex(assembler, &fall_through);
778 // EBX: index as Smi.
779 // EAX: array.
780 __ movl(EDI, Address(ESP, + 1 * kWordSize));
781 __ SmiUntag(EDI);
782 // EDI: undtagged value.
783 __ testl(EDI, Immediate(kSmiTagMask));
784 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
785 __ movw(FieldAddress(EAX, EBX, TIMES_1, Uint16Array::data_offset()), EDI);
786 __ ret();
787 __ Bind(&fall_through);
788 return false;
789 }
790
791
792 bool Intrinsifier::Uint16Array_new(Assembler* assembler) { 581 bool Intrinsifier::Uint16Array_new(Assembler* assembler) {
793 TYPED_ARRAY_ALLOCATION(Uint16Array, TIMES_2); 582 TYPED_ARRAY_ALLOCATION(Uint16Array, TIMES_2);
794 return false; 583 return false;
795 } 584 }
796 585
797 586
798 bool Intrinsifier::Int32Array_getIndexed(Assembler* assembler) {
799 Label fall_through;
800 TestByteArrayGetIndex(assembler, &fall_through);
801 // EBX: index as Smi.
802 // EAX: array.
803 __ movl(EAX, FieldAddress(EAX,
804 EBX,
805 TIMES_2,
806 Int32Array::data_offset()));
807 // Verify that the signed value in EAX can fit inside a Smi.
808 __ cmpl(EAX, Immediate(0xC0000000));
809 __ j(NEGATIVE, &fall_through, Assembler::kNearJump); // Won't fit Smi.
810 __ SmiTag(EAX);
811 __ ret();
812 __ Bind(&fall_through);
813 return false;
814 }
815
816
817 bool Intrinsifier::Int32Array_new(Assembler* assembler) { 587 bool Intrinsifier::Int32Array_new(Assembler* assembler) {
818 TYPED_ARRAY_ALLOCATION(Int32Array, TIMES_4); 588 TYPED_ARRAY_ALLOCATION(Int32Array, TIMES_4);
819 return false; 589 return false;
820 } 590 }
821 591
822 592
823 bool Intrinsifier::Uint32Array_getIndexed(Assembler* assembler) {
824 Label fall_through;
825 TestByteArrayGetIndex(assembler, &fall_through);
826 // EBX: index as Smi.
827 // EAX: array.
828 __ movl(EAX, FieldAddress(EAX,
829 EBX,
830 TIMES_2,
831 Uint32Array::data_offset()));
832 // Verify that the unsigned value in EAX can be stored in a Smi.
833 __ testl(EAX, Immediate(0xC0000000));
834 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Won't fit Smi.
835 __ SmiTag(EAX);
836 __ ret();
837 __ Bind(&fall_through);
838 return false;
839 }
840
841
842 bool Intrinsifier::Uint32Array_new(Assembler* assembler) { 593 bool Intrinsifier::Uint32Array_new(Assembler* assembler) {
843 TYPED_ARRAY_ALLOCATION(Uint32Array, TIMES_4); 594 TYPED_ARRAY_ALLOCATION(Uint32Array, TIMES_4);
844 return false; 595 return false;
845 } 596 }
846 597
847 598
848 bool Intrinsifier::Int64Array_getIndexed(Assembler* assembler) { 599 bool Intrinsifier::Int64Array_getIndexed(Assembler* assembler) {
849 return false; 600 return false;
850 } 601 }
851 602
852 603
853 bool Intrinsifier::Int64Array_new(Assembler* assembler) { 604 bool Intrinsifier::Int64Array_new(Assembler* assembler) {
854 TYPED_ARRAY_ALLOCATION(Int64Array, TIMES_8); 605 TYPED_ARRAY_ALLOCATION(Int64Array, TIMES_8);
855 return false; 606 return false;
856 } 607 }
857 608
858 609
859 bool Intrinsifier::Uint64Array_getIndexed(Assembler* assembler) { 610 bool Intrinsifier::Uint64Array_getIndexed(Assembler* assembler) {
860 return false; 611 return false;
861 } 612 }
862 613
863 614
864 bool Intrinsifier::Uint64Array_new(Assembler* assembler) { 615 bool Intrinsifier::Uint64Array_new(Assembler* assembler) {
865 TYPED_ARRAY_ALLOCATION(Uint64Array, TIMES_8); 616 TYPED_ARRAY_ALLOCATION(Uint64Array, TIMES_8);
866 return false; 617 return false;
867 } 618 }
868 619
869 620
870 bool Intrinsifier::Float32Array_getIndexed(Assembler* assembler) {
871 Label fall_through;
872 TestByteArrayGetIndex(assembler, &fall_through);
873 // EBX: index as Smi.
874 // EAX: array.
875 // Load single precision float into XMM7.
876 __ movss(XMM7, FieldAddress(EAX, EBX, TIMES_2,
877 Float32Array::data_offset()));
878 // Convert into a double precision float.
879 __ cvtss2sd(XMM7, XMM7);
880 // Allocate a double instance.
881 const Class& double_class = Class::Handle(
882 Isolate::Current()->object_store()->double_class());
883 AssemblerMacros::TryAllocate(assembler,
884 double_class,
885 &fall_through,
886 Assembler::kNearJump, EAX);
887 // Store XMM7 into double instance.
888 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM7);
889 __ ret();
890 __ Bind(&fall_through);
891
892 return false;
893 }
894
895
896 bool Intrinsifier::Float32Array_setIndexed(Assembler* assembler) {
897 Label fall_through;
898 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Value.
899 // If EAX is not an instance of double, jump to fall through.
900 __ testl(EAX, Immediate(kSmiTagMask));
901 __ j(ZERO, &fall_through);
902 __ CompareClassId(EAX, kDoubleCid, EDI);
903 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
904 // Load double value into XMM7.
905 __ movsd(XMM7, FieldAddress(EAX, Double::value_offset()));
906 TestByteArraySetIndex(assembler, &fall_through);
907 // EBX: index as Smi.
908 // EAX: array.
909 // Convert from double precision float to single precision float.
910 __ cvtsd2ss(XMM7, XMM7);
911 // Store into array.
912 __ movss(FieldAddress(EAX, EBX, TIMES_2, Float32Array::data_offset()), XMM7);
913 // End fast path.
914 __ ret();
915 __ Bind(&fall_through);
916 return false;
917 }
918
919
920 bool Intrinsifier::Float32Array_new(Assembler* assembler) { 621 bool Intrinsifier::Float32Array_new(Assembler* assembler) {
921 TYPED_ARRAY_ALLOCATION(Float32Array, TIMES_4); 622 TYPED_ARRAY_ALLOCATION(Float32Array, TIMES_4);
922 return false; 623 return false;
923 } 624 }
924 625
925 626
926 bool Intrinsifier::Float64Array_getIndexed(Assembler* assembler) {
927 Label fall_through;
928 TestByteArrayGetIndex(assembler, &fall_through);
929 // EBX: index as Smi.
930 // EAX: array.
931 // Load double precision float into XMM7.
932 __ movsd(XMM7, FieldAddress(EAX, EBX, TIMES_4,
933 Float64Array::data_offset()));
934 // Allocate a double instance.
935 const Class& double_class = Class::Handle(
936 Isolate::Current()->object_store()->double_class());
937 AssemblerMacros::TryAllocate(assembler,
938 double_class,
939 &fall_through,
940 Assembler::kNearJump, EAX);
941 // Store XMM7 into double instance.
942 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM7);
943 __ ret();
944 __ Bind(&fall_through);
945 return false;
946 }
947
948
949 bool Intrinsifier::Float64Array_setIndexed(Assembler* assembler) {
950 Label fall_through;
951 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Value.
952 // If EAX is not an instance of double, jump to fall through.
953 __ testl(EAX, Immediate(kSmiTagMask));
954 __ j(ZERO, &fall_through, Assembler::kNearJump);
955 __ CompareClassId(EAX, kDoubleCid, EDI);
956 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
957 // Load double value into XMM7.
958 __ movsd(XMM7, FieldAddress(EAX, Double::value_offset()));
959 TestByteArraySetIndex(assembler, &fall_through);
960 // EBX: index as Smi.
961 // EAX: array.
962 __ movsd(FieldAddress(EAX, EBX, TIMES_4, Float64Array::data_offset()), XMM7);
963 __ ret();
964 __ Bind(&fall_through);
965 return false;
966 }
967
968
969 bool Intrinsifier::Float64Array_new(Assembler* assembler) { 627 bool Intrinsifier::Float64Array_new(Assembler* assembler) {
970 TYPED_ARRAY_ALLOCATION(Float64Array, TIMES_8); 628 TYPED_ARRAY_ALLOCATION(Float64Array, TIMES_8);
971 return false; 629 return false;
972 } 630 }
973 631
974 632
975 bool Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) {
976 Label fall_through;
977 TestByteArrayGetIndex(assembler, &fall_through);
978 // EBX: index as Smi.
979 // EAX: array.
980 __ SmiUntag(EBX);
981 __ movl(EAX, FieldAddress(EAX, ExternalUint8Array::data_offset()));
982 __ movzxb(EAX, Address(EAX, EBX, TIMES_1, 0));
983 __ SmiTag(EAX);
984 __ ret();
985 __ Bind(&fall_through);
986 return false;
987 }
988
989
990 bool Intrinsifier::ExternalUint8ClampedArray_getIndexed(Assembler* assembler) {
991 Label fall_through;
992 TestByteArrayGetIndex(assembler, &fall_through);
993 // EBX: index as Smi.
994 // EAX: array.
995 __ SmiUntag(EBX);
996 __ movl(EAX, FieldAddress(EAX, ExternalUint8ClampedArray::data_offset()));
997 __ movzxb(EAX, Address(EAX, EBX, TIMES_1, 0));
998 __ SmiTag(EAX);
999 __ ret();
1000 __ Bind(&fall_through);
1001 return false;
1002 }
1003
1004
1005 bool Intrinsifier::ExternalUint8ClampedArray_setIndexed(Assembler* assembler) {
1006 Label fall_through, store_value, load_0xff;
1007 TestByteArraySetIndex(assembler, &fall_through);
1008 // EBX: index as Smi.
1009 // EAX: array.
1010 __ SmiUntag(EBX);
1011 __ movl(EAX, FieldAddress(EAX, ExternalUint8ClampedArray::data_offset()));
1012 // Free EBX for the value since we need a byte register.
1013 __ leal(EAX, Address(EAX, EBX, TIMES_1, 0));
1014 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Value.
1015 __ testl(EBX, Immediate(kSmiTagMask));
1016 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
1017
1018 __ SmiUntag(EBX);
1019 __ cmpl(EBX, Immediate(0xFF));
1020 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump);
1021 // Clamp to 0x00 or 0xFF respectively.
1022 __ j(GREATER, &load_0xff, Assembler::kNearJump);
1023 __ xorl(EBX, EBX); // Zero.
1024 __ jmp(&store_value, Assembler::kNearJump);
1025 __ Bind(&load_0xff);
1026 __ movl(EBX, Immediate(0xFF));
1027
1028 __ Bind(&store_value);
1029 __ movb(Address(EAX, 0), BL);
1030 __ ret();
1031 __ Bind(&fall_through);
1032 return false;
1033 }
1034
1035
1036 // Tests if two top most arguments are smis, jumps to label not_smi if not. 633 // Tests if two top most arguments are smis, jumps to label not_smi if not.
1037 // Topmost argument is in EAX. 634 // Topmost argument is in EAX.
1038 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) { 635 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
1039 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 636 __ movl(EAX, Address(ESP, + 1 * kWordSize));
1040 __ movl(EBX, Address(ESP, + 2 * kWordSize)); 637 __ movl(EBX, Address(ESP, + 2 * kWordSize));
1041 __ orl(EBX, EAX); 638 __ orl(EBX, EAX);
1042 __ testl(EBX, Immediate(kSmiTagMask)); 639 __ testl(EBX, Immediate(kSmiTagMask));
1043 __ j(NOT_ZERO, not_smi, Assembler::kNearJump); 640 __ j(NOT_ZERO, not_smi, Assembler::kNearJump);
1044 } 641 }
1045 642
(...skipping 825 matching lines...) Expand 10 before | Expand all | Expand 10 after
1871 __ Bind(&is_true); 1468 __ Bind(&is_true);
1872 __ LoadObject(EAX, Bool::True()); 1469 __ LoadObject(EAX, Bool::True());
1873 __ ret(); 1470 __ ret();
1874 return true; 1471 return true;
1875 } 1472 }
1876 1473
1877 #undef __ 1474 #undef __
1878 } // namespace dart 1475 } // namespace dart
1879 1476
1880 #endif // defined TARGET_ARCH_IA32 1477 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_arm.cc ('k') | runtime/vm/intrinsifier_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698