mirror of
https://github.com/zebrajr/ladybird.git
synced 2025-12-06 00:19:53 +01:00
LibWasm: Use [[gnu::musttail]] on new-enough GCC versions
This is supported starting GCC 15. The warning -Wmaybe-musttail-local-addr complained about &value possibly escaping (it cannot, but gcc is being pessimistic about store_to_memory), so a little rearrangement of that function was necessary.
This commit is contained in:
parent
15bb9fee71
commit
2397ae4af5
|
|
@ -25,10 +25,20 @@
|
||||||
|
|
||||||
using namespace AK::SIMD;
|
using namespace AK::SIMD;
|
||||||
|
|
||||||
|
#ifdef AK_COMPILER_CLANG
|
||||||
|
# define TAILCALL [[clang::musttail]]
|
||||||
|
# define HAS_TAILCALL
|
||||||
|
#elif defined(AK_COMPILER_GCC) && (__GNUC__ > 14)
|
||||||
|
# define TAILCALL [[gnu::musttail]]
|
||||||
|
# define HAS_TAILCALL
|
||||||
|
#else
|
||||||
|
# define TAILCALL
|
||||||
|
#endif
|
||||||
|
|
||||||
// ASAN allocates frames for all the not-explicitly-tail-called functions,
|
// ASAN allocates frames for all the not-explicitly-tail-called functions,
|
||||||
// which blows out the stack. So disable direct threading when ASAN is enabled.
|
// which blows out the stack. So disable direct threading when ASAN is enabled.
|
||||||
// We use the explicit annotation on clang, so allow it there.
|
// We use the explicit annotation where available, so allow it there.
|
||||||
#if defined(HAS_ADDRESS_SANITIZER) && !defined(AK_COMPILER_CLANG)
|
#if defined(HAS_ADDRESS_SANITIZER) && !defined(HAS_TAILCALL)
|
||||||
constexpr static auto should_try_to_use_direct_threading = false;
|
constexpr static auto should_try_to_use_direct_threading = false;
|
||||||
#else
|
#else
|
||||||
constexpr static auto should_try_to_use_direct_threading = true;
|
constexpr static auto should_try_to_use_direct_threading = true;
|
||||||
|
|
@ -117,11 +127,6 @@ struct InstructionHandler { };
|
||||||
template<bool HasDynamicInsnLimit, typename Continue> \
|
template<bool HasDynamicInsnLimit, typename Continue> \
|
||||||
Outcome InstructionHandler<Instructions::name.value()>::operator()(HANDLER_PARAMS(DECOMPOSE_PARAMS))
|
Outcome InstructionHandler<Instructions::name.value()>::operator()(HANDLER_PARAMS(DECOMPOSE_PARAMS))
|
||||||
|
|
||||||
#ifdef AK_COMPILER_CLANG
|
|
||||||
# define TAILCALL [[clang::musttail]]
|
|
||||||
#else
|
|
||||||
# define TAILCALL
|
|
||||||
#endif
|
|
||||||
struct Continue {
|
struct Continue {
|
||||||
static Outcome operator()(BytecodeInterpreter& interpreter, Configuration& configuration, Instruction const*, SourcesAndDestination addresses, u64 current_ip_value, Dispatch const* cc)
|
static Outcome operator()(BytecodeInterpreter& interpreter, Configuration& configuration, Instruction const*, SourcesAndDestination addresses, u64 current_ip_value, Dispatch const* cc)
|
||||||
{
|
{
|
||||||
|
|
@ -1571,26 +1576,27 @@ HANDLE_INSTRUCTION(memory_grow)
|
||||||
|
|
||||||
HANDLE_INSTRUCTION(memory_fill)
|
HANDLE_INSTRUCTION(memory_fill)
|
||||||
{
|
{
|
||||||
auto& args = instruction->arguments().get<Instruction::MemoryIndexArgument>();
|
{
|
||||||
auto address = configuration.frame().module().memories().data()[args.memory_index.value()];
|
auto& args = instruction->arguments().get<Instruction::MemoryIndexArgument>();
|
||||||
auto instance = configuration.store().get(address);
|
auto address = configuration.frame().module().memories().data()[args.memory_index.value()];
|
||||||
// bounds checked by verifier.
|
auto instance = configuration.store().get(address);
|
||||||
auto count = configuration.take_source(0, addresses.sources).to<u32>();
|
// bounds checked by verifier.
|
||||||
u8 value = static_cast<u8>(configuration.take_source(1, addresses.sources).to<u32>());
|
auto count = configuration.take_source(0, addresses.sources).to<u32>();
|
||||||
auto destination_offset = configuration.take_source(2, addresses.sources).to<u32>();
|
auto destination_offset = configuration.take_source(2, addresses.sources).to<u32>();
|
||||||
|
|
||||||
Checked<u32> checked_end = destination_offset;
|
Checked<u32> checked_end = destination_offset;
|
||||||
checked_end += count;
|
checked_end += count;
|
||||||
TRAP_IN_LOOP_IF_NOT(!checked_end.has_overflow() && static_cast<size_t>(checked_end.value()) <= instance->data().size());
|
TRAP_IN_LOOP_IF_NOT(!checked_end.has_overflow() && static_cast<size_t>(checked_end.value()) <= instance->data().size());
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
TAILCALL
|
TAILCALL return continue_(HANDLER_PARAMS(DECOMPOSE_PARAMS_NAME_ONLY));
|
||||||
return continue_(HANDLER_PARAMS(DECOMPOSE_PARAMS_NAME_ONLY));
|
|
||||||
|
|
||||||
Instruction::MemoryArgument memarg { 0, 0, args.memory_index };
|
Instruction::MemoryArgument memarg { 0, 0, args.memory_index };
|
||||||
for (u32 i = 0; i < count; ++i) {
|
u8 value = static_cast<u8>(configuration.take_source(1, addresses.sources).to<u32>());
|
||||||
if (interpreter.store_to_memory(configuration, memarg, { &value, sizeof(value) }, destination_offset + i))
|
for (u32 i = 0; i < count; ++i) {
|
||||||
return Outcome::Return;
|
if (interpreter.store_to_memory(configuration, memarg, { &value, sizeof(value) }, destination_offset + i))
|
||||||
|
return Outcome::Return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TAILCALL return continue_(HANDLER_PARAMS(DECOMPOSE_PARAMS_NAME_ONLY));
|
TAILCALL return continue_(HANDLER_PARAMS(DECOMPOSE_PARAMS_NAME_ONLY));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user