[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}
This commit is contained in:
Ben L. Titzer 2017-08-17 19:38:18 +02:00 committed by Commit Bot
parent af4f152063
commit d04660db3f
16 changed files with 585 additions and 627 deletions

View File

@ -67,13 +67,13 @@ void MergeControlToEnd(JSGraph* jsgraph, Node* node) {
} // namespace
WasmGraphBuilder::WasmGraphBuilder(
const wasm::ModuleEnv* module_env, Zone* zone, JSGraph* jsgraph,
Handle<Code> centry_stub, wasm::FunctionSig* sig,
ModuleEnv* env, Zone* zone, JSGraph* jsgraph, Handle<Code> centry_stub,
wasm::FunctionSig* sig,
compiler::SourcePositionTable* source_position_table)
: zone_(zone),
jsgraph_(jsgraph),
centry_stub_node_(jsgraph_->HeapConstant(centry_stub)),
module_env_(module_env),
env_(env),
signature_tables_(zone),
function_tables_(zone),
function_table_sizes_(zone),
@ -192,10 +192,9 @@ Node* WasmGraphBuilder::Int64Constant(int64_t value) {
void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position,
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.
if (FLAG_wasm_no_stack_checks || !module_env_ ||
!has_runtime_exception_support_) {
if (FLAG_wasm_no_stack_checks || !env_ || !has_runtime_exception_support_) {
return;
}
if (effect == nullptr) effect = effect_;
@ -2226,12 +2225,13 @@ Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets,
DCHECK_NULL(args[0]);
// Add code object as constant.
// TODO(wasm): Always use the illegal builtin, except for testing.
Handle<Code> code = module_env_->GetFunctionCode(index);
Handle<Code> code = index < env_->function_code.size()
? env_->function_code[index]
: env_->default_function_code;
DCHECK(!code.is_null());
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);
}
@ -2240,13 +2240,11 @@ Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args,
Node*** rets,
wasm::WasmCodePosition position) {
DCHECK_NOT_NULL(args[0]);
DCHECK_NOT_NULL(module_env_);
DCHECK_NOT_NULL(env_);
// Assume only one table for now.
uint32_t table_index = 0;
wasm::FunctionSig* sig = module_env_->GetSignature(sig_index);
DCHECK(module_env_->IsValidTable(table_index));
wasm::FunctionSig* sig = env_->module->signatures[sig_index];
EnsureFunctionTableNodes();
MachineOperatorBuilder* machine = jsgraph()->machine();
@ -2272,10 +2270,10 @@ Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args,
Int32Constant(kPointerSizeLog2)),
Int32Constant(fixed_offset)),
*effect_, *control_);
auto& map = module_env_->module()->function_tables[0].map;
auto map = env_->signature_maps[table_index];
Node* sig_match = graph()->NewNode(
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);
}
@ -2953,8 +2951,8 @@ void WasmGraphBuilder::BuildCWasmEntry() {
}
Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
DCHECK_NOT_NULL(module_env_);
uintptr_t mem_start = reinterpret_cast<uintptr_t>(module_env_->mem_start());
DCHECK_NOT_NULL(env_);
uintptr_t mem_start = reinterpret_cast<uintptr_t>(env_->mem_start);
if (offset == 0) {
if (!mem_buffer_) {
mem_buffer_ = jsgraph()->RelocatableIntPtrConstant(
@ -2970,7 +2968,7 @@ Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
Node* WasmGraphBuilder::CurrentMemoryPages() {
// CurrentMemoryPages can not be called from asm.js.
DCHECK_EQ(wasm::kWasmOrigin, module_env_->module()->origin());
DCHECK_EQ(wasm::kWasmOrigin, env_->module->origin());
SetNeedsStackCheck();
Node* call = BuildCallToRuntime(Runtime::kWasmMemorySize, nullptr, 0);
Node* result = BuildChangeSmiToInt32(call);
@ -2978,9 +2976,9 @@ Node* WasmGraphBuilder::CurrentMemoryPages() {
}
Node* WasmGraphBuilder::MemSize() {
DCHECK_NOT_NULL(module_env_);
DCHECK_NOT_NULL(env_);
if (mem_size_) return mem_size_;
uint32_t size = module_env_->mem_size();
uint32_t size = env_->mem_size;
mem_size_ = jsgraph()->RelocatableInt32Constant(
size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
return mem_size_;
@ -2988,17 +2986,13 @@ Node* WasmGraphBuilder::MemSize() {
void WasmGraphBuilder::EnsureFunctionTableNodes() {
if (function_tables_.size() > 0) return;
size_t tables_size = module_env_->module()->function_tables.size();
DCHECK_EQ(tables_size, module_env_->function_tables().size());
DCHECK_EQ(tables_size, module_env_->signature_tables().size());
size_t tables_size = env_->function_tables.size();
for (size_t i = 0; i < tables_size; ++i) {
auto function_handle = module_env_->function_tables()[i];
auto signature_handle = module_env_->signature_tables()[i];
auto function_handle = env_->function_tables[i];
auto signature_handle = env_->signature_tables[i];
function_tables_.push_back(HeapConstant(function_handle));
signature_tables_.push_back(HeapConstant(signature_handle));
uint32_t table_size =
module_env_->module()->function_tables[i].initial_size;
uint32_t table_size = env_->module->function_tables[i].initial_size;
function_table_sizes_.push_back(jsgraph()->RelocatableInt32Constant(
static_cast<uint32_t>(table_size),
RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE));
@ -3096,10 +3090,9 @@ Node* WasmGraphBuilder::BuildCallToRuntime(Runtime::FunctionId f,
Node* WasmGraphBuilder::GetGlobal(uint32_t index) {
MachineType mem_type =
wasm::WasmOpcodes::MachineTypeFor(module_env_->GetGlobalType(index));
byte* globals_start = module_env_->globals_start();
uintptr_t global_addr = reinterpret_cast<uintptr_t>(
globals_start + module_env_->module()->globals[index].offset);
wasm::WasmOpcodes::MachineTypeFor(env_->module->globals[index].type);
uintptr_t global_addr =
env_->globals_start + env_->module->globals[index].offset;
Node* addr = jsgraph()->RelocatableIntPtrConstant(
global_addr, RelocInfo::WASM_GLOBAL_REFERENCE);
const Operator* op = jsgraph()->machine()->Load(mem_type);
@ -3111,12 +3104,11 @@ Node* WasmGraphBuilder::GetGlobal(uint32_t index) {
Node* WasmGraphBuilder::SetGlobal(uint32_t index, Node* val) {
MachineType mem_type =
wasm::WasmOpcodes::MachineTypeFor(module_env_->GetGlobalType(index));
byte* globals_start = module_env_->globals_start();
wasm::WasmOpcodes::MachineTypeFor(env_->module->globals[index].type);
uintptr_t global_addr =
env_->globals_start + env_->module->globals[index].offset;
Node* addr = jsgraph()->RelocatableIntPtrConstant(
reinterpret_cast<uintptr_t>(globals_start +
module_env_->module()->globals[index].offset),
RelocInfo::WASM_GLOBAL_REFERENCE);
global_addr, RelocInfo::WASM_GLOBAL_REFERENCE);
const Operator* op = jsgraph()->machine()->Store(
StoreRepresentation(mem_type.representation(), kNoWriteBarrier));
Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), val,
@ -3129,49 +3121,50 @@ void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index,
uint32_t offset,
wasm::WasmCodePosition position) {
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.
uint64_t min_size = static_cast<uint64_t>(env_->module->initial_pages) *
wasm::WasmModule::kPageSize;
uint64_t max_size = static_cast<uint64_t>(env_->module->has_maximum_pages
? env_->module->maximum_pages
: wasm::kV8MaxWasmMemoryPages) *
wasm::WasmModule::kPageSize;
// 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;
byte access_size = wasm::WasmOpcodes::MemSize(memtype);
Node* cond = graph()->NewNode(jsgraph()->machine()->Uint32LessThan(),
jsgraph()->IntPtrConstant(effective_offset),
jsgraph()->RelocatableInt32Constant(
static_cast<uint32_t>(size),
RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
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);
// 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 {
effective_size = size - offset - memsize + 1;
CHECK(effective_size <= kMaxUInt32);
// The end offset is within the bounds of the smallest memory, so only
// one check is required. Check to see if the index is also a constant.
Uint32Matcher m(index);
if (m.HasValue()) {
uint32_t value = m.Value();
if (value < effective_size) {
// The bounds check will always succeed.
uint64_t index_val = m.Value();
if ((index_val + offset + access_size) <= min_size) {
// The input index is a constant and everything is statically within
// bounds of the smallest possible memory.
return;
}
}
}
uint64_t effective_size = env_->mem_size - (end_offset - 1);
Node* cond = graph()->NewNode(jsgraph()->machine()->Uint32LessThan(), index,
jsgraph()->RelocatableInt32Constant(
static_cast<uint32_t>(effective_size),
@ -3824,11 +3817,18 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
Node* control = nullptr;
Node* effect = nullptr;
// TODO(mtrofin): refactor CompileJSToWasmWrapper to not require a module_env.
// It's not really applicable.
wasm::ModuleEnv module_env(module, BUILTIN_CODE(isolate, Illegal));
// TODO(titzer): compile JS to WASM wrappers without a {ModuleEnv}.
ModuleEnv env = {module,
std::vector<Handle<FixedArray>>(), // function_tables
std::vector<Handle<FixedArray>>(), // signature_tables
std::vector<wasm::SignatureMap*>(), // signature_maps
std::vector<Handle<Code>>(), // function_code
BUILTIN_CODE(isolate, Illegal), // default_function_code
0,
0,
0};
WasmGraphBuilder builder(&module_env, &zone, &jsgraph,
WasmGraphBuilder builder(&env, &zone, &jsgraph,
CEntryStub(isolate, 1).GetCode(), func->sig);
builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect);
@ -3844,8 +3844,8 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
}
// Schedule and compile to machine code.
int params = static_cast<int>(
module_env.GetFunctionSignature(index)->parameter_count());
int params =
static_cast<int>(module->functions[index].sig->parameter_count());
CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
&zone, false, params + 1, CallDescriptor::kNoFlags);
Code::Flags flags = Code::ComputeFlags(Code::JS_TO_WASM_FUNCTION);
@ -4103,6 +4103,15 @@ Handle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
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;
if (FLAG_trace_wasm_decode_time) {
decode_timer.Start();
@ -4111,8 +4120,8 @@ SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
SourcePositionTable* source_position_table =
new (jsgraph_->zone()) SourcePositionTable(jsgraph_->graph());
WasmGraphBuilder builder(module_env_, jsgraph_->zone(), jsgraph_,
centry_stub_, func_body_.sig, source_position_table);
WasmGraphBuilder builder(env_, jsgraph_->zone(), jsgraph_, centry_stub_,
func_body_.sig, source_position_table);
graph_construction_result_ =
wasm::BuildTFGraph(isolate_->allocator(), &builder, func_body_);
@ -4133,7 +4142,7 @@ SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
if (func_index_ >= FLAG_trace_wasm_ast_start &&
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) {
*decode_ms = decode_timer.Elapsed().InMillisecondsF();
@ -4162,24 +4171,22 @@ Vector<const char> GetDebugName(Zone* zone, wasm::WasmName name, int index) {
} // namespace
WasmCompilationUnit::WasmCompilationUnit(
Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes,
const wasm::ModuleEnv* module_env, const wasm::WasmFunction* function,
Handle<Code> centry_stub)
Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env,
const wasm::WasmFunction* function, Handle<Code> centry_stub)
: WasmCompilationUnit(
isolate, module_env,
isolate, env,
wasm::FunctionBody{function->sig, function->code.offset(),
wire_bytes.start() + function->code.offset(),
wire_bytes.start() + function->code.end_offset()},
wire_bytes.GetNameOrNull(function), function->func_index,
centry_stub) {}
WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate,
const wasm::ModuleEnv* module_env,
WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate, ModuleEnv* env,
wasm::FunctionBody body,
wasm::WasmName name, int index,
Handle<Code> centry_stub)
: isolate_(isolate),
module_env_(module_env),
env_(env),
func_body_(body),
func_name_(name),
counters_(isolate->counters()),
@ -4187,11 +4194,11 @@ WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate,
func_index_(index) {}
WasmCompilationUnit::WasmCompilationUnit(
Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes,
const wasm::ModuleEnv* module_env, const wasm::WasmFunction* function,
Handle<Code> centry_stub, const std::shared_ptr<Counters>& async_counters)
Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env,
const wasm::WasmFunction* function, Handle<Code> centry_stub,
const std::shared_ptr<Counters>& async_counters)
: WasmCompilationUnit(
isolate, module_env,
isolate, env,
wasm::FunctionBody{function->sig, function->code.offset(),
wire_bytes.start() + function->code.offset(),
wire_bytes.start() + function->code.end_offset()},
@ -4199,11 +4206,11 @@ WasmCompilationUnit::WasmCompilationUnit(
async_counters) {}
WasmCompilationUnit::WasmCompilationUnit(
Isolate* isolate, const wasm::ModuleEnv* module_env,
wasm::FunctionBody body, wasm::WasmName name, int index,
Handle<Code> centry_stub, const std::shared_ptr<Counters>& async_counters)
Isolate* isolate, ModuleEnv* env, wasm::FunctionBody body,
wasm::WasmName name, int index, Handle<Code> centry_stub,
const std::shared_ptr<Counters>& async_counters)
: isolate_(isolate),
module_env_(module_env),
env_(env),
func_body_(body),
func_name_(name),
counters_(async_counters.get()),
@ -4211,7 +4218,7 @@ WasmCompilationUnit::WasmCompilationUnit(
func_index_(index) {}
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_asm_function_time();
TimedHistogramScope wasm_compile_function_time_scope(timed_histogram);
@ -4270,7 +4277,7 @@ void WasmCompilationUnit::ExecuteCompilation() {
job_.reset(Pipeline::NewWasmCompilationJob(
info_.get(), jsgraph_, descriptor, source_positions,
&protected_instructions, module_env_->module()->origin()));
&protected_instructions, env_->module->origin()));
ok_ = job_->ExecuteJob() == CompilationJob::SUCCEEDED;
// TODO(bradnelson): Improve histogram handling of size_t.
counters()->wasm_compile_function_peak_memory_bytes()->AddSample(
@ -4341,9 +4348,9 @@ MaybeHandle<Code> WasmCompilationUnit::FinishCompilation(
// static
MaybeHandle<Code> WasmCompilationUnit::CompileWasmFunction(
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) {
WasmCompilationUnit unit(isolate, wire_bytes, module_env, function,
WasmCompilationUnit unit(isolate, wire_bytes, env, function,
CEntryStub(isolate, 1).GetCode());
unit.ExecuteCompilation();
return unit.FinishCompilation(thrower);

View File

@ -32,33 +32,67 @@ class SourcePositionTable;
namespace wasm {
struct DecodeStruct;
class SignatureMap;
// Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
typedef compiler::Node TFNode;
typedef compiler::JSGraph TFGraph;
} // namespace wasm
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 {
public:
// Use the following constructors if you know you are running on the
// foreground thread.
WasmCompilationUnit(Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes,
const wasm::ModuleEnv* module_env,
const wasm::WasmFunction* function,
Handle<Code> centry_stub);
WasmCompilationUnit(Isolate* isolate, const wasm::ModuleEnv* module_env,
wasm::FunctionBody body, wasm::WasmName name, int index,
ModuleEnv* env, const wasm::WasmFunction* function,
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
// thread.
WasmCompilationUnit(Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes,
const wasm::ModuleEnv* module_env,
const wasm::WasmFunction* function,
ModuleEnv* env, const wasm::WasmFunction* function,
Handle<Code> centry_stub,
const std::shared_ptr<Counters>& async_counters);
WasmCompilationUnit(Isolate* isolate, const wasm::ModuleEnv* module_env,
wasm::FunctionBody body, wasm::WasmName name, int index,
Handle<Code> centry_stub,
WasmCompilationUnit(Isolate* isolate, ModuleEnv* env, wasm::FunctionBody body,
wasm::WasmName name, int index, Handle<Code> centry_stub,
const std::shared_ptr<Counters>& async_counters);
int func_index() const { return func_index_; }
@ -68,8 +102,8 @@ class WasmCompilationUnit final {
static MaybeHandle<Code> CompileWasmFunction(
wasm::ErrorThrower* thrower, Isolate* isolate,
const wasm::ModuleWireBytes& wire_bytes,
const wasm::ModuleEnv* module_env, const wasm::WasmFunction* function);
const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env,
const wasm::WasmFunction* function);
void set_memory_cost(size_t memory_cost) { memory_cost_ = memory_cost; }
size_t memory_cost() const { return memory_cost_; }
@ -78,7 +112,7 @@ class WasmCompilationUnit final {
SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
Isolate* isolate_;
const wasm::ModuleEnv* module_env_;
ModuleEnv* env_;
wasm::FunctionBody func_body_;
wasm::WasmName func_name_;
Counters* counters_;
@ -137,8 +171,8 @@ typedef ZoneVector<Node*> NodeVector;
class WasmGraphBuilder {
public:
WasmGraphBuilder(
const wasm::ModuleEnv* module_env, Zone* z, JSGraph* g,
Handle<Code> centry_stub_, wasm::FunctionSig* sig,
ModuleEnv* env, Zone* z, JSGraph* g, Handle<Code> centry_stub_,
wasm::FunctionSig* sig,
compiler::SourcePositionTable* source_position_table = nullptr);
Node** Buffer(size_t count) {
@ -284,19 +318,19 @@ class WasmGraphBuilder {
bool has_simd() const { return has_simd_; }
const wasm::ModuleEnv* module_env() const { return module_env_; }
void SetRuntimeExceptionSupport(bool value) {
has_runtime_exception_support_ = value;
}
const wasm::WasmModule* module() { return env_ ? env_->module : nullptr; }
private:
static const int kDefaultBufferSize = 16;
Zone* zone_;
JSGraph* jsgraph_;
Node* centry_stub_node_;
const wasm::ModuleEnv* module_env_ = nullptr;
ModuleEnv* env_ = nullptr;
Node* mem_buffer_ = nullptr;
Node* mem_size_ = nullptr;
NodeVector signature_tables_;

View File

@ -619,11 +619,7 @@ class WasmFullDecoder : public WasmDecoder {
: WasmFullDecoder(zone, module, nullptr, body) {}
WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body)
: WasmFullDecoder(zone,
builder->module_env() == nullptr
? nullptr
: builder->module_env()->module(),
builder, body) {}
: WasmFullDecoder(zone, builder->module(), builder, body) {}
bool Decode() {
if (FLAG_wasm_code_fuzzer_gen_test) {

View File

@ -83,7 +83,8 @@ size_t ModuleCompiler::CodeGenerationSchedule::GetRandomIndexInSchedule() {
}
ModuleCompiler::ModuleCompiler(Isolate* isolate,
std::unique_ptr<WasmModule> module)
std::unique_ptr<WasmModule> module,
Handle<Code> centry_stub)
: isolate_(isolate),
module_(std::move(module)),
async_counters_(isolate->async_counters()),
@ -97,7 +98,7 @@ ModuleCompiler::ModuleCompiler(Isolate* isolate,
Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())),
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.
ModuleCompiler::CompilationTask::CompilationTask(ModuleCompiler* compiler)
@ -150,8 +151,8 @@ bool ModuleCompiler::FetchAndExecuteCompilationUnit(
size_t ModuleCompiler::InitializeCompilationUnits(
const std::vector<WasmFunction>& functions,
const ModuleWireBytes& wire_bytes, const ModuleEnv* module_env) {
uint32_t start = module_env->module()->num_imported_functions +
const ModuleWireBytes& wire_bytes, compiler::ModuleEnv* module_env) {
uint32_t start = module_env->module->num_imported_functions +
FLAG_skip_compiling_wasm_funcs;
uint32_t num_funcs = static_cast<uint32_t>(functions.size());
uint32_t funcs_to_compile = start > num_funcs ? 0 : num_funcs - start;
@ -168,10 +169,6 @@ size_t ModuleCompiler::InitializeCompilationUnits(
return funcs_to_compile;
}
void ModuleCompiler::ReopenHandlesInDeferredScope() {
centry_stub_ = handle(*centry_stub_, isolate_);
}
void ModuleCompiler::RestartCompilationTasks() {
base::LockGuard<base::Mutex> guard(&tasks_mutex_);
for (; stopped_compilation_tasks_ > 0; --stopped_compilation_tasks_) {
@ -220,10 +217,10 @@ MaybeHandle<Code> ModuleCompiler::FinishCompilationUnit(ErrorThrower* thrower,
}
void ModuleCompiler::CompileInParallel(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env,
compiler::ModuleEnv* module_env,
std::vector<Handle<Code>>& results,
ErrorThrower* thrower) {
const WasmModule* module = module_env->module();
const WasmModule* module = module_env->module;
// Data structures for the parallel compilation.
//-----------------------------------------------------------------------
@ -277,12 +274,12 @@ void ModuleCompiler::CompileInParallel(const ModuleWireBytes& wire_bytes,
}
void ModuleCompiler::CompileSequentially(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env,
compiler::ModuleEnv* module_env,
std::vector<Handle<Code>>& results,
ErrorThrower* thrower) {
DCHECK(!thrower->error());
const WasmModule* module = module_env->module();
const WasmModule* module = module_env->module;
for (uint32_t i = FLAG_skip_compiling_wasm_funcs;
i < module->functions.size(); ++i) {
const WasmFunction& func = module->functions[i];
@ -302,11 +299,11 @@ void ModuleCompiler::CompileSequentially(const ModuleWireBytes& wire_bytes,
}
void ModuleCompiler::ValidateSequentially(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env,
compiler::ModuleEnv* module_env,
ErrorThrower* thrower) {
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) {
const WasmFunction& func = module->functions[i];
if (func.imported) continue;
@ -365,7 +362,8 @@ void RecordStats(Code* code, Counters* counters) {
void RecordStats(Handle<FixedArray> functions, Counters* counters) {
DisallowHeapAllocation no_gc;
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,
@ -520,14 +518,48 @@ double MonotonicallyIncreasingTimeInMs() {
base::Time::kMillisecondsPerSecond;
}
void SetFunctionTablesToDefault(Factory* factory, wasm::ModuleEnv* module_env) {
for (uint32_t i = 0,
e = static_cast<uint32_t>(module_env->function_tables().size());
i < e; ++i) {
DCHECK(module_env->function_tables()[i].is_null());
DCHECK(module_env->signature_tables()[i].is_null());
module_env->SetFunctionTable(i, factory->NewFixedArray(1, TENURED),
factory->NewFixedArray(1, TENURED));
std::unique_ptr<compiler::ModuleEnv> CreateDefaultModuleEnv(
Factory* factory, WasmModule* module, Handle<Code> illegal_builtin) {
std::vector<Handle<FixedArray>> function_tables;
std::vector<Handle<FixedArray>> signature_tables;
std::vector<SignatureMap*> signature_maps;
for (size_t i = 0; i < module->function_tables.size(); i++) {
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(
? BUILTIN_CODE(isolate_, WasmCompileLazy)
: BUILTIN_CODE(isolate_, Illegal);
ModuleEnv env(module_.get(), init_builtin);
SetFunctionTablesToDefault(factory, &env);
auto env = CreateDefaultModuleEnv(factory, module_.get(), init_builtin);
// The {code_table} array contains import wrappers and functions (which
// are both included in {functions.size()}, and export wrappers).
@ -570,12 +600,12 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal(
funcs_to_compile > 1 &&
V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads() > 0;
// 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) {
CompileInParallel(wire_bytes, &env, results, thrower);
CompileInParallel(wire_bytes, env.get(), results, thrower);
} else {
CompileSequentially(wire_bytes, &env, results, thrower);
CompileSequentially(wire_bytes, env.get(), results, thrower);
}
if (thrower->error()) return {};
@ -594,7 +624,7 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal(
// TODO(clemensh): According to the spec, we can actually skip validation
// at module creation time, and return a function that always traps at
// (lazy) compilation time.
ValidateSequentially(wire_bytes, &env, thrower);
ValidateSequentially(wire_bytes, env.get(), thrower);
}
if (thrower->error()) return {};
@ -636,12 +666,12 @@ MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal(
script, asm_js_offset_table);
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
// serializable. Instantiation may occur off a deserialized version of this
// object.
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
// debugger.
@ -937,7 +967,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
CHECK(memory->byte_length()->ToUint32(&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();
// We might get instantiated again with the same memory. No patching
// needed in this case.
@ -1877,14 +1907,6 @@ AsyncCompileJob::~AsyncCompileJob() {
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) {
RejectPromise(isolate_, context_, thrower, module_promise_);
isolate_->wasm_compilation_manager()->RemoveJob(this);
@ -2031,39 +2053,49 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
std::unique_ptr<WasmModule> module_;
void RunInForeground() override {
TRACE_COMPILE("(2) Prepare and start compile...\n");
HandleScope scope(job_->isolate_);
Isolate* isolate = job_->isolate_;
HandleScope scope(isolate);
Factory* factory = job_->isolate_->factory();
// Initialize {code_table_} with the illegal builtin. All call sites
// will be patched at instantiation.
// TODO(wasm): Fix this for lazy compilation.
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);
Factory* factory = isolate->factory();
Handle<Code> illegal_builtin = BUILTIN_CODE(isolate, Illegal);
job_->module_env_ =
CreateDefaultModuleEnv(factory, module_.get(), illegal_builtin);
// The {code_table} array contains import wrappers and functions (which
// are both included in {functions.size()}, and export wrappers.
// 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() +
module_->num_exported_functions);
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
// keep a pointer.
WasmModule* module = module_.get();
job_->compiler_.reset(
new ModuleCompiler(job_->isolate_, std::move(module_)));
job_->compiler_->EnableThrottling();
Handle<Code> centry_stub = CEntryStub(isolate, 1).GetCode();
// Reopen all handles which should survive in the DeferredHandleScope.
job_->ReopenHandlesInDeferredScope();
{
// 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(
new ModuleCompiler(isolate, std::move(module_), centry_stub));
job_->compiler_->EnableThrottling();
DCHECK_LE(module->num_imported_functions, module->functions.size());
size_t num_functions =
@ -2203,8 +2235,8 @@ class AsyncCompileJob::FinishCompile : public CompileStep {
for (int i = FLAG_skip_compiling_wasm_funcs,
e = job_->code_table_->length();
i < e; ++i) {
Code* code = Code::cast(job_->code_table_->get(i));
RecordStats(code, job_->counters());
Object* val = job_->code_table_->get(i);
if (val->IsCode()) RecordStats(Code::cast(val), job_->counters());
}
// Create heap objects for script and module bytes to be stored in the
@ -2243,9 +2275,8 @@ class AsyncCompileJob::FinishCompile : public CompileStep {
// and information needed at instantiation time. This object needs to be
// serializable. Instantiation may occur off a deserialized version of
// this object.
job_->compiled_module_ = WasmCompiledModule::New(
job_->isolate_, shared, job_->code_table_, *job_->module_env_);
job_->compiled_module_ = NewCompiledModule(
job_->isolate_, shared, job_->code_table_, job_->module_env_.get());
// Finish the wasm script now and make it public to the debugger.
script->set_wasm_compiled_module(*job_->compiled_module_);
job_->isolate_->debug()->OnAfterCompile(script);

View File

@ -27,7 +27,8 @@ class ModuleCompiler {
// In {CompileToModuleObject}, it will transfer ownership to the generated
// {WasmModuleWrapper}. If this method is not called, ownership may be
// 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.
class CompilationTask : public CancelableTask {
@ -48,7 +49,7 @@ class ModuleCompiler {
~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,
WasmName name) {
units_.emplace_back(new compiler::WasmCompilationUnit(
@ -128,9 +129,7 @@ class ModuleCompiler {
size_t InitializeCompilationUnits(const std::vector<WasmFunction>& functions,
const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env);
void ReopenHandlesInDeferredScope();
compiler::ModuleEnv* module_env);
void RestartCompilationTasks();
@ -143,17 +142,18 @@ class ModuleCompiler {
int* func_index);
void CompileInParallel(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env,
compiler::ModuleEnv* module_env,
std::vector<Handle<Code>>& results,
ErrorThrower* thrower);
void CompileSequentially(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env,
compiler::ModuleEnv* module_env,
std::vector<Handle<Code>>& results,
ErrorThrower* thrower);
void ValidateSequentially(const ModuleWireBytes& wire_bytes,
const ModuleEnv* module_env, ErrorThrower* thrower);
compiler::ModuleEnv* module_env,
ErrorThrower* thrower);
MaybeHandle<WasmModuleObject> CompileToModuleObject(
ErrorThrower* thrower, const ModuleWireBytes& wire_bytes,
@ -346,7 +346,7 @@ class AsyncCompileJob {
Handle<Context> context_;
Handle<JSPromise> module_promise_;
std::unique_ptr<ModuleCompiler> compiler_;
std::unique_ptr<ModuleEnv> module_env_;
std::unique_ptr<compiler::ModuleEnv> module_env_;
std::vector<DeferredHandles*> deferred_handles_;
Handle<WasmModuleObject> module_object_;
@ -365,8 +365,6 @@ class AsyncCompileJob {
}
Counters* counters() const { return async_counters().get(); }
void ReopenHandlesInDeferredScope();
void AsyncCompileFailed(ErrorThrower& thrower);
void AsyncCompileSucceeded(Handle<Object> result);

View File

@ -12,6 +12,11 @@
namespace v8 {
namespace internal {
namespace compiler {
struct ModuleEnv;
}
namespace wasm {
const uint32_t kWasmMagic = 0x6d736100;
@ -106,7 +111,7 @@ V8_EXPORT_PRIVATE FunctionResult SyncDecodeWasmFunction(
const byte* function_end);
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 std::shared_ptr<Counters> async_counters);

View File

@ -95,7 +95,6 @@ void CodeSpecialization::RelocateMemoryReferences(Address old_start,
uint32_t new_size) {
DCHECK(old_mem_start == nullptr && old_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_size = old_size;
new_mem_start = new_start;
@ -104,14 +103,12 @@ void CodeSpecialization::RelocateMemoryReferences(Address old_start,
void CodeSpecialization::RelocateGlobals(Address old_start, Address new_start) {
DCHECK(old_globals_start == 0 && new_globals_start == 0);
DCHECK(old_start != 0 || new_start != 0);
old_globals_start = old_start;
new_globals_start = new_start;
}
void CodeSpecialization::PatchTableSize(uint32_t old_size, uint32_t new_size) {
DCHECK(old_function_table_size == 0 && new_function_table_size == 0);
DCHECK(old_size != 0 || new_size != 0);
old_function_table_size = old_size;
new_function_table_size = new_size;
}

View File

@ -212,48 +212,43 @@ void RecordLazyCodeStats(Code* code, Counters* counters) {
counters->wasm_reloc_size()->Increment(code->relocation_info()->length());
}
ModuleEnv CreateModuleEnvFromRuntimeObject(
compiler::ModuleEnv CreateModuleEnvFromCompiledModule(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
DisallowHeapAllocation no_gc;
// Store a vector of handles to be embedded in the generated code.
// TODO(clemensh): For concurrent compilation, these will have to live in a
// DeferredHandleScope.
wasm::ModuleEnv module_env(compiled_module->module(),
BUILTIN_CODE(isolate, WasmCompileLazy));
WasmModule* module = compiled_module->module();
// We set unchecked because the data on the compiled module
// is authoritative.
module_env.SetMemSizeUnchecked(compiled_module->has_embedded_mem_size()
? compiled_module->embedded_mem_size()
: 0);
module_env.set_mem_start(
reinterpret_cast<byte*>(compiled_module->has_embedded_mem_start()
? compiled_module->embedded_mem_start()
: 0));
module_env.set_globals_start(reinterpret_cast<byte*>(
compiled_module->has_globals_start() ? compiled_module->globals_start()
: 0));
std::vector<Handle<FixedArray>> function_tables;
std::vector<Handle<FixedArray>> signature_tables;
std::vector<SignatureMap*> signature_maps;
DCHECK_EQ(compiled_module->has_function_tables(),
compiled_module->has_signature_tables());
int num_function_tables = static_cast<int>(module->function_tables.size());
for (int i = 0; i < num_function_tables; i++) {
FixedArray* ft = compiled_module->ptr_to_function_tables();
FixedArray* st = compiled_module->ptr_to_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))));
}
// TODO(clemensh): defer these handles for concurrent compilation.
function_tables.push_back(handle(FixedArray::cast(ft->get(i))));
signature_tables.push_back(handle(FixedArray::cast(st->get(i))));
signature_maps.push_back(&module->function_tables[i].map);
}
return module_env;
std::vector<Handle<Code>> empty_code;
compiler::ModuleEnv result = {
module, // --
function_tables, // --
signature_tables, // --
signature_maps, // --
empty_code, // --
BUILTIN_CODE(isolate, WasmCompileLazy), // --
reinterpret_cast<uintptr_t>( // --
compiled_module->GetEmbeddedMemStartOrNull()), // --
reinterpret_cast<uint32_t>( // --
compiled_module->GetEmbeddedMemSizeOrZero()), // --
reinterpret_cast<uintptr_t>( // --
compiled_module->GetGlobalsStartOrNull()) // --
};
return result;
}
} // namespace
@ -804,9 +799,10 @@ MaybeHandle<WasmModuleObject> wasm::SyncCompileTranslatedAsmJs(
// Transfer ownership to the {WasmModuleWrapper} generated in
// {CompileToModuleObject}.
ModuleCompiler helper(isolate, std::move(result.val));
return helper.CompileToModuleObject(thrower, bytes, asm_js_script,
asm_js_offset_table_bytes);
Handle<Code> centry_stub = CEntryStub(isolate, 1).GetCode();
ModuleCompiler compiler(isolate, std::move(result.val), centry_stub);
return compiler.CompileToModuleObject(thrower, bytes, asm_js_script,
asm_js_offset_table_bytes);
}
MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate,
@ -826,9 +822,10 @@ MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate,
// Transfer ownership to the {WasmModuleWrapper} generated in
// {CompileToModuleObject}.
ModuleCompiler helper(isolate, std::move(result.val));
return helper.CompileToModuleObject(thrower, bytes, Handle<Script>(),
Vector<const byte>());
Handle<Code> centry_stub = CEntryStub(isolate, 1).GetCode();
ModuleCompiler compiler(isolate, std::move(result.val), centry_stub);
return compiler.CompileToModuleObject(thrower, bytes, Handle<Script>(),
Vector<const byte>());
}
MaybeHandle<WasmInstanceObject> wasm::SyncInstantiate(
@ -1001,12 +998,12 @@ void LazyCompilationOrchestrator::CompileFunction(
return;
}
wasm::ModuleEnv module_env =
CreateModuleEnvFromRuntimeObject(isolate, compiled_module);
compiler::ModuleEnv module_env =
CreateModuleEnvFromCompiledModule(isolate, compiled_module);
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(),
module_start + func->code.offset(),
module_start + func->code.end_offset()};

View File

@ -280,142 +280,6 @@ struct V8_EXPORT_PRIVATE ModuleWireBytes {
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.
struct WasmFunctionName {
WasmFunctionName(const WasmFunction* function, WasmName name)

View File

@ -796,7 +796,10 @@ void WasmSharedModuleData::PrepareForLazyCompilation(
Handle<WasmCompiledModule> WasmCompiledModule::New(
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 =
isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED);
// WasmCompiledModule::cast would fail since fields are not set yet.
@ -806,25 +809,6 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(
compiled_module->set_shared(shared);
compiled_module->set_native_context(isolate->native_context());
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
// reliable, and we need these at Reset (which is called at
// finalization). If the order were reliable, and top-down, we could instead
@ -832,6 +816,22 @@ Handle<WasmCompiledModule> WasmCompiledModule::New(
compiled_module->set_initial_pages(shared->module()->initial_pages);
compiled_module->set_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.
// We're currently OK because we're only using defaults.
return compiled_module;
@ -871,7 +871,7 @@ void WasmCompiledModule::Reset(Isolate* isolate,
Object* undefined = *isolate->factory()->undefined_value();
Object* fct_obj = compiled_module->ptr_to_code_table();
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
// module, because if we can statically prove a memory access is over
// bounds, we'll codegen a trap. See {WasmGraphBuilder::BoundsCheckMem}
@ -1069,11 +1069,6 @@ void WasmCompiledModule::ReinitializeAfterDeserialization(
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 {
return initial_pages() * WasmModule::kPageSize;
}

View File

@ -386,7 +386,7 @@ class WasmCompiledModule : public FixedArray {
MACRO(OBJECT, FixedArray, weak_exported_functions) \
MACRO(OBJECT, FixedArray, function_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, globals_start) \
MACRO(LARGE_NUMBER, uint32_t, embedded_mem_size) \
@ -417,32 +417,31 @@ class WasmCompiledModule : public FixedArray {
};
public:
static Handle<WasmCompiledModule> New(Isolate* isolate,
Handle<WasmSharedModuleData> shared,
Handle<FixedArray> code_table,
const wasm::ModuleEnv& module_env);
static Handle<WasmCompiledModule> New(
Isolate* isolate, Handle<WasmSharedModuleData> shared,
Handle<FixedArray> code_table,
const std::vector<Handle<FixedArray>>& function_tables,
const std::vector<Handle<FixedArray>>& signature_tables);
static Handle<WasmCompiledModule> Clone(Isolate* isolate,
Handle<WasmCompiledModule> module);
static void Reset(Isolate* isolate, WasmCompiledModule* module);
Address GetEmbeddedMemStartOrNull() const {
DisallowHeapAllocation no_gc;
if (has_embedded_mem_start()) {
return reinterpret_cast<Address>(embedded_mem_start());
}
return nullptr;
return has_embedded_mem_start()
? reinterpret_cast<Address>(embedded_mem_start())
: nullptr;
}
Address GetGlobalsStartOrNull() const {
DisallowHeapAllocation no_gc;
if (has_globals_start()) {
return reinterpret_cast<Address>(globals_start());
}
return nullptr;
return has_globals_start() ? reinterpret_cast<Address>(globals_start())
: 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;
void ResetSpecializationMemInfoIfNeeded();

View File

@ -141,7 +141,7 @@ Handle<JSObject> MakeFakeBreakpoint(Isolate* isolate, int position) {
void SetBreakpoint(WasmRunnerBase& runner, int function_index, int byte_offset,
int expected_set_byte_offset = -1) {
int func_offset =
runner.module().module()->functions[function_index].code.offset();
runner.module().GetFunctionAt(function_index)->code.offset();
int code_offset = func_offset + byte_offset;
if (expected_set_byte_offset == -1) expected_set_byte_offset = byte_offset;
Handle<WasmInstanceObject> instance = runner.module().instance_object();

View File

@ -73,17 +73,18 @@ const uint32_t kMaxGlobalsSize = 128;
// progressively added by a test. In turn, we piecemeal update the runtime
// objects, i.e. {WasmInstanceObject}, {WasmCompiledModule} and, if necessary,
// the interpreter.
class TestingModule : public ModuleEnv {
class TestingModule {
public:
explicit TestingModule(Zone* zone, WasmExecutionMode mode = kExecuteCompiled)
: isolate_(CcTest::InitIsolateOnce()),
: test_module_ptr_(&test_module_),
isolate_(CcTest::InitIsolateOnce()),
global_offset(0),
mem_start_(nullptr),
mem_size_(0),
interpreter_(nullptr) {
module_ = &test_module_;
WasmJs::Install(isolate_);
set_globals_start(global_data);
test_module_.globals_size = kMaxGlobalsSize;
memset(global_data, 0, sizeof(global_data));
memset(globals_data_, 0, sizeof(globals_data_));
instance_object_ = InitInstanceObject();
if (mode == kExecuteInterpreted) {
interpreter_ = WasmDebugInfo::SetupForTesting(instance_object_);
@ -94,8 +95,8 @@ class TestingModule : public ModuleEnv {
byte* AddMemory(uint32_t size) {
CHECK(!test_module_.has_memory);
CHECK_NULL(mem_start());
CHECK_EQ(0, mem_size());
CHECK_NULL(mem_start_);
CHECK_EQ(0, mem_size_);
DCHECK(!instance_object_->has_memory_buffer());
test_module_.has_memory = true;
bool enable_guard_regions = EnableGuardRegions() && test_module_.is_wasm();
@ -105,10 +106,10 @@ class TestingModule : public ModuleEnv {
wasm::NewArrayBuffer(isolate_, alloc_size, enable_guard_regions);
CHECK(!new_buffer.is_null());
instance_object_->set_memory_buffer(*new_buffer);
set_mem_start(reinterpret_cast<byte*>(new_buffer->backing_store()));
CHECK(size == 0 || mem_start());
memset(mem_start(), 0, size);
SetMemSizeUnchecked(size);
mem_start_ = reinterpret_cast<byte*>(new_buffer->backing_store());
mem_size_ = size;
CHECK(size == 0 || mem_start_);
memset(mem_start_, 0, size);
Handle<WasmCompiledModule> compiled_module =
handle(instance_object_->compiled_module());
Factory* factory = CcTest::i_isolate()->factory();
@ -116,14 +117,14 @@ class TestingModule : public ModuleEnv {
// if we happened to have one, but this is a reasonable inefficiencly,
// given this is test.
WasmCompiledModule::recreate_embedded_mem_size(compiled_module, factory,
mem_size());
mem_size_);
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_) {
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(); }
@ -138,37 +139,37 @@ class TestingModule : public ModuleEnv {
T* AddGlobal(
ValueType type = WasmOpcodes::ValueTypeFor(MachineTypeForC<T>())) {
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) {
test_module_.signatures.push_back(sig);
size_t size = module()->signatures.size();
size_t size = test_module_.signatures.size();
CHECK(size < 127);
return static_cast<byte>(size - 1);
}
template <typename T>
T* raw_mem_start() {
DCHECK(mem_start());
return reinterpret_cast<T*>(mem_start());
DCHECK(mem_start_);
return reinterpret_cast<T*>(mem_start_);
}
template <typename T>
T* raw_mem_end() {
DCHECK(mem_start());
return reinterpret_cast<T*>(mem_start() + mem_size());
DCHECK(mem_start_);
return reinterpret_cast<T*>(mem_start_ + mem_size_);
}
template <typename T>
T raw_mem_at(int i) {
DCHECK(mem_start());
return ReadMemory(&(reinterpret_cast<T*>(mem_start())[i]));
DCHECK(mem_start_);
return ReadMemory(&(reinterpret_cast<T*>(mem_start_)[i]));
}
template <typename T>
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>
@ -184,7 +185,7 @@ class TestingModule : public ModuleEnv {
// Zero-initialize the memory.
void BlankMemory() {
byte* raw = raw_mem_start<byte>();
memset(raw, 0, mem_size());
memset(raw, 0, mem_size_);
}
// Pseudo-randomly intialize the memory.
@ -201,12 +202,12 @@ class TestingModule : public ModuleEnv {
}
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
// structs from moving.
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(
{sig, index, 0, {0, 0}, {0, 0}, false, false});
if (name) {
@ -216,7 +217,7 @@ class TestingModule : public ModuleEnv {
}
function_code_.push_back(code);
if (interpreter_) {
interpreter_->AddFunctionForTesting(&module()->functions.back());
interpreter_->AddFunctionForTesting(&test_module_.functions.back());
}
DCHECK_LT(index, kMaxFunctions); // limited for testing.
return index;
@ -228,7 +229,7 @@ class TestingModule : public ModuleEnv {
uint32_t index = AddFunction(sig, Handle<Code>::null(), nullptr);
Handle<Code> code = CompileWasmToJSWrapper(
isolate_, jsfunc, sig, index, Handle<String>::null(),
Handle<String>::null(), module()->origin());
Handle<String>::null(), test_module_.origin());
function_code_[index] = code;
return index;
}
@ -237,11 +238,11 @@ class TestingModule : public ModuleEnv {
// Wrap the code so it can be called as a JS function.
Handle<Code> code = function_code_[index];
Handle<Code> ret_code =
compiler::CompileJSToWasmWrapper(isolate_, module(), code, index);
compiler::CompileJSToWasmWrapper(isolate_, &test_module_, code, index);
Handle<JSFunction> ret = WasmExportedFunction::New(
isolate_, instance_object(), MaybeHandle<String>(),
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);
// Add weak reference to exported functions.
@ -281,10 +282,10 @@ class TestingModule : public ModuleEnv {
void PopulateIndirectFunctionTable() {
if (interpret()) return;
// 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];
Handle<FixedArray> function_table = function_tables()[i];
Handle<FixedArray> signature_table = signature_tables()[i];
Handle<FixedArray> function_table = function_tables_[i];
Handle<FixedArray> signature_table = signature_tables_[i];
int table_size = static_cast<int>(table.values.size());
for (int j = 0; j < table_size; j++) {
WasmFunction& function = test_module_.functions[table.values[j]];
@ -319,12 +320,42 @@ class TestingModule : public ModuleEnv {
bool interpret() { return interpreter_ != nullptr; }
Isolate* isolate() { return isolate_; }
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:
WasmModule test_module_;
WasmModule* test_module_ptr_;
Isolate* isolate_;
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_;
Handle<WasmInstanceObject> instance_object_;
@ -336,7 +367,7 @@ class TestingModule : public ModuleEnv {
global_offset += size;
// limit number of globals.
CHECK_LT(global_offset, kMaxGlobalsSize);
return &module()->globals.back();
return &test_module_.globals.back();
}
Handle<WasmInstanceObject> InitInstanceObject() {
@ -344,8 +375,8 @@ class TestingModule : public ModuleEnv {
isolate_->factory()->NewStringFromOneByte({}).ToHandleChecked());
// The lifetime of the wasm module is tied to this object's, and we cannot
// rely on the mechanics of Managed<T>.
Handle<Foreign> module_wrapper =
isolate_->factory()->NewForeign(reinterpret_cast<Address>(&module_));
Handle<Foreign> module_wrapper = isolate_->factory()->NewForeign(
reinterpret_cast<Address>(&test_module_ptr_));
Handle<Script> script =
isolate_->factory()->NewScript(isolate_->factory()->empty_string());
script->set_type(Script::TYPE_WASM);
@ -354,14 +385,15 @@ class TestingModule : public ModuleEnv {
script, Handle<ByteArray>::null());
Handle<FixedArray> code_table = isolate_->factory()->NewFixedArray(0);
Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New(
isolate_, shared_module_data, code_table, *this);
Handle<WasmCompiledModule> compiled_module =
WasmCompiledModule::New(isolate_, shared_module_data, code_table,
function_tables_, signature_tables_);
// This method is called when we initialize TestEnvironment. We don't
// have a memory yet, so we won't create it here. We'll update the
// interpreter when we get a memory. We do have globals, though.
WasmCompiledModule::recreate_globals_start(
compiled_module, isolate_->factory(),
reinterpret_cast<size_t>(globals_start()));
reinterpret_cast<size_t>(globals_data_));
Handle<FixedArray> weak_exported = isolate_->factory()->NewFixedArray(0);
compiled_module->set_weak_exported_functions(weak_exported);
DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module));
@ -568,7 +600,8 @@ class WasmFunctionCompiler : private GraphAndBuilders {
}
// 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,
runtime_exception_support_);
Handle<Code> code = Compile();
@ -801,8 +834,7 @@ class WasmRunner : public WasmRunnerBase {
};
set_trap_callback_for_testing(trap_callback);
wrapper_.SetInnerCode(
module_.GetFunctionCode(functions_[0]->function_index()));
wrapper_.SetInnerCode(module_.GetFunctionCode(0));
CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
wrapper_.GetWrapperCode(), wrapper_.signature());
int32_t result = runner.Call(static_cast<void*>(&p)...,

View File

@ -14,6 +14,7 @@ function instantiate(buffer, ffi) {
}
(function BasicTest() {
print("BasicTest");
let builder = new WasmModuleBuilder();
builder.addMemory(1, 2, false);
builder.addFunction("foo", kSig_i_v)
@ -26,6 +27,7 @@ function instantiate(buffer, ffi) {
})();
(function ImportTest() {
print("ImportTest");
let builder = new WasmModuleBuilder();
var index = builder.addImport("", "print", makeSig_v_x(kWasmI32));
builder.addFunction("foo", kSig_v_v)
@ -39,6 +41,7 @@ function instantiate(buffer, ffi) {
})();
(function LocalsTest() {
print("LocalsTest");
let builder = new WasmModuleBuilder();
builder.addFunction(undefined, kSig_i_i)
.addLocals({i32_count: 1})
@ -52,6 +55,7 @@ function instantiate(buffer, ffi) {
})();
(function LocalsTest2() {
print("LocalsTest2");
// TODO(titzer): i64 only works on 64-bit platforms.
var types = [
{locals: {i32_count: 1}, type: kWasmI32},
@ -75,6 +79,7 @@ function instantiate(buffer, ffi) {
})();
(function CallTest() {
print("CallTest");
let builder = new WasmModuleBuilder();
builder.addFunction("add", kSig_i_ii)
.addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]);
@ -88,6 +93,7 @@ function instantiate(buffer, ffi) {
})();
(function IndirectCallTest() {
print("IndirectCallTest");
let builder = new WasmModuleBuilder();
builder.addFunction("add", kSig_i_ii)
.addBody([kExprGetLocal, 0, kExprGetLocal, 1, kExprI32Add]);
@ -104,6 +110,7 @@ function instantiate(buffer, ffi) {
})();
(function DataSegmentTest() {
print("DataSegmentTest");
let builder = new WasmModuleBuilder();
builder.addMemory(1, 1, false);
builder.addFunction("load", kSig_i_i)
@ -118,6 +125,7 @@ function instantiate(buffer, ffi) {
(function BasicTestWithUint8Array() {
print("BasicTestWithUint8Array");
let builder = new WasmModuleBuilder();
builder.addMemory(1, 2, false);
builder.addFunction("foo", kSig_i_v)
@ -144,6 +152,7 @@ function instantiate(buffer, ffi) {
})();
(function ImportTestTwoLevel() {
print("ImportTestTwoLevel");
let builder = new WasmModuleBuilder();
var index = builder.addImport("mod", "print", makeSig_v_x(kWasmI32));
builder.addFunction("foo", kSig_v_v)

View File

@ -90,7 +90,7 @@ class FunctionBodyDecoderTest : public TestWithZone {
FunctionBodyDecoderTest() : module(nullptr), local_decls(zone()) {}
TestSignatures sigs;
ModuleEnv* module;
WasmModule* module;
LocalDeclEncoder local_decls;
void AddLocals(ValueType type, uint32_t count) {
@ -121,9 +121,8 @@ class FunctionBodyDecoderTest : public TestWithZone {
PrepareBytecode(&start, &end);
// Verify the code.
DecodeResult result = VerifyWasmCode(
zone()->allocator(), module == nullptr ? nullptr : module->module(),
sig, start, end);
DecodeResult result =
VerifyWasmCode(zone()->allocator(), module, sig, start, end);
uint32_t pc = result.error_offset();
std::ostringstream str;
@ -191,10 +190,9 @@ constexpr size_t kMaxByteSizedLeb128 = 127;
// A helper for tests that require a module environment for functions,
// globals, or memories.
class TestModuleEnv : public ModuleEnv {
class TestModuleBuilder {
public:
explicit TestModuleEnv(ModuleOrigin origin = kWasmOrigin) {
module_ = &mod;
explicit TestModuleBuilder(ModuleOrigin origin = kWasmOrigin) {
mod.set_origin(origin);
}
byte AddGlobal(ValueType type, bool mutability = true) {
@ -237,6 +235,8 @@ class TestModuleEnv : public ModuleEnv {
void InitializeFunctionTable() { mod.function_tables.emplace_back(); }
WasmModule* module() { return &mod; }
private:
WasmModule mod;
};
@ -1089,9 +1089,9 @@ TEST_F(FunctionBodyDecoderTest, TypeConversions) {
}
TEST_F(FunctionBodyDecoderTest, MacrosStmt) {
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
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),
WASM_I32V_1(40)));
@ -1228,18 +1228,18 @@ TEST_F(FunctionBodyDecoderTest, AllSimpleExpressions) {
}
TEST_F(FunctionBodyDecoderTest, MemorySize) {
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
byte code[] = {kExprMemorySize, 0};
EXPECT_VERIFIES_C(i_i, code);
EXPECT_FAILURE_C(f_ff, code);
}
TEST_F(FunctionBodyDecoderTest, LoadMemOffset) {
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
for (int offset = 0; offset < 128; offset += 7) {
byte code[] = {kExprI32Const, 0, kExprI32LoadMem, ZERO_ALIGNMENT,
static_cast<byte>(offset)};
@ -1248,9 +1248,9 @@ TEST_F(FunctionBodyDecoderTest, LoadMemOffset) {
}
TEST_F(FunctionBodyDecoderTest, LoadMemAlignment) {
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
struct {
WasmOpcode instruction;
uint32_t maximum_aligment;
@ -1285,9 +1285,9 @@ TEST_F(FunctionBodyDecoderTest, LoadMemAlignment) {
}
TEST_F(FunctionBodyDecoderTest, StoreMemOffset) {
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
for (byte offset = 0; offset < 128; offset += 7) {
byte code[] = {WASM_STORE_MEM_OFFSET(MachineType::Int32(), offset,
WASM_ZERO, WASM_ZERO)};
@ -1296,9 +1296,9 @@ TEST_F(FunctionBodyDecoderTest, StoreMemOffset) {
}
TEST_F(FunctionBodyDecoderTest, StoreMemOffset_void) {
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
EXPECT_FAILURE(i_i, WASM_STORE_MEM_OFFSET(MachineType::Int32(), 0, WASM_ZERO,
WASM_ZERO));
}
@ -1314,9 +1314,9 @@ TEST_F(FunctionBodyDecoderTest, StoreMemOffset_void) {
#define VARINT4(x) BYTE0(x) | 0x80, BYTE1(x) | 0x80, BYTE2(x) | 0x80, BYTE3(x)
TEST_F(FunctionBodyDecoderTest, LoadMemOffset_varint) {
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
EXPECT_VERIFIES(i_i, WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT,
VARINT1(0x45));
EXPECT_VERIFIES(i_i, WASM_ZERO, kExprI32LoadMem, ZERO_ALIGNMENT,
@ -1328,9 +1328,9 @@ TEST_F(FunctionBodyDecoderTest, LoadMemOffset_varint) {
}
TEST_F(FunctionBodyDecoderTest, StoreMemOffset_varint) {
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
EXPECT_VERIFIES(v_i, WASM_ZERO, WASM_ZERO, kExprI32StoreMem, ZERO_ALIGNMENT,
VARINT1(0x33));
EXPECT_VERIFIES(v_i, WASM_ZERO, WASM_ZERO, kExprI32StoreMem, ZERO_ALIGNMENT,
@ -1342,9 +1342,9 @@ TEST_F(FunctionBodyDecoderTest, StoreMemOffset_varint) {
}
TEST_F(FunctionBodyDecoderTest, AllLoadMemCombinations) {
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
for (size_t i = 0; i < arraysize(kValueTypes); i++) {
ValueType local_type = kValueTypes[i];
for (size_t j = 0; j < arraysize(machineTypes); j++) {
@ -1361,9 +1361,9 @@ TEST_F(FunctionBodyDecoderTest, AllLoadMemCombinations) {
}
TEST_F(FunctionBodyDecoderTest, AllStoreMemCombinations) {
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
for (size_t i = 0; i < arraysize(kValueTypes); i++) {
ValueType local_type = kValueTypes[i];
for (size_t j = 0; j < arraysize(machineTypes); j++) {
@ -1381,12 +1381,12 @@ TEST_F(FunctionBodyDecoderTest, AllStoreMemCombinations) {
TEST_F(FunctionBodyDecoderTest, SimpleCalls) {
FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
module_env.AddFunction(sigs.i_v());
module_env.AddFunction(sigs.i_i());
module_env.AddFunction(sigs.i_ii());
builder.AddFunction(sigs.i_v());
builder.AddFunction(sigs.i_i());
builder.AddFunction(sigs.i_ii());
EXPECT_VERIFIES_S(sig, WASM_CALL_FUNCTION0(0));
EXPECT_VERIFIES_S(sig, WASM_CALL_FUNCTION(1, WASM_I32V_1(27)));
@ -1396,12 +1396,12 @@ TEST_F(FunctionBodyDecoderTest, SimpleCalls) {
TEST_F(FunctionBodyDecoderTest, CallsWithTooFewArguments) {
FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
module_env.AddFunction(sigs.i_i());
module_env.AddFunction(sigs.i_ii());
module_env.AddFunction(sigs.f_ff());
builder.AddFunction(sigs.i_i());
builder.AddFunction(sigs.i_ii());
builder.AddFunction(sigs.f_ff());
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION0(0));
EXPECT_FAILURE_S(sig, WASM_CALL_FUNCTION(1, WASM_ZERO));
@ -1410,10 +1410,10 @@ TEST_F(FunctionBodyDecoderTest, CallsWithTooFewArguments) {
TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs2) {
FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
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_F32(17.1)));
@ -1422,16 +1422,16 @@ TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs2) {
TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs3) {
FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
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_I64V_1(27)));
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_I64V_1(16)));
@ -1443,11 +1443,11 @@ TEST_F(FunctionBodyDecoderTest, MultiReturn) {
ValueType storage[] = {kWasmI32, kWasmI32};
FunctionSig sig_ii_v(2, 0, storage);
FunctionSig sig_v_ii(0, 2, storage);
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
module_env.AddFunction(&sig_v_ii);
module_env.AddFunction(&sig_ii_v);
builder.AddFunction(&sig_v_ii);
builder.AddFunction(&sig_ii_v);
EXPECT_VERIFIES_S(&sig_ii_v, WASM_CALL_FUNCTION0(1));
EXPECT_VERIFIES(v_v, WASM_CALL_FUNCTION0(1), WASM_DROP, WASM_DROP);
@ -1465,9 +1465,9 @@ TEST_F(FunctionBodyDecoderTest, MultiReturnType) {
ValueType storage_cd[] = {kValueTypes[c], kValueTypes[d]};
FunctionSig sig_cd_v(2, 0, storage_cd);
TestModuleEnv module_env;
module = &module_env;
module_env.AddFunction(&sig_cd_v);
TestModuleBuilder builder;
module = builder.module();
builder.AddFunction(&sig_cd_v);
EXPECT_VERIFIES_S(&sig_cd_v, WASM_CALL_FUNCTION0(0));
@ -1484,13 +1484,13 @@ TEST_F(FunctionBodyDecoderTest, MultiReturnType) {
TEST_F(FunctionBodyDecoderTest, SimpleIndirectCalls) {
FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env;
module_env.InitializeFunctionTable();
module = &module_env;
TestModuleBuilder builder;
builder.InitializeFunctionTable();
module = builder.module();
byte f0 = module_env.AddSignature(sigs.i_v());
byte f1 = module_env.AddSignature(sigs.i_i());
byte f2 = module_env.AddSignature(sigs.i_ii());
byte f0 = builder.AddSignature(sigs.i_v());
byte f1 = builder.AddSignature(sigs.i_i());
byte f2 = builder.AddSignature(sigs.i_ii());
EXPECT_VERIFIES_S(sig, WASM_CALL_INDIRECT0(f0, WASM_ZERO));
EXPECT_VERIFIES_S(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I32V_1(22)));
@ -1500,16 +1500,16 @@ TEST_F(FunctionBodyDecoderTest, SimpleIndirectCalls) {
TEST_F(FunctionBodyDecoderTest, IndirectCallsOutOfBounds) {
FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env;
module_env.InitializeFunctionTable();
module = &module_env;
TestModuleBuilder builder;
builder.InitializeFunctionTable();
module = builder.module();
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_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_FAILURE_S(sig, WASM_CALL_INDIRECT1(2, WASM_ZERO, WASM_I32V_1(27)));
@ -1517,11 +1517,11 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsOutOfBounds) {
TEST_F(FunctionBodyDecoderTest, IndirectCallsWithMismatchedSigs3) {
FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env;
module_env.InitializeFunctionTable();
module = &module_env;
TestModuleBuilder builder;
builder.InitializeFunctionTable();
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_I64V_1(27)));
@ -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_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_I64V_1(16)));
@ -1540,12 +1540,12 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsWithMismatchedSigs3) {
TEST_F(FunctionBodyDecoderTest, IndirectCallsWithoutTableCrash) {
FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
byte f0 = module_env.AddSignature(sigs.i_v());
byte f1 = module_env.AddSignature(sigs.i_i());
byte f2 = module_env.AddSignature(sigs.i_ii());
byte f0 = builder.AddSignature(sigs.i_v());
byte f1 = builder.AddSignature(sigs.i_i());
byte f2 = builder.AddSignature(sigs.i_ii());
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT0(f0, WASM_ZERO));
EXPECT_FAILURE_S(sig, WASM_CALL_INDIRECT1(f1, WASM_ZERO, WASM_I32V_1(22)));
@ -1555,12 +1555,12 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsWithoutTableCrash) {
TEST_F(FunctionBodyDecoderTest, SimpleImportCalls) {
FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
byte f0 = module_env.AddImport(sigs.i_v());
byte f1 = module_env.AddImport(sigs.i_i());
byte f2 = module_env.AddImport(sigs.i_ii());
byte f0 = builder.AddImport(sigs.i_v());
byte f1 = builder.AddImport(sigs.i_i());
byte f2 = builder.AddImport(sigs.i_ii());
EXPECT_VERIFIES_S(sig, WASM_CALL_FUNCTION0(f0));
EXPECT_VERIFIES_S(sig, WASM_CALL_FUNCTION(f1, WASM_I32V_1(22)));
@ -1570,17 +1570,17 @@ TEST_F(FunctionBodyDecoderTest, SimpleImportCalls) {
TEST_F(FunctionBodyDecoderTest, ImportCallsWithMismatchedSigs3) {
FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
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_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_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_FUNCTION(f1, WASM_I32V_1(16)));
@ -1590,10 +1590,10 @@ TEST_F(FunctionBodyDecoderTest, ImportCallsWithMismatchedSigs3) {
TEST_F(FunctionBodyDecoderTest, Int32Globals) {
FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
module_env.AddGlobal(kWasmI32);
builder.AddGlobal(kWasmI32);
EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(0));
EXPECT_FAILURE_S(sig, WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0)));
@ -1602,11 +1602,11 @@ TEST_F(FunctionBodyDecoderTest, Int32Globals) {
TEST_F(FunctionBodyDecoderTest, ImmutableGlobal) {
FunctionSig* sig = sigs.v_v();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
uint32_t g0 = module_env.AddGlobal(kWasmI32, true);
uint32_t g1 = module_env.AddGlobal(kWasmI32, false);
uint32_t g0 = builder.AddGlobal(kWasmI32, true);
uint32_t g1 = builder.AddGlobal(kWasmI32, false);
EXPECT_VERIFIES_S(sig, WASM_SET_GLOBAL(g0, WASM_ZERO));
EXPECT_FAILURE_S(sig, WASM_SET_GLOBAL(g1, WASM_ZERO));
@ -1614,13 +1614,13 @@ TEST_F(FunctionBodyDecoderTest, ImmutableGlobal) {
TEST_F(FunctionBodyDecoderTest, Int32Globals_fail) {
FunctionSig* sig = sigs.i_i();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
module_env.AddGlobal(kWasmI64);
module_env.AddGlobal(kWasmI64);
module_env.AddGlobal(kWasmF32);
module_env.AddGlobal(kWasmF64);
builder.AddGlobal(kWasmI64);
builder.AddGlobal(kWasmI64);
builder.AddGlobal(kWasmF32);
builder.AddGlobal(kWasmF64);
EXPECT_FAILURE_S(sig, WASM_GET_GLOBAL(0));
EXPECT_FAILURE_S(sig, WASM_GET_GLOBAL(1));
@ -1635,11 +1635,11 @@ TEST_F(FunctionBodyDecoderTest, Int32Globals_fail) {
TEST_F(FunctionBodyDecoderTest, Int64Globals) {
FunctionSig* sig = sigs.l_l();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
module_env.AddGlobal(kWasmI64);
module_env.AddGlobal(kWasmI64);
builder.AddGlobal(kWasmI64);
builder.AddGlobal(kWasmI64);
EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(0));
EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(1));
@ -1652,10 +1652,10 @@ TEST_F(FunctionBodyDecoderTest, Int64Globals) {
TEST_F(FunctionBodyDecoderTest, Float32Globals) {
FunctionSig* sig = sigs.f_ff();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
module_env.AddGlobal(kWasmF32);
builder.AddGlobal(kWasmF32);
EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(0));
EXPECT_VERIFIES_S(sig, WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0)),
@ -1664,10 +1664,10 @@ TEST_F(FunctionBodyDecoderTest, Float32Globals) {
TEST_F(FunctionBodyDecoderTest, Float64Globals) {
FunctionSig* sig = sigs.d_dd();
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
module_env.AddGlobal(kWasmF64);
builder.AddGlobal(kWasmF64);
EXPECT_VERIFIES_S(sig, WASM_GET_GLOBAL(0));
EXPECT_VERIFIES_S(sig, WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0)),
@ -1680,9 +1680,9 @@ TEST_F(FunctionBodyDecoderTest, AllGetGlobalCombinations) {
for (size_t j = 0; j < arraysize(kValueTypes); j++) {
ValueType global_type = kValueTypes[j];
FunctionSig sig(1, 0, &local_type);
TestModuleEnv module_env;
module = &module_env;
module_env.AddGlobal(global_type);
TestModuleBuilder builder;
module = builder.module();
builder.AddGlobal(global_type);
if (local_type == global_type) {
EXPECT_VERIFIES_S(&sig, WASM_GET_GLOBAL(0));
} else {
@ -1698,9 +1698,9 @@ TEST_F(FunctionBodyDecoderTest, AllSetGlobalCombinations) {
for (size_t j = 0; j < arraysize(kValueTypes); j++) {
ValueType global_type = kValueTypes[j];
FunctionSig sig(0, 1, &local_type);
TestModuleEnv module_env;
module = &module_env;
module_env.AddGlobal(global_type);
TestModuleBuilder builder;
module = builder.module();
builder.AddGlobal(global_type);
if (local_type == global_type) {
EXPECT_VERIFIES_S(&sig, WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0)));
} else {
@ -1711,9 +1711,9 @@ TEST_F(FunctionBodyDecoderTest, AllSetGlobalCombinations) {
}
TEST_F(FunctionBodyDecoderTest, WasmGrowMemory) {
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
byte code[] = {WASM_GET_LOCAL(0), kExprGrowMemory, 0};
EXPECT_VERIFIES_C(i_i, code);
@ -1721,9 +1721,9 @@ TEST_F(FunctionBodyDecoderTest, WasmGrowMemory) {
}
TEST_F(FunctionBodyDecoderTest, AsmJsGrowMemory) {
TestModuleEnv module_env(kAsmJsOrigin);
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder(kAsmJsOrigin);
module = builder.module();
builder.InitializeMemory();
byte code[] = {WASM_GET_LOCAL(0), kExprGrowMemory, 0};
EXPECT_FAILURE_C(i_i, code);
@ -1753,18 +1753,18 @@ TEST_F(FunctionBodyDecoderTest, AsmJsBinOpsCheckOrigin) {
};
{
TestModuleEnv module_env(kAsmJsOrigin);
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder(kAsmJsOrigin);
module = builder.module();
builder.InitializeMemory();
for (size_t i = 0; i < arraysize(AsmJsBinOps); i++) {
TestBinop(AsmJsBinOps[i].op, AsmJsBinOps[i].sig);
}
}
{
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
for (size_t i = 0; i < arraysize(AsmJsBinOps); i++) {
byte code[] = {
WASM_BINOP(AsmJsBinOps[i].op, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
@ -1801,18 +1801,18 @@ TEST_F(FunctionBodyDecoderTest, AsmJsUnOpsCheckOrigin) {
{kExprI32AsmjsSConvertF64, sigs.i_d()},
{kExprI32AsmjsUConvertF64, sigs.i_d()}};
{
TestModuleEnv module_env(kAsmJsOrigin);
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder(kAsmJsOrigin);
module = builder.module();
builder.InitializeMemory();
for (size_t i = 0; i < arraysize(AsmJsUnOps); i++) {
TestUnop(AsmJsUnOps[i].op, AsmJsUnOps[i].sig);
}
}
{
TestModuleEnv module_env;
module = &module_env;
module_env.InitializeMemory();
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
for (size_t i = 0; i < arraysize(AsmJsUnOps); i++) {
byte code[] = {WASM_UNOP(AsmJsUnOps[i].op, WASM_GET_LOCAL(0))};
EXPECT_FAILURE_SC(AsmJsUnOps[i].sig, code);
@ -2241,11 +2241,11 @@ TEST_F(FunctionBodyDecoderTest, Select_TypeCheck) {
TEST_F(FunctionBodyDecoderTest, Throw) {
EXPERIMENTAL_FLAG_SCOPE(eh);
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
module_env.AddException(sigs.v_v());
module_env.AddException(sigs.v_i());
builder.AddException(sigs.v_v());
builder.AddException(sigs.v_i());
AddLocals(kWasmI32, 1);
EXPECT_VERIFIES(v_v, kExprThrow, 0);
@ -2262,11 +2262,11 @@ TEST_F(FunctionBodyDecoderTest, Throw) {
TEST_F(FunctionBodyDecoderTest, ThrowUnreachable) {
// TODO(titzer): unreachable code after throw should validate.
EXPERIMENTAL_FLAG_SCOPE(eh);
TestModuleEnv module_env;
module = &module_env;
TestModuleBuilder builder;
module = builder.module();
module_env.AddException(sigs.v_v());
module_env.AddException(sigs.v_i());
builder.AddException(sigs.v_v());
builder.AddException(sigs.v_i());
AddLocals(kWasmI32, 1);
EXPECT_VERIFIES(i_i, kExprThrow, 0, WASM_GET_LOCAL(0));
@ -2281,10 +2281,10 @@ TEST_F(FunctionBodyDecoderTest, ThrowUnreachable) {
TEST_F(FunctionBodyDecoderTest, TryCatch) {
EXPERIMENTAL_FLAG_SCOPE(eh);
TestModuleEnv module_env;
module = &module_env;
module_env.AddException(sigs.v_v());
module_env.AddException(sigs.v_v());
TestModuleBuilder builder;
module = builder.module();
builder.AddException(sigs.v_v());
builder.AddException(sigs.v_v());
// TODO(kschimpf): Need to fix catch to use declared exception.
EXPECT_VERIFIES(v_v, WASM_TRY_OP, WASM_CATCH(0), kExprEnd);

View File

@ -985,16 +985,11 @@ TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) {
class WasmFunctionVerifyTest : public TestWithIsolateAndZone {
public:
WasmFunctionVerifyTest() : env(&module, Handle<Code>::null()) {}
WasmFunctionVerifyTest() {}
virtual ~WasmFunctionVerifyTest() {}
const ModuleEnv* get_env() const { return &env; }
Vector<const byte> get_bytes() const { return bytes; }
private:
WasmModule module;
Vector<const byte> bytes;
ModuleEnv env;
DISALLOW_COPY_AND_ASSIGN(WasmFunctionVerifyTest);
};
@ -1013,9 +1008,8 @@ TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
kExprEnd // body
};
FunctionResult result =
SyncDecodeWasmFunction(isolate(), zone(), get_bytes(),
get_env()->module(), data, data + sizeof(data));
FunctionResult result = SyncDecodeWasmFunction(
isolate(), zone(), bytes, &module, data, data + sizeof(data));
EXPECT_OK(result);
if (result.val && result.ok()) {