diff --git a/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp b/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp index 47a9af93260..6a3cfe9de26 100644 --- a/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp +++ b/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp @@ -267,8 +267,7 @@ void BytecodeInterpreter::interpret_impl(Configuration& configuration, Expressio RUN_NEXT_INSTRUCTION(CouldHaveChangedIP::Yes); } case Instructions::return_.value(): { - while (configuration.label_stack().size() - 1 != configuration.frame().label_index()) - configuration.label_stack().take_last(); + configuration.label_stack().shrink(configuration.frame().label_index() + 1, true); configuration.ip() = max_ip_value; RUN_NEXT_INSTRUCTION(CouldHaveChangedIP::Yes); } @@ -2233,8 +2232,8 @@ void BytecodeInterpreter::interpret_impl(Configuration& configuration, Expressio void BytecodeInterpreter::branch_to_label(Configuration& configuration, LabelIndex index) { dbgln_if(WASM_TRACE_DEBUG, "Branch to label with index {}...", index.value()); - for (size_t i = 0; i < index.value(); ++i) - configuration.label_stack().take_last(); + auto& label_stack = configuration.label_stack(); + label_stack.shrink(label_stack.size() - index.value(), true); auto label = configuration.label_stack().last(); dbgln_if(WASM_TRACE_DEBUG, "...which is actually IP {}, and has {} result(s)", label.continuation().value(), label.arity()); diff --git a/Libraries/LibWasm/AbstractMachine/Configuration.h b/Libraries/LibWasm/AbstractMachine/Configuration.h index d3fca15caf0..eb5e161bb18 100644 --- a/Libraries/LibWasm/AbstractMachine/Configuration.h +++ b/Libraries/LibWasm/AbstractMachine/Configuration.h @@ -25,6 +25,8 @@ public: frame.label_index() = m_label_stack.size(); if (auto hint = frame.expression().stack_usage_hint(); hint.has_value()) m_value_stack.ensure_capacity(*hint + m_value_stack.size()); + if (auto hint = frame.expression().frame_usage_hint(); hint.has_value()) + m_label_stack.ensure_capacity(*hint + m_label_stack.size()); m_frame_stack.append(move(frame)); m_label_stack.append(label); m_locals_base = m_frame_stack.unchecked_last().locals().data(); @@ -120,7 +122,7 @@ public: private: Store& m_store; Vector m_value_stack; - DoublyLinkedList m_label_stack; + Vector m_label_stack; DoublyLinkedList m_frame_stack; size_t m_depth { 0 }; u64 m_ip { 0 }; diff --git a/Libraries/LibWasm/AbstractMachine/Validator.cpp b/Libraries/LibWasm/AbstractMachine/Validator.cpp index 19efac5e3b6..94a54ec45d0 100644 --- a/Libraries/LibWasm/AbstractMachine/Validator.cpp +++ b/Libraries/LibWasm/AbstractMachine/Validator.cpp @@ -271,6 +271,7 @@ ErrorOr Validator::validate(CodeSection const& section) } function_validator.m_frames.empend(function_type, FrameKind::Function, (size_t)0); + function_validator.m_max_frame_size = max(function_validator.m_max_frame_size, function_validator.m_frames.size()); auto results = TRY(function_validator.validate(function.body(), function_type.results())); if (results.result_types.size() != function_type.results().size()) @@ -1971,6 +1972,7 @@ VALIDATE_INSTRUCTION(block) TRY(stack.take(parameters[parameters.size() - i])); m_frames.empend(block_type, FrameKind::Block, stack.size()); + m_max_frame_size = max(m_max_frame_size, m_frames.size()); for (auto& parameter : parameters) stack.append(parameter); @@ -1987,6 +1989,7 @@ VALIDATE_INSTRUCTION(loop) TRY(stack.take(parameters[parameters.size() - i])); m_frames.empend(block_type, FrameKind::Loop, stack.size()); + m_max_frame_size = max(m_max_frame_size, m_frames.size()); for (auto& parameter : parameters) stack.append(parameter); @@ -2007,6 +2010,7 @@ VALIDATE_INSTRUCTION(if_) TRY(stack.take(parameters[parameters.size() - i])); m_frames.empend(block_type, FrameKind::If, stack.size()); + m_max_frame_size = max(m_max_frame_size, m_frames.size()); for (auto& parameter : parameters) stack.append(parameter); @@ -3734,9 +3738,12 @@ ErrorOr Validator::validate(Ex for (auto& type : result_types) stack.append(type); m_frames.take_last(); - VERIFY(m_frames.is_empty()); expression.set_stack_usage_hint(stack.max_known_size()); + expression.set_frame_usage_hint(m_max_frame_size); + + VERIFY(m_frames.is_empty()); + m_max_frame_size = 0; // Now that we're in happy land, try to compile the expression down to a list of labels to help dispatch. expression.compiled_instructions = try_compile_instructions(expression, m_context.functions.span()); diff --git a/Libraries/LibWasm/AbstractMachine/Validator.h b/Libraries/LibWasm/AbstractMachine/Validator.h index 64b32befac4..69d59fd985a 100644 --- a/Libraries/LibWasm/AbstractMachine/Validator.h +++ b/Libraries/LibWasm/AbstractMachine/Validator.h @@ -361,6 +361,7 @@ private: Context m_context; Vector m_frames; + size_t m_max_frame_size { 0 }; COWVector m_globals_without_internal_globals; }; diff --git a/Libraries/LibWasm/Types.h b/Libraries/LibWasm/Types.h index 495f8409267..6093fc12de3 100644 --- a/Libraries/LibWasm/Types.h +++ b/Libraries/LibWasm/Types.h @@ -758,11 +758,15 @@ public: void set_stack_usage_hint(size_t value) const { m_stack_usage_hint = value; } auto stack_usage_hint() const { return m_stack_usage_hint; } + void set_frame_usage_hint(size_t value) const { m_frame_usage_hint = value; } + auto frame_usage_hint() const { return m_frame_usage_hint; } + mutable CompiledInstructions compiled_instructions; private: Vector m_instructions; mutable Optional m_stack_usage_hint; + mutable Optional m_frame_usage_hint; }; class GlobalSection {