Skip to content
Open
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
6 changes: 5 additions & 1 deletion src/interpreter/store.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define interpreter_store_h

#include <cassert>
#include <deque>
#include <vector>

#include "expression-iterator.h"
Expand Down Expand Up @@ -65,7 +66,10 @@ struct WasmStore {
// TODO: Storage for memories, tables, globals, heap objects, etc.
// TODO: Map instances and import names to other instances to find imports.
std::vector<Frame> callStack;
std::vector<Instance> instances;
// Use std::deque so that references to existing Instance objects are not
// invalidated when new instances are added. Frame holds Instance& and would
// become dangling if a std::vector reallocated its storage.
std::deque<Instance> instances;

Frame& getFrame() {
assert(!callStack.empty());
Expand Down
29 changes: 29 additions & 0 deletions test/gtest/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// TODO: Replace this test file with spec tests as soon as possible.

#include "interpreter/interpreter.h"
#include "interpreter/store.h"
#include "literal.h"
#include "wasm-ir-builder.h"
#include "wasm.h"
Expand Down Expand Up @@ -969,3 +970,31 @@ TEST(InterpreterTest, GlobalInitI32) {

EXPECT_EQ(results, expected);
}

TEST(InterpreterTest, InstanceReferenceStability) {
using namespace interpreter;

auto module = std::make_shared<Module>();

WasmStore store;
store.instances.emplace_back(module);
store.instances[0].globalValues["x"] = Literal(int32_t(42));

Instance* addrBefore = &store.instances[0];

ExpressionIterator emptyIter;
store.callStack.emplace_back(store.instances[0], std::move(emptyIter));

// Add many more instances to exercise container growth.
for (int i = 0; i < 100; ++i) {
store.instances.emplace_back(module);
}

// With std::deque, existing elements are never relocated.
Instance* addrAfter = &store.instances[0];
EXPECT_EQ(addrBefore, addrAfter);

// The frame's Instance& reference is still valid.
EXPECT_EQ(store.callStack.back().instance.globalValues["x"],
Literal(int32_t(42)));
}
Loading