| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
| 15 // | 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #if defined(V8_TARGET_ARCH_IA32) | 30 #if V8_TARGET_ARCH_IA32 |
| 31 | 31 |
| 32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
| 33 #include "code-stubs.h" | 33 #include "code-stubs.h" |
| 34 #include "isolate.h" | 34 #include "isolate.h" |
| 35 #include "jsregexp.h" | 35 #include "jsregexp.h" |
| 36 #include "regexp-macro-assembler.h" | 36 #include "regexp-macro-assembler.h" |
| 37 #include "runtime.h" | 37 #include "runtime.h" |
| 38 #include "stub-cache.h" | 38 #include "stub-cache.h" |
| 39 #include "codegen.h" | 39 #include "codegen.h" |
| 40 #include "runtime.h" | 40 #include "runtime.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 58 Isolate* isolate, | 58 Isolate* isolate, |
| 59 CodeStubInterfaceDescriptor* descriptor) { | 59 CodeStubInterfaceDescriptor* descriptor) { |
| 60 static Register registers[] = { eax, ebx, ecx, edx }; | 60 static Register registers[] = { eax, ebx, ecx, edx }; |
| 61 descriptor->register_param_count_ = 4; | 61 descriptor->register_param_count_ = 4; |
| 62 descriptor->register_params_ = registers; | 62 descriptor->register_params_ = registers; |
| 63 descriptor->deoptimization_handler_ = | 63 descriptor->deoptimization_handler_ = |
| 64 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; | 64 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; |
| 65 } | 65 } |
| 66 | 66 |
| 67 | 67 |
| 68 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( |
| 69 Isolate* isolate, |
| 70 CodeStubInterfaceDescriptor* descriptor) { |
| 71 static Register registers[] = { ebx }; |
| 72 descriptor->register_param_count_ = 1; |
| 73 descriptor->register_params_ = registers; |
| 74 descriptor->deoptimization_handler_ = NULL; |
| 75 } |
| 76 |
| 77 |
| 68 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( | 78 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( |
| 69 Isolate* isolate, | 79 Isolate* isolate, |
| 70 CodeStubInterfaceDescriptor* descriptor) { | 80 CodeStubInterfaceDescriptor* descriptor) { |
| 71 static Register registers[] = { edx, ecx }; | 81 static Register registers[] = { edx, ecx }; |
| 72 descriptor->register_param_count_ = 2; | 82 descriptor->register_param_count_ = 2; |
| 73 descriptor->register_params_ = registers; | 83 descriptor->register_params_ = registers; |
| 74 descriptor->deoptimization_handler_ = | 84 descriptor->deoptimization_handler_ = |
| 75 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); | 85 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); |
| 76 } | 86 } |
| 77 | 87 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 static Register registers[] = { eax }; | 233 static Register registers[] = { eax }; |
| 224 descriptor->register_param_count_ = 1; | 234 descriptor->register_param_count_ = 1; |
| 225 descriptor->register_params_ = registers; | 235 descriptor->register_params_ = registers; |
| 226 descriptor->deoptimization_handler_ = | 236 descriptor->deoptimization_handler_ = |
| 227 FUNCTION_ADDR(ToBooleanIC_Miss); | 237 FUNCTION_ADDR(ToBooleanIC_Miss); |
| 228 descriptor->SetMissHandler( | 238 descriptor->SetMissHandler( |
| 229 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate)); | 239 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate)); |
| 230 } | 240 } |
| 231 | 241 |
| 232 | 242 |
| 243 void UnaryOpStub::InitializeInterfaceDescriptor( |
| 244 Isolate* isolate, |
| 245 CodeStubInterfaceDescriptor* descriptor) { |
| 246 static Register registers[] = { eax }; |
| 247 descriptor->register_param_count_ = 1; |
| 248 descriptor->register_params_ = registers; |
| 249 descriptor->deoptimization_handler_ = |
| 250 FUNCTION_ADDR(UnaryOpIC_Miss); |
| 251 } |
| 252 |
| 253 |
| 254 void StoreGlobalStub::InitializeInterfaceDescriptor( |
| 255 Isolate* isolate, |
| 256 CodeStubInterfaceDescriptor* descriptor) { |
| 257 static Register registers[] = { edx, ecx, eax }; |
| 258 descriptor->register_param_count_ = 3; |
| 259 descriptor->register_params_ = registers; |
| 260 descriptor->deoptimization_handler_ = |
| 261 FUNCTION_ADDR(StoreIC_MissFromStubFailure); |
| 262 } |
| 263 |
| 264 |
| 233 #define __ ACCESS_MASM(masm) | 265 #define __ ACCESS_MASM(masm) |
| 234 | 266 |
| 235 | 267 |
| 236 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { | 268 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { |
| 237 // Update the static counter each time a new code stub is generated. | 269 // Update the static counter each time a new code stub is generated. |
| 238 Isolate* isolate = masm->isolate(); | 270 Isolate* isolate = masm->isolate(); |
| 239 isolate->counters()->code_stubs()->Increment(); | 271 isolate->counters()->code_stubs()->Increment(); |
| 240 | 272 |
| 241 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate); | 273 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate); |
| 242 int param_count = descriptor->register_param_count_; | 274 int param_count = descriptor->register_param_count_; |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 752 // Result is in ecx. Trashes ebx, xmm0, and xmm1. | 784 // Result is in ecx. Trashes ebx, xmm0, and xmm1. |
| 753 static void ConvertHeapNumberToInt32(MacroAssembler* masm, | 785 static void ConvertHeapNumberToInt32(MacroAssembler* masm, |
| 754 Register source, | 786 Register source, |
| 755 Label* conversion_failure) { | 787 Label* conversion_failure) { |
| 756 __ movdbl(xmm0, FieldOperand(source, HeapNumber::kValueOffset)); | 788 __ movdbl(xmm0, FieldOperand(source, HeapNumber::kValueOffset)); |
| 757 FloatingPointHelper::CheckSSE2OperandIsInt32( | 789 FloatingPointHelper::CheckSSE2OperandIsInt32( |
| 758 masm, conversion_failure, xmm0, ecx, ebx, xmm1); | 790 masm, conversion_failure, xmm0, ecx, ebx, xmm1); |
| 759 } | 791 } |
| 760 | 792 |
| 761 | 793 |
| 762 void UnaryOpStub::PrintName(StringStream* stream) { | |
| 763 const char* op_name = Token::Name(op_); | |
| 764 const char* overwrite_name = NULL; // Make g++ happy. | |
| 765 switch (mode_) { | |
| 766 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; | |
| 767 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; | |
| 768 } | |
| 769 stream->Add("UnaryOpStub_%s_%s_%s", | |
| 770 op_name, | |
| 771 overwrite_name, | |
| 772 UnaryOpIC::GetName(operand_type_)); | |
| 773 } | |
| 774 | |
| 775 | |
| 776 // TODO(svenpanne): Use virtual functions instead of switch. | |
| 777 void UnaryOpStub::Generate(MacroAssembler* masm) { | |
| 778 switch (operand_type_) { | |
| 779 case UnaryOpIC::UNINITIALIZED: | |
| 780 GenerateTypeTransition(masm); | |
| 781 break; | |
| 782 case UnaryOpIC::SMI: | |
| 783 GenerateSmiStub(masm); | |
| 784 break; | |
| 785 case UnaryOpIC::NUMBER: | |
| 786 GenerateNumberStub(masm); | |
| 787 break; | |
| 788 case UnaryOpIC::GENERIC: | |
| 789 GenerateGenericStub(masm); | |
| 790 break; | |
| 791 } | |
| 792 } | |
| 793 | |
| 794 | |
| 795 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { | |
| 796 __ pop(ecx); // Save return address. | |
| 797 | |
| 798 __ push(eax); // the operand | |
| 799 __ push(Immediate(Smi::FromInt(op_))); | |
| 800 __ push(Immediate(Smi::FromInt(mode_))); | |
| 801 __ push(Immediate(Smi::FromInt(operand_type_))); | |
| 802 | |
| 803 __ push(ecx); // Push return address. | |
| 804 | |
| 805 // Patch the caller to an appropriate specialized stub and return the | |
| 806 // operation result to the caller of the stub. | |
| 807 __ TailCallExternalReference( | |
| 808 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1); | |
| 809 } | |
| 810 | |
| 811 | |
| 812 // TODO(svenpanne): Use virtual functions instead of switch. | |
| 813 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { | |
| 814 switch (op_) { | |
| 815 case Token::SUB: | |
| 816 GenerateSmiStubSub(masm); | |
| 817 break; | |
| 818 case Token::BIT_NOT: | |
| 819 GenerateSmiStubBitNot(masm); | |
| 820 break; | |
| 821 default: | |
| 822 UNREACHABLE(); | |
| 823 } | |
| 824 } | |
| 825 | |
| 826 | |
| 827 void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) { | |
| 828 Label non_smi, undo, slow; | |
| 829 GenerateSmiCodeSub(masm, &non_smi, &undo, &slow, | |
| 830 Label::kNear, Label::kNear, Label::kNear); | |
| 831 __ bind(&undo); | |
| 832 GenerateSmiCodeUndo(masm); | |
| 833 __ bind(&non_smi); | |
| 834 __ bind(&slow); | |
| 835 GenerateTypeTransition(masm); | |
| 836 } | |
| 837 | |
| 838 | |
| 839 void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) { | |
| 840 Label non_smi; | |
| 841 GenerateSmiCodeBitNot(masm, &non_smi); | |
| 842 __ bind(&non_smi); | |
| 843 GenerateTypeTransition(masm); | |
| 844 } | |
| 845 | |
| 846 | |
| 847 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, | |
| 848 Label* non_smi, | |
| 849 Label* undo, | |
| 850 Label* slow, | |
| 851 Label::Distance non_smi_near, | |
| 852 Label::Distance undo_near, | |
| 853 Label::Distance slow_near) { | |
| 854 // Check whether the value is a smi. | |
| 855 __ JumpIfNotSmi(eax, non_smi, non_smi_near); | |
| 856 | |
| 857 // We can't handle -0 with smis, so use a type transition for that case. | |
| 858 __ test(eax, eax); | |
| 859 __ j(zero, slow, slow_near); | |
| 860 | |
| 861 // Try optimistic subtraction '0 - value', saving operand in eax for undo. | |
| 862 __ mov(edx, eax); | |
| 863 __ Set(eax, Immediate(0)); | |
| 864 __ sub(eax, edx); | |
| 865 __ j(overflow, undo, undo_near); | |
| 866 __ ret(0); | |
| 867 } | |
| 868 | |
| 869 | |
| 870 void UnaryOpStub::GenerateSmiCodeBitNot( | |
| 871 MacroAssembler* masm, | |
| 872 Label* non_smi, | |
| 873 Label::Distance non_smi_near) { | |
| 874 // Check whether the value is a smi. | |
| 875 __ JumpIfNotSmi(eax, non_smi, non_smi_near); | |
| 876 | |
| 877 // Flip bits and revert inverted smi-tag. | |
| 878 __ not_(eax); | |
| 879 __ and_(eax, ~kSmiTagMask); | |
| 880 __ ret(0); | |
| 881 } | |
| 882 | |
| 883 | |
| 884 void UnaryOpStub::GenerateSmiCodeUndo(MacroAssembler* masm) { | |
| 885 __ mov(eax, edx); | |
| 886 } | |
| 887 | |
| 888 | |
| 889 // TODO(svenpanne): Use virtual functions instead of switch. | |
| 890 void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) { | |
| 891 switch (op_) { | |
| 892 case Token::SUB: | |
| 893 GenerateNumberStubSub(masm); | |
| 894 break; | |
| 895 case Token::BIT_NOT: | |
| 896 GenerateNumberStubBitNot(masm); | |
| 897 break; | |
| 898 default: | |
| 899 UNREACHABLE(); | |
| 900 } | |
| 901 } | |
| 902 | |
| 903 | |
| 904 void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) { | |
| 905 Label non_smi, undo, slow, call_builtin; | |
| 906 GenerateSmiCodeSub(masm, &non_smi, &undo, &call_builtin, Label::kNear); | |
| 907 __ bind(&non_smi); | |
| 908 GenerateHeapNumberCodeSub(masm, &slow); | |
| 909 __ bind(&undo); | |
| 910 GenerateSmiCodeUndo(masm); | |
| 911 __ bind(&slow); | |
| 912 GenerateTypeTransition(masm); | |
| 913 __ bind(&call_builtin); | |
| 914 GenerateGenericCodeFallback(masm); | |
| 915 } | |
| 916 | |
| 917 | |
| 918 void UnaryOpStub::GenerateNumberStubBitNot( | |
| 919 MacroAssembler* masm) { | |
| 920 Label non_smi, slow; | |
| 921 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear); | |
| 922 __ bind(&non_smi); | |
| 923 GenerateHeapNumberCodeBitNot(masm, &slow); | |
| 924 __ bind(&slow); | |
| 925 GenerateTypeTransition(masm); | |
| 926 } | |
| 927 | |
| 928 | |
| 929 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, | |
| 930 Label* slow) { | |
| 931 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | |
| 932 __ cmp(edx, masm->isolate()->factory()->heap_number_map()); | |
| 933 __ j(not_equal, slow); | |
| 934 | |
| 935 if (mode_ == UNARY_OVERWRITE) { | |
| 936 __ xor_(FieldOperand(eax, HeapNumber::kExponentOffset), | |
| 937 Immediate(HeapNumber::kSignMask)); // Flip sign. | |
| 938 } else { | |
| 939 __ mov(edx, eax); | |
| 940 // edx: operand | |
| 941 | |
| 942 Label slow_allocate_heapnumber, heapnumber_allocated; | |
| 943 __ AllocateHeapNumber(eax, ebx, ecx, &slow_allocate_heapnumber); | |
| 944 __ jmp(&heapnumber_allocated, Label::kNear); | |
| 945 | |
| 946 __ bind(&slow_allocate_heapnumber); | |
| 947 { | |
| 948 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 949 __ push(edx); | |
| 950 __ CallRuntime(Runtime::kNumberAlloc, 0); | |
| 951 __ pop(edx); | |
| 952 } | |
| 953 | |
| 954 __ bind(&heapnumber_allocated); | |
| 955 // eax: allocated 'empty' number | |
| 956 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); | |
| 957 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. | |
| 958 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); | |
| 959 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); | |
| 960 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | |
| 961 } | |
| 962 __ ret(0); | |
| 963 } | |
| 964 | |
| 965 | |
| 966 void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm, | |
| 967 Label* slow) { | |
| 968 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | |
| 969 __ cmp(edx, masm->isolate()->factory()->heap_number_map()); | |
| 970 __ j(not_equal, slow); | |
| 971 | |
| 972 // Convert the heap number in eax to an untagged integer in ecx. | |
| 973 IntegerConvert(masm, eax, CpuFeatures::IsSupported(SSE3), slow); | |
| 974 | |
| 975 // Do the bitwise operation and check if the result fits in a smi. | |
| 976 Label try_float; | |
| 977 __ not_(ecx); | |
| 978 __ cmp(ecx, 0xc0000000); | |
| 979 __ j(sign, &try_float, Label::kNear); | |
| 980 | |
| 981 // Tag the result as a smi and we're done. | |
| 982 STATIC_ASSERT(kSmiTagSize == 1); | |
| 983 __ lea(eax, Operand(ecx, times_2, kSmiTag)); | |
| 984 __ ret(0); | |
| 985 | |
| 986 // Try to store the result in a heap number. | |
| 987 __ bind(&try_float); | |
| 988 if (mode_ == UNARY_NO_OVERWRITE) { | |
| 989 Label slow_allocate_heapnumber, heapnumber_allocated; | |
| 990 __ mov(ebx, eax); | |
| 991 __ AllocateHeapNumber(eax, edx, edi, &slow_allocate_heapnumber); | |
| 992 __ jmp(&heapnumber_allocated); | |
| 993 | |
| 994 __ bind(&slow_allocate_heapnumber); | |
| 995 { | |
| 996 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 997 // Push the original HeapNumber on the stack. The integer value can't | |
| 998 // be stored since it's untagged and not in the smi range (so we can't | |
| 999 // smi-tag it). We'll recalculate the value after the GC instead. | |
| 1000 __ push(ebx); | |
| 1001 __ CallRuntime(Runtime::kNumberAlloc, 0); | |
| 1002 // New HeapNumber is in eax. | |
| 1003 __ pop(edx); | |
| 1004 } | |
| 1005 // IntegerConvert uses ebx and edi as scratch registers. | |
| 1006 // This conversion won't go slow-case. | |
| 1007 IntegerConvert(masm, edx, CpuFeatures::IsSupported(SSE3), slow); | |
| 1008 __ not_(ecx); | |
| 1009 | |
| 1010 __ bind(&heapnumber_allocated); | |
| 1011 } | |
| 1012 if (CpuFeatures::IsSupported(SSE2)) { | |
| 1013 CpuFeatureScope use_sse2(masm, SSE2); | |
| 1014 __ cvtsi2sd(xmm0, ecx); | |
| 1015 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | |
| 1016 } else { | |
| 1017 __ push(ecx); | |
| 1018 __ fild_s(Operand(esp, 0)); | |
| 1019 __ pop(ecx); | |
| 1020 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
| 1021 } | |
| 1022 __ ret(0); | |
| 1023 } | |
| 1024 | |
| 1025 | |
| 1026 // TODO(svenpanne): Use virtual functions instead of switch. | |
| 1027 void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) { | |
| 1028 switch (op_) { | |
| 1029 case Token::SUB: | |
| 1030 GenerateGenericStubSub(masm); | |
| 1031 break; | |
| 1032 case Token::BIT_NOT: | |
| 1033 GenerateGenericStubBitNot(masm); | |
| 1034 break; | |
| 1035 default: | |
| 1036 UNREACHABLE(); | |
| 1037 } | |
| 1038 } | |
| 1039 | |
| 1040 | |
| 1041 void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) { | |
| 1042 Label non_smi, undo, slow; | |
| 1043 GenerateSmiCodeSub(masm, &non_smi, &undo, &slow, Label::kNear); | |
| 1044 __ bind(&non_smi); | |
| 1045 GenerateHeapNumberCodeSub(masm, &slow); | |
| 1046 __ bind(&undo); | |
| 1047 GenerateSmiCodeUndo(masm); | |
| 1048 __ bind(&slow); | |
| 1049 GenerateGenericCodeFallback(masm); | |
| 1050 } | |
| 1051 | |
| 1052 | |
| 1053 void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) { | |
| 1054 Label non_smi, slow; | |
| 1055 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear); | |
| 1056 __ bind(&non_smi); | |
| 1057 GenerateHeapNumberCodeBitNot(masm, &slow); | |
| 1058 __ bind(&slow); | |
| 1059 GenerateGenericCodeFallback(masm); | |
| 1060 } | |
| 1061 | |
| 1062 | |
| 1063 void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) { | |
| 1064 // Handle the slow case by jumping to the corresponding JavaScript builtin. | |
| 1065 __ pop(ecx); // pop return address. | |
| 1066 __ push(eax); | |
| 1067 __ push(ecx); // push return address | |
| 1068 switch (op_) { | |
| 1069 case Token::SUB: | |
| 1070 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); | |
| 1071 break; | |
| 1072 case Token::BIT_NOT: | |
| 1073 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); | |
| 1074 break; | |
| 1075 default: | |
| 1076 UNREACHABLE(); | |
| 1077 } | |
| 1078 } | |
| 1079 | |
| 1080 | |
| 1081 void BinaryOpStub::Initialize() { | 794 void BinaryOpStub::Initialize() { |
| 1082 platform_specific_bit_ = CpuFeatures::IsSupported(SSE3); | 795 platform_specific_bit_ = CpuFeatures::IsSupported(SSE3); |
| 1083 } | 796 } |
| 1084 | 797 |
| 1085 | 798 |
| 1086 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { | 799 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { |
| 1087 __ pop(ecx); // Save return address. | 800 __ pop(ecx); // Save return address. |
| 1088 __ push(edx); | 801 __ push(edx); |
| 1089 __ push(eax); | 802 __ push(eax); |
| 1090 // Left and right arguments are now on top. | 803 // Left and right arguments are now on top. |
| (...skipping 3599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4690 // Load the cache state into ecx. | 4403 // Load the cache state into ecx. |
| 4691 __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset)); | 4404 __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset)); |
| 4692 | 4405 |
| 4693 // A monomorphic cache hit or an already megamorphic state: invoke the | 4406 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 4694 // function without changing the state. | 4407 // function without changing the state. |
| 4695 __ cmp(ecx, edi); | 4408 __ cmp(ecx, edi); |
| 4696 __ j(equal, &done); | 4409 __ j(equal, &done); |
| 4697 __ cmp(ecx, Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); | 4410 __ cmp(ecx, Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); |
| 4698 __ j(equal, &done); | 4411 __ j(equal, &done); |
| 4699 | 4412 |
| 4700 // Special handling of the Array() function, which caches not only the | 4413 // If we came here, we need to see if we are the array function. |
| 4701 // monomorphic Array function but the initial ElementsKind with special | 4414 // If we didn't have a matching function, and we didn't find the megamorph |
| 4702 // sentinels | 4415 // sentinel, then we have in the cell either some other function or an |
| 4703 Handle<Object> terminal_kind_sentinel = | 4416 // AllocationSite. Do a map check on the object in ecx. |
| 4704 TypeFeedbackCells::MonomorphicArraySentinel(isolate, | 4417 Handle<Map> allocation_site_map( |
| 4705 LAST_FAST_ELEMENTS_KIND); | 4418 masm->isolate()->heap()->allocation_site_map(), |
| 4706 __ JumpIfNotSmi(ecx, &miss); | 4419 masm->isolate()); |
| 4707 __ cmp(ecx, Immediate(terminal_kind_sentinel)); | 4420 __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map)); |
| 4708 __ j(above, &miss); | 4421 __ j(not_equal, &miss); |
| 4422 |
| 4709 // Load the global or builtins object from the current context | 4423 // Load the global or builtins object from the current context |
| 4710 __ LoadGlobalContext(ecx); | 4424 __ LoadGlobalContext(ecx); |
| 4711 // Make sure the function is the Array() function | 4425 // Make sure the function is the Array() function |
| 4712 __ cmp(edi, Operand(ecx, | 4426 __ cmp(edi, Operand(ecx, |
| 4713 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | 4427 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
| 4714 __ j(not_equal, &megamorphic); | 4428 __ j(not_equal, &megamorphic); |
| 4715 __ jmp(&done); | 4429 __ jmp(&done); |
| 4716 | 4430 |
| 4717 __ bind(&miss); | 4431 __ bind(&miss); |
| 4718 | 4432 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4729 | 4443 |
| 4730 // An uninitialized cache is patched with the function or sentinel to | 4444 // An uninitialized cache is patched with the function or sentinel to |
| 4731 // indicate the ElementsKind if function is the Array constructor. | 4445 // indicate the ElementsKind if function is the Array constructor. |
| 4732 __ bind(&initialize); | 4446 __ bind(&initialize); |
| 4733 __ LoadGlobalContext(ecx); | 4447 __ LoadGlobalContext(ecx); |
| 4734 // Make sure the function is the Array() function | 4448 // Make sure the function is the Array() function |
| 4735 __ cmp(edi, Operand(ecx, | 4449 __ cmp(edi, Operand(ecx, |
| 4736 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | 4450 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
| 4737 __ j(not_equal, ¬_array_function); | 4451 __ j(not_equal, ¬_array_function); |
| 4738 | 4452 |
| 4739 // The target function is the Array constructor, install a sentinel value in | 4453 // The target function is the Array constructor, |
| 4740 // the constructor's type info cell that will track the initial ElementsKind | 4454 // Create an AllocationSite if we don't already have it, store it in the cell |
| 4741 // that should be used for the array when its constructed. | 4455 { |
| 4742 Handle<Object> initial_kind_sentinel = | 4456 FrameScope scope(masm, StackFrame::INTERNAL); |
| 4743 TypeFeedbackCells::MonomorphicArraySentinel(isolate, | 4457 |
| 4744 GetInitialFastElementsKind()); | 4458 __ push(eax); |
| 4745 __ mov(FieldOperand(ebx, Cell::kValueOffset), | 4459 __ push(edi); |
| 4746 Immediate(initial_kind_sentinel)); | 4460 __ push(ebx); |
| 4461 |
| 4462 CreateAllocationSiteStub create_stub; |
| 4463 __ CallStub(&create_stub); |
| 4464 |
| 4465 __ pop(ebx); |
| 4466 __ pop(edi); |
| 4467 __ pop(eax); |
| 4468 } |
| 4747 __ jmp(&done); | 4469 __ jmp(&done); |
| 4748 | 4470 |
| 4749 __ bind(¬_array_function); | 4471 __ bind(¬_array_function); |
| 4750 __ mov(FieldOperand(ebx, Cell::kValueOffset), edi); | 4472 __ mov(FieldOperand(ebx, Cell::kValueOffset), edi); |
| 4751 // No need for a write barrier here - cells are rescanned. | 4473 // No need for a write barrier here - cells are rescanned. |
| 4752 | 4474 |
| 4753 __ bind(&done); | 4475 __ bind(&done); |
| 4754 } | 4476 } |
| 4755 | 4477 |
| 4756 | 4478 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4902 } | 4624 } |
| 4903 | 4625 |
| 4904 | 4626 |
| 4905 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 4627 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 4906 CEntryStub::GenerateAheadOfTime(isolate); | 4628 CEntryStub::GenerateAheadOfTime(isolate); |
| 4907 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 4629 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 4908 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 4630 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
| 4909 // It is important that the store buffer overflow stubs are generated first. | 4631 // It is important that the store buffer overflow stubs are generated first. |
| 4910 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); | 4632 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 4911 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); | 4633 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); |
| 4634 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); |
| 4912 } | 4635 } |
| 4913 | 4636 |
| 4914 | 4637 |
| 4915 void CodeStub::GenerateFPStubs(Isolate* isolate) { | 4638 void CodeStub::GenerateFPStubs(Isolate* isolate) { |
| 4916 if (CpuFeatures::IsSupported(SSE2)) { | 4639 if (CpuFeatures::IsSupported(SSE2)) { |
| 4917 CEntryStub save_doubles(1, kSaveFPRegs); | 4640 CEntryStub save_doubles(1, kSaveFPRegs); |
| 4918 // Stubs might already be in the snapshot, detect that and don't regenerate, | 4641 // Stubs might already be in the snapshot, detect that and don't regenerate, |
| 4919 // which would lead to code stub initialization state being messed up. | 4642 // which would lead to code stub initialization state being messed up. |
| 4920 Code* save_doubles_code; | 4643 Code* save_doubles_code; |
| 4921 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) { | 4644 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5070 | 4793 |
| 5071 | 4794 |
| 5072 void CEntryStub::Generate(MacroAssembler* masm) { | 4795 void CEntryStub::Generate(MacroAssembler* masm) { |
| 5073 // eax: number of arguments including receiver | 4796 // eax: number of arguments including receiver |
| 5074 // ebx: pointer to C function (C callee-saved) | 4797 // ebx: pointer to C function (C callee-saved) |
| 5075 // ebp: frame pointer (restored after C call) | 4798 // ebp: frame pointer (restored after C call) |
| 5076 // esp: stack pointer (restored after C call) | 4799 // esp: stack pointer (restored after C call) |
| 5077 // esi: current context (C callee-saved) | 4800 // esi: current context (C callee-saved) |
| 5078 // edi: JS function of the caller (C callee-saved) | 4801 // edi: JS function of the caller (C callee-saved) |
| 5079 | 4802 |
| 4803 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
| 4804 |
| 5080 // NOTE: Invocations of builtins may return failure objects instead | 4805 // NOTE: Invocations of builtins may return failure objects instead |
| 5081 // of a proper result. The builtin entry handles this by performing | 4806 // of a proper result. The builtin entry handles this by performing |
| 5082 // a garbage collection and retrying the builtin (twice). | 4807 // a garbage collection and retrying the builtin (twice). |
| 5083 | 4808 |
| 5084 // Enter the exit frame that transitions from JavaScript to C++. | 4809 // Enter the exit frame that transitions from JavaScript to C++. |
| 5085 __ EnterExitFrame(save_doubles_ == kSaveFPRegs); | 4810 __ EnterExitFrame(save_doubles_ == kSaveFPRegs); |
| 5086 | 4811 |
| 5087 // eax: result parameter for PerformGC, if any (setup below) | 4812 // eax: result parameter for PerformGC, if any (setup below) |
| 5088 // ebx: pointer to builtin function (C callee-saved) | 4813 // ebx: pointer to builtin function (C callee-saved) |
| 5089 // ebp: frame pointer (restored after C call) | 4814 // ebp: frame pointer (restored after C call) |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5143 | 4868 |
| 5144 __ bind(&throw_normal_exception); | 4869 __ bind(&throw_normal_exception); |
| 5145 __ Throw(eax); | 4870 __ Throw(eax); |
| 5146 } | 4871 } |
| 5147 | 4872 |
| 5148 | 4873 |
| 5149 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { | 4874 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { |
| 5150 Label invoke, handler_entry, exit; | 4875 Label invoke, handler_entry, exit; |
| 5151 Label not_outermost_js, not_outermost_js_2; | 4876 Label not_outermost_js, not_outermost_js_2; |
| 5152 | 4877 |
| 4878 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
| 4879 |
| 5153 // Set up frame. | 4880 // Set up frame. |
| 5154 __ push(ebp); | 4881 __ push(ebp); |
| 5155 __ mov(ebp, esp); | 4882 __ mov(ebp, esp); |
| 5156 | 4883 |
| 5157 // Push marker in two places. | 4884 // Push marker in two places. |
| 5158 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; | 4885 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; |
| 5159 __ push(Immediate(Smi::FromInt(marker))); // context slot | 4886 __ push(Immediate(Smi::FromInt(marker))); // context slot |
| 5160 __ push(Immediate(Smi::FromInt(marker))); // function slot | 4887 __ push(Immediate(Smi::FromInt(marker))); // function slot |
| 5161 // Save callee-saved registers (C calling conventions). | 4888 // Save callee-saved registers (C calling conventions). |
| 5162 __ push(edi); | 4889 __ push(edi); |
| (...skipping 2521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7684 __ pop(ecx); | 7411 __ pop(ecx); |
| 7685 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE | 7412 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE |
| 7686 ? kPointerSize | 7413 ? kPointerSize |
| 7687 : 0; | 7414 : 0; |
| 7688 __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset)); | 7415 __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset)); |
| 7689 __ jmp(ecx); // Return to IC Miss stub, continuation still on stack. | 7416 __ jmp(ecx); // Return to IC Miss stub, continuation still on stack. |
| 7690 } | 7417 } |
| 7691 | 7418 |
| 7692 | 7419 |
| 7693 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 7420 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
| 7694 if (entry_hook_ != NULL) { | 7421 if (masm->isolate()->function_entry_hook() != NULL) { |
| 7422 // It's always safe to call the entry hook stub, as the hook itself |
| 7423 // is not allowed to call back to V8. |
| 7424 AllowStubCallsScope allow_stub_calls(masm, true); |
| 7425 |
| 7695 ProfileEntryHookStub stub; | 7426 ProfileEntryHookStub stub; |
| 7696 masm->CallStub(&stub); | 7427 masm->CallStub(&stub); |
| 7697 } | 7428 } |
| 7698 } | 7429 } |
| 7699 | 7430 |
| 7700 | 7431 |
| 7701 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { | 7432 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { |
| 7702 // Ecx is the only volatile register we must save. | 7433 // Save volatile registers. |
| 7703 const int kNumSavedRegisters = 1; | 7434 const int kNumSavedRegisters = 3; |
| 7435 __ push(eax); |
| 7704 __ push(ecx); | 7436 __ push(ecx); |
| 7437 __ push(edx); |
| 7705 | 7438 |
| 7706 // Calculate and push the original stack pointer. | 7439 // Calculate and push the original stack pointer. |
| 7707 __ lea(eax, Operand(esp, (kNumSavedRegisters + 1) * kPointerSize)); | 7440 __ lea(eax, Operand(esp, (kNumSavedRegisters + 1) * kPointerSize)); |
| 7708 __ push(eax); | 7441 __ push(eax); |
| 7709 | 7442 |
| 7710 // Retrieve our return address and use it to calculate the calling | 7443 // Retrieve our return address and use it to calculate the calling |
| 7711 // function's address. | 7444 // function's address. |
| 7712 __ mov(eax, Operand(esp, (kNumSavedRegisters + 1) * kPointerSize)); | 7445 __ mov(eax, Operand(esp, (kNumSavedRegisters + 1) * kPointerSize)); |
| 7713 __ sub(eax, Immediate(Assembler::kCallInstructionLength)); | 7446 __ sub(eax, Immediate(Assembler::kCallInstructionLength)); |
| 7714 __ push(eax); | 7447 __ push(eax); |
| 7715 | 7448 |
| 7716 // Call the entry hook. | 7449 // Call the entry hook. |
| 7717 int32_t hook_location = reinterpret_cast<int32_t>(&entry_hook_); | 7450 ASSERT(masm->isolate()->function_entry_hook() != NULL); |
| 7718 __ call(Operand(hook_location, RelocInfo::NONE32)); | 7451 __ call(FUNCTION_ADDR(masm->isolate()->function_entry_hook()), |
| 7452 RelocInfo::RUNTIME_ENTRY); |
| 7719 __ add(esp, Immediate(2 * kPointerSize)); | 7453 __ add(esp, Immediate(2 * kPointerSize)); |
| 7720 | 7454 |
| 7721 // Restore ecx. | 7455 // Restore ecx. |
| 7456 __ pop(edx); |
| 7722 __ pop(ecx); | 7457 __ pop(ecx); |
| 7458 __ pop(eax); |
| 7459 |
| 7723 __ ret(0); | 7460 __ ret(0); |
| 7724 } | 7461 } |
| 7725 | 7462 |
| 7726 | 7463 |
| 7727 template<class T> | 7464 template<class T> |
| 7728 static void CreateArrayDispatch(MacroAssembler* masm) { | 7465 static void CreateArrayDispatch(MacroAssembler* masm) { |
| 7729 int last_index = GetSequenceIndexFromFastElementsKind( | 7466 int last_index = GetSequenceIndexFromFastElementsKind( |
| 7730 TERMINAL_FAST_ELEMENTS_KIND); | 7467 TERMINAL_FAST_ELEMENTS_KIND); |
| 7731 for (int i = 0; i <= last_index; ++i) { | 7468 for (int i = 0; i <= last_index; ++i) { |
| 7732 Label next; | 7469 Label next; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7765 __ test_b(edx, 1); | 7502 __ test_b(edx, 1); |
| 7766 Label normal_sequence; | 7503 Label normal_sequence; |
| 7767 __ j(not_zero, &normal_sequence); | 7504 __ j(not_zero, &normal_sequence); |
| 7768 | 7505 |
| 7769 // look at the first argument | 7506 // look at the first argument |
| 7770 __ mov(ecx, Operand(esp, kPointerSize)); | 7507 __ mov(ecx, Operand(esp, kPointerSize)); |
| 7771 __ test(ecx, ecx); | 7508 __ test(ecx, ecx); |
| 7772 __ j(zero, &normal_sequence); | 7509 __ j(zero, &normal_sequence); |
| 7773 | 7510 |
| 7774 // We are going to create a holey array, but our kind is non-holey. | 7511 // We are going to create a holey array, but our kind is non-holey. |
| 7775 // Fix kind and retry | 7512 // Fix kind and retry (only if we have an allocation site in the cell). |
| 7776 __ inc(edx); | 7513 __ inc(edx); |
| 7777 __ cmp(ebx, Immediate(undefined_sentinel)); | 7514 __ cmp(ebx, Immediate(undefined_sentinel)); |
| 7778 __ j(equal, &normal_sequence); | 7515 __ j(equal, &normal_sequence); |
| 7516 __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset)); |
| 7517 Handle<Map> allocation_site_map( |
| 7518 masm->isolate()->heap()->allocation_site_map(), |
| 7519 masm->isolate()); |
| 7520 __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map)); |
| 7521 __ j(not_equal, &normal_sequence); |
| 7779 | 7522 |
| 7780 // Save the resulting elements kind in type info | 7523 // Save the resulting elements kind in type info |
| 7781 __ SmiTag(edx); | 7524 __ SmiTag(edx); |
| 7782 __ mov(FieldOperand(ebx, kPointerSize), edx); | 7525 __ mov(FieldOperand(ecx, AllocationSite::kPayloadOffset), edx); |
| 7783 __ SmiUntag(edx); | 7526 __ SmiUntag(edx); |
| 7784 | 7527 |
| 7785 __ bind(&normal_sequence); | 7528 __ bind(&normal_sequence); |
| 7786 int last_index = GetSequenceIndexFromFastElementsKind( | 7529 int last_index = GetSequenceIndexFromFastElementsKind( |
| 7787 TERMINAL_FAST_ELEMENTS_KIND); | 7530 TERMINAL_FAST_ELEMENTS_KIND); |
| 7788 for (int i = 0; i <= last_index; ++i) { | 7531 for (int i = 0; i <= last_index; ++i) { |
| 7789 Label next; | 7532 Label next; |
| 7790 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7533 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7791 __ cmp(edx, kind); | 7534 __ cmp(edx, kind); |
| 7792 __ j(not_equal, &next); | 7535 __ j(not_equal, &next); |
| 7793 ArraySingleArgumentConstructorStub stub(kind); | 7536 ArraySingleArgumentConstructorStub stub(kind); |
| 7794 __ TailCallStub(&stub); | 7537 __ TailCallStub(&stub); |
| 7795 __ bind(&next); | 7538 __ bind(&next); |
| 7796 } | 7539 } |
| 7797 | 7540 |
| 7798 // If we reached this point there is a problem. | 7541 // If we reached this point there is a problem. |
| 7799 __ Abort("Unexpected ElementsKind in array constructor"); | 7542 __ Abort("Unexpected ElementsKind in array constructor"); |
| 7800 } | 7543 } |
| 7801 | 7544 |
| 7802 | 7545 |
| 7803 template<class T> | 7546 template<class T> |
| 7804 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 7547 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
| 7805 int to_index = GetSequenceIndexFromFastElementsKind( | 7548 int to_index = GetSequenceIndexFromFastElementsKind( |
| 7806 TERMINAL_FAST_ELEMENTS_KIND); | 7549 TERMINAL_FAST_ELEMENTS_KIND); |
| 7807 for (int i = 0; i <= to_index; ++i) { | 7550 for (int i = 0; i <= to_index; ++i) { |
| 7808 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7551 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7809 T stub(kind, false); | 7552 T stub(kind); |
| 7810 stub.GetCode(isolate)->set_is_pregenerated(true); | 7553 stub.GetCode(isolate)->set_is_pregenerated(true); |
| 7811 if (AllocationSiteInfo::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { | 7554 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { |
| 7812 T stub1(kind, true); | 7555 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); |
| 7813 stub1.GetCode(isolate)->set_is_pregenerated(true); | 7556 stub1.GetCode(isolate)->set_is_pregenerated(true); |
| 7814 } | 7557 } |
| 7815 } | 7558 } |
| 7816 } | 7559 } |
| 7817 | 7560 |
| 7818 | 7561 |
| 7819 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { | 7562 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 7820 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( | 7563 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( |
| 7821 isolate); | 7564 isolate); |
| 7822 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( | 7565 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7873 __ cmp(FieldOperand(ebx, 0), Immediate(cell_map)); | 7616 __ cmp(FieldOperand(ebx, 0), Immediate(cell_map)); |
| 7874 __ Assert(equal, "Expected property cell in register ebx"); | 7617 __ Assert(equal, "Expected property cell in register ebx"); |
| 7875 __ bind(&okay_here); | 7618 __ bind(&okay_here); |
| 7876 } | 7619 } |
| 7877 | 7620 |
| 7878 Label no_info, switch_ready; | 7621 Label no_info, switch_ready; |
| 7879 // Get the elements kind and case on that. | 7622 // Get the elements kind and case on that. |
| 7880 __ cmp(ebx, Immediate(undefined_sentinel)); | 7623 __ cmp(ebx, Immediate(undefined_sentinel)); |
| 7881 __ j(equal, &no_info); | 7624 __ j(equal, &no_info); |
| 7882 __ mov(edx, FieldOperand(ebx, Cell::kValueOffset)); | 7625 __ mov(edx, FieldOperand(ebx, Cell::kValueOffset)); |
| 7883 __ JumpIfNotSmi(edx, &no_info); | 7626 |
| 7627 // The type cell may have undefined in its value. |
| 7628 __ cmp(edx, Immediate(undefined_sentinel)); |
| 7629 __ j(equal, &no_info); |
| 7630 |
| 7631 // We should have an allocation site object |
| 7632 if (FLAG_debug_code) { |
| 7633 __ cmp(FieldOperand(edx, 0), |
| 7634 Immediate(Handle<Map>( |
| 7635 masm->isolate()->heap()->allocation_site_map()))); |
| 7636 __ Assert(equal, "Expected AllocationSite object in register edx"); |
| 7637 } |
| 7638 |
| 7639 __ mov(edx, FieldOperand(edx, AllocationSite::kPayloadOffset)); |
| 7884 __ SmiUntag(edx); | 7640 __ SmiUntag(edx); |
| 7885 __ jmp(&switch_ready); | 7641 __ jmp(&switch_ready); |
| 7886 __ bind(&no_info); | 7642 __ bind(&no_info); |
| 7887 __ mov(edx, Immediate(GetInitialFastElementsKind())); | 7643 __ mov(edx, Immediate(GetInitialFastElementsKind())); |
| 7888 __ bind(&switch_ready); | 7644 __ bind(&switch_ready); |
| 7889 | 7645 |
| 7890 if (argument_count_ == ANY) { | 7646 if (argument_count_ == ANY) { |
| 7891 Label not_zero_case, not_one_case; | 7647 Label not_zero_case, not_one_case; |
| 7892 __ test(eax, eax); | 7648 __ test(eax, eax); |
| 7893 __ j(not_zero, ¬_zero_case); | 7649 __ j(not_zero, ¬_zero_case); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7998 __ bind(&fast_elements_case); | 7754 __ bind(&fast_elements_case); |
| 7999 GenerateCase(masm, FAST_ELEMENTS); | 7755 GenerateCase(masm, FAST_ELEMENTS); |
| 8000 } | 7756 } |
| 8001 | 7757 |
| 8002 | 7758 |
| 8003 #undef __ | 7759 #undef __ |
| 8004 | 7760 |
| 8005 } } // namespace v8::internal | 7761 } } // namespace v8::internal |
| 8006 | 7762 |
| 8007 #endif // V8_TARGET_ARCH_IA32 | 7763 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |