Revision: 11012
Author:   [email protected]
Date:     Mon Mar 12 07:56:04 2012
Log:      Ensure consistency of Math.sqrt on Intel platforms.

BUG=
TEST=regress-sqrt.js

Review URL: https://chromiumcodereview.appspot.com/9690010
http://code.google.com/p/v8/source/detail?r=11012

Added:
 /branches/bleeding_edge/test/mjsunit/regress/regress-sqrt.js
Modified:
 /branches/bleeding_edge/src/arm/codegen-arm.cc
 /branches/bleeding_edge/src/codegen.h
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc
 /branches/bleeding_edge/src/mips/codegen-mips.cc
 /branches/bleeding_edge/src/platform-posix.cc
 /branches/bleeding_edge/src/platform-win32.cc
 /branches/bleeding_edge/src/platform.h
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/x64/codegen-x64.cc

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-sqrt.js Mon Mar 12 07:56:04 2012
@@ -0,0 +1,47 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+// Check that Math.sqrt returns the same value regardless of being
+// optimized or not.
+
+function f(x) {
+  return Math.sqrt(x);
+}
+
+var x = 7.0506280066499245e-233;
+
+var a = f(x);
+
+f(0.1);
+f(0.2);
+%OptimizeFunctionOnNextCall(f);
+
+var b = f(x);
+
+assertEquals(a, b);
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc      Mon Mar  5 00:17:16 2012
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc      Mon Mar 12 07:56:04 2012
@@ -37,8 +37,7 @@

 #define __ ACCESS_MASM(masm)

-TranscendentalFunction CreateTranscendentalFunction(
-    TranscendentalCache::Type type) {
+UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type) {
   switch (type) {
     case TranscendentalCache::SIN: return &sin;
     case TranscendentalCache::COS: return &cos;
@@ -50,6 +49,10 @@
 }


+UnaryMathFunction CreateSqrtFunction() {
+  return &sqrt;
+}
+
// -------------------------------------------------------------------------
 // Platform-specific RuntimeCallHelper functions.

=======================================
--- /branches/bleeding_edge/src/codegen.h       Mon Mar  5 00:17:16 2012
+++ /branches/bleeding_edge/src/codegen.h       Mon Mar 12 07:56:04 2012
@@ -87,10 +87,10 @@
// Results of the library implementation of transcendental functions may differ
 // from the one we use in our generated code.  Therefore we use the same
 // generated code both in runtime and compiled code.
-typedef double (*TranscendentalFunction)(double x);
-
-TranscendentalFunction CreateTranscendentalFunction(
-    TranscendentalCache::Type type);
+typedef double (*UnaryMathFunction)(double x);
+
+UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type);
+UnaryMathFunction CreateSqrtFunction();


 class ElementsTransitionGenerator : public AllStatic {
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Mon Mar 5 00:17:16 2012 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Mon Mar 12 07:56:04 2012
@@ -57,8 +57,7 @@
 #define __ masm.


-TranscendentalFunction CreateTranscendentalFunction(
-    TranscendentalCache::Type type) {
+UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type) {
   size_t actual_size;
   // Allocate buffer in executable space.
   byte* buffer = static_cast<byte*>(OS::Allocate(1 * KB,
@@ -99,7 +98,40 @@

   CPU::FlushICache(buffer, actual_size);
   OS::ProtectCode(buffer, actual_size);
-  return FUNCTION_CAST<TranscendentalFunction>(buffer);
+  return FUNCTION_CAST<UnaryMathFunction>(buffer);
+}
+
+
+UnaryMathFunction CreateSqrtFunction() {
+  size_t actual_size;
+  // Allocate buffer in executable space.
+  byte* buffer = static_cast<byte*>(OS::Allocate(1 * KB,
+                                                 &actual_size,
+                                                 true));
+  // If SSE2 is not available, we can use libc's implementation to ensure
+ // consistency since code by fullcodegen's calls into runtime in that case.
+  if (buffer == NULL || !CpuFeatures::IsSupported(SSE2)) return &sqrt;
+  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
+  // esp[1 * kPointerSize]: raw double input
+  // esp[0 * kPointerSize]: return address
+  // Move double input into registers.
+  {
+    CpuFeatures::Scope use_sse2(SSE2);
+    __ movdbl(xmm0, Operand(esp, 1 * kPointerSize));
+    __ sqrtsd(xmm0, xmm0);
+    __ movdbl(Operand(esp, 1 * kPointerSize), xmm0);
+    // Load result into floating point register as return value.
+    __ fld_d(Operand(esp, 1 * kPointerSize));
+    __ Ret();
+  }
+
+  CodeDesc desc;
+  masm.GetCode(&desc);
+  ASSERT(desc.reloc_size == 0);
+
+  CPU::FlushICache(buffer, actual_size);
+  OS::ProtectCode(buffer, actual_size);
+  return FUNCTION_CAST<UnaryMathFunction>(buffer);
 }


=======================================
--- /branches/bleeding_edge/src/mips/codegen-mips.cc Mon Mar 5 00:17:16 2012 +++ /branches/bleeding_edge/src/mips/codegen-mips.cc Mon Mar 12 07:56:04 2012
@@ -37,8 +37,7 @@

 #define __ ACCESS_MASM(masm)

-TranscendentalFunction CreateTranscendentalFunction(
-    TranscendentalCache::Type type) {
+UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type) {
   switch (type) {
     case TranscendentalCache::SIN: return &sin;
     case TranscendentalCache::COS: return &cos;
@@ -50,6 +49,10 @@
 }


+UnaryMathFunction CreateSqrtFunction() {
+  return &sqrt;
+}
+
// -------------------------------------------------------------------------
 // Platform-specific RuntimeCallHelper functions.

=======================================
--- /branches/bleeding_edge/src/platform-posix.cc       Mon Mar 12 06:56:56 2012
+++ /branches/bleeding_edge/src/platform-posix.cc       Mon Mar 12 07:56:04 2012
@@ -127,27 +127,27 @@
 }


-static Mutex* transcendental_function_mutex = OS::CreateMutex();
-
-#define TRANSCENDENTAL_FUNCTION(name, type)                   \
-static TranscendentalFunction fast_##name##_function = NULL;  \
-double fast_##name(double x) {                                \
-  if (fast_##name##_function == NULL) {                       \
-    ScopedLock lock(transcendental_function_mutex);           \
-    TranscendentalFunction temp =                             \
-        CreateTranscendentalFunction(type);                   \
-    MemoryBarrier();                                          \
-    fast_##name##_function = temp;                            \
-  }                                                           \
-  return (*fast_##name##_function)(x);                        \
+static Mutex* math_function_mutex = OS::CreateMutex();
+
+#define UNARY_MATH_FUNCTION(name, generator)             \
+static UnaryMathFunction fast_##name##_function = NULL;  \
+double fast_##name(double x) {                           \
+  if (fast_##name##_function == NULL) {                  \
+    ScopedLock lock(math_function_mutex);                \
+    UnaryMathFunction temp = generator;                  \
+    MemoryBarrier();                                     \
+    fast_##name##_function = temp;                       \
+  }                                                      \
+  return (*fast_##name##_function)(x);                   \
 }

-TRANSCENDENTAL_FUNCTION(sin, TranscendentalCache::SIN)
-TRANSCENDENTAL_FUNCTION(cos, TranscendentalCache::COS)
-TRANSCENDENTAL_FUNCTION(tan, TranscendentalCache::TAN)
-TRANSCENDENTAL_FUNCTION(log, TranscendentalCache::LOG)
-
-#undef TRANSCENDENTAL_FUNCTION
+UNARY_MATH_FUNCTION(sin, CreateTranscendentalFunction(TranscendentalCache::SIN)) +UNARY_MATH_FUNCTION(cos, CreateTranscendentalFunction(TranscendentalCache::COS)) +UNARY_MATH_FUNCTION(tan, CreateTranscendentalFunction(TranscendentalCache::TAN)) +UNARY_MATH_FUNCTION(log, CreateTranscendentalFunction(TranscendentalCache::LOG))
+UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction())
+
+#undef MATH_FUNCTION


 double OS::nan_value() {
=======================================
--- /branches/bleeding_edge/src/platform-win32.cc       Mon Mar 12 07:41:59 2012
+++ /branches/bleeding_edge/src/platform-win32.cc       Mon Mar 12 07:56:04 2012
@@ -208,27 +208,27 @@
 #endif  // _WIN64


-static Mutex* transcendental_function_mutex = OS::CreateMutex();
-
-#define TRANSCENDENTAL_FUNCTION(name, type)                   \
-static TranscendentalFunction fast_##name##_function = NULL;  \
-double fast_##name(double x) {                                \
-  if (fast_##name##_function == NULL) {                       \
-    ScopedLock lock(transcendental_function_mutex);           \
-    TranscendentalFunction temp =                             \
-        CreateTranscendentalFunction(type);                   \
-    MemoryBarrier();                                          \
-    fast_##name##_function = temp;                            \
-  }                                                           \
-  return (*fast_##name##_function)(x);                        \
+static Mutex* math_function_mutex = OS::CreateMutex();
+
+#define UNARY_MATH_FUNCTION(name, generator)             \
+static UnaryMathFunction fast_##name##_function = NULL;  \
+double fast_##name(double x) {                           \
+  if (fast_##name##_function == NULL) {                  \
+    ScopedLock lock(math_function_mutex);                \
+    UnaryMathFunction temp = generator;                  \
+    MemoryBarrier();                                     \
+    fast_##name##_function = temp;                       \
+  }                                                      \
+  return (*fast_##name##_function)(x);                   \
 }

-TRANSCENDENTAL_FUNCTION(sin, TranscendentalCache::SIN)
-TRANSCENDENTAL_FUNCTION(cos, TranscendentalCache::COS)
-TRANSCENDENTAL_FUNCTION(tan, TranscendentalCache::TAN)
-TRANSCENDENTAL_FUNCTION(log, TranscendentalCache::LOG)
-
-#undef TRANSCENDENTAL_FUNCTION
+UNARY_MATH_FUNCTION(sin, CreateTranscendentalFunction(TranscendentalCache::SIN)) +UNARY_MATH_FUNCTION(cos, CreateTranscendentalFunction(TranscendentalCache::COS)) +UNARY_MATH_FUNCTION(tan, CreateTranscendentalFunction(TranscendentalCache::TAN)) +UNARY_MATH_FUNCTION(log, CreateTranscendentalFunction(TranscendentalCache::LOG))
+UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction())
+
+#undef MATH_FUNCTION


// ----------------------------------------------------------------------------
=======================================
--- /branches/bleeding_edge/src/platform.h      Mon Mar 12 06:56:56 2012
+++ /branches/bleeding_edge/src/platform.h      Mon Mar 12 07:56:04 2012
@@ -102,6 +102,7 @@
 double fast_cos(double input);
 double fast_tan(double input);
 double fast_log(double input);
+double fast_sqrt(double input);

 // Forward declarations.
 class Socket;
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Mon Mar 12 05:49:41 2012
+++ /branches/bleeding_edge/src/runtime.cc      Mon Mar 12 07:56:04 2012
@@ -7441,9 +7441,11 @@
   if (y == y_int) {
     result = power_double_int(x, y_int);  // Returns 1 if exponent is 0.
   } else  if (y == 0.5) {
- result = (isinf(x)) ? V8_INFINITY : sqrt(x + 0.0); // Convert -0 to +0.
+    result = (isinf(x)) ? V8_INFINITY
+                        : fast_sqrt(x + 0.0);  // Convert -0 to +0.
   } else if (y == -0.5) {
-    result = (isinf(x)) ? 0 : 1.0 / sqrt(x + 0.0);  // Convert -0 to +0.
+    result = (isinf(x)) ? 0
+                        : 1.0 / fast_sqrt(x + 0.0);  // Convert -0 to +0.
   } else {
     result = power_double_double(x, y);
   }
@@ -7529,7 +7531,7 @@
   isolate->counters()->math_sqrt()->Increment();

   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
-  return isolate->heap()->AllocateHeapNumber(sqrt(x));
+  return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
 }


=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Thu Mar  8 07:46:23 2012
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Mon Mar 12 07:56:04 2012
@@ -55,8 +55,7 @@
 #define __ masm.


-TranscendentalFunction CreateTranscendentalFunction(
-    TranscendentalCache::Type type) {
+UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type) {
   size_t actual_size;
   // Allocate buffer in executable space.
   byte* buffer = static_cast<byte*>(OS::Allocate(1 * KB,
@@ -96,7 +95,31 @@

   CPU::FlushICache(buffer, actual_size);
   OS::ProtectCode(buffer, actual_size);
-  return FUNCTION_CAST<TranscendentalFunction>(buffer);
+  return FUNCTION_CAST<UnaryMathFunction>(buffer);
+}
+
+
+UnaryMathFunction CreateSqrtFunction() {
+  size_t actual_size;
+  // Allocate buffer in executable space.
+  byte* buffer = static_cast<byte*>(OS::Allocate(1 * KB,
+                                                 &actual_size,
+                                                 true));
+  if (buffer == NULL) return &sqrt;
+
+  MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
+  // xmm0: raw double input.
+  // Move double input into registers.
+  __ sqrtsd(xmm0, xmm0);
+  __ Ret();
+
+  CodeDesc desc;
+  masm.GetCode(&desc);
+  ASSERT(desc.reloc_size == 0);
+
+  CPU::FlushICache(buffer, actual_size);
+  OS::ProtectCode(buffer, actual_size);
+  return FUNCTION_CAST<UnaryMathFunction>(buffer);
 }


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to