diff --git a/src/prebuilt/wasm2c_source_declarations.cc b/src/prebuilt/wasm2c_source_declarations.cc index 148357494..965ace7e2 100644 --- a/src/prebuilt/wasm2c_source_declarations.cc +++ b/src/prebuilt/wasm2c_source_declarations.cc @@ -137,22 +137,65 @@ R"w2c_template( #define UNREACHABLE TRAP(UNREACHABLE) )w2c_template" R"w2c_template( -static inline bool func_types_eq(const wasm_rt_func_type_t a, +#if defined(__clang__) || defined(__GNUC__) )w2c_template" -R"w2c_template( const wasm_rt_func_type_t b) { +R"w2c_template(#define W2C_COLD_FUNC __attribute__((noinline, cold)) )w2c_template" -R"w2c_template( return (a == b) || LIKELY(a && b && !memcmp(a, b, 32)); +R"w2c_template(#elif defined(_MSC_VER) )w2c_template" -R"w2c_template(} +R"w2c_template(#define W2C_COLD_FUNC __declspec(noinline) +)w2c_template" +R"w2c_template(#else +)w2c_template" +R"w2c_template(#define W2C_COLD_FUNC +)w2c_template" +R"w2c_template(#endif )w2c_template" R"w2c_template( -#define CHECK_CALL_INDIRECT(table, ft, x) \ +W2C_COLD_FUNC static bool func_types_eq_slowpath( +)w2c_template" +R"w2c_template( const wasm_rt_funcref_table_t* table, +)w2c_template" +R"w2c_template( const wasm_rt_func_type_t expected_type, +)w2c_template" +R"w2c_template( uint32_t index) { +)w2c_template" +R"w2c_template( const size_t sha256size = 32; +)w2c_template" +R"w2c_template( if (index >= table->size) { +)w2c_template" +R"w2c_template( // Table index out of bounds. Raise Wasm trap. +)w2c_template" +R"w2c_template( TRAP(CALL_INDIRECT); +)w2c_template" +R"w2c_template( return false; )w2c_template" -R"w2c_template( (LIKELY((x) < table.size && table.data[x].func && \ +R"w2c_template( } +)w2c_template" +R"w2c_template( const wasm_rt_funcref_t* const func_ref = &table->data[index]; +)w2c_template" +R"w2c_template( if (!expected_type || !func_ref->func || !func_ref->func_type || +)w2c_template" +R"w2c_template( memcmp(expected_type, func_ref->func_type, sha256size) != 0) { +)w2c_template" +R"w2c_template( // Type check failed. Raise Wasm trap. +)w2c_template" +R"w2c_template( TRAP(CALL_INDIRECT); +)w2c_template" +R"w2c_template( return false; +)w2c_template" +R"w2c_template( } +)w2c_template" +R"w2c_template( return true; +)w2c_template" +R"w2c_template(} +)w2c_template" +R"w2c_template( +#define CHECK_CALL_INDIRECT(table, ft, x) \ )w2c_template" -R"w2c_template( func_types_eq(ft, table.data[x].func_type)) || \ +R"w2c_template( (LIKELY((x) < table.size && ft == table.data[x].func_type) || \ )w2c_template" -R"w2c_template( TRAP(CALL_INDIRECT)) +R"w2c_template( func_types_eq_slowpath(&(table), ft, x)) )w2c_template" R"w2c_template( #define DO_CALL_INDIRECT(table, t, x, ...) ((t)table.data[x].func)(__VA_ARGS__) diff --git a/src/template/wasm2c.declarations.c b/src/template/wasm2c.declarations.c index ae9dc3008..fce64b0d8 100644 --- a/src/template/wasm2c.declarations.c +++ b/src/template/wasm2c.declarations.c @@ -73,15 +73,37 @@ static inline void wasm_rt_segue_write_base(void* base) { #define UNREACHABLE TRAP(UNREACHABLE) -static inline bool func_types_eq(const wasm_rt_func_type_t a, - const wasm_rt_func_type_t b) { - return (a == b) || LIKELY(a && b && !memcmp(a, b, 32)); +#if defined(__clang__) || defined(__GNUC__) +#define W2C_COLD_FUNC __attribute__((noinline, cold)) +#elif defined(_MSC_VER) +#define W2C_COLD_FUNC __declspec(noinline) +#else +#define W2C_COLD_FUNC +#endif + +W2C_COLD_FUNC static bool func_types_eq_slowpath( + const wasm_rt_funcref_table_t* table, + const wasm_rt_func_type_t expected_type, + uint32_t index) { + const size_t sha256size = 32; + if (index >= table->size) { + // Table index out of bounds. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + const wasm_rt_funcref_t* const func_ref = &table->data[index]; + if (!expected_type || !func_ref->func || !func_ref->func_type || + memcmp(expected_type, func_ref->func_type, sha256size) != 0) { + // Type check failed. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + return true; } -#define CHECK_CALL_INDIRECT(table, ft, x) \ - (LIKELY((x) < table.size && table.data[x].func && \ - func_types_eq(ft, table.data[x].func_type)) || \ - TRAP(CALL_INDIRECT)) +#define CHECK_CALL_INDIRECT(table, ft, x) \ + (LIKELY((x) < table.size && ft == table.data[x].func_type) || \ + func_types_eq_slowpath(&(table), ft, x)) #define DO_CALL_INDIRECT(table, t, x, ...) ((t)table.data[x].func)(__VA_ARGS__) diff --git a/test/wasm2c/add.txt b/test/wasm2c/add.txt index f33780f15..6a9b4f234 100644 --- a/test/wasm2c/add.txt +++ b/test/wasm2c/add.txt @@ -140,15 +140,37 @@ static inline void wasm_rt_segue_write_base(void* base) { #define UNREACHABLE TRAP(UNREACHABLE) -static inline bool func_types_eq(const wasm_rt_func_type_t a, - const wasm_rt_func_type_t b) { - return (a == b) || LIKELY(a && b && !memcmp(a, b, 32)); -} +#if defined(__clang__) || defined(__GNUC__) +#define W2C_COLD_FUNC __attribute__((noinline, cold)) +#elif defined(_MSC_VER) +#define W2C_COLD_FUNC __declspec(noinline) +#else +#define W2C_COLD_FUNC +#endif -#define CHECK_CALL_INDIRECT(table, ft, x) \ - (LIKELY((x) < table.size && table.data[x].func && \ - func_types_eq(ft, table.data[x].func_type)) || \ - TRAP(CALL_INDIRECT)) +W2C_COLD_FUNC static bool func_types_eq_slowpath( + const wasm_rt_funcref_table_t* table, + const wasm_rt_func_type_t expected_type, + uint32_t index) { + const size_t sha256size = 32; + if (index >= table->size) { + // Table index out of bounds. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + const wasm_rt_funcref_t* const func_ref = &table->data[index]; + if (!expected_type || !func_ref->func || !func_ref->func_type || + memcmp(expected_type, func_ref->func_type, sha256size) != 0) { + // Type check failed. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + return true; +} + +#define CHECK_CALL_INDIRECT(table, ft, x) \ + (LIKELY((x) < table.size && ft == table.data[x].func_type) || \ + func_types_eq_slowpath(&(table), ft, x)) #define DO_CALL_INDIRECT(table, t, x, ...) ((t)table.data[x].func)(__VA_ARGS__) diff --git a/test/wasm2c/check-imports.txt b/test/wasm2c/check-imports.txt index 15e4ea447..0e48f43eb 100644 --- a/test/wasm2c/check-imports.txt +++ b/test/wasm2c/check-imports.txt @@ -165,15 +165,37 @@ static inline void wasm_rt_segue_write_base(void* base) { #define UNREACHABLE TRAP(UNREACHABLE) -static inline bool func_types_eq(const wasm_rt_func_type_t a, - const wasm_rt_func_type_t b) { - return (a == b) || LIKELY(a && b && !memcmp(a, b, 32)); -} +#if defined(__clang__) || defined(__GNUC__) +#define W2C_COLD_FUNC __attribute__((noinline, cold)) +#elif defined(_MSC_VER) +#define W2C_COLD_FUNC __declspec(noinline) +#else +#define W2C_COLD_FUNC +#endif -#define CHECK_CALL_INDIRECT(table, ft, x) \ - (LIKELY((x) < table.size && table.data[x].func && \ - func_types_eq(ft, table.data[x].func_type)) || \ - TRAP(CALL_INDIRECT)) +W2C_COLD_FUNC static bool func_types_eq_slowpath( + const wasm_rt_funcref_table_t* table, + const wasm_rt_func_type_t expected_type, + uint32_t index) { + const size_t sha256size = 32; + if (index >= table->size) { + // Table index out of bounds. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + const wasm_rt_funcref_t* const func_ref = &table->data[index]; + if (!expected_type || !func_ref->func || !func_ref->func_type || + memcmp(expected_type, func_ref->func_type, sha256size) != 0) { + // Type check failed. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + return true; +} + +#define CHECK_CALL_INDIRECT(table, ft, x) \ + (LIKELY((x) < table.size && ft == table.data[x].func_type) || \ + func_types_eq_slowpath(&(table), ft, x)) #define DO_CALL_INDIRECT(table, t, x, ...) ((t)table.data[x].func)(__VA_ARGS__) diff --git a/test/wasm2c/export-names.txt b/test/wasm2c/export-names.txt index be10c3be1..54ab285c2 100644 --- a/test/wasm2c/export-names.txt +++ b/test/wasm2c/export-names.txt @@ -165,15 +165,37 @@ static inline void wasm_rt_segue_write_base(void* base) { #define UNREACHABLE TRAP(UNREACHABLE) -static inline bool func_types_eq(const wasm_rt_func_type_t a, - const wasm_rt_func_type_t b) { - return (a == b) || LIKELY(a && b && !memcmp(a, b, 32)); +#if defined(__clang__) || defined(__GNUC__) +#define W2C_COLD_FUNC __attribute__((noinline, cold)) +#elif defined(_MSC_VER) +#define W2C_COLD_FUNC __declspec(noinline) +#else +#define W2C_COLD_FUNC +#endif + +W2C_COLD_FUNC static bool func_types_eq_slowpath( + const wasm_rt_funcref_table_t* table, + const wasm_rt_func_type_t expected_type, + uint32_t index) { + const size_t sha256size = 32; + if (index >= table->size) { + // Table index out of bounds. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + const wasm_rt_funcref_t* const func_ref = &table->data[index]; + if (!expected_type || !func_ref->func || !func_ref->func_type || + memcmp(expected_type, func_ref->func_type, sha256size) != 0) { + // Type check failed. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + return true; } -#define CHECK_CALL_INDIRECT(table, ft, x) \ - (LIKELY((x) < table.size && table.data[x].func && \ - func_types_eq(ft, table.data[x].func_type)) || \ - TRAP(CALL_INDIRECT)) +#define CHECK_CALL_INDIRECT(table, ft, x) \ + (LIKELY((x) < table.size && ft == table.data[x].func_type) || \ + func_types_eq_slowpath(&(table), ft, x)) #define DO_CALL_INDIRECT(table, t, x, ...) ((t)table.data[x].func)(__VA_ARGS__) diff --git a/test/wasm2c/hello.txt b/test/wasm2c/hello.txt index 92c12a57c..6a6274f30 100644 --- a/test/wasm2c/hello.txt +++ b/test/wasm2c/hello.txt @@ -172,15 +172,37 @@ static inline void wasm_rt_segue_write_base(void* base) { #define UNREACHABLE TRAP(UNREACHABLE) -static inline bool func_types_eq(const wasm_rt_func_type_t a, - const wasm_rt_func_type_t b) { - return (a == b) || LIKELY(a && b && !memcmp(a, b, 32)); -} +#if defined(__clang__) || defined(__GNUC__) +#define W2C_COLD_FUNC __attribute__((noinline, cold)) +#elif defined(_MSC_VER) +#define W2C_COLD_FUNC __declspec(noinline) +#else +#define W2C_COLD_FUNC +#endif -#define CHECK_CALL_INDIRECT(table, ft, x) \ - (LIKELY((x) < table.size && table.data[x].func && \ - func_types_eq(ft, table.data[x].func_type)) || \ - TRAP(CALL_INDIRECT)) +W2C_COLD_FUNC static bool func_types_eq_slowpath( + const wasm_rt_funcref_table_t* table, + const wasm_rt_func_type_t expected_type, + uint32_t index) { + const size_t sha256size = 32; + if (index >= table->size) { + // Table index out of bounds. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + const wasm_rt_funcref_t* const func_ref = &table->data[index]; + if (!expected_type || !func_ref->func || !func_ref->func_type || + memcmp(expected_type, func_ref->func_type, sha256size) != 0) { + // Type check failed. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + return true; +} + +#define CHECK_CALL_INDIRECT(table, ft, x) \ + (LIKELY((x) < table.size && ft == table.data[x].func_type) || \ + func_types_eq_slowpath(&(table), ft, x)) #define DO_CALL_INDIRECT(table, t, x, ...) ((t)table.data[x].func)(__VA_ARGS__) diff --git a/test/wasm2c/minimal.txt b/test/wasm2c/minimal.txt index ba4df5499..1afe9fb32 100644 --- a/test/wasm2c/minimal.txt +++ b/test/wasm2c/minimal.txt @@ -134,15 +134,37 @@ static inline void wasm_rt_segue_write_base(void* base) { #define UNREACHABLE TRAP(UNREACHABLE) -static inline bool func_types_eq(const wasm_rt_func_type_t a, - const wasm_rt_func_type_t b) { - return (a == b) || LIKELY(a && b && !memcmp(a, b, 32)); -} +#if defined(__clang__) || defined(__GNUC__) +#define W2C_COLD_FUNC __attribute__((noinline, cold)) +#elif defined(_MSC_VER) +#define W2C_COLD_FUNC __declspec(noinline) +#else +#define W2C_COLD_FUNC +#endif -#define CHECK_CALL_INDIRECT(table, ft, x) \ - (LIKELY((x) < table.size && table.data[x].func && \ - func_types_eq(ft, table.data[x].func_type)) || \ - TRAP(CALL_INDIRECT)) +W2C_COLD_FUNC static bool func_types_eq_slowpath( + const wasm_rt_funcref_table_t* table, + const wasm_rt_func_type_t expected_type, + uint32_t index) { + const size_t sha256size = 32; + if (index >= table->size) { + // Table index out of bounds. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + const wasm_rt_funcref_t* const func_ref = &table->data[index]; + if (!expected_type || !func_ref->func || !func_ref->func_type || + memcmp(expected_type, func_ref->func_type, sha256size) != 0) { + // Type check failed. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + return true; +} + +#define CHECK_CALL_INDIRECT(table, ft, x) \ + (LIKELY((x) < table.size && ft == table.data[x].func_type) || \ + func_types_eq_slowpath(&(table), ft, x)) #define DO_CALL_INDIRECT(table, t, x, ...) ((t)table.data[x].func)(__VA_ARGS__) diff --git a/test/wasm2c/tail-calls.txt b/test/wasm2c/tail-calls.txt index 847a36515..ea6dd154c 100644 --- a/test/wasm2c/tail-calls.txt +++ b/test/wasm2c/tail-calls.txt @@ -164,15 +164,37 @@ static inline void wasm_rt_segue_write_base(void* base) { #define UNREACHABLE TRAP(UNREACHABLE) -static inline bool func_types_eq(const wasm_rt_func_type_t a, - const wasm_rt_func_type_t b) { - return (a == b) || LIKELY(a && b && !memcmp(a, b, 32)); +#if defined(__clang__) || defined(__GNUC__) +#define W2C_COLD_FUNC __attribute__((noinline, cold)) +#elif defined(_MSC_VER) +#define W2C_COLD_FUNC __declspec(noinline) +#else +#define W2C_COLD_FUNC +#endif + +W2C_COLD_FUNC static bool func_types_eq_slowpath( + const wasm_rt_funcref_table_t* table, + const wasm_rt_func_type_t expected_type, + uint32_t index) { + const size_t sha256size = 32; + if (index >= table->size) { + // Table index out of bounds. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + const wasm_rt_funcref_t* const func_ref = &table->data[index]; + if (!expected_type || !func_ref->func || !func_ref->func_type || + memcmp(expected_type, func_ref->func_type, sha256size) != 0) { + // Type check failed. Raise Wasm trap. + TRAP(CALL_INDIRECT); + return false; + } + return true; } -#define CHECK_CALL_INDIRECT(table, ft, x) \ - (LIKELY((x) < table.size && table.data[x].func && \ - func_types_eq(ft, table.data[x].func_type)) || \ - TRAP(CALL_INDIRECT)) +#define CHECK_CALL_INDIRECT(table, ft, x) \ + (LIKELY((x) < table.size && ft == table.data[x].func_type) || \ + func_types_eq_slowpath(&(table), ft, x)) #define DO_CALL_INDIRECT(table, t, x, ...) ((t)table.data[x].func)(__VA_ARGS__)