Skip to content

Commit bdde2f3

Browse files
Followups with trap to remove ExternalInterface
1 parent 2c2fd5a commit bdde2f3

File tree

4 files changed

+67
-70
lines changed

4 files changed

+67
-70
lines changed

src/ir/runtime-memory.cpp

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,18 @@
1717
#include "ir/runtime-memory.h"
1818
#include "fp16.h"
1919
#include "interpreter/exception.h"
20+
#include <iostream>
2021

2122
namespace wasm {
2223

23-
RuntimeMemory::RuntimeMemory(Memory memory,
24-
ExternalInterface* externalInterface)
25-
: externalInterface(externalInterface), memoryDefinition(std::move(memory)) {}
26-
2724
namespace {
2825

29-
Address getFinalAddress(const RuntimeMemory& runtimeMemory,
30-
Address addr,
26+
[[noreturn]] void trap(std::string_view reason) {
27+
std::cout << "[trap " << reason << "]\n";
28+
throw TrapException{};
29+
}
30+
31+
Address getFinalAddress(Address addr,
3132
Address offset,
3233
Index bytes,
3334
Address memorySizeBytes) {
@@ -36,14 +37,14 @@ Address getFinalAddress(const RuntimeMemory& runtimeMemory,
3637
msg += std::to_string(uint64_t(offset));
3738
msg += " > ";
3839
msg += std::to_string(uint64_t(memorySizeBytes));
39-
runtimeMemory.trap(msg);
40+
trap(msg);
4041
}
4142
if (addr > memorySizeBytes - offset) {
4243
std::string msg = "final > memory: ";
4344
msg += std::to_string(uint64_t(addr));
4445
msg += " > ";
4546
msg += std::to_string(uint64_t(memorySizeBytes - offset));
46-
runtimeMemory.trap(msg);
47+
trap(msg);
4748
}
4849

4950
addr = size_t(addr) + offset;
@@ -55,13 +56,12 @@ Address getFinalAddress(const RuntimeMemory& runtimeMemory,
5556
msg += std::to_string(uint64_t(bytes));
5657
msg += " > ";
5758
msg += std::to_string(uint64_t(memorySizeBytes));
58-
runtimeMemory.trap(msg);
59+
trap(msg);
5960
}
6061
return addr;
6162
}
6263

63-
void checkLoadAddress(const RuntimeMemory& runtimeMemory,
64-
Address addr,
64+
void checkLoadAddress(Address addr,
6565
Index bytes,
6666
Address memorySizeBytes) {
6767
if (addr > memorySizeBytes || bytes > memorySizeBytes - addr) {
@@ -71,19 +71,18 @@ void checkLoadAddress(const RuntimeMemory& runtimeMemory,
7171
msg += std::to_string(uint64_t(bytes));
7272
msg += " > ";
7373
msg += std::to_string(uint64_t(memorySizeBytes));
74-
runtimeMemory.trap(msg);
74+
trap(msg);
7575
}
7676
}
7777

78-
void checkAtomicAddress(const RuntimeMemory& runtimeMemory,
79-
Address addr,
78+
void checkAtomicAddress(Address addr,
8079
Index bytes,
8180
Address memorySizeBytes) {
82-
checkLoadAddress(runtimeMemory, addr, bytes, memorySizeBytes);
81+
checkLoadAddress(addr, bytes, memorySizeBytes);
8382
// Unaligned atomics trap.
8483
if (bytes > 1) {
8584
if (addr & (bytes - 1)) {
86-
runtimeMemory.trap("unaligned atomic operation");
85+
trap("unaligned atomic operation");
8786
}
8887
}
8988
}
@@ -95,9 +94,8 @@ template<typename T> bool aligned(const uint8_t* address) {
9594

9695
} // namespace
9796

98-
RealRuntimeMemory::RealRuntimeMemory(Memory memory,
99-
ExternalInterface* externalInterface)
100-
: RuntimeMemory(std::move(memory), externalInterface) {
97+
RealRuntimeMemory::RealRuntimeMemory(Memory memory)
98+
: RuntimeMemory(std::move(memory)) {
10199
resize(memoryDefinition.initialByteSize());
102100
}
103101

@@ -107,9 +105,9 @@ Literal RealRuntimeMemory::load(Address addr,
107105
MemoryOrder order,
108106
Type type,
109107
bool signed_) const {
110-
Address final = getFinalAddress(*this, addr, offset, byteCount, size());
108+
Address final = getFinalAddress(addr, offset, byteCount, size());
111109
if (order != MemoryOrder::Unordered) {
112-
checkAtomicAddress(*this, final, byteCount, size());
110+
checkAtomicAddress(final, byteCount, size());
113111
}
114112
switch (type.getBasic()) {
115113
case Type::i32: {
@@ -170,9 +168,9 @@ void RealRuntimeMemory::store(Address addr,
170168
MemoryOrder order,
171169
Literal value,
172170
Type type) {
173-
Address final = getFinalAddress(*this, addr, offset, byteCount, size());
171+
Address final = getFinalAddress(addr, offset, byteCount, size());
174172
if (order != MemoryOrder::Unordered) {
175-
checkAtomicAddress(*this, final, byteCount, size());
173+
checkAtomicAddress(final, byteCount, size());
176174
}
177175
switch (type.getBasic()) {
178176
case Type::i32: {
@@ -213,9 +211,9 @@ void RealRuntimeMemory::store(Address addr,
213211
case Type::f32: {
214212
switch (byteCount) {
215213
case 2:
216-
set<uint16_t>(
217-
final,
218-
fp16_ieee_from_fp32_value(bit_cast<float>(value.reinterpreti32())));
214+
set<uint16_t>(final,
215+
fp16_ieee_from_fp32_value(
216+
bit_cast<float>(value.reinterpreti32())));
219217
break;
220218
case 4:
221219
set<int32_t>(final, value.reinterpreti32());
@@ -261,7 +259,7 @@ void RealRuntimeMemory::init(Address dest,
261259
if (src > data->data.size() || byteCount > data->data.size() - src) {
262260
trap("out of bounds segment access in memory.init");
263261
}
264-
Address final = getFinalAddress(*this, dest, 0, byteCount, size());
262+
Address final = getFinalAddress(dest, 0, byteCount, size());
265263
if (byteCount > 0) {
266264
std::memcpy(&memory[final], &data->data[src], byteCount);
267265
}
@@ -271,9 +269,8 @@ void RealRuntimeMemory::copy(Address dest,
271269
Address src,
272270
Address byteCount,
273271
const RuntimeMemory* srcMemory) {
274-
Address finalDest = getFinalAddress(*this, dest, 0, byteCount, size());
275-
Address finalSrc =
276-
getFinalAddress(*srcMemory, src, 0, byteCount, srcMemory->size());
272+
Address finalDest = getFinalAddress(dest, 0, byteCount, size());
273+
Address finalSrc = getFinalAddress(src, 0, byteCount, srcMemory->size());
277274
const std::vector<uint8_t>* srcBuffer = srcMemory->getBuffer();
278275
if (!srcBuffer) {
279276
// If it's not a memory with a direct buffer, we might need another way to
@@ -287,7 +284,7 @@ void RealRuntimeMemory::copy(Address dest,
287284
}
288285

289286
void RealRuntimeMemory::fill(Address dest, uint8_t value, Address byteCount) {
290-
Address final = getFinalAddress(*this, dest, 0, byteCount, size());
287+
Address final = getFinalAddress(dest, 0, byteCount, size());
291288
if (byteCount > 0) {
292289
std::memset(&memory[final], value, byteCount);
293290
}
@@ -300,8 +297,7 @@ void RealRuntimeMemory::resize(size_t newSize) {
300297
size_t newAllocatedSize = std::max(minSize, newSize);
301298
if (newAllocatedSize > oldAllocatedSize) {
302299
memory.resize(newAllocatedSize);
303-
std::memset(
304-
&memory[oldAllocatedSize], 0, newAllocatedSize - oldAllocatedSize);
300+
std::memset(&memory[oldAllocatedSize], 0, newAllocatedSize - oldAllocatedSize);
305301
}
306302
if (newSize < oldAllocatedSize && newSize < minSize) {
307303
std::memset(&memory[newSize], 0, minSize - newSize);
@@ -347,7 +343,6 @@ template void RealRuntimeMemory::set<uint32_t>(size_t, uint32_t);
347343
template void RealRuntimeMemory::set<int64_t>(size_t, int64_t);
348344
template void RealRuntimeMemory::set<uint64_t>(size_t, uint64_t);
349345
template void
350-
RealRuntimeMemory::set<std::array<uint8_t, 16>>(size_t,
351-
std::array<uint8_t, 16>);
346+
RealRuntimeMemory::set<std::array<uint8_t, 16>>(size_t, std::array<uint8_t, 16>);
352347

353348
} // namespace wasm

src/ir/runtime-memory.h

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,7 @@ namespace wasm {
2323

2424
class RuntimeMemory {
2525
public:
26-
// Forward declare to avoid circular dependency
27-
struct ExternalInterface {
28-
virtual ~ExternalInterface() = default;
29-
virtual void trap(std::string_view why) = 0;
30-
};
31-
32-
RuntimeMemory(Memory memory, ExternalInterface* externalInterface);
26+
RuntimeMemory(Memory memory) : memoryDefinition(std::move(memory)) {}
3327
virtual ~RuntimeMemory() = default;
3428

3529
virtual Literal load(Address addr,
@@ -50,32 +44,26 @@ class RuntimeMemory {
5044

5145
virtual Address size() const = 0;
5246

53-
virtual void init(Address dest,
54-
Address src,
55-
Address byteCount,
56-
const DataSegment* data) = 0;
47+
virtual void
48+
init(Address dest, Address src, Address byteCount, const DataSegment* data) = 0;
5749

58-
virtual void copy(Address dest,
59-
Address src,
60-
Address byteCount,
61-
const RuntimeMemory* srcMemory) = 0;
50+
virtual void
51+
copy(Address dest, Address src, Address byteCount, const RuntimeMemory* srcMemory) = 0;
6252

6353
virtual void fill(Address dest, uint8_t value, Address byteCount) = 0;
6454

6555
const Memory* getDefinition() const { return &memoryDefinition; }
6656

6757
virtual const std::vector<uint8_t>* getBuffer() const { return nullptr; }
6858

69-
void trap(std::string_view why) const { externalInterface->trap(why); }
70-
7159
protected:
72-
ExternalInterface* externalInterface;
7360
const Memory memoryDefinition;
7461
};
7562

7663
class RealRuntimeMemory : public RuntimeMemory {
7764
public:
78-
RealRuntimeMemory(Memory memory, ExternalInterface* externalInterface);
65+
RealRuntimeMemory(Memory memory);
66+
7967
virtual ~RealRuntimeMemory() = default;
8068

8169
Literal load(Address addr,

src/tools/wasm-ctor-eval.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "wasm-interpreter.h"
4343
#include "wasm-io.h"
4444
#include "wasm-validator.h"
45+
#include "interpreter/exception.h"
4546

4647
using namespace wasm;
4748

@@ -242,9 +243,8 @@ class EvallingModuleRunner : public ModuleRunnerBase<EvallingModuleRunner> {
242243
this->wasm,
243244
[this](Name name, Type type) { return makeFuncData(name, type); });
244245
},
245-
[](Memory memory, ExternalInterface* externalInterface) {
246-
return std::make_unique<CtorEvalRuntimeMemory>(memory,
247-
externalInterface);
246+
[](Memory memory) {
247+
return std::make_unique<CtorEvalRuntimeMemory>(memory);
248248
}) {}
249249

250250
Flow visitGlobalGet(GlobalGet* curr) {
@@ -1117,6 +1117,12 @@ EvalCtorOutcome evalCtor(EvallingModuleRunner& instance,
11171117
Flow flow;
11181118
try {
11191119
flow = instance.visit(curr);
1120+
} catch (TrapException&) {
1121+
throw FailToEvalException("trap");
1122+
} catch (WasmException& exn) {
1123+
std::stringstream ss;
1124+
ss << "exception thrown: " << exn;
1125+
throw FailToEvalException(ss.str());
11201126
} catch (FailToEvalException& fail) {
11211127
if (!quiet) {
11221128
if (successes == 0) {
@@ -1353,7 +1359,15 @@ void evalCtors(Module& wasm,
13531359
// create an instance for evalling
13541360
EvallingModuleRunner instance(
13551361
wasm, &interface, interface.instanceInitialized, linkedInstances);
1356-
instance.instantiate();
1362+
try {
1363+
instance.instantiate();
1364+
} catch (TrapException&) {
1365+
throw FailToEvalException("trap");
1366+
} catch (WasmException& exn) {
1367+
std::stringstream ss;
1368+
ss << "exception thrown: " << exn;
1369+
throw FailToEvalException(ss.str());
1370+
}
13571371
interface.instanceInitialized = true;
13581372
// go one by one, in order, until we fail
13591373
// TODO: if we knew priorities, we could reorder?

src/wasm-interpreter.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3003,7 +3003,7 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
30033003
// ExternalInterface provides embedding-specific functionality like calling
30043004
// an imported function or accessing memory.
30053005
//
3006-
struct ExternalInterface : RuntimeMemory::ExternalInterface {
3006+
struct ExternalInterface {
30073007
ExternalInterface(
30083008
std::map<Name, std::shared_ptr<SubType>> linkedInstances = {}) {}
30093009
virtual ~ExternalInterface() = default;
@@ -3035,8 +3035,7 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
30353035
std::unordered_map<Name, RuntimeMemory*> allMemories;
30363036

30373037
using CreateTableFunc = std::unique_ptr<RuntimeTable>(Literal, Table);
3038-
using CreateMemoryFunc = std::unique_ptr<RuntimeMemory>(Memory,
3039-
ExternalInterface*);
3038+
using CreateMemoryFunc = std::unique_ptr<RuntimeMemory>(Memory);
30403039

30413040
ModuleRunnerBase(
30423041
Module& wasm,
@@ -3056,13 +3055,14 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
30563055
[](Literal initial, Table t) -> std::unique_ptr<RuntimeTable> {
30573056
return std::make_unique<RealRuntimeTable>(initial, t);
30583057
})),
3059-
createMemory(createMemory != nullptr
3060-
? std::move(createMemory)
3061-
: static_cast<std::function<CreateMemoryFunc>>(
3062-
[externalInterface](Memory m, ExternalInterface* ei)
3063-
-> std::unique_ptr<RuntimeMemory> {
3064-
return std::make_unique<RealRuntimeMemory>(m, ei);
3065-
})) {
3058+
createMemory(
3059+
createMemory != nullptr
3060+
? std::move(createMemory)
3061+
: static_cast<std::function<CreateMemoryFunc>>(
3062+
[](Memory m) -> std::unique_ptr<RuntimeMemory> {
3063+
return std::make_unique<RealRuntimeMemory>(m);
3064+
})) {
3065+
30663066
// Set up a single shared CurrContinuations for all these linked instances,
30673067
// reusing one if it exists.
30683068
std::shared_ptr<ContinuationStore> shared;
@@ -3468,8 +3468,8 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
34683468
// parsing/validation checked this already.
34693469
assert(inserted && "Unexpected repeated memory name");
34703470
} else {
3471-
auto& runtimeMemory = definedMemories.emplace_back(
3472-
createMemory(*memory, externalInterface));
3471+
auto& runtimeMemory =
3472+
definedMemories.emplace_back(createMemory(*memory));
34733473
[[maybe_unused]] auto [_, inserted] =
34743474
allMemories.try_emplace(memory->name, runtimeMemory.get());
34753475
assert(inserted && "Unexpected repeated memory name");

0 commit comments

Comments
 (0)