@@ -109,6 +109,54 @@ inline bool store_into_memory(
109109 return true ;
110110}
111111
112+ // / Checks that exception is one of the types expected to be thrown from bytes::resize().
113+ // / We catch ... in memory.grow implementation for the sake of smaller binary code and assert it's
114+ // / one of expected exceptions.
115+ [[maybe_unused]] bool is_resize_exception (std::exception_ptr exception) noexcept
116+ {
117+ try
118+ {
119+ std::rethrow_exception (exception);
120+ }
121+ catch (const std::bad_alloc&)
122+ {
123+ return true ;
124+ }
125+ catch (const std::length_error&)
126+ {
127+ return true ;
128+ }
129+ catch (...)
130+ {
131+ return false ;
132+ }
133+ }
134+
135+ // / Increases the size of memory by @a delta_pages.
136+ // / @return Number of memory pages before expansion if successful, otherwise 2^32-1 in case
137+ // / requested resize goes above @a memory_pages_limit or if allocation failed.
138+ inline uint32_t grow_memory (
139+ bytes& memory, uint32_t delta_pages, uint32_t memory_pages_limit) noexcept
140+ {
141+ const auto cur_pages = memory.size () / PageSize;
142+ assert (cur_pages <= size_t (std::numeric_limits<int32_t >::max ()));
143+ const auto new_pages = cur_pages + delta_pages;
144+ assert (new_pages >= cur_pages);
145+ if (new_pages > memory_pages_limit)
146+ return static_cast <uint32_t >(-1 );
147+
148+ try
149+ {
150+ memory.resize (new_pages * PageSize);
151+ return static_cast <uint32_t >(cur_pages);
152+ }
153+ catch (...)
154+ {
155+ assert (is_resize_exception (std::current_exception ()));
156+ return static_cast <uint32_t >(-1 );
157+ }
158+ }
159+
112160// / Converts the top stack item by truncating a float value to an integer value.
113161template <typename SrcT, typename DstT>
114162inline bool trunc (OperandStack& stack) noexcept
@@ -828,23 +876,8 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args,
828876 }
829877 case Instr::memory_grow:
830878 {
831- const auto delta = stack.pop ().as <uint32_t >();
832- const auto cur_pages = memory->size () / PageSize;
833- assert (cur_pages <= size_t (std::numeric_limits<int32_t >::max ()));
834- const auto new_pages = cur_pages + delta;
835- assert (new_pages >= cur_pages);
836- uint32_t ret = static_cast <uint32_t >(cur_pages);
837- try
838- {
839- if (new_pages > instance.memory_pages_limit )
840- throw std::bad_alloc ();
841- memory->resize (new_pages * PageSize);
842- }
843- catch (std::bad_alloc const &)
844- {
845- ret = static_cast <uint32_t >(-1 );
846- }
847- stack.push (ret);
879+ stack.top () =
880+ grow_memory (*memory, stack.top ().as <uint32_t >(), instance.memory_pages_limit );
848881 break ;
849882 }
850883 case Instr::i32_const:
0 commit comments