Bug 1050278 - IonMonkey (ARM): Consolidate the mpu feature detection and remove the ARM remnants in js/src/assembler. r=nbp

This commit is contained in:
Douglas Crosher 2014-08-13 01:25:17 +10:00
parent 96c7ebdc7d
commit c082b84209
7 changed files with 158 additions and 364 deletions

View File

@ -39,13 +39,8 @@
#include "jit/none/BaseMacroAssembler-none.h"
namespace JSC { typedef MacroAssemblerNone MacroAssembler; }
#elif WTF_CPU_ARM_THUMB2
#include "assembler/assembler/MacroAssemblerARMv7.h"
namespace JSC { typedef MacroAssemblerARMv7 MacroAssembler; }
#elif WTF_CPU_ARM_TRADITIONAL
#include "assembler/assembler/MacroAssemblerARM.h"
namespace JSC { typedef MacroAssemblerARM MacroAssembler; }
#elif JS_CODEGEN_ARM
// Merged with the jit backend support.
#elif WTF_CPU_MIPS
#include "assembler/assembler/MacroAssemblerMIPS.h"

View File

@ -1,100 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Copyright (C) 2009 University of Szeged
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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.
*
* ***** END LICENSE BLOCK ***** */
#include "assembler/wtf/Platform.h"
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
#include "assembler/assembler/MacroAssemblerARM.h"
#if (WTF_OS_LINUX || WTF_OS_ANDROID) && !defined(JS_ARM_SIMULATOR)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <elf.h>
#include <stdio.h>
// lame check for kernel version
// see bug 586550
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
#include <asm/procinfo.h>
#else
#include <asm/hwcap.h>
#endif
#endif
namespace JSC {
static bool isVFPPresent()
{
#ifdef JS_ARM_SIMULATOR
return true;
#else
#if WTF_OS_LINUX
int fd = open("/proc/self/auxv", O_RDONLY);
if (fd > 0) {
Elf32_auxv_t aux;
while (read(fd, &aux, sizeof(Elf32_auxv_t))) {
if (aux.a_type == AT_HWCAP) {
close(fd);
return aux.a_un.a_val & HWCAP_VFP;
}
}
close(fd);
}
#endif
#if defined(__GNUC__) && defined(__VFP_FP__)
return true;
#endif
#ifdef WTF_OS_ANDROID
FILE *fp = fopen("/proc/cpuinfo", "r");
if (!fp)
return false;
char buf[1024];
fread(buf, sizeof(char), sizeof(buf), fp);
fclose(fp);
if (strstr(buf, "vfp"))
return true;
#endif
return false;
#endif // JS_ARM_SIMULATOR
}
const bool MacroAssemblerARM::s_isVFPPresent = isVFPPresent();
}
#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)

View File

@ -1,51 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Copyright (C) 2008 Apple Inc.
* Copyright (C) 2009, 2010 University of Szeged
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
*
* ***** END LICENSE BLOCK ***** */
#ifndef assembler_assembler_MacroAssemblerARM_h
#define assembler_assembler_MacroAssemblerARM_h
#include "assembler/wtf/Platform.h"
#if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
namespace JSC {
class MacroAssemblerARM {
public:
static bool supportsFloatingPoint() { return s_isVFPPresent; }
static const bool s_isVFPPresent;
};
}
#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
#endif /* assembler_assembler_MacroAssemblerARM_h */

View File

@ -1,49 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Copyright (C) 2009 Apple Inc. All rights reserved.
* Copyright (C) 2010 University of Szeged
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
*
* ***** END LICENSE BLOCK ***** */
#ifndef assembler_assembler_MacroAssemblerARMv7_h
#define assembler_assembler_MacroAssemblerARMv7_h
#include "assembler/wtf/Platform.h"
#if ENABLE(ASSEMBLER)
namespace JSC {
class MacroAssemblerARMv7 {
public:
static bool supportsFloatingPoint() { return true; }
};
} // namespace JSC
#endif // ENABLE(ASSEMBLER)
#endif /* assembler_assembler_MacroAssemblerARMv7_h */

View File

@ -16,28 +16,98 @@
#include "jit/arm/Assembler-arm.h"
#include "jit/RegisterSets.h"
#define HWCAP_USE_HARDFP_ABI (1 << 27)
#if !(defined(ANDROID) || defined(MOZ_B2G)) && !defined(JS_ARM_SIMULATOR)
#define HWCAP_ARMv7 (1 << 28)
#include <asm/hwcap.h>
#if defined(ANDROID) || defined(MOZ_B2G) || defined(JS_ARM_SIMULATOR)
// The Android NDK does not include the hwcap.h kernel header, and it is not
// defined when building the simulator, so inline the header defines we need.
# define HWCAP_VFP (1 << 6)
# define HWCAP_NEON (1 << 12)
# define HWCAP_VFPv3 (1 << 13)
# define HWCAP_VFPv3D16 (1 << 14) /* also set for VFPv4-D16 */
# define HWCAP_VFPv4 (1 << 16)
# define HWCAP_IDIVA (1 << 17)
# define HWCAP_IDIVT (1 << 18)
# define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */
# define AT_HWCAP 16
#else
#define HWCAP_VFP (1<<0)
#define HWCAP_VFPv3 (1<<1)
#define HWCAP_VFPv3D16 (1<<2)
#define HWCAP_VFPv4 (1<<3)
#define HWCAP_IDIVA (1<<4)
#define HWCAP_IDIVT (1<<5)
#define HWCAP_NEON (1<<6)
#define HWCAP_ARMv7 (1<<7)
# include <asm/hwcap.h>
# if !defined(HWCAP_IDIVA)
# define HWCAP_IDIVA (1 << 17)
# endif
# if !defined(HWCAP_VFPD32)
# define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */
# endif
#endif
// Not part of the HWCAP flag, but we need to know this, and this bit is not
// used so we are using it.
#define HWCAP_ARMv7 (1 << 28)
// Also take a bit to flag the use of the hardfp ABI.
#define HWCAP_USE_HARDFP_ABI (1 << 27)
namespace js {
namespace jit {
// Parse the Linux kernel cpuinfo features. This is also used to parse the
// override features which has some extensions: 'armv7' and 'hardfp'.
uint32_t
ParseARMCpuFeatures(const char *features, bool override = false)
{
uint32_t flags = 0;
for (;;) {
char ch = *features;
if (!ch) {
// End of string.
break;
}
if (ch == ' ' || ch == ',') {
// Skip separator characters.
features++;
continue;
}
// Find the end of the token.
const char *end = features + 1;
for (; ; end++) {
ch = *end;
if (!ch || ch == ' ' || ch == ',')
break;
}
size_t count = end - features;
if (count == 3 && strncmp(features, "vfp", 3) == 0)
flags |= HWCAP_VFP;
else if (count == 4 && strncmp(features, "neon", 4) == 0)
flags |= HWCAP_NEON;
else if (count == 5 && strncmp(features, "vfpv3", 5) == 0)
flags |= HWCAP_VFPv3;
else if (count == 8 && strncmp(features, "vfpv3d16", 8) == 0)
flags |= HWCAP_VFPv3D16;
else if (count == 5 && strncmp(features, "vfpv4", 5) == 0)
flags |= HWCAP_VFPv4;
else if (count == 5 && strncmp(features, "idiva", 5) == 0)
flags |= HWCAP_IDIVA;
else if (count == 5 && strncmp(features, "idivt", 5) == 0)
flags |= HWCAP_IDIVT;
else if (count == 6 && strncmp(features, "vfpd32", 6) == 0)
flags |= HWCAP_VFPD32;
else if (count == 5 && strncmp(features, "armv7", 5) == 0)
flags |= HWCAP_ARMv7;
#if defined(JS_ARM_SIMULATOR)
else if (count == 6 && strncmp(features, "hardfp", 6) == 0)
flags |= HWCAP_USE_HARDFP_ABI;
#endif
else if (override)
fprintf(stderr, "Warning: unexpected ARM feature at: %s\n", features);
features = end;
}
IonSpew(IonSpew_Codegen, "ARM features: '%s'\n flags: 0x%x\n", features, flags);
return flags;
}
// The override flags parsed from the ARMHWCAP environment variable or from the
// --arm-hwcap js shell argument.
static uint32_t armHwCapFlags = 0;
volatile static uint32_t armHwCapFlags = 0;
bool
ParseARMHwCapFlags(const char *armHwCap)
@ -65,6 +135,7 @@ ParseARMHwCapFlags(const char *armHwCap)
" vfpv4 \n"
" idiva \n"
" idivt \n"
" vfpd32 \n"
#if defined(JS_ARM_SIMULATOR)
" hardfp \n"
#endif
@ -74,168 +145,108 @@ ParseARMHwCapFlags(const char *armHwCap)
/*NOTREACHED*/
}
// Canonicalize each token to have a leading and trailing space.
const char *start = armHwCap; // Token start.
for (;;) {
char ch = *start;
if (!ch) {
// End of string.
break;
}
if (ch == ' ' || ch == ',') {
// Skip separator characters.
start++;
continue;
}
// Find the end of the token.
const char *end = start + 1;
for (; ; end++) {
ch = *end;
if (!ch || ch == ' ' || ch == ',')
break;
}
size_t count = end - start;
if (count == 3 && strncmp(start, "vfp", 3) == 0)
flags |= HWCAP_VFP;
else if (count == 5 && strncmp(start, "vfpv3", 5) == 0)
flags |= HWCAP_VFPv3;
else if (count == 8 && strncmp(start, "vfpv3d16", 8) == 0)
flags |= HWCAP_VFPv3D16;
else if (count == 5 && strncmp(start, "vfpv4", 5) == 0)
flags |= HWCAP_VFPv4;
else if (count == 5 && strncmp(start, "idiva", 5) == 0)
flags |= HWCAP_IDIVA;
else if (count == 5 && strncmp(start, "idivt", 5) == 0)
flags |= HWCAP_IDIVT;
else if (count == 4 && strncmp(start, "neon", 4) == 0)
flags |= HWCAP_NEON;
else if (count == 5 && strncmp(start, "armv7", 5) == 0)
flags |= HWCAP_ARMv7;
#if defined(JS_ARM_SIMULATOR)
else if (count == 6 && strncmp(start, "hardfp", 6) == 0)
flags |= HWCAP_USE_HARDFP_ABI;
#endif
else
fprintf(stderr, "Warning: unexpected ARMHWCAP flag at: %s\n", start);
start = end;
}
#ifdef DEBUG
IonSpew(IonSpew_Codegen, "ARMHWCAP: '%s'\n flags: 0x%x\n", armHwCap, flags);
#endif
armHwCapFlags = flags;
armHwCapFlags = ParseARMCpuFeatures(armHwCap, /* override = */ true);
return true;
}
uint32_t GetARMFlags()
{
static bool isSet = false;
static uint32_t flags = 0;
volatile static bool isSet = false;
volatile static uint32_t flags = 0;
if (isSet)
return flags;
const char *env = getenv("ARMHWCAP");
if (ParseARMHwCapFlags(env) || armHwCapFlags) {
isSet = true;
flags = armHwCapFlags;
isSet = true;
return flags;
}
#ifdef JS_CODEGEN_ARM_HARDFP
flags |= HWCAP_USE_HARDFP_ABI;
#endif
#ifdef JS_ARM_SIMULATOR
isSet = true;
flags = HWCAP_ARMv7 | HWCAP_VFP | HWCAP_VFPv3 | HWCAP_VFPv4 | HWCAP_NEON;
return flags;
#else
#if WTF_OS_LINUX
#if defined(WTF_OS_LINUX) || defined(WTF_OS_ANDROID) || defined(MOZ_B2G)
bool readAuxv = false;
int fd = open("/proc/self/auxv", O_RDONLY);
if (fd > 0) {
Elf32_auxv_t aux;
while (read(fd, &aux, sizeof(Elf32_auxv_t))) {
struct { uint32_t a_type; uint32_t a_val; } aux;
while (read(fd, &aux, sizeof(aux))) {
if (aux.a_type == AT_HWCAP) {
close(fd);
flags = aux.a_un.a_val;
isSet = true;
#if defined(__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
// This should really be detected at runtime, but /proc/*/auxv
// doesn't seem to carry the ISA. We could look in /proc/cpuinfo
// as well, but the chances that it will be different from this
// are low.
flags |= HWCAP_ARMv7;
#endif
return flags;
flags = aux.a_val;
readAuxv = true;
break;
}
}
close(fd);
}
#if defined(__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
flags = HWCAP_ARMv7;
#endif
isSet = true;
return flags;
#elif defined(WTF_OS_ANDROID) || defined(MOZ_B2G)
FILE *fp = fopen("/proc/cpuinfo", "r");
if (!fp)
return false;
char buf[1024];
memset(buf, 0, sizeof(buf));
size_t len = fread(buf, sizeof(char), sizeof(buf) - 2, fp);
fclose(fp);
// Canonicalize each token to have a leading and trailing space.
buf[len] = ' ';
buf[len + 1] = '\0';
for (size_t i = 0; i < len; i++) {
char ch = buf[i];
if (!ch)
break;
else if (ch == '\n')
buf[i] = 0x20;
else
buf[i] = ch;
if (!readAuxv) {
// Read the Features if the auxv is not available.
FILE *fp = fopen("/proc/cpuinfo", "r");
if (fp) {
char buf[1024];
memset(buf, 0, sizeof(buf));
size_t len = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
fclose(fp);
buf[len] = '\0';
char *featureList = strstr(buf, "Features");
if (featureList) {
if (char *featuresEnd = strstr(featureList, "\n"))
*featuresEnd = '\0';
flags = ParseARMCpuFeatures(featureList + 8);
}
if (strstr(buf, "ARMv7"))
flags |= HWCAP_ARMv7;
}
}
#endif
if (strstr(buf, " vfp "))
flags |= HWCAP_VFP;
// If compiled to use specialized features then these features can be
// assumed to be present otherwise the compiler would fail to run.
if (strstr(buf, " vfpv3 "))
#ifdef JS_CODEGEN_ARM_HARDFP
// Compiled to use the hardfp ABI.
flags |= HWCAP_USE_HARDFP_ABI;
#endif
#if defined(__VFP_FP__) && !defined(__SOFTFP__)
// Compiled to use VFP instructions so assume VFP support.
flags |= HWCAP_VFP;
#endif
#if defined(__ARM_ARCH_7__) || defined (__ARM_ARCH_7A__)
// Compiled to use ARMv7 instructions so assume the ARMv7 arch.
flags |= HWCAP_ARMv7;
#endif
#endif // JS_ARM_SIMULATOR
// Canonicalize the flags. These rules are also applied to the features
// supplied for simulation.
// The VFPv3 feature is expected when the VFPv3D16 is reported, but add it
// just in case of a kernel difference in feature reporting.
if (flags & HWCAP_VFPv3D16)
flags |= HWCAP_VFPv3;
if (strstr(buf, " vfpv3d16 "))
flags |= HWCAP_VFPv3D16;
if (strstr(buf, " vfpv4 "))
flags |= HWCAP_VFPv4;
if (strstr(buf, " idiva "))
flags |= HWCAP_IDIVA;
if (strstr(buf, " idivt "))
flags |= HWCAP_IDIVT;
if (strstr(buf, " neon "))
flags |= HWCAP_NEON;
// Not part of the HWCAP flag, but we need to know this, and we're not using
// that bit, so... we are using it.
if (strstr(buf, "ARMv7"))
// If VFPv3 or Neon is supported then this must be an ARMv7.
if (flags & (HWCAP_VFPv3 | HWCAP_NEON))
flags |= HWCAP_ARMv7;
#ifdef DEBUG
IonSpew(IonSpew_Codegen, "ARMHWCAP: '%s'\n flags: 0x%x\n", buf, flags);
#endif
// Some old kernels report VFP and not VFPv3, but if ARMv7 then it must be
// VFPv3.
if (flags & HWCAP_VFP && flags & HWCAP_ARMv7)
flags |= HWCAP_VFPv3;
// Older kernels do not implement the HWCAP_VFPD32 flag.
if ((flags & HWCAP_VFPv3) && !(flags & HWCAP_VFPv3D16))
flags |= HWCAP_VFPD32;
IonSpew(IonSpew_Codegen, "ARM HWCAP: 0x%x\n", flags);
isSet = true;
return flags;
#endif
return 0;
#endif // JS_ARM_SIMULATOR
}
bool HasMOVWT()
@ -253,20 +264,12 @@ bool HasVFP()
bool Has32DP()
{
return (GetARMFlags() & HWCAP_VFPv3) && !(GetARMFlags() & HWCAP_VFPv3D16);
}
bool UseConvReg()
{
return Has32DP();
return GetARMFlags() & HWCAP_VFPD32;
}
bool HasIDIV()
{
#if defined HWCAP_IDIVA
return GetARMFlags() & HWCAP_IDIVA;
#else
return false;
#endif
}
// This is defined in the header and inlined when not using the simulator.

View File

@ -378,10 +378,6 @@ if CONFIG['ENABLE_ION']:
SOURCES += [
'assembler/assembler/MacroAssemblerX86Common.cpp',
]
elif CONFIG['JS_CODEGEN_ARM']:
SOURCES += [
'assembler/assembler/MacroAssemblerARM.cpp',
]
if CONFIG['JS_HAS_CTYPES']:
SOURCES += [

View File

@ -235,12 +235,12 @@ JSRuntime::JSRuntime(JSRuntime *parentRuntime)
static bool
JitSupportsFloatingPoint()
{
if (!JSC::MacroAssembler::supportsFloatingPoint())
return false;
#if WTF_ARM_ARCH_VERSION == 6
#if defined(JS_CODEGEN_ARM)
if (!js::jit::HasVFP())
return false;
#else
if (!JSC::MacroAssembler::supportsFloatingPoint())
return false;
#endif
return true;