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

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 8831008: Tweaks on Math.pow (ia32 and x64). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years 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/assembler.cc ('k') | src/runtime.cc » ('j') | src/runtime.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/assembler.cc ('k') | src/runtime.cc » ('j') | src/runtime.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698