OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2941 CpuFeatures::Scope use_sse2(SSE2); | 2941 CpuFeatures::Scope use_sse2(SSE2); |
2942 Factory* factory = masm->isolate()->factory(); | 2942 Factory* factory = masm->isolate()->factory(); |
2943 const Register exponent = eax; | 2943 const Register exponent = eax; |
2944 const Register base = edx; | 2944 const Register base = edx; |
2945 const Register scratch = ecx; | 2945 const Register scratch = ecx; |
2946 const XMMRegister double_result = xmm3; | 2946 const XMMRegister double_result = xmm3; |
2947 const XMMRegister double_base = xmm2; | 2947 const XMMRegister double_base = xmm2; |
2948 const XMMRegister double_exponent = xmm1; | 2948 const XMMRegister double_exponent = xmm1; |
2949 const XMMRegister double_scratch = xmm4; | 2949 const XMMRegister double_scratch = xmm4; |
2950 | 2950 |
2951 Label double_int_runtime, generic_runtime, done; | 2951 Label call_runtime, done, exponent_not_smi, int_exponent; |
2952 Label exponent_not_smi, int_exponent; | |
2953 | 2952 |
2954 // Save 1 in double_result - we need this several times later on. | 2953 // Save 1 in double_result - we need this several times later on. |
2955 __ mov(scratch, Immediate(1)); | 2954 __ mov(scratch, Immediate(1)); |
2956 __ cvtsi2sd(double_result, scratch); | 2955 __ cvtsi2sd(double_result, scratch); |
2957 | 2956 |
2958 if (exponent_type_ == ON_STACK) { | 2957 if (exponent_type_ == ON_STACK) { |
2959 Label base_is_smi, unpack_exponent; | 2958 Label base_is_smi, unpack_exponent; |
2960 // The exponent and base are supplied as arguments on the stack. | 2959 // The exponent and base are supplied as arguments on the stack. |
2961 // This can only happen if the stub is called from non-optimized code. | 2960 // This can only happen if the stub is called from non-optimized code. |
2962 // Load input parameters from stack. | 2961 // Load input parameters from stack. |
2963 __ mov(base, Operand(esp, 2 * kPointerSize)); | 2962 __ mov(base, Operand(esp, 2 * kPointerSize)); |
2964 __ mov(exponent, Operand(esp, 1 * kPointerSize)); | 2963 __ mov(exponent, Operand(esp, 1 * kPointerSize)); |
2965 | 2964 |
2966 __ JumpIfSmi(base, &base_is_smi, Label::kNear); | 2965 __ JumpIfSmi(base, &base_is_smi, Label::kNear); |
2967 __ cmp(FieldOperand(base, HeapObject::kMapOffset), | 2966 __ cmp(FieldOperand(base, HeapObject::kMapOffset), |
2968 factory->heap_number_map()); | 2967 factory->heap_number_map()); |
2969 __ j(not_equal, &generic_runtime); | 2968 __ j(not_equal, &call_runtime); |
2970 | 2969 |
2971 __ movdbl(double_base, FieldOperand(base, HeapNumber::kValueOffset)); | 2970 __ movdbl(double_base, FieldOperand(base, HeapNumber::kValueOffset)); |
2972 __ jmp(&unpack_exponent, Label::kNear); | 2971 __ jmp(&unpack_exponent, Label::kNear); |
2973 | 2972 |
2974 __ bind(&base_is_smi); | 2973 __ bind(&base_is_smi); |
2975 __ SmiUntag(base); | 2974 __ SmiUntag(base); |
2976 __ cvtsi2sd(double_base, base); | 2975 __ cvtsi2sd(double_base, base); |
2977 | 2976 |
2978 __ bind(&unpack_exponent); | 2977 __ bind(&unpack_exponent); |
2979 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 2978 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
2980 __ SmiUntag(exponent); | 2979 __ SmiUntag(exponent); |
2981 __ jmp(&int_exponent); | 2980 __ jmp(&int_exponent); |
2982 | 2981 |
2983 __ bind(&exponent_not_smi); | 2982 __ bind(&exponent_not_smi); |
2984 __ cmp(FieldOperand(exponent, HeapObject::kMapOffset), | 2983 __ cmp(FieldOperand(exponent, HeapObject::kMapOffset), |
2985 factory->heap_number_map()); | 2984 factory->heap_number_map()); |
2986 __ j(not_equal, &generic_runtime); | 2985 __ j(not_equal, &call_runtime); |
2987 __ movdbl(double_exponent, | 2986 __ movdbl(double_exponent, |
2988 FieldOperand(exponent, HeapNumber::kValueOffset)); | 2987 FieldOperand(exponent, HeapNumber::kValueOffset)); |
2989 } else if (exponent_type_ == TAGGED) { | 2988 } else if (exponent_type_ == TAGGED) { |
2990 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 2989 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
2991 __ SmiUntag(exponent); | 2990 __ SmiUntag(exponent); |
2992 __ jmp(&int_exponent); | 2991 __ jmp(&int_exponent); |
2993 | 2992 |
2994 __ bind(&exponent_not_smi); | 2993 __ bind(&exponent_not_smi); |
2995 __ movdbl(double_exponent, | 2994 __ movdbl(double_exponent, |
2996 FieldOperand(exponent, HeapNumber::kValueOffset)); | 2995 FieldOperand(exponent, HeapNumber::kValueOffset)); |
2997 } | 2996 } |
2998 | 2997 |
2999 if (exponent_type_ != INTEGER) { | 2998 if (exponent_type_ != INTEGER) { |
3000 Label fast_power; | 2999 Label fast_power; |
3001 // Detect integer exponents stored as double. | 3000 // Detect integer exponents stored as double. |
3002 __ cvttsd2si(exponent, Operand(double_exponent)); | 3001 __ cvttsd2si(exponent, Operand(double_exponent)); |
3003 // Skip to runtime if possibly NaN (indicated by the indefinite integer). | 3002 // Skip to runtime if possibly NaN (indicated by the indefinite integer). |
3004 __ cmp(exponent, Immediate(0x80000000u)); | 3003 __ cmp(exponent, Immediate(0x80000000u)); |
3005 __ j(equal, &generic_runtime); | 3004 __ j(equal, &call_runtime); |
3006 __ cvtsi2sd(double_scratch, exponent); | 3005 __ cvtsi2sd(double_scratch, exponent); |
3007 // Already ruled out NaNs for exponent. | 3006 // Already ruled out NaNs for exponent. |
3008 __ ucomisd(double_exponent, double_scratch); | 3007 __ ucomisd(double_exponent, double_scratch); |
3009 __ j(equal, &int_exponent); | 3008 __ j(equal, &int_exponent); |
3010 | 3009 |
3011 if (exponent_type_ == ON_STACK) { | 3010 if (exponent_type_ == ON_STACK) { |
3012 // Detect square root case. Crankshaft detects constant +/-0.5 at | 3011 // Detect square root case. Crankshaft detects constant +/-0.5 at |
3013 // compile time and uses DoMathPowHalf instead. We then skip this check | 3012 // compile time and uses DoMathPowHalf instead. We then skip this check |
3014 // for non-constant cases of +/-0.5 as these hardly occur. | 3013 // for non-constant cases of +/-0.5 as these hardly occur. |
3015 Label continue_sqrt, continue_rsqrt, not_plus_half; | 3014 Label continue_sqrt, continue_rsqrt, not_plus_half; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3112 __ test_b(eax, 0x5F); // We check for all but precision exception. | 3111 __ test_b(eax, 0x5F); // We check for all but precision exception. |
3113 __ j(not_zero, &fast_power_failed, Label::kNear); | 3112 __ j(not_zero, &fast_power_failed, Label::kNear); |
3114 __ fstp_d(Operand(esp, 0)); | 3113 __ fstp_d(Operand(esp, 0)); |
3115 __ movdbl(double_result, Operand(esp, 0)); | 3114 __ movdbl(double_result, Operand(esp, 0)); |
3116 __ add(esp, Immediate(kDoubleSize)); | 3115 __ add(esp, Immediate(kDoubleSize)); |
3117 __ jmp(&done); | 3116 __ jmp(&done); |
3118 | 3117 |
3119 __ bind(&fast_power_failed); | 3118 __ bind(&fast_power_failed); |
3120 __ fninit(); | 3119 __ fninit(); |
3121 __ add(esp, Immediate(kDoubleSize)); | 3120 __ add(esp, Immediate(kDoubleSize)); |
3122 __ jmp(&generic_runtime); | 3121 __ jmp(&call_runtime); |
3123 } | 3122 } |
3124 | 3123 |
3125 // Calculate power with integer exponent. | 3124 // Calculate power with integer exponent. |
3126 __ bind(&int_exponent); | 3125 __ bind(&int_exponent); |
3127 const XMMRegister double_scratch2 = double_exponent; | 3126 const XMMRegister double_scratch2 = double_exponent; |
3128 __ mov(scratch, exponent); // Back up exponent. | 3127 __ mov(scratch, exponent); // Back up exponent. |
3129 __ movsd(double_scratch, double_base); // Back up base. | 3128 __ movsd(double_scratch, double_base); // Back up base. |
3130 __ movsd(double_scratch2, double_result); // Load double_exponent with 1. | 3129 __ movsd(double_scratch2, double_result); // Load double_exponent with 1. |
3131 | 3130 |
3132 // Get absolute value of exponent. | 3131 // Get absolute value of exponent. |
3133 Label while_true, no_multiply; | 3132 Label no_neg, while_true, no_multiply; |
3134 const uint32_t kClearSignBitMask = 0x7FFFFFFF; | 3133 __ test(scratch, scratch); |
3135 __ and_(exponent, Immediate(kClearSignBitMask)); | 3134 __ j(positive, &no_neg, Label::kNear); |
Yang
2011/12/07 15:07:50
This is a screw-up I did earlier. Obviously this c
| |
3135 __ neg(scratch); | |
3136 __ bind(&no_neg); | |
3136 | 3137 |
3137 __ bind(&while_true); | 3138 __ bind(&while_true); |
3138 __ shr(exponent, 1); | 3139 __ shr(scratch, 1); |
3139 __ j(not_carry, &no_multiply, Label::kNear); | 3140 __ j(not_carry, &no_multiply, Label::kNear); |
3140 __ mulsd(double_result, double_base); | 3141 __ mulsd(double_result, double_scratch); |
3141 __ bind(&no_multiply); | 3142 __ bind(&no_multiply); |
3142 | 3143 |
3143 __ mulsd(double_base, double_base); | 3144 __ mulsd(double_scratch, double_scratch); |
3144 __ j(not_zero, &while_true); | 3145 __ j(not_zero, &while_true); |
3145 | 3146 |
3146 // scratch has the original value of the exponent - if the exponent is | 3147 // scratch has the original value of the exponent - if the exponent is |
3147 // negative, return 1/result. | 3148 // negative, return 1/result. |
3148 __ test(scratch, scratch); | 3149 __ test(exponent, exponent); |
3149 __ j(positive, &done); | 3150 __ j(positive, &done); |
3150 __ divsd(double_scratch2, double_result); | 3151 __ divsd(double_scratch2, double_result); |
3151 __ movsd(double_result, double_scratch2); | 3152 __ movsd(double_result, double_scratch2); |
3152 // Test whether result is zero. Bail out to check for subnormal result. | 3153 // Test whether result is zero. Bail out to check for subnormal result. |
3153 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. | 3154 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. |
3154 __ xorps(double_scratch2, double_scratch2); | 3155 __ xorps(double_scratch2, double_scratch2); |
3155 __ ucomisd(double_scratch2, double_result); // Result cannot be NaN. | 3156 __ ucomisd(double_scratch2, double_result); // Result cannot be NaN. |
3156 __ j(equal, &double_int_runtime); | 3157 __ j(not_equal, &done); |
3158 __ cvtsi2sd(double_exponent, exponent); | |
3157 | 3159 |
3158 // Returning or bailing out. | 3160 // Returning or bailing out. |
3161 Counters* counters = masm->isolate()->counters(); | |
3159 if (exponent_type_ == ON_STACK) { | 3162 if (exponent_type_ == ON_STACK) { |
3163 // The arguments are still on the stack. | |
3164 __ bind(&call_runtime); | |
3165 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); | |
3166 | |
3160 // The stub is called from non-optimized code, which expects the result | 3167 // The stub is called from non-optimized code, which expects the result |
3161 // as heap number in exponent. | 3168 // as heap number in exponent. |
3162 __ bind(&done); | 3169 __ bind(&done); |
3163 __ AllocateHeapNumber(exponent, scratch, base, &generic_runtime); | 3170 __ AllocateHeapNumber(eax, scratch, base, &call_runtime); |
3164 __ movdbl(FieldOperand(exponent, HeapNumber::kValueOffset), double_result); | 3171 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), double_result); |
3172 __ IncrementCounter(counters->math_pow(), 1); | |
3165 __ ret(2 * kPointerSize); | 3173 __ ret(2 * kPointerSize); |
3166 | |
3167 // The arguments are still on the stack. | |
3168 __ bind(&generic_runtime); | |
3169 __ bind(&double_int_runtime); | |
3170 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); | |
3171 } else { | 3174 } else { |
3172 __ jmp(&done); | 3175 __ bind(&call_runtime); |
3173 | |
3174 Label return_from_runtime; | |
3175 __ bind(&generic_runtime); | |
3176 { | 3176 { |
3177 AllowExternalCallThatCantCauseGC scope(masm); | 3177 AllowExternalCallThatCantCauseGC scope(masm); |
3178 __ PrepareCallCFunction(4, exponent); | 3178 __ PrepareCallCFunction(4, scratch); |
3179 __ movdbl(Operand(esp, 0 * kDoubleSize), double_base); | 3179 __ movdbl(Operand(esp, 0 * kDoubleSize), double_base); |
3180 __ movdbl(Operand(esp, 1 * kDoubleSize), double_exponent); | 3180 __ movdbl(Operand(esp, 1 * kDoubleSize), double_exponent); |
3181 __ CallCFunction( | 3181 __ CallCFunction( |
3182 ExternalReference::power_double_double_function(masm->isolate()), 4); | 3182 ExternalReference::power_double_double_function(masm->isolate()), 4); |
3183 } | 3183 } |
3184 __ jmp(&return_from_runtime, Label::kNear); | |
3185 | |
3186 __ bind(&double_int_runtime); | |
3187 { | |
3188 AllowExternalCallThatCantCauseGC scope(masm); | |
3189 __ PrepareCallCFunction(4, exponent); | |
3190 __ movdbl(Operand(esp, 0 * kDoubleSize), double_scratch); | |
3191 __ mov(Operand(esp, 1 * kDoubleSize), scratch); | |
3192 __ CallCFunction( | |
3193 ExternalReference::power_double_int_function(masm->isolate()), 4); | |
3194 } | |
3195 | |
3196 __ bind(&return_from_runtime); | |
3197 // Return value is in st(0) on ia32. | 3184 // Return value is in st(0) on ia32. |
3198 // Store it into the (fixed) result register. | 3185 // Store it into the (fixed) result register. |
3199 __ sub(esp, Immediate(kDoubleSize)); | 3186 __ sub(esp, Immediate(kDoubleSize)); |
3200 __ fstp_d(Operand(esp, 0)); | 3187 __ fstp_d(Operand(esp, 0)); |
3201 __ movdbl(double_result, Operand(esp, 0)); | 3188 __ movdbl(double_result, Operand(esp, 0)); |
3202 __ add(esp, Immediate(kDoubleSize)); | 3189 __ add(esp, Immediate(kDoubleSize)); |
3203 | 3190 |
3204 __ bind(&done); | 3191 __ bind(&done); |
3192 __ IncrementCounter(counters->math_pow(), 1); | |
3205 __ ret(0); | 3193 __ ret(0); |
3206 } | 3194 } |
3207 } | 3195 } |
3208 | 3196 |
3209 | 3197 |
3210 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 3198 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
3211 // The key is in edx and the parameter count is in eax. | 3199 // The key is in edx and the parameter count is in eax. |
3212 | 3200 |
3213 // The displacement is used for skipping the frame pointer on the | 3201 // The displacement is used for skipping the frame pointer on the |
3214 // stack. It is the offset of the last parameter (if any) relative | 3202 // stack. It is the offset of the last parameter (if any) relative |
(...skipping 4067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7282 false); | 7270 false); |
7283 __ pop(edx); | 7271 __ pop(edx); |
7284 __ ret(0); | 7272 __ ret(0); |
7285 } | 7273 } |
7286 | 7274 |
7287 #undef __ | 7275 #undef __ |
7288 | 7276 |
7289 } } // namespace v8::internal | 7277 } } // namespace v8::internal |
7290 | 7278 |
7291 #endif // V8_TARGET_ARCH_IA32 | 7279 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |