Commit e79d4f06 authored by Michael Achenbach's avatar Michael Achenbach Committed by Commit Bot

Revert "[wasm] Move the ModuleEnv to compiler and make it immutable."

This reverts commit d04660db.

Reason for revert: Suspect for blocking the roll:
https://chromium-review.googlesource.com/c/621191

See:
https://build.chromium.org/p/tryserver.chromium.win/builders/win_optional_gpu_tests_rel/builds/13583

Original change's description:
> [wasm] Move the ModuleEnv to compiler and make it immutable.
> 
> This CL (finally) makes the contract between the compiler and the module
> environment clear. In order to compile a function, the caller must provide
> an instance of the compiler::ModuleEnv struct, which contains references
> to code, function and signature tables, memory start, etc.
> 
> R=​mtrofin@chromium.org,ahaas@chromium.org
> 
> Bug: 
> Change-Id: I68e44d5da2c5ad44dad402029c2e57f2d5d25b4f
> Reviewed-on: https://chromium-review.googlesource.com/613880
> Reviewed-by: Mircea Trofin <mtrofin@chromium.org>
> Reviewed-by: Andreas Haas <ahaas@chromium.org>
> Commit-Queue: Ben Titzer <titzer@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#47418}

TBR=titzer@chromium.org,mtrofin@chromium.org,ahaas@chromium.org

Change-Id: I60a369a43121720fbb13ea6c2ec6ca948d60a20b
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/622547
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: 's avatarMichael Achenbach <machenbach@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47451}
parent af37f6b9
This diff is collapsed.
...@@ -32,67 +32,33 @@ class SourcePositionTable; ...@@ -32,67 +32,33 @@ class SourcePositionTable;
namespace wasm { namespace wasm {
struct DecodeStruct; struct DecodeStruct;
class SignatureMap;
// Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}. // Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
typedef compiler::Node TFNode; typedef compiler::Node TFNode;
typedef compiler::JSGraph TFGraph; typedef compiler::JSGraph TFGraph;
} // namespace wasm } // namespace wasm
namespace compiler { namespace compiler {
// The {ModuleEnv} encapsulates the module data that is used by the
// {WasmGraphBuilder} during graph building. It represents the parameters to
// which the compiled code should be specialized, including which code to call
// for direct calls {function_code}, which tables to use for indirect calls
// {function_tables}, memory start address and size {mem_start, mem_size},
// globals start address {globals_start}, as well as signature maps
// {signature_maps} and the module itself {module}.
// ModuleEnvs are shareable across multiple compilations.
struct ModuleEnv {
// A pointer to the decoded module's static representation.
const wasm::WasmModule* module;
// The function tables are FixedArrays of code used to dispatch indirect
// calls. (the same length as module.function_tables)
const std::vector<Handle<FixedArray>> function_tables;
// The signatures tables are FixedArrays of SMIs used to check signatures
// match at runtime.
// (the same length as module.function_tables)
const std::vector<Handle<FixedArray>> signature_tables;
// Signature maps canonicalize {FunctionSig*} to indexes. New entries can be
// added to a signature map during graph building.
// Normally, these signature maps correspond to the signature maps in the
// function tables stored in the {module}.
const std::vector<wasm::SignatureMap*> signature_maps;
// Contains the code objects to call for each indirect call.
// (the same length as module.functions)
const std::vector<Handle<Code>> function_code;
// If the default code is not a null handle, always use it for direct calls.
const Handle<Code> default_function_code;
// Address of the start of memory.
const uintptr_t mem_start;
// Size of memory in bytes.
const uint32_t mem_size;
// Address of the start of the globals region.
const uintptr_t globals_start;
};
class WasmCompilationUnit final { class WasmCompilationUnit final {
public: public:
// Use the following constructors if you know you are running on the // Use the following constructors if you know you are running on the
// foreground thread. // foreground thread.
WasmCompilationUnit(Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes, WasmCompilationUnit(Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes,
ModuleEnv* env, const wasm::WasmFunction* function, const wasm::ModuleEnv* module_env,
const wasm::WasmFunction* function,
Handle<Code> centry_stub);
WasmCompilationUnit(Isolate* isolate, const wasm::ModuleEnv* module_env,
wasm::FunctionBody body, wasm::WasmName name, int index,
Handle<Code> centry_stub); Handle<Code> centry_stub);
WasmCompilationUnit(Isolate* isolate, ModuleEnv* 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 // Use the following constructors if the compilation may run on a background
// thread. // thread.
WasmCompilationUnit(Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes, WasmCompilationUnit(Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes,
ModuleEnv* env, const wasm::WasmFunction* function, const wasm::ModuleEnv* module_env,
const wasm::WasmFunction* function,
Handle<Code> centry_stub, Handle<Code> centry_stub,
const std::shared_ptr<Counters>& async_counters); const std::shared_ptr<Counters>& async_counters);
WasmCompilationUnit(Isolate* isolate, ModuleEnv* env, wasm::FunctionBody body, WasmCompilationUnit(Isolate* isolate, const wasm::ModuleEnv* module_env,
wasm::WasmName name, int index, Handle<Code> centry_stub, wasm::FunctionBody body, wasm::WasmName name, int index,
Handle<Code> centry_stub,
const std::shared_ptr<Counters>& async_counters); const std::shared_ptr<Counters>& async_counters);
int func_index() const { return func_index_; } int func_index() const { return func_index_; }
...@@ -102,8 +68,8 @@ class WasmCompilationUnit final { ...@@ -102,8 +68,8 @@ class WasmCompilationUnit final {
static MaybeHandle<Code> CompileWasmFunction( static MaybeHandle<Code> CompileWasmFunction(
wasm::ErrorThrower* thrower, Isolate* isolate, wasm::ErrorThrower* thrower, Isolate* isolate,
const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env, const wasm::ModuleWireBytes& wire_bytes,
const wasm::WasmFunction* function); const wasm::ModuleEnv* module_env, const wasm::WasmFunction* function);
void set_memory_cost(size_t memory_cost) { memory_cost_ = memory_cost; } void set_memory_cost(size_t memory_cost) { memory_cost_ = memory_cost; }
size_t memory_cost() const { return memory_cost_; } size_t memory_cost() const { return memory_cost_; }
...@@ -112,7 +78,7 @@ class WasmCompilationUnit final { ...@@ -112,7 +78,7 @@ class WasmCompilationUnit final {
SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms); SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
Isolate* isolate_; Isolate* isolate_;
ModuleEnv* env_; const wasm::ModuleEnv* module_env_;
wasm::FunctionBody func_body_; wasm::FunctionBody func_body_;
wasm::WasmName func_name_; wasm::WasmName func_name_;
Counters* counters_; Counters* counters_;
...@@ -171,8 +137,8 @@ typedef ZoneVector<Node*> NodeVector; ...@@ -171,8 +137,8 @@ typedef ZoneVector<Node*> NodeVector;
class WasmGraphBuilder { class WasmGraphBuilder {
public: public:
WasmGraphBuilder( WasmGraphBuilder(
ModuleEnv* env, Zone* z, JSGraph* g, Handle<Code> centry_stub_, const wasm::ModuleEnv* module_env, Zone* z, JSGraph* g,
wasm::FunctionSig* sig, Handle<Code> centry_stub_, wasm::FunctionSig* sig,
compiler::SourcePositionTable* source_position_table = nullptr); compiler::SourcePositionTable* source_position_table = nullptr);
Node** Buffer(size_t count) { Node** Buffer(size_t count) {
...@@ -318,19 +284,19 @@ class WasmGraphBuilder { ...@@ -318,19 +284,19 @@ class WasmGraphBuilder {
bool has_simd() const { return has_simd_; } bool has_simd() const { return has_simd_; }
const wasm::ModuleEnv* module_env() const { return module_env_; }
void SetRuntimeExceptionSupport(bool value) { void SetRuntimeExceptionSupport(bool value) {
has_runtime_exception_support_ = value; has_runtime_exception_support_ = value;
} }
const wasm::WasmModule* module() { return env_ ? env_->module : nullptr; }
private: private:
static const int kDefaultBufferSize = 16; static const int kDefaultBufferSize = 16;
Zone* zone_; Zone* zone_;
JSGraph* jsgraph_; JSGraph* jsgraph_;
Node* centry_stub_node_; Node* centry_stub_node_;
ModuleEnv* env_ = nullptr; const wasm::ModuleEnv* module_env_ = nullptr;
Node* mem_buffer_ = nullptr; Node* mem_buffer_ = nullptr;
Node* mem_size_ = nullptr; Node* mem_size_ = nullptr;
NodeVector signature_tables_; NodeVector signature_tables_;
......
...@@ -619,7 +619,11 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -619,7 +619,11 @@ class WasmFullDecoder : public WasmDecoder {
: WasmFullDecoder(zone, module, nullptr, body) {} : WasmFullDecoder(zone, module, nullptr, body) {}
WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body) WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body)
: WasmFullDecoder(zone, builder->module(), builder, body) {} : WasmFullDecoder(zone,
builder->module_env() == nullptr
? nullptr
: builder->module_env()->module(),
builder, body) {}
bool Decode() { bool Decode() {
if (FLAG_wasm_code_fuzzer_gen_test) { if (FLAG_wasm_code_fuzzer_gen_test) {
......
This diff is collapsed.
...@@ -27,8 +27,7 @@ class ModuleCompiler { ...@@ -27,8 +27,7 @@ class ModuleCompiler {
// In {CompileToModuleObject}, it will transfer ownership to the generated // In {CompileToModuleObject}, it will transfer ownership to the generated
// {WasmModuleWrapper}. If this method is not called, ownership may be // {WasmModuleWrapper}. If this method is not called, ownership may be
// reclaimed by explicitely releasing the {module_} field. // reclaimed by explicitely releasing the {module_} field.
ModuleCompiler(Isolate* isolate, std::unique_ptr<WasmModule> module, ModuleCompiler(Isolate* isolate, std::unique_ptr<WasmModule> module);
Handle<Code> centry_stub);
// The actual runnable task that performs compilations in the background. // The actual runnable task that performs compilations in the background.
class CompilationTask : public CancelableTask { class CompilationTask : public CancelableTask {
...@@ -49,7 +48,7 @@ class ModuleCompiler { ...@@ -49,7 +48,7 @@ class ModuleCompiler {
~CompilationUnitBuilder() { DCHECK(units_.empty()); } ~CompilationUnitBuilder() { DCHECK(units_.empty()); }
void AddUnit(compiler::ModuleEnv* module_env, const WasmFunction* function, void AddUnit(const ModuleEnv* module_env, const WasmFunction* function,
uint32_t buffer_offset, Vector<const uint8_t> bytes, uint32_t buffer_offset, Vector<const uint8_t> bytes,
WasmName name) { WasmName name) {
units_.emplace_back(new compiler::WasmCompilationUnit( units_.emplace_back(new compiler::WasmCompilationUnit(
...@@ -129,7 +128,9 @@ class ModuleCompiler { ...@@ -129,7 +128,9 @@ class ModuleCompiler {
size_t InitializeCompilationUnits(const std::vector<WasmFunction>& functions, size_t InitializeCompilationUnits(const std::vector<WasmFunction>& functions,
const ModuleWireBytes& wire_bytes, const ModuleWireBytes& wire_bytes,
compiler::ModuleEnv* module_env); const ModuleEnv* module_env);
void ReopenHandlesInDeferredScope();
void RestartCompilationTasks(); void RestartCompilationTasks();
...@@ -142,18 +143,17 @@ class ModuleCompiler { ...@@ -142,18 +143,17 @@ class ModuleCompiler {
int* func_index); int* func_index);
void CompileInParallel(const ModuleWireBytes& wire_bytes, void CompileInParallel(const ModuleWireBytes& wire_bytes,
compiler::ModuleEnv* module_env, const ModuleEnv* module_env,
std::vector<Handle<Code>>& results, std::vector<Handle<Code>>& results,
ErrorThrower* thrower); ErrorThrower* thrower);
void CompileSequentially(const ModuleWireBytes& wire_bytes, void CompileSequentially(const ModuleWireBytes& wire_bytes,
compiler::ModuleEnv* module_env, const ModuleEnv* module_env,
std::vector<Handle<Code>>& results, std::vector<Handle<Code>>& results,
ErrorThrower* thrower); ErrorThrower* thrower);
void ValidateSequentially(const ModuleWireBytes& wire_bytes, void ValidateSequentially(const ModuleWireBytes& wire_bytes,
compiler::ModuleEnv* module_env, const ModuleEnv* module_env, ErrorThrower* thrower);
ErrorThrower* thrower);
MaybeHandle<WasmModuleObject> CompileToModuleObject( MaybeHandle<WasmModuleObject> CompileToModuleObject(
ErrorThrower* thrower, const ModuleWireBytes& wire_bytes, ErrorThrower* thrower, const ModuleWireBytes& wire_bytes,
...@@ -346,7 +346,7 @@ class AsyncCompileJob { ...@@ -346,7 +346,7 @@ class AsyncCompileJob {
Handle<Context> context_; Handle<Context> context_;
Handle<JSPromise> module_promise_; Handle<JSPromise> module_promise_;
std::unique_ptr<ModuleCompiler> compiler_; std::unique_ptr<ModuleCompiler> compiler_;
std::unique_ptr<compiler::ModuleEnv> module_env_; std::unique_ptr<ModuleEnv> module_env_;
std::vector<DeferredHandles*> deferred_handles_; std::vector<DeferredHandles*> deferred_handles_;
Handle<WasmModuleObject> module_object_; Handle<WasmModuleObject> module_object_;
...@@ -365,6 +365,8 @@ class AsyncCompileJob { ...@@ -365,6 +365,8 @@ class AsyncCompileJob {
} }
Counters* counters() const { return async_counters().get(); } Counters* counters() const { return async_counters().get(); }
void ReopenHandlesInDeferredScope();
void AsyncCompileFailed(ErrorThrower& thrower); void AsyncCompileFailed(ErrorThrower& thrower);
void AsyncCompileSucceeded(Handle<Object> result); void AsyncCompileSucceeded(Handle<Object> result);
......
...@@ -12,11 +12,6 @@ ...@@ -12,11 +12,6 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace compiler {
struct ModuleEnv;
}
namespace wasm { namespace wasm {
const uint32_t kWasmMagic = 0x6d736100; const uint32_t kWasmMagic = 0x6d736100;
...@@ -111,7 +106,7 @@ V8_EXPORT_PRIVATE FunctionResult SyncDecodeWasmFunction( ...@@ -111,7 +106,7 @@ V8_EXPORT_PRIVATE FunctionResult SyncDecodeWasmFunction(
const byte* function_end); const byte* function_end);
V8_EXPORT_PRIVATE FunctionResult V8_EXPORT_PRIVATE FunctionResult
AsyncDecodeWasmFunction(Isolate* isolate, Zone* zone, compiler::ModuleEnv* env, AsyncDecodeWasmFunction(Isolate* isolate, Zone* zone, const ModuleEnv* env,
const byte* function_start, const byte* function_end, const byte* function_start, const byte* function_end,
const std::shared_ptr<Counters> async_counters); const std::shared_ptr<Counters> async_counters);
......
...@@ -95,6 +95,7 @@ void CodeSpecialization::RelocateMemoryReferences(Address old_start, ...@@ -95,6 +95,7 @@ void CodeSpecialization::RelocateMemoryReferences(Address old_start,
uint32_t new_size) { uint32_t new_size) {
DCHECK(old_mem_start == nullptr && old_mem_size == 0 && DCHECK(old_mem_start == nullptr && old_mem_size == 0 &&
new_mem_start == nullptr && new_mem_size == 0); new_mem_start == nullptr && new_mem_size == 0);
DCHECK(old_start != new_start || old_size != new_size);
old_mem_start = old_start; old_mem_start = old_start;
old_mem_size = old_size; old_mem_size = old_size;
new_mem_start = new_start; new_mem_start = new_start;
...@@ -103,12 +104,14 @@ void CodeSpecialization::RelocateMemoryReferences(Address old_start, ...@@ -103,12 +104,14 @@ void CodeSpecialization::RelocateMemoryReferences(Address old_start,
void CodeSpecialization::RelocateGlobals(Address old_start, Address new_start) { void CodeSpecialization::RelocateGlobals(Address old_start, Address new_start) {
DCHECK(old_globals_start == 0 && new_globals_start == 0); DCHECK(old_globals_start == 0 && new_globals_start == 0);
DCHECK(old_start != 0 || new_start != 0);
old_globals_start = old_start; old_globals_start = old_start;
new_globals_start = new_start; new_globals_start = new_start;
} }
void CodeSpecialization::PatchTableSize(uint32_t old_size, uint32_t new_size) { void CodeSpecialization::PatchTableSize(uint32_t old_size, uint32_t new_size) {
DCHECK(old_function_table_size == 0 && new_function_table_size == 0); DCHECK(old_function_table_size == 0 && new_function_table_size == 0);
DCHECK(old_size != 0 || new_size != 0);
old_function_table_size = old_size; old_function_table_size = old_size;
new_function_table_size = new_size; new_function_table_size = new_size;
} }
......
...@@ -212,43 +212,48 @@ void RecordLazyCodeStats(Code* code, Counters* counters) { ...@@ -212,43 +212,48 @@ void RecordLazyCodeStats(Code* code, Counters* counters) {
counters->wasm_reloc_size()->Increment(code->relocation_info()->length()); counters->wasm_reloc_size()->Increment(code->relocation_info()->length());
} }
compiler::ModuleEnv CreateModuleEnvFromCompiledModule( ModuleEnv CreateModuleEnvFromRuntimeObject(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
WasmModule* module = compiled_module->module(); // Store a vector of handles to be embedded in the generated code.
// TODO(clemensh): For concurrent compilation, these will have to live in a
std::vector<Handle<FixedArray>> function_tables; // DeferredHandleScope.
std::vector<Handle<FixedArray>> signature_tables; wasm::ModuleEnv module_env(compiled_module->module(),
std::vector<SignatureMap*> signature_maps; BUILTIN_CODE(isolate, WasmCompileLazy));
int num_function_tables = static_cast<int>(module->function_tables.size()); // We set unchecked because the data on the compiled module
for (int i = 0; i < num_function_tables; i++) { // is authoritative.
FixedArray* ft = compiled_module->ptr_to_function_tables(); module_env.SetMemSizeUnchecked(compiled_module->has_embedded_mem_size()
FixedArray* st = compiled_module->ptr_to_signature_tables(); ? compiled_module->embedded_mem_size()
: 0);
// TODO(clemensh): defer these handles for concurrent compilation. module_env.set_mem_start(
function_tables.push_back(handle(FixedArray::cast(ft->get(i)))); reinterpret_cast<byte*>(compiled_module->has_embedded_mem_start()
signature_tables.push_back(handle(FixedArray::cast(st->get(i)))); ? compiled_module->embedded_mem_start()
signature_maps.push_back(&module->function_tables[i].map); : 0));
module_env.set_globals_start(reinterpret_cast<byte*>(
compiled_module->has_globals_start() ? compiled_module->globals_start()
: 0));
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;
std::vector<Handle<Code>> empty_code;
compiler::ModuleEnv result = {
module, // --
function_tables, // --
signature_tables, // --
signature_maps, // --
empty_code, // --
BUILTIN_CODE(isolate, WasmCompileLazy), // --
reinterpret_cast<uintptr_t>( // --
compiled_module->GetEmbeddedMemStartOrNull()), // --
reinterpret_cast<uint32_t>( // --
compiled_module->GetEmbeddedMemSizeOrZero()), // --
reinterpret_cast<uintptr_t>( // --
compiled_module->GetGlobalsStartOrNull()) // --
};
return result;
} }
} // namespace } // namespace
...@@ -799,10 +804,9 @@ MaybeHandle<WasmModuleObject> wasm::SyncCompileTranslatedAsmJs( ...@@ -799,10 +804,9 @@ MaybeHandle<WasmModuleObject> wasm::SyncCompileTranslatedAsmJs(
// Transfer ownership to the {WasmModuleWrapper} generated in // Transfer ownership to the {WasmModuleWrapper} generated in
// {CompileToModuleObject}. // {CompileToModuleObject}.
Handle<Code> centry_stub = CEntryStub(isolate, 1).GetCode(); ModuleCompiler helper(isolate, std::move(result.val));
ModuleCompiler compiler(isolate, std::move(result.val), centry_stub); return helper.CompileToModuleObject(thrower, bytes, asm_js_script,
return compiler.CompileToModuleObject(thrower, bytes, asm_js_script, asm_js_offset_table_bytes);
asm_js_offset_table_bytes);
} }
MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate, MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate,
...@@ -822,10 +826,9 @@ MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate, ...@@ -822,10 +826,9 @@ MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate,
// Transfer ownership to the {WasmModuleWrapper} generated in // Transfer ownership to the {WasmModuleWrapper} generated in
// {CompileToModuleObject}. // {CompileToModuleObject}.
Handle<Code> centry_stub = CEntryStub(isolate, 1).GetCode(); ModuleCompiler helper(isolate, std::move(result.val));
ModuleCompiler compiler(isolate, std::move(result.val), centry_stub); return helper.CompileToModuleObject(thrower, bytes, Handle<Script>(),
return compiler.CompileToModuleObject(thrower, bytes, Handle<Script>(), Vector<const byte>());
Vector<const byte>());
} }
MaybeHandle<WasmInstanceObject> wasm::SyncInstantiate( MaybeHandle<WasmInstanceObject> wasm::SyncInstantiate(
...@@ -998,12 +1001,12 @@ void LazyCompilationOrchestrator::CompileFunction( ...@@ -998,12 +1001,12 @@ void LazyCompilationOrchestrator::CompileFunction(
return; return;
} }
compiler::ModuleEnv module_env = wasm::ModuleEnv module_env =
CreateModuleEnvFromCompiledModule(isolate, compiled_module); CreateModuleEnvFromRuntimeObject(isolate, compiled_module);
const uint8_t* module_start = compiled_module->module_bytes()->GetChars(); const uint8_t* module_start = compiled_module->module_bytes()->GetChars();
const WasmFunction* func = &module_env.module->functions[func_index]; const WasmFunction* func = &module_env.module()->functions[func_index];
wasm::FunctionBody body{func->sig, func->code.offset(), wasm::FunctionBody body{func->sig, func->code.offset(),
module_start + func->code.offset(), module_start + func->code.offset(),
module_start + func->code.end_offset()}; module_start + func->code.end_offset()};
......
...@@ -280,6 +280,142 @@ struct V8_EXPORT_PRIVATE ModuleWireBytes { ...@@ -280,6 +280,142 @@ struct V8_EXPORT_PRIVATE ModuleWireBytes {
const Vector<const byte> module_bytes_; const Vector<const byte> module_bytes_;
}; };
// 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, Handle<Code> default_function_code)
: module_(module),
function_tables_(module->function_tables.size()),
signature_tables_(module->function_tables.size()),
default_function_code_(default_function_code),
mem_size_(module->initial_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 index < module_->globals.size();
}
bool IsValidFunction(uint32_t index) const {
return index < module_->functions.size();
}
bool IsValidSignature(uint32_t index) const {
return index < module_->signatures.size();
}
bool IsValidTable(uint32_t index) const {
return index < module_->function_tables.size();
}
ValueType GetGlobalType(uint32_t index) const {
DCHECK(IsValidGlobal(index));
return module_->globals[index].type;
}
FunctionSig* GetFunctionSignature(uint32_t index) const {
DCHECK(IsValidFunction(index));
// 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) const {
DCHECK(IsValidSignature(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];
}
bool is_asm_js() const { return module_->is_asm_js(); }
bool is_wasm() const { return module_->is_wasm(); }
Handle<Code> GetFunctionCode(uint32_t index) const {
if (index < function_code_.size()) {
return function_code_[index];
}
return default_function_code_;
}
// 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);
}
default_function_code_ = handle(*default_function_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_;
// a user of the compiler may choose to pre-populate this
// with code objects to be used instead of the default
std::vector<Handle<Code>> function_code_;
private:
Handle<Code> default_function_code_;
// 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. // A helper for printing out the names of functions.
struct WasmFunctionName { struct WasmFunctionName {
WasmFunctionName(const WasmFunction* function, WasmName name) WasmFunctionName(const WasmFunction* function, WasmName name)
......
...@@ -796,10 +796,7 @@ void WasmSharedModuleData::PrepareForLazyCompilation( ...@@ -796,10 +796,7 @@ void WasmSharedModuleData::PrepareForLazyCompilation(
Handle<WasmCompiledModule> WasmCompiledModule::New( Handle<WasmCompiledModule> WasmCompiledModule::New(
Isolate* isolate, Handle<WasmSharedModuleData> shared, Isolate* isolate, Handle<WasmSharedModuleData> shared,
Handle<FixedArray> code_table, Handle<FixedArray> code_table, const ModuleEnv& module_env) {
const std::vector<Handle<FixedArray>>& function_tables,
const std::vector<Handle<FixedArray>>& signature_tables) {
DCHECK_EQ(function_tables.size(), signature_tables.size());
Handle<FixedArray> ret = Handle<FixedArray> ret =
isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED); isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED);
// WasmCompiledModule::cast would fail since fields are not set yet. // WasmCompiledModule::cast would fail since fields are not set yet.
...@@ -809,6 +806,25 @@ Handle<WasmCompiledModule> WasmCompiledModule::New( ...@@ -809,6 +806,25 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(
compiled_module->set_shared(shared); compiled_module->set_shared(shared);
compiled_module->set_native_context(isolate->native_context()); compiled_module->set_native_context(isolate->native_context());
compiled_module->set_code_table(code_table); compiled_module->set_code_table(code_table);
size_t function_table_count = shared->module()->function_tables.size();
if (function_table_count > 0) {
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) {
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);
compiled_module->set_function_tables(func_tables);
}
// TODO(mtrofin): we copy these because the order of finalization isn't // TODO(mtrofin): we copy these because the order of finalization isn't
// reliable, and we need these at Reset (which is called at // reliable, and we need these at Reset (which is called at
// finalization). If the order were reliable, and top-down, we could instead // finalization). If the order were reliable, and top-down, we could instead
...@@ -816,22 +832,6 @@ Handle<WasmCompiledModule> WasmCompiledModule::New( ...@@ -816,22 +832,6 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(
compiled_module->set_initial_pages(shared->module()->initial_pages); compiled_module->set_initial_pages(shared->module()->initial_pages);
compiled_module->set_num_imported_functions( compiled_module->set_num_imported_functions(
shared->module()->num_imported_functions); shared->module()->num_imported_functions);
int num_function_tables = static_cast<int>(function_tables.size());
if (num_function_tables > 0) {
Handle<FixedArray> st =
isolate->factory()->NewFixedArray(num_function_tables, TENURED);
Handle<FixedArray> ft =
isolate->factory()->NewFixedArray(num_function_tables, TENURED);
for (int i = 0; i < num_function_tables; ++i) {
st->set(i, *(signature_tables[i]));
ft->set(i, *(function_tables[i]));
}
compiled_module->set_signature_tables(st);
compiled_module->set_empty_function_tables(ft);
compiled_module->set_function_tables(ft);
}
// TODO(mtrofin): copy the rest of the specialization parameters over. // TODO(mtrofin): copy the rest of the specialization parameters over.
// We're currently OK because we're only using defaults. // We're currently OK because we're only using defaults.
return compiled_module; return compiled_module;
...@@ -871,7 +871,7 @@ void WasmCompiledModule::Reset(Isolate* isolate, ...@@ -871,7 +871,7 @@ void WasmCompiledModule::Reset(Isolate* isolate,
Object* undefined = *isolate->factory()->undefined_value(); Object* undefined = *isolate->factory()->undefined_value();
Object* fct_obj = compiled_module->ptr_to_code_table(); Object* fct_obj = compiled_module->ptr_to_code_table();
if (fct_obj != nullptr && fct_obj != undefined) { if (fct_obj != nullptr && fct_obj != undefined) {
uint32_t old_mem_size = compiled_module->GetEmbeddedMemSizeOrZero(); uint32_t old_mem_size = compiled_module->mem_size();
// We use default_mem_size throughout, as the mem size of an uninstantiated // We use default_mem_size throughout, as the mem size of an uninstantiated
// module, because if we can statically prove a memory access is over // module, because if we can statically prove a memory access is over
// bounds, we'll codegen a trap. See {WasmGraphBuilder::BoundsCheckMem} // bounds, we'll codegen a trap. See {WasmGraphBuilder::BoundsCheckMem}
...@@ -1069,6 +1069,11 @@ void WasmCompiledModule::ReinitializeAfterDeserialization( ...@@ -1069,6 +1069,11 @@ void WasmCompiledModule::ReinitializeAfterDeserialization(
DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*shared)); DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*shared));
} }
uint32_t WasmCompiledModule::mem_size() const {
DCHECK(has_embedded_mem_size() == has_embedded_mem_start());
return has_embedded_mem_start() ? embedded_mem_size() : default_mem_size();
}
uint32_t WasmCompiledModule::default_mem_size() const { uint32_t WasmCompiledModule::default_mem_size() const {
return initial_pages() * WasmModule::kPageSize; return initial_pages() * WasmModule::kPageSize;
} }
......
...@@ -386,7 +386,7 @@ class WasmCompiledModule : public FixedArray { ...@@ -386,7 +386,7 @@ class WasmCompiledModule : public FixedArray {
MACRO(OBJECT, FixedArray, weak_exported_functions) \ MACRO(OBJECT, FixedArray, weak_exported_functions) \
MACRO(OBJECT, FixedArray, function_tables) \ MACRO(OBJECT, FixedArray, function_tables) \
MACRO(OBJECT, FixedArray, signature_tables) \ MACRO(OBJECT, FixedArray, signature_tables) \
MACRO(OBJECT, FixedArray, empty_function_tables) \ MACRO(CONST_OBJECT, FixedArray, empty_function_tables) \
MACRO(LARGE_NUMBER, size_t, embedded_mem_start) \ MACRO(LARGE_NUMBER, size_t, embedded_mem_start) \
MACRO(LARGE_NUMBER, size_t, globals_start) \ MACRO(LARGE_NUMBER, size_t, globals_start) \
MACRO(LARGE_NUMBER, uint32_t, embedded_mem_size) \ MACRO(LARGE_NUMBER, uint32_t, embedded_mem_size) \
...@@ -417,31 +417,32 @@ class WasmCompiledModule : public FixedArray { ...@@ -417,31 +417,32 @@ class WasmCompiledModule : public FixedArray {
}; };
public: public:
static Handle<WasmCompiledModule> New( static Handle<WasmCompiledModule> New(Isolate* isolate,
Isolate* isolate, Handle<WasmSharedModuleData> shared, Handle<WasmSharedModuleData> shared,
Handle<FixedArray> code_table, Handle<FixedArray> code_table,
const std::vector<Handle<FixedArray>>& function_tables, const wasm::ModuleEnv& module_env);
const std::vector<Handle<FixedArray>>& signature_tables);
static Handle<WasmCompiledModule> Clone(Isolate* isolate, static Handle<WasmCompiledModule> Clone(Isolate* isolate,
Handle<WasmCompiledModule> module); Handle<WasmCompiledModule> module);
static void Reset(Isolate* isolate, WasmCompiledModule* module); static void Reset(Isolate* isolate, WasmCompiledModule* module);
Address GetEmbeddedMemStartOrNull() const { Address GetEmbeddedMemStartOrNull() const {
return has_embedded_mem_start() DisallowHeapAllocation no_gc;
? reinterpret_cast<Address>(embedded_mem_start()) if (has_embedded_mem_start()) {
: nullptr; return reinterpret_cast<Address>(embedded_mem_start());
}
return nullptr;
} }
Address GetGlobalsStartOrNull() const { Address GetGlobalsStartOrNull() const {
return has_globals_start() ? reinterpret_cast<Address>(globals_start()) DisallowHeapAllocation no_gc;
: nullptr; if (has_globals_start()) {
} return reinterpret_cast<Address>(globals_start());
}
uint32_t GetEmbeddedMemSizeOrZero() const { return nullptr;
return has_embedded_mem_size() ? embedded_mem_size() : 0;
} }
uint32_t mem_size() const;
uint32_t default_mem_size() const; uint32_t default_mem_size() const;
void ResetSpecializationMemInfoIfNeeded(); void ResetSpecializationMemInfoIfNeeded();
......
...@@ -141,7 +141,7 @@ Handle<JSObject> MakeFakeBreakpoint(Isolate* isolate, int position) { ...@@ -141,7 +141,7 @@ Handle<JSObject> MakeFakeBreakpoint(Isolate* isolate, int position) {
void SetBreakpoint(WasmRunnerBase& runner, int function_index, int byte_offset, void SetBreakpoint(WasmRunnerBase& runner, int function_index, int byte_offset,
int expected_set_byte_offset = -1) { int expected_set_byte_offset = -1) {
int func_offset = int func_offset =
runner.module().GetFunctionAt(function_index)->code.offset(); runner.module().module()->functions[function_index].code.offset();
int code_offset = func_offset + byte_offset; int code_offset = func_offset + byte_offset;
if (expected_set_byte_offset == -1) expected_set_byte_offset = byte_offset; if (expected_set_byte_offset == -1) expected_set_byte_offset = byte_offset;
Handle<WasmInstanceObject> instance = runner.module().instance_object(); Handle<WasmInstanceObject> instance = runner.module().instance_object();
......
This diff is collapsed.
...@@ -14,7 +14,6 @@ function instantiate(buffer, ffi) { ...@@ -14,7 +14,6 @@ function instantiate(buffer, ffi) {
} }
(function BasicTest() { (function BasicTest() {
print("BasicTest");
let builder = new WasmModuleBuilder(); let builder = new WasmModuleBuilder();
builder.addMemory(1, 2, false); builder.addMemory(1, 2, false);
builder.addFunction("foo", kSig_i_v) builder.addFunction("foo", kSig_i_v)
...@@ -27,7 +26,6 @@ function instantiate(buffer, ffi) { ...@@ -27,7 +26,6 @@ function instantiate(buffer, ffi) {
})(); })();
(function ImportTest() { (function ImportTest() {
print("ImportTest");
let builder = new WasmModuleBuilder(); let builder = new WasmModuleBuilder();
var index = builder.addImport("", "print", makeSig_v_x(kWasmI32)); var index = builder.addImport("", "print", makeSig_v_x(kWasmI32));
builder.addFunction("foo", kSig_v_v) builder.addFunction("foo", kSig_v_v)
...@@ -41,7 +39,6 @@ function instantiate(buffer, ffi) { ...@@ -41,7 +39,6 @@ function instantiate(buffer, ffi) {
})(); })();
(function LocalsTest() { (function LocalsTest() {
print("LocalsTest");
let builder = new WasmModuleBuilder(); let builder = new WasmModuleBuilder();
builder.addFunction(undefined, kSig_i_i) builder.addFunction(undefined, kSig_i_i)
.addLocals({i32_count: 1}) .addLocals({i32_count: 1})
...@@ -55,7 +52,6 @@ function instantiate(buffer, ffi) { ...@@ -55,7 +52,6 @@ function instantiate(buffer, ffi) {
})(); })();
(function LocalsTest2() { (function LocalsTest2() {
print("LocalsTest2");
// TODO(titzer): i64 only works on 64-bit platforms. // TODO(titzer): i64 only works on 64-bit platforms.
var types = [ var types = [
{locals: {i32_count: 1}, type: kWasmI32}, {locals: {i32_count: 1}, type: kWasmI32},
...@@ -79,7 +75,6 @@ function instantiate(buffer, ffi) { ...@@ -79,7 +75,6 @@ function instantiate(buffer, ffi) {
})(); })();
(function CallTest() { (function CallTest() {
print("CallTest");
let builder = new WasmModuleBuilder(); let builder = new WasmModuleBuilder();
builder.addFunction("add", kSig_i_ii) builder.addFunction("add", kSig_i_ii)
.addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]); .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]);
...@@ -93,7 +88,6 @@ function instantiate(buffer, ffi) { ...@@ -93,7 +88,6 @@ function instantiate(buffer, ffi) {
})(); })();
(function IndirectCallTest() { (function IndirectCallTest() {
print("IndirectCallTest");
let builder = new WasmModuleBuilder(); let builder = new WasmModuleBuilder();
builder.addFunction("add", kSig_i_ii) builder.addFunction("add", kSig_i_ii)
.addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]); .addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]);
...@@ -110,7 +104,6 @@ function instantiate(buffer, ffi) { ...@@ -110,7 +104,6 @@ function instantiate(buffer, ffi) {
})(); })();
(function DataSegmentTest() { (function DataSegmentTest() {
print("DataSegmentTest");
let builder = new WasmModuleBuilder(); let builder = new WasmModuleBuilder();
builder.addMemory(1, 1, false); builder.addMemory(1, 1, false);
builder.addFunction("load", kSig_i_i) builder.addFunction("load", kSig_i_i)
...@@ -125,7 +118,6 @@ function instantiate(buffer, ffi) { ...@@ -125,7 +118,6 @@ function instantiate(buffer, ffi) {
(function BasicTestWithUint8Array() { (function BasicTestWithUint8Array() {
print("BasicTestWithUint8Array");
let builder = new WasmModuleBuilder(); let builder = new WasmModuleBuilder();
builder.addMemory(1, 2, false); builder.addMemory(1, 2, false);
builder.addFunction("foo", kSig_i_v) builder.addFunction("foo", kSig_i_v)
...@@ -152,7 +144,6 @@ function instantiate(buffer, ffi) { ...@@ -152,7 +144,6 @@ function instantiate(buffer, ffi) {
})(); })();
(function ImportTestTwoLevel() { (function ImportTestTwoLevel() {
print("ImportTestTwoLevel");
let builder = new WasmModuleBuilder(); let builder = new WasmModuleBuilder();
var index = builder.addImport("mod", "print", makeSig_v_x(kWasmI32)); var index = builder.addImport("mod", "print", makeSig_v_x(kWasmI32));
builder.addFunction("foo", kSig_v_v) builder.addFunction("foo", kSig_v_v)
......
...@@ -985,11 +985,16 @@ TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) { ...@@ -985,11 +985,16 @@ TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) {
class WasmFunctionVerifyTest : public TestWithIsolateAndZone { class WasmFunctionVerifyTest : public TestWithIsolateAndZone {
public: public:
WasmFunctionVerifyTest() {} WasmFunctionVerifyTest() : env(&module, Handle<Code>::null()) {}
virtual ~WasmFunctionVerifyTest() {} virtual ~WasmFunctionVerifyTest() {}
const ModuleEnv* get_env() const { return &env; }
Vector<const byte> get_bytes() const { return bytes; }
private:
WasmModule module; WasmModule module;
Vector<const byte> bytes; Vector<const byte> bytes;
ModuleEnv env;
DISALLOW_COPY_AND_ASSIGN(WasmFunctionVerifyTest); DISALLOW_COPY_AND_ASSIGN(WasmFunctionVerifyTest);
}; };
...@@ -1008,8 +1013,9 @@ TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) { ...@@ -1008,8 +1013,9 @@ TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
kExprEnd // body kExprEnd // body
}; };
FunctionResult result = SyncDecodeWasmFunction( FunctionResult result =
isolate(), zone(), bytes, &module, data, data + sizeof(data)); SyncDecodeWasmFunction(isolate(), zone(), get_bytes(),
get_env()->module(), data, data + sizeof(data));
EXPECT_OK(result); EXPECT_OK(result);
if (result.val && result.ok()) { 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