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

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

Issue 10701147: Implement more intrinisification for x64 (not as inlined code but as header of the target). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 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_ia32.cc ('k') | no next file » | 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/globals.h" // Needed here to get TARGET_ARCH_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/intrinsifier.h" 8 #include "vm/intrinsifier.h"
9 9
10 #include "vm/assembler.h" 10 #include "vm/assembler.h"
11 #include "vm/assembler_macros.h"
11 #include "vm/instructions.h" 12 #include "vm/instructions.h"
12 #include "vm/object_store.h" 13 #include "vm/object_store.h"
13 14
14 namespace dart { 15 namespace dart {
15 16
16 DECLARE_FLAG(bool, enable_type_checks); 17 DECLARE_FLAG(bool, enable_type_checks);
17 18
18 // When entering intrinsics code: 19 // When entering intrinsics code:
19 // RBX: IC Data 20 // RBX: IC Data
20 // R10: Arguments descriptor 21 // R10: Arguments descriptor
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) { 479 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
479 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 480 __ movq(RAX, Address(RSP, + 1 * kWordSize));
480 __ movq(RCX, Address(RSP, + 2 * kWordSize)); 481 __ movq(RCX, Address(RSP, + 2 * kWordSize));
481 __ orq(RCX, RAX); 482 __ orq(RCX, RAX);
482 __ testq(RCX, Immediate(kSmiTagMask)); 483 __ testq(RCX, Immediate(kSmiTagMask));
483 __ j(NOT_ZERO, not_smi, Assembler::kNearJump); 484 __ j(NOT_ZERO, not_smi, Assembler::kNearJump);
484 } 485 }
485 486
486 487
487 bool Intrinsifier::Integer_addFromInteger(Assembler* assembler) { 488 bool Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
489 Label fall_through;
490 TestBothArgumentsSmis(assembler, &fall_through);
491 // RAX contains right argument.
492 __ movq(RCX, Address(RSP, + 2 * kWordSize));
493 __ addq(RAX, RCX);
494 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
495 // Result is in RAX.
496 __ ret();
497 __ Bind(&fall_through);
488 return false; 498 return false;
489 } 499 }
490 500
491 501
492 bool Intrinsifier::Integer_add(Assembler* assembler) { 502 bool Intrinsifier::Integer_add(Assembler* assembler) {
493 return false; 503 return Integer_addFromInteger(assembler);
494 } 504 }
495 505
496 506
497 bool Intrinsifier::Integer_subFromInteger(Assembler* assembler) { 507 bool Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
498 Label fall_through; 508 Label fall_through;
499 TestBothArgumentsSmis(assembler, &fall_through); 509 TestBothArgumentsSmis(assembler, &fall_through);
500 // RAX contains right argument, which is the actual minuend of subtraction. 510 // RAX contains right argument, which is the actual minuend of subtraction.
501 __ subq(RAX, Address(RSP, + 2 * kWordSize)); 511 __ subq(RAX, Address(RSP, + 2 * kWordSize));
502 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 512 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
503 // Result is in RAX. 513 // Result is in RAX.
504 __ ret(); 514 __ ret();
505 __ Bind(&fall_through); 515 __ Bind(&fall_through);
506 return false; 516 return false;
507 } 517 }
508 518
509 519
510 bool Intrinsifier::Integer_sub(Assembler* assembler) { 520 bool Intrinsifier::Integer_sub(Assembler* assembler) {
521 Label fall_through;
522 TestBothArgumentsSmis(assembler, &fall_through);
523 // RAX contains right argument, which is the actual subtrahend of subtraction.
524 __ movq(RCX, RAX);
525 __ movq(RAX, Address(RSP, + 2 * kWordSize));
526 __ subq(RAX, RCX);
527 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
528 // Result is in RAX.
529 __ ret();
530 __ Bind(&fall_through);
511 return false; 531 return false;
512 } 532 }
513 533
514 534
515 535
516 bool Intrinsifier::Integer_mulFromInteger(Assembler* assembler) { 536 bool Intrinsifier::Integer_mulFromInteger(Assembler* assembler) {
537 Label fall_through;
538 TestBothArgumentsSmis(assembler, &fall_through);
539 // RAX is the right argument.
540 ASSERT(kSmiTag == 0); // Adjust code below if not the case.
541 __ SmiUntag(RAX);
542 __ movq(RCX, Address(RSP, + 2 * kWordSize));
543 __ imulq(RAX, RCX);
544 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
545 // Result is in RAX.
546 __ ret();
547 __ Bind(&fall_through);
517 return false; 548 return false;
518 } 549 }
519 550
520 551
521 bool Intrinsifier::Integer_mul(Assembler* assembler) { 552 bool Intrinsifier::Integer_mul(Assembler* assembler) {
522 return false; 553 return Integer_mulFromInteger(assembler);
523 } 554 }
524 555
525 556
526 bool Intrinsifier::Integer_modulo(Assembler* assembler) { 557 bool Intrinsifier::Integer_modulo(Assembler* assembler) {
527 Label fall_through, return_zero, try_modulo; 558 Label fall_through, return_zero, try_modulo;
528 TestBothArgumentsSmis(assembler, &fall_through); 559 TestBothArgumentsSmis(assembler, &fall_through);
529 // RAX: right argument (divisor) 560 // RAX: right argument (divisor)
530 // Check if modulo by zero -> exception thrown in main function. 561 // Check if modulo by zero -> exception thrown in main function.
531 __ cmpq(RAX, Immediate(0)); 562 __ cmpq(RAX, Immediate(0));
532 __ j(EQUAL, &fall_through, Assembler::kNearJump); 563 __ j(EQUAL, &fall_through, Assembler::kNearJump);
(...skipping 18 matching lines...) Expand all
551 __ idivq(RCX); 582 __ idivq(RCX);
552 __ movq(RAX, RDX); 583 __ movq(RAX, RDX);
553 __ SmiTag(RAX); 584 __ SmiTag(RAX);
554 __ ret(); 585 __ ret();
555 __ Bind(&fall_through); 586 __ Bind(&fall_through);
556 return false; 587 return false;
557 } 588 }
558 589
559 590
560 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) { 591 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) {
592 Label fall_through;
593 TestBothArgumentsSmis(assembler, &fall_through);
594 // RAX: right argument (divisor)
595 __ cmpq(RAX, Immediate(0));
596 __ j(EQUAL, &fall_through, Assembler::kNearJump);
597 __ movq(RCX, RAX);
598 __ SmiUntag(RCX);
599 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument (dividend).
600 __ SmiUntag(RAX);
601 __ pushq(RDX); // Preserve RDX in case of 'fall_through'.
602 __ cqo();
603 __ idivq(RCX);
604 __ popq(RDX);
605 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
606 // cannot tag the result.
607 __ cmpq(RAX, Immediate(0x4000000000000000));
608 __ j(EQUAL, &fall_through);
609 __ SmiTag(RAX);
610 __ ret();
611 __ Bind(&fall_through);
561 return false; 612 return false;
562 } 613 }
563 614
564 615
565 bool Intrinsifier::Integer_negate(Assembler* assembler) { 616 bool Intrinsifier::Integer_negate(Assembler* assembler) {
617 Label fall_through;
618 __ movq(RAX, Address(RSP, + 1 * kWordSize));
619 __ testq(RAX, Immediate(kSmiTagMask));
620 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi value.
621 __ negq(RAX);
622 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
623 // Result is in RAX.
624 __ ret();
625 __ Bind(&fall_through);
566 return false; 626 return false;
567 } 627 }
568 628
569 629
570 bool Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) { 630 bool Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
631 Label fall_through;
632 TestBothArgumentsSmis(assembler, &fall_through);
633 // RAX is the right argument.
634 __ movq(RCX, Address(RSP, + 2 * kWordSize));
635 __ andq(RAX, RCX);
636 // Result is in RAX.
637 __ ret();
638 __ Bind(&fall_through);
571 return false; 639 return false;
572 } 640 }
573 641
574 642
575 bool Intrinsifier::Integer_bitAnd(Assembler* assembler) { 643 bool Intrinsifier::Integer_bitAnd(Assembler* assembler) {
576 return false; 644 return Integer_bitAndFromInteger(assembler);
577 } 645 }
578 646
579 647
580 bool Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) { 648 bool Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) {
649 Label fall_through;
650 TestBothArgumentsSmis(assembler, &fall_through);
651 // RAX is the right argument.
652 __ movq(RCX, Address(RSP, + 2 * kWordSize));
653 __ orq(RAX, RCX);
654 // Result is in RAX.
655 __ ret();
656 __ Bind(&fall_through);
581 return false; 657 return false;
582 } 658 }
583 659
584 660
585 bool Intrinsifier::Integer_bitOr(Assembler* assembler) { 661 bool Intrinsifier::Integer_bitOr(Assembler* assembler) {
586 return false; 662 return Integer_bitOrFromInteger(assembler);
587 } 663 }
588 664
589 665
590 bool Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) { 666 bool Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) {
667 Label fall_through;
668 TestBothArgumentsSmis(assembler, &fall_through);
669 // RAX is the right argument.
670 __ movq(RCX, Address(RSP, + 2 * kWordSize));
671 __ xorq(RAX, RCX);
672 // Result is in RAX.
673 __ ret();
674 __ Bind(&fall_through);
591 return false; 675 return false;
592 } 676 }
593 677
594 678
595 bool Intrinsifier::Integer_bitXor(Assembler* assembler) { 679 bool Intrinsifier::Integer_bitXor(Assembler* assembler) {
596 return false; 680 return Integer_bitXorFromInteger(assembler);
597 } 681 }
598 682
599 683
600 bool Intrinsifier::Integer_shl(Assembler* assembler) { 684 bool Intrinsifier::Integer_shl(Assembler* assembler) {
601 return false; 685 return false;
602 } 686 }
603 687
604 688
605 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { 689 static bool CompareIntegers(Assembler* assembler, Condition true_condition) {
606 Label fall_through, true_label; 690 Label fall_through, true_label;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 return CompareIntegers(assembler, GREATER_EQUAL); 729 return CompareIntegers(assembler, GREATER_EQUAL);
646 } 730 }
647 731
648 732
649 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) { 733 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
650 return false; 734 return false;
651 } 735 }
652 736
653 737
654 bool Intrinsifier::Integer_equal(Assembler* assembler) { 738 bool Intrinsifier::Integer_equal(Assembler* assembler) {
655 return false; 739 return Integer_equalToInteger(assembler);
656 } 740 }
657 741
658 742
659 bool Intrinsifier::Integer_sar(Assembler* assembler) { 743 bool Intrinsifier::Integer_sar(Assembler* assembler) {
660 return false; 744 return false;
661 } 745 }
662 746
663 747
664 bool Intrinsifier::Smi_bitNegate(Assembler* assembler) { 748 bool Intrinsifier::Smi_bitNegate(Assembler* assembler) {
665 return false; 749 return false;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 __ LoadObject(RAX, bool_false); 825 __ LoadObject(RAX, bool_false);
742 __ ret(); 826 __ ret();
743 __ Bind(&is_true); 827 __ Bind(&is_true);
744 __ LoadObject(RAX, bool_true); 828 __ LoadObject(RAX, bool_true);
745 __ ret(); 829 __ ret();
746 return true; // Method is complete, no slow case. 830 return true; // Method is complete, no slow case.
747 } 831 }
748 832
749 833
750 bool Intrinsifier::Double_isNegative(Assembler* assembler) { 834 bool Intrinsifier::Double_isNegative(Assembler* assembler) {
751 return false; 835 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
836 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
837 Label is_false, is_true, is_zero;
838 __ movq(RAX, Address(RSP, +1 * kWordSize));
839 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
840 __ xorpd(XMM1, XMM1); // 0.0 -> XMM1.
841 __ comisd(XMM0, XMM1);
842 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false.
843 __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero.
844 __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false.
845 __ Bind(&is_true);
846 __ LoadObject(RAX, bool_true);
847 __ ret();
848 __ Bind(&is_false);
849 __ LoadObject(RAX, bool_false);
850 __ ret();
851 __ Bind(&is_zero);
852 // Check for negative zero (get the sign bit).
853 __ movmskpd(RAX, XMM0);
854 __ testq(RAX, Immediate(1));
855 __ j(NOT_ZERO, &is_true, Assembler::kNearJump);
856 __ jmp(&is_false, Assembler::kNearJump);
857 return true; // Method is complete, no slow case.
858 }
859
860
861 // Check if the last argument is a double, jump to label 'is_smi' if smi
862 // (easy to convert to double), otherwise jump to label 'not_double_smi',
863 // Returns the last argument in RAX.
864 static void TestLastArgumentIsDouble(Assembler* assembler,
865 Label* is_smi,
866 Label* not_double_smi) {
867 __ movq(RAX, Address(RSP, + 1 * kWordSize));
868 __ testq(RAX, Immediate(kSmiTagMask));
869 __ j(ZERO, is_smi, Assembler::kNearJump); // Jump if Smi.
870 __ CompareClassId(RAX, kDouble);
871 __ j(NOT_EQUAL, not_double_smi, Assembler::kNearJump);
872 // Fall through if double.
873 }
874
875
876 enum TrigonometricFunctions {
877 kSine,
878 kCosine,
879 };
880
881 static void EmitTrigonometric(Assembler* assembler,
882 TrigonometricFunctions kind) {
883 Label fall_through, is_smi, double_op;
884 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
885 // Argument is double and is in EAX.
886 __ fldl(FieldAddress(RAX, Double::value_offset()));
887 __ Bind(&double_op);
888 switch (kind) {
889 case kSine: __ fsin(); break;
890 case kCosine: __ fcos(); break;
891 default:
892 UNREACHABLE();
893 }
894 const Class& double_class = Class::Handle(
895 Isolate::Current()->object_store()->double_class());
896 Label alloc_failed;
897 AssemblerMacros::TryAllocate(assembler,
898 double_class,
899 &alloc_failed,
900 RAX); // Result register.
901 __ fstpl(FieldAddress(RAX, Double::value_offset()));
902 __ ret();
903
904 __ Bind(&is_smi); // smi -> double.
905 __ SmiUntag(RAX);
906 __ pushq(RAX);
907 __ fildl(Address(RSP, 0));
908 __ popq(RAX);
909 __ jmp(&double_op);
910
911 __ Bind(&alloc_failed);
912 __ ffree(0);
913 __ fincstp();
914
915 __ Bind(&fall_through);
752 } 916 }
753 917
754 918
755 bool Intrinsifier::Math_sqrt(Assembler* assembler) { 919 bool Intrinsifier::Math_sqrt(Assembler* assembler) {
920 Label fall_through, is_smi, double_op;
921 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
922 // Argument is double and is in RAX.
923 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset()));
924 __ Bind(&double_op);
925 __ sqrtsd(XMM0, XMM1);
926 const Class& double_class = Class::Handle(
927 Isolate::Current()->object_store()->double_class());
928 AssemblerMacros::TryAllocate(assembler,
929 double_class,
930 &fall_through,
931 RAX); // Result register.
932 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
933 __ ret();
934 __ Bind(&is_smi);
935 __ SmiUntag(RAX);
936 __ cvtsi2sd(XMM1, RAX);
937 __ jmp(&double_op);
938 __ Bind(&fall_through);
756 return false; 939 return false;
757 } 940 }
758 941
759 942
760 bool Intrinsifier::Math_sin(Assembler* assembler) { 943 bool Intrinsifier::Math_sin(Assembler* assembler) {
761 return false; 944 EmitTrigonometric(assembler, kSine);
945 return false; // Compile method for slow case.
762 } 946 }
763 947
764 948
765 bool Intrinsifier::Math_cos(Assembler* assembler) { 949 bool Intrinsifier::Math_cos(Assembler* assembler) {
766 return false; 950 EmitTrigonometric(assembler, kCosine);
767 } 951 return false; // Compile method for slow case.
768 952 }
769 953
954
955 // Identity comparison.
770 bool Intrinsifier::Object_equal(Assembler* assembler) { 956 bool Intrinsifier::Object_equal(Assembler* assembler) {
771 return false; 957 Label is_true;
772 } 958 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
773 959 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
774 960 __ movq(RAX, Address(RSP, + 1 * kWordSize));
961 __ cmpq(RAX, Address(RSP, + 2 * kWordSize));
962 __ j(EQUAL, &is_true, Assembler::kNearJump);
963 __ LoadObject(RAX, bool_false);
964 __ ret();
965 __ Bind(&is_true);
966 __ LoadObject(RAX, bool_true);
967 __ ret();
968 return true;
969 }
970
971
972 static intptr_t GetOffsetForField(const char* class_name_p,
973 const char* field_name_p) {
974 const String& class_name = String::Handle(String::NewSymbol(class_name_p));
975 const String& field_name = String::Handle(String::NewSymbol(field_name_p));
976 const Class& cls = Class::Handle(Library::Handle(
977 Library::CoreImplLibrary()).LookupClass(class_name));
978 ASSERT(!cls.IsNull());
979 const Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name));
980 ASSERT(!field.IsNull());
981 return field.Offset();
982 }
983
984 static const char* kFixedSizeArrayIteratorClassName = "FixedSizeArrayIterator";
985
986 // Class 'FixedSizeArrayIterator':
987 // T next() {
988 // return _array[_pos++];
989 // }
990 // Intrinsify: return _array[_pos++];
991 // TODO(srdjan): Throw a 'NoMoreElementsException' exception if the iterator
992 // has no more elements.
775 bool Intrinsifier::FixedSizeArrayIterator_next(Assembler* assembler) { 993 bool Intrinsifier::FixedSizeArrayIterator_next(Assembler* assembler) {
776 return false; 994 Label fall_through;
777 } 995 const intptr_t array_offset =
778 996 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_array");
779 997 const intptr_t pos_offset =
998 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_pos");
999 ASSERT((array_offset >= 0) && (pos_offset >= 0));
1000 // Receiver is not NULL.
1001 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Receiver.
1002 __ movq(RCX, FieldAddress(RAX, pos_offset)); // Field _pos.
1003 // '_pos' cannot be greater than array length and therefore is always Smi.
1004 #if defined(DEBUG)
1005 Label pos_ok;
1006 __ testq(RCX, Immediate(kSmiTagMask));
1007 __ j(ZERO, &pos_ok, Assembler::kNearJump);
1008 __ Stop("pos must be Smi");
1009 __ Bind(&pos_ok);
1010 #endif
1011 // Check that we are not trying to call 'next' when 'hasNext' is false.
1012 __ movq(RAX, FieldAddress(RAX, array_offset)); // Field _array.
1013 __ cmpq(RCX, FieldAddress(RAX, Array::length_offset())); // Range check.
1014 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
1015
1016 // RCX is Smi, i.e, times 2.
1017 ASSERT(kSmiTagShift == 1);
1018 __ movq(RDI, FieldAddress(RAX, RCX, TIMES_4, sizeof(RawArray))); // Result.
1019 const Immediate value = Immediate(reinterpret_cast<int64_t>(Smi::New(1)));
1020 __ addq(RCX, value); // _pos++.
1021 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
1022 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Receiver.
1023 __ StoreIntoObjectNoBarrier(RAX,
1024 FieldAddress(RAX, pos_offset),
1025 RCX); // Store _pos.
1026 __ movq(RAX, RDI);
1027 __ ret();
1028 __ Bind(&fall_through);
1029 return false;
1030 }
1031
1032
1033 // Class 'FixedSizeArrayIterator':
1034 // bool hasNext() {
1035 // return _length > _pos;
1036 // }
780 bool Intrinsifier::FixedSizeArrayIterator_hasNext(Assembler* assembler) { 1037 bool Intrinsifier::FixedSizeArrayIterator_hasNext(Assembler* assembler) {
1038 Label fall_through, is_true;
1039 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1040 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1041 const intptr_t length_offset =
1042 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_length");
1043 const intptr_t pos_offset =
1044 GetOffsetForField(kFixedSizeArrayIteratorClassName, "_pos");
1045 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Receiver.
1046 __ movq(RCX, FieldAddress(RAX, length_offset)); // Field _length.
1047 __ movq(RAX, FieldAddress(RAX, pos_offset)); // Field _pos.
1048 __ movq(RDI, RAX);
1049 __ orq(RDI, RCX);
1050 __ testq(RDI, Immediate(kSmiTagMask));
1051 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi _length/_pos.
1052 __ cmpq(RCX, RAX); // _length > _pos.
1053 __ j(GREATER, &is_true, Assembler::kNearJump);
1054 __ LoadObject(RAX, bool_false);
1055 __ ret();
1056 __ Bind(&is_true);
1057 __ LoadObject(RAX, bool_true);
1058 __ ret();
1059 __ Bind(&fall_through);
781 return false; 1060 return false;
782 } 1061 }
783 1062
784 1063
785 bool Intrinsifier::String_getLength(Assembler* assembler) { 1064 bool Intrinsifier::String_getLength(Assembler* assembler) {
786 return false; 1065 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object.
787 } 1066 __ movq(RAX, FieldAddress(RAX, String::length_offset()));
788 1067 __ ret();
789 1068 return true;
1069 }
1070
1071
1072 // TODO(srdjan): Implement for two and four byte strings as well.
790 bool Intrinsifier::String_charCodeAt(Assembler* assembler) { 1073 bool Intrinsifier::String_charCodeAt(Assembler* assembler) {
1074 Label fall_through;
1075 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index.
1076 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // String.
1077 __ testq(RCX, Immediate(kSmiTagMask));
1078 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index.
1079 // Range check.
1080 __ cmpq(RCX, FieldAddress(RAX, String::length_offset()));
1081 // Runtime throws exception.
1082 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
1083 __ CompareClassId(RAX, kOneByteString);
1084 __ j(NOT_EQUAL, &fall_through);
1085 __ SmiUntag(RCX);
1086 __ movzxb(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset()));
1087 __ SmiTag(RAX);
1088 __ ret();
1089 __ Bind(&fall_through);
791 return false; 1090 return false;
792 } 1091 }
793 1092
794 1093
795 bool Intrinsifier::String_hashCode(Assembler* assembler) { 1094 bool Intrinsifier::String_hashCode(Assembler* assembler) {
1095 Label fall_through;
1096 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object.
1097 __ movq(RAX, FieldAddress(RAX, String::hash_offset()));
1098 __ cmpq(RAX, Immediate(0));
1099 __ j(EQUAL, &fall_through, Assembler::kNearJump);
1100 __ ret();
1101 __ Bind(&fall_through);
1102 // Hash not yet computed.
796 return false; 1103 return false;
797 } 1104 }
798 1105
799 1106
800 bool Intrinsifier::String_isEmpty(Assembler* assembler) { 1107 bool Intrinsifier::String_isEmpty(Assembler* assembler) {
801 return false; 1108 Label is_true;
1109 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1110 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1111 // Get length.
1112 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object.
1113 __ movq(RAX, FieldAddress(RAX, String::length_offset()));
1114 __ cmpq(RAX, Immediate(Smi::RawValue(0)));
1115 __ j(EQUAL, &is_true, Assembler::kNearJump);
1116 __ LoadObject(RAX, bool_false);
1117 __ ret();
1118 __ Bind(&is_true);
1119 __ LoadObject(RAX, bool_true);
1120 __ ret();
1121 return true;
802 } 1122 }
803 1123
804 #undef __ 1124 #undef __
805 1125
806 } // namespace dart 1126 } // namespace dart
807 1127
808 #endif // defined TARGET_ARCH_X64 1128 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698