Commit 72dd5738 authored by Mircea Trofin's avatar Mircea Trofin Committed by Commit Bot

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

This reverts commit e79d4f06.

Reason for revert: Fixed compile error

Original change's description:
> 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: Michael Achenbach <machenbach@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#47451}

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

Change-Id: Ie0efa6204c41b2cb672586a7ac0a622ca13ce5fe
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/622033
Commit-Queue: Mircea Trofin <mtrofin@chromium.org>
Reviewed-by: 's avatarMircea Trofin <mtrofin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47453}
parent fe4d0686
...@@ -67,13 +67,13 @@ void MergeControlToEnd(JSGraph* jsgraph, Node* node) { ...@@ -67,13 +67,13 @@ void MergeControlToEnd(JSGraph* jsgraph, Node* node) {
} // namespace } // namespace
WasmGraphBuilder::WasmGraphBuilder( WasmGraphBuilder::WasmGraphBuilder(
const wasm::ModuleEnv* module_env, Zone* zone, JSGraph* jsgraph, ModuleEnv* env, Zone* zone, JSGraph* jsgraph, Handle<Code> centry_stub,
Handle<Code> centry_stub, wasm::FunctionSig* sig, wasm::FunctionSig* sig,
compiler::SourcePositionTable* source_position_table) compiler::SourcePositionTable* source_position_table)
: zone_(zone), : zone_(zone),
jsgraph_(jsgraph), jsgraph_(jsgraph),
centry_stub_node_(jsgraph_->HeapConstant(centry_stub)), centry_stub_node_(jsgraph_->HeapConstant(centry_stub)),
module_env_(module_env), env_(env),
signature_tables_(zone), signature_tables_(zone),
function_tables_(zone), function_tables_(zone),
function_table_sizes_(zone), function_table_sizes_(zone),
...@@ -192,10 +192,9 @@ Node* WasmGraphBuilder::Int64Constant(int64_t value) { ...@@ -192,10 +192,9 @@ Node* WasmGraphBuilder::Int64Constant(int64_t value) {
void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position, void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position,
Node** effect, Node** control) { Node** effect, Node** control) {
// TODO(mtrofin): "!module_" happens when we generate a wrapper. // TODO(mtrofin): "!env_" happens when we generate a wrapper.
// We should factor wrappers separately from wasm codegen. // We should factor wrappers separately from wasm codegen.
if (FLAG_wasm_no_stack_checks || !module_env_ || if (FLAG_wasm_no_stack_checks || !env_ || !has_runtime_exception_support_) {
!has_runtime_exception_support_) {
return; return;
} }
if (effect == nullptr) effect = effect_; if (effect == nullptr) effect = effect_;
...@@ -2226,12 +2225,13 @@ Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets, ...@@ -2226,12 +2225,13 @@ Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets,
DCHECK_NULL(args[0]); DCHECK_NULL(args[0]);
// Add code object as constant. // Add code object as constant.
// TODO(wasm): Always use the illegal builtin, except for testing. Handle<Code> code = index < env_->function_code.size()
Handle<Code> code = module_env_->GetFunctionCode(index); ? env_->function_code[index]
: env_->default_function_code;
DCHECK(!code.is_null()); DCHECK(!code.is_null());
args[0] = HeapConstant(code); args[0] = HeapConstant(code);
wasm::FunctionSig* sig = module_env_->GetFunctionSignature(index); wasm::FunctionSig* sig = env_->module->functions[index].sig;
return BuildWasmCall(sig, args, rets, position); return BuildWasmCall(sig, args, rets, position);
} }
...@@ -2240,13 +2240,11 @@ Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args, ...@@ -2240,13 +2240,11 @@ Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args,
Node*** rets, Node*** rets,
wasm::WasmCodePosition position) { wasm::WasmCodePosition position) {
DCHECK_NOT_NULL(args[0]); DCHECK_NOT_NULL(args[0]);
DCHECK_NOT_NULL(module_env_); DCHECK_NOT_NULL(env_);
// Assume only one table for now. // Assume only one table for now.
uint32_t table_index = 0; uint32_t table_index = 0;
wasm::FunctionSig* sig = module_env_->GetSignature(sig_index); wasm::FunctionSig* sig = env_->module->signatures[sig_index];
DCHECK(module_env_->IsValidTable(table_index));
EnsureFunctionTableNodes(); EnsureFunctionTableNodes();
MachineOperatorBuilder* machine = jsgraph()->machine(); MachineOperatorBuilder* machine = jsgraph()->machine();
...@@ -2272,10 +2270,10 @@ Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args, ...@@ -2272,10 +2270,10 @@ Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args,
Int32Constant(kPointerSizeLog2)), Int32Constant(kPointerSizeLog2)),
Int32Constant(fixed_offset)), Int32Constant(fixed_offset)),
*effect_, *control_); *effect_, *control_);
auto& map = module_env_->module()->function_tables[0].map; auto map = env_->signature_maps[table_index];
Node* sig_match = graph()->NewNode( Node* sig_match = graph()->NewNode(
machine->WordEqual(), load_sig, machine->WordEqual(), load_sig,
jsgraph()->SmiConstant(static_cast<int>(map.FindOrInsert(sig)))); jsgraph()->SmiConstant(static_cast<int>(map->FindOrInsert(sig))));
TrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position); TrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position);
} }
...@@ -2953,8 +2951,8 @@ void WasmGraphBuilder::BuildCWasmEntry() { ...@@ -2953,8 +2951,8 @@ void WasmGraphBuilder::BuildCWasmEntry() {
} }
Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
DCHECK_NOT_NULL(module_env_); DCHECK_NOT_NULL(env_);
uintptr_t mem_start = reinterpret_cast<uintptr_t>(module_env_->mem_start()); const uintptr_t mem_start = static_cast<const uintptr_t>(env_->mem_start);
if (offset == 0) { if (offset == 0) {
if (!mem_buffer_) { if (!mem_buffer_) {
mem_buffer_ = jsgraph()->RelocatableIntPtrConstant( mem_buffer_ = jsgraph()->RelocatableIntPtrConstant(
...@@ -2970,7 +2968,7 @@ Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { ...@@ -2970,7 +2968,7 @@ Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
Node* WasmGraphBuilder::CurrentMemoryPages() { Node* WasmGraphBuilder::CurrentMemoryPages() {
// CurrentMemoryPages can not be called from asm.js. // CurrentMemoryPages can not be called from asm.js.
DCHECK_EQ(wasm::kWasmOrigin, module_env_->module()->origin()); DCHECK_EQ(wasm::kWasmOrigin, env_->module->origin());
SetNeedsStackCheck(); SetNeedsStackCheck();
Node* call = BuildCallToRuntime(Runtime::kWasmMemorySize, nullptr, 0); Node* call = BuildCallToRuntime(Runtime::kWasmMemorySize, nullptr, 0);
Node* result = BuildChangeSmiToInt32(call); Node* result = BuildChangeSmiToInt32(call);
...@@ -2978,9 +2976,9 @@ Node* WasmGraphBuilder::CurrentMemoryPages() { ...@@ -2978,9 +2976,9 @@ Node* WasmGraphBuilder::CurrentMemoryPages() {
} }
Node* WasmGraphBuilder::MemSize() { Node* WasmGraphBuilder::MemSize() {
DCHECK_NOT_NULL(module_env_); DCHECK_NOT_NULL(env_);
if (mem_size_) return mem_size_; if (mem_size_) return mem_size_;
uint32_t size = module_env_->mem_size(); uint32_t size = env_->mem_size;
mem_size_ = jsgraph()->RelocatableInt32Constant( mem_size_ = jsgraph()->RelocatableInt32Constant(
size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
return mem_size_; return mem_size_;
...@@ -2988,17 +2986,13 @@ Node* WasmGraphBuilder::MemSize() { ...@@ -2988,17 +2986,13 @@ Node* WasmGraphBuilder::MemSize() {
void WasmGraphBuilder::EnsureFunctionTableNodes() { void WasmGraphBuilder::EnsureFunctionTableNodes() {
if (function_tables_.size() > 0) return; if (function_tables_.size() > 0) return;
size_t tables_size = module_env_->module()->function_tables.size(); size_t tables_size = env_->function_tables.size();
DCHECK_EQ(tables_size, module_env_->function_tables().size());
DCHECK_EQ(tables_size, module_env_->signature_tables().size());
for (size_t i = 0; i < tables_size; ++i) { for (size_t i = 0; i < tables_size; ++i) {
auto function_handle = module_env_->function_tables()[i]; auto function_handle = env_->function_tables[i];
auto signature_handle = module_env_->signature_tables()[i]; auto signature_handle = env_->signature_tables[i];
function_tables_.push_back(HeapConstant(function_handle)); function_tables_.push_back(HeapConstant(function_handle));
signature_tables_.push_back(HeapConstant(signature_handle)); signature_tables_.push_back(HeapConstant(signature_handle));
uint32_t table_size = uint32_t table_size = env_->module->function_tables[i].initial_size;
module_env_->module()->function_tables[i].initial_size;
function_table_sizes_.push_back(jsgraph()->RelocatableInt32Constant( function_table_sizes_.push_back(jsgraph()->RelocatableInt32Constant(
static_cast<uint32_t>(table_size), static_cast<uint32_t>(table_size),
RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE)); RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE));
...@@ -3096,10 +3090,9 @@ Node* WasmGraphBuilder::BuildCallToRuntime(Runtime::FunctionId f, ...@@ -3096,10 +3090,9 @@ Node* WasmGraphBuilder::BuildCallToRuntime(Runtime::FunctionId f,
Node* WasmGraphBuilder::GetGlobal(uint32_t index) { Node* WasmGraphBuilder::GetGlobal(uint32_t index) {
MachineType mem_type = MachineType mem_type =
wasm::WasmOpcodes::MachineTypeFor(module_env_->GetGlobalType(index)); wasm::WasmOpcodes::MachineTypeFor(env_->module->globals[index].type);
byte* globals_start = module_env_->globals_start(); uintptr_t global_addr =
uintptr_t global_addr = reinterpret_cast<uintptr_t>( env_->globals_start + env_->module->globals[index].offset;
globals_start + module_env_->module()->globals[index].offset);
Node* addr = jsgraph()->RelocatableIntPtrConstant( Node* addr = jsgraph()->RelocatableIntPtrConstant(
global_addr, RelocInfo::WASM_GLOBAL_REFERENCE); global_addr, RelocInfo::WASM_GLOBAL_REFERENCE);
const Operator* op = jsgraph()->machine()->Load(mem_type); const Operator* op = jsgraph()->machine()->Load(mem_type);
...@@ -3111,12 +3104,11 @@ Node* WasmGraphBuilder::GetGlobal(uint32_t index) { ...@@ -3111,12 +3104,11 @@ Node* WasmGraphBuilder::GetGlobal(uint32_t index) {
Node* WasmGraphBuilder::SetGlobal(uint32_t index, Node* val) { Node* WasmGraphBuilder::SetGlobal(uint32_t index, Node* val) {
MachineType mem_type = MachineType mem_type =
wasm::WasmOpcodes::MachineTypeFor(module_env_->GetGlobalType(index)); wasm::WasmOpcodes::MachineTypeFor(env_->module->globals[index].type);
byte* globals_start = module_env_->globals_start(); uintptr_t global_addr =
env_->globals_start + env_->module->globals[index].offset;
Node* addr = jsgraph()->RelocatableIntPtrConstant( Node* addr = jsgraph()->RelocatableIntPtrConstant(
reinterpret_cast<uintptr_t>(globals_start + global_addr, RelocInfo::WASM_GLOBAL_REFERENCE);
module_env_->module()->globals[index].offset),
RelocInfo::WASM_GLOBAL_REFERENCE);
const Operator* op = jsgraph()->machine()->Store( const Operator* op = jsgraph()->machine()->Store(
StoreRepresentation(mem_type.representation(), kNoWriteBarrier)); StoreRepresentation(mem_type.representation(), kNoWriteBarrier));
Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), val, Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), val,
...@@ -3129,49 +3121,50 @@ void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index, ...@@ -3129,49 +3121,50 @@ void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index,
uint32_t offset, uint32_t offset,
wasm::WasmCodePosition position) { wasm::WasmCodePosition position) {
if (FLAG_wasm_no_bounds_checks) return; if (FLAG_wasm_no_bounds_checks) return;
uint32_t size = module_env_->mem_size();
byte memsize = wasm::WasmOpcodes::MemSize(memtype);
size_t effective_size;
if (size <= offset || size < (static_cast<uint64_t>(offset) + memsize)) {
// Two checks are needed in the case where the offset is statically
// out of bounds; one check for the offset being in bounds, and the next for
// the offset + index being out of bounds for code to be patched correctly
// on relocation.
// Check for overflows.
if ((std::numeric_limits<uint32_t>::max() - memsize) + 1 < offset) {
// Always trap. Do not use TrapAlways because it does not create a valid
// graph here.
TrapIfEq32(wasm::kTrapMemOutOfBounds, jsgraph()->Int32Constant(0), 0,
position);
return;
}
size_t effective_offset = (offset - 1) + memsize;
Node* cond = graph()->NewNode(jsgraph()->machine()->Uint32LessThan(), uint64_t min_size = static_cast<uint64_t>(env_->module->initial_pages) *
jsgraph()->IntPtrConstant(effective_offset), wasm::WasmModule::kPageSize;
jsgraph()->RelocatableInt32Constant( uint64_t max_size = static_cast<uint64_t>(env_->module->has_maximum_pages
static_cast<uint32_t>(size), ? env_->module->maximum_pages
RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); : wasm::kV8MaxWasmMemoryPages) *
wasm::WasmModule::kPageSize;
byte access_size = wasm::WasmOpcodes::MemSize(memtype);
uint64_t end_offset = static_cast<uint64_t>(offset) + access_size;
if (end_offset > max_size) {
// The access will be out of bounds, even for the largest memory.
TrapIfEq32(wasm::kTrapMemOutOfBounds, jsgraph()->Int32Constant(0), 0,
position);
return;
}
if (end_offset > min_size) {
// The end offset is larger than the smallest memory.
// Dynamically check the end offset against the actual memory size, which
// is not known at compile time.
Node* cond = graph()->NewNode(
jsgraph()->machine()->Uint32LessThanOrEqual(),
jsgraph()->IntPtrConstant(static_cast<uintptr_t>(end_offset)),
jsgraph()->RelocatableInt32Constant(
static_cast<uint32_t>(env_->mem_size),
RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
TrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position); TrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position);
// For offset > effective size, this relies on check above to fail and
// effective size can be negative, relies on wrap around.
effective_size = size - offset - memsize + 1;
} else { } else {
effective_size = size - offset - memsize + 1; // The end offset is within the bounds of the smallest memory, so only
CHECK(effective_size <= kMaxUInt32); // one check is required. Check to see if the index is also a constant.
Uint32Matcher m(index); Uint32Matcher m(index);
if (m.HasValue()) { if (m.HasValue()) {
uint32_t value = m.Value(); uint64_t index_val = m.Value();
if (value < effective_size) { if ((index_val + offset + access_size) <= min_size) {
// The bounds check will always succeed. // The input index is a constant and everything is statically within
// bounds of the smallest possible memory.
return; return;
} }
} }
} }
uint64_t effective_size = env_->mem_size - (end_offset - 1);
Node* cond = graph()->NewNode(jsgraph()->machine()->Uint32LessThan(), index, Node* cond = graph()->NewNode(jsgraph()->machine()->Uint32LessThan(), index,
jsgraph()->RelocatableInt32Constant( jsgraph()->RelocatableInt32Constant(
static_cast<uint32_t>(effective_size), static_cast<uint32_t>(effective_size),
...@@ -3824,11 +3817,18 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module, ...@@ -3824,11 +3817,18 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
Node* control = nullptr; Node* control = nullptr;
Node* effect = nullptr; Node* effect = nullptr;
// TODO(mtrofin): refactor CompileJSToWasmWrapper to not require a module_env. // TODO(titzer): compile JS to WASM wrappers without a {ModuleEnv}.
// It's not really applicable. ModuleEnv env = {module,
wasm::ModuleEnv module_env(module, BUILTIN_CODE(isolate, Illegal)); std::vector<Handle<FixedArray>>(), // function_tables
std::vector<Handle<FixedArray>>(), // signature_tables
WasmGraphBuilder builder(&module_env, &zone, &jsgraph, std::vector<wasm::SignatureMap*>(), // signature_maps
std::vector<Handle<Code>>(), // function_code
BUILTIN_CODE(isolate, Illegal), // default_function_code
0,
0,
0};
WasmGraphBuilder builder(&env, &zone, &jsgraph,
CEntryStub(isolate, 1).GetCode(), func->sig); CEntryStub(isolate, 1).GetCode(), func->sig);
builder.set_control_ptr(&control); builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect); builder.set_effect_ptr(&effect);
...@@ -3844,8 +3844,8 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module, ...@@ -3844,8 +3844,8 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
} }
// Schedule and compile to machine code. // Schedule and compile to machine code.
int params = static_cast<int>( int params =
module_env.GetFunctionSignature(index)->parameter_count()); static_cast<int>(module->functions[index].sig->parameter_count());
CallDescriptor* incoming = Linkage::GetJSCallDescriptor( CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
&zone, false, params + 1, CallDescriptor::kNoFlags); &zone, false, params + 1, CallDescriptor::kNoFlags);
Code::Flags flags = Code::ComputeFlags(Code::JS_TO_WASM_FUNCTION); Code::Flags flags = Code::ComputeFlags(Code::JS_TO_WASM_FUNCTION);
...@@ -4103,6 +4103,15 @@ Handle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) { ...@@ -4103,6 +4103,15 @@ Handle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction( SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
double* decode_ms) { double* decode_ms) {
#if DEBUG
if (env_) {
size_t tables_size = env_->module->function_tables.size();
DCHECK_EQ(tables_size, env_->function_tables.size());
DCHECK_EQ(tables_size, env_->signature_tables.size());
DCHECK_EQ(tables_size, env_->signature_maps.size());
}
#endif
base::ElapsedTimer decode_timer; base::ElapsedTimer decode_timer;
if (FLAG_trace_wasm_decode_time) { if (FLAG_trace_wasm_decode_time) {
decode_timer.Start(); decode_timer.Start();
...@@ -4111,8 +4120,8 @@ SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction( ...@@ -4111,8 +4120,8 @@ SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
SourcePositionTable* source_position_table = SourcePositionTable* source_position_table =
new (jsgraph_->zone()) SourcePositionTable(jsgraph_->graph()); new (jsgraph_->zone()) SourcePositionTable(jsgraph_->graph());
WasmGraphBuilder builder(module_env_, jsgraph_->zone(), jsgraph_, WasmGraphBuilder builder(env_, jsgraph_->zone(), jsgraph_, centry_stub_,
centry_stub_, func_body_.sig, source_position_table); func_body_.sig, source_position_table);
graph_construction_result_ = graph_construction_result_ =
wasm::BuildTFGraph(isolate_->allocator(), &builder, func_body_); wasm::BuildTFGraph(isolate_->allocator(), &builder, func_body_);
...@@ -4133,7 +4142,7 @@ SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction( ...@@ -4133,7 +4142,7 @@ SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
if (func_index_ >= FLAG_trace_wasm_ast_start && if (func_index_ >= FLAG_trace_wasm_ast_start &&
func_index_ < FLAG_trace_wasm_ast_end) { func_index_ < FLAG_trace_wasm_ast_end) {
PrintRawWasmCode(isolate_->allocator(), func_body_, module_env_->module()); PrintRawWasmCode(isolate_->allocator(), func_body_, env_->module);
} }
if (FLAG_trace_wasm_decode_time) { if (FLAG_trace_wasm_decode_time) {
*decode_ms = decode_timer.Elapsed().InMillisecondsF(); *decode_ms = decode_timer.Elapsed().InMillisecondsF();
...@@ -4162,24 +4171,22 @@ Vector<const char> GetDebugName(Zone* zone, wasm::WasmName name, int index) { ...@@ -4162,24 +4171,22 @@ Vector<const char> GetDebugName(Zone* zone, wasm::WasmName name, int index) {
} // namespace } // namespace
WasmCompilationUnit::WasmCompilationUnit( WasmCompilationUnit::WasmCompilationUnit(
Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes, Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env,
const wasm::ModuleEnv* module_env, const wasm::WasmFunction* function, const wasm::WasmFunction* function, Handle<Code> centry_stub)
Handle<Code> centry_stub)
: WasmCompilationUnit( : WasmCompilationUnit(
isolate, module_env, isolate, env,
wasm::FunctionBody{function->sig, function->code.offset(), wasm::FunctionBody{function->sig, function->code.offset(),
wire_bytes.start() + function->code.offset(), wire_bytes.start() + function->code.offset(),
wire_bytes.start() + function->code.end_offset()}, wire_bytes.start() + function->code.end_offset()},
wire_bytes.GetNameOrNull(function), function->func_index, wire_bytes.GetNameOrNull(function), function->func_index,
centry_stub) {} centry_stub) {}
WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate, WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate, ModuleEnv* env,
const wasm::ModuleEnv* module_env,
wasm::FunctionBody body, wasm::FunctionBody body,
wasm::WasmName name, int index, wasm::WasmName name, int index,
Handle<Code> centry_stub) Handle<Code> centry_stub)
: isolate_(isolate), : isolate_(isolate),
module_env_(module_env), env_(env),
func_body_(body), func_body_(body),
func_name_(name), func_name_(name),
counters_(isolate->counters()), counters_(isolate->counters()),
...@@ -4187,11 +4194,11 @@ WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate, ...@@ -4187,11 +4194,11 @@ WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate,
func_index_(index) {} func_index_(index) {}
WasmCompilationUnit::WasmCompilationUnit( WasmCompilationUnit::WasmCompilationUnit(
Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes, Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env,
const wasm::ModuleEnv* module_env, const wasm::WasmFunction* function, 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( : WasmCompilationUnit(
isolate, module_env, isolate, env,
wasm::FunctionBody{function->sig, function->code.offset(), wasm::FunctionBody{function->sig, function->code.offset(),
wire_bytes.start() + function->code.offset(), wire_bytes.start() + function->code.offset(),
wire_bytes.start() + function->code.end_offset()}, wire_bytes.start() + function->code.end_offset()},
...@@ -4199,11 +4206,11 @@ WasmCompilationUnit::WasmCompilationUnit( ...@@ -4199,11 +4206,11 @@ WasmCompilationUnit::WasmCompilationUnit(
async_counters) {} async_counters) {}
WasmCompilationUnit::WasmCompilationUnit( WasmCompilationUnit::WasmCompilationUnit(
Isolate* isolate, const wasm::ModuleEnv* module_env, Isolate* isolate, ModuleEnv* env, wasm::FunctionBody body,
wasm::FunctionBody body, wasm::WasmName name, int index, wasm::WasmName name, int index, Handle<Code> centry_stub,
Handle<Code> centry_stub, const std::shared_ptr<Counters>& async_counters) const std::shared_ptr<Counters>& async_counters)
: isolate_(isolate), : isolate_(isolate),
module_env_(module_env), env_(env),
func_body_(body), func_body_(body),
func_name_(name), func_name_(name),
counters_(async_counters.get()), counters_(async_counters.get()),
...@@ -4211,7 +4218,7 @@ WasmCompilationUnit::WasmCompilationUnit( ...@@ -4211,7 +4218,7 @@ WasmCompilationUnit::WasmCompilationUnit(
func_index_(index) {} func_index_(index) {}
void WasmCompilationUnit::ExecuteCompilation() { void WasmCompilationUnit::ExecuteCompilation() {
auto timed_histogram = module_env_->is_wasm() auto timed_histogram = env_->module->is_wasm()
? counters()->wasm_compile_wasm_function_time() ? counters()->wasm_compile_wasm_function_time()
: counters()->wasm_compile_asm_function_time(); : counters()->wasm_compile_asm_function_time();
TimedHistogramScope wasm_compile_function_time_scope(timed_histogram); TimedHistogramScope wasm_compile_function_time_scope(timed_histogram);
...@@ -4270,7 +4277,7 @@ void WasmCompilationUnit::ExecuteCompilation() { ...@@ -4270,7 +4277,7 @@ void WasmCompilationUnit::ExecuteCompilation() {
job_.reset(Pipeline::NewWasmCompilationJob( job_.reset(Pipeline::NewWasmCompilationJob(
info_.get(), jsgraph_, descriptor, source_positions, info_.get(), jsgraph_, descriptor, source_positions,
&protected_instructions, module_env_->module()->origin())); &protected_instructions, env_->module->origin()));
ok_ = job_->ExecuteJob() == CompilationJob::SUCCEEDED; ok_ = job_->ExecuteJob() == CompilationJob::SUCCEEDED;
// TODO(bradnelson): Improve histogram handling of size_t. // TODO(bradnelson): Improve histogram handling of size_t.
counters()->wasm_compile_function_peak_memory_bytes()->AddSample( counters()->wasm_compile_function_peak_memory_bytes()->AddSample(
...@@ -4341,9 +4348,9 @@ MaybeHandle<Code> WasmCompilationUnit::FinishCompilation( ...@@ -4341,9 +4348,9 @@ MaybeHandle<Code> WasmCompilationUnit::FinishCompilation(
// static // static
MaybeHandle<Code> WasmCompilationUnit::CompileWasmFunction( MaybeHandle<Code> WasmCompilationUnit::CompileWasmFunction(
wasm::ErrorThrower* thrower, Isolate* isolate, wasm::ErrorThrower* thrower, Isolate* isolate,
const wasm::ModuleWireBytes& wire_bytes, const wasm::ModuleEnv* module_env, const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env,
const wasm::WasmFunction* function) { const wasm::WasmFunction* function) {
WasmCompilationUnit unit(isolate, wire_bytes, module_env, function, WasmCompilationUnit unit(isolate, wire_bytes, env, function,
CEntryStub(isolate, 1).GetCode()); CEntryStub(isolate, 1).GetCode());
unit.ExecuteCompilation(); unit.ExecuteCompilation();
return unit.FinishCompilation(thrower); return unit.FinishCompilation(thrower);
......
...@@ -32,33 +32,67 @@ class SourcePositionTable; ...@@ -32,33 +32,67 @@ 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,
const wasm::ModuleEnv* module_env, ModuleEnv* env, const wasm::WasmFunction* function,
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,
const wasm::ModuleEnv* module_env, ModuleEnv* env, const wasm::WasmFunction* function,
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, const wasm::ModuleEnv* module_env, WasmCompilationUnit(Isolate* isolate, ModuleEnv* env, wasm::FunctionBody body,
wasm::FunctionBody body, wasm::WasmName name, int index, wasm::WasmName name, int index, Handle<Code> centry_stub,
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_; }
...@@ -68,8 +102,8 @@ class WasmCompilationUnit final { ...@@ -68,8 +102,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, const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env,
const wasm::ModuleEnv* module_env, const wasm::WasmFunction* function); 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_; }
...@@ -78,7 +112,7 @@ class WasmCompilationUnit final { ...@@ -78,7 +112,7 @@ class WasmCompilationUnit final {
SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms); SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
Isolate* isolate_; Isolate* isolate_;
const wasm::ModuleEnv* module_env_; ModuleEnv* env_;
wasm::FunctionBody func_body_; wasm::FunctionBody func_body_;
wasm::WasmName func_name_; wasm::WasmName func_name_;
Counters* counters_; Counters* counters_;
...@@ -137,8 +171,8 @@ typedef ZoneVector<Node*> NodeVector; ...@@ -137,8 +171,8 @@ typedef ZoneVector<Node*> NodeVector;
class WasmGraphBuilder { class WasmGraphBuilder {
public: public:
WasmGraphBuilder( WasmGraphBuilder(
const wasm::ModuleEnv* module_env, Zone* z, JSGraph* g, ModuleEnv* env, Zone* z, JSGraph* g, Handle<Code> centry_stub_,
Handle<Code> centry_stub_, wasm::FunctionSig* sig, 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) {
...@@ -284,19 +318,19 @@ class WasmGraphBuilder { ...@@ -284,19 +318,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_;
const wasm::ModuleEnv* module_env_ = nullptr; ModuleEnv* 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,11 +619,7 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -619,11 +619,7 @@ 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, : WasmFullDecoder(zone, builder->module(), builder, body) {}
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) {
......
...@@ -83,7 +83,8 @@ size_t ModuleCompiler::CodeGenerationSchedule::GetRandomIndexInSchedule() { ...@@ -83,7 +83,8 @@ size_t ModuleCompiler::CodeGenerationSchedule::GetRandomIndexInSchedule() {
} }
ModuleCompiler::ModuleCompiler(Isolate* isolate, ModuleCompiler::ModuleCompiler(Isolate* isolate,
std::unique_ptr<WasmModule> module) std::unique_ptr<WasmModule> module,
Handle<Code> centry_stub)
: isolate_(isolate), : isolate_(isolate),
module_(std::move(module)), module_(std::move(module)),
async_counters_(isolate->async_counters()), async_counters_(isolate->async_counters()),
...@@ -97,7 +98,7 @@ ModuleCompiler::ModuleCompiler(Isolate* isolate, ...@@ -97,7 +98,7 @@ ModuleCompiler::ModuleCompiler(Isolate* isolate,
Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks), Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())), V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())),
stopped_compilation_tasks_(num_background_tasks_), stopped_compilation_tasks_(num_background_tasks_),
centry_stub_(CEntryStub(isolate, 1).GetCode()) {} centry_stub_(centry_stub) {}
// The actual runnable task that performs compilations in the background. // The actual runnable task that performs compilations in the background.
ModuleCompiler::CompilationTask::CompilationTask(ModuleCompiler* compiler) ModuleCompiler::CompilationTask::CompilationTask(ModuleCompiler* compiler)
...@@ -150,8 +151,8 @@ bool ModuleCompiler::FetchAndExecuteCompilationUnit( ...@@ -150,8 +151,8 @@ bool ModuleCompiler::FetchAndExecuteCompilationUnit(
size_t ModuleCompiler::InitializeCompilationUnits( size_t ModuleCompiler::InitializeCompilationUnits(
const std::vector<WasmFunction>& functions, const std::vector<WasmFunction>& functions,
const ModuleWireBytes& wire_bytes, const ModuleEnv* module_env) { const ModuleWireBytes& wire_bytes, compiler::ModuleEnv* module_env) {
uint32_t start = module_env->module()->num_imported_functions + uint32_t start = module_env->module->num_imported_functions +
FLAG_skip_compiling_wasm_funcs; FLAG_skip_compiling_wasm_funcs;
uint32_t num_funcs = static_cast<uint32_t>(functions.size()); uint32_t num_funcs = static_cast<uint32_t>(functions.size());
uint32_t funcs_to_compile = start > num_funcs ? 0 : num_funcs - start; uint32_t funcs_to_compile = start > num_funcs ? 0 : num_funcs - start;
...@@ -168,10 +169,6 @@ size_t ModuleCompiler::InitializeCompilationUnits( ...@@ -168,10 +169,6 @@ size_t ModuleCompiler::InitializeCompilationUnits(
return funcs_to_compile; return funcs_to_compile;
} }
void ModuleCompiler::ReopenHandlesInDeferredScope() {
centry_stub_ = handle(*centry_stub_, isolate_);
}
void ModuleCompiler::RestartCompilationTasks() { void ModuleCompiler::RestartCompilationTasks() {
base::LockGuard<base::Mutex> guard(&tasks_mutex_); base::LockGuard<base::Mutex> guard(&tasks_mutex_);
for (; stopped_compilation_tasks_ > 0; --stopped_compilation_tasks_) { for (; stopped_compilation_tasks_ > 0; --stopped_compilation_tasks_) {
...@@ -220,10 +217,10 @@ MaybeHandle<Code> ModuleCompiler::FinishCompilationUnit(ErrorThrower* thrower, ...@@ -220,10 +217,10 @@ MaybeHandle<Code> ModuleCompiler::FinishCompilationUnit(ErrorThrower* thrower,
} }
void ModuleCompiler::CompileInParallel(const ModuleWireBytes& wire_bytes, void ModuleCompiler::CompileInParallel(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env, compiler::ModuleEnv* module_env,
std::vector<Handle<Code>>& results, std::vector<Handle<Code>>& results,
ErrorThrower* thrower) { ErrorThrower* thrower) {
const WasmModule* module = module_env->module(); const WasmModule* module = module_env->module;
// Data structures for the parallel compilation. // Data structures for the parallel compilation.
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
...@@ -277,12 +274,12 @@ void ModuleCompiler::CompileInParallel(const ModuleWireBytes& wire_bytes, ...@@ -277,12 +274,12 @@ void ModuleCompiler::CompileInParallel(const ModuleWireBytes& wire_bytes,
} }
void ModuleCompiler::CompileSequentially(const ModuleWireBytes& wire_bytes, void ModuleCompiler::CompileSequentially(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env, compiler::ModuleEnv* module_env,
std::vector<Handle<Code>>& results, std::vector<Handle<Code>>& results,
ErrorThrower* thrower) { ErrorThrower* thrower) {
DCHECK(!thrower->error()); DCHECK(!thrower->error());
const WasmModule* module = module_env->module(); const WasmModule* module = module_env->module;
for (uint32_t i = FLAG_skip_compiling_wasm_funcs; for (uint32_t i = FLAG_skip_compiling_wasm_funcs;
i < module->functions.size(); ++i) { i < module->functions.size(); ++i) {
const WasmFunction& func = module->functions[i]; const WasmFunction& func = module->functions[i];
...@@ -302,11 +299,11 @@ void ModuleCompiler::CompileSequentially(const ModuleWireBytes& wire_bytes, ...@@ -302,11 +299,11 @@ void ModuleCompiler::CompileSequentially(const ModuleWireBytes& wire_bytes,
} }
void ModuleCompiler::ValidateSequentially(const ModuleWireBytes& wire_bytes, void ModuleCompiler::ValidateSequentially(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env, compiler::ModuleEnv* module_env,
ErrorThrower* thrower) { ErrorThrower* thrower) {
DCHECK(!thrower->error()); DCHECK(!thrower->error());
const WasmModule* module = module_env->module(); const WasmModule* module = module_env->module;
for (uint32_t i = 0; i < module->functions.size(); ++i) { for (uint32_t i = 0; i < module->functions.size(); ++i) {
const WasmFunction& func = module->functions[i]; const WasmFunction& func = module->functions[i];
if (func.imported) continue; if (func.imported) continue;
...@@ -365,7 +362,8 @@ void RecordStats(Code* code, Counters* counters) { ...@@ -365,7 +362,8 @@ void RecordStats(Code* code, Counters* counters) {
void RecordStats(Handle<FixedArray> functions, Counters* counters) { void RecordStats(Handle<FixedArray> functions, Counters* counters) {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
for (int i = 0; i < functions->length(); ++i) { for (int i = 0; i < functions->length(); ++i) {
RecordStats(Code::cast(functions->get(i)), counters); Object* val = functions->get(i);
if (val->IsCode()) RecordStats(Code::cast(val), counters);
} }
} }
Handle<Script> CreateWasmScript(Isolate* isolate, Handle<Script> CreateWasmScript(Isolate* isolate,
...@@ -520,14 +518,48 @@ double MonotonicallyIncreasingTimeInMs() { ...@@ -520,14 +518,48 @@ double MonotonicallyIncreasingTimeInMs() {
base::Time::kMillisecondsPerSecond; base::Time::kMillisecondsPerSecond;
} }
void SetFunctionTablesToDefault(Factory* factory, wasm::ModuleEnv* module_env) { std::unique_ptr<compiler::ModuleEnv> CreateDefaultModuleEnv(
for (uint32_t i = 0, Factory* factory, WasmModule* module, Handle<Code> illegal_builtin) {
e = static_cast<uint32_t>(module_env->function_tables().size()); std::vector<Handle<FixedArray>> function_tables;
i < e; ++i) { std::vector<Handle<FixedArray>> signature_tables;
DCHECK(module_env->function_tables()[i].is_null()); std::vector<SignatureMap*> signature_maps;
DCHECK(module_env->signature_tables()[i].is_null());
module_env->SetFunctionTable(i, factory->NewFixedArray(1, TENURED), for (size_t i = 0; i < module->function_tables.size(); i++) {
factory->NewFixedArray(1, TENURED)); auto& function_table = module->function_tables[i];
function_tables.push_back(factory->NewFixedArray(1, TENURED));
signature_tables.push_back(factory->NewFixedArray(1, TENURED));
signature_maps.push_back(&function_table.map);
}
std::vector<Handle<Code>> empty_code;
compiler::ModuleEnv result = {
module, // --
function_tables, // --
signature_tables, // --
signature_maps, // --
empty_code, // --
illegal_builtin, // --
0, // --
0, // --
0 // --
};
return std::unique_ptr<compiler::ModuleEnv>(new compiler::ModuleEnv(result));
}
Handle<WasmCompiledModule> NewCompiledModule(
Isolate* isolate, Handle<WasmSharedModuleData> shared,
Handle<FixedArray> code_table, compiler::ModuleEnv* env) {
Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New(
isolate, shared, code_table, env->function_tables, env->signature_tables);
return compiled_module;
}
template <typename T>
void ReopenHandles(Isolate* isolate, const std::vector<Handle<T>>& vec) {
auto& mut = const_cast<std::vector<Handle<T>>&>(vec);
for (size_t i = 0; i < mut.size(); i++) {
mut[i] = Handle<T>(*mut[i], isolate);
} }
} }
...@@ -547,9 +579,7 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal( ...@@ -547,9 +579,7 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal(
? BUILTIN_CODE(isolate_, WasmCompileLazy) ? BUILTIN_CODE(isolate_, WasmCompileLazy)
: BUILTIN_CODE(isolate_, Illegal); : BUILTIN_CODE(isolate_, Illegal);
ModuleEnv env(module_.get(), init_builtin); auto env = CreateDefaultModuleEnv(factory, module_.get(), init_builtin);
SetFunctionTablesToDefault(factory, &env);
// The {code_table} array contains import wrappers and functions (which // The {code_table} array contains import wrappers and functions (which
// are both included in {functions.size()}, and export wrappers). // are both included in {functions.size()}, and export wrappers).
...@@ -570,12 +600,12 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal( ...@@ -570,12 +600,12 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal(
funcs_to_compile > 1 && funcs_to_compile > 1 &&
V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads() > 0; V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads() > 0;
// Avoid a race condition by collecting results into a second vector. // Avoid a race condition by collecting results into a second vector.
std::vector<Handle<Code>> results(env.module()->functions.size()); std::vector<Handle<Code>> results(env->module->functions.size());
if (compile_parallel) { if (compile_parallel) {
CompileInParallel(wire_bytes, &env, results, thrower); CompileInParallel(wire_bytes, env.get(), results, thrower);
} else { } else {
CompileSequentially(wire_bytes, &env, results, thrower); CompileSequentially(wire_bytes, env.get(), results, thrower);
} }
if (thrower->error()) return {}; if (thrower->error()) return {};
...@@ -594,7 +624,7 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal( ...@@ -594,7 +624,7 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal(
// TODO(clemensh): According to the spec, we can actually skip validation // TODO(clemensh): According to the spec, we can actually skip validation
// at module creation time, and return a function that always traps at // at module creation time, and return a function that always traps at
// (lazy) compilation time. // (lazy) compilation time.
ValidateSequentially(wire_bytes, &env, thrower); ValidateSequentially(wire_bytes, env.get(), thrower);
} }
if (thrower->error()) return {}; if (thrower->error()) return {};
...@@ -636,12 +666,12 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal( ...@@ -636,12 +666,12 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal(
script, asm_js_offset_table); script, asm_js_offset_table);
if (lazy_compile) WasmSharedModuleData::PrepareForLazyCompilation(shared); if (lazy_compile) WasmSharedModuleData::PrepareForLazyCompilation(shared);
// Create the compiled module object, and populate with compiled functions // Create the compiled module object and populate with compiled functions
// and information needed at instantiation time. This object needs to be // and information needed at instantiation time. This object needs to be
// serializable. Instantiation may occur off a deserialized version of this // serializable. Instantiation may occur off a deserialized version of this
// object. // object.
Handle<WasmCompiledModule> compiled_module = Handle<WasmCompiledModule> compiled_module =
WasmCompiledModule::New(isolate_, shared, code_table, env); NewCompiledModule(isolate_, shared, code_table, env.get());
// If we created a wasm script, finish it now and make it public to the // If we created a wasm script, finish it now and make it public to the
// debugger. // debugger.
...@@ -937,7 +967,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() { ...@@ -937,7 +967,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
CHECK(memory->byte_length()->ToUint32(&mem_size)); CHECK(memory->byte_length()->ToUint32(&mem_size));
LoadDataSegments(mem_start, mem_size); LoadDataSegments(mem_start, mem_size);
uint32_t old_mem_size = compiled_module_->mem_size(); uint32_t old_mem_size = compiled_module_->GetEmbeddedMemSizeOrZero();
Address old_mem_start = compiled_module_->GetEmbeddedMemStartOrNull(); Address old_mem_start = compiled_module_->GetEmbeddedMemStartOrNull();
// We might get instantiated again with the same memory. No patching // We might get instantiated again with the same memory. No patching
// needed in this case. // needed in this case.
...@@ -1877,14 +1907,6 @@ AsyncCompileJob::~AsyncCompileJob() { ...@@ -1877,14 +1907,6 @@ AsyncCompileJob::~AsyncCompileJob() {
for (auto d : deferred_handles_) delete d; for (auto d : deferred_handles_) delete d;
} }
void AsyncCompileJob::ReopenHandlesInDeferredScope() {
DeferredHandleScope deferred(isolate_);
code_table_ = handle(*code_table_, isolate_);
module_env_->ReopenHandles(isolate_);
compiler_->ReopenHandlesInDeferredScope();
deferred_handles_.push_back(deferred.Detach());
}
void AsyncCompileJob::AsyncCompileFailed(ErrorThrower& thrower) { void AsyncCompileJob::AsyncCompileFailed(ErrorThrower& thrower) {
RejectPromise(isolate_, context_, thrower, module_promise_); RejectPromise(isolate_, context_, thrower, module_promise_);
isolate_->wasm_compilation_manager()->RemoveJob(this); isolate_->wasm_compilation_manager()->RemoveJob(this);
...@@ -2031,40 +2053,50 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep { ...@@ -2031,40 +2053,50 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
std::unique_ptr<WasmModule> module_; std::unique_ptr<WasmModule> module_;
void RunInForeground() override { void RunInForeground() override {
TRACE_COMPILE("(2) Prepare and start compile...\n"); TRACE_COMPILE("(2) Prepare and start compile...\n");
HandleScope scope(job_->isolate_); Isolate* isolate = job_->isolate_;
HandleScope scope(isolate);
Factory* factory = job_->isolate_->factory(); Factory* factory = isolate->factory();
// Initialize {code_table_} with the illegal builtin. All call sites Handle<Code> illegal_builtin = BUILTIN_CODE(isolate, Illegal);
// will be patched at instantiation. job_->module_env_ =
// TODO(wasm): Fix this for lazy compilation. CreateDefaultModuleEnv(factory, module_.get(), illegal_builtin);
Handle<Code> illegal_builtin = BUILTIN_CODE(job_->isolate_, Illegal);
job_->module_env_.reset(new ModuleEnv(module_.get(), illegal_builtin));
ModuleEnv* module_env = job_->module_env_.get();
SetFunctionTablesToDefault(factory, module_env);
// The {code_table} array contains import wrappers and functions (which // The {code_table} array contains import wrappers and functions (which
// are both included in {functions.size()}, and export wrappers. // are both included in {functions.size()}, and export wrappers.
// The results of compilation will be written into it. // The results of compilation will be written into it.
// Initialize {code_table_} with the illegal builtin. All call sites
// will be patched at instantiation.
int code_table_size = static_cast<int>(module_->functions.size() + int code_table_size = static_cast<int>(module_->functions.size() +
module_->num_exported_functions); module_->num_exported_functions);
job_->code_table_ = factory->NewFixedArray(code_table_size, TENURED); job_->code_table_ = factory->NewFixedArray(code_table_size, TENURED);
// TODO(wasm): Fix this for lazy compilation.
for (int i = 0; i < code_table_size; ++i) {
job_->code_table_->set(static_cast<int>(i), *illegal_builtin);
}
// Transfer ownership of the {WasmModule} to the {ModuleCompiler}, but // Transfer ownership of the {WasmModule} to the {ModuleCompiler}, but
// keep a pointer. // keep a pointer.
WasmModule* module = module_.get(); WasmModule* module = module_.get();
Handle<Code> centry_stub = CEntryStub(isolate, 1).GetCode();
{
// Now reopen the handles in a deferred scope in order to use
// them in the concurrent steps.
DeferredHandleScope deferred(isolate);
centry_stub = Handle<Code>(*centry_stub, isolate);
job_->code_table_ = Handle<FixedArray>(*job_->code_table_, isolate);
compiler::ModuleEnv* env = job_->module_env_.get();
ReopenHandles(isolate, env->function_tables);
ReopenHandles(isolate, env->signature_tables);
ReopenHandles(isolate, env->function_code);
Handle<Code>* mut =
const_cast<Handle<Code>*>(&env->default_function_code);
*mut = Handle<Code>(**mut, isolate);
job_->deferred_handles_.push_back(deferred.Detach());
}
job_->compiler_.reset( job_->compiler_.reset(
new ModuleCompiler(job_->isolate_, std::move(module_))); new ModuleCompiler(isolate, std::move(module_), centry_stub));
job_->compiler_->EnableThrottling(); job_->compiler_->EnableThrottling();
// Reopen all handles which should survive in the DeferredHandleScope.
job_->ReopenHandlesInDeferredScope();
DCHECK_LE(module->num_imported_functions, module->functions.size()); DCHECK_LE(module->num_imported_functions, module->functions.size());
size_t num_functions = size_t num_functions =
module->functions.size() - module->num_imported_functions; module->functions.size() - module->num_imported_functions;
...@@ -2203,8 +2235,8 @@ class AsyncCompileJob::FinishCompile : public CompileStep { ...@@ -2203,8 +2235,8 @@ class AsyncCompileJob::FinishCompile : public CompileStep {
for (int i = FLAG_skip_compiling_wasm_funcs, for (int i = FLAG_skip_compiling_wasm_funcs,
e = job_->code_table_->length(); e = job_->code_table_->length();
i < e; ++i) { i < e; ++i) {
Code* code = Code::cast(job_->code_table_->get(i)); Object* val = job_->code_table_->get(i);
RecordStats(code, job_->counters()); if (val->IsCode()) RecordStats(Code::cast(val), job_->counters());
} }
// Create heap objects for script and module bytes to be stored in the // Create heap objects for script and module bytes to be stored in the
...@@ -2243,9 +2275,8 @@ class AsyncCompileJob::FinishCompile : public CompileStep { ...@@ -2243,9 +2275,8 @@ class AsyncCompileJob::FinishCompile : public CompileStep {
// and information needed at instantiation time. This object needs to be // and information needed at instantiation time. This object needs to be
// serializable. Instantiation may occur off a deserialized version of // serializable. Instantiation may occur off a deserialized version of
// this object. // this object.
job_->compiled_module_ = WasmCompiledModule::New( job_->compiled_module_ = NewCompiledModule(
job_->isolate_, shared, job_->code_table_, *job_->module_env_); job_->isolate_, shared, job_->code_table_, job_->module_env_.get());
// Finish the wasm script now and make it public to the debugger. // Finish the wasm script now and make it public to the debugger.
script->set_wasm_compiled_module(*job_->compiled_module_); script->set_wasm_compiled_module(*job_->compiled_module_);
job_->isolate_->debug()->OnAfterCompile(script); job_->isolate_->debug()->OnAfterCompile(script);
......
...@@ -27,7 +27,8 @@ class ModuleCompiler { ...@@ -27,7 +27,8 @@ 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 {
...@@ -48,7 +49,7 @@ class ModuleCompiler { ...@@ -48,7 +49,7 @@ class ModuleCompiler {
~CompilationUnitBuilder() { DCHECK(units_.empty()); } ~CompilationUnitBuilder() { DCHECK(units_.empty()); }
void AddUnit(const ModuleEnv* module_env, const WasmFunction* function, void AddUnit(compiler::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(
...@@ -128,9 +129,7 @@ class ModuleCompiler { ...@@ -128,9 +129,7 @@ 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,
const ModuleEnv* module_env); compiler::ModuleEnv* module_env);
void ReopenHandlesInDeferredScope();
void RestartCompilationTasks(); void RestartCompilationTasks();
...@@ -143,17 +142,18 @@ class ModuleCompiler { ...@@ -143,17 +142,18 @@ class ModuleCompiler {
int* func_index); int* func_index);
void CompileInParallel(const ModuleWireBytes& wire_bytes, void CompileInParallel(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env, compiler::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,
const ModuleEnv* module_env, compiler::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,
const ModuleEnv* module_env, ErrorThrower* thrower); compiler::ModuleEnv* module_env,
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<ModuleEnv> module_env_; std::unique_ptr<compiler::ModuleEnv> module_env_;
std::vector<DeferredHandles*> deferred_handles_; std::vector<DeferredHandles*> deferred_handles_;
Handle<WasmModuleObject> module_object_; Handle<WasmModuleObject> module_object_;
...@@ -365,8 +365,6 @@ class AsyncCompileJob { ...@@ -365,8 +365,6 @@ 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,6 +12,11 @@ ...@@ -12,6 +12,11 @@
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;
...@@ -106,7 +111,7 @@ V8_EXPORT_PRIVATE FunctionResult SyncDecodeWasmFunction( ...@@ -106,7 +111,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, const ModuleEnv* env, AsyncDecodeWasmFunction(Isolate* isolate, Zone* zone, compiler::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,7 +95,6 @@ void CodeSpecialization::RelocateMemoryReferences(Address old_start, ...@@ -95,7 +95,6 @@ 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;
...@@ -104,14 +103,12 @@ void CodeSpecialization::RelocateMemoryReferences(Address old_start, ...@@ -104,14 +103,12 @@ 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,48 +212,42 @@ void RecordLazyCodeStats(Code* code, Counters* counters) { ...@@ -212,48 +212,42 @@ void RecordLazyCodeStats(Code* code, Counters* counters) {
counters->wasm_reloc_size()->Increment(code->relocation_info()->length()); counters->wasm_reloc_size()->Increment(code->relocation_info()->length());
} }
ModuleEnv CreateModuleEnvFromRuntimeObject( compiler::ModuleEnv CreateModuleEnvFromCompiledModule(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
// Store a vector of handles to be embedded in the generated code. WasmModule* module = compiled_module->module();
// TODO(clemensh): For concurrent compilation, these will have to live in a
// DeferredHandleScope. std::vector<Handle<FixedArray>> function_tables;
wasm::ModuleEnv module_env(compiled_module->module(), std::vector<Handle<FixedArray>> signature_tables;
BUILTIN_CODE(isolate, WasmCompileLazy)); std::vector<SignatureMap*> signature_maps;
// We set unchecked because the data on the compiled module int num_function_tables = static_cast<int>(module->function_tables.size());
// is authoritative. for (int i = 0; i < num_function_tables; i++) {
module_env.SetMemSizeUnchecked(compiled_module->has_embedded_mem_size() FixedArray* ft = compiled_module->ptr_to_function_tables();
? compiled_module->embedded_mem_size() FixedArray* st = compiled_module->ptr_to_signature_tables();
: 0);
module_env.set_mem_start( // TODO(clemensh): defer these handles for concurrent compilation.
reinterpret_cast<byte*>(compiled_module->has_embedded_mem_start() function_tables.push_back(handle(FixedArray::cast(ft->get(i))));
? compiled_module->embedded_mem_start() signature_tables.push_back(handle(FixedArray::cast(st->get(i))));
: 0)); signature_maps.push_back(&module->function_tables[i].map);
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()), // --
compiled_module->GetEmbeddedMemSizeOrZero(), // --
reinterpret_cast<uintptr_t>( // --
compiled_module->GetGlobalsStartOrNull()) // --
};
return result;
} }
} // namespace } // namespace
...@@ -804,9 +798,10 @@ MaybeHandle<WasmModuleObject> wasm::SyncCompileTranslatedAsmJs( ...@@ -804,9 +798,10 @@ MaybeHandle<WasmModuleObject> wasm::SyncCompileTranslatedAsmJs(
// Transfer ownership to the {WasmModuleWrapper} generated in // Transfer ownership to the {WasmModuleWrapper} generated in
// {CompileToModuleObject}. // {CompileToModuleObject}.
ModuleCompiler helper(isolate, std::move(result.val)); Handle<Code> centry_stub = CEntryStub(isolate, 1).GetCode();
return helper.CompileToModuleObject(thrower, bytes, asm_js_script, ModuleCompiler compiler(isolate, std::move(result.val), centry_stub);
asm_js_offset_table_bytes); return compiler.CompileToModuleObject(thrower, bytes, asm_js_script,
asm_js_offset_table_bytes);
} }
MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate, MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate,
...@@ -826,9 +821,10 @@ MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate, ...@@ -826,9 +821,10 @@ MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate,
// Transfer ownership to the {WasmModuleWrapper} generated in // Transfer ownership to the {WasmModuleWrapper} generated in
// {CompileToModuleObject}. // {CompileToModuleObject}.
ModuleCompiler helper(isolate, std::move(result.val)); Handle<Code> centry_stub = CEntryStub(isolate, 1).GetCode();
return helper.CompileToModuleObject(thrower, bytes, Handle<Script>(), ModuleCompiler compiler(isolate, std::move(result.val), centry_stub);
Vector<const byte>()); return compiler.CompileToModuleObject(thrower, bytes, Handle<Script>(),
Vector<const byte>());
} }
MaybeHandle<WasmInstanceObject> wasm::SyncInstantiate( MaybeHandle<WasmInstanceObject> wasm::SyncInstantiate(
...@@ -1001,12 +997,12 @@ void LazyCompilationOrchestrator::CompileFunction( ...@@ -1001,12 +997,12 @@ void LazyCompilationOrchestrator::CompileFunction(
return; return;
} }
wasm::ModuleEnv module_env = compiler::ModuleEnv module_env =
CreateModuleEnvFromRuntimeObject(isolate, compiled_module); CreateModuleEnvFromCompiledModule(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,142 +280,6 @@ struct V8_EXPORT_PRIVATE ModuleWireBytes { ...@@ -280,142 +280,6 @@ 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,7 +796,10 @@ void WasmSharedModuleData::PrepareForLazyCompilation( ...@@ -796,7 +796,10 @@ 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, const ModuleEnv& module_env) { Handle<FixedArray> code_table,
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.
...@@ -806,25 +809,6 @@ Handle<WasmCompiledModule> WasmCompiledModule::New( ...@@ -806,25 +809,6 @@ 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
...@@ -832,6 +816,22 @@ Handle<WasmCompiledModule> WasmCompiledModule::New( ...@@ -832,6 +816,22 @@ 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->mem_size(); uint32_t old_mem_size = compiled_module->GetEmbeddedMemSizeOrZero();
// 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,11 +1069,6 @@ void WasmCompiledModule::ReinitializeAfterDeserialization( ...@@ -1069,11 +1069,6 @@ 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(CONST_OBJECT, FixedArray, empty_function_tables) \ MACRO(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,32 +417,31 @@ class WasmCompiledModule : public FixedArray { ...@@ -417,32 +417,31 @@ class WasmCompiledModule : public FixedArray {
}; };
public: public:
static Handle<WasmCompiledModule> New(Isolate* isolate, static Handle<WasmCompiledModule> New(
Handle<WasmSharedModuleData> shared, Isolate* isolate, Handle<WasmSharedModuleData> shared,
Handle<FixedArray> code_table, Handle<FixedArray> code_table,
const wasm::ModuleEnv& module_env); const std::vector<Handle<FixedArray>>& function_tables,
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 {
DisallowHeapAllocation no_gc; return has_embedded_mem_start()
if (has_embedded_mem_start()) { ? reinterpret_cast<Address>(embedded_mem_start())
return reinterpret_cast<Address>(embedded_mem_start()); : nullptr;
}
return nullptr;
} }
Address GetGlobalsStartOrNull() const { Address GetGlobalsStartOrNull() const {
DisallowHeapAllocation no_gc; return has_globals_start() ? reinterpret_cast<Address>(globals_start())
if (has_globals_start()) { : nullptr;
return reinterpret_cast<Address>(globals_start()); }
}
return nullptr; uint32_t GetEmbeddedMemSizeOrZero() const {
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().module()->functions[function_index].code.offset(); runner.module().GetFunctionAt(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();
......
...@@ -73,17 +73,18 @@ const uint32_t kMaxGlobalsSize = 128; ...@@ -73,17 +73,18 @@ const uint32_t kMaxGlobalsSize = 128;
// progressively added by a test. In turn, we piecemeal update the runtime // progressively added by a test. In turn, we piecemeal update the runtime
// objects, i.e. {WasmInstanceObject}, {WasmCompiledModule} and, if necessary, // objects, i.e. {WasmInstanceObject}, {WasmCompiledModule} and, if necessary,
// the interpreter. // the interpreter.
class TestingModule : public ModuleEnv { class TestingModule {
public: public:
explicit TestingModule(Zone* zone, WasmExecutionMode mode = kExecuteCompiled) explicit TestingModule(Zone* zone, WasmExecutionMode mode = kExecuteCompiled)
: isolate_(CcTest::InitIsolateOnce()), : test_module_ptr_(&test_module_),
isolate_(CcTest::InitIsolateOnce()),
global_offset(0), global_offset(0),
mem_start_(nullptr),
mem_size_(0),
interpreter_(nullptr) { interpreter_(nullptr) {
module_ = &test_module_;
WasmJs::Install(isolate_); WasmJs::Install(isolate_);
set_globals_start(global_data);
test_module_.globals_size = kMaxGlobalsSize; test_module_.globals_size = kMaxGlobalsSize;
memset(global_data, 0, sizeof(global_data)); memset(globals_data_, 0, sizeof(globals_data_));
instance_object_ = InitInstanceObject(); instance_object_ = InitInstanceObject();
if (mode == kExecuteInterpreted) { if (mode == kExecuteInterpreted) {
interpreter_ = WasmDebugInfo::SetupForTesting(instance_object_); interpreter_ = WasmDebugInfo::SetupForTesting(instance_object_);
...@@ -94,8 +95,8 @@ class TestingModule : public ModuleEnv { ...@@ -94,8 +95,8 @@ class TestingModule : public ModuleEnv {
byte* AddMemory(uint32_t size) { byte* AddMemory(uint32_t size) {
CHECK(!test_module_.has_memory); CHECK(!test_module_.has_memory);
CHECK_NULL(mem_start()); CHECK_NULL(mem_start_);
CHECK_EQ(0, mem_size()); CHECK_EQ(0, mem_size_);
DCHECK(!instance_object_->has_memory_buffer()); DCHECK(!instance_object_->has_memory_buffer());
test_module_.has_memory = true; test_module_.has_memory = true;
bool enable_guard_regions = EnableGuardRegions() && test_module_.is_wasm(); bool enable_guard_regions = EnableGuardRegions() && test_module_.is_wasm();
...@@ -105,10 +106,10 @@ class TestingModule : public ModuleEnv { ...@@ -105,10 +106,10 @@ class TestingModule : public ModuleEnv {
wasm::NewArrayBuffer(isolate_, alloc_size, enable_guard_regions); wasm::NewArrayBuffer(isolate_, alloc_size, enable_guard_regions);
CHECK(!new_buffer.is_null()); CHECK(!new_buffer.is_null());
instance_object_->set_memory_buffer(*new_buffer); instance_object_->set_memory_buffer(*new_buffer);
set_mem_start(reinterpret_cast<byte*>(new_buffer->backing_store())); mem_start_ = reinterpret_cast<byte*>(new_buffer->backing_store());
CHECK(size == 0 || mem_start()); mem_size_ = size;
memset(mem_start(), 0, size); CHECK(size == 0 || mem_start_);
SetMemSizeUnchecked(size); memset(mem_start_, 0, size);
Handle<WasmCompiledModule> compiled_module = Handle<WasmCompiledModule> compiled_module =
handle(instance_object_->compiled_module()); handle(instance_object_->compiled_module());
Factory* factory = CcTest::i_isolate()->factory(); Factory* factory = CcTest::i_isolate()->factory();
...@@ -116,14 +117,14 @@ class TestingModule : public ModuleEnv { ...@@ -116,14 +117,14 @@ class TestingModule : public ModuleEnv {
// if we happened to have one, but this is a reasonable inefficiencly, // if we happened to have one, but this is a reasonable inefficiencly,
// given this is test. // given this is test.
WasmCompiledModule::recreate_embedded_mem_size(compiled_module, factory, WasmCompiledModule::recreate_embedded_mem_size(compiled_module, factory,
mem_size()); mem_size_);
WasmCompiledModule::recreate_embedded_mem_start( WasmCompiledModule::recreate_embedded_mem_start(
compiled_module, factory, reinterpret_cast<size_t>(mem_start())); compiled_module, factory, reinterpret_cast<size_t>(mem_start_));
if (interpreter_) { if (interpreter_) {
interpreter_->UpdateMemory(mem_start(), mem_size()); interpreter_->UpdateMemory(mem_start_, mem_size_);
} }
return mem_start(); return mem_start_;
} }
size_t CodeTableLength() const { return function_code_.size(); } size_t CodeTableLength() const { return function_code_.size(); }
...@@ -138,37 +139,37 @@ class TestingModule : public ModuleEnv { ...@@ -138,37 +139,37 @@ class TestingModule : public ModuleEnv {
T* AddGlobal( T* AddGlobal(
ValueType type = WasmOpcodes::ValueTypeFor(MachineTypeForC<T>())) { ValueType type = WasmOpcodes::ValueTypeFor(MachineTypeForC<T>())) {
const WasmGlobal* global = AddGlobal(type); const WasmGlobal* global = AddGlobal(type);
return reinterpret_cast<T*>(globals_start() + global->offset); return reinterpret_cast<T*>(globals_data_ + global->offset);
} }
byte AddSignature(FunctionSig* sig) { byte AddSignature(FunctionSig* sig) {
test_module_.signatures.push_back(sig); test_module_.signatures.push_back(sig);
size_t size = module()->signatures.size(); size_t size = test_module_.signatures.size();
CHECK(size < 127); CHECK(size < 127);
return static_cast<byte>(size - 1); return static_cast<byte>(size - 1);
} }
template <typename T> template <typename T>
T* raw_mem_start() { T* raw_mem_start() {
DCHECK(mem_start()); DCHECK(mem_start_);
return reinterpret_cast<T*>(mem_start()); return reinterpret_cast<T*>(mem_start_);
} }
template <typename T> template <typename T>
T* raw_mem_end() { T* raw_mem_end() {
DCHECK(mem_start()); DCHECK(mem_start_);
return reinterpret_cast<T*>(mem_start() + mem_size()); return reinterpret_cast<T*>(mem_start_ + mem_size_);
} }
template <typename T> template <typename T>
T raw_mem_at(int i) { T raw_mem_at(int i) {
DCHECK(mem_start()); DCHECK(mem_start_);
return ReadMemory(&(reinterpret_cast<T*>(mem_start())[i])); return ReadMemory(&(reinterpret_cast<T*>(mem_start_)[i]));
} }
template <typename T> template <typename T>
T raw_val_at(int i) { T raw_val_at(int i) {
return ReadMemory(reinterpret_cast<T*>(mem_start() + i)); return ReadMemory(reinterpret_cast<T*>(mem_start_ + i));
} }
template <typename T> template <typename T>
...@@ -184,7 +185,7 @@ class TestingModule : public ModuleEnv { ...@@ -184,7 +185,7 @@ class TestingModule : public ModuleEnv {
// Zero-initialize the memory. // Zero-initialize the memory.
void BlankMemory() { void BlankMemory() {
byte* raw = raw_mem_start<byte>(); byte* raw = raw_mem_start<byte>();
memset(raw, 0, mem_size()); memset(raw, 0, mem_size_);
} }
// Pseudo-randomly intialize the memory. // Pseudo-randomly intialize the memory.
...@@ -201,12 +202,12 @@ class TestingModule : public ModuleEnv { ...@@ -201,12 +202,12 @@ class TestingModule : public ModuleEnv {
} }
uint32_t AddFunction(FunctionSig* sig, Handle<Code> code, const char* name) { uint32_t AddFunction(FunctionSig* sig, Handle<Code> code, const char* name) {
if (module()->functions.size() == 0) { if (test_module_.functions.size() == 0) {
// TODO(titzer): Reserving space here to avoid the underlying WasmFunction // TODO(titzer): Reserving space here to avoid the underlying WasmFunction
// structs from moving. // structs from moving.
test_module_.functions.reserve(kMaxFunctions); test_module_.functions.reserve(kMaxFunctions);
} }
uint32_t index = static_cast<uint32_t>(module()->functions.size()); uint32_t index = static_cast<uint32_t>(test_module_.functions.size());
test_module_.functions.push_back( test_module_.functions.push_back(
{sig, index, 0, {0, 0}, {0, 0}, false, false}); {sig, index, 0, {0, 0}, {0, 0}, false, false});
if (name) { if (name) {
...@@ -216,7 +217,7 @@ class TestingModule : public ModuleEnv { ...@@ -216,7 +217,7 @@ class TestingModule : public ModuleEnv {
} }
function_code_.push_back(code); function_code_.push_back(code);
if (interpreter_) { if (interpreter_) {
interpreter_->AddFunctionForTesting(&module()->functions.back()); interpreter_->AddFunctionForTesting(&test_module_.functions.back());
} }
DCHECK_LT(index, kMaxFunctions); // limited for testing. DCHECK_LT(index, kMaxFunctions); // limited for testing.
return index; return index;
...@@ -228,7 +229,7 @@ class TestingModule : public ModuleEnv { ...@@ -228,7 +229,7 @@ class TestingModule : public ModuleEnv {
uint32_t index = AddFunction(sig, Handle<Code>::null(), nullptr); uint32_t index = AddFunction(sig, Handle<Code>::null(), nullptr);
Handle<Code> code = CompileWasmToJSWrapper( Handle<Code> code = CompileWasmToJSWrapper(
isolate_, jsfunc, sig, index, Handle<String>::null(), isolate_, jsfunc, sig, index, Handle<String>::null(),
Handle<String>::null(), module()->origin()); Handle<String>::null(), test_module_.origin());
function_code_[index] = code; function_code_[index] = code;
return index; return index;
} }
...@@ -237,11 +238,11 @@ class TestingModule : public ModuleEnv { ...@@ -237,11 +238,11 @@ class TestingModule : public ModuleEnv {
// Wrap the code so it can be called as a JS function. // Wrap the code so it can be called as a JS function.
Handle<Code> code = function_code_[index]; Handle<Code> code = function_code_[index];
Handle<Code> ret_code = Handle<Code> ret_code =
compiler::CompileJSToWasmWrapper(isolate_, module(), code, index); compiler::CompileJSToWasmWrapper(isolate_, &test_module_, code, index);
Handle<JSFunction> ret = WasmExportedFunction::New( Handle<JSFunction> ret = WasmExportedFunction::New(
isolate_, instance_object(), MaybeHandle<String>(), isolate_, instance_object(), MaybeHandle<String>(),
static_cast<int>(index), static_cast<int>(index),
static_cast<int>(module()->functions[index].sig->parameter_count()), static_cast<int>(test_module_.functions[index].sig->parameter_count()),
ret_code); ret_code);
// Add weak reference to exported functions. // Add weak reference to exported functions.
...@@ -281,10 +282,10 @@ class TestingModule : public ModuleEnv { ...@@ -281,10 +282,10 @@ class TestingModule : public ModuleEnv {
void PopulateIndirectFunctionTable() { void PopulateIndirectFunctionTable() {
if (interpret()) return; if (interpret()) return;
// Initialize the fixed arrays in instance->function_tables. // Initialize the fixed arrays in instance->function_tables.
for (uint32_t i = 0; i < function_tables().size(); i++) { for (uint32_t i = 0; i < function_tables_.size(); i++) {
WasmIndirectFunctionTable& table = test_module_.function_tables[i]; WasmIndirectFunctionTable& table = test_module_.function_tables[i];
Handle<FixedArray> function_table = function_tables()[i]; Handle<FixedArray> function_table = function_tables_[i];
Handle<FixedArray> signature_table = signature_tables()[i]; Handle<FixedArray> signature_table = signature_tables_[i];
int table_size = static_cast<int>(table.values.size()); int table_size = static_cast<int>(table.values.size());
for (int j = 0; j < table_size; j++) { for (int j = 0; j < table_size; j++) {
WasmFunction& function = test_module_.functions[table.values[j]]; WasmFunction& function = test_module_.functions[table.values[j]];
...@@ -319,12 +320,42 @@ class TestingModule : public ModuleEnv { ...@@ -319,12 +320,42 @@ class TestingModule : public ModuleEnv {
bool interpret() { return interpreter_ != nullptr; } bool interpret() { return interpreter_ != nullptr; }
Isolate* isolate() { return isolate_; } Isolate* isolate() { return isolate_; }
Handle<WasmInstanceObject> instance_object() { return instance_object_; } Handle<WasmInstanceObject> instance_object() { return instance_object_; }
Handle<Code> GetFunctionCode(int index) { return function_code_[index]; }
void SetFunctionCode(int index, Handle<Code> code) {
function_code_[index] = code;
}
Address globals_start() { return reinterpret_cast<Address>(globals_data_); }
compiler::ModuleEnv CreateModuleEnv() {
std::vector<SignatureMap*> signature_maps;
for (size_t i = 0; i < test_module_.function_tables.size(); i++) {
auto& function_table = test_module_.function_tables[i];
signature_maps.push_back(&function_table.map);
}
return {
&test_module_,
function_tables_,
signature_tables_,
signature_maps,
function_code_,
Handle<Code>::null(),
reinterpret_cast<uintptr_t>(mem_start_),
mem_size_,
reinterpret_cast<uintptr_t>(globals_data_),
};
}
private: private:
WasmModule test_module_; WasmModule test_module_;
WasmModule* test_module_ptr_;
Isolate* isolate_; Isolate* isolate_;
uint32_t global_offset; uint32_t global_offset;
V8_ALIGNED(8) byte global_data[kMaxGlobalsSize]; // preallocated global data. byte* mem_start_;
uint32_t mem_size_;
std::vector<Handle<Code>> function_code_;
std::vector<Handle<FixedArray>> function_tables_;
std::vector<Handle<FixedArray>> signature_tables_;
V8_ALIGNED(8) byte globals_data_[kMaxGlobalsSize];
WasmInterpreter* interpreter_; WasmInterpreter* interpreter_;
Handle<WasmInstanceObject> instance_object_; Handle<WasmInstanceObject> instance_object_;
...@@ -336,7 +367,7 @@ class TestingModule : public ModuleEnv { ...@@ -336,7 +367,7 @@ class TestingModule : public ModuleEnv {
global_offset += size; global_offset += size;
// limit number of globals. // limit number of globals.
CHECK_LT(global_offset, kMaxGlobalsSize); CHECK_LT(global_offset, kMaxGlobalsSize);
return &module()->globals.back(); return &test_module_.globals.back();
} }
Handle<WasmInstanceObject> InitInstanceObject() { Handle<WasmInstanceObject> InitInstanceObject() {
...@@ -344,8 +375,8 @@ class TestingModule : public ModuleEnv { ...@@ -344,8 +375,8 @@ class TestingModule : public ModuleEnv {
isolate_->factory()->NewStringFromOneByte({}).ToHandleChecked()); isolate_->factory()->NewStringFromOneByte({}).ToHandleChecked());
// The lifetime of the wasm module is tied to this object's, and we cannot // The lifetime of the wasm module is tied to this object's, and we cannot
// rely on the mechanics of Managed<T>. // rely on the mechanics of Managed<T>.
Handle<Foreign> module_wrapper = Handle<Foreign> module_wrapper = isolate_->factory()->NewForeign(
isolate_->factory()->NewForeign(reinterpret_cast<Address>(&module_)); reinterpret_cast<Address>(&test_module_ptr_));
Handle<Script> script = Handle<Script> script =
isolate_->factory()->NewScript(isolate_->factory()->empty_string()); isolate_->factory()->NewScript(isolate_->factory()->empty_string());
script->set_type(Script::TYPE_WASM); script->set_type(Script::TYPE_WASM);
...@@ -354,14 +385,15 @@ class TestingModule : public ModuleEnv { ...@@ -354,14 +385,15 @@ class TestingModule : public ModuleEnv {
script, Handle<ByteArray>::null()); script, Handle<ByteArray>::null());
Handle<FixedArray> code_table = isolate_->factory()->NewFixedArray(0); Handle<FixedArray> code_table = isolate_->factory()->NewFixedArray(0);
Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New( Handle<WasmCompiledModule> compiled_module =
isolate_, shared_module_data, code_table, *this); WasmCompiledModule::New(isolate_, shared_module_data, code_table,
function_tables_, signature_tables_);
// This method is called when we initialize TestEnvironment. We don't // 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 // 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. // interpreter when we get a memory. We do have globals, though.
WasmCompiledModule::recreate_globals_start( WasmCompiledModule::recreate_globals_start(
compiled_module, isolate_->factory(), compiled_module, isolate_->factory(),
reinterpret_cast<size_t>(globals_start())); reinterpret_cast<size_t>(globals_data_));
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));
...@@ -568,7 +600,8 @@ class WasmFunctionCompiler : private GraphAndBuilders { ...@@ -568,7 +600,8 @@ class WasmFunctionCompiler : private GraphAndBuilders {
} }
// Build the TurboFan graph. // Build the TurboFan graph.
TestBuildingGraph(zone(), &jsgraph, testing_module_, sig, compiler::ModuleEnv module_env = testing_module_->CreateModuleEnv();
TestBuildingGraph(zone(), &jsgraph, &module_env, sig,
&source_position_table_, start, end, &source_position_table_, start, end,
runtime_exception_support_); runtime_exception_support_);
Handle<Code> code = Compile(); Handle<Code> code = Compile();
...@@ -801,8 +834,7 @@ class WasmRunner : public WasmRunnerBase { ...@@ -801,8 +834,7 @@ class WasmRunner : public WasmRunnerBase {
}; };
set_trap_callback_for_testing(trap_callback); set_trap_callback_for_testing(trap_callback);
wrapper_.SetInnerCode( wrapper_.SetInnerCode(module_.GetFunctionCode(0));
module_.GetFunctionCode(functions_[0]->function_index()));
CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(), CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
wrapper_.GetWrapperCode(), wrapper_.signature()); wrapper_.GetWrapperCode(), wrapper_.signature());
int32_t result = runner.Call(static_cast<void*>(&p)..., int32_t result = runner.Call(static_cast<void*>(&p)...,
......
...@@ -14,6 +14,7 @@ function instantiate(buffer, ffi) { ...@@ -14,6 +14,7 @@ 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)
...@@ -26,6 +27,7 @@ function instantiate(buffer, ffi) { ...@@ -26,6 +27,7 @@ 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)
...@@ -39,6 +41,7 @@ function instantiate(buffer, ffi) { ...@@ -39,6 +41,7 @@ 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})
...@@ -52,6 +55,7 @@ function instantiate(buffer, ffi) { ...@@ -52,6 +55,7 @@ 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},
...@@ -75,6 +79,7 @@ function instantiate(buffer, ffi) { ...@@ -75,6 +79,7 @@ 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]);
...@@ -88,6 +93,7 @@ function instantiate(buffer, ffi) { ...@@ -88,6 +93,7 @@ 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]);
...@@ -104,6 +110,7 @@ function instantiate(buffer, ffi) { ...@@ -104,6 +110,7 @@ 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)
...@@ -118,6 +125,7 @@ function instantiate(buffer, ffi) { ...@@ -118,6 +125,7 @@ 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)
...@@ -144,6 +152,7 @@ function instantiate(buffer, ffi) { ...@@ -144,6 +152,7 @@ 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)
......
...@@ -90,7 +90,7 @@ class FunctionBodyDecoderTest : public TestWithZone { ...@@ -90,7 +90,7 @@ class FunctionBodyDecoderTest : public TestWithZone {
FunctionBodyDecoderTest() : module(nullptr), local_decls(zone()) {} FunctionBodyDecoderTest() : module(nullptr), local_decls(zone()) {}
TestSignatures sigs; TestSignatures sigs;
ModuleEnv* module; WasmModule* module;
LocalDeclEncoder local_decls; LocalDeclEncoder local_decls;
void AddLocals(ValueType type, uint32_t count) { void AddLocals(ValueType type, uint32_t count) {
...@@ -121,9 +121,8 @@ class FunctionBodyDecoderTest : public TestWithZone { ...@@ -121,9 +121,8 @@ class FunctionBodyDecoderTest : public TestWithZone {
PrepareBytecode(&start, &end); PrepareBytecode(&start, &end);
// Verify the code. // Verify the code.
DecodeResult result = VerifyWasmCode( DecodeResult result =
zone()->allocator(), module == nullptr ? nullptr : module->module(), VerifyWasmCode(zone()->allocator(), module, sig, start, end);
sig, start, end);
uint32_t pc = result.error_offset(); uint32_t pc = result.error_offset();
std::ostringstream str; std::ostringstream str;
...@@ -191,10 +190,9 @@ constexpr size_t kMaxByteSizedLeb128 = 127; ...@@ -191,10 +190,9 @@ constexpr size_t kMaxByteSizedLeb128 = 127;
// A helper for tests that require a module environment for functions, // A helper for tests that require a module environment for functions,
// globals, or memories. // globals, or memories.
class TestModuleEnv : public ModuleEnv { class TestModuleBuilder {
public: public:
explicit TestModuleEnv(ModuleOrigin origin = kWasmOrigin) { explicit TestModuleBuilder(ModuleOrigin origin = kWasmOrigin) {
module_ = &mod;
mod.set_origin(origin); mod.set_origin(origin);
} }
byte AddGlobal(ValueType type, bool mutability = true) { byte AddGlobal(ValueType type, bool mutability = true) {
...@@ -237,6 +235,8 @@ class TestModuleEnv : public ModuleEnv { ...@@ -237,6 +235,8 @@ class TestModuleEnv : public ModuleEnv {
void InitializeFunctionTable() { mod.function_tables.emplace_back(); } void InitializeFunctionTable() { mod.function_tables.emplace_back(); }
WasmModule* module() { return &mod; }
private: private:
WasmModule mod; WasmModule mod;
}; };
...@@ -1089,9 +1089,9 @@ TEST_F(FunctionBodyDecoderTest, TypeConversions) { ...@@ -1089,9 +1089,9 @@ TEST_F(FunctionBodyDecoderTest, TypeConversions) {
} }
TEST_F(FunctionBodyDecoderTest, MacrosStmt) { TEST_F(FunctionBodyDecoderTest, MacrosStmt) {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
EXPECT_VERIFIES(v_i, WASM_SET_LOCAL(0, WASM_I32V_3(87348))); EXPECT_VERIFIES(v_i, WASM_SET_LOCAL(0, WASM_I32V_3(87348)));
EXPECT_VERIFIES(v_i, WASM_STORE_MEM(MachineType::Int32(), WASM_I32V_1(24), EXPECT_VERIFIES(v_i, WASM_STORE_MEM(MachineType::Int32(), WASM_I32V_1(24),
WASM_I32V_1(40))); WASM_I32V_1(40)));
...@@ -1228,18 +1228,18 @@ TEST_F(FunctionBodyDecoderTest, AllSimpleExpressions) { ...@@ -1228,18 +1228,18 @@ TEST_F(FunctionBodyDecoderTest, AllSimpleExpressions) {
} }
TEST_F(FunctionBodyDecoderTest, MemorySize) { TEST_F(FunctionBodyDecoderTest, MemorySize) {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
byte code[] = {kExprMemorySize, 0}; byte code[] = {kExprMemorySize, 0};
EXPECT_VERIFIES_C(i_i, code); EXPECT_VERIFIES_C(i_i, code);
EXPECT_FAILURE_C(f_ff, code); EXPECT_FAILURE_C(f_ff, code);
} }
TEST_F(FunctionBodyDecoderTest, LoadMemOffset) { TEST_F(FunctionBodyDecoderTest, LoadMemOffset) {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
for (int offset = 0; offset < 128; offset += 7) { for (int offset = 0; offset < 128; offset += 7) {
byte code[] = {kExprI32Const, 0, kExprI32LoadMem, ZERO_ALIGNMENT, byte code[] = {kExprI32Const, 0, kExprI32LoadMem, ZERO_ALIGNMENT,
static_cast<byte>(offset)}; static_cast<byte>(offset)};
...@@ -1248,9 +1248,9 @@ TEST_F(FunctionBodyDecoderTest, LoadMemOffset) { ...@@ -1248,9 +1248,9 @@ TEST_F(FunctionBodyDecoderTest, LoadMemOffset) {
} }
TEST_F(FunctionBodyDecoderTest, LoadMemAlignment) { TEST_F(FunctionBodyDecoderTest, LoadMemAlignment) {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
struct { struct {
WasmOpcode instruction; WasmOpcode instruction;
uint32_t maximum_aligment; uint32_t maximum_aligment;
...@@ -1285,9 +1285,9 @@ TEST_F(FunctionBodyDecoderTest, LoadMemAlignment) { ...@@ -1285,9 +1285,9 @@ TEST_F(FunctionBodyDecoderTest, LoadMemAlignment) {
} }
TEST_F(FunctionBodyDecoderTest, StoreMemOffset) { TEST_F(FunctionBodyDecoderTest, StoreMemOffset) {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
for (byte offset = 0; offset < 128; offset += 7) { for (byte offset = 0; offset < 128; offset += 7) {
byte code[] = {WASM_STORE_MEM_OFFSET(MachineType::Int32(), offset, byte code[] = {WASM_STORE_MEM_OFFSET(MachineType::Int32(), offset,
WASM_ZERO, WASM_ZERO)}; WASM_ZERO, WASM_ZERO)};
...@@ -1296,9 +1296,9 @@ TEST_F(FunctionBodyDecoderTest, StoreMemOffset) { ...@@ -1296,9 +1296,9 @@ TEST_F(FunctionBodyDecoderTest, StoreMemOffset) {
} }
TEST_F(FunctionBodyDecoderTest, StoreMemOffset_void) { TEST_F(FunctionBodyDecoderTest, StoreMemOffset_void) {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
EXPECT_FAILURE(i_i, WASM_STORE_MEM_OFFSET(MachineType::Int32(), 0, WASM_ZERO, EXPECT_FAILURE(i_i, WASM_STORE_MEM_OFFSET(MachineType::Int32(), 0, WASM_ZERO,
WASM_ZERO)); WASM_ZERO));
} }
...@@ -1314,9 +1314,9 @@ TEST_F(FunctionBodyDecoderTest, StoreMemOffset_void) { ...@@ -1314,9 +1314,9 @@ TEST_F(FunctionBodyDecoderTest, StoreMemOffset_void) {
#define VARINT4(x) BYTE0(x) | 0x80, BYTE1(x) | 0x80, BYTE2(x) | 0x80, BYTE3(x) #define VARINT4(x) BYTE0(x) | 0x80, BYTE1(x) | 0x80, BYTE2(x) | 0x80, BYTE3(x)
TEST_F(FunctionBodyDecoderTest, LoadMemOffset_varint) { TEST_F(FunctionBodyDecoderTest, LoadMemOffset_varint) {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
EXPECT_VERIFIES(i_i, WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT, EXPECT_VERIFIES(i_i, WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT,
VARINT1(0x45)); VARINT1(0x45));
EXPECT_VERIFIES(i_i, WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT, EXPECT_VERIFIES(i_i, WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT,
...@@ -1328,9 +1328,9 @@ TEST_F(FunctionBodyDecoderTest, LoadMemOffset_varint) { ...@@ -1328,9 +1328,9 @@ TEST_F(FunctionBodyDecoderTest, LoadMemOffset_varint) {
} }
TEST_F(FunctionBodyDecoderTest, StoreMemOffset_varint) { TEST_F(FunctionBodyDecoderTest, StoreMemOffset_varint) {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
EXPECT_VERIFIES(v_i, WASM_ZERO, WASM_ZERO, kExprI32StoreMem, ZERO_ALIGNMENT, EXPECT_VERIFIES(v_i, WASM_ZERO, WASM_ZERO, kExprI32StoreMem, ZERO_ALIGNMENT,
VARINT1(0x33)); VARINT1(0x33));
EXPECT_VERIFIES(v_i, WASM_ZERO, WASM_ZERO, kExprI32StoreMem, ZERO_ALIGNMENT, EXPECT_VERIFIES(v_i, WASM_ZERO, WASM_ZERO, kExprI32StoreMem, ZERO_ALIGNMENT,
...@@ -1342,9 +1342,9 @@ TEST_F(FunctionBodyDecoderTest, StoreMemOffset_varint) { ...@@ -1342,9 +1342,9 @@ TEST_F(FunctionBodyDecoderTest, StoreMemOffset_varint) {
} }
TEST_F(FunctionBodyDecoderTest, AllLoadMemCombinations) { TEST_F(FunctionBodyDecoderTest, AllLoadMemCombinations) {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
for (size_t i = 0; i < arraysize(kValueTypes); i++) { for (size_t i = 0; i < arraysize(kValueTypes); i++) {
ValueType local_type = kValueTypes[i]; ValueType local_type = kValueTypes[i];
for (size_t j = 0; j < arraysize(machineTypes); j++) { for (size_t j = 0; j < arraysize(machineTypes); j++) {
...@@ -1361,9 +1361,9 @@ TEST_F(FunctionBodyDecoderTest, AllLoadMemCombinations) { ...@@ -1361,9 +1361,9 @@ TEST_F(FunctionBodyDecoderTest, AllLoadMemCombinations) {
} }
TEST_F(FunctionBodyDecoderTest, AllStoreMemCombinations) { TEST_F(FunctionBodyDecoderTest, AllStoreMemCombinations) {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
for (size_t i = 0; i < arraysize(kValueTypes); i++) { for (size_t i = 0; i < arraysize(kValueTypes); i++) {
ValueType local_type = kValueTypes[i]; ValueType local_type = kValueTypes[i];
for (size_t j = 0; j < arraysize(machineTypes); j++) { for (size_t j = 0; j < arraysize(machineTypes); j++) {
...@@ -1381,12 +1381,12 @@ TEST_F(FunctionBodyDecoderTest, AllStoreMemCombinations) { ...@@ -1381,12 +1381,12 @@ TEST_F(FunctionBodyDecoderTest, AllStoreMemCombinations) {
TEST_F(FunctionBodyDecoderTest, SimpleCalls) { TEST_F(FunctionBodyDecoderTest, SimpleCalls) {
FunctionSig* sig = sigs.i_i(); FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddFunction(sigs.i_v()); builder.AddFunction(sigs.i_v());
module_env.AddFunction(sigs.i_i()); builder.AddFunction(sigs.i_i());
module_env.AddFunction(sigs.i_ii()); builder.AddFunction(sigs.i_ii());
EXPECT_VERIFIES_S(sig, WASM_CALL_FUNCTION0(0)); EXPECT_VERIFIES_S(sig, WASM_CALL_FUNCTION0(0));
EXPECT_VERIFIES_S(sig, WASM_CALL_FUNCTION(1, WASM_I32V_1(27))); EXPECT_VERIFIES_S(sig, WASM_CALL_FUNCTION(1, WASM_I32V_1(27)));
...@@ -1396,12 +1396,12 @@ TEST_F(FunctionBodyDecoderTest, SimpleCalls) { ...@@ -1396,12 +1396,12 @@ TEST_F(FunctionBodyDecoderTest, SimpleCalls) {
TEST_F(FunctionBodyDecoderTest, CallsWithTooFewArguments) { TEST_F(FunctionBodyDecoderTest, CallsWithTooFewArguments) {
FunctionSig* sig = sigs.i_i(); FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddFunction(sigs.i_i()); builder.AddFunction(sigs.i_i());
module_env.AddFunction(sigs.i_ii()); builder.AddFunction(sigs.i_ii());
module_env.AddFunction(sigs.f_ff()); builder.AddFunction(sigs.f_ff());
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION0(0)); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION0(0));
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(1, WASM_ZERO)); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(1, WASM_ZERO));
...@@ -1410,10 +1410,10 @@ TEST_F(FunctionBodyDecoderTest, CallsWithTooFewArguments) { ...@@ -1410,10 +1410,10 @@ TEST_F(FunctionBodyDecoderTest, CallsWithTooFewArguments) {
TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs2) { TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs2) {
FunctionSig* sig = sigs.i_i(); FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddFunction(sigs.i_i()); builder.AddFunction(sigs.i_i());
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(0, WASM_I64V_1(17))); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(0, WASM_I64V_1(17)));
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(0, WASM_F32(17.1))); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(0, WASM_F32(17.1)));
...@@ -1422,16 +1422,16 @@ TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs2) { ...@@ -1422,16 +1422,16 @@ TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs2) {
TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs3) { TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs3) {
FunctionSig* sig = sigs.i_i(); FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddFunction(sigs.i_f()); builder.AddFunction(sigs.i_f());
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(0, WASM_I32V_1(17))); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(0, WASM_I32V_1(17)));
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(0, WASM_I64V_1(27))); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(0, WASM_I64V_1(27)));
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(0, WASM_F64(37.2))); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(0, WASM_F64(37.2)));
module_env.AddFunction(sigs.i_d()); builder.AddFunction(sigs.i_d());
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(1, WASM_I32V_1(16))); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(1, WASM_I32V_1(16)));
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(1, WASM_I64V_1(16))); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(1, WASM_I64V_1(16)));
...@@ -1443,11 +1443,11 @@ TEST_F(FunctionBodyDecoderTest, MultiReturn) { ...@@ -1443,11 +1443,11 @@ TEST_F(FunctionBodyDecoderTest, MultiReturn) {
ValueType storage[] = {kWasmI32, kWasmI32}; ValueType storage[] = {kWasmI32, kWasmI32};
FunctionSig sig_ii_v(2, 0, storage); FunctionSig sig_ii_v(2, 0, storage);
FunctionSig sig_v_ii(0, 2, storage); FunctionSig sig_v_ii(0, 2, storage);
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddFunction(&sig_v_ii); builder.AddFunction(&sig_v_ii);
module_env.AddFunction(&sig_ii_v); builder.AddFunction(&sig_ii_v);
EXPECT_VERIFIES_S(&sig_ii_v, WASM_CALL_FUNCTION0(1)); EXPECT_VERIFIES_S(&sig_ii_v, WASM_CALL_FUNCTION0(1));
EXPECT_VERIFIES(v_v, WASM_CALL_FUNCTION0(1), WASM_DROP, WASM_DROP); EXPECT_VERIFIES(v_v, WASM_CALL_FUNCTION0(1), WASM_DROP, WASM_DROP);
...@@ -1465,9 +1465,9 @@ TEST_F(FunctionBodyDecoderTest, MultiReturnType) { ...@@ -1465,9 +1465,9 @@ TEST_F(FunctionBodyDecoderTest, MultiReturnType) {
ValueType storage_cd[] = {kValueTypes[c], kValueTypes[d]}; ValueType storage_cd[] = {kValueTypes[c], kValueTypes[d]};
FunctionSig sig_cd_v(2, 0, storage_cd); FunctionSig sig_cd_v(2, 0, storage_cd);
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddFunction(&sig_cd_v); builder.AddFunction(&sig_cd_v);
EXPECT_VERIFIES_S(&sig_cd_v, WASM_CALL_FUNCTION0(0)); EXPECT_VERIFIES_S(&sig_cd_v, WASM_CALL_FUNCTION0(0));
...@@ -1484,13 +1484,13 @@ TEST_F(FunctionBodyDecoderTest, MultiReturnType) { ...@@ -1484,13 +1484,13 @@ TEST_F(FunctionBodyDecoderTest, MultiReturnType) {
TEST_F(FunctionBodyDecoderTest, SimpleIndirectCalls) { TEST_F(FunctionBodyDecoderTest, SimpleIndirectCalls) {
FunctionSig* sig = sigs.i_i(); FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env; TestModuleBuilder builder;
module_env.InitializeFunctionTable(); builder.InitializeFunctionTable();
module = &module_env; module = builder.module();
byte f0 = module_env.AddSignature(sigs.i_v()); byte f0 = builder.AddSignature(sigs.i_v());
byte f1 = module_env.AddSignature(sigs.i_i()); byte f1 = builder.AddSignature(sigs.i_i());
byte f2 = module_env.AddSignature(sigs.i_ii()); byte f2 = builder.AddSignature(sigs.i_ii());
EXPECT_VERIFIES_S(sig, WASM_CALL_INDIRECT0(f0, WASM_ZERO)); EXPECT_VERIFIES_S(sig, WASM_CALL_INDIRECT0(f0, WASM_ZERO));
EXPECT_VERIFIES_S(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I32V_1(22))); EXPECT_VERIFIES_S(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I32V_1(22)));
...@@ -1500,16 +1500,16 @@ TEST_F(FunctionBodyDecoderTest, SimpleIndirectCalls) { ...@@ -1500,16 +1500,16 @@ TEST_F(FunctionBodyDecoderTest, SimpleIndirectCalls) {
TEST_F(FunctionBodyDecoderTest, IndirectCallsOutOfBounds) { TEST_F(FunctionBodyDecoderTest, IndirectCallsOutOfBounds) {
FunctionSig* sig = sigs.i_i(); FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env; TestModuleBuilder builder;
module_env.InitializeFunctionTable(); builder.InitializeFunctionTable();
module = &module_env; module = builder.module();
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT0(0, WASM_ZERO)); EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT0(0, WASM_ZERO));
module_env.AddSignature(sigs.i_v()); builder.AddSignature(sigs.i_v());
EXPECT_VERIFIES_S(sig, WASM_CALL_INDIRECT0(0, WASM_ZERO)); EXPECT_VERIFIES_S(sig, WASM_CALL_INDIRECT0(0, WASM_ZERO));
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(1, WASM_ZERO, WASM_I32V_1(22))); EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(1, WASM_ZERO, WASM_I32V_1(22)));
module_env.AddSignature(sigs.i_i()); builder.AddSignature(sigs.i_i());
EXPECT_VERIFIES_S(sig, WASM_CALL_INDIRECT1(1, WASM_ZERO, WASM_I32V_1(27))); EXPECT_VERIFIES_S(sig, WASM_CALL_INDIRECT1(1, WASM_ZERO, WASM_I32V_1(27)));
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(2, WASM_ZERO, WASM_I32V_1(27))); EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(2, WASM_ZERO, WASM_I32V_1(27)));
...@@ -1517,11 +1517,11 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsOutOfBounds) { ...@@ -1517,11 +1517,11 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsOutOfBounds) {
TEST_F(FunctionBodyDecoderTest, IndirectCallsWithMismatchedSigs3) { TEST_F(FunctionBodyDecoderTest, IndirectCallsWithMismatchedSigs3) {
FunctionSig* sig = sigs.i_i(); FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env; TestModuleBuilder builder;
module_env.InitializeFunctionTable(); builder.InitializeFunctionTable();
module = &module_env; module = builder.module();
byte f0 = module_env.AddFunction(sigs.i_f()); byte f0 = builder.AddFunction(sigs.i_f());
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(f0, WASM_ZERO, WASM_I32V_1(17))); EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(f0, WASM_ZERO, WASM_I32V_1(17)));
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(f0, WASM_ZERO, WASM_I64V_1(27))); EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(f0, WASM_ZERO, WASM_I64V_1(27)));
...@@ -1531,7 +1531,7 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsWithMismatchedSigs3) { ...@@ -1531,7 +1531,7 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsWithMismatchedSigs3) {
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT0(f0, WASM_I64V_1(27))); EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT0(f0, WASM_I64V_1(27)));
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT0(f0, WASM_F64(37.2))); EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT0(f0, WASM_F64(37.2)));
byte f1 = module_env.AddFunction(sigs.i_d()); byte f1 = builder.AddFunction(sigs.i_d());
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I32V_1(16))); EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I32V_1(16)));
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I64V_1(16))); EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I64V_1(16)));
...@@ -1540,12 +1540,12 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsWithMismatchedSigs3) { ...@@ -1540,12 +1540,12 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsWithMismatchedSigs3) {
TEST_F(FunctionBodyDecoderTest, IndirectCallsWithoutTableCrash) { TEST_F(FunctionBodyDecoderTest, IndirectCallsWithoutTableCrash) {
FunctionSig* sig = sigs.i_i(); FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
byte f0 = module_env.AddSignature(sigs.i_v()); byte f0 = builder.AddSignature(sigs.i_v());
byte f1 = module_env.AddSignature(sigs.i_i()); byte f1 = builder.AddSignature(sigs.i_i());
byte f2 = module_env.AddSignature(sigs.i_ii()); byte f2 = builder.AddSignature(sigs.i_ii());
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT0(f0, WASM_ZERO)); EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT0(f0, WASM_ZERO));
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I32V_1(22))); EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I32V_1(22)));
...@@ -1555,12 +1555,12 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsWithoutTableCrash) { ...@@ -1555,12 +1555,12 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsWithoutTableCrash) {
TEST_F(FunctionBodyDecoderTest, SimpleImportCalls) { TEST_F(FunctionBodyDecoderTest, SimpleImportCalls) {
FunctionSig* sig = sigs.i_i(); FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
byte f0 = module_env.AddImport(sigs.i_v()); byte f0 = builder.AddImport(sigs.i_v());
byte f1 = module_env.AddImport(sigs.i_i()); byte f1 = builder.AddImport(sigs.i_i());
byte f2 = module_env.AddImport(sigs.i_ii()); byte f2 = builder.AddImport(sigs.i_ii());
EXPECT_VERIFIES_S(sig, WASM_CALL_FUNCTION0(f0)); EXPECT_VERIFIES_S(sig, WASM_CALL_FUNCTION0(f0));
EXPECT_VERIFIES_S(sig, WASM_CALL_FUNCTION(f1, WASM_I32V_1(22))); EXPECT_VERIFIES_S(sig, WASM_CALL_FUNCTION(f1, WASM_I32V_1(22)));
...@@ -1570,17 +1570,17 @@ TEST_F(FunctionBodyDecoderTest, SimpleImportCalls) { ...@@ -1570,17 +1570,17 @@ TEST_F(FunctionBodyDecoderTest, SimpleImportCalls) {
TEST_F(FunctionBodyDecoderTest, ImportCallsWithMismatchedSigs3) { TEST_F(FunctionBodyDecoderTest, ImportCallsWithMismatchedSigs3) {
FunctionSig* sig = sigs.i_i(); FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
byte f0 = module_env.AddImport(sigs.i_f()); byte f0 = builder.AddImport(sigs.i_f());
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION0(f0)); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION0(f0));
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(f0, WASM_I32V_1(17))); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(f0, WASM_I32V_1(17)));
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(f0, WASM_I64V_1(27))); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(f0, WASM_I64V_1(27)));
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(f0, WASM_F64(37.2))); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(f0, WASM_F64(37.2)));
byte f1 = module_env.AddImport(sigs.i_d()); byte f1 = builder.AddImport(sigs.i_d());
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION0(f1)); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION0(f1));
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(f1, WASM_I32V_1(16))); EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(f1, WASM_I32V_1(16)));
...@@ -1590,10 +1590,10 @@ TEST_F(FunctionBodyDecoderTest, ImportCallsWithMismatchedSigs3) { ...@@ -1590,10 +1590,10 @@ TEST_F(FunctionBodyDecoderTest, ImportCallsWithMismatchedSigs3) {
TEST_F(FunctionBodyDecoderTest, Int32Globals) { TEST_F(FunctionBodyDecoderTest, Int32Globals) {
FunctionSig* sig = sigs.i_i(); FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddGlobal(kWasmI32); builder.AddGlobal(kWasmI32);
EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(0)); EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(0));
EXPECT_FAILURE_S(sig, WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0))); EXPECT_FAILURE_S(sig, WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0)));
...@@ -1602,11 +1602,11 @@ TEST_F(FunctionBodyDecoderTest, Int32Globals) { ...@@ -1602,11 +1602,11 @@ TEST_F(FunctionBodyDecoderTest, Int32Globals) {
TEST_F(FunctionBodyDecoderTest, ImmutableGlobal) { TEST_F(FunctionBodyDecoderTest, ImmutableGlobal) {
FunctionSig* sig = sigs.v_v(); FunctionSig* sig = sigs.v_v();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
uint32_t g0 = module_env.AddGlobal(kWasmI32, true); uint32_t g0 = builder.AddGlobal(kWasmI32, true);
uint32_t g1 = module_env.AddGlobal(kWasmI32, false); uint32_t g1 = builder.AddGlobal(kWasmI32, false);
EXPECT_VERIFIES_S(sig, WASM_SET_GLOBAL(g0, WASM_ZERO)); EXPECT_VERIFIES_S(sig, WASM_SET_GLOBAL(g0, WASM_ZERO));
EXPECT_FAILURE_S(sig, WASM_SET_GLOBAL(g1, WASM_ZERO)); EXPECT_FAILURE_S(sig, WASM_SET_GLOBAL(g1, WASM_ZERO));
...@@ -1614,13 +1614,13 @@ TEST_F(FunctionBodyDecoderTest, ImmutableGlobal) { ...@@ -1614,13 +1614,13 @@ TEST_F(FunctionBodyDecoderTest, ImmutableGlobal) {
TEST_F(FunctionBodyDecoderTest, Int32Globals_fail) { TEST_F(FunctionBodyDecoderTest, Int32Globals_fail) {
FunctionSig* sig = sigs.i_i(); FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddGlobal(kWasmI64); builder.AddGlobal(kWasmI64);
module_env.AddGlobal(kWasmI64); builder.AddGlobal(kWasmI64);
module_env.AddGlobal(kWasmF32); builder.AddGlobal(kWasmF32);
module_env.AddGlobal(kWasmF64); builder.AddGlobal(kWasmF64);
EXPECT_FAILURE_S(sig, WASM_GET_GLOBAL(0)); EXPECT_FAILURE_S(sig, WASM_GET_GLOBAL(0));
EXPECT_FAILURE_S(sig, WASM_GET_GLOBAL(1)); EXPECT_FAILURE_S(sig, WASM_GET_GLOBAL(1));
...@@ -1635,11 +1635,11 @@ TEST_F(FunctionBodyDecoderTest, Int32Globals_fail) { ...@@ -1635,11 +1635,11 @@ TEST_F(FunctionBodyDecoderTest, Int32Globals_fail) {
TEST_F(FunctionBodyDecoderTest, Int64Globals) { TEST_F(FunctionBodyDecoderTest, Int64Globals) {
FunctionSig* sig = sigs.l_l(); FunctionSig* sig = sigs.l_l();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddGlobal(kWasmI64); builder.AddGlobal(kWasmI64);
module_env.AddGlobal(kWasmI64); builder.AddGlobal(kWasmI64);
EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(0)); EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(0));
EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(1)); EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(1));
...@@ -1652,10 +1652,10 @@ TEST_F(FunctionBodyDecoderTest, Int64Globals) { ...@@ -1652,10 +1652,10 @@ TEST_F(FunctionBodyDecoderTest, Int64Globals) {
TEST_F(FunctionBodyDecoderTest, Float32Globals) { TEST_F(FunctionBodyDecoderTest, Float32Globals) {
FunctionSig* sig = sigs.f_ff(); FunctionSig* sig = sigs.f_ff();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddGlobal(kWasmF32); builder.AddGlobal(kWasmF32);
EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(0)); EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(0));
EXPECT_VERIFIES_S(sig, WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0)), EXPECT_VERIFIES_S(sig, WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0)),
...@@ -1664,10 +1664,10 @@ TEST_F(FunctionBodyDecoderTest, Float32Globals) { ...@@ -1664,10 +1664,10 @@ TEST_F(FunctionBodyDecoderTest, Float32Globals) {
TEST_F(FunctionBodyDecoderTest, Float64Globals) { TEST_F(FunctionBodyDecoderTest, Float64Globals) {
FunctionSig* sig = sigs.d_dd(); FunctionSig* sig = sigs.d_dd();
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddGlobal(kWasmF64); builder.AddGlobal(kWasmF64);
EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(0)); EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(0));
EXPECT_VERIFIES_S(sig, WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0)), EXPECT_VERIFIES_S(sig, WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0)),
...@@ -1680,9 +1680,9 @@ TEST_F(FunctionBodyDecoderTest, AllGetGlobalCombinations) { ...@@ -1680,9 +1680,9 @@ TEST_F(FunctionBodyDecoderTest, AllGetGlobalCombinations) {
for (size_t j = 0; j < arraysize(kValueTypes); j++) { for (size_t j = 0; j < arraysize(kValueTypes); j++) {
ValueType global_type = kValueTypes[j]; ValueType global_type = kValueTypes[j];
FunctionSig sig(1, 0, &local_type); FunctionSig sig(1, 0, &local_type);
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddGlobal(global_type); builder.AddGlobal(global_type);
if (local_type == global_type) { if (local_type == global_type) {
EXPECT_VERIFIES_S(&sig, WASM_GET_GLOBAL(0)); EXPECT_VERIFIES_S(&sig, WASM_GET_GLOBAL(0));
} else { } else {
...@@ -1698,9 +1698,9 @@ TEST_F(FunctionBodyDecoderTest, AllSetGlobalCombinations) { ...@@ -1698,9 +1698,9 @@ TEST_F(FunctionBodyDecoderTest, AllSetGlobalCombinations) {
for (size_t j = 0; j < arraysize(kValueTypes); j++) { for (size_t j = 0; j < arraysize(kValueTypes); j++) {
ValueType global_type = kValueTypes[j]; ValueType global_type = kValueTypes[j];
FunctionSig sig(0, 1, &local_type); FunctionSig sig(0, 1, &local_type);
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddGlobal(global_type); builder.AddGlobal(global_type);
if (local_type == global_type) { if (local_type == global_type) {
EXPECT_VERIFIES_S(&sig, WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0))); EXPECT_VERIFIES_S(&sig, WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0)));
} else { } else {
...@@ -1711,9 +1711,9 @@ TEST_F(FunctionBodyDecoderTest, AllSetGlobalCombinations) { ...@@ -1711,9 +1711,9 @@ TEST_F(FunctionBodyDecoderTest, AllSetGlobalCombinations) {
} }
TEST_F(FunctionBodyDecoderTest, WasmGrowMemory) { TEST_F(FunctionBodyDecoderTest, WasmGrowMemory) {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
byte code[] = {WASM_GET_LOCAL(0), kExprGrowMemory, 0}; byte code[] = {WASM_GET_LOCAL(0), kExprGrowMemory, 0};
EXPECT_VERIFIES_C(i_i, code); EXPECT_VERIFIES_C(i_i, code);
...@@ -1721,9 +1721,9 @@ TEST_F(FunctionBodyDecoderTest, WasmGrowMemory) { ...@@ -1721,9 +1721,9 @@ TEST_F(FunctionBodyDecoderTest, WasmGrowMemory) {
} }
TEST_F(FunctionBodyDecoderTest, AsmJsGrowMemory) { TEST_F(FunctionBodyDecoderTest, AsmJsGrowMemory) {
TestModuleEnv module_env(kAsmJsOrigin); TestModuleBuilder builder(kAsmJsOrigin);
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
byte code[] = {WASM_GET_LOCAL(0), kExprGrowMemory, 0}; byte code[] = {WASM_GET_LOCAL(0), kExprGrowMemory, 0};
EXPECT_FAILURE_C(i_i, code); EXPECT_FAILURE_C(i_i, code);
...@@ -1753,18 +1753,18 @@ TEST_F(FunctionBodyDecoderTest, AsmJsBinOpsCheckOrigin) { ...@@ -1753,18 +1753,18 @@ TEST_F(FunctionBodyDecoderTest, AsmJsBinOpsCheckOrigin) {
}; };
{ {
TestModuleEnv module_env(kAsmJsOrigin); TestModuleBuilder builder(kAsmJsOrigin);
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
for (size_t i = 0; i < arraysize(AsmJsBinOps); i++) { for (size_t i = 0; i < arraysize(AsmJsBinOps); i++) {
TestBinop(AsmJsBinOps[i].op, AsmJsBinOps[i].sig); TestBinop(AsmJsBinOps[i].op, AsmJsBinOps[i].sig);
} }
} }
{ {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
for (size_t i = 0; i < arraysize(AsmJsBinOps); i++) { for (size_t i = 0; i < arraysize(AsmJsBinOps); i++) {
byte code[] = { byte code[] = {
WASM_BINOP(AsmJsBinOps[i].op, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))}; WASM_BINOP(AsmJsBinOps[i].op, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
...@@ -1801,18 +1801,18 @@ TEST_F(FunctionBodyDecoderTest, AsmJsUnOpsCheckOrigin) { ...@@ -1801,18 +1801,18 @@ TEST_F(FunctionBodyDecoderTest, AsmJsUnOpsCheckOrigin) {
{kExprI32AsmjsSConvertF64, sigs.i_d()}, {kExprI32AsmjsSConvertF64, sigs.i_d()},
{kExprI32AsmjsUConvertF64, sigs.i_d()}}; {kExprI32AsmjsUConvertF64, sigs.i_d()}};
{ {
TestModuleEnv module_env(kAsmJsOrigin); TestModuleBuilder builder(kAsmJsOrigin);
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
for (size_t i = 0; i < arraysize(AsmJsUnOps); i++) { for (size_t i = 0; i < arraysize(AsmJsUnOps); i++) {
TestUnop(AsmJsUnOps[i].op, AsmJsUnOps[i].sig); TestUnop(AsmJsUnOps[i].op, AsmJsUnOps[i].sig);
} }
} }
{ {
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.InitializeMemory(); builder.InitializeMemory();
for (size_t i = 0; i < arraysize(AsmJsUnOps); i++) { for (size_t i = 0; i < arraysize(AsmJsUnOps); i++) {
byte code[] = {WASM_UNOP(AsmJsUnOps[i].op, WASM_GET_LOCAL(0))}; byte code[] = {WASM_UNOP(AsmJsUnOps[i].op, WASM_GET_LOCAL(0))};
EXPECT_FAILURE_SC(AsmJsUnOps[i].sig, code); EXPECT_FAILURE_SC(AsmJsUnOps[i].sig, code);
...@@ -2241,11 +2241,11 @@ TEST_F(FunctionBodyDecoderTest, Select_TypeCheck) { ...@@ -2241,11 +2241,11 @@ TEST_F(FunctionBodyDecoderTest, Select_TypeCheck) {
TEST_F(FunctionBodyDecoderTest, Throw) { TEST_F(FunctionBodyDecoderTest, Throw) {
EXPERIMENTAL_FLAG_SCOPE(eh); EXPERIMENTAL_FLAG_SCOPE(eh);
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddException(sigs.v_v()); builder.AddException(sigs.v_v());
module_env.AddException(sigs.v_i()); builder.AddException(sigs.v_i());
AddLocals(kWasmI32, 1); AddLocals(kWasmI32, 1);
EXPECT_VERIFIES(v_v, kExprThrow, 0); EXPECT_VERIFIES(v_v, kExprThrow, 0);
...@@ -2262,11 +2262,11 @@ TEST_F(FunctionBodyDecoderTest, Throw) { ...@@ -2262,11 +2262,11 @@ TEST_F(FunctionBodyDecoderTest, Throw) {
TEST_F(FunctionBodyDecoderTest, ThrowUnreachable) { TEST_F(FunctionBodyDecoderTest, ThrowUnreachable) {
// TODO(titzer): unreachable code after throw should validate. // TODO(titzer): unreachable code after throw should validate.
EXPERIMENTAL_FLAG_SCOPE(eh); EXPERIMENTAL_FLAG_SCOPE(eh);
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddException(sigs.v_v()); builder.AddException(sigs.v_v());
module_env.AddException(sigs.v_i()); builder.AddException(sigs.v_i());
AddLocals(kWasmI32, 1); AddLocals(kWasmI32, 1);
EXPECT_VERIFIES(i_i, kExprThrow, 0, WASM_GET_LOCAL(0)); EXPECT_VERIFIES(i_i, kExprThrow, 0, WASM_GET_LOCAL(0));
...@@ -2281,10 +2281,10 @@ TEST_F(FunctionBodyDecoderTest, ThrowUnreachable) { ...@@ -2281,10 +2281,10 @@ TEST_F(FunctionBodyDecoderTest, ThrowUnreachable) {
TEST_F(FunctionBodyDecoderTest, TryCatch) { TEST_F(FunctionBodyDecoderTest, TryCatch) {
EXPERIMENTAL_FLAG_SCOPE(eh); EXPERIMENTAL_FLAG_SCOPE(eh);
TestModuleEnv module_env; TestModuleBuilder builder;
module = &module_env; module = builder.module();
module_env.AddException(sigs.v_v()); builder.AddException(sigs.v_v());
module_env.AddException(sigs.v_v()); builder.AddException(sigs.v_v());
// TODO(kschimpf): Need to fix catch to use declared exception. // TODO(kschimpf): Need to fix catch to use declared exception.
EXPECT_VERIFIES(v_v, WASM_TRY_OP, WASM_CATCH(0), kExprEnd); EXPECT_VERIFIES(v_v, WASM_TRY_OP, WASM_CATCH(0), kExprEnd);
......
...@@ -985,16 +985,11 @@ TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) { ...@@ -985,16 +985,11 @@ TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) {
class WasmFunctionVerifyTest : public TestWithIsolateAndZone { class WasmFunctionVerifyTest : public TestWithIsolateAndZone {
public: public:
WasmFunctionVerifyTest() : env(&module, Handle<Code>::null()) {} WasmFunctionVerifyTest() {}
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);
}; };
...@@ -1013,9 +1008,8 @@ TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) { ...@@ -1013,9 +1008,8 @@ TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
kExprEnd // body kExprEnd // body
}; };
FunctionResult result = FunctionResult result = SyncDecodeWasmFunction(
SyncDecodeWasmFunction(isolate(), zone(), get_bytes(), isolate(), zone(), bytes, &module, data, data + sizeof(data));
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