[JSC][ARM64][Linux] Add collectCPUFeatures using auxiliary vector
https://bugs.webkit.org/show_bug.cgi?id=185055

Reviewed by JF Bastien.

This patch is paving the way to emitting jscvt instruction if possible.
To do that, we need to determine jscvt instruction is supported in the
given CPU.

We add a function collectCPUFeatures, which is responsible to collect
CPU features if necessary. In Linux, we can use auxiliary vector to get
the information without parsing /proc/cpuinfo.

Currently, nobody calls this function. It is later called when we emit
jscvt instruction. To make it possible, we also need to add disassembler
support too.

* assembler/AbstractMacroAssembler.h:
* assembler/MacroAssemblerARM64.cpp:
(JSC::MacroAssemblerARM64::collectCPUFeatures):
* assembler/MacroAssemblerARM64.h:
* assembler/MacroAssemblerX86Common.h:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@231118 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 8ca38cd..474bc61 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,28 @@
+2018-04-27  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [JSC][ARM64][Linux] Add collectCPUFeatures using auxiliary vector
+        https://bugs.webkit.org/show_bug.cgi?id=185055
+
+        Reviewed by JF Bastien.
+
+        This patch is paving the way to emitting jscvt instruction if possible.
+        To do that, we need to determine jscvt instruction is supported in the
+        given CPU.
+
+        We add a function collectCPUFeatures, which is responsible to collect
+        CPU features if necessary. In Linux, we can use auxiliary vector to get
+        the information without parsing /proc/cpuinfo.
+
+        Currently, nobody calls this function. It is later called when we emit
+        jscvt instruction. To make it possible, we also need to add disassembler
+        support too.
+
+        * assembler/AbstractMacroAssembler.h:
+        * assembler/MacroAssemblerARM64.cpp:
+        (JSC::MacroAssemblerARM64::collectCPUFeatures):
+        * assembler/MacroAssemblerARM64.h:
+        * assembler/MacroAssemblerX86Common.h:
+
 2018-04-26  Filip Pizlo  <fpizlo@apple.com>
 
         Also run foldPathConstants before mussing up SSA
diff --git a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
index cf03f68..9f4aaee 100644
--- a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
+++ b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h
@@ -82,6 +82,12 @@
     template<PtrTag tag> using CodePtr = MacroAssemblerCodePtr<tag>;
     template<PtrTag tag> using CodeRef = MacroAssemblerCodeRef<tag>;
 
+    enum class CPUIDCheckState {
+        NotChecked,
+        Clear,
+        Set
+    };
+
     class Jump;
 
     typedef typename AssemblerType::RegisterID RegisterID;
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM64.cpp b/Source/JavaScriptCore/assembler/MacroAssemblerARM64.cpp
index ed34330..edfb442 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerARM64.cpp
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM64.cpp
@@ -31,6 +31,11 @@
 #include "ProbeContext.h"
 #include <wtf/InlineASM.h>
 
+#if OS(LINUX)
+#include <asm/hwcap.h>
+#include <sys/auxv.h>
+#endif
+
 namespace JSC {
 
 #if ENABLE(MASM_PROBE)
@@ -526,6 +531,34 @@
 
 #endif // ENABLE(MASM_PROBE)
 
+void MacroAssemblerARM64::collectCPUFeatures()
+{
+    static std::once_flag onceKey;
+    std::call_once(onceKey, [] {
+#if OS(LINUX)
+        // A register for describing ARM64 CPU features are only accessible in kernel mode.
+        // Thus, some kernel support is necessary to collect CPU features. In Linux, the
+        // kernel passes CPU feature flags in AT_HWCAP auxiliary vector which is passed
+        // when the process starts. While this may pose a bit conservative information
+        // (for example, the Linux kernel may add a flag for a feature after the feature
+        // is shipped and implemented in some CPUs. In that case, even if the CPU has
+        // that feature, the kernel does not tell it to users.), it is a stable approach.
+        // https://www.kernel.org/doc/Documentation/arm64/elf_hwcaps.txt
+        unsigned long hwcaps = getauxval(AT_HWCAP);
+
+#if !defined(HWCAP_JSCVT)
+#define HWCAP_JSCVT (1 << 13)
+#endif
+
+        s_jscvtCheckState = (hwcaps & HWCAP_JSCVT) ? CPUIDCheckState::Set : CPUIDCheckState::Clear;
+#else
+        s_jscvtCheckState = CPUIDCheckState::Clear;
+#endif
+    });
+}
+
+MacroAssemblerARM64::CPUIDCheckState MacroAssemblerARM64::s_jscvtCheckState = CPUIDCheckState::NotChecked;
+
 } // namespace JSC
 
 #endif // ENABLE(ASSEMBLER) && CPU(ARM64)
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
index 52481bb..80cdd1f 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h
@@ -4460,6 +4460,10 @@
             Assembler::linkCall(code, call.m_label, function.template retaggedExecutableAddress<NoPtrTag>());
     }
 
+    JS_EXPORT_PRIVATE static void collectCPUFeatures();
+
+    JS_EXPORT_PRIVATE static CPUIDCheckState s_jscvtCheckState;
+
     CachedTempRegister m_dataMemoryTempRegister;
     CachedTempRegister m_cachedMemoryTempRegister;
     bool m_makeJumpPatchable;
diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
index e8c8599..0f73325 100644
--- a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
+++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
@@ -4188,11 +4188,6 @@
     static CPUID getCPUIDEx(unsigned level, unsigned count);
     JS_EXPORT_PRIVATE static void collectCPUFeatures();
 
-    enum class CPUIDCheckState {
-        NotChecked,
-        Clear,
-        Set
-    };
     JS_EXPORT_PRIVATE static CPUIDCheckState s_sse2CheckState;
     JS_EXPORT_PRIVATE static CPUIDCheckState s_sse4_1CheckState;
     JS_EXPORT_PRIVATE static CPUIDCheckState s_sse4_2CheckState;