Commit f9d4090b authored by Mircea Trofin's avatar Mircea Trofin Committed by Commit Bot

[wasm] Consolidate ownership of instantiation/specialization parameters

This CL consolidates ownership of parameters used to compile code (which
we always specialize) in 2 places:
- ModuleEnv for compile-time data
- WasmCompiledModule for runtime data

The parameters in question are: memory size and start; globals start; 
address of indirect function tables (and their signatures, respectively); 
and address to be used for wasm call sites.

Ideally, we'd collapse this down to one place, however, we need
specialization data to survive serialization. We can achieve this we get off 
the GC heap and use a different wasm code serializer.

The CL:
- removes aliasing of parts of the specialization data, and moves
to using ModuleEnv as a token of passing around compile-time data, instead
of a mixture of ModuleEnv, WasmInstance, and some other structures. ModuleEnv
is responsible for providing a consistent view of the specialization data,
e.g. valid memory sizes (multiples of page size), and matching sized function
tables and signatures.

- removes WasmInstance, as its data is now contained by ModuleEnv.

- removes ModuleBytesEnv. We now pass the wire bytes explicitly. They can't
always be assumed as present (e.g. streaming compilation), and probably more
refactoring may need to happen once streaming compilation lands and we
better understand our dependencies.

Change-Id: Id7e6f2cf29e51b5756eee8b6f8827fb1f375e5c3
Reviewed-on: https://chromium-review.googlesource.com/592531
Commit-Queue: Mircea Trofin <mtrofin@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47229}
parent 9359dc4d
This diff is collapsed.
......@@ -31,14 +31,7 @@ class SourcePositionTable;
} // namespace compiler
namespace wasm {
// Forward declarations for some wasm data structures.
struct ModuleBytesEnv;
struct ModuleEnv;
struct WasmFunction;
struct WasmModule;
class ErrorThrower;
struct DecodeStruct;
// Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
typedef compiler::Node TFNode;
typedef compiler::JSGraph TFGraph;
......@@ -49,19 +42,21 @@ class WasmCompilationUnit final {
public:
// Use the following constructors if you know you are running on the
// foreground thread.
WasmCompilationUnit(Isolate* isolate, wasm::ModuleBytesEnv* module_env,
WasmCompilationUnit(Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes,
const wasm::ModuleEnv* module_env,
const wasm::WasmFunction* function,
Handle<Code> centry_stub);
WasmCompilationUnit(Isolate* isolate, wasm::ModuleEnv* module_env,
WasmCompilationUnit(Isolate* isolate, const wasm::ModuleEnv* module_env,
wasm::FunctionBody body, wasm::WasmName name, int index,
Handle<Code> centry_stub);
// Use the following constructors if the compilation may run on a background
// thread.
WasmCompilationUnit(Isolate* isolate, wasm::ModuleBytesEnv* module_env,
WasmCompilationUnit(Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes,
const wasm::ModuleEnv* module_env,
const wasm::WasmFunction* function,
Handle<Code> centry_stub,
const std::shared_ptr<Counters>& async_counters);
WasmCompilationUnit(Isolate* isolate, wasm::ModuleEnv* module_env,
WasmCompilationUnit(Isolate* isolate, const wasm::ModuleEnv* module_env,
wasm::FunctionBody body, wasm::WasmName name, int index,
Handle<Code> centry_stub,
const std::shared_ptr<Counters>& async_counters);
......@@ -73,7 +68,8 @@ class WasmCompilationUnit final {
static MaybeHandle<Code> CompileWasmFunction(
wasm::ErrorThrower* thrower, Isolate* isolate,
wasm::ModuleBytesEnv* module_env, const wasm::WasmFunction* function);
const wasm::ModuleWireBytes& wire_bytes,
const wasm::ModuleEnv* module_env, const wasm::WasmFunction* function);
void set_memory_cost(size_t memory_cost) { memory_cost_ = memory_cost; }
size_t memory_cost() const { return memory_cost_; }
......@@ -82,7 +78,7 @@ class WasmCompilationUnit final {
SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
Isolate* isolate_;
wasm::ModuleEnv* module_env_;
const wasm::ModuleEnv* module_env_;
wasm::FunctionBody func_body_;
wasm::WasmName func_name_;
Counters* counters_;
......@@ -145,7 +141,7 @@ typedef ZoneVector<Node*> NodeVector;
class WasmGraphBuilder {
public:
WasmGraphBuilder(
wasm::ModuleEnv* module_env, Zone* z, JSGraph* g,
const wasm::ModuleEnv* module_env, Zone* z, JSGraph* g,
Handle<Code> centry_stub_, wasm::FunctionSig* sig,
compiler::SourcePositionTable* source_position_table = nullptr);
......@@ -294,7 +290,7 @@ class WasmGraphBuilder {
bool has_simd() const { return has_simd_; }
wasm::ModuleEnv* module_env() const { return module_; }
const wasm::ModuleEnv* module_env() const { return module_env_; }
void SetRuntimeExceptionSupport(bool value) {
has_runtime_exception_support_ = value;
......@@ -306,7 +302,7 @@ class WasmGraphBuilder {
Zone* zone_;
JSGraph* jsgraph_;
Node* centry_stub_node_;
wasm::ModuleEnv* module_ = nullptr;
const wasm::ModuleEnv* module_env_ = nullptr;
Node* mem_buffer_ = nullptr;
Node* mem_size_ = nullptr;
NodeVector signature_tables_;
......
......@@ -619,9 +619,10 @@ class WasmFullDecoder : public WasmDecoder {
: WasmFullDecoder(zone, module, nullptr, body) {}
WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body)
: WasmFullDecoder(zone, builder->module_env() == nullptr
? nullptr
: builder->module_env()->module,
: WasmFullDecoder(zone,
builder->module_env() == nullptr
? nullptr
: builder->module_env()->module(),
builder, body) {}
bool Decode() {
......
This diff is collapsed.
......@@ -48,7 +48,7 @@ class ModuleCompiler {
~CompilationUnitBuilder() { DCHECK(units_.empty()); }
void AddUnit(ModuleEnv* module_env, const WasmFunction* function,
void AddUnit(const ModuleEnv* module_env, const WasmFunction* function,
uint32_t buffer_offset, Vector<const uint8_t> bytes,
WasmName name) {
units_.emplace_back(new compiler::WasmCompilationUnit(
......@@ -127,7 +127,8 @@ class ModuleCompiler {
}
size_t InitializeCompilationUnits(const std::vector<WasmFunction>& functions,
ModuleBytesEnv& module_env);
const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env);
void ReopenHandlesInDeferredScope();
......@@ -141,15 +142,18 @@ class ModuleCompiler {
MaybeHandle<Code> FinishCompilationUnit(ErrorThrower* thrower,
int* func_index);
void CompileInParallel(ModuleBytesEnv* module_env,
void CompileInParallel(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env,
std::vector<Handle<Code>>& results,
ErrorThrower* thrower);
void CompileSequentially(ModuleBytesEnv* module_env,
void CompileSequentially(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env,
std::vector<Handle<Code>>& results,
ErrorThrower* thrower);
void ValidateSequentially(ModuleBytesEnv* module_env, ErrorThrower* thrower);
void ValidateSequentially(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env, ErrorThrower* thrower);
MaybeHandle<WasmModuleObject> CompileToModuleObject(
ErrorThrower* thrower, const ModuleWireBytes& wire_bytes,
......@@ -162,8 +166,7 @@ class ModuleCompiler {
MaybeHandle<WasmModuleObject> CompileToModuleObjectInternal(
ErrorThrower* thrower, const ModuleWireBytes& wire_bytes,
Handle<Script> asm_js_script,
Vector<const byte> asm_js_offset_table_bytes, Factory* factory,
WasmInstance* temp_instance);
Vector<const byte> asm_js_offset_table_bytes, Factory* factory);
Isolate* isolate_;
std::unique_ptr<WasmModule> module_;
......@@ -343,13 +346,12 @@ class AsyncCompileJob {
Handle<Context> context_;
Handle<JSPromise> module_promise_;
std::unique_ptr<ModuleCompiler> compiler_;
std::unique_ptr<ModuleBytesEnv> module_bytes_env_;
std::unique_ptr<ModuleEnv> module_env_;
std::vector<DeferredHandles*> deferred_handles_;
Handle<WasmModuleObject> module_object_;
Handle<WasmCompiledModule> compiled_module_;
Handle<FixedArray> code_table_;
std::unique_ptr<WasmInstance> temp_instance_ = nullptr;
size_t outstanding_units_ = 0;
std::unique_ptr<CompileStep> step_;
CancelableTaskManager background_task_manager_;
......
......@@ -712,11 +712,10 @@ class ModuleDecoder : public Decoder {
&module_->functions[i + module_->num_imported_functions];
function->code = {offset, size};
if (verify_functions) {
ModuleBytesEnv module_env(module_.get(), nullptr,
ModuleWireBytes(start_, end_));
ModuleWireBytes bytes(start_, end_);
VerifyFunctionBody(module_->signature_zone->allocator(),
i + module_->num_imported_functions, &module_env,
function);
i + module_->num_imported_functions, bytes,
module_.get(), function);
}
}
}
......@@ -847,7 +846,9 @@ class ModuleDecoder : public Decoder {
}
// Decodes a single anonymous function starting at {start_}.
FunctionResult DecodeSingleFunction(Zone* zone, ModuleBytesEnv* module_env,
FunctionResult DecodeSingleFunction(Zone* zone,
const ModuleWireBytes& wire_bytes,
const WasmModule* module,
std::unique_ptr<WasmFunction> function) {
pc_ = start_;
function->sig = consume_sig(zone);
......@@ -855,7 +856,8 @@ class ModuleDecoder : public Decoder {
function->code = {off(pc_), static_cast<uint32_t>(end_ - pc_)};
if (ok())
VerifyFunctionBody(zone->allocator(), 0, module_env, function.get());
VerifyFunctionBody(zone->allocator(), 0, wire_bytes, module,
function.get());
FunctionResult result(std::move(function));
// Copy error code and location.
......@@ -1002,9 +1004,9 @@ class ModuleDecoder : public Decoder {
// Verifies the body (code) of a given function.
void VerifyFunctionBody(AccountingAllocator* allocator, uint32_t func_num,
ModuleBytesEnv* menv, WasmFunction* function) {
WasmFunctionName func_name(function,
menv->wire_bytes.GetNameOrNull(function));
const ModuleWireBytes& wire_bytes,
const WasmModule* module, WasmFunction* function) {
WasmFunctionName func_name(function, wire_bytes.GetNameOrNull(function));
if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
OFStream os(stdout);
os << "Verifying wasm function " << func_name << std::endl;
......@@ -1013,9 +1015,8 @@ class ModuleDecoder : public Decoder {
function->sig, function->code.offset(),
start_ + GetBufferRelativeOffset(function->code.offset()),
start_ + GetBufferRelativeOffset(function->code.end_offset())};
DecodeResult result = VerifyWasmCodeWithStats(
allocator, menv == nullptr ? nullptr : menv->module_env.module, body,
IsWasm(), GetCounters());
DecodeResult result = VerifyWasmCodeWithStats(allocator, module, body,
IsWasm(), GetCounters());
if (result.failed()) {
// Wrap the error message from the function decoder.
std::ostringstream wrapped;
......@@ -1357,7 +1358,8 @@ WasmInitExpr DecodeWasmInitExprForTesting(const byte* start, const byte* end) {
namespace {
FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone,
ModuleBytesEnv* module_env,
const ModuleWireBytes& wire_bytes,
const WasmModule* module,
const byte* function_start,
const byte* function_end,
Counters* counters) {
......@@ -1368,25 +1370,26 @@ FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone,
return FunctionResult::Error("size > maximum function size: %zu", size);
ModuleDecoder decoder(function_start, function_end, kWasmOrigin);
decoder.SetCounters(counters);
return decoder.DecodeSingleFunction(zone, module_env,
return decoder.DecodeSingleFunction(zone, wire_bytes, module,
base::make_unique<WasmFunction>());
}
} // namespace
FunctionResult SyncDecodeWasmFunction(Isolate* isolate, Zone* zone,
ModuleBytesEnv* module_env,
const ModuleWireBytes& wire_bytes,
const WasmModule* module,
const byte* function_start,
const byte* function_end) {
return DecodeWasmFunction(isolate, zone, module_env, function_start,
return DecodeWasmFunction(isolate, zone, wire_bytes, module, function_start,
function_end, isolate->counters());
}
FunctionResult AsyncDecodeWasmFunction(
Isolate* isolate, Zone* zone, ModuleBytesEnv* module_env,
const byte* function_start, const byte* function_end,
std::shared_ptr<Counters> async_counters) {
return DecodeWasmFunction(isolate, zone, module_env, function_start,
Isolate* isolate, Zone* zone, const ModuleWireBytes& wire_bytes,
const WasmModule* module, const byte* function_start,
const byte* function_end, std::shared_ptr<Counters> async_counters) {
return DecodeWasmFunction(isolate, zone, wire_bytes, module, function_start,
function_end, async_counters.get());
}
......
......@@ -100,12 +100,13 @@ V8_EXPORT_PRIVATE FunctionSig* DecodeWasmSignatureForTesting(Zone* zone,
// Decodes the bytes of a wasm function between
// {function_start} and {function_end}.
V8_EXPORT_PRIVATE FunctionResult
SyncDecodeWasmFunction(Isolate* isolate, Zone* zone, ModuleBytesEnv* env,
const byte* function_start, const byte* function_end);
V8_EXPORT_PRIVATE FunctionResult SyncDecodeWasmFunction(
Isolate* isolate, Zone* zone, const ModuleWireBytes& wire_bytes,
const WasmModule* module, const byte* function_start,
const byte* function_end);
V8_EXPORT_PRIVATE FunctionResult
AsyncDecodeWasmFunction(Isolate* isolate, Zone* zone, ModuleBytesEnv* env,
AsyncDecodeWasmFunction(Isolate* isolate, Zone* zone, const ModuleEnv* env,
const byte* function_start, const byte* function_end,
const std::shared_ptr<Counters> async_counters);
......
......@@ -214,6 +214,37 @@ void RecordLazyCodeStats(Code* code, Counters* counters) {
counters->wasm_reloc_size()->Increment(code->relocation_info()->length());
}
ModuleEnv CreateModuleEnvFromRuntimeObject(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
DisallowHeapAllocation no_gc;
// Store a vector of handles to be embedded in the generated code.
// TODO(clemensh): For concurrent compilation, these will have to live in a
// DeferredHandleScope.
wasm::ModuleEnv module_env(compiled_module->module(),
BUILTIN_CODE(isolate, WasmCompileLazy));
DCHECK_EQ(compiled_module->has_function_tables(),
compiled_module->has_signature_tables());
if (compiled_module->has_function_tables()) {
// TODO(clemensh): For concurrent compilation, these will have to live in a
// DeferredHandleScope.
FixedArray* function_tables = compiled_module->ptr_to_function_tables();
FixedArray* signature_tables = compiled_module->ptr_to_signature_tables();
DCHECK_EQ(function_tables->length(), signature_tables->length());
DCHECK_EQ(function_tables->length(), module_env.function_tables().size());
for (uint32_t i = 0, e = static_cast<uint32_t>(
module_env.function_tables().size());
i < e; ++i) {
int index = static_cast<int>(i);
module_env.SetFunctionTable(
i, handle(FixedArray::cast(function_tables->get(index))),
handle(FixedArray::cast(signature_tables->get(index))));
}
}
return module_env;
}
} // namespace
// static
......@@ -954,25 +985,12 @@ void LazyCompilationOrchestrator::CompileFunction(
return;
}
size_t num_function_tables =
compiled_module->module()->function_tables.size();
// Store a vector of handles to be embedded in the generated code.
// TODO(clemensh): For concurrent compilation, these will have to live in a
// DeferredHandleScope.
std::vector<Handle<FixedArray>> fun_tables(num_function_tables);
std::vector<Handle<FixedArray>> sig_tables(num_function_tables);
for (size_t i = 0; i < num_function_tables; ++i) {
Object* fun_table =
compiled_module->function_tables()->get(static_cast<int>(i));
fun_tables[i] = handle(FixedArray::cast(fun_table), isolate);
Object* sig_table =
compiled_module->signature_tables()->get(static_cast<int>(i));
sig_tables[i] = handle(FixedArray::cast(sig_table), isolate);
}
wasm::ModuleEnv module_env(compiled_module->module(), &fun_tables,
&sig_tables);
uint8_t* module_start = compiled_module->module_bytes()->GetChars();
const WasmFunction* func = &module_env.module->functions[func_index];
wasm::ModuleEnv module_env =
CreateModuleEnvFromRuntimeObject(isolate, compiled_module);
const uint8_t* module_start = compiled_module->module_bytes()->GetChars();
const WasmFunction* func = &module_env.module()->functions[func_index];
wasm::FunctionBody body{func->sig, func->code.offset(),
module_start + func->code.offset(),
module_start + func->code.end_offset()};
......@@ -1016,10 +1034,11 @@ void LazyCompilationOrchestrator::CompileFunction(
// Now specialize the generated code for this instance.
Zone specialization_zone(isolate->allocator(), ZONE_NAME);
CodeSpecialization code_specialization(isolate, &specialization_zone);
if (module_env.module->globals_size) {
if (module_env.module()->globals_size) {
Address globals_start =
reinterpret_cast<Address>(compiled_module->globals_start());
code_specialization.RelocateGlobals(nullptr, globals_start);
code_specialization.RelocateGlobals(module_env.globals_start(),
globals_start);
}
if (instance->has_memory_buffer()) {
Address mem_start =
......@@ -1027,8 +1046,8 @@ void LazyCompilationOrchestrator::CompileFunction(
int mem_size = instance->memory_buffer()->byte_length()->Number();
DCHECK_IMPLIES(mem_start == nullptr, mem_size == 0);
if (mem_start != nullptr) {
code_specialization.RelocateMemoryReferences(nullptr, 0, mem_start,
mem_size);
code_specialization.RelocateMemoryReferences(
module_env.mem_start(), module_env.mem_size(), mem_start, mem_size);
}
}
code_specialization.RelocateDirectCalls(instance);
......
......@@ -223,44 +223,6 @@ struct V8_EXPORT_PRIVATE WasmModule {
typedef Managed<WasmModule> WasmModuleWrapper;
// An instantiated wasm module, including memory, function table, etc.
struct WasmInstance {
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(WasmInstance);
WasmModule* module; // static representation of the module.
// -- Heap allocated --------------------------------------------------------
std::vector<Handle<FixedArray>> function_tables; // indirect function tables.
std::vector<Handle<FixedArray>>
signature_tables; // indirect signature tables.
// TODO(wasm): Remove this vector, since it is only used for testing.
std::vector<Handle<Code>> function_code; // code objects for each function.
// -- raw memory ------------------------------------------------------------
byte* mem_start = nullptr; // start of linear memory.
uint32_t mem_size = 0; // size of the linear memory.
// -- raw globals -----------------------------------------------------------
byte* globals_start = nullptr; // start of the globals area.
explicit WasmInstance(WasmModule* m)
: module(m),
function_tables(m->function_tables.size()),
signature_tables(m->function_tables.size()),
function_code(m->functions.size()) {}
void ReopenHandles(Isolate* isolate) {
for (auto& table : function_tables) {
table = handle(*table, isolate);
}
for (auto& table : signature_tables) {
table = handle(*table, isolate);
}
for (auto& code : function_code) {
code = handle(*code, isolate);
}
}
};
// Interface to the storage (wire bytes) of a wasm module.
// It is illegal for anyone receiving a ModuleWireBytes to store pointers based
// on module_bytes, as this storage is only guaranteed to be alive as long as
......@@ -318,80 +280,136 @@ struct V8_EXPORT_PRIVATE ModuleWireBytes {
const Vector<const byte> module_bytes_;
};
// Interface provided to the decoder/graph builder which contains only
// minimal information about the globals, functions, and function tables.
struct V8_EXPORT_PRIVATE ModuleEnv {
// Specialization parameters the compiler needs to use when compiling the wasm
// functions of a module.
// We currently only produce code specialized to an instance. Even when
// compiling without instantiating, we still need to pick *a* value for these
// parameters.
class V8_EXPORT_PRIVATE ModuleEnv {
public:
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ModuleEnv);
ModuleEnv(WasmModule* module, WasmInstance* instance)
: module(module),
instance(instance),
function_tables(instance ? &instance->function_tables : nullptr),
signature_tables(instance ? &instance->signature_tables : nullptr) {}
ModuleEnv(WasmModule* module,
std::vector<Handle<FixedArray>>* function_tables,
std::vector<Handle<FixedArray>>* signature_tables)
: module(module),
instance(nullptr),
function_tables(function_tables),
signature_tables(signature_tables) {}
WasmModule* module;
WasmInstance* instance;
std::vector<Handle<FixedArray>>* function_tables;
std::vector<Handle<FixedArray>>* signature_tables;
ModuleEnv(WasmModule* module, Handle<Code> default_function_code)
: module_(module),
function_tables_(module->function_tables.size()),
signature_tables_(module->function_tables.size()),
function_code_(module->functions.size(), default_function_code),
mem_size_(module->min_mem_pages * WasmModule::kPageSize) {}
WasmModule* module() const { return module_; }
uint32_t mem_size() const { return mem_size_; }
void set_mem_size(uint32_t mem_size) {
DCHECK_EQ(0, mem_size % WasmModule::kPageSize);
mem_size_ = mem_size;
}
byte* mem_start() const { return mem_start_; }
void set_mem_start(byte* mem_start) { mem_start_ = mem_start; }
byte* globals_start() const { return globals_start_; }
void set_globals_start(byte* globals_start) {
globals_start_ = globals_start;
}
const std::vector<Handle<FixedArray>>& function_tables() const {
return function_tables_;
}
const std::vector<Handle<FixedArray>>& signature_tables() const {
return signature_tables_;
}
void SetFunctionTable(uint32_t index, Handle<FixedArray> function_table,
Handle<FixedArray> signature_table) {
DCHECK(IsValidTable(index));
DCHECK_EQ(function_tables_.size(), signature_tables_.size());
function_tables_[index] = function_table;
signature_tables_[index] = signature_table;
}
bool IsValidGlobal(uint32_t index) const {
return module && index < module->globals.size();
return index < module_->globals.size();
}
bool IsValidFunction(uint32_t index) const {
return module && index < module->functions.size();
return index < module_->functions.size();
}
bool IsValidSignature(uint32_t index) const {
return module && index < module->signatures.size();
return index < module_->signatures.size();
}
bool IsValidTable(uint32_t index) const {
return module && index < module->function_tables.size();
return index < module_->function_tables.size();
}
ValueType GetGlobalType(uint32_t index) {
ValueType GetGlobalType(uint32_t index) const {
DCHECK(IsValidGlobal(index));
return module->globals[index].type;
return module_->globals[index].type;
}
FunctionSig* GetFunctionSignature(uint32_t index) {
FunctionSig* GetFunctionSignature(uint32_t index) const {
DCHECK(IsValidFunction(index));
return module->functions[index].sig;
// This const_cast preserves design intent, because
// FunctionSig is an immutable type.
return const_cast<FunctionSig*>(module_->functions[index].sig);
}
FunctionSig* GetSignature(uint32_t index) {
FunctionSig* GetSignature(uint32_t index) const {
DCHECK(IsValidSignature(index));
return module->signatures[index];
// This const_cast preserves design intent, because
// FunctionSig is an immutable type.
return const_cast<FunctionSig*>(module_->signatures[index]);
}
const WasmIndirectFunctionTable* GetTable(uint32_t index) const {
DCHECK(IsValidTable(index));
return &module->function_tables[index];
return &module_->function_tables[index];
}
bool is_asm_js() const { return module->is_asm_js(); }
bool is_wasm() const { return module->is_wasm(); }
bool is_asm_js() const { return module_->is_asm_js(); }
bool is_wasm() const { return module_->is_wasm(); }
// Only used for testing.
Handle<Code> GetFunctionCode(uint32_t index) {
DCHECK_NOT_NULL(instance);
return instance->function_code[index];
Handle<Code> GetFunctionCode(uint32_t index) const {
return function_code_[index];
}
};
// A ModuleEnv together with ModuleWireBytes.
struct ModuleBytesEnv {
ModuleBytesEnv(WasmModule* module, WasmInstance* instance,
Vector<const byte> module_bytes)
: module_env(module, instance), wire_bytes(module_bytes) {}
ModuleBytesEnv(WasmModule* module, WasmInstance* instance,
const ModuleWireBytes& wire_bytes)
: module_env(module, instance), wire_bytes(wire_bytes) {}
ModuleEnv module_env;
ModuleWireBytes wire_bytes;
// TODO(mtrofin): this is async compilation-specific. Move this out.
void ReopenHandles(Isolate* isolate) {
for (auto& table : function_tables_) {
table = handle(*table, isolate);
}
for (auto& table : signature_tables_) {
table = handle(*table, isolate);
}
for (auto& code : function_code_) {
code = handle(*code, isolate);
}
}
// Intentionally set a memory size that may not conform to
// the wasm invariant that it should be divisible by kPageSize - for test.
void SetMemSizeUnchecked(uint32_t size) { mem_size_ = size; }
protected:
// The derived class is responsible for correctly setting up the
// state. This is currently used by test, where we set up the state
// gradually, and also sometimes intentionally invalidating some
// invariants.
ModuleEnv() = default;
// decoded wasm module.
WasmModule* module_ = nullptr;
// indirect function tables.
std::vector<Handle<FixedArray>> function_tables_;
// indirect signature tables.
std::vector<Handle<FixedArray>> signature_tables_;
// TODO(mtrofin): this should be a Handle<Code>, not a vector,
// however, cctest currently builds up modules in a non-production
// standard way. We should address that first.
std::vector<Handle<Code>> function_code_;
private:
// size of the linear memory.
uint32_t mem_size_ = 0;
// start of linear memory.
byte* mem_start_ = nullptr;
// start of the globals area.
byte* globals_start_ = nullptr;
};
// A helper for printing out the names of functions.
......
......@@ -785,9 +785,7 @@ void WasmSharedModuleData::PrepareForLazyCompilation(
Handle<WasmCompiledModule> WasmCompiledModule::New(
Isolate* isolate, Handle<WasmSharedModuleData> shared,
Handle<FixedArray> code_table,
const std::vector<Handle<FixedArray>>& function_tables,
const std::vector<Handle<FixedArray>>& signature_tables) {
Handle<FixedArray> code_table, const ModuleEnv& module_env) {
Handle<FixedArray> ret =
isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED);
// WasmCompiledModule::cast would fail since fields are not set yet.
......@@ -799,16 +797,18 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(
compiled_module->set_code_table(code_table);
size_t function_table_count = shared->module()->function_tables.size();
if (function_table_count > 0) {
DCHECK_EQ(function_tables.size(), signature_tables.size());
DCHECK_EQ(function_tables.size(), function_table_count);
DCHECK_EQ(module_env.function_tables().size(),
module_env.signature_tables().size());
DCHECK_EQ(module_env.function_tables().size(), function_table_count);
int count_as_int = static_cast<int>(function_table_count);
Handle<FixedArray> sig_tables =
isolate->factory()->NewFixedArray(count_as_int, TENURED);
Handle<FixedArray> func_tables =
isolate->factory()->NewFixedArray(count_as_int, TENURED);
for (int i = 0; i < count_as_int; ++i) {
sig_tables->set(i, *(signature_tables[static_cast<size_t>(i)]));
func_tables->set(i, *(function_tables[static_cast<size_t>(i)]));
size_t index = static_cast<size_t>(i);
sig_tables->set(i, *(module_env.signature_tables()[index]));
func_tables->set(i, *(module_env.function_tables()[index]));
}
compiled_module->set_signature_tables(sig_tables);
compiled_module->set_empty_function_tables(func_tables);
......@@ -821,6 +821,8 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(
compiled_module->set_min_mem_pages(shared->module()->min_mem_pages);
compiled_module->set_num_imported_functions(
shared->module()->num_imported_functions);
// TODO(mtrofin): copy the rest of the specialization parameters over.
// We're currently OK because we're only using defaults.
return compiled_module;
}
......
......@@ -420,11 +420,10 @@ class WasmCompiledModule : public FixedArray {
};
public:
static Handle<WasmCompiledModule> New(
Isolate* isolate, Handle<WasmSharedModuleData> shared,
Handle<FixedArray> code_table,
const std::vector<Handle<FixedArray>>& function_tables,
const std::vector<Handle<FixedArray>>& signature_tables);
static Handle<WasmCompiledModule> New(Isolate* isolate,
Handle<WasmSharedModuleData> shared,
Handle<FixedArray> code_table,
const wasm::ModuleEnv& module_env);
static Handle<WasmCompiledModule> Clone(Isolate* isolate,
Handle<WasmCompiledModule> module);
......
......@@ -230,11 +230,10 @@ WASM_EXEC_TEST(StoreMemI32_oob_asm) {
WasmRunner<int32_t, uint32_t> r(kExecuteCompiled); \
r.module().ChangeOriginToAsmjs(); \
BUILD(r, WASM_UNOP(OP_TYPE, WASM_GET_LOCAL(0))); \
CHECK_EQ(1, \
GetMatchingRelocInfoCount(r.module().instance->function_code[0], \
RelocInfo::WASM_MEMORY_REFERENCE)); \
CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().GetFunctionCode(0), \
RelocInfo::WASM_MEMORY_REFERENCE)); \
CHECK_NE( \
0, GetMatchingRelocInfoCount(r.module().instance->function_code[0], \
0, GetMatchingRelocInfoCount(r.module().GetFunctionCode(0), \
RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); \
}
......@@ -245,11 +244,10 @@ FOREACH_INT_CHECKED_LOAD_OP(INT_LOAD_TEST)
WasmRunner<int32_t, uint32_t, uint32_t> r(kExecuteCompiled); \
r.module().ChangeOriginToAsmjs(); \
BUILD(r, WASM_BINOP(OP_TYPE, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); \
CHECK_EQ(1, \
GetMatchingRelocInfoCount(r.module().instance->function_code[0], \
RelocInfo::WASM_MEMORY_REFERENCE)); \
CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().GetFunctionCode(0), \
RelocInfo::WASM_MEMORY_REFERENCE)); \
CHECK_NE( \
0, GetMatchingRelocInfoCount(r.module().instance->function_code[0], \
0, GetMatchingRelocInfoCount(r.module().GetFunctionCode(0), \
RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); \
}
......@@ -260,9 +258,9 @@ TEST(RunWasm_AsmCheckedLoadFloat32RelocInfo) {
r.module().ChangeOriginToAsmjs();
BUILD(r, WASM_UNOP(kExprF32AsmjsLoadMem, WASM_GET_LOCAL(0)));
CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().instance->function_code[0],
CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().GetFunctionCode(0),
RelocInfo::WASM_MEMORY_REFERENCE));
CHECK_NE(0, GetMatchingRelocInfoCount(r.module().instance->function_code[0],
CHECK_NE(0, GetMatchingRelocInfoCount(r.module().GetFunctionCode(0),
RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
}
......@@ -272,9 +270,9 @@ TEST(RunWasm_AsmCheckedStoreFloat32RelocInfo) {
BUILD(r, WASM_BINOP(kExprF32AsmjsStoreMem, WASM_GET_LOCAL(0),
WASM_GET_LOCAL(1)));
CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().instance->function_code[0],
CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().GetFunctionCode(0),
RelocInfo::WASM_MEMORY_REFERENCE));
CHECK_NE(0, GetMatchingRelocInfoCount(r.module().instance->function_code[0],
CHECK_NE(0, GetMatchingRelocInfoCount(r.module().GetFunctionCode(0),
RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
}
......@@ -283,9 +281,9 @@ TEST(RunWasm_AsmCheckedLoadFloat64RelocInfo) {
r.module().ChangeOriginToAsmjs();
BUILD(r, WASM_UNOP(kExprF64AsmjsLoadMem, WASM_GET_LOCAL(0)));
CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().instance->function_code[0],
CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().GetFunctionCode(0),
RelocInfo::WASM_MEMORY_REFERENCE));
CHECK_NE(0, GetMatchingRelocInfoCount(r.module().instance->function_code[0],
CHECK_NE(0, GetMatchingRelocInfoCount(r.module().GetFunctionCode(0),
RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
}
......@@ -295,8 +293,8 @@ TEST(RunWasm_AsmCheckedStoreFloat64RelocInfo) {
BUILD(r, WASM_BINOP(kExprF64AsmjsStoreMem, WASM_GET_LOCAL(0),
WASM_GET_LOCAL(1)));
CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().instance->function_code[0],
CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().GetFunctionCode(0),
RelocInfo::WASM_MEMORY_REFERENCE));
CHECK_NE(0, GetMatchingRelocInfoCount(r.module().instance->function_code[0],
CHECK_NE(0, GetMatchingRelocInfoCount(r.module().GetFunctionCode(0),
RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
}
......@@ -32,13 +32,13 @@ using namespace v8::internal::compiler;
/* global = global + p0 */ \
BUILD(r, WASM_SET_GLOBAL(1, ADD(WASM_GET_GLOBAL(0), WASM_GET_LOCAL(0))), \
WASM_GET_GLOBAL(0)); \
CHECK_EQ(1, r.module().instance->function_code.size()); \
CHECK_EQ(1, r.module().FunctionCodeSize()); \
\
int filter = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; \
\
Handle<Code> code = r.module().instance->function_code[0]; \
Handle<Code> code = r.module().GetFunctionCode(0); \
\
Address old_start = r.module().instance->globals_start; \
Address old_start = r.module().globals_start(); \
Address new_start = old_start + 1; \
\
Address old_addresses[4]; \
......
......@@ -141,7 +141,7 @@ Handle<JSObject> MakeFakeBreakpoint(Isolate* isolate, int position) {
void SetBreakpoint(WasmRunnerBase& runner, int function_index, int byte_offset,
int expected_set_byte_offset = -1) {
int func_offset =
runner.module().module->functions[function_index].code.offset();
runner.module().module()->functions[function_index].code.offset();
int code_offset = func_offset + byte_offset;
if (expected_set_byte_offset == -1) expected_set_byte_offset = byte_offset;
Handle<WasmInstanceObject> instance = runner.module().instance_object();
......
This diff is collapsed.
......@@ -122,8 +122,8 @@ class FunctionBodyDecoderTest : public TestWithZone {
// Verify the code.
DecodeResult result = VerifyWasmCode(
zone()->allocator(), module == nullptr ? nullptr : module->module, sig,
start, end);
zone()->allocator(), module == nullptr ? nullptr : module->module(),
sig, start, end);
uint32_t pc = result.error_offset();
std::ostringstream str;
......@@ -193,8 +193,8 @@ constexpr size_t kMaxByteSizedLeb128 = 127;
// globals, or memories.
class TestModuleEnv : public ModuleEnv {
public:
explicit TestModuleEnv(ModuleOrigin origin = kWasmOrigin)
: ModuleEnv(&mod, nullptr) {
explicit TestModuleEnv(ModuleOrigin origin = kWasmOrigin) {
module_ = &mod;
mod.set_origin(origin);
}
byte AddGlobal(ValueType type, bool mutability = true) {
......
......@@ -985,17 +985,16 @@ TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) {
class WasmFunctionVerifyTest : public TestWithIsolateAndZone {
public:
WasmFunctionVerifyTest()
: instance(&module), env(&module, &instance, bytes) {}
WasmFunctionVerifyTest() : env(&module, Handle<Code>::null()) {}
virtual ~WasmFunctionVerifyTest() {}
ModuleBytesEnv* get_env() { return &env; }
const ModuleEnv* get_env() const { return &env; }
Vector<const byte> get_bytes() const { return bytes; }
private:
WasmModule module;
WasmInstance instance;
Vector<const byte> bytes;
ModuleBytesEnv env;
ModuleEnv env;
DISALLOW_COPY_AND_ASSIGN(WasmFunctionVerifyTest);
};
......@@ -1014,8 +1013,9 @@ TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
kExprEnd // body
};
FunctionResult result = SyncDecodeWasmFunction(isolate(), zone(), get_env(),
data, data + sizeof(data));
FunctionResult result =
SyncDecodeWasmFunction(isolate(), zone(), get_bytes(),
get_env()->module(), data, data + sizeof(data));
EXPECT_OK(result);
if (result.val && result.ok()) {
......
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