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

Side by Side Diff: src/ia32/ic-ia32.cc

Issue 6529032: Merge 6168:6800 from bleeding_edge to experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 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 | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 // |done| label if a property with the given name is found leaving the 101 // |done| label if a property with the given name is found leaving the
102 // index into the dictionary in |r0|. Jump to the |miss| label 102 // index into the dictionary in |r0|. Jump to the |miss| label
103 // otherwise. 103 // otherwise.
104 static void GenerateStringDictionaryProbes(MacroAssembler* masm, 104 static void GenerateStringDictionaryProbes(MacroAssembler* masm,
105 Label* miss, 105 Label* miss,
106 Label* done, 106 Label* done,
107 Register elements, 107 Register elements,
108 Register name, 108 Register name,
109 Register r0, 109 Register r0,
110 Register r1) { 110 Register r1) {
111 // Assert that name contains a string.
112 if (FLAG_debug_code) __ AbortIfNotString(name);
113
111 // Compute the capacity mask. 114 // Compute the capacity mask.
112 const int kCapacityOffset = 115 const int kCapacityOffset =
113 StringDictionary::kHeaderSize + 116 StringDictionary::kHeaderSize +
114 StringDictionary::kCapacityIndex * kPointerSize; 117 StringDictionary::kCapacityIndex * kPointerSize;
115 __ mov(r1, FieldOperand(elements, kCapacityOffset)); 118 __ mov(r1, FieldOperand(elements, kCapacityOffset));
116 __ shr(r1, kSmiTagSize); // convert smi to int 119 __ shr(r1, kSmiTagSize); // convert smi to int
117 __ dec(r1); 120 __ dec(r1);
118 121
119 // Generate an unrolled loop that performs a few probes before 122 // Generate an unrolled loop that performs a few probes before
120 // giving up. Measurements done on Gmail indicate that 2 probes 123 // giving up. Measurements done on Gmail indicate that 2 probes
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 // -- esp[0] : return address 384 // -- esp[0] : return address
382 // ----------------------------------- 385 // -----------------------------------
383 Label miss; 386 Label miss;
384 387
385 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); 388 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss);
386 __ bind(&miss); 389 __ bind(&miss);
387 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 390 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
388 } 391 }
389 392
390 393
391 void LoadIC::GenerateStringLength(MacroAssembler* masm) { 394 void LoadIC::GenerateStringLength(MacroAssembler* masm,
395 bool support_wrappers) {
392 // ----------- S t a t e ------------- 396 // ----------- S t a t e -------------
393 // -- eax : receiver 397 // -- eax : receiver
394 // -- ecx : name 398 // -- ecx : name
395 // -- esp[0] : return address 399 // -- esp[0] : return address
396 // ----------------------------------- 400 // -----------------------------------
397 Label miss; 401 Label miss;
398 402
399 StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss); 403 StubCompiler::GenerateLoadStringLength(masm, eax, edx, ebx, &miss,
404 support_wrappers);
400 __ bind(&miss); 405 __ bind(&miss);
401 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 406 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
402 } 407 }
403 408
404 409
405 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { 410 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
406 // ----------- S t a t e ------------- 411 // ----------- S t a t e -------------
407 // -- eax : receiver 412 // -- eax : receiver
408 // -- ecx : name 413 // -- ecx : name
409 // -- esp[0] : return address 414 // -- esp[0] : return address
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 edx, 552 edx,
548 eax, 553 eax,
549 ecx, 554 ecx,
550 eax, 555 eax,
551 NULL, 556 NULL,
552 &slow); 557 &slow);
553 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 558 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
554 __ ret(0); 559 __ ret(0);
555 560
556 __ bind(&check_pixel_array); 561 __ bind(&check_pixel_array);
557 // Check whether the elements is a pixel array. 562 GenerateFastPixelArrayLoad(masm,
558 // edx: receiver 563 edx,
559 // eax: key 564 eax,
560 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 565 ecx,
561 __ mov(ebx, eax); 566 ebx,
562 __ SmiUntag(ebx); 567 eax,
563 __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true); 568 &check_number_dictionary,
564 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); 569 NULL,
565 __ j(above_equal, &slow); 570 &slow);
566 __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset));
567 __ movzx_b(eax, Operand(eax, ebx, times_1, 0));
568 __ SmiTag(eax);
569 __ ret(0);
570 571
571 __ bind(&check_number_dictionary); 572 __ bind(&check_number_dictionary);
572 // Check whether the elements is a number dictionary. 573 // Check whether the elements is a number dictionary.
573 // edx: receiver 574 // edx: receiver
574 // ebx: untagged index 575 // ebx: untagged index
575 // eax: key 576 // eax: key
576 // ecx: elements 577 // ecx: elements
577 __ CheckMap(ecx, Factory::hash_table_map(), &slow, true); 578 __ CheckMap(ecx, Factory::hash_table_map(), &slow, true);
578 Label slow_pop_receiver; 579 Label slow_pop_receiver;
579 // Push receiver on the stack to free up a register for the dictionary 580 // Push receiver on the stack to free up a register for the dictionary
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 __ ret(0); 712 __ ret(0);
712 713
713 StubRuntimeCallHelper call_helper; 714 StubRuntimeCallHelper call_helper;
714 char_at_generator.GenerateSlow(masm, call_helper); 715 char_at_generator.GenerateSlow(masm, call_helper);
715 716
716 __ bind(&miss); 717 __ bind(&miss);
717 GenerateMiss(masm); 718 GenerateMiss(masm);
718 } 719 }
719 720
720 721
721 void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
722 ExternalArrayType array_type) {
723 // ----------- S t a t e -------------
724 // -- eax : key
725 // -- edx : receiver
726 // -- esp[0] : return address
727 // -----------------------------------
728 Label slow, failed_allocation;
729
730 // Check that the object isn't a smi.
731 __ test(edx, Immediate(kSmiTagMask));
732 __ j(zero, &slow, not_taken);
733
734 // Check that the key is a smi.
735 __ test(eax, Immediate(kSmiTagMask));
736 __ j(not_zero, &slow, not_taken);
737
738 // Get the map of the receiver.
739 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
740 // Check that the receiver does not require access checks. We need
741 // to check this explicitly since this generic stub does not perform
742 // map checks.
743 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset),
744 1 << Map::kIsAccessCheckNeeded);
745 __ j(not_zero, &slow, not_taken);
746
747 __ CmpInstanceType(ecx, JS_OBJECT_TYPE);
748 __ j(not_equal, &slow, not_taken);
749
750 // Check that the elements array is the appropriate type of
751 // ExternalArray.
752 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
753 Handle<Map> map(Heap::MapForExternalArrayType(array_type));
754 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
755 Immediate(map));
756 __ j(not_equal, &slow, not_taken);
757
758 // eax: key, known to be a smi.
759 // edx: receiver, known to be a JSObject.
760 // ebx: elements object, known to be an external array.
761 // Check that the index is in range.
762 __ mov(ecx, eax);
763 __ SmiUntag(ecx); // Untag the index.
764 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
765 // Unsigned comparison catches both negative and too-large values.
766 __ j(above_equal, &slow);
767
768 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
769 // ebx: base pointer of external storage
770 switch (array_type) {
771 case kExternalByteArray:
772 __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0));
773 break;
774 case kExternalUnsignedByteArray:
775 __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0));
776 break;
777 case kExternalShortArray:
778 __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0));
779 break;
780 case kExternalUnsignedShortArray:
781 __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0));
782 break;
783 case kExternalIntArray:
784 case kExternalUnsignedIntArray:
785 __ mov(ecx, Operand(ebx, ecx, times_4, 0));
786 break;
787 case kExternalFloatArray:
788 __ fld_s(Operand(ebx, ecx, times_4, 0));
789 break;
790 default:
791 UNREACHABLE();
792 break;
793 }
794
795 // For integer array types:
796 // ecx: value
797 // For floating-point array type:
798 // FP(0): value
799
800 if (array_type == kExternalIntArray ||
801 array_type == kExternalUnsignedIntArray) {
802 // For the Int and UnsignedInt array types, we need to see whether
803 // the value can be represented in a Smi. If not, we need to convert
804 // it to a HeapNumber.
805 Label box_int;
806 if (array_type == kExternalIntArray) {
807 __ cmp(ecx, 0xC0000000);
808 __ j(sign, &box_int);
809 } else {
810 ASSERT_EQ(array_type, kExternalUnsignedIntArray);
811 // The test is different for unsigned int values. Since we need
812 // the value to be in the range of a positive smi, we can't
813 // handle either of the top two bits being set in the value.
814 __ test(ecx, Immediate(0xC0000000));
815 __ j(not_zero, &box_int);
816 }
817
818 __ mov(eax, ecx);
819 __ SmiTag(eax);
820 __ ret(0);
821
822 __ bind(&box_int);
823
824 // Allocate a HeapNumber for the int and perform int-to-double
825 // conversion.
826 if (array_type == kExternalIntArray) {
827 __ push(ecx);
828 __ fild_s(Operand(esp, 0));
829 __ pop(ecx);
830 } else {
831 ASSERT(array_type == kExternalUnsignedIntArray);
832 // Need to zero-extend the value.
833 // There's no fild variant for unsigned values, so zero-extend
834 // to a 64-bit int manually.
835 __ push(Immediate(0));
836 __ push(ecx);
837 __ fild_d(Operand(esp, 0));
838 __ pop(ecx);
839 __ pop(ecx);
840 }
841 // FP(0): value
842 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
843 // Set the value.
844 __ mov(eax, ecx);
845 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
846 __ ret(0);
847 } else if (array_type == kExternalFloatArray) {
848 // For the floating-point array type, we need to always allocate a
849 // HeapNumber.
850 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
851 // Set the value.
852 __ mov(eax, ecx);
853 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
854 __ ret(0);
855 } else {
856 __ mov(eax, ecx);
857 __ SmiTag(eax);
858 __ ret(0);
859 }
860
861 // If we fail allocation of the HeapNumber, we still have a value on
862 // top of the FPU stack. Remove it.
863 __ bind(&failed_allocation);
864 __ ffree();
865 __ fincstp();
866 // Fall through to slow case.
867
868 // Slow case: Jump to runtime.
869 __ bind(&slow);
870 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
871 GenerateRuntimeGetProperty(masm);
872 }
873
874
875 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { 722 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
876 // ----------- S t a t e ------------- 723 // ----------- S t a t e -------------
877 // -- eax : key 724 // -- eax : key
878 // -- edx : receiver 725 // -- edx : receiver
879 // -- esp[0] : return address 726 // -- esp[0] : return address
880 // ----------------------------------- 727 // -----------------------------------
881 Label slow; 728 Label slow;
882 729
883 // Check that the receiver isn't a smi. 730 // Check that the receiver isn't a smi.
884 __ test(edx, Immediate(kSmiTagMask)); 731 __ test(edx, Immediate(kSmiTagMask));
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 // Slow case: call runtime. 802 // Slow case: call runtime.
956 __ bind(&slow); 803 __ bind(&slow);
957 GenerateRuntimeSetProperty(masm); 804 GenerateRuntimeSetProperty(masm);
958 805
959 // Check whether the elements is a pixel array. 806 // Check whether the elements is a pixel array.
960 __ bind(&check_pixel_array); 807 __ bind(&check_pixel_array);
961 // eax: value 808 // eax: value
962 // ecx: key (a smi) 809 // ecx: key (a smi)
963 // edx: receiver 810 // edx: receiver
964 // edi: elements array 811 // edi: elements array
965 __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); 812 GenerateFastPixelArrayStore(masm,
966 // Check that the value is a smi. If a conversion is needed call into the 813 edx,
967 // runtime to convert and clamp. 814 ecx,
968 __ test(eax, Immediate(kSmiTagMask)); 815 eax,
969 __ j(not_zero, &slow); 816 edi,
970 __ mov(ebx, ecx); 817 ebx,
971 __ SmiUntag(ebx); 818 false,
972 __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); 819 NULL,
973 __ j(above_equal, &slow); 820 &slow,
974 __ mov(ecx, eax); // Save the value. Key is not longer needed. 821 &slow,
975 __ SmiUntag(ecx); 822 &slow);
976 { // Clamp the value to [0..255].
977 Label done;
978 __ test(ecx, Immediate(0xFFFFFF00));
979 __ j(zero, &done);
980 __ setcc(negative, ecx); // 1 if negative, 0 if positive.
981 __ dec_b(ecx); // 0 if negative, 255 if positive.
982 __ bind(&done);
983 }
984 __ mov(edi, FieldOperand(edi, PixelArray::kExternalPointerOffset));
985 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
986 __ ret(0); // Return value in eax.
987 823
988 // Extra capacity case: Check if there is extra capacity to 824 // Extra capacity case: Check if there is extra capacity to
989 // perform the store and update the length. Used for adding one 825 // perform the store and update the length. Used for adding one
990 // element to the array by writing to array[array.length]. 826 // element to the array by writing to array[array.length].
991 __ bind(&extra); 827 __ bind(&extra);
992 // eax: value 828 // eax: value
993 // edx: receiver, a JSArray 829 // edx: receiver, a JSArray
994 // ecx: key, a smi. 830 // ecx: key, a smi.
995 // edi: receiver->elements, a FixedArray 831 // edi: receiver->elements, a FixedArray
996 // flags: compare (ecx, edx.length()) 832 // flags: compare (ecx, edx.length())
(...skipping 28 matching lines...) Expand all
1025 // edi: FixedArray receiver->elements 861 // edi: FixedArray receiver->elements
1026 __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); 862 __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax);
1027 863
1028 // Update write barrier for the elements array address. 864 // Update write barrier for the elements array address.
1029 __ mov(edx, Operand(eax)); 865 __ mov(edx, Operand(eax));
1030 __ RecordWrite(edi, 0, edx, ecx, kDontSaveFPRegs); 866 __ RecordWrite(edi, 0, edx, ecx, kDontSaveFPRegs);
1031 __ ret(0); 867 __ ret(0);
1032 } 868 }
1033 869
1034 870
1035 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
1036 ExternalArrayType array_type) {
1037 // ----------- S t a t e -------------
1038 // -- eax : value
1039 // -- ecx : key
1040 // -- edx : receiver
1041 // -- esp[0] : return address
1042 // -----------------------------------
1043 Label slow, check_heap_number;
1044
1045 // Check that the object isn't a smi.
1046 __ test(edx, Immediate(kSmiTagMask));
1047 __ j(zero, &slow);
1048 // Get the map from the receiver.
1049 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
1050 // Check that the receiver does not require access checks. We need
1051 // to do this because this generic stub does not perform map checks.
1052 __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
1053 1 << Map::kIsAccessCheckNeeded);
1054 __ j(not_zero, &slow);
1055 // Check that the key is a smi.
1056 __ test(ecx, Immediate(kSmiTagMask));
1057 __ j(not_zero, &slow);
1058 // Get the instance type from the map of the receiver.
1059 __ CmpInstanceType(edi, JS_OBJECT_TYPE);
1060 __ j(not_equal, &slow);
1061
1062 // Check that the elements array is the appropriate type of
1063 // ExternalArray.
1064 // eax: value
1065 // edx: receiver, a JSObject
1066 // ecx: key, a smi
1067 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
1068 __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)),
1069 &slow, true);
1070
1071 // Check that the index is in range.
1072 __ mov(ebx, ecx);
1073 __ SmiUntag(ebx);
1074 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset));
1075 // Unsigned comparison catches both negative and too-large values.
1076 __ j(above_equal, &slow);
1077
1078 // Handle both smis and HeapNumbers in the fast path. Go to the
1079 // runtime for all other kinds of values.
1080 // eax: value
1081 // edx: receiver
1082 // ecx: key
1083 // edi: elements array
1084 // ebx: untagged index
1085 __ test(eax, Immediate(kSmiTagMask));
1086 __ j(not_equal, &check_heap_number);
1087 // smi case
1088 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed.
1089 __ SmiUntag(ecx);
1090 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
1091 // ecx: base pointer of external storage
1092 switch (array_type) {
1093 case kExternalByteArray:
1094 case kExternalUnsignedByteArray:
1095 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
1096 break;
1097 case kExternalShortArray:
1098 case kExternalUnsignedShortArray:
1099 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
1100 break;
1101 case kExternalIntArray:
1102 case kExternalUnsignedIntArray:
1103 __ mov(Operand(edi, ebx, times_4, 0), ecx);
1104 break;
1105 case kExternalFloatArray:
1106 // Need to perform int-to-float conversion.
1107 __ push(ecx);
1108 __ fild_s(Operand(esp, 0));
1109 __ pop(ecx);
1110 __ fstp_s(Operand(edi, ebx, times_4, 0));
1111 break;
1112 default:
1113 UNREACHABLE();
1114 break;
1115 }
1116 __ ret(0); // Return the original value.
1117
1118 __ bind(&check_heap_number);
1119 // eax: value
1120 // edx: receiver
1121 // ecx: key
1122 // edi: elements array
1123 // ebx: untagged index
1124 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
1125 Immediate(Factory::heap_number_map()));
1126 __ j(not_equal, &slow);
1127
1128 // The WebGL specification leaves the behavior of storing NaN and
1129 // +/-Infinity into integer arrays basically undefined. For more
1130 // reproducible behavior, convert these to zero.
1131 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
1132 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
1133 // ebx: untagged index
1134 // edi: base pointer of external storage
1135 // top of FPU stack: value
1136 if (array_type == kExternalFloatArray) {
1137 __ fstp_s(Operand(edi, ebx, times_4, 0));
1138 __ ret(0);
1139 } else {
1140 // Need to perform float-to-int conversion.
1141 // Test the top of the FP stack for NaN.
1142 Label is_nan;
1143 __ fucomi(0);
1144 __ j(parity_even, &is_nan);
1145
1146 if (array_type != kExternalUnsignedIntArray) {
1147 __ push(ecx); // Make room on stack
1148 __ fistp_s(Operand(esp, 0));
1149 __ pop(ecx);
1150 } else {
1151 // fistp stores values as signed integers.
1152 // To represent the entire range, we need to store as a 64-bit
1153 // int and discard the high 32 bits.
1154 __ sub(Operand(esp), Immediate(2 * kPointerSize));
1155 __ fistp_d(Operand(esp, 0));
1156 __ pop(ecx);
1157 __ add(Operand(esp), Immediate(kPointerSize));
1158 }
1159 // ecx: untagged integer value
1160 switch (array_type) {
1161 case kExternalByteArray:
1162 case kExternalUnsignedByteArray:
1163 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
1164 break;
1165 case kExternalShortArray:
1166 case kExternalUnsignedShortArray:
1167 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
1168 break;
1169 case kExternalIntArray:
1170 case kExternalUnsignedIntArray: {
1171 // We also need to explicitly check for +/-Infinity. These are
1172 // converted to MIN_INT, but we need to be careful not to
1173 // confuse with legal uses of MIN_INT.
1174 Label not_infinity;
1175 // This test would apparently detect both NaN and Infinity,
1176 // but we've already checked for NaN using the FPU hardware
1177 // above.
1178 __ mov_w(edx, FieldOperand(eax, HeapNumber::kValueOffset + 6));
1179 __ and_(edx, 0x7FF0);
1180 __ cmp(edx, 0x7FF0);
1181 __ j(not_equal, &not_infinity);
1182 __ mov(ecx, 0);
1183 __ bind(&not_infinity);
1184 __ mov(Operand(edi, ebx, times_4, 0), ecx);
1185 break;
1186 }
1187 default:
1188 UNREACHABLE();
1189 break;
1190 }
1191 __ ret(0); // Return original value.
1192
1193 __ bind(&is_nan);
1194 __ ffree();
1195 __ fincstp();
1196 switch (array_type) {
1197 case kExternalByteArray:
1198 case kExternalUnsignedByteArray:
1199 __ mov_b(Operand(edi, ebx, times_1, 0), 0);
1200 break;
1201 case kExternalShortArray:
1202 case kExternalUnsignedShortArray:
1203 __ Set(ecx, Immediate(0));
1204 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
1205 break;
1206 case kExternalIntArray:
1207 case kExternalUnsignedIntArray:
1208 __ mov(Operand(edi, ebx, times_4, 0), Immediate(0));
1209 break;
1210 default:
1211 UNREACHABLE();
1212 break;
1213 }
1214 __ ret(0); // Return the original value.
1215 }
1216
1217 // Slow case: call runtime.
1218 __ bind(&slow);
1219 GenerateRuntimeSetProperty(masm);
1220 }
1221
1222
1223 // The generated code does not accept smi keys. 871 // The generated code does not accept smi keys.
1224 // The generated code falls through if both probes miss. 872 // The generated code falls through if both probes miss.
1225 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, 873 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
1226 int argc, 874 int argc,
1227 Code::Kind kind) { 875 Code::Kind kind) {
1228 // ----------- S t a t e ------------- 876 // ----------- S t a t e -------------
1229 // -- ecx : name 877 // -- ecx : name
1230 // -- edx : receiver 878 // -- edx : receiver
1231 // ----------------------------------- 879 // -----------------------------------
1232 Label number, non_number, non_string, boolean, probe, miss; 880 Label number, non_number, non_string, boolean, probe, miss;
1233 881
1234 // Probe the stub cache. 882 // Probe the stub cache.
1235 Code::Flags flags = 883 Code::Flags flags = Code::ComputeFlags(kind,
1236 Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); 884 NOT_IN_LOOP,
885 MONOMORPHIC,
886 Code::kNoExtraICState,
887 NORMAL,
888 argc);
1237 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax); 889 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax);
1238 890
1239 // If the stub cache probing failed, the receiver might be a value. 891 // If the stub cache probing failed, the receiver might be a value.
1240 // For value objects, we use the map of the prototype objects for 892 // For value objects, we use the map of the prototype objects for
1241 // the corresponding JSValue for the cache and that is what we need 893 // the corresponding JSValue for the cache and that is what we need
1242 // to probe. 894 // to probe.
1243 // 895 //
1244 // Check for number. 896 // Check for number.
1245 __ test(edx, Immediate(kSmiTagMask)); 897 __ test(edx, Immediate(kSmiTagMask));
1246 __ j(zero, &number, not_taken); 898 __ j(zero, &number, not_taken);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1319 971
1320 // eax: elements 972 // eax: elements
1321 // Search the dictionary placing the result in edi. 973 // Search the dictionary placing the result in edi.
1322 GenerateDictionaryLoad(masm, &miss, eax, ecx, edi, ebx, edi); 974 GenerateDictionaryLoad(masm, &miss, eax, ecx, edi, ebx, edi);
1323 GenerateFunctionTailCall(masm, argc, &miss); 975 GenerateFunctionTailCall(masm, argc, &miss);
1324 976
1325 __ bind(&miss); 977 __ bind(&miss);
1326 } 978 }
1327 979
1328 980
1329 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { 981 static void GenerateCallMiss(MacroAssembler* masm,
982 int argc,
983 IC::UtilityId id) {
1330 // ----------- S t a t e ------------- 984 // ----------- S t a t e -------------
1331 // -- ecx : name 985 // -- ecx : name
1332 // -- esp[0] : return address 986 // -- esp[0] : return address
1333 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 987 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1334 // -- ... 988 // -- ...
1335 // -- esp[(argc + 1) * 4] : receiver 989 // -- esp[(argc + 1) * 4] : receiver
1336 // ----------------------------------- 990 // -----------------------------------
1337 991
1338 if (id == IC::kCallIC_Miss) { 992 if (id == IC::kCallIC_Miss) {
1339 __ IncrementCounter(&Counters::call_miss, 1); 993 __ IncrementCounter(&Counters::call_miss, 1);
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
1540 1194
1541 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 1195 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
1542 // ----------- S t a t e ------------- 1196 // ----------- S t a t e -------------
1543 // -- ecx : name 1197 // -- ecx : name
1544 // -- esp[0] : return address 1198 // -- esp[0] : return address
1545 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1199 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1546 // -- ... 1200 // -- ...
1547 // -- esp[(argc + 1) * 4] : receiver 1201 // -- esp[(argc + 1) * 4] : receiver
1548 // ----------------------------------- 1202 // -----------------------------------
1549 1203
1204 // Check if the name is a string.
1205 Label miss;
1206 __ test(ecx, Immediate(kSmiTagMask));
1207 __ j(zero, &miss);
1208 Condition cond = masm->IsObjectStringType(ecx, eax, eax);
1209 __ j(NegateCondition(cond), &miss);
1550 GenerateCallNormal(masm, argc); 1210 GenerateCallNormal(masm, argc);
1211 __ bind(&miss);
1551 GenerateMiss(masm, argc); 1212 GenerateMiss(masm, argc);
1552 } 1213 }
1553 1214
1554 1215
1555 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { 1216 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
1556 // ----------- S t a t e ------------- 1217 // ----------- S t a t e -------------
1557 // -- ecx : name 1218 // -- ecx : name
1558 // -- esp[0] : return address 1219 // -- esp[0] : return address
1559 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1220 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1560 // -- ... 1221 // -- ...
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
1820 __ pop(ebx); 1481 __ pop(ebx);
1821 __ push(edx); // receiver 1482 __ push(edx); // receiver
1822 __ push(eax); // name 1483 __ push(eax); // name
1823 __ push(ebx); // return address 1484 __ push(ebx); // return address
1824 1485
1825 // Perform tail call to the entry. 1486 // Perform tail call to the entry.
1826 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 1487 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
1827 } 1488 }
1828 1489
1829 1490
1830 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 1491 void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
1492 Code::ExtraICState extra_ic_state) {
1831 // ----------- S t a t e ------------- 1493 // ----------- S t a t e -------------
1832 // -- eax : value 1494 // -- eax : value
1833 // -- ecx : name 1495 // -- ecx : name
1834 // -- edx : receiver 1496 // -- edx : receiver
1835 // -- esp[0] : return address 1497 // -- esp[0] : return address
1836 // ----------------------------------- 1498 // -----------------------------------
1837 1499
1838 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, 1500 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
1839 NOT_IN_LOOP, 1501 NOT_IN_LOOP,
1840 MONOMORPHIC); 1502 MONOMORPHIC,
1503 extra_ic_state);
1841 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 1504 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
1842 1505
1843 // Cache miss: Jump to runtime. 1506 // Cache miss: Jump to runtime.
1844 GenerateMiss(masm); 1507 GenerateMiss(masm);
1845 } 1508 }
1846 1509
1847 1510
1848 void StoreIC::GenerateMiss(MacroAssembler* masm) { 1511 void StoreIC::GenerateMiss(MacroAssembler* masm) {
1849 // ----------- S t a t e ------------- 1512 // ----------- S t a t e -------------
1850 // -- eax : value 1513 // -- eax : value
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
2108 Condition cc = *jmp_address == Assembler::kJncShortOpcode 1771 Condition cc = *jmp_address == Assembler::kJncShortOpcode
2109 ? not_zero 1772 ? not_zero
2110 : zero; 1773 : zero;
2111 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1774 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
2112 } 1775 }
2113 1776
2114 1777
2115 } } // namespace v8::internal 1778 } } // namespace v8::internal
2116 1779
2117 #endif // V8_TARGET_ARCH_IA32 1780 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698