summaryrefslogtreecommitdiff
path: root/src/wasm-interpreter.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm-interpreter.h')
-rw-r--r--src/wasm-interpreter.h413
1 files changed, 265 insertions, 148 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 254a1a2e2..fec560e35 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -2273,7 +2273,7 @@ public:
Literals& arguments,
Type result,
SubType& instance) = 0;
- virtual bool growMemory(Address oldSize, Address newSize) = 0;
+ virtual bool growMemory(Name name, Address oldSize, Address newSize) = 0;
virtual bool growTable(Name name,
const Literal& value,
Index oldSize,
@@ -2284,18 +2284,18 @@ public:
// the default impls for load and store switch on the sizes. you can either
// customize load/store, or the sub-functions which they call
- virtual Literal load(Load* load, Address addr) {
+ virtual Literal load(Load* load, Address addr, Name memory) {
switch (load->type.getBasic()) {
case Type::i32: {
switch (load->bytes) {
case 1:
- return load->signed_ ? Literal((int32_t)load8s(addr))
- : Literal((int32_t)load8u(addr));
+ return load->signed_ ? Literal((int32_t)load8s(addr, memory))
+ : Literal((int32_t)load8u(addr, memory));
case 2:
- return load->signed_ ? Literal((int32_t)load16s(addr))
- : Literal((int32_t)load16u(addr));
+ return load->signed_ ? Literal((int32_t)load16s(addr, memory))
+ : Literal((int32_t)load16u(addr, memory));
case 4:
- return Literal((int32_t)load32s(addr));
+ return Literal((int32_t)load32s(addr, memory));
default:
WASM_UNREACHABLE("invalid size");
}
@@ -2304,45 +2304,45 @@ public:
case Type::i64: {
switch (load->bytes) {
case 1:
- return load->signed_ ? Literal((int64_t)load8s(addr))
- : Literal((int64_t)load8u(addr));
+ return load->signed_ ? Literal((int64_t)load8s(addr, memory))
+ : Literal((int64_t)load8u(addr, memory));
case 2:
- return load->signed_ ? Literal((int64_t)load16s(addr))
- : Literal((int64_t)load16u(addr));
+ return load->signed_ ? Literal((int64_t)load16s(addr, memory))
+ : Literal((int64_t)load16u(addr, memory));
case 4:
- return load->signed_ ? Literal((int64_t)load32s(addr))
- : Literal((int64_t)load32u(addr));
+ return load->signed_ ? Literal((int64_t)load32s(addr, memory))
+ : Literal((int64_t)load32u(addr, memory));
case 8:
- return Literal((int64_t)load64s(addr));
+ return Literal((int64_t)load64s(addr, memory));
default:
WASM_UNREACHABLE("invalid size");
}
break;
}
case Type::f32:
- return Literal(load32u(addr)).castToF32();
+ return Literal(load32u(addr, memory)).castToF32();
case Type::f64:
- return Literal(load64u(addr)).castToF64();
+ return Literal(load64u(addr, memory)).castToF64();
case Type::v128:
- return Literal(load128(addr).data());
+ return Literal(load128(addr, load->memory).data());
case Type::none:
case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
}
WASM_UNREACHABLE("invalid type");
}
- virtual void store(Store* store, Address addr, Literal value) {
+ virtual void store(Store* store, Address addr, Literal value, Name memory) {
switch (store->valueType.getBasic()) {
case Type::i32: {
switch (store->bytes) {
case 1:
- store8(addr, value.geti32());
+ store8(addr, value.geti32(), memory);
break;
case 2:
- store16(addr, value.geti32());
+ store16(addr, value.geti32(), memory);
break;
case 4:
- store32(addr, value.geti32());
+ store32(addr, value.geti32(), memory);
break;
default:
WASM_UNREACHABLE("invalid store size");
@@ -2352,16 +2352,16 @@ public:
case Type::i64: {
switch (store->bytes) {
case 1:
- store8(addr, value.geti64());
+ store8(addr, value.geti64(), memory);
break;
case 2:
- store16(addr, value.geti64());
+ store16(addr, value.geti64(), memory);
break;
case 4:
- store32(addr, value.geti64());
+ store32(addr, value.geti64(), memory);
break;
case 8:
- store64(addr, value.geti64());
+ store64(addr, value.geti64(), memory);
break;
default:
WASM_UNREACHABLE("invalid store size");
@@ -2370,13 +2370,13 @@ public:
}
// write floats carefully, ensuring all bits reach memory
case Type::f32:
- store32(addr, value.reinterpreti32());
+ store32(addr, value.reinterpreti32(), memory);
break;
case Type::f64:
- store64(addr, value.reinterpreti64());
+ store64(addr, value.reinterpreti64(), memory);
break;
case Type::v128:
- store128(addr, value.getv128());
+ store128(addr, value.getv128(), memory);
break;
case Type::none:
case Type::unreachable:
@@ -2384,31 +2384,48 @@ public:
}
}
- virtual int8_t load8s(Address addr) { WASM_UNREACHABLE("unimp"); }
- virtual uint8_t load8u(Address addr) { WASM_UNREACHABLE("unimp"); }
- virtual int16_t load16s(Address addr) { WASM_UNREACHABLE("unimp"); }
- virtual uint16_t load16u(Address addr) { WASM_UNREACHABLE("unimp"); }
- virtual int32_t load32s(Address addr) { WASM_UNREACHABLE("unimp"); }
- virtual uint32_t load32u(Address addr) { WASM_UNREACHABLE("unimp"); }
- virtual int64_t load64s(Address addr) { WASM_UNREACHABLE("unimp"); }
- virtual uint64_t load64u(Address addr) { WASM_UNREACHABLE("unimp"); }
- virtual std::array<uint8_t, 16> load128(Address addr) {
+ virtual int8_t load8s(Address addr, Name memoryName) {
+ WASM_UNREACHABLE("unimp");
+ }
+ virtual uint8_t load8u(Address addr, Name memoryName) {
+ WASM_UNREACHABLE("unimp");
+ }
+ virtual int16_t load16s(Address addr, Name memoryName) {
+ WASM_UNREACHABLE("unimp");
+ }
+ virtual uint16_t load16u(Address addr, Name memoryName) {
+ WASM_UNREACHABLE("unimp");
+ }
+ virtual int32_t load32s(Address addr, Name memoryName) {
+ WASM_UNREACHABLE("unimp");
+ }
+ virtual uint32_t load32u(Address addr, Name memoryName) {
+ WASM_UNREACHABLE("unimp");
+ }
+ virtual int64_t load64s(Address addr, Name memoryName) {
+ WASM_UNREACHABLE("unimp");
+ }
+ virtual uint64_t load64u(Address addr, Name memoryName) {
+ WASM_UNREACHABLE("unimp");
+ }
+ virtual std::array<uint8_t, 16> load128(Address addr, Name memoryName) {
WASM_UNREACHABLE("unimp");
}
- virtual void store8(Address addr, int8_t value) {
+ virtual void store8(Address addr, int8_t value, Name memoryName) {
WASM_UNREACHABLE("unimp");
}
- virtual void store16(Address addr, int16_t value) {
+ virtual void store16(Address addr, int16_t value, Name memoryName) {
WASM_UNREACHABLE("unimp");
}
- virtual void store32(Address addr, int32_t value) {
+ virtual void store32(Address addr, int32_t value, Name memoryName) {
WASM_UNREACHABLE("unimp");
}
- virtual void store64(Address addr, int64_t value) {
+ virtual void store64(Address addr, int64_t value, Name memoryName) {
WASM_UNREACHABLE("unimp");
}
- virtual void store128(Address addr, const std::array<uint8_t, 16>&) {
+ virtual void
+ store128(Address addr, const std::array<uint8_t, 16>&, Name memoryName) {
WASM_UNREACHABLE("unimp");
}
@@ -2441,8 +2458,6 @@ public:
externalInterface(externalInterface), linkedInstances(linkedInstances_) {
// import globals from the outside
externalInterface->importGlobals(globals, wasm);
- // prepare memory
- memorySize = wasm.memory.initial;
// generate internal (non-imported) globals
ModuleUtils::iterDefinedGlobals(wasm, [&](Global* global) {
globals[global->name] = self()->visit(global->init).values;
@@ -2556,7 +2571,27 @@ private:
});
}
+ struct MemoryInstanceInfo {
+ // The ModuleRunner instance in which the memory is defined.
+ SubType* instance;
+ // The name the memory has in that interface.
+ Name name;
+ };
+
+ MemoryInstanceInfo getMemoryInstanceInfo(Name name) {
+ auto* memory = wasm.getMemory(name);
+ MemoryInstanceInfo memoryInterfaceInfo;
+ if (!memory->imported()) {
+ return MemoryInstanceInfo{self(), name};
+ }
+
+ auto& importedInstance = linkedInstances.at(memory->module);
+ auto* memoryExport = importedInstance->wasm.getExport(memory->base);
+ return importedInstance->getMemoryInstanceInfo(memoryExport->value);
+ }
+
void initializeMemoryContents() {
+ initializeMemorySizes();
Const offset;
offset.value = Literal(uint32_t(0));
offset.finalize();
@@ -2572,6 +2607,7 @@ private:
size.finalize();
MemoryInit init;
+ init.memory = segment->memory;
init.segment = i;
init.dest = segment->offset;
init.offset = &offset;
@@ -2587,6 +2623,31 @@ private:
}
}
+ // in pages, used to keep track of memorySize throughout the below memops
+ std::unordered_map<Name, Address> memorySizes;
+
+ void initializeMemorySizes() {
+ for (auto& memory : wasm.memories) {
+ memorySizes[memory->name] = memory->initial;
+ }
+ }
+
+ Address getMemorySize(Name memory) {
+ auto iter = memorySizes.find(memory);
+ if (iter == memorySizes.end()) {
+ externalInterface->trap("getMemorySize called on non-existing memory");
+ }
+ return iter->second;
+ }
+
+ void setMemorySize(Name memory, Address size) {
+ auto iter = memorySizes.find(memory);
+ if (iter == memorySizes.end()) {
+ externalInterface->trap("setMemorySize called on non-existing memory");
+ }
+ memorySizes[memory] = size;
+ }
+
public:
class FunctionScope {
public:
@@ -2645,15 +2706,6 @@ private:
SmallVector<std::pair<WasmException, Name>, 4> exceptionStack;
protected:
- // Returns the instance that defines the memory used by this one.
- SubType* getMemoryInstance() {
- auto* inst = self();
- while (inst->wasm.memory.imported()) {
- inst = inst->linkedInstances.at(inst->wasm.memory.module).get();
- }
- return inst;
- }
-
// Returns a reference to the current value of a potentially imported global
Literals& getGlobal(Name name) {
auto* inst = self();
@@ -2874,12 +2926,14 @@ public:
return flow;
}
NOTE_EVAL1(flow);
- auto* inst = getMemoryInstance();
- auto addr = inst->getFinalAddress(curr, flow.getSingleValue());
+ auto info = getMemoryInstanceInfo(curr->memory);
+ auto memorySize = info.instance->getMemorySize(info.name);
+ auto addr =
+ info.instance->getFinalAddress(curr, flow.getSingleValue(), memorySize);
if (curr->isAtomic) {
- inst->checkAtomicAddress(addr, curr->bytes);
+ info.instance->checkAtomicAddress(addr, curr->bytes, memorySize);
}
- auto ret = inst->externalInterface->load(curr, addr);
+ auto ret = info.instance->externalInterface->load(curr, addr, info.name);
NOTE_EVAL1(addr);
NOTE_EVAL1(ret);
return ret;
@@ -2894,14 +2948,17 @@ public:
if (value.breaking()) {
return value;
}
- auto* inst = getMemoryInstance();
- auto addr = inst->getFinalAddress(curr, ptr.getSingleValue());
+ auto info = getMemoryInstanceInfo(curr->memory);
+ auto memorySize = info.instance->getMemorySize(info.name);
+ auto addr =
+ info.instance->getFinalAddress(curr, ptr.getSingleValue(), memorySize);
if (curr->isAtomic) {
- inst->checkAtomicAddress(addr, curr->bytes);
+ info.instance->checkAtomicAddress(addr, curr->bytes, memorySize);
}
NOTE_EVAL1(addr);
NOTE_EVAL1(value);
- inst->externalInterface->store(curr, addr, value.getSingleValue());
+ info.instance->externalInterface->store(
+ curr, addr, value.getSingleValue(), info.name);
return Flow();
}
@@ -2916,11 +2973,14 @@ public:
return value;
}
NOTE_EVAL1(ptr);
- auto* inst = getMemoryInstance();
- auto addr = inst->getFinalAddress(curr, ptr.getSingleValue());
+ auto info = getMemoryInstanceInfo(curr->memory);
+ auto memorySize = info.instance->getMemorySize(info.name);
+ auto addr =
+ info.instance->getFinalAddress(curr, ptr.getSingleValue(), memorySize);
NOTE_EVAL1(addr);
NOTE_EVAL1(value);
- auto loaded = inst->doAtomicLoad(addr, curr->bytes, curr->type);
+ auto loaded = info.instance->doAtomicLoad(
+ addr, curr->bytes, curr->type, info.name, memorySize);
NOTE_EVAL1(loaded);
auto computed = value.getSingleValue();
switch (curr->op) {
@@ -2942,7 +3002,8 @@ public:
case RMWXchg:
break;
}
- inst->doAtomicStore(addr, curr->bytes, computed);
+ info.instance->doAtomicStore(
+ addr, curr->bytes, computed, info.name, memorySize);
return loaded;
}
Flow visitAtomicCmpxchg(AtomicCmpxchg* curr) {
@@ -2960,16 +3021,20 @@ public:
if (replacement.breaking()) {
return replacement;
}
- auto* inst = getMemoryInstance();
- auto addr = inst->getFinalAddress(curr, ptr.getSingleValue());
+ auto info = getMemoryInstanceInfo(curr->memory);
+ auto memorySize = info.instance->getMemorySize(info.name);
+ auto addr =
+ info.instance->getFinalAddress(curr, ptr.getSingleValue(), memorySize);
expected = Flow(wrapToSmallerSize(expected.getSingleValue(), curr->bytes));
NOTE_EVAL1(addr);
NOTE_EVAL1(expected);
NOTE_EVAL1(replacement);
- auto loaded = inst->doAtomicLoad(addr, curr->bytes, curr->type);
+ auto loaded = info.instance->doAtomicLoad(
+ addr, curr->bytes, curr->type, info.name, memorySize);
NOTE_EVAL1(loaded);
if (loaded == expected.getSingleValue()) {
- inst->doAtomicStore(addr, curr->bytes, replacement.getSingleValue());
+ info.instance->doAtomicStore(
+ addr, curr->bytes, replacement.getSingleValue(), info.name, memorySize);
}
return loaded;
}
@@ -2990,10 +3055,13 @@ public:
if (timeout.breaking()) {
return timeout;
}
- auto* inst = getMemoryInstance();
auto bytes = curr->expectedType.getByteSize();
- auto addr = inst->getFinalAddress(curr, ptr.getSingleValue(), bytes);
- auto loaded = inst->doAtomicLoad(addr, bytes, curr->expectedType);
+ auto info = getMemoryInstanceInfo(curr->memory);
+ auto memorySize = info.instance->getMemorySize(info.name);
+ auto addr = info.instance->getFinalAddress(
+ curr, ptr.getSingleValue(), bytes, memorySize);
+ auto loaded = info.instance->doAtomicLoad(
+ addr, bytes, curr->expectedType, info.name, memorySize);
NOTE_EVAL1(loaded);
if (loaded != expected.getSingleValue()) {
return Literal(int32_t(1)); // not equal
@@ -3014,10 +3082,12 @@ public:
if (count.breaking()) {
return count;
}
- auto* inst = getMemoryInstance();
- auto addr = inst->getFinalAddress(curr, ptr.getSingleValue(), 4);
+ auto info = getMemoryInstanceInfo(curr->memory);
+ auto memorySize = info.instance->getMemorySize(info.name);
+ auto addr =
+ info.instance->getFinalAddress(curr, ptr.getSingleValue(), 4, memorySize);
// Just check TODO actual threads support
- inst->checkAtomicAddress(addr, 4);
+ info.instance->checkAtomicAddress(addr, 4, memorySize);
return Literal(int32_t(0)); // none woken up
}
Flow visitSIMDLoad(SIMDLoad* curr) {
@@ -3043,6 +3113,7 @@ public:
}
Flow visitSIMDLoadSplat(SIMDLoad* curr) {
Load load;
+ load.memory = curr->memory;
load.type = Type::i32;
load.bytes = curr->getMemBytes();
load.signed_ = false;
@@ -3082,30 +3153,37 @@ public:
}
NOTE_EVAL1(flow);
Address src(uint32_t(flow.getSingleValue().geti32()));
- auto* inst = getMemoryInstance();
+ auto info = getMemoryInstanceInfo(curr->memory);
auto loadLane = [&](Address addr) {
switch (curr->op) {
case Load8x8SVec128:
- return Literal(int32_t(inst->externalInterface->load8s(addr)));
+ return Literal(
+ int32_t(info.instance->externalInterface->load8s(addr, info.name)));
case Load8x8UVec128:
- return Literal(int32_t(inst->externalInterface->load8u(addr)));
+ return Literal(
+ int32_t(info.instance->externalInterface->load8u(addr, info.name)));
case Load16x4SVec128:
- return Literal(int32_t(inst->externalInterface->load16s(addr)));
+ return Literal(int32_t(
+ info.instance->externalInterface->load16s(addr, info.name)));
case Load16x4UVec128:
- return Literal(int32_t(inst->externalInterface->load16u(addr)));
+ return Literal(int32_t(
+ info.instance->externalInterface->load16u(addr, info.name)));
case Load32x2SVec128:
- return Literal(int64_t(inst->externalInterface->load32s(addr)));
+ return Literal(int64_t(
+ info.instance->externalInterface->load32s(addr, info.name)));
case Load32x2UVec128:
- return Literal(int64_t(inst->externalInterface->load32u(addr)));
+ return Literal(int64_t(
+ info.instance->externalInterface->load32u(addr, info.name)));
default:
WASM_UNREACHABLE("unexpected op");
}
WASM_UNREACHABLE("invalid op");
};
+ auto memorySize = info.instance->getMemorySize(info.name);
auto fillLanes = [&](auto lanes, size_t laneBytes) {
for (auto& lane : lanes) {
- lane = loadLane(
- inst->getFinalAddress(curr, Literal(uint32_t(src)), laneBytes));
+ lane = loadLane(info.instance->getFinalAddress(
+ curr, Literal(uint32_t(src)), laneBytes, memorySize));
src = Address(uint32_t(src) + laneBytes);
}
return Literal(lanes);
@@ -3137,16 +3215,19 @@ public:
return flow;
}
NOTE_EVAL1(flow);
- auto* inst = getMemoryInstance();
- Address src =
- inst->getFinalAddress(curr, flow.getSingleValue(), curr->getMemBytes());
+ auto info = getMemoryInstanceInfo(curr->memory);
+ auto memorySize = info.instance->getMemorySize(info.name);
+ Address src = info.instance->getFinalAddress(
+ curr, flow.getSingleValue(), curr->getMemBytes(), memorySize);
auto zero =
Literal::makeZero(curr->op == Load32ZeroVec128 ? Type::i32 : Type::i64);
if (curr->op == Load32ZeroVec128) {
- auto val = Literal(inst->externalInterface->load32u(src));
+ auto val =
+ Literal(info.instance->externalInterface->load32u(src, info.name));
return Literal(std::array<Literal, 4>{{val, zero, zero, zero}});
} else {
- auto val = Literal(inst->externalInterface->load64u(src));
+ auto val =
+ Literal(info.instance->externalInterface->load64u(src, info.name));
return Literal(std::array<Literal, 2>{{val, zero}});
}
}
@@ -3157,9 +3238,10 @@ public:
return flow;
}
NOTE_EVAL1(flow);
- auto* inst = getMemoryInstance();
- Address addr =
- inst->getFinalAddress(curr, flow.getSingleValue(), curr->getMemBytes());
+ auto info = getMemoryInstanceInfo(curr->memory);
+ auto memorySize = info.instance->getMemorySize(info.name);
+ Address addr = info.instance->getFinalAddress(
+ curr, flow.getSingleValue(), curr->getMemBytes(), memorySize);
flow = self()->visit(curr->vec);
if (flow.breaking()) {
return flow;
@@ -3170,10 +3252,12 @@ public:
case Store8LaneVec128: {
std::array<Literal, 16> lanes = vec.getLanesUI8x16();
if (curr->isLoad()) {
- lanes[curr->index] = Literal(inst->externalInterface->load8u(addr));
+ lanes[curr->index] =
+ Literal(info.instance->externalInterface->load8u(addr, info.name));
return Literal(lanes);
} else {
- inst->externalInterface->store8(addr, lanes[curr->index].geti32());
+ info.instance->externalInterface->store8(
+ addr, lanes[curr->index].geti32(), info.name);
return {};
}
}
@@ -3181,10 +3265,12 @@ public:
case Store16LaneVec128: {
std::array<Literal, 8> lanes = vec.getLanesUI16x8();
if (curr->isLoad()) {
- lanes[curr->index] = Literal(inst->externalInterface->load16u(addr));
+ lanes[curr->index] =
+ Literal(info.instance->externalInterface->load16u(addr, info.name));
return Literal(lanes);
} else {
- inst->externalInterface->store16(addr, lanes[curr->index].geti32());
+ info.instance->externalInterface->store16(
+ addr, lanes[curr->index].geti32(), info.name);
return {};
}
}
@@ -3192,10 +3278,12 @@ public:
case Store32LaneVec128: {
std::array<Literal, 4> lanes = vec.getLanesI32x4();
if (curr->isLoad()) {
- lanes[curr->index] = Literal(inst->externalInterface->load32u(addr));
+ lanes[curr->index] =
+ Literal(info.instance->externalInterface->load32u(addr, info.name));
return Literal(lanes);
} else {
- inst->externalInterface->store32(addr, lanes[curr->index].geti32());
+ info.instance->externalInterface->store32(
+ addr, lanes[curr->index].geti32(), info.name);
return {};
}
}
@@ -3203,10 +3291,12 @@ public:
case Load64LaneVec128: {
std::array<Literal, 2> lanes = vec.getLanesI64x2();
if (curr->isLoad()) {
- lanes[curr->index] = Literal(inst->externalInterface->load64u(addr));
+ lanes[curr->index] =
+ Literal(info.instance->externalInterface->load64u(addr, info.name));
return Literal(lanes);
} else {
- inst->externalInterface->store64(addr, lanes[curr->index].geti64());
+ info.instance->externalInterface->store64(
+ addr, lanes[curr->index].geti64(), info.name);
return {};
}
}
@@ -3215,38 +3305,44 @@ public:
}
Flow visitMemorySize(MemorySize* curr) {
NOTE_ENTER("MemorySize");
- auto* inst = getMemoryInstance();
- return Literal::makeFromInt64(inst->memorySize,
- inst->wasm.memory.indexType);
+ auto info = getMemoryInstanceInfo(curr->memory);
+ auto memorySize = info.instance->getMemorySize(info.name);
+ auto* memory = info.instance->wasm.getMemory(info.name);
+ return Literal::makeFromInt64(memorySize, memory->indexType);
}
Flow visitMemoryGrow(MemoryGrow* curr) {
NOTE_ENTER("MemoryGrow");
- auto* inst = getMemoryInstance();
- auto indexType = inst->wasm.memory.indexType;
- auto fail = Literal::makeFromInt64(-1, indexType);
+ auto info = getMemoryInstanceInfo(curr->memory);
+ auto memorySize = info.instance->getMemorySize(info.name);
+ auto* memory = info.instance->wasm.getMemory(info.name);
+ auto indexType = memory->indexType;
+ auto fail = Literal::makeFromInt64(-1, memory->indexType);
Flow flow = self()->visit(curr->delta);
if (flow.breaking()) {
return flow;
}
- Flow ret = Literal::makeFromInt64(inst->memorySize, indexType);
+ Flow ret = Literal::makeFromInt64(memorySize, indexType);
uint64_t delta = flow.getSingleValue().getUnsigned();
if (delta > uint32_t(-1) / Memory::kPageSize && indexType == Type::i32) {
return fail;
}
- if (inst->memorySize >= uint32_t(-1) - delta && indexType == Type::i32) {
+ if (memorySize >= uint32_t(-1) - delta && indexType == Type::i32) {
return fail;
}
- auto newSize = inst->memorySize + delta;
- if (newSize > inst->wasm.memory.max) {
+ auto newSize = memorySize + delta;
+ if (newSize > memory->max) {
return fail;
}
- if (!inst->externalInterface->growMemory(
- inst->memorySize * Memory::kPageSize, newSize * Memory::kPageSize)) {
+ if (!info.instance->externalInterface->growMemory(
+ info.name,
+ memorySize * Memory::kPageSize,
+ newSize * Memory::kPageSize)) {
// We failed to grow the memory in practice, even though it was valid
// to try to do so.
return fail;
}
- inst->memorySize = newSize;
+ memorySize = newSize;
+ info.instance->setMemorySize(info.name, memorySize);
return ret;
}
Flow visitMemoryInit(MemoryInit* curr) {
@@ -3280,15 +3376,17 @@ public:
if ((uint64_t)offsetVal + sizeVal > segment->data.size()) {
trap("out of bounds segment access in memory.init");
}
- auto* inst = getMemoryInstance();
- if (destVal + sizeVal > inst->memorySize * Memory::kPageSize) {
+ auto info = getMemoryInstanceInfo(curr->memory);
+ auto memorySize = info.instance->getMemorySize(info.name);
+ if (destVal + sizeVal > memorySize * Memory::kPageSize) {
trap("out of bounds memory access in memory.init");
}
for (size_t i = 0; i < sizeVal; ++i) {
Literal addr(destVal + i);
- inst->externalInterface->store8(
- inst->getFinalAddressWithoutOffset(addr, 1),
- segment->data[offsetVal + i]);
+ info.instance->externalInterface->store8(
+ info.instance->getFinalAddressWithoutOffset(addr, 1, memorySize),
+ segment->data[offsetVal + i],
+ info.name);
}
return {};
}
@@ -3318,9 +3416,12 @@ public:
Address sourceVal(source.getSingleValue().getUnsigned());
Address sizeVal(size.getSingleValue().getUnsigned());
- auto* inst = getMemoryInstance();
- if (sourceVal + sizeVal > inst->memorySize * Memory::kPageSize ||
- destVal + sizeVal > inst->memorySize * Memory::kPageSize ||
+ auto destInfo = getMemoryInstanceInfo(curr->destMemory);
+ auto sourceInfo = getMemoryInstanceInfo(curr->sourceMemory);
+ auto destMemorySize = destInfo.instance->getMemorySize(destInfo.name);
+ auto sourceMemorySize = sourceInfo.instance->getMemorySize(sourceInfo.name);
+ if (sourceVal + sizeVal > sourceMemorySize * Memory::kPageSize ||
+ destVal + sizeVal > destMemorySize * Memory::kPageSize ||
// FIXME: better/cheaper way to detect wrapping?
sourceVal + sizeVal < sourceVal || sourceVal + sizeVal < sizeVal ||
destVal + sizeVal < destVal || destVal + sizeVal < sizeVal) {
@@ -3337,10 +3438,14 @@ public:
step = -1;
}
for (int64_t i = start; i != end; i += step) {
- inst->externalInterface->store8(
- inst->getFinalAddressWithoutOffset(Literal(destVal + i), 1),
- inst->externalInterface->load8s(
- inst->getFinalAddressWithoutOffset(Literal(sourceVal + i), 1)));
+ destInfo.instance->externalInterface->store8(
+ destInfo.instance->getFinalAddressWithoutOffset(
+ Literal(destVal + i), 1, destMemorySize),
+ sourceInfo.instance->externalInterface->load8s(
+ sourceInfo.instance->getFinalAddressWithoutOffset(
+ Literal(sourceVal + i), 1, sourceMemorySize),
+ sourceInfo.name),
+ destInfo.name);
}
return {};
}
@@ -3364,17 +3469,21 @@ public:
Address destVal(dest.getSingleValue().getUnsigned());
Address sizeVal(size.getSingleValue().getUnsigned());
- auto* inst = getMemoryInstance();
+ auto info = getMemoryInstanceInfo(curr->memory);
+ auto memorySize = info.instance->getMemorySize(info.name);
// FIXME: cheaper wrapping detection?
- if (destVal > inst->memorySize * Memory::kPageSize ||
- sizeVal > inst->memorySize * Memory::kPageSize ||
- destVal + sizeVal > inst->memorySize * Memory::kPageSize) {
+ if (destVal > memorySize * Memory::kPageSize ||
+ sizeVal > memorySize * Memory::kPageSize ||
+ destVal + sizeVal > memorySize * Memory::kPageSize) {
trap("out of bounds memory access in memory.fill");
}
uint8_t val(value.getSingleValue().geti32());
for (size_t i = 0; i < sizeVal; ++i) {
- inst->externalInterface->store8(
- inst->getFinalAddressWithoutOffset(Literal(destVal + i), 1), val);
+ info.instance->externalInterface->store8(
+ info.instance->getFinalAddressWithoutOffset(
+ Literal(destVal + i), 1, memorySize),
+ val,
+ info.name);
}
return {};
}
@@ -3550,8 +3659,6 @@ public:
static const Index maxDepth = 250;
protected:
- Address memorySize; // in pages
-
void trapIfGt(uint64_t lhs, uint64_t rhs, const char* msg) {
if (lhs > rhs) {
std::stringstream ss;
@@ -3561,34 +3668,37 @@ protected:
}
template<class LS>
- Address getFinalAddress(LS* curr, Literal ptr, Index bytes) {
+ Address
+ getFinalAddress(LS* curr, Literal ptr, Index bytes, Address memorySize) {
Address memorySizeBytes = memorySize * Memory::kPageSize;
uint64_t addr = ptr.type == Type::i32 ? ptr.geti32() : ptr.geti64();
trapIfGt(curr->offset, memorySizeBytes, "offset > memory");
trapIfGt(addr, memorySizeBytes - curr->offset, "final > memory");
addr += curr->offset;
trapIfGt(bytes, memorySizeBytes, "bytes > memory");
- checkLoadAddress(addr, bytes);
+ checkLoadAddress(addr, bytes, memorySize);
return addr;
}
- template<class LS> Address getFinalAddress(LS* curr, Literal ptr) {
- return getFinalAddress(curr, ptr, curr->bytes);
+ template<class LS>
+ Address getFinalAddress(LS* curr, Literal ptr, Address memorySize) {
+ return getFinalAddress(curr, ptr, curr->bytes, memorySize);
}
- Address getFinalAddressWithoutOffset(Literal ptr, Index bytes) {
+ Address
+ getFinalAddressWithoutOffset(Literal ptr, Index bytes, Address memorySize) {
uint64_t addr = ptr.type == Type::i32 ? ptr.geti32() : ptr.geti64();
- checkLoadAddress(addr, bytes);
+ checkLoadAddress(addr, bytes, memorySize);
return addr;
}
- void checkLoadAddress(Address addr, Index bytes) {
+ void checkLoadAddress(Address addr, Index bytes, Address memorySize) {
Address memorySizeBytes = memorySize * Memory::kPageSize;
trapIfGt(addr, memorySizeBytes - bytes, "highest > memory");
}
- void checkAtomicAddress(Address addr, Index bytes) {
- checkLoadAddress(addr, bytes);
+ void checkAtomicAddress(Address addr, Index bytes, Address memorySize) {
+ checkLoadAddress(addr, bytes, memorySize);
// Unaligned atomics trap.
if (bytes > 1) {
if (addr & (bytes - 1)) {
@@ -3597,8 +3707,9 @@ protected:
}
}
- Literal doAtomicLoad(Address addr, Index bytes, Type type) {
- checkAtomicAddress(addr, bytes);
+ Literal doAtomicLoad(
+ Address addr, Index bytes, Type type, Name memoryName, Address memorySize) {
+ checkAtomicAddress(addr, bytes, memorySize);
Const ptr;
ptr.value = Literal(int32_t(addr));
ptr.type = Type::i32;
@@ -3611,11 +3722,16 @@ protected:
load.isAtomic = true; // understatement
load.ptr = &ptr;
load.type = type;
- return externalInterface->load(&load, addr);
+ load.memory = memoryName;
+ return externalInterface->load(&load, addr, memoryName);
}
- void doAtomicStore(Address addr, Index bytes, Literal toStore) {
- checkAtomicAddress(addr, bytes);
+ void doAtomicStore(Address addr,
+ Index bytes,
+ Literal toStore,
+ Name memoryName,
+ Address memorySize) {
+ checkAtomicAddress(addr, bytes, memorySize);
Const ptr;
ptr.value = Literal(int32_t(addr));
ptr.type = Type::i32;
@@ -3629,7 +3745,8 @@ protected:
store.ptr = &ptr;
store.value = &value;
store.valueType = value.type;
- return externalInterface->store(&store, addr, toStore);
+ store.memory = memoryName;
+ return externalInterface->store(&store, addr, toStore, memoryName);
}
ExternalInterface* externalInterface;