Merge pull request #6829 from krisfur/master

Make the type hash 63-bit to not crash OMG JIT in WebKit under WASM.
This commit is contained in:
Jeroen van Rijn
2026-06-13 11:12:44 +02:00
committed by GitHub
3 changed files with 23 additions and 0 deletions

View File

@@ -539,6 +539,8 @@ struct BuildContext {
bool disallow_do;
bool show_import_graph;
bool webkit_switch_workaround;
IntegerDivisionByZeroKind integer_division_by_zero_behaviour;
LinkerChoice linker_choice;

View File

@@ -312,6 +312,7 @@ enum BuildFlagKind {
BuildFlag_Debug,
BuildFlag_DisableAssert,
BuildFlag_NoBoundsCheck,
BuildFlag_WebkitSwitchWorkaround,
BuildFlag_NoTypeAssert,
BuildFlag_NoDynamicLiterals,
BuildFlag_DynamicLiterals,
@@ -545,6 +546,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
add_flag(&build_flags, BuildFlag_Debug, str_lit("debug"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_DisableAssert, str_lit("disable-assert"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_NoBoundsCheck, str_lit("no-bounds-check"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_WebkitSwitchWorkaround, str_lit("webkit-switch-workaround"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_NoTypeAssert, str_lit("no-type-assert"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_NoThreadLocal, str_lit("no-thread-local"), BuildFlagParam_None, Command__does_check);
add_flag(&build_flags, BuildFlag_NoDynamicLiterals, str_lit("no-dynamic-literals"), BuildFlagParam_None, Command__does_check);
@@ -1235,6 +1237,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
case BuildFlag_NoBoundsCheck:
build_context.no_bounds_check = true;
break;
case BuildFlag_WebkitSwitchWorkaround:
build_context.webkit_switch_workaround = true;
break;
case BuildFlag_NoTypeAssert:
build_context.no_type_assert = true;
break;
@@ -2891,6 +2896,11 @@ gb_internal int print_show_help(String const arg0, String command, String option
print_usage_line(2, "Disables bounds checking program wide.");
}
if (print_flag("-webkit-switch-workaround")) {
print_usage_line(2, "Constrains 'typeid' values to 63 bits to avoid an OMG JIT crash in WebKit when running WASM builds.");
print_usage_line(2, "Only needed for 'js_wasm32'/'js_wasm64p32' targets run in Safari/WebKit. See: https://github.com/odin-lang/Odin/issues/6810");
}
if (print_flag("-no-crt")) {
print_usage_line(2, "Disables automatic linking with the C Run Time.");
}

View File

@@ -520,6 +520,17 @@ gb_internal u64 type_hash_canonical_type(Type *type) {
type_writer_make_hasher(&w, &w.hash_ctx);
write_type_to_canonical_string(&w, type);
u64 hash = typeid_hash_context_fini(&w.hash_ctx);
if (build_context.webkit_switch_workaround) {
// Clear the top bit so every `typeid` is in [1, 2^63). A `switch` over a
// typeid (e.g. a type switch over `any` in core:fmt) then has a case-value
// span < 2^63. WebKit's B3/OMG wasm JIT computes a switch's value range as
// a signed i64 (max - min); a span >= 2^63 overflows and makes it build a
// pathologically-sized jump table, OOM-crashing the tab.
// WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=317022
// Odin issue/PR: https://github.com/odin-lang/Odin/issues/6810
hash &= 0x7fffffffffffffffull;
hash = hash ? hash : 1;
}
type->canonical_hash.store(hash, std::memory_order_relaxed);