mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Print list of CPU features in crash reports (#12350)
Co-authored-by: Jarred-Sumner <Jarred-Sumner@users.noreply.github.com>
This commit is contained in:
@@ -3,7 +3,7 @@ cmake_policy(SET CMP0091 NEW)
|
||||
cmake_policy(SET CMP0067 NEW)
|
||||
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
|
||||
set(Bun_VERSION "1.1.18")
|
||||
set(Bun_VERSION "1.1.19")
|
||||
set(WEBKIT_TAG 615e8585f96aa718b0f5158210259b83fe8440ea)
|
||||
|
||||
set(BUN_WORKDIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
@@ -1126,6 +1126,7 @@ if(WIN32)
|
||||
set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDLL")
|
||||
|
||||
target_compile_options(${bun} PUBLIC "/EHsc" "/GR-")
|
||||
|
||||
target_link_options(${bun} PUBLIC "/STACK:0x1200000,0x100000" "/DEF:${BUN_SRC}/symbols.def" "/errorlimit:0")
|
||||
else()
|
||||
target_compile_options(${bun} PUBLIC
|
||||
|
||||
@@ -101,7 +101,6 @@ pub const Features = struct {
|
||||
pub var loaders: usize = 0;
|
||||
pub var lockfile_migration_from_package_lock: usize = 0;
|
||||
pub var macros: usize = 0;
|
||||
pub var origin: usize = 0;
|
||||
pub var shell: usize = 0;
|
||||
pub var spawn: usize = 0;
|
||||
pub var standalone_shell: usize = 0;
|
||||
@@ -110,7 +109,8 @@ pub const Features = struct {
|
||||
pub var tsconfig: usize = 0;
|
||||
pub var virtual_modules: usize = 0;
|
||||
pub var WebSocket: usize = 0;
|
||||
|
||||
pub var no_avx: usize = 0;
|
||||
pub var no_avx2: usize = 0;
|
||||
pub var builtin_modules = std.enums.EnumSet(bun.JSC.HardcodedModule).initEmpty();
|
||||
|
||||
pub fn formatter() Formatter {
|
||||
|
||||
110
src/bun.js/bindings/CPUFeatures.cpp
Normal file
110
src/bun.js/bindings/CPUFeatures.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "root.h"
|
||||
|
||||
enum class X86CPUFeature : uint8_t {
|
||||
sse42 = 1,
|
||||
popcnt = 2,
|
||||
avx = 3,
|
||||
avx2 = 4,
|
||||
avx512 = 5,
|
||||
};
|
||||
|
||||
enum class AArch64CPUFeature : uint8_t {
|
||||
neon = 1,
|
||||
fp = 2,
|
||||
aes = 3,
|
||||
crc32 = 4,
|
||||
atomics = 5,
|
||||
sve = 6,
|
||||
};
|
||||
|
||||
#if CPU(X86_64)
|
||||
|
||||
#if OS(WINDOWS)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#endif
|
||||
|
||||
static uint8_t x86_cpu_features()
|
||||
{
|
||||
uint8_t features = 0;
|
||||
|
||||
#if OS(WINDOWS)
|
||||
if (IsProcessorFeaturePresent(PF_SSE4_2_INSTRUCTIONS_AVAILABLE))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::sse42);
|
||||
|
||||
if (IsProcessorFeaturePresent(PF_AVX_INSTRUCTIONS_AVAILABLE))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::avx);
|
||||
|
||||
if (IsProcessorFeaturePresent(PF_AVX2_INSTRUCTIONS_AVAILABLE))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::avx2);
|
||||
|
||||
if (IsProcessorFeaturePresent(PF_AVX512F_INSTRUCTIONS_AVAILABLE))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::avx512);
|
||||
|
||||
#else
|
||||
|
||||
#if __has_builtin(__builtin_cpu_supports)
|
||||
__builtin_cpu_init();
|
||||
|
||||
if (__builtin_cpu_supports("sse4.2"))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::sse42);
|
||||
if (__builtin_cpu_supports("popcnt"))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::popcnt);
|
||||
if (__builtin_cpu_supports("avx"))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::avx);
|
||||
if (__builtin_cpu_supports("avx2"))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::avx2);
|
||||
if (__builtin_cpu_supports("avx512f"))
|
||||
features |= 1 << static_cast<uint8_t>(X86CPUFeature::avx512);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if CPU(ARM64)
|
||||
|
||||
static uint8_t aarch64_cpu_features()
|
||||
{
|
||||
uint8_t features = 0;
|
||||
|
||||
#if OS(WINDOWS)
|
||||
#pragma error "TODO: Implement AArch64 CPU features for Windows"
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_cpu_supports)
|
||||
__builtin_cpu_init();
|
||||
|
||||
if (__builtin_cpu_supports("neon"))
|
||||
features |= 1 << static_cast<uint8_t>(AArch64CPUFeature::neon);
|
||||
if (__builtin_cpu_supports("crypto"))
|
||||
features |= 1 << static_cast<uint8_t>(AArch64CPUFeature::fp);
|
||||
if (__builtin_cpu_supports("aes"))
|
||||
features |= 1 << static_cast<uint8_t>(AArch64CPUFeature::aes);
|
||||
if (__builtin_cpu_supports("crc32"))
|
||||
features |= 1 << static_cast<uint8_t>(AArch64CPUFeature::crc32);
|
||||
if (__builtin_cpu_supports("atomics"))
|
||||
features |= 1 << static_cast<uint8_t>(AArch64CPUFeature::atomics);
|
||||
if (__builtin_cpu_supports("sve"))
|
||||
features |= 1 << static_cast<uint8_t>(AArch64CPUFeature::sve);
|
||||
#endif
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern "C" uint8_t bun_cpu_features()
|
||||
{
|
||||
#if CPU(X86_64)
|
||||
return x86_cpu_features();
|
||||
#elif CPU(ARM64)
|
||||
return aarch64_cpu_features();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
89
src/bun.js/bindings/CPUFeatures.zig
Normal file
89
src/bun.js/bindings/CPUFeatures.zig
Normal file
@@ -0,0 +1,89 @@
|
||||
const bun = @import("root").bun;
|
||||
const std = @import("std");
|
||||
|
||||
fn Impl(comptime T: type) type {
|
||||
return struct {
|
||||
pub fn format(this: T, comptime _: []const u8, _: anytype, writer: anytype) !void {
|
||||
var is_first = true;
|
||||
inline for (comptime std.meta.fieldNames(T)) |fieldName| {
|
||||
if (comptime bun.strings.eqlComptime(fieldName, "padding") or bun.strings.eqlComptime(fieldName, "none"))
|
||||
continue;
|
||||
|
||||
const value = @field(this, fieldName);
|
||||
if (value) {
|
||||
if (!is_first)
|
||||
try writer.writeAll(" ");
|
||||
is_first = false;
|
||||
try writer.writeAll(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn isEmpty(this: T) bool {
|
||||
return @as(u8, @bitCast(this)) == 0;
|
||||
}
|
||||
|
||||
pub fn get() T {
|
||||
const this: T = @bitCast(bun_cpu_features());
|
||||
|
||||
// sanity check
|
||||
assert(this.none == false and this.padding == 0);
|
||||
|
||||
if (bun.Environment.isX64) {
|
||||
bun.analytics.Features.no_avx += @as(usize, @intFromBool(!this.avx));
|
||||
bun.analytics.Features.no_avx2 += @as(usize, @intFromBool(!this.avx2));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const X86CPUFeatures = packed struct(u8) {
|
||||
none: bool = false,
|
||||
|
||||
sse42: bool = false,
|
||||
popcnt: bool = false,
|
||||
avx: bool = false,
|
||||
avx2: bool = false,
|
||||
avx512: bool = false,
|
||||
|
||||
padding: u2 = 0,
|
||||
|
||||
pub usingnamespace Impl(@This());
|
||||
};
|
||||
const AArch64CPUFeatures = packed struct(u8) {
|
||||
none: bool = false,
|
||||
|
||||
neon: bool = false,
|
||||
fp: bool = false,
|
||||
aes: bool = false,
|
||||
crc32: bool = false,
|
||||
atomics: bool = false,
|
||||
sve: bool = false,
|
||||
|
||||
padding: u1 = 0,
|
||||
|
||||
pub usingnamespace Impl(@This());
|
||||
};
|
||||
|
||||
pub const CPUFeatures = if (bun.Environment.isX64)
|
||||
X86CPUFeatures
|
||||
else if (bun.Environment.isAarch64)
|
||||
AArch64CPUFeatures
|
||||
else
|
||||
struct {
|
||||
pub fn get() @This() {
|
||||
return .{};
|
||||
}
|
||||
|
||||
pub fn format(_: @This(), comptime _: []const u8, _: anytype, _: anytype) !void {}
|
||||
|
||||
pub fn isEmpty(_: @This()) bool {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" fn bun_cpu_features() u8;
|
||||
|
||||
const assert = bun.debugAssert;
|
||||
@@ -50,6 +50,8 @@ var panic_mutex = std.Thread.Mutex{};
|
||||
/// This is used to catch and handle panics triggered by the panic handler.
|
||||
threadlocal var panic_stage: usize = 0;
|
||||
|
||||
const CPUFeatures = @import("./bun.js/bindings/CPUFeatures.zig").CPUFeatures;
|
||||
|
||||
/// This structure and formatter must be kept in sync with `bun.report`'s decoder implementation.
|
||||
pub const CrashReason = union(enum) {
|
||||
/// From @panic()
|
||||
@@ -746,6 +748,7 @@ pub fn printMetadata(writer: anytype) !void {
|
||||
try writer.writeAll(metadata_version_line);
|
||||
{
|
||||
const platform = bun.Analytics.GenerateHeader.GeneratePlatform.forOS();
|
||||
const cpu_features = CPUFeatures.get();
|
||||
if (bun.Environment.isLinux) {
|
||||
// TODO: musl
|
||||
const version = gnu_get_libc_version() orelse "";
|
||||
@@ -758,6 +761,11 @@ pub fn printMetadata(writer: anytype) !void {
|
||||
} else if (bun.Environment.isMac) {
|
||||
try writer.print("macOS v{s}\n", .{platform.version});
|
||||
}
|
||||
|
||||
if (!cpu_features.isEmpty()) {
|
||||
try writer.print("CPU: {}\n", .{cpu_features});
|
||||
}
|
||||
|
||||
try writer.print("Args: ", .{});
|
||||
var arg_chars_left: usize = if (bun.Environment.isDebug) 4096 else 196;
|
||||
for (bun.argv, 0..) |arg, i| {
|
||||
|
||||
@@ -1754,7 +1754,6 @@ pub const BundleOptions = struct {
|
||||
opts.polyfill_node_globals = opts.target == .browser;
|
||||
|
||||
Analytics.Features.filesystem_router += @as(usize, @intFromBool(opts.routes.routes_enabled));
|
||||
Analytics.Features.origin += @as(usize, @intFromBool(opts.origin.href.len > 0));
|
||||
Analytics.Features.macros += @as(usize, @intFromBool(opts.target == .bun_macro));
|
||||
Analytics.Features.external += @as(usize, @intFromBool(transform.external.len > 0));
|
||||
return opts;
|
||||
|
||||
Reference in New Issue
Block a user