Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions lib/fizzy/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,10 +641,7 @@ execution_result execute(
const auto& code = instance.module.codesec[code_idx];
auto* const memory = instance.memory.get();

std::vector<uint64_t> locals = std::move(args);
locals.resize(locals.size() + code.local_count);

OperandStack stack(static_cast<size_t>(code.max_stack_height));
OperandStack stack(args, code.local_count, static_cast<size_t>(code.max_stack_height));

LabelStack labels;
// The function's implicit block.
Expand Down Expand Up @@ -843,22 +840,19 @@ execution_result execute(
case Instr::local_get:
{
const auto idx = read<uint32_t>(immediates);
assert(idx <= locals.size());
stack.push(locals[idx]);
stack.push(stack.local(idx));
break;
}
case Instr::local_set:
{
const auto idx = read<uint32_t>(immediates);
assert(idx <= locals.size());
locals[idx] = stack.pop();
stack.local(idx) = stack.pop();
break;
}
case Instr::local_tee:
{
const auto idx = read<uint32_t>(immediates);
assert(idx <= locals.size());
locals[idx] = stack.top();
stack.local(idx) = stack.top();
break;
}
case Instr::global_get:
Expand Down
37 changes: 26 additions & 11 deletions lib/fizzy/stack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,32 +58,40 @@ class Stack : public std::vector<T>

class OperandStack
{
/// The pointer to the top item, or below the stack bottom if stack is empty.
/// The pointer to the stack top item, or below the stack bottom if stack is empty.
///
/// This pointer always alias m_storage, but it is kept as the first field
/// because it is accessed the most. Therefore, it must be initialized
/// in the constructor after the m_storage.
uint64_t* m_top;

/// The pointer to the stack bottom.
///
/// TODO: This value is const, but because of the initialization order it must be assigned
/// after m_storage initialization.
uint64_t* m_bottom;

/// The storage for items.
std::unique_ptr<uint64_t[]> m_storage;

public:
/// Default constructor. Sets the top item pointer to below the stack bottom.
explicit OperandStack(size_t max_stack_height)
: m_storage{std::make_unique<uint64_t[]>(max_stack_height)}
/// Constructor.
OperandStack(const std::vector<uint64_t>& args, size_t num_locals, size_t max_stack_height)
{
m_top = m_storage.get() - 1;
const auto locals_size = args.size() + num_locals;
const auto storage_size = locals_size + max_stack_height;
m_storage = std::make_unique<uint64_t[]>(storage_size);
std::copy(std::begin(args), std::end(args), m_storage.get());
std::fill_n(m_storage.get() + args.size(), num_locals, 0);
m_bottom = m_storage.get() + locals_size;
m_top = m_bottom - 1;
}

OperandStack(const OperandStack&) = delete;
OperandStack& operator=(const OperandStack&) = delete;

/// The current number of items on the stack (aka stack height).
[[nodiscard]] size_t size() const noexcept
{
return static_cast<size_t>(m_top + 1 - m_storage.get());
}
[[nodiscard]] size_t size() const noexcept { return static_cast<size_t>(m_top + 1 - m_bottom); }

/// Returns the reference to the top item.
/// Requires non-empty stack.
Expand Down Expand Up @@ -121,13 +129,20 @@ class OperandStack
{
assert(new_size <= size());
// For new_size == 0, the m_top will point below the storage.
m_top = m_storage.get() + new_size - 1;
m_top = m_bottom + new_size - 1;
}

/// Returns iterator to the bottom of the stack.
[[nodiscard]] const uint64_t* rbegin() const noexcept { return m_storage.get(); }
[[nodiscard]] const uint64_t* rbegin() const noexcept { return m_bottom; }

/// Returns end iterator counting from the bottom of the stack.
[[nodiscard]] const uint64_t* rend() const noexcept { return m_top + 1; }

/// Access the local of the given index.
uint64_t& local(size_t index) noexcept
{
assert(index < static_cast<size_t>(m_bottom - m_storage.get()));
return m_storage[index];
}
};
} // namespace fizzy
14 changes: 7 additions & 7 deletions test/unittests/stack_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,15 +170,15 @@ TEST(stack, clear_on_empty)

TEST(operand_stack, construct)
{
OperandStack stack(0);
OperandStack stack({}, 0, 0);
EXPECT_EQ(stack.size(), 0);
stack.shrink(0);
EXPECT_EQ(stack.size(), 0);
}

TEST(operand_stack, top)
{
OperandStack stack(1);
OperandStack stack({}, 0, 1);
EXPECT_EQ(stack.size(), 0);

stack.push(1);
Expand All @@ -202,7 +202,7 @@ TEST(operand_stack, top)

TEST(operand_stack, small)
{
OperandStack stack(3);
OperandStack stack({}, 0, 3);
EXPECT_EQ(stack.size(), 0);

stack.push(1);
Expand Down Expand Up @@ -231,7 +231,7 @@ TEST(operand_stack, small)
TEST(operand_stack, large)
{
constexpr auto max_height = 33;
OperandStack stack(max_height);
OperandStack stack({}, 0, max_height);

for (unsigned i = 0; i < max_height; ++i)
stack.push(i);
Expand All @@ -245,7 +245,7 @@ TEST(operand_stack, large)
TEST(operand_stack, shrink)
{
constexpr auto max_height = 60;
OperandStack stack(max_height);
OperandStack stack({}, 0, max_height);

for (unsigned i = 0; i < max_height; ++i)
stack.push(i);
Expand All @@ -261,7 +261,7 @@ TEST(operand_stack, shrink)

TEST(operand_stack, rbegin_rend)
{
OperandStack stack(3);
OperandStack stack({}, 0, 3);
EXPECT_EQ(stack.rbegin(), stack.rend());

stack.push(1);
Expand All @@ -274,7 +274,7 @@ TEST(operand_stack, rbegin_rend)

TEST(operand_stack, to_vector)
{
OperandStack stack(3);
OperandStack stack({}, 0, 3);
EXPECT_THAT(std::vector(stack.rbegin(), stack.rend()), IsEmpty());

stack.push(1);
Expand Down