diff --git a/src/interpreter/store.h b/src/interpreter/store.h index 570adbc2b6e..d1e8b4eef25 100644 --- a/src/interpreter/store.h +++ b/src/interpreter/store.h @@ -18,6 +18,7 @@ #define interpreter_store_h #include +#include #include #include "expression-iterator.h" @@ -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 callStack; - std::vector 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 instances; Frame& getFrame() { assert(!callStack.empty()); diff --git a/test/gtest/interpreter.cpp b/test/gtest/interpreter.cpp index ca1beb6c564..b777e6bb6d0 100644 --- a/test/gtest/interpreter.cpp +++ b/test/gtest/interpreter.cpp @@ -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" @@ -969,3 +970,31 @@ TEST(InterpreterTest, GlobalInitI32) { EXPECT_EQ(results, expected); } + +TEST(InterpreterTest, InstanceReferenceStability) { + using namespace interpreter; + + auto module = std::make_shared(); + + 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))); +}