Skip to content

Commit a7faf92

Browse files
Fixed
1 parent 48ef9fc commit a7faf92

File tree

5 files changed

+57
-28
lines changed

5 files changed

+57
-28
lines changed

src/shell-interface.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ struct ShellExternalInterface : ModuleRunner::ExternalInterface {
148148
// Use a null instance because these are host functions.
149149
return Literal(
150150
std::make_shared<FuncData>(import->name,
151-
nullptr,
151+
/*instanceId=*/0,
152152
[](const Literals& arguments) -> Flow {
153153
for (auto argument : arguments) {
154154
std::cout << argument << " : "
@@ -159,7 +159,7 @@ struct ShellExternalInterface : ModuleRunner::ExternalInterface {
159159
import->type);
160160
} else if (import->module == ENV && import->base == EXIT) {
161161
return Literal(std::make_shared<FuncData>(import->name,
162-
nullptr,
162+
/*instanceId=*/0,
163163
[](const Literals&) -> Flow {
164164
// XXX hack for torture tests
165165
std::cout << "exit()\n";

src/tools/execution-results.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ struct LoggingExternalInterface : public ShellExternalInterface {
210210
return {};
211211
};
212212
// Use a null instance because this is a host function.
213-
return Literal(std::make_shared<FuncData>(import->name, nullptr, f),
213+
return Literal(std::make_shared<FuncData>(import->name, /*instanceId=*/0, f),
214214
import->type);
215215
}
216216

src/tools/wasm-ctor-eval.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,9 @@ class EvallingModuleRunner : public ModuleRunnerBase<EvallingModuleRunner> {
104104

105105
// This needs to be duplicated from ModuleRunner, unfortunately.
106106
Literal makeFuncData(Name name, Type type) {
107+
// TODO fix this too
107108
auto allocation =
108-
std::make_shared<FuncData>(name, this, [this, name](Literals arguments) {
109+
std::make_shared<FuncData>(name, reinterpret_cast<uintptr_t>(this), [this, name](Literals arguments) {
109110
return callFunction(name, arguments);
110111
});
111112
#if __has_feature(leak_sanitizer) || __has_feature(address_sanitizer)
@@ -320,7 +321,7 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface {
320321
// Use a null instance because these are either host functions or imported
321322
// from unknown sources.
322323
// TODO: Be more precise about the types we allow these imports to have.
323-
return Literal(std::make_shared<FuncData>(import->name, nullptr, f),
324+
return Literal(std::make_shared<FuncData>(import->name, /*instanceId=*/0, f),
324325
import->type);
325326
}
326327

src/wasm-interpreter.h

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class Flow {
8686
}
8787

8888
Literals values;
89-
Name breakTo; // if non-null, a break is going on
89+
Name breakTo; // if non-null, a break is going on
9090
Tag* suspendTag = nullptr; // if non-null, breakTo must be SUSPEND_FLOW, and
9191
// this is the tag being suspended
9292

@@ -140,17 +140,18 @@ struct FuncData {
140140
// an unknown source.) Two functions are equal iff they have the same name and
141141
// are defined by the same instance (in particular, we do *not* compare the
142142
// |call| field below, which is an execution detail).
143-
void* self;
143+
uintptr_t instanceId;
144144

145145
// A way to execute this function. We use this when it is called.
146146
using Call = std::function<Flow(const Literals&)>;
147147
Call call;
148148

149-
FuncData(Name name, void* self = nullptr, Call call = {})
150-
: name(name), self(self), call(call) {}
149+
// todo?
150+
FuncData(Name name, uintptr_t instanceId = 0, Call call = {})
151+
: name(name), instanceId(instanceId), call(call) {}
151152

152153
bool operator==(const FuncData& other) const {
153-
return name == other.name && self == other.self;
154+
return name == other.name && instanceId == other.instanceId;
154155
}
155156

156157
Flow doCall(const Literals& arguments) {
@@ -361,7 +362,7 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
361362
Literal makeFuncData(Name name, Type type) {
362363
// Identify the interpreter, but do not provide a way to actually call the
363364
// function.
364-
auto allocation = std::make_shared<FuncData>(name, this);
365+
auto allocation = std::make_shared<FuncData>(name, (uintptr_t)this);
365366
#if __has_feature(leak_sanitizer) || __has_feature(address_sanitizer)
366367
__lsan_ignore_object(allocation.get());
367368
#endif
@@ -2916,7 +2917,7 @@ using GlobalValueSet = std::map<Name, Literals>;
29162917
//
29172918

29182919
template<typename SubType>
2919-
class ModuleRunnerBase : public ExpressionRunner<SubType> {
2920+
class ModuleRunnerBase : public ExpressionRunner<SubType>, public std::enable_shared_from_this<ModuleRunnerBase<SubType>> {
29202921
public:
29212922
//
29222923
// You need to implement one of these to create a concrete interpreter. The
@@ -3206,9 +3207,9 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
32063207
}
32073208
return Literal(std::make_shared<FuncData>(
32083209
func->name,
3209-
this,
3210-
[this, func](const Literals& arguments) -> Flow {
3211-
return callFunction(func->name, arguments);
3210+
reinterpret_cast<uintptr_t>(this),
3211+
[self = this->shared_from_this(), func](const Literals& arguments) -> Flow {
3212+
return self->callFunction(func->name, arguments);
32123213
}),
32133214
func->type);
32143215
}
@@ -4773,7 +4774,7 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
47734774
auto func = entry[0];
47744775
auto data = func.getFuncData();
47754776
// We must be in the right module to do the call using that name.
4776-
if (data->self != self()) {
4777+
if (data->instanceId != (uintptr_t)self()) {
47774778
// Restore the entry to the resume stack, as the other module's
47784779
// callFunction() will read it. Then call into the other module. This
47794780
// sets this up as if we called into the proper module in the first
@@ -4865,10 +4866,9 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
48654866
flow.values.pop_back();
48664867
arguments = flow.values;
48674868

4868-
if (nextData->self != this) {
4869+
if (nextData->instanceId != (uintptr_t)self()) {
48694870
// This function is in another module. Call from there.
4870-
auto other = (decltype(this))nextData->self;
4871-
flow = other->callFunction(name, arguments);
4871+
flow = nextData->doCall(arguments);
48724872
break;
48734873
}
48744874
}
@@ -4998,23 +4998,21 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
49984998
std::map<Name, std::shared_ptr<SubType>> linkedInstances;
49994999
};
50005000

5001-
class ModuleRunner : public ModuleRunnerBase<ModuleRunner>,
5002-
public std::enable_shared_from_this<ModuleRunner> {
5001+
class ModuleRunner : public ModuleRunnerBase<ModuleRunner> {
50035002
public:
50045003
ModuleRunner(
50055004
Module& wasm,
50065005
ExternalInterface* externalInterface,
50075006
std::map<Name, std::shared_ptr<ModuleRunner>> linkedInstances = {})
50085007
: ModuleRunnerBase(wasm, externalInterface, linkedInstances) {}
50095008

5010-
// As the super's |makeFuncData|, but here we also provide a way to
5011-
// actually call the function.
50125009
Literal makeFuncData(Name name, Type type) {
5013-
// This function may outlive the ModuleRunner in the case that instantiation
5014-
// fails. Use shared_from_this() to extend this ModuleRunner's lifetime.
5015-
auto allocation = std::make_shared<FuncData>(
5016-
name, this, [self = shared_from_this(), name](Literals arguments) {
5017-
return self->callFunction(name, arguments);
5010+
// As the super's |makeFuncData|, but here we also provide a way to
5011+
// actually call the function.
5012+
auto allocation =
5013+
std::make_shared<FuncData>(name, reinterpret_cast<uintptr_t>(this),
5014+
[moduleRunner = std::static_pointer_cast<ModuleRunner>(std::enable_shared_from_this<ModuleRunnerBase<ModuleRunner>>::shared_from_this()), name](Literals arguments) {
5015+
return moduleRunner->callFunction(name, arguments);
50185016
});
50195017

50205018
return Literal(allocation, type);

test/spec/linking0.wast

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
;; adapted from test/spec/testsuite/linking0.wast, with some assertions removed
2+
3+
(module $Mt
4+
(type (func (result i32)))
5+
(type (func))
6+
7+
(table (export "tab") 10 funcref)
8+
(elem (i32.const 2) $g $g $g $g)
9+
(func $g (result i32) (i32.const 4))
10+
(func (export "h") (result i32) (i32.const -4))
11+
12+
(func (export "call") (param i32) (result i32)
13+
(call_indirect (type 0) (local.get 0))
14+
)
15+
)
16+
(register "Mt" $Mt)
17+
18+
(assert_trap
19+
(module
20+
(table (import "Mt" "tab") 10 funcref)
21+
(func $f (result i32) (i32.const 0))
22+
(elem (i32.const 7) $f)
23+
(memory 0)
24+
(memory $m 1)
25+
(memory 0)
26+
(data $m (i32.const 0x10000) "d") ;; out of bounds
27+
)
28+
"out of bounds memory access"
29+
)
30+
(assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0))

0 commit comments

Comments
 (0)