Commit 3f1e32b3 authored by Mircea Trofin's avatar Mircea Trofin Committed by Commit Bot

[wasm] Clarify source of runtime information for interpreter.

This is part of the effort to consolidate the ownership of
wasm instantiation/specialization parameters.

This change is focused solely on the interpreter part of that effort, to
verify we're not regressing performance in interpreter benchmarks.

There are two aspects being addressed:
- dataflow-wise, we always fetch the interpreter's memory view from the
runtime objects (i.e. WasmInstanceObject/WasmCompiledModule). This is
consistent with how other instance-specific information is obtained
(e.g. code, indirect functions).

- representation-wise, we do not reuse ModuleEnv/WasmInstance just for
the memory view, because it is surprising that other instance info isn't
accessed from there. 

Bug: 
Change-Id: I536fbffd8e1f142a315fa1770ba9b08319f56a8e
Reviewed-on: https://chromium-review.googlesource.com/602083Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Commit-Queue: Mircea Trofin <mtrofin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47205}
parent 81778aaf
...@@ -95,10 +95,9 @@ InterpreterHandle* GetInterpreterHandle(WasmDebugInfo* debug_info); ...@@ -95,10 +95,9 @@ InterpreterHandle* GetInterpreterHandle(WasmDebugInfo* debug_info);
class InterpreterHandle { class InterpreterHandle {
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(InterpreterHandle); MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(InterpreterHandle);
WasmInstance instance_;
WasmInterpreter interpreter_;
Isolate* isolate_; Isolate* isolate_;
const WasmModule* module_;
WasmInterpreter interpreter_;
StepAction next_step_action_ = StepNone; StepAction next_step_action_ = StepNone;
int last_step_stack_depth_ = 0; int last_step_stack_depth_ = 0;
std::unordered_map<Address, uint32_t> activations_; std::unordered_map<Address, uint32_t> activations_;
...@@ -132,50 +131,53 @@ class InterpreterHandle { ...@@ -132,50 +131,53 @@ class InterpreterHandle {
return {frame_base, frame_limit}; return {frame_base, frame_limit};
} }
public: static Vector<const byte> GetBytes(WasmDebugInfo* debug_info) {
// Initialize in the right order, using helper methods to make this possible. // Return raw pointer into heap. The WasmInterpreter will make its own copy
// WasmInterpreter has to be allocated in place, since it is not movable. // of this data anyway, and there is no heap allocation in-between.
InterpreterHandle(Isolate* isolate, WasmDebugInfo* debug_info, SeqOneByteString* bytes_str =
WasmInstance* external_instance = nullptr) debug_info->wasm_instance()->compiled_module()->module_bytes();
: instance_(debug_info->wasm_instance()->compiled_module()->module()), return {bytes_str->GetChars(), static_cast<size_t>(bytes_str->length())};
interpreter_(isolate, GetBytesEnv(external_instance ? external_instance }
: &instance_,
debug_info)),
isolate_(isolate) {
DisallowHeapAllocation no_gc;
WasmInstanceObject* instance = debug_info->wasm_instance();
// Set memory start pointer and size.
instance_.mem_start = nullptr;
instance_.mem_size = 0;
if (instance->has_memory_buffer()) {
UpdateMemory(instance->memory_buffer());
} else {
DCHECK_EQ(0, instance_.module->min_mem_pages);
}
// Set pointer to globals storage. static uint32_t GetMemSize(WasmDebugInfo* debug_info) {
instance_.globals_start = DisallowHeapAllocation no_gc;
debug_info->wasm_instance()->compiled_module()->GetGlobalsStartOrNull(); WasmCompiledModule* compiled_module =
debug_info->wasm_instance()->compiled_module();
return compiled_module->has_embedded_mem_size()
? compiled_module->embedded_mem_size()
: 0;
} }
~InterpreterHandle() { static byte* GetMemStart(WasmDebugInfo* debug_info) {
DCHECK_EQ(0, activations_.size()); DisallowHeapAllocation no_gc;
WasmCompiledModule* compiled_module =
debug_info->wasm_instance()->compiled_module();
return reinterpret_cast<byte*>(compiled_module->has_embedded_mem_start()
? compiled_module->embedded_mem_start()
: 0);
} }
static ModuleBytesEnv GetBytesEnv(WasmInstance* instance, static byte* GetGlobalsStart(WasmDebugInfo* debug_info) {
WasmDebugInfo* debug_info) { DisallowHeapAllocation no_gc;
// Return raw pointer into heap. The WasmInterpreter will make its own copy WasmCompiledModule* compiled_module =
// of this data anyway, and there is no heap allocation in-between. debug_info->wasm_instance()->compiled_module();
SeqOneByteString* bytes_str = return reinterpret_cast<byte*>(compiled_module->has_globals_start()
debug_info->wasm_instance()->compiled_module()->module_bytes(); ? compiled_module->globals_start()
Vector<const byte> bytes(bytes_str->GetChars(), bytes_str->length()); : 0);
return {instance->module, instance, bytes};
} }
public:
InterpreterHandle(Isolate* isolate, WasmDebugInfo* debug_info)
: isolate_(isolate),
module_(debug_info->wasm_instance()->compiled_module()->module()),
interpreter_(isolate, module_, GetBytes(debug_info),
GetGlobalsStart(debug_info), GetMemStart(debug_info),
GetMemSize(debug_info)) {}
~InterpreterHandle() { DCHECK_EQ(0, activations_.size()); }
WasmInterpreter* interpreter() { return &interpreter_; } WasmInterpreter* interpreter() { return &interpreter_; }
const WasmModule* module() { return instance_.module; } const WasmModule* module() const { return module_; }
void PrepareStep(StepAction step_action) { void PrepareStep(StepAction step_action) {
next_step_action_ = step_action; next_step_action_ = step_action;
...@@ -647,11 +649,10 @@ Handle<WasmDebugInfo> WasmDebugInfo::New(Handle<WasmInstanceObject> instance) { ...@@ -647,11 +649,10 @@ Handle<WasmDebugInfo> WasmDebugInfo::New(Handle<WasmInstanceObject> instance) {
} }
WasmInterpreter* WasmDebugInfo::SetupForTesting( WasmInterpreter* WasmDebugInfo::SetupForTesting(
Handle<WasmInstanceObject> instance_obj, WasmInstance* instance) { Handle<WasmInstanceObject> instance_obj) {
Handle<WasmDebugInfo> debug_info = WasmDebugInfo::New(instance_obj); Handle<WasmDebugInfo> debug_info = WasmDebugInfo::New(instance_obj);
Isolate* isolate = instance_obj->GetIsolate(); Isolate* isolate = instance_obj->GetIsolate();
InterpreterHandle* cpp_handle = InterpreterHandle* cpp_handle = new InterpreterHandle(isolate, *debug_info);
new InterpreterHandle(isolate, *debug_info, instance);
Handle<Object> handle = Managed<InterpreterHandle>::New(isolate, cpp_handle); Handle<Object> handle = Managed<InterpreterHandle>::New(isolate, cpp_handle);
debug_info->set(kInterpreterHandleIndex, *handle); debug_info->set(kInterpreterHandleIndex, *handle);
return cpp_handle->interpreter(); return cpp_handle->interpreter();
......
...@@ -176,6 +176,27 @@ namespace wasm { ...@@ -176,6 +176,27 @@ namespace wasm {
namespace { namespace {
// CachedInstanceInfo encapsulates globals and memory buffer runtime information
// for a wasm instance. The interpreter caches that information when
// constructed, copying it from the {WasmInstanceObject}. It expects it be
// notified on changes to it, e.g. {GrowMemory}. We cache it because interpreter
// perf is sensitive to accesses to this information.
//
// TODO(wasm): other runtime information, such as indirect function table, or
// code table (incl. imports) is currently handled separately. Consider
// unifying, if possible, with {ModuleEnv}.
struct CachedInstanceInfo {
CachedInstanceInfo(byte* globals, byte* mem, uint32_t size)
: globals_start(globals), mem_start(mem), mem_size(size) {}
// We do not expect the location of the globals buffer to
// change for an instance.
byte* const globals_start = nullptr;
// The memory buffer may change because of GrowMemory
byte* mem_start = nullptr;
uint32_t mem_size = 0;
};
inline int32_t ExecuteI32DivS(int32_t a, int32_t b, TrapReason* trap) { inline int32_t ExecuteI32DivS(int32_t a, int32_t b, TrapReason* trap) {
if (b == 0) { if (b == 0) {
*trap = kTrapDivByZero; *trap = kTrapDivByZero;
...@@ -598,18 +619,29 @@ inline int64_t ExecuteI64ReinterpretF64(WasmValue a) { ...@@ -598,18 +619,29 @@ inline int64_t ExecuteI64ReinterpretF64(WasmValue a) {
inline int32_t ExecuteGrowMemory(uint32_t delta_pages, inline int32_t ExecuteGrowMemory(uint32_t delta_pages,
MaybeHandle<WasmInstanceObject> instance_obj, MaybeHandle<WasmInstanceObject> instance_obj,
WasmInstance* instance) { CachedInstanceInfo* mem_info) {
DCHECK_EQ(0, instance->mem_size % WasmModule::kPageSize); Handle<WasmInstanceObject> instance = instance_obj.ToHandleChecked();
uint32_t old_pages = instance->mem_size / WasmModule::kPageSize; Isolate* isolate = instance->GetIsolate();
int32_t ret = WasmInstanceObject::GrowMemory(isolate, instance, delta_pages);
Isolate* isolate = instance_obj.ToHandleChecked()->GetIsolate();
int32_t ret = WasmInstanceObject::GrowMemory( #ifdef DEBUG
isolate, instance_obj.ToHandleChecked(), delta_pages); // Ensure the effects of GrowMemory have been observed by the interpreter.
// Some sanity checks. // See {UpdateMemory}. In all cases, we are in agreement with the runtime
DCHECK_EQ(ret == -1 ? old_pages : old_pages + delta_pages, // object's view.
instance->mem_size / WasmModule::kPageSize); uint32_t cached_size = mem_info->mem_size;
DCHECK(ret == -1 || static_cast<uint32_t>(ret) == old_pages); byte* cached_start = mem_info->mem_start;
USE(old_pages); uint32_t instance_size =
instance->compiled_module()->has_embedded_mem_size()
? instance->compiled_module()->embedded_mem_size()
: 0;
byte* instance_start =
instance->compiled_module()->has_embedded_mem_start()
? reinterpret_cast<byte*>(
instance->compiled_module()->embedded_mem_start())
: nullptr;
CHECK_EQ(cached_size, instance_size);
CHECK_EQ(cached_start, instance_start);
#endif
return ret; return ret;
} }
...@@ -1100,9 +1132,10 @@ class ThreadImpl { ...@@ -1100,9 +1132,10 @@ class ThreadImpl {
}; };
public: public:
ThreadImpl(Zone* zone, CodeMap* codemap, WasmInstance* instance) ThreadImpl(Zone* zone, CodeMap* codemap,
CachedInstanceInfo* cached_instance_info)
: codemap_(codemap), : codemap_(codemap),
instance_(instance), cached_instance_info_(cached_instance_info),
zone_(zone), zone_(zone),
frames_(zone), frames_(zone),
activations_(zone) {} activations_(zone) {}
...@@ -1262,7 +1295,7 @@ class ThreadImpl { ...@@ -1262,7 +1295,7 @@ class ThreadImpl {
friend class InterpretedFrameImpl; friend class InterpretedFrameImpl;
CodeMap* codemap_; CodeMap* codemap_;
WasmInstance* instance_; CachedInstanceInfo* const cached_instance_info_;
Zone* zone_; Zone* zone_;
WasmValue* stack_start_ = nullptr; // Start of allocated stack space. WasmValue* stack_start_ = nullptr; // Start of allocated stack space.
WasmValue* stack_limit_ = nullptr; // End of allocated stack space. WasmValue* stack_limit_ = nullptr; // End of allocated stack space.
...@@ -1278,9 +1311,8 @@ class ThreadImpl { ...@@ -1278,9 +1311,8 @@ class ThreadImpl {
// inspection). // inspection).
ZoneVector<Activation> activations_; ZoneVector<Activation> activations_;
CodeMap* codemap() { return codemap_; } CodeMap* codemap() const { return codemap_; }
WasmInstance* instance() { return instance_; } const WasmModule* module() const { return codemap_->module(); }
const WasmModule* module() { return instance_->module; }
void DoTrap(TrapReason trap, pc_t pc) { void DoTrap(TrapReason trap, pc_t pc) {
state_ = WasmInterpreter::TRAPPED; state_ = WasmInterpreter::TRAPPED;
...@@ -1426,11 +1458,12 @@ class ThreadImpl { ...@@ -1426,11 +1458,12 @@ class ThreadImpl {
bool ExecuteLoad(Decoder* decoder, InterpreterCode* code, pc_t pc, int& len) { bool ExecuteLoad(Decoder* decoder, InterpreterCode* code, pc_t pc, int& len) {
MemoryAccessOperand<false> operand(decoder, code->at(pc), sizeof(ctype)); MemoryAccessOperand<false> operand(decoder, code->at(pc), sizeof(ctype));
uint32_t index = Pop().to<uint32_t>(); uint32_t index = Pop().to<uint32_t>();
if (!BoundsCheck<mtype>(instance()->mem_size, operand.offset, index)) { if (!BoundsCheck<mtype>(cached_instance_info_->mem_size, operand.offset,
index)) {
DoTrap(kTrapMemOutOfBounds, pc); DoTrap(kTrapMemOutOfBounds, pc);
return false; return false;
} }
byte* addr = instance()->mem_start + operand.offset + index; byte* addr = cached_instance_info_->mem_start + operand.offset + index;
WasmValue result(static_cast<ctype>(ReadLittleEndianValue<mtype>(addr))); WasmValue result(static_cast<ctype>(ReadLittleEndianValue<mtype>(addr)));
Push(result); Push(result);
...@@ -1445,11 +1478,12 @@ class ThreadImpl { ...@@ -1445,11 +1478,12 @@ class ThreadImpl {
WasmValue val = Pop(); WasmValue val = Pop();
uint32_t index = Pop().to<uint32_t>(); uint32_t index = Pop().to<uint32_t>();
if (!BoundsCheck<mtype>(instance()->mem_size, operand.offset, index)) { if (!BoundsCheck<mtype>(cached_instance_info_->mem_size, operand.offset,
index)) {
DoTrap(kTrapMemOutOfBounds, pc); DoTrap(kTrapMemOutOfBounds, pc);
return false; return false;
} }
byte* addr = instance()->mem_start + operand.offset + index; byte* addr = cached_instance_info_->mem_start + operand.offset + index;
WriteLittleEndianValue<mtype>(addr, static_cast<mtype>(val.to<ctype>())); WriteLittleEndianValue<mtype>(addr, static_cast<mtype>(val.to<ctype>()));
len = 1 + operand.length; len = 1 + operand.length;
...@@ -1744,7 +1778,7 @@ class ThreadImpl { ...@@ -1744,7 +1778,7 @@ class ThreadImpl {
case kExprGetGlobal: { case kExprGetGlobal: {
GlobalIndexOperand<false> operand(&decoder, code->at(pc)); GlobalIndexOperand<false> operand(&decoder, code->at(pc));
const WasmGlobal* global = &module()->globals[operand.index]; const WasmGlobal* global = &module()->globals[operand.index];
byte* ptr = instance()->globals_start + global->offset; byte* ptr = cached_instance_info_->globals_start + global->offset;
WasmValue val; WasmValue val;
switch (global->type) { switch (global->type) {
#define CASE_TYPE(wasm, ctype) \ #define CASE_TYPE(wasm, ctype) \
...@@ -1763,7 +1797,7 @@ class ThreadImpl { ...@@ -1763,7 +1797,7 @@ class ThreadImpl {
case kExprSetGlobal: { case kExprSetGlobal: {
GlobalIndexOperand<false> operand(&decoder, code->at(pc)); GlobalIndexOperand<false> operand(&decoder, code->at(pc));
const WasmGlobal* global = &module()->globals[operand.index]; const WasmGlobal* global = &module()->globals[operand.index];
byte* ptr = instance()->globals_start + global->offset; byte* ptr = cached_instance_info_->globals_start + global->offset;
WasmValue val = Pop(); WasmValue val = Pop();
switch (global->type) { switch (global->type) {
#define CASE_TYPE(wasm, ctype) \ #define CASE_TYPE(wasm, ctype) \
...@@ -1818,19 +1852,19 @@ class ThreadImpl { ...@@ -1818,19 +1852,19 @@ class ThreadImpl {
STORE_CASE(F64StoreMem, double, double); STORE_CASE(F64StoreMem, double, double);
#undef STORE_CASE #undef STORE_CASE
#define ASMJS_LOAD_CASE(name, ctype, mtype, defval) \ #define ASMJS_LOAD_CASE(name, ctype, mtype, defval) \
case kExpr##name: { \ case kExpr##name: { \
uint32_t index = Pop().to<uint32_t>(); \ uint32_t index = Pop().to<uint32_t>(); \
ctype result; \ ctype result; \
if (!BoundsCheck<mtype>(instance()->mem_size, 0, index)) { \ if (!BoundsCheck<mtype>(cached_instance_info_->mem_size, 0, index)) { \
result = defval; \ result = defval; \
} else { \ } else { \
byte* addr = instance()->mem_start + index; \ byte* addr = cached_instance_info_->mem_start + index; \
/* TODO(titzer): alignment for asmjs load mem? */ \ /* TODO(titzer): alignment for asmjs load mem? */ \
result = static_cast<ctype>(*reinterpret_cast<mtype*>(addr)); \ result = static_cast<ctype>(*reinterpret_cast<mtype*>(addr)); \
} \ } \
Push(WasmValue(result)); \ Push(WasmValue(result)); \
break; \ break; \
} }
ASMJS_LOAD_CASE(I32AsmjsLoadMem8S, int32_t, int8_t, 0); ASMJS_LOAD_CASE(I32AsmjsLoadMem8S, int32_t, int8_t, 0);
ASMJS_LOAD_CASE(I32AsmjsLoadMem8U, int32_t, uint8_t, 0); ASMJS_LOAD_CASE(I32AsmjsLoadMem8U, int32_t, uint8_t, 0);
...@@ -1847,8 +1881,8 @@ class ThreadImpl { ...@@ -1847,8 +1881,8 @@ class ThreadImpl {
case kExpr##name: { \ case kExpr##name: { \
WasmValue val = Pop(); \ WasmValue val = Pop(); \
uint32_t index = Pop().to<uint32_t>(); \ uint32_t index = Pop().to<uint32_t>(); \
if (BoundsCheck<mtype>(instance()->mem_size, 0, index)) { \ if (BoundsCheck<mtype>(cached_instance_info_->mem_size, 0, index)) { \
byte* addr = instance()->mem_start + index; \ byte* addr = cached_instance_info_->mem_start + index; \
/* TODO(titzer): alignment for asmjs store mem? */ \ /* TODO(titzer): alignment for asmjs store mem? */ \
*(reinterpret_cast<mtype*>(addr)) = static_cast<mtype>(val.to<ctype>()); \ *(reinterpret_cast<mtype*>(addr)) = static_cast<mtype>(val.to<ctype>()); \
} \ } \
...@@ -1866,13 +1900,13 @@ class ThreadImpl { ...@@ -1866,13 +1900,13 @@ class ThreadImpl {
MemoryIndexOperand<false> operand(&decoder, code->at(pc)); MemoryIndexOperand<false> operand(&decoder, code->at(pc));
uint32_t delta_pages = Pop().to<uint32_t>(); uint32_t delta_pages = Pop().to<uint32_t>();
Push(WasmValue(ExecuteGrowMemory( Push(WasmValue(ExecuteGrowMemory(
delta_pages, codemap_->maybe_instance(), instance()))); delta_pages, codemap_->maybe_instance(), cached_instance_info_)));
len = 1 + operand.length; len = 1 + operand.length;
break; break;
} }
case kExprMemorySize: { case kExprMemorySize: {
MemoryIndexOperand<false> operand(&decoder, code->at(pc)); MemoryIndexOperand<false> operand(&decoder, code->at(pc));
Push(WasmValue(static_cast<uint32_t>(instance()->mem_size / Push(WasmValue(static_cast<uint32_t>(cached_instance_info_->mem_size /
WasmModule::kPageSize))); WasmModule::kPageSize)));
len = 1 + operand.length; len = 1 + operand.length;
break; break;
...@@ -2511,7 +2545,9 @@ uint32_t WasmInterpreter::Thread::ActivationFrameBase(uint32_t id) { ...@@ -2511,7 +2545,9 @@ uint32_t WasmInterpreter::Thread::ActivationFrameBase(uint32_t id) {
//============================================================================ //============================================================================
class WasmInterpreterInternals : public ZoneObject { class WasmInterpreterInternals : public ZoneObject {
public: public:
WasmInstance* instance_; // We cache the memory information of the debugged instance here, and all
// threads (currently, one) share it and update it in case of {GrowMemory}.
CachedInstanceInfo cached_instance_info_;
// Create a copy of the module bytes for the interpreter, since the passed // Create a copy of the module bytes for the interpreter, since the passed
// pointer might be invalidated after constructing the interpreter. // pointer might be invalidated after constructing the interpreter.
const ZoneVector<uint8_t> module_bytes_; const ZoneVector<uint8_t> module_bytes_;
...@@ -2519,24 +2555,29 @@ class WasmInterpreterInternals : public ZoneObject { ...@@ -2519,24 +2555,29 @@ class WasmInterpreterInternals : public ZoneObject {
ZoneVector<ThreadImpl> threads_; ZoneVector<ThreadImpl> threads_;
WasmInterpreterInternals(Isolate* isolate, Zone* zone, WasmInterpreterInternals(Isolate* isolate, Zone* zone,
const ModuleBytesEnv& env) const WasmModule* module,
: instance_(env.module_env.instance), const ModuleWireBytes& wire_bytes,
module_bytes_(env.wire_bytes.start(), env.wire_bytes.end(), zone), byte* globals_start, byte* mem_start,
codemap_( uint32_t mem_size)
isolate, : cached_instance_info_(globals_start, mem_start, mem_size),
env.module_env.instance ? env.module_env.instance->module : nullptr, module_bytes_(wire_bytes.start(), wire_bytes.end(), zone),
module_bytes_.data(), zone), codemap_(isolate, module, module_bytes_.data(), zone),
threads_(zone) { threads_(zone) {
threads_.emplace_back(zone, &codemap_, env.module_env.instance); threads_.emplace_back(zone, &codemap_, &cached_instance_info_);
} }
}; };
//============================================================================ //============================================================================
// Implementation of the public interface of the interpreter. // Implementation of the public interface of the interpreter.
//============================================================================ //============================================================================
WasmInterpreter::WasmInterpreter(Isolate* isolate, const ModuleBytesEnv& env) WasmInterpreter::WasmInterpreter(Isolate* isolate, const WasmModule* module,
const ModuleWireBytes& wire_bytes,
byte* globals_start, byte* mem_start,
uint32_t mem_size)
: zone_(isolate->allocator(), ZONE_NAME), : zone_(isolate->allocator(), ZONE_NAME),
internals_(new (&zone_) WasmInterpreterInternals(isolate, &zone_, env)) {} internals_(new (&zone_) WasmInterpreterInternals(
isolate, &zone_, module, wire_bytes, globals_start, mem_start,
mem_size)) {}
WasmInterpreter::~WasmInterpreter() { internals_->~WasmInterpreterInternals(); } WasmInterpreter::~WasmInterpreter() { internals_->~WasmInterpreterInternals(); }
...@@ -2588,22 +2629,12 @@ WasmInterpreter::Thread* WasmInterpreter::GetThread(int id) { ...@@ -2588,22 +2629,12 @@ WasmInterpreter::Thread* WasmInterpreter::GetThread(int id) {
return ToThread(&internals_->threads_[id]); return ToThread(&internals_->threads_[id]);
} }
size_t WasmInterpreter::GetMemorySize() {
return internals_->instance_->mem_size;
}
WasmValue WasmInterpreter::ReadMemory(size_t offset) {
UNIMPLEMENTED();
return WasmValue();
}
void WasmInterpreter::WriteMemory(size_t offset, WasmValue val) {
UNIMPLEMENTED();
}
void WasmInterpreter::UpdateMemory(byte* mem_start, uint32_t mem_size) { void WasmInterpreter::UpdateMemory(byte* mem_start, uint32_t mem_size) {
internals_->instance_->mem_start = mem_start; // We assume one thread. Things are likely to be more complicated than this
internals_->instance_->mem_size = mem_size; // in a multi-threaded case.
DCHECK_EQ(1, internals_->threads_.size());
internals_->cached_instance_info_.mem_start = mem_start;
internals_->cached_instance_info_.mem_size = mem_size;
} }
void WasmInterpreter::AddFunctionForTesting(const WasmFunction* function) { void WasmInterpreter::AddFunctionForTesting(const WasmFunction* function) {
......
...@@ -20,7 +20,7 @@ class WasmInstanceObject; ...@@ -20,7 +20,7 @@ class WasmInstanceObject;
namespace wasm { namespace wasm {
// forward declarations. // forward declarations.
struct ModuleBytesEnv; struct ModuleWireBytes;
struct WasmFunction; struct WasmFunction;
struct WasmModule; struct WasmModule;
class WasmInterpreterInternals; class WasmInterpreterInternals;
...@@ -171,7 +171,9 @@ class V8_EXPORT_PRIVATE WasmInterpreter { ...@@ -171,7 +171,9 @@ class V8_EXPORT_PRIVATE WasmInterpreter {
uint32_t ActivationFrameBase(uint32_t activation_id); uint32_t ActivationFrameBase(uint32_t activation_id);
}; };
WasmInterpreter(Isolate* isolate, const ModuleBytesEnv& env); WasmInterpreter(Isolate* isolate, const WasmModule* module,
const ModuleWireBytes& wire_bytes, byte* globals_start,
byte* mem_start, uint32_t mem_size);
~WasmInterpreter(); ~WasmInterpreter();
//========================================================================== //==========================================================================
...@@ -197,12 +199,8 @@ class V8_EXPORT_PRIVATE WasmInterpreter { ...@@ -197,12 +199,8 @@ class V8_EXPORT_PRIVATE WasmInterpreter {
Thread* GetThread(int id); Thread* GetThread(int id);
//========================================================================== //==========================================================================
// Memory access. // Update the cached module env memory parameters after a grow memory event.
//========================================================================== //==========================================================================
size_t GetMemorySize();
WasmValue ReadMemory(size_t offset);
void WriteMemory(size_t offset, WasmValue val);
// Update the memory region, e.g. after external GrowMemory.
void UpdateMemory(byte* mem_start, uint32_t mem_size); void UpdateMemory(byte* mem_start, uint32_t mem_size);
//========================================================================== //==========================================================================
...@@ -222,7 +220,7 @@ class V8_EXPORT_PRIVATE WasmInterpreter { ...@@ -222,7 +220,7 @@ class V8_EXPORT_PRIVATE WasmInterpreter {
private: private:
Zone zone_; Zone zone_;
WasmInterpreterInternals* internals_; WasmInterpreterInternals* const internals_;
}; };
} // namespace wasm } // namespace wasm
......
...@@ -611,7 +611,7 @@ class WasmDebugInfo : public FixedArray { ...@@ -611,7 +611,7 @@ class WasmDebugInfo : public FixedArray {
// WasmDebugInfo. // WasmDebugInfo.
// Use for testing only. // Use for testing only.
V8_EXPORT_PRIVATE static wasm::WasmInterpreter* SetupForTesting( V8_EXPORT_PRIVATE static wasm::WasmInterpreter* SetupForTesting(
Handle<WasmInstanceObject>, wasm::WasmInstance*); Handle<WasmInstanceObject>);
// Set a breakpoint in the given function at the given byte offset within that // Set a breakpoint in the given function at the given byte offset within that
// function. This will redirect all future calls to this function to the // function. This will redirect all future calls to this function to the
......
...@@ -69,9 +69,10 @@ using namespace v8::internal::wasm; ...@@ -69,9 +69,10 @@ using namespace v8::internal::wasm;
const uint32_t kMaxGlobalsSize = 128; const uint32_t kMaxGlobalsSize = 128;
// A helper for module environments that adds the ability to allocate memory // A buildable ModuleEnv. Globals are pre-set, however, memory and code may be
// and global variables. Contains a built-in {WasmModule} and // progressively added by a test. In turn, we piecemeal update the runtime
// {WasmInstance}. // objects, i.e. {WasmInstanceObject}, {WasmCompiledModule} and, if necessary,
// the interpreter.
class TestingModule : public ModuleEnv { class TestingModule : public ModuleEnv {
public: public:
explicit TestingModule(Zone* zone, WasmExecutionMode mode = kExecuteCompiled) explicit TestingModule(Zone* zone, WasmExecutionMode mode = kExecuteCompiled)
...@@ -89,8 +90,7 @@ class TestingModule : public ModuleEnv { ...@@ -89,8 +90,7 @@ class TestingModule : public ModuleEnv {
memset(global_data, 0, sizeof(global_data)); memset(global_data, 0, sizeof(global_data));
instance_object_ = InitInstanceObject(); instance_object_ = InitInstanceObject();
if (mode == kExecuteInterpreted) { if (mode == kExecuteInterpreted) {
interpreter_ = interpreter_ = WasmDebugInfo::SetupForTesting(instance_object_);
WasmDebugInfo::SetupForTesting(instance_object_, &instance_);
} }
} }
...@@ -113,6 +113,21 @@ class TestingModule : public ModuleEnv { ...@@ -113,6 +113,21 @@ class TestingModule : public ModuleEnv {
CHECK(size == 0 || instance->mem_start); CHECK(size == 0 || instance->mem_start);
memset(instance->mem_start, 0, size); memset(instance->mem_start, 0, size);
instance->mem_size = size; instance->mem_size = size;
Handle<WasmCompiledModule> compiled_module =
handle(instance_object_->compiled_module());
Factory* factory = CcTest::i_isolate()->factory();
// It's not really necessary we recreate the Number objects,
// if we happened to have one, but this is a reasonable inefficiencly,
// given this is test.
WasmCompiledModule::recreate_embedded_mem_size(compiled_module, factory,
instance->mem_size);
WasmCompiledModule::recreate_embedded_mem_start(
compiled_module, factory,
reinterpret_cast<size_t>(instance->mem_start));
if (interpreter_) {
interpreter_->UpdateMemory(instance->mem_start, instance->mem_size);
}
return instance->mem_start; return instance->mem_start;
} }
...@@ -346,6 +361,12 @@ class TestingModule : public ModuleEnv { ...@@ -346,6 +361,12 @@ class TestingModule : public ModuleEnv {
std::vector<Handle<FixedArray>> empty; std::vector<Handle<FixedArray>> empty;
Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New( Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New(
isolate_, shared_module_data, code_table, empty, empty); isolate_, shared_module_data, code_table, empty, empty);
// This method is called when we initialize TestEnvironment. We don't
// have a memory yet, so we won't create it here. We'll update the
// interpreter when we get a memory. We do have globals, though.
WasmCompiledModule::recreate_globals_start(
compiled_module, isolate_->factory(),
reinterpret_cast<size_t>(instance->globals_start));
Handle<FixedArray> weak_exported = isolate_->factory()->NewFixedArray(0); Handle<FixedArray> weak_exported = isolate_->factory()->NewFixedArray(0);
compiled_module->set_weak_exported_functions(weak_exported); compiled_module->set_weak_exported_functions(weak_exported);
DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module));
......
...@@ -91,8 +91,7 @@ int32_t InterpretWasmModule(Isolate* isolate, ...@@ -91,8 +91,7 @@ int32_t InterpretWasmModule(Isolate* isolate,
Zone zone(isolate->allocator(), ZONE_NAME); Zone zone(isolate->allocator(), ZONE_NAME);
v8::internal::HandleScope scope(isolate); v8::internal::HandleScope scope(isolate);
WasmInterpreter* interpreter = WasmInterpreter* interpreter = WasmDebugInfo::SetupForTesting(instance);
WasmDebugInfo::SetupForTesting(instance, nullptr);
WasmInterpreter::HeapObjectsScope heap_objects_scope(interpreter, instance); WasmInterpreter::HeapObjectsScope heap_objects_scope(interpreter, instance);
WasmInterpreter::Thread* thread = interpreter->GetThread(0); WasmInterpreter::Thread* thread = interpreter->GetThread(0);
thread->Reset(); thread->Reset();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment