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

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

Issue 285403004: Adds intrinsics for arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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_arm64.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 19 matching lines...) Expand all
30 30
31 31
32 void Intrinsifier::Array_getLength(Assembler* assembler) { 32 void Intrinsifier::Array_getLength(Assembler* assembler) {
33 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 33 __ movl(EAX, Address(ESP, + 1 * kWordSize));
34 __ movl(EAX, FieldAddress(EAX, Array::length_offset())); 34 __ movl(EAX, FieldAddress(EAX, Array::length_offset()));
35 __ ret(); 35 __ ret();
36 } 36 }
37 37
38 38
39 void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { 39 void Intrinsifier::ImmutableList_getLength(Assembler* assembler) {
40 return Array_getLength(assembler); 40 Array_getLength(assembler);
41 } 41 }
42 42
43 43
44 void Intrinsifier::Array_getIndexed(Assembler* assembler) { 44 void Intrinsifier::Array_getIndexed(Assembler* assembler) {
45 Label fall_through; 45 Label fall_through;
46 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. 46 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index.
47 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. 47 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array.
48 __ testl(EBX, Immediate(kSmiTagMask)); 48 __ testl(EBX, Immediate(kSmiTagMask));
49 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. 49 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index.
50 // Range check. 50 // Range check.
51 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset())); 51 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset()));
52 // Runtime throws exception. 52 // Runtime throws exception.
53 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); 53 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
54 // Note that EBX is Smi, i.e, times 2. 54 // Note that EBX is Smi, i.e, times 2.
55 ASSERT(kSmiTagShift == 1); 55 ASSERT(kSmiTagShift == 1);
56 __ movl(EAX, FieldAddress(EAX, EBX, TIMES_2, Array::data_offset())); 56 __ movl(EAX, FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()));
57 __ ret(); 57 __ ret();
58 __ Bind(&fall_through); 58 __ Bind(&fall_through);
59 } 59 }
60 60
61 61
62 void Intrinsifier::ImmutableList_getIndexed(Assembler* assembler) { 62 void Intrinsifier::ImmutableList_getIndexed(Assembler* assembler) {
63 return Array_getIndexed(assembler); 63 Array_getIndexed(assembler);
64 } 64 }
65 65
66 66
67 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { 67 static intptr_t ComputeObjectArrayTypeArgumentsOffset() {
68 const Library& core_lib = Library::Handle(Library::CoreLibrary()); 68 const Library& core_lib = Library::Handle(Library::CoreLibrary());
69 const Class& cls = Class::Handle( 69 const Class& cls = Class::Handle(
70 core_lib.LookupClassAllowPrivate(Symbols::_List())); 70 core_lib.LookupClassAllowPrivate(Symbols::_List()));
71 ASSERT(!cls.IsNull()); 71 ASSERT(!cls.IsNull());
72 ASSERT(cls.NumTypeArguments() == 1); 72 ASSERT(cls.NumTypeArguments() == 1);
73 const intptr_t field_offset = cls.type_arguments_field_offset(); 73 const intptr_t field_offset = cls.type_arguments_field_offset();
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 TestBothArgumentsSmis(assembler, &fall_through); 488 TestBothArgumentsSmis(assembler, &fall_through);
489 __ addl(EAX, Address(ESP, + 2 * kWordSize)); 489 __ addl(EAX, Address(ESP, + 2 * kWordSize));
490 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 490 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
491 // Result is in EAX. 491 // Result is in EAX.
492 __ ret(); 492 __ ret();
493 __ Bind(&fall_through); 493 __ Bind(&fall_through);
494 } 494 }
495 495
496 496
497 void Intrinsifier::Integer_add(Assembler* assembler) { 497 void Intrinsifier::Integer_add(Assembler* assembler) {
498 return Integer_addFromInteger(assembler); 498 Integer_addFromInteger(assembler);
499 } 499 }
500 500
501 501
502 void Intrinsifier::Integer_subFromInteger(Assembler* assembler) { 502 void Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
503 Label fall_through; 503 Label fall_through;
504 TestBothArgumentsSmis(assembler, &fall_through); 504 TestBothArgumentsSmis(assembler, &fall_through);
505 __ subl(EAX, Address(ESP, + 2 * kWordSize)); 505 __ subl(EAX, Address(ESP, + 2 * kWordSize));
506 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 506 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
507 // Result is in EAX. 507 // Result is in EAX.
508 __ ret(); 508 __ ret();
(...skipping 22 matching lines...) Expand all
531 __ SmiUntag(EAX); 531 __ SmiUntag(EAX);
532 __ imull(EAX, Address(ESP, + 2 * kWordSize)); 532 __ imull(EAX, Address(ESP, + 2 * kWordSize));
533 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 533 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
534 // Result is in EAX. 534 // Result is in EAX.
535 __ ret(); 535 __ ret();
536 __ Bind(&fall_through); 536 __ Bind(&fall_through);
537 } 537 }
538 538
539 539
540 void Intrinsifier::Integer_mul(Assembler* assembler) { 540 void Intrinsifier::Integer_mul(Assembler* assembler) {
541 return Integer_mulFromInteger(assembler); 541 Integer_mulFromInteger(assembler);
542 } 542 }
543 543
544 544
545 // Optimizations: 545 // Optimizations:
546 // - result is 0 if: 546 // - result is 0 if:
547 // - left is 0 547 // - left is 0
548 // - left equals right 548 // - left equals right
549 // - result is left if 549 // - result is left if
550 // - left > 0 && left < right 550 // - left > 0 && left < right
551 // EAX: Tagged left (dividend). 551 // EAX: Tagged left (dividend).
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 TestBothArgumentsSmis(assembler, &fall_through); 665 TestBothArgumentsSmis(assembler, &fall_through);
666 __ movl(EBX, Address(ESP, + 2 * kWordSize)); 666 __ movl(EBX, Address(ESP, + 2 * kWordSize));
667 __ andl(EAX, EBX); 667 __ andl(EAX, EBX);
668 // Result is in EAX. 668 // Result is in EAX.
669 __ ret(); 669 __ ret();
670 __ Bind(&fall_through); 670 __ Bind(&fall_through);
671 } 671 }
672 672
673 673
674 void Intrinsifier::Integer_bitAnd(Assembler* assembler) { 674 void Intrinsifier::Integer_bitAnd(Assembler* assembler) {
675 return Integer_bitAndFromInteger(assembler); 675 Integer_bitAndFromInteger(assembler);
676 } 676 }
677 677
678 678
679 void Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) { 679 void Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) {
680 Label fall_through; 680 Label fall_through;
681 TestBothArgumentsSmis(assembler, &fall_through); 681 TestBothArgumentsSmis(assembler, &fall_through);
682 __ movl(EBX, Address(ESP, + 2 * kWordSize)); 682 __ movl(EBX, Address(ESP, + 2 * kWordSize));
683 __ orl(EAX, EBX); 683 __ orl(EAX, EBX);
684 // Result is in EAX. 684 // Result is in EAX.
685 __ ret(); 685 __ ret();
686 __ Bind(&fall_through); 686 __ Bind(&fall_through);
687 } 687 }
688 688
689 689
690 void Intrinsifier::Integer_bitOr(Assembler* assembler) { 690 void Intrinsifier::Integer_bitOr(Assembler* assembler) {
691 return Integer_bitOrFromInteger(assembler); 691 Integer_bitOrFromInteger(assembler);
692 } 692 }
693 693
694 694
695 void Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) { 695 void Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) {
696 Label fall_through; 696 Label fall_through;
697 TestBothArgumentsSmis(assembler, &fall_through); 697 TestBothArgumentsSmis(assembler, &fall_through);
698 __ movl(EBX, Address(ESP, + 2 * kWordSize)); 698 __ movl(EBX, Address(ESP, + 2 * kWordSize));
699 __ xorl(EAX, EBX); 699 __ xorl(EAX, EBX);
700 // Result is in EAX. 700 // Result is in EAX.
701 __ ret(); 701 __ ret();
702 __ Bind(&fall_through); 702 __ Bind(&fall_through);
703 } 703 }
704 704
705 705
706 void Intrinsifier::Integer_bitXor(Assembler* assembler) { 706 void Intrinsifier::Integer_bitXor(Assembler* assembler) {
707 return Integer_bitXorFromInteger(assembler); 707 Integer_bitXorFromInteger(assembler);
708 } 708 }
709 709
710 710
711 void Intrinsifier::Integer_shl(Assembler* assembler) { 711 void Intrinsifier::Integer_shl(Assembler* assembler) {
712 ASSERT(kSmiTagShift == 1); 712 ASSERT(kSmiTagShift == 1);
713 ASSERT(kSmiTag == 0); 713 ASSERT(kSmiTag == 0);
714 Label fall_through, overflow; 714 Label fall_through, overflow;
715 TestBothArgumentsSmis(assembler, &fall_through); 715 TestBothArgumentsSmis(assembler, &fall_through);
716 // Shift value is in EAX. Compare with tagged Smi. 716 // Shift value is in EAX. Compare with tagged Smi.
717 __ cmpl(EAX, Immediate(Smi::RawValue(Smi::kBits))); 717 __ cmpl(EAX, Immediate(Smi::RawValue(Smi::kBits)));
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
837 __ jmp(&is_true); 837 __ jmp(&is_true);
838 838
839 __ Bind(&drop_two_fall_through); 839 __ Bind(&drop_two_fall_through);
840 __ Drop(2); 840 __ Drop(2);
841 __ Bind(&fall_through); 841 __ Bind(&fall_through);
842 } 842 }
843 843
844 844
845 845
846 void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) { 846 void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) {
847 return CompareIntegers(assembler, LESS); 847 CompareIntegers(assembler, LESS);
848 } 848 }
849 849
850 850
851 void Intrinsifier::Integer_lessThan(Assembler* assembler) { 851 void Intrinsifier::Integer_lessThan(Assembler* assembler) {
852 return Integer_greaterThanFromInt(assembler); 852 Integer_greaterThanFromInt(assembler);
853 } 853 }
854 854
855 855
856 void Intrinsifier::Integer_greaterThan(Assembler* assembler) { 856 void Intrinsifier::Integer_greaterThan(Assembler* assembler) {
857 return CompareIntegers(assembler, GREATER); 857 CompareIntegers(assembler, GREATER);
858 } 858 }
859 859
860 860
861 void Intrinsifier::Integer_lessEqualThan(Assembler* assembler) { 861 void Intrinsifier::Integer_lessEqualThan(Assembler* assembler) {
862 return CompareIntegers(assembler, LESS_EQUAL); 862 CompareIntegers(assembler, LESS_EQUAL);
863 } 863 }
864 864
865 865
866 void Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) { 866 void Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) {
867 return CompareIntegers(assembler, GREATER_EQUAL); 867 CompareIntegers(assembler, GREATER_EQUAL);
868 } 868 }
869 869
870 870
871 // This is called for Smi, Mint and Bigint receivers. The right argument 871 // This is called for Smi, Mint and Bigint receivers. The right argument
872 // can be Smi, Mint, Bigint or double. 872 // can be Smi, Mint, Bigint or double.
873 void Intrinsifier::Integer_equalToInteger(Assembler* assembler) { 873 void Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
874 Label fall_through, true_label, check_for_mint; 874 Label fall_through, true_label, check_for_mint;
875 // For integer receiver '===' check first. 875 // For integer receiver '===' check first.
876 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 876 __ movl(EAX, Address(ESP, + 1 * kWordSize));
877 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); 877 __ cmpl(EAX, Address(ESP, + 2 * kWordSize));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 __ j(NOT_ZERO, &fall_through); 913 __ j(NOT_ZERO, &fall_through);
914 __ LoadObject(EAX, Bool::False()); 914 __ LoadObject(EAX, Bool::False());
915 __ ret(); 915 __ ret();
916 // TODO(srdjan): Implement Mint == Mint comparison. 916 // TODO(srdjan): Implement Mint == Mint comparison.
917 917
918 __ Bind(&fall_through); 918 __ Bind(&fall_through);
919 } 919 }
920 920
921 921
922 void Intrinsifier::Integer_equal(Assembler* assembler) { 922 void Intrinsifier::Integer_equal(Assembler* assembler) {
923 return Integer_equalToInteger(assembler); 923 Integer_equalToInteger(assembler);
924 } 924 }
925 925
926 926
927 void Intrinsifier::Integer_sar(Assembler* assembler) { 927 void Intrinsifier::Integer_sar(Assembler* assembler) {
928 Label fall_through, shift_count_ok; 928 Label fall_through, shift_count_ok;
929 TestBothArgumentsSmis(assembler, &fall_through); 929 TestBothArgumentsSmis(assembler, &fall_through);
930 // Can destroy ECX since we are not falling through. 930 // Can destroy ECX since we are not falling through.
931 const Immediate& count_limit = Immediate(0x1F); 931 const Immediate& count_limit = Immediate(0x1F);
932 // Check that the count is not larger than what the hardware can handle. 932 // Check that the count is not larger than what the hardware can handle.
933 // For shifting right a Smi the result is the same for all numbers 933 // For shifting right a Smi the result is the same for all numbers
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 __ Bind(&is_smi); 1015 __ Bind(&is_smi);
1016 __ SmiUntag(EAX); 1016 __ SmiUntag(EAX);
1017 __ cvtsi2sd(XMM1, EAX); 1017 __ cvtsi2sd(XMM1, EAX);
1018 __ jmp(&double_op); 1018 __ jmp(&double_op);
1019 __ Bind(&fall_through); 1019 __ Bind(&fall_through);
1020 } 1020 }
1021 1021
1022 1022
1023 // arg0 is Double, arg1 is unknown. 1023 // arg0 is Double, arg1 is unknown.
1024 void Intrinsifier::Double_greaterThan(Assembler* assembler) { 1024 void Intrinsifier::Double_greaterThan(Assembler* assembler) {
1025 return CompareDoubles(assembler, ABOVE); 1025 CompareDoubles(assembler, ABOVE);
1026 } 1026 }
1027 1027
1028 1028
1029 // arg0 is Double, arg1 is unknown. 1029 // arg0 is Double, arg1 is unknown.
1030 void Intrinsifier::Double_greaterEqualThan(Assembler* assembler) { 1030 void Intrinsifier::Double_greaterEqualThan(Assembler* assembler) {
1031 return CompareDoubles(assembler, ABOVE_EQUAL); 1031 CompareDoubles(assembler, ABOVE_EQUAL);
1032 } 1032 }
1033 1033
1034 1034
1035 // arg0 is Double, arg1 is unknown. 1035 // arg0 is Double, arg1 is unknown.
1036 void Intrinsifier::Double_lessThan(Assembler* assembler) { 1036 void Intrinsifier::Double_lessThan(Assembler* assembler) {
1037 return CompareDoubles(assembler, BELOW); 1037 CompareDoubles(assembler, BELOW);
1038 } 1038 }
1039 1039
1040 1040
1041 // arg0 is Double, arg1 is unknown. 1041 // arg0 is Double, arg1 is unknown.
1042 void Intrinsifier::Double_equal(Assembler* assembler) { 1042 void Intrinsifier::Double_equal(Assembler* assembler) {
1043 return CompareDoubles(assembler, EQUAL); 1043 CompareDoubles(assembler, EQUAL);
1044 } 1044 }
1045 1045
1046 1046
1047 // arg0 is Double, arg1 is unknown. 1047 // arg0 is Double, arg1 is unknown.
1048 void Intrinsifier::Double_lessEqualThan(Assembler* assembler) { 1048 void Intrinsifier::Double_lessEqualThan(Assembler* assembler) {
1049 return CompareDoubles(assembler, BELOW_EQUAL); 1049 CompareDoubles(assembler, BELOW_EQUAL);
1050 } 1050 }
1051 1051
1052 1052
1053 // Expects left argument to be double (receiver). Right argument is unknown. 1053 // Expects left argument to be double (receiver). Right argument is unknown.
1054 // Both arguments are on stack. 1054 // Both arguments are on stack.
1055 static void DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) { 1055 static void DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) {
1056 Label fall_through; 1056 Label fall_through;
1057 TestLastArgumentIsDouble(assembler, &fall_through, &fall_through); 1057 TestLastArgumentIsDouble(assembler, &fall_through, &fall_through);
1058 // Both arguments are double, right operand is in EAX. 1058 // Both arguments are double, right operand is in EAX.
1059 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); 1059 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset()));
(...skipping 13 matching lines...) Expand all
1073 Assembler::kNearJump, 1073 Assembler::kNearJump,
1074 EAX, // Result register. 1074 EAX, // Result register.
1075 EBX); 1075 EBX);
1076 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); 1076 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
1077 __ ret(); 1077 __ ret();
1078 __ Bind(&fall_through); 1078 __ Bind(&fall_through);
1079 } 1079 }
1080 1080
1081 1081
1082 void Intrinsifier::Double_add(Assembler* assembler) { 1082 void Intrinsifier::Double_add(Assembler* assembler) {
1083 return DoubleArithmeticOperations(assembler, Token::kADD); 1083 DoubleArithmeticOperations(assembler, Token::kADD);
1084 } 1084 }
1085 1085
1086 1086
1087 void Intrinsifier::Double_mul(Assembler* assembler) { 1087 void Intrinsifier::Double_mul(Assembler* assembler) {
1088 return DoubleArithmeticOperations(assembler, Token::kMUL); 1088 DoubleArithmeticOperations(assembler, Token::kMUL);
1089 } 1089 }
1090 1090
1091 1091
1092 void Intrinsifier::Double_sub(Assembler* assembler) { 1092 void Intrinsifier::Double_sub(Assembler* assembler) {
1093 return DoubleArithmeticOperations(assembler, Token::kSUB); 1093 DoubleArithmeticOperations(assembler, Token::kSUB);
1094 } 1094 }
1095 1095
1096 1096
1097 void Intrinsifier::Double_div(Assembler* assembler) { 1097 void Intrinsifier::Double_div(Assembler* assembler) {
1098 return DoubleArithmeticOperations(assembler, Token::kDIV); 1098 DoubleArithmeticOperations(assembler, Token::kDIV);
1099 } 1099 }
1100 1100
1101 1101
1102 // Left is double right is integer (Bigint, Mint or Smi) 1102 // Left is double right is integer (Bigint, Mint or Smi)
1103 void Intrinsifier::Double_mulFromInteger(Assembler* assembler) { 1103 void Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
1104 Label fall_through; 1104 Label fall_through;
1105 // Only smis allowed. 1105 // Only smis allowed.
1106 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 1106 __ movl(EAX, Address(ESP, + 1 * kWordSize));
1107 __ testl(EAX, Immediate(kSmiTagMask)); 1107 __ testl(EAX, Immediate(kSmiTagMask));
1108 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); 1108 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 Isolate::current_tag_offset()); 1675 Isolate::current_tag_offset());
1676 // Set return value to Isolate::current_tag_. 1676 // Set return value to Isolate::current_tag_.
1677 __ movl(EAX, current_tag_addr); 1677 __ movl(EAX, current_tag_addr);
1678 __ ret(); 1678 __ ret();
1679 } 1679 }
1680 1680
1681 #undef __ 1681 #undef __
1682 } // namespace dart 1682 } // namespace dart
1683 1683
1684 #endif // defined TARGET_ARCH_IA32 1684 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_arm64.cc ('k') | runtime/vm/intrinsifier_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698