From a4b0817cd3ce98288f28b2ffcaedabea8be8c5a9 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Mon, 8 Jul 2024 15:08:07 -0700 Subject: [PATCH] Print list of CPU features in crash reports (#12350) Co-authored-by: Jarred-Sumner --- CMakeLists.txt | 3 +- LATEST | 2 +- src/analytics/analytics_thread.zig | 4 +- src/bun.js/bindings/CPUFeatures.cpp | 110 ++++++++++++++++++++++++++++ src/bun.js/bindings/CPUFeatures.zig | 89 ++++++++++++++++++++++ src/crash_handler.zig | 8 ++ src/options.zig | 1 - 7 files changed, 212 insertions(+), 5 deletions(-) create mode 100644 src/bun.js/bindings/CPUFeatures.cpp create mode 100644 src/bun.js/bindings/CPUFeatures.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index fdceab1972..237cc31e0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/LATEST b/LATEST index 95ce23d450..b0c8928e40 100644 --- a/LATEST +++ b/LATEST @@ -1 +1 @@ -1.1.17 \ No newline at end of file +1.1.18 \ No newline at end of file diff --git a/src/analytics/analytics_thread.zig b/src/analytics/analytics_thread.zig index 551171f99a..532749437d 100644 --- a/src/analytics/analytics_thread.zig +++ b/src/analytics/analytics_thread.zig @@ -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 { diff --git a/src/bun.js/bindings/CPUFeatures.cpp b/src/bun.js/bindings/CPUFeatures.cpp new file mode 100644 index 0000000000..861de32dc1 --- /dev/null +++ b/src/bun.js/bindings/CPUFeatures.cpp @@ -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 + +#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(X86CPUFeature::sse42); + + if (IsProcessorFeaturePresent(PF_AVX_INSTRUCTIONS_AVAILABLE)) + features |= 1 << static_cast(X86CPUFeature::avx); + + if (IsProcessorFeaturePresent(PF_AVX2_INSTRUCTIONS_AVAILABLE)) + features |= 1 << static_cast(X86CPUFeature::avx2); + + if (IsProcessorFeaturePresent(PF_AVX512F_INSTRUCTIONS_AVAILABLE)) + features |= 1 << static_cast(X86CPUFeature::avx512); + +#else + +#if __has_builtin(__builtin_cpu_supports) + __builtin_cpu_init(); + + if (__builtin_cpu_supports("sse4.2")) + features |= 1 << static_cast(X86CPUFeature::sse42); + if (__builtin_cpu_supports("popcnt")) + features |= 1 << static_cast(X86CPUFeature::popcnt); + if (__builtin_cpu_supports("avx")) + features |= 1 << static_cast(X86CPUFeature::avx); + if (__builtin_cpu_supports("avx2")) + features |= 1 << static_cast(X86CPUFeature::avx2); + if (__builtin_cpu_supports("avx512f")) + features |= 1 << static_cast(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(AArch64CPUFeature::neon); + if (__builtin_cpu_supports("crypto")) + features |= 1 << static_cast(AArch64CPUFeature::fp); + if (__builtin_cpu_supports("aes")) + features |= 1 << static_cast(AArch64CPUFeature::aes); + if (__builtin_cpu_supports("crc32")) + features |= 1 << static_cast(AArch64CPUFeature::crc32); + if (__builtin_cpu_supports("atomics")) + features |= 1 << static_cast(AArch64CPUFeature::atomics); + if (__builtin_cpu_supports("sve")) + features |= 1 << static_cast(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 +} \ No newline at end of file diff --git a/src/bun.js/bindings/CPUFeatures.zig b/src/bun.js/bindings/CPUFeatures.zig new file mode 100644 index 0000000000..a5f6f44491 --- /dev/null +++ b/src/bun.js/bindings/CPUFeatures.zig @@ -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; diff --git a/src/crash_handler.zig b/src/crash_handler.zig index dc7b9aafa2..9fc3a2d8dc 100644 --- a/src/crash_handler.zig +++ b/src/crash_handler.zig @@ -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| { diff --git a/src/options.zig b/src/options.zig index 9a8293b7c0..d228c73a69 100644 --- a/src/options.zig +++ b/src/options.zig @@ -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;