以下调查的结果是:最近的 Node.js 不能移植到 AMD Geode(或其他非 SSE x86)处理器!!!
我深入研究了代码并陷入了 ia32-assembler 实现,它将 SSE/SSE2 指令深度集成到他们的代码中(宏、宏、宏......)。主要后果是,由于缺少更新的指令集扩展,您无法在 AMD geode 处理器上运行最新版本的 node.js。回退到 387 算法仅适用于 node.js 代码,但不适用于它所依赖的 javascript V8 编译器实现。调整 V8 以支持非 SSE x86 处理器是一件痛苦的事,而且需要付出很多努力。
如果有人提供相反的证据,我会很高兴听到 ;-)
调查历史
我有一个正在运行的 ALIX.2D13 ( https://www.pcengines.ch ),它有一个 AMD Geode LX 作为主处理器。它运行 voyage linux,这是一个基于 debian jessi 的资源受限嵌入式设备的发行版。
root@voyage:~# cat /proc/cpuinfo
processor : 0
vendor_id : AuthenticAMD
cpu family : 5
model : 10
model name : Geode(TM) Integrated Processor by AMD PCS
stepping : 2
cpu MHz : 498.004
cache size : 128 KB
physical id : 0
siblings : 1
core id : 0
cpu cores : 1
apicid : 0
initial apicid : 0
fdiv_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu de pse tsc msr cx8 sep pge cmov clflush mmx mmxext 3dnowext 3dnow 3dnowprefetch vmmcall
bugs : sysret_ss_attrs
bogomips : 996.00
clflush size : 32
cache_alignment : 32
address sizes : 32 bits physical, 32 bits virtual
当我按照https://nodejs.org/en/download/package-manager/上的说明安装 nodejs 8.x 时,我得到一些“无效的机器指令”(不确定是否正确,但从德语错误输出翻译而来)。当我下载 32 位 x86 的二进制文件以及手动编译它时,也会发生这种情况。
deps/v8/gypfiles/toolchain.gypi
在下面的答案之后,我通过删除-msse2
和添加来更改编译器标志-march=geode -mtune=geode
。现在我得到了同样的错误,但有一个堆栈跟踪:
root@voyage:~/GIT/node# ./node
#
# Fatal error in ../deps/v8/src/ia32/assembler-ia32.cc, line 109
# Check failed: cpu.has_sse2().
#
==== C stack trace ===============================
./node(v8::base::debug::StackTrace::StackTrace()+0x12) [0x908df36]
./node() [0x8f2b0c3]
./node(V8_Fatal+0x58) [0x908b559]
./node(v8::internal::CpuFeatures::ProbeImpl(bool)+0x19a) [0x8de6d08]
./node(v8::internal::V8::InitializeOncePerProcessImpl()+0x96) [0x8d8daf0]
./node(v8::base::CallOnceImpl(int*, void (*)(void*), void*)+0x35) [0x908bdf5]
./node(v8::internal::V8::Initialize()+0x21) [0x8d8db6d]
./node(v8::V8::Initialize()+0xb) [0x86700a1]
./node(node::Start(int, char**)+0xd3) [0x8e89f27]
./node(main+0x67) [0x846845c]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0xb74fc723]
./node() [0x846a09c]
Ungültiger Maschinenbefehl
root@voyage:~/GIT/node#
如果你现在查看这个文件,你会发现以下内容
... [line 107-110]
void CpuFeatures::ProbeImpl(bool cross_compile) {
base::CPU cpu;
CHECK(cpu.has_sse2()); // SSE2 support is mandatory.
CHECK(cpu.has_cmov()); // CMOV support is mandatory.
...
我评论了这条线,但仍然是“Ungültiger Maschinenbefehl”(无效的机器指令)。
这是gdb ./node
显示(执行run
):
root@voyage:~/GIT/node# gdb ./node
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
[...]
This GDB was configured as "i586-linux-gnu".
[...]
Reading symbols from ./node...done.
(gdb) run
Starting program: /root/GIT/node/node
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
[New Thread 0xb7ce2b40 (LWP 29876)]
[New Thread 0xb74e2b40 (LWP 29877)]
[New Thread 0xb6ce2b40 (LWP 29878)]
[New Thread 0xb64e2b40 (LWP 29879)]
Program received signal SIGILL, Illegal instruction.
0x287a23c0 in ?? ()
(gdb)
我认为,有必要用调试符号编译......
make clean
make CFLAGS="-g"
没有机会解决所有 SSE/SSE2 问题……放弃!看我最上面的部分