mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-10-19 22:49:47 +00:00
LibWasm: Try really hard to avoid touching the value stack
This commit adds a register allocator, with 8 available "register" slots. In testing with various random blobs, this moves anywhere from 30% to 74% of value accesses into predefined slots, and is about a ~20% perf increase end-to-end. To actually make this usable, a few structural changes were also made: - we no longer do one instruction per interpret call - trapping is an (unlikely) exit condition - the label and frame stacks are replaced with linked lists with a huge node cache size, as we only need to touch the last element and push/pop is very frequent.
This commit is contained in:
parent
998454028c
commit
0e5ecef848
Notes:
github-actions[bot]
2025-08-08 10:55:57 +00:00
Author: https://github.com/alimpfard
Commit: 0e5ecef848
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5060
Reviewed-by: https://github.com/Hendiadyoin1
Reviewed-by: https://github.com/R-Goc
Reviewed-by: https://github.com/awesomekling
Reviewed-by: https://github.com/gmta
9 changed files with 3217 additions and 1824 deletions
|
@ -52,54 +52,62 @@ struct BytecodeInterpreter final : public Interpreter {
|
|||
IndirectCall,
|
||||
};
|
||||
|
||||
template<bool HasCompiledList, bool HasDynamicInsnLimit>
|
||||
void interpret_impl(Configuration&, Expression const&);
|
||||
|
||||
protected:
|
||||
void interpret_instruction(Configuration&, InstructionPointer&, Instruction const&);
|
||||
void branch_to_label(Configuration&, LabelIndex);
|
||||
template<typename ReadT, typename PushT>
|
||||
void load_and_push(Configuration&, Instruction const&);
|
||||
bool load_and_push(Configuration&, Instruction const&);
|
||||
template<typename PopT, typename StoreT>
|
||||
void pop_and_store(Configuration&, Instruction const&);
|
||||
bool pop_and_store(Configuration&, Instruction const&);
|
||||
template<typename StoreT>
|
||||
bool store_value(Configuration&, Instruction const&, StoreT, size_t address_source);
|
||||
template<size_t N>
|
||||
void pop_and_store_lane_n(Configuration&, Instruction const&);
|
||||
bool pop_and_store_lane_n(Configuration&, Instruction const&);
|
||||
template<size_t M, size_t N, template<typename> typename SetSign>
|
||||
void load_and_push_mxn(Configuration&, Instruction const&);
|
||||
bool load_and_push_mxn(Configuration&, Instruction const&);
|
||||
template<size_t N>
|
||||
void load_and_push_lane_n(Configuration&, Instruction const&);
|
||||
bool load_and_push_lane_n(Configuration&, Instruction const&);
|
||||
template<size_t N>
|
||||
void load_and_push_zero_n(Configuration&, Instruction const&);
|
||||
bool load_and_push_zero_n(Configuration&, Instruction const&);
|
||||
template<size_t M>
|
||||
void load_and_push_m_splat(Configuration&, Instruction const&);
|
||||
bool load_and_push_m_splat(Configuration&, Instruction const&);
|
||||
template<size_t M, template<size_t> typename NativeType>
|
||||
void set_top_m_splat(Configuration&, NativeType<M>);
|
||||
template<size_t M, template<size_t> typename NativeType>
|
||||
void pop_and_push_m_splat(Configuration&, Instruction const&);
|
||||
template<typename M, template<typename> typename SetSign, typename VectorType = Native128ByteVectorOf<M, SetSign>>
|
||||
VectorType pop_vector(Configuration&);
|
||||
void store_to_memory(Configuration&, Instruction::MemoryArgument const&, ReadonlyBytes data, u32 base);
|
||||
void call_address(Configuration&, FunctionAddress, CallAddressSource = CallAddressSource::DirectCall);
|
||||
VectorType pop_vector(Configuration&, size_t source);
|
||||
bool store_to_memory(Configuration&, Instruction::MemoryArgument const&, ReadonlyBytes data, u32 base);
|
||||
bool call_address(Configuration&, FunctionAddress, CallAddressSource = CallAddressSource::DirectCall);
|
||||
|
||||
template<typename PopTypeLHS, typename PushType, typename Operator, typename PopTypeRHS = PopTypeLHS, typename... Args>
|
||||
void binary_numeric_operation(Configuration&, Args&&...);
|
||||
bool binary_numeric_operation(Configuration&, Args&&...);
|
||||
|
||||
template<typename PopType, typename PushType, typename Operator, typename... Args>
|
||||
void unary_operation(Configuration&, Args&&...);
|
||||
bool unary_operation(Configuration&, Args&&...);
|
||||
|
||||
template<typename T>
|
||||
T read_value(ReadonlyBytes data);
|
||||
|
||||
ALWAYS_INLINE bool trap_if_not(bool value, StringView reason)
|
||||
{
|
||||
if (!value)
|
||||
if (!value) [[unlikely]] {
|
||||
m_trap = Trap { ByteString(reason) };
|
||||
return !m_trap.has<Empty>();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename... Rest>
|
||||
ALWAYS_INLINE bool trap_if_not(bool value, StringView reason, CheckedFormatString<StringView, Rest...> format, Rest const&... args)
|
||||
{
|
||||
if (!value)
|
||||
if (!value) [[unlikely]] {
|
||||
m_trap = Trap { ByteString::formatted(move(format), reason, args...) };
|
||||
return !m_trap.has<Empty>();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Variant<Trap, Empty> m_trap;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue