Fixing mozilla test failures regarding Math.pow.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 6 Dec 2011 13:14:46 +0000 (13:14 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 6 Dec 2011 13:14:46 +0000 (13:14 +0000)
BUG=
TEST=

Review URL: http://codereview.chromium.org/8820011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10177 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ia32/code-stubs-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/x64/lithium-codegen-x64.cc
test/mjsunit/math-pow.js

index aa70c5f..6bea2dc 100644 (file)
@@ -2997,7 +2997,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
     __ cmp(eax, Immediate(0x80000000u));
     __ j(equal, &generic_runtime);
     __ cvtsi2sd(xmm4, eax);
-    __ ucomisd(xmm2, xmm4);
+    __ ucomisd(xmm2, xmm4);  // Already ruled out NaNs for exponent.
     __ j(equal, &int_exponent);
 
     if (exponent_type_ == ON_STACK) {
@@ -3011,7 +3011,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
       __ movd(xmm4, ecx);
       __ cvtss2sd(xmm4, xmm4);
       // xmm4 now has 0.5.
-      __ ucomisd(xmm4, xmm2);
+      __ ucomisd(xmm4, xmm2);  // Already ruled out NaNs for exponent.
       __ j(not_equal, &not_plus_half, Label::kNear);
 
       // Calculates square root of base.  Check for the special case of
@@ -3022,7 +3022,10 @@ void MathPowStub::Generate(MacroAssembler* masm) {
       __ movd(xmm4, ecx);
       __ cvtss2sd(xmm4, xmm4);
       __ ucomisd(xmm1, xmm4);
+      // Comparing -Infinity with NaN results in "unordered", which sets the
+      // zero flag as if both were equal.  However, it also sets the carry flag.
       __ j(not_equal, &continue_sqrt, Label::kNear);
+      __ j(carry, &continue_sqrt, Label::kNear);
 
       // Set result to Infinity in the special case.
       __ xorps(xmm3, xmm3);
@@ -3042,7 +3045,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
       // Since xmm3 is 1 and xmm4 is 0.5 this is simply xmm4 - xmm3.
       __ subsd(xmm4, xmm3);
       // xmm4 now has -0.5.
-      __ ucomisd(xmm4, xmm2);
+      __ ucomisd(xmm4, xmm2);  // Already ruled out NaNs for exponent.
       __ j(not_equal, &fast_power, Label::kNear);
 
       // Calculates reciprocal of square root of base.  Check for the special
@@ -3053,7 +3056,10 @@ void MathPowStub::Generate(MacroAssembler* masm) {
       __ movd(xmm4, ecx);
       __ cvtss2sd(xmm4, xmm4);
       __ ucomisd(xmm1, xmm4);
+      // Comparing -Infinity with NaN results in "unordered", which sets the
+      // zero flag as if both were equal.  However, it also sets the carry flag.
       __ j(not_equal, &continue_rsqrt, Label::kNear);
+      __ j(carry, &continue_rsqrt, Label::kNear);
 
       // Set result to 0 in the special case.
       __ xorps(xmm3, xmm3);
@@ -3143,7 +3149,7 @@ void MathPowStub::Generate(MacroAssembler* masm) {
   // Test whether result is zero.  Bail out to check for subnormal result.
   // Due to subnormals, x^-y == (1/x)^y does not hold in all cases.
   __ xorps(xmm2, xmm2);
-  __ ucomisd(xmm2, xmm3);
+  __ ucomisd(xmm2, xmm3);  // Result cannot be NaN.
   __ j(equal, &double_int_runtime);
 
   // Returning or bailing out.
index 804a9d1..965dc44 100644 (file)
@@ -2970,7 +2970,10 @@ void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
   __ movd(xmm_scratch, scratch);
   __ cvtss2sd(xmm_scratch, xmm_scratch);
   __ ucomisd(input_reg, xmm_scratch);
+  // Comparing -Infinity with NaN results in "unordered", which sets the
+  // zero flag as if both were equal.  However, it also sets the carry flag.
   __ j(not_equal, &sqrt, Label::kNear);
+  __ j(carry, &sqrt, Label::kNear);
   // If input is -Infinity, return Infinity.
   __ xorps(input_reg, input_reg);
   __ subsd(input_reg, xmm_scratch);
index 32c122c..c0d73d8 100644 (file)
@@ -2861,7 +2861,10 @@ void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
   __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000), RelocInfo::NONE);
   __ movq(xmm_scratch, kScratchRegister);
   __ ucomisd(xmm_scratch, input_reg);
+  // Comparing -Infinity with NaN results in "unordered", which sets the
+  // zero flag as if both were equal.  However, it also sets the carry flag.
   __ j(not_equal, &sqrt, Label::kNear);
+  __ j(carry, &sqrt, Label::kNear);
   // If input is -Infinity, return Infinity.
   __ xorps(input_reg, input_reg);
   __ subsd(input_reg, xmm_scratch);
index 96d4eb4..e2b2c78 100644 (file)
@@ -140,6 +140,20 @@ function test() {
   assertEquals(NaN, Math.pow(-16, 0.5));
   assertEquals(0.25, Math.pow(16, -0.5));
   assertEquals(NaN, Math.pow(-16, -0.5));
+  
+  // Tests from Mozilla 15.8.2.13.
+  assertEquals(2, Math.pow.length);
+  assertEquals(NaN, Math.pow());
+  assertEquals(1, Math.pow(null, null));
+  assertEquals(NaN, Math.pow(void 0, void 0));
+  assertEquals(1, Math.pow(true, false));
+  assertEquals(0, Math.pow(false, true));
+  assertEquals(Infinity, Math.pow(-Infinity, Infinity));
+  assertEquals(0, Math.pow(-Infinity, -Infinity));
+  assertEquals(1, Math.pow(0, 0));
+  assertEquals(0, Math.pow(0, Infinity));
+  assertEquals(NaN, Math.pow(NaN, 0.5));
+  assertEquals(NaN, Math.pow(NaN, -0.5));
 
   // Tests from Sputnik S8.5_A13_T1.
   assertTrue(