Efficient Implementation of JSDOUBLE_IS_INT using SSE2 (original patch by Moh Haghighat/Intel, bug 530896, r=dvander)

This commit is contained in:
Andreas Gal 2009-12-17 14:03:45 -08:00
parent f02162a25b
commit 4c8dc43072
6 changed files with 127 additions and 46 deletions

View File

@ -2488,6 +2488,39 @@ if test -z "$COMPILE_ENVIRONMENT"; then
SKIP_LIBRARY_CHECKS=1
fi
dnl Configure SSE2 support
HAVE_SSE2=
MUST_DETECT_SSE2=
case "$target" in
i?86-*)
HAVE_SSE2=1
case "$target_os" in
darwin*)
;;
*)
MUST_DETECT_SSE2=1
;;
esac
;;
x86_64*-*)e
HAVE_SSE2=1
;;
esac
if test "$HAVE_SSE2"; then
AC_DEFINE(HAVE_SSE2)
if test "$GNU_CC"; then
CFLAGS="$CFLAGS -msse2"
fi
if test "$GNU_CXX"; then
CXXFLAGS="$CXXFLAGS -msse2"
fi
if test "$MUST_DETECT_SSE2"; then
AC_DEFINE(MUST_DETECT_SSE2)
fi
fi
dnl Configure JIT support
case "$target" in

View File

@ -825,6 +825,9 @@ JSRuntime::~JSRuntime()
JS_PUBLIC_API(JSRuntime *)
JS_NewRuntime(uint32 maxbytes)
{
#ifdef MUST_DETECT_SSE2
js_use_SSE2 = js_DetectSSE2();
#endif
#ifdef DEBUG
if (!js_NewRuntimeWasCalled) {
/*

View File

@ -47,6 +47,13 @@
#ifdef SOLARIS
#include <ieeefp.h>
#endif
#ifdef HAVE_SSE2
#ifdef __GNUC__
#include <xmmintrin.h>
#else
#include <emmintrin.h>
#endif
#endif
/*
* JS number (IEEE double) interface.
@ -131,9 +138,32 @@ JSDOUBLE_IS_NEGZERO(jsdouble d)
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
#define JSDOUBLE_HI32_MANTMASK 0x000fffff
static inline int
/* Older versions of MSVC don't have _mm_castpd_si128. */
#if defined(HAVE_SSE2) && defined (_MSC_VER) && (_MSC_VER < 1500)
static inline __m128i
_mm_castpd_si128(__m128d v) {
return *(__m128i *)&v;
}
#endif
static inline bool
JSDOUBLE_IS_INT(jsdouble d, jsint& i)
{
#ifdef HAVE_SSE2
if (js_use_SSE2) {
__m128d xd = _mm_set_sd(d); /* load double into an XMM register */
int ii = _mm_cvtsd_si32(xd); /* Inf/NaN & large |d| convert to -2^31 */
__m128d xdi = _mm_setzero_pd(); /* kill dependencies for the top half of xdi */
xdi = _mm_cvtsi32_sd(xdi, ii); /* convert the result back to double */
__m128i xcmp = _mm_cmpeq_epi32(_mm_castpd_si128(xd), /* 32-bit integer bit-to-bit */
_mm_castpd_si128(xdi)); /* comparison */
int m = _mm_movemask_epi8(xcmp); /* extract significant bits of compare */
if ((m & 0xff) != 0xff) /* result is non-integer? */
return false;
i = ii;
return true;
}
#endif
if (JSDOUBLE_IS_NEGZERO(d))
return false;
return d == (i = jsint(d));

View File

@ -74,6 +74,7 @@
#include "jsscript.h"
#include "jsstaticcheck.h"
#include "jstracer.h"
#include "jsutil.h"
#include "jsxml.h"
#include "jsatominlines.h"
@ -7266,50 +7267,6 @@ js_AbortRecording(JSContext* cx, const char* reason)
#endif
}
#if defined NANOJIT_IA32
static bool
CheckForSSE2()
{
char *c = getenv("X86_FORCE_SSE2");
if (c)
return (!strcmp(c, "true") ||
!strcmp(c, "1") ||
!strcmp(c, "yes"));
int features = 0;
#if defined _MSC_VER
__asm
{
pushad
mov eax, 1
cpuid
mov features, edx
popad
}
#elif defined __GNUC__
asm("xchg %%esi, %%ebx\n" /* we can't clobber ebx on gcc (PIC register) */
"mov $0x01, %%eax\n"
"cpuid\n"
"mov %%edx, %0\n"
"xchg %%esi, %%ebx\n"
: "=m" (features)
: /* We have no inputs */
: "%eax", "%esi", "%ecx", "%edx"
);
#elif defined __SUNPRO_C || defined __SUNPRO_CC
asm("push %%ebx\n"
"mov $0x01, %%eax\n"
"cpuid\n"
"pop %%ebx\n"
: "=d" (features)
: /* We have no inputs */
: "%eax", "%ecx"
);
#endif
return (features & (1<<26)) != 0;
}
#endif
#if defined(NANOJIT_ARM)
#if defined(_MSC_VER) && defined(WINCE)
@ -7571,7 +7528,7 @@ js_InitJIT(JSTraceMonitor *tm)
if (!did_we_check_processor_features) {
#if defined NANOJIT_IA32
avmplus::AvmCore::config.use_cmov =
avmplus::AvmCore::config.sse2 = CheckForSSE2();
avmplus::AvmCore::config.sse2 = js_use_SSE2;
avmplus::AvmCore::config.fixed_esp = true;
#endif
#if defined NANOJIT_ARM

View File

@ -43,6 +43,7 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jstypes.h"
#include "jsstdint.h"
#include "jsutil.h"
@ -71,6 +72,52 @@ JS_PUBLIC_API(void) JS_Assert(const char *s, const char *file, JSIntn ln)
#endif
}
#ifdef MUST_DETECT_SSE2
bool js_use_SSE2;
bool
js_DetectSSE2()
{
char *c = getenv("X86_FORCE_SSE2");
if (c)
return (!strcmp(c, "true") ||
!strcmp(c, "1") ||
!strcmp(c, "yes"));
int features = 0;
#if defined _MSC_VER
__asm
{
pushad
mov eax, 1
cpuid
mov features, edx
popad
}
#elif defined __GNUC__
asm("xchg %%esi, %%ebx\n" /* we can't clobber ebx on gcc (PIC register) */
"mov $0x01, %%eax\n"
"cpuid\n"
"mov %%edx, %0\n"
"xchg %%esi, %%ebx\n"
: "=m" (features)
: /* We have no inputs */
: "%eax", "%esi", "%ecx", "%edx"
);
#elif defined __SUNPRO_C || defined __SUNPRO_CC
asm("push %%ebx\n"
"mov $0x01, %%eax\n"
"cpuid\n"
"pop %%ebx\n"
: "=d" (features)
: /* We have no inputs */
: "%eax", "%ecx"
);
#endif
return (features & (1<<26)) != 0;
}
#endif
#ifdef JS_BASIC_STATS
#include <math.h>

View File

@ -74,6 +74,17 @@ JS_Assert(const char *s, const char *file, JSIntn ln);
#endif /* defined(DEBUG) */
#ifdef HAVE_SSE2
#ifdef MUST_DETECT_SSE2
extern bool js_use_SSE2;
bool
js_DetectSSE2();
#else
static const bool js_use_SSE2 = true;
#endif
#endif
/*
* Compile-time assert. "cond" must be a constant expression.
* The macro can be used only in places where an "extern" declaration is