[wasm] Tear apart the WasmCompilationUnit

This refactoring is a big step towards separating Turbofan-related code
from backend independent code. This will allow us to include way less
headers from "src/compiler" at various places.

The {WasmCompilationUnit} contained information for Turbofan
compilation, and for Liftoff compilation. This CL tears this apart, such
that {WasmCompilationUnit} holds backend-independent information, plus
a pointer to either {LiftoffCompilationUnit} or
{TurbofanWasmCompilationUnit}. These pointers are opaque, so that
{function-compiler.h}, defining {WasmCompilationUnit}, does not need to
include any Turbofan specific or Liftoff specific headers.

R=ahaas@chromium.org, titzer@chromium.org, mstarzinger@chromium.org

Bug: v8:7570, v8:6600
Change-Id: I024c9a23508ee1b4b3cbe1d068c8e785d732daca
Reviewed-on: https://chromium-review.googlesource.com/1016640
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52684}
This commit is contained in:
Clemens Hammacher 2018-04-19 12:16:37 +02:00 committed by Commit Bot
parent a0c59cbfd3
commit 0da7ec58c9
15 changed files with 587 additions and 476 deletions

View File

@ -2304,6 +2304,7 @@ v8_source_set("v8_base") {
"src/wasm/baseline/liftoff-assembler.cc",
"src/wasm/baseline/liftoff-assembler.h",
"src/wasm/baseline/liftoff-compiler.cc",
"src/wasm/baseline/liftoff-compiler.h",
"src/wasm/baseline/liftoff-register.h",
"src/wasm/compilation-manager.cc",
"src/wasm/compilation-manager.h",
@ -2311,6 +2312,8 @@ v8_source_set("v8_base") {
"src/wasm/function-body-decoder-impl.h",
"src/wasm/function-body-decoder.cc",
"src/wasm/function-body-decoder.h",
"src/wasm/function-compiler.cc",
"src/wasm/function-compiler.h",
"src/wasm/leb-helper.h",
"src/wasm/local-decl-encoder.cc",
"src/wasm/local-decl-encoder.h",

View File

@ -36,6 +36,7 @@
#include "src/macro-assembler-inl.h"
#include "src/trap-handler/trap-handler.h"
#include "src/wasm/function-body-decoder.h"
#include "src/wasm/function-compiler.h"
#include "src/wasm/memory-tracing.h"
#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-limits.h"
@ -97,10 +98,10 @@ bool ContainsSimd(wasm::FunctionSig* sig) {
} // namespace
WasmGraphBuilder::WasmGraphBuilder(
ModuleEnv* env, Zone* zone, JSGraph* jsgraph, Handle<Code> centry_stub,
Handle<Oddball> anyref_null, wasm::FunctionSig* sig,
compiler::SourcePositionTable* source_position_table,
RuntimeExceptionSupport exception_support)
wasm::ModuleEnv* env, Zone* zone, JSGraph* jsgraph,
Handle<Code> centry_stub, Handle<Oddball> anyref_null,
wasm::FunctionSig* sig,
compiler::SourcePositionTable* source_position_table)
: zone_(zone),
jsgraph_(jsgraph),
centry_stub_node_(jsgraph_->HeapConstant(centry_stub)),
@ -110,7 +111,6 @@ WasmGraphBuilder::WasmGraphBuilder(
cur_bufsize_(kDefaultBufferSize),
has_simd_(ContainsSimd(sig)),
untrusted_code_mitigations_(FLAG_untrusted_code_mitigations),
runtime_exception_support_(exception_support),
sig_(sig),
source_position_table_(source_position_table) {
DCHECK_IMPLIES(use_trap_handler(), trap_handler::IsTrapHandlerEnabled());
@ -221,7 +221,7 @@ void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position,
Node** effect, Node** control) {
// TODO(mtrofin): "!env_" happens when we generate a wrapper.
// We should factor wrappers separately from wasm codegen.
if (FLAG_wasm_no_stack_checks || !env_ || !runtime_exception_support_) {
if (FLAG_wasm_no_stack_checks || !env_ || !env_->runtime_exception_support) {
return;
}
if (effect == nullptr) effect = effect_;
@ -878,7 +878,9 @@ Node* WasmGraphBuilder::BranchExpectFalse(Node* cond, Node** true_node,
}
Builtins::Name WasmGraphBuilder::GetBuiltinIdForTrap(wasm::TrapReason reason) {
if (runtime_exception_support_ == kNoRuntimeExceptionSupport) {
// TODO(wasm): "!env_" should not happen when compiling an actual wasm
// function.
if (!env_ || !env_->runtime_exception_support) {
// We use Builtins::builtin_count as a marker to tell the code generator
// to generate a call to a testing c-function instead of a runtime
// function. This code should only be called from a cctest.
@ -4645,7 +4647,7 @@ void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
Handle<WeakCell> weak_instance,
wasm::WasmCode* wasm_code, uint32_t index,
bool use_trap_handler) {
wasm::UseTrapHandler use_trap_handler) {
const wasm::WasmFunction* func = &module->functions[index];
//----------------------------------------------------------------------------
@ -4664,7 +4666,7 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
Node* effect = nullptr;
// TODO(titzer): compile JS to WASM wrappers without a {ModuleEnv}.
ModuleEnv env(module, use_trap_handler);
wasm::ModuleEnv env(module, use_trap_handler, wasm::kRuntimeExceptionSupport);
WasmGraphBuilder builder(&env, &zone, &jsgraph,
CEntryStub(isolate, 1).GetCode(),
@ -4750,7 +4752,7 @@ void ValidateImportWrapperReferencesImmovables(Handle<Code> wrapper) {
Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
wasm::FunctionSig* sig, uint32_t index,
wasm::ModuleOrigin origin,
bool use_trap_handler) {
wasm::UseTrapHandler use_trap_handler) {
//----------------------------------------------------------------------------
// Create the Graph
//----------------------------------------------------------------------------
@ -4770,7 +4772,10 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
origin == wasm::kAsmJsOrigin ? new (&zone) SourcePositionTable(&graph)
: nullptr;
ModuleEnv env(nullptr, use_trap_handler);
// TODO(wasm): Generate wasm-to-js wrappers without a ModuleEnv.
wasm::ModuleEnv env(nullptr, use_trap_handler,
wasm::kRuntimeExceptionSupport);
WasmGraphBuilder builder(
&env, &zone, &jsgraph, CEntryStub(isolate, 1).GetCode(),
isolate->factory()->null_value(), sig, source_position_table);
@ -4948,7 +4953,7 @@ Handle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
}
WasmCompilationData::WasmCompilationData(
RuntimeExceptionSupport runtime_exception_support)
wasm::RuntimeExceptionSupport runtime_exception_support)
: protected_instructions_(
new std::vector<trap_handler::ProtectedInstructionData>()),
runtime_exception_support_(runtime_exception_support) {}
@ -4964,7 +4969,7 @@ int FixedArrayOffsetMinusTag(uint32_t index) {
return access.offset - access.tag();
}
SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
SourcePositionTable* TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
double* decode_ms) {
base::ElapsedTimer decode_timer;
if (FLAG_trace_wasm_decode_time) {
@ -4973,20 +4978,20 @@ SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
// Create a TF graph during decoding.
SourcePositionTable* source_position_table =
new (tf_.jsgraph_->zone()) SourcePositionTable(tf_.jsgraph_->graph());
new (jsgraph_->zone()) SourcePositionTable(jsgraph_->graph());
// We get the handle for {null_value()} directly from the isolate although we
// are on a background task because the handle is stored in the isolate
// anyways, and it is immortal and immovable.
WasmGraphBuilder builder(env_, tf_.jsgraph_->zone(), tf_.jsgraph_,
centry_stub_, isolate_->factory()->null_value(),
func_body_.sig, source_position_table,
wasm_compilation_data_.runtime_exception_support());
tf_.graph_construction_result_ =
wasm::BuildTFGraph(isolate_->allocator(), &builder, func_body_);
if (tf_.graph_construction_result_.failed()) {
WasmGraphBuilder builder(wasm_unit_->env_, jsgraph_->zone(), jsgraph_,
wasm_unit_->centry_stub_,
wasm_unit_->isolate_->factory()->null_value(),
wasm_unit_->func_body_.sig, source_position_table);
graph_construction_result_ = wasm::BuildTFGraph(
wasm_unit_->isolate_->allocator(), &builder, wasm_unit_->func_body_);
if (graph_construction_result_.failed()) {
if (FLAG_trace_wasm_compiler) {
OFStream os(stdout);
os << "Compilation failed: " << tf_.graph_construction_result_.error_msg()
os << "Compilation failed: " << graph_construction_result_.error_msg()
<< std::endl;
}
return nullptr;
@ -4995,14 +5000,14 @@ SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
builder.LowerInt64();
if (builder.has_simd() &&
(!CpuFeatures::SupportsWasmSimd128() || lower_simd_)) {
SimdScalarLowering(tf_.jsgraph_, func_body_.sig).LowerGraph();
(!CpuFeatures::SupportsWasmSimd128() || wasm_unit_->lower_simd_)) {
SimdScalarLowering(jsgraph_, wasm_unit_->func_body_.sig).LowerGraph();
}
if (func_index_ >= FLAG_trace_wasm_ast_start &&
func_index_ < FLAG_trace_wasm_ast_end) {
PrintRawWasmCode(isolate_->allocator(), func_body_, env_->module,
wasm::kPrintLocals);
if (wasm_unit_->func_index_ >= FLAG_trace_wasm_ast_start &&
wasm_unit_->func_index_ < FLAG_trace_wasm_ast_end) {
PrintRawWasmCode(wasm_unit_->isolate_->allocator(), wasm_unit_->func_body_,
wasm_unit_->env_->module, wasm::kPrintLocals);
}
if (FLAG_trace_wasm_decode_time) {
*decode_ms = decode_timer.Elapsed().InMillisecondsF();
@ -5032,88 +5037,15 @@ Vector<const char> GetDebugName(Zone* zone, wasm::WasmName name, int index) {
} // namespace
// static
WasmCompilationUnit::CompilationMode
WasmCompilationUnit::GetDefaultCompilationMode() {
return FLAG_liftoff ? WasmCompilationUnit::CompilationMode::kLiftoff
: WasmCompilationUnit::CompilationMode::kTurbofan;
}
WasmCompilationUnit::WasmCompilationUnit(
Isolate* isolate, ModuleEnv* env, wasm::NativeModule* native_module,
wasm::FunctionBody body, wasm::WasmName name, int index,
Handle<Code> centry_stub, CompilationMode mode, Counters* counters,
RuntimeExceptionSupport exception_support, bool lower_simd)
: isolate_(isolate),
env_(env),
func_body_(body),
func_name_(name),
counters_(counters ? counters : isolate->counters()),
centry_stub_(centry_stub),
func_index_(index),
native_module_(native_module),
lower_simd_(lower_simd),
wasm_compilation_data_(exception_support),
mode_(mode) {
switch (mode_) {
case WasmCompilationUnit::CompilationMode::kLiftoff:
new (&liftoff_) LiftoffData(isolate);
break;
case WasmCompilationUnit::CompilationMode::kTurbofan:
new (&tf_) TurbofanData();
break;
}
}
WasmCompilationUnit::~WasmCompilationUnit() {
switch (mode_) {
case WasmCompilationUnit::CompilationMode::kLiftoff:
liftoff_.~LiftoffData();
break;
case WasmCompilationUnit::CompilationMode::kTurbofan:
tf_.~TurbofanData();
break;
}
}
void WasmCompilationUnit::ExecuteCompilation() {
auto size_histogram = env_->module->is_wasm()
? counters()->wasm_wasm_function_size_bytes()
: counters()->wasm_asm_function_size_bytes();
size_histogram->AddSample(
static_cast<int>(func_body_.end - func_body_.start));
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);
if (FLAG_trace_wasm_compiler) {
PrintF("Compiling wasm function %d\n\n", func_index_);
}
switch (mode_) {
case WasmCompilationUnit::CompilationMode::kLiftoff:
if (ExecuteLiftoffCompilation()) break;
// Otherwise, fall back to turbofan.
liftoff_.~LiftoffData();
mode_ = WasmCompilationUnit::CompilationMode::kTurbofan;
new (&tf_) TurbofanData();
V8_FALLTHROUGH;
case WasmCompilationUnit::CompilationMode::kTurbofan:
ExecuteTurbofanCompilation();
break;
}
}
void WasmCompilationUnit::ExecuteTurbofanCompilation() {
void TurbofanWasmCompilationUnit::ExecuteCompilation() {
double decode_ms = 0;
size_t node_count = 0;
// Scope for the {graph_zone}.
{
Zone graph_zone(isolate_->allocator(), ZONE_NAME);
tf_.jsgraph_ = new (&graph_zone) JSGraph(
isolate_, new (&graph_zone) Graph(&graph_zone),
Zone graph_zone(wasm_unit_->isolate_->allocator(), ZONE_NAME);
jsgraph_ = new (&graph_zone) JSGraph(
wasm_unit_->isolate_, new (&graph_zone) Graph(&graph_zone),
new (&graph_zone) CommonOperatorBuilder(&graph_zone), nullptr, nullptr,
new (&graph_zone) MachineOperatorBuilder(
&graph_zone, MachineType::PointerRepresentation(),
@ -5122,91 +5054,75 @@ void WasmCompilationUnit::ExecuteTurbofanCompilation() {
SourcePositionTable* source_positions =
BuildGraphForWasmFunction(&decode_ms);
if (tf_.graph_construction_result_.failed()) {
if (graph_construction_result_.failed()) {
ok_ = false;
return;
}
base::ElapsedTimer pipeline_timer;
if (FLAG_trace_wasm_decode_time) {
node_count = tf_.jsgraph_->graph()->NodeCount();
node_count = jsgraph_->graph()->NodeCount();
pipeline_timer.Start();
}
tf_.compilation_zone_.reset(new Zone(isolate_->allocator(), ZONE_NAME));
compilation_zone_.reset(
new Zone(wasm_unit_->isolate_->allocator(), ZONE_NAME));
// Run the compiler pipeline to generate machine code.
auto call_descriptor =
GetWasmCallDescriptor(tf_.compilation_zone_.get(), func_body_.sig);
if (tf_.jsgraph_->machine()->Is32()) {
call_descriptor = GetI32WasmCallDescriptor(tf_.compilation_zone_.get(),
call_descriptor);
auto call_descriptor = GetWasmCallDescriptor(compilation_zone_.get(),
wasm_unit_->func_body_.sig);
if (jsgraph_->machine()->Is32()) {
call_descriptor =
GetI32WasmCallDescriptor(compilation_zone_.get(), call_descriptor);
}
tf_.info_.reset(new OptimizedCompilationInfo(
GetDebugName(tf_.compilation_zone_.get(), func_name_, func_index_),
tf_.compilation_zone_.get(), Code::WASM_FUNCTION));
info_.reset(new OptimizedCompilationInfo(
GetDebugName(compilation_zone_.get(), wasm_unit_->func_name_,
wasm_unit_->func_index_),
compilation_zone_.get(), Code::WASM_FUNCTION));
tf_.job_.reset(Pipeline::NewWasmCompilationJob(
tf_.info_.get(), isolate_, tf_.jsgraph_, call_descriptor,
source_positions, &wasm_compilation_data_, env_->module->origin()));
ok_ = tf_.job_->ExecuteJob() == CompilationJob::SUCCEEDED;
job_.reset(Pipeline::NewWasmCompilationJob(
info_.get(), wasm_unit_->isolate_, jsgraph_, call_descriptor,
source_positions, &wasm_compilation_data_,
wasm_unit_->env_->module->origin()));
ok_ = job_->ExecuteJob() == CompilationJob::SUCCEEDED;
// TODO(bradnelson): Improve histogram handling of size_t.
counters()->wasm_compile_function_peak_memory_bytes()->AddSample(
static_cast<int>(tf_.jsgraph_->graph()->zone()->allocation_size()));
wasm_unit_->counters_->wasm_compile_function_peak_memory_bytes()->AddSample(
static_cast<int>(jsgraph_->graph()->zone()->allocation_size()));
if (FLAG_trace_wasm_decode_time) {
double pipeline_ms = pipeline_timer.Elapsed().InMillisecondsF();
PrintF(
"wasm-compilation phase 1 ok: %u bytes, %0.3f ms decode, %zu nodes, "
"%0.3f ms pipeline\n",
static_cast<unsigned>(func_body_.end - func_body_.start), decode_ms,
node_count, pipeline_ms);
static_cast<unsigned>(wasm_unit_->func_body_.end -
wasm_unit_->func_body_.start),
decode_ms, node_count, pipeline_ms);
}
// The graph zone is about to get out of scope. Avoid invalid references.
tf_.jsgraph_ = nullptr;
jsgraph_ = nullptr;
}
// Record the memory cost this unit places on the system until
// it is finalized.
memory_cost_ = tf_.job_->AllocatedMemory();
wasm_unit_->memory_cost_ = job_->AllocatedMemory();
}
// WasmCompilationUnit::ExecuteLiftoffCompilation() is defined in
// liftoff-compiler.cc.
wasm::WasmCode* WasmCompilationUnit::FinishCompilation(
wasm::ErrorThrower* thrower) {
wasm::WasmCode* ret;
switch (mode_) {
case WasmCompilationUnit::CompilationMode::kLiftoff:
ret = FinishLiftoffCompilation(thrower);
break;
case WasmCompilationUnit::CompilationMode::kTurbofan:
ret = FinishTurbofanCompilation(thrower);
break;
default:
UNREACHABLE();
}
if (ret == nullptr) {
thrower->RuntimeError("Error finalizing code.");
}
return ret;
}
wasm::WasmCode* WasmCompilationUnit::FinishTurbofanCompilation(
wasm::WasmCode* TurbofanWasmCompilationUnit::FinishCompilation(
wasm::ErrorThrower* thrower) {
if (!ok_) {
if (tf_.graph_construction_result_.failed()) {
if (graph_construction_result_.failed()) {
// Add the function as another context for the exception.
EmbeddedVector<char, 128> message;
if (func_name_.start() == nullptr) {
SNPrintF(message, "Compiling wasm function #%d failed", func_index_);
if (wasm_unit_->func_name_.start() == nullptr) {
SNPrintF(message, "Compiling wasm function #%d failed",
wasm_unit_->func_index_);
} else {
wasm::TruncatedUserString<> trunc_name(func_name_);
wasm::TruncatedUserString<> trunc_name(wasm_unit_->func_name_);
SNPrintF(message, "Compiling wasm function #%d:%.*s failed",
func_index_, trunc_name.length(), trunc_name.start());
wasm_unit_->func_index_, trunc_name.length(),
trunc_name.start());
}
thrower->CompileFailed(message.start(), tf_.graph_construction_result_);
thrower->CompileFailed(message.start(), graph_construction_result_);
}
return nullptr;
@ -5216,69 +5132,34 @@ wasm::WasmCode* WasmCompilationUnit::FinishTurbofanCompilation(
codegen_timer.Start();
}
if (tf_.job_->FinalizeJob(isolate_) != CompilationJob::SUCCEEDED) {
if (job_->FinalizeJob(wasm_unit_->isolate_) != CompilationJob::SUCCEEDED) {
return nullptr;
}
// TODO(mtrofin): when we crystalize a design in lieu of WasmCodeDesc, that
// works for both wasm and non-wasm, we can simplify AddCode to just take
// that as a parameter.
const CodeDesc& desc =
tf_.job_->compilation_info()->wasm_code_desc()->code_desc;
wasm::WasmCode* code = native_module_->AddCode(
desc, tf_.job_->compilation_info()->wasm_code_desc()->frame_slot_count,
func_index_,
tf_.job_->compilation_info()->wasm_code_desc()->safepoint_table_offset,
tf_.job_->compilation_info()->wasm_code_desc()->handler_table_offset,
const CodeDesc& desc = job_->compilation_info()->wasm_code_desc()->code_desc;
wasm::WasmCode* code = wasm_unit_->native_module_->AddCode(
desc, job_->compilation_info()->wasm_code_desc()->frame_slot_count,
wasm_unit_->func_index_,
job_->compilation_info()->wasm_code_desc()->safepoint_table_offset,
job_->compilation_info()->wasm_code_desc()->handler_table_offset,
wasm_compilation_data_.ReleaseProtectedInstructions(),
tf_.job_->compilation_info()->wasm_code_desc()->source_positions_table,
job_->compilation_info()->wasm_code_desc()->source_positions_table,
wasm::WasmCode::kTurbofan);
if (!code) return code;
if (FLAG_trace_wasm_decode_time) {
double codegen_ms = codegen_timer.Elapsed().InMillisecondsF();
PrintF("wasm-code-generation ok: %u bytes, %0.3f ms code generation\n",
static_cast<unsigned>(func_body_.end - func_body_.start),
static_cast<unsigned>(wasm_unit_->func_body_.end -
wasm_unit_->func_body_.start),
codegen_ms);
}
return code;
}
wasm::WasmCode* WasmCompilationUnit::FinishLiftoffCompilation(
wasm::ErrorThrower* thrower) {
CodeDesc desc;
liftoff_.asm_.GetCode(isolate_, &desc);
Handle<ByteArray> source_positions =
liftoff_.source_position_table_builder_.ToSourcePositionTable(isolate_);
wasm::WasmCode* code = native_module_->AddCode(
desc, liftoff_.asm_.GetTotalFrameSlotCount(), func_index_,
liftoff_.safepoint_table_offset_, 0,
wasm_compilation_data_.ReleaseProtectedInstructions(), source_positions,
wasm::WasmCode::kLiftoff);
return code;
}
// static
wasm::WasmCode* WasmCompilationUnit::CompileWasmFunction(
wasm::NativeModule* native_module, wasm::ErrorThrower* thrower,
Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env,
const wasm::WasmFunction* function, CompilationMode mode) {
wasm::FunctionBody function_body{
function->sig, function->code.offset(),
wire_bytes.start() + function->code.offset(),
wire_bytes.start() + function->code.end_offset()};
WasmCompilationUnit unit(isolate, env, native_module, function_body,
wire_bytes.GetNameOrNull(function, env->module),
function->func_index,
CEntryStub(isolate, 1).GetCode(), mode);
unit.ExecuteCompilation();
return unit.FinishCompilation(thrower);
}
#undef WASM_64
#undef FATAL_UNSUPPORTED_OPCODE
#undef WASM_INSTANCE_OBJECT_OFFSET

View File

@ -12,8 +12,8 @@
#include "src/compiler.h"
#include "src/optimized-compilation-info.h"
#include "src/trap-handler/trap-handler.h"
#include "src/wasm/baseline/liftoff-assembler.h"
#include "src/wasm/function-body-decoder.h"
#include "src/wasm/function-compiler.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-result.h"
@ -43,31 +43,12 @@ class WasmCode;
namespace compiler {
// The {ModuleEnv} encapsulates the module data that is used by the
// {WasmGraphBuilder} during graph building.
// ModuleEnvs are shareable across multiple compilations.
struct ModuleEnv {
// A pointer to the decoded module's static representation.
const wasm::WasmModule* module;
// True if trap handling should be used in compiled code, rather than
// compiling in bounds checks for each memory access.
const bool use_trap_handler;
ModuleEnv(const wasm::WasmModule* module, bool use_trap_handler)
: module(module), use_trap_handler(use_trap_handler) {}
};
enum RuntimeExceptionSupport : bool {
kRuntimeExceptionSupport = true,
kNoRuntimeExceptionSupport = false
};
// Information about Wasm compilation that needs to be plumbed through the
// different layers of the compiler.
class WasmCompilationData {
public:
explicit WasmCompilationData(RuntimeExceptionSupport);
explicit WasmCompilationData(
wasm::RuntimeExceptionSupport runtime_exception_support);
void AddProtectedInstruction(uint32_t instr_offset, uint32_t landing_offset);
@ -76,7 +57,7 @@ class WasmCompilationData {
return std::move(protected_instructions_);
}
RuntimeExceptionSupport runtime_exception_support() const {
wasm::RuntimeExceptionSupport runtime_exception_support() const {
return runtime_exception_support_;
}
@ -84,115 +65,56 @@ class WasmCompilationData {
std::unique_ptr<std::vector<trap_handler::ProtectedInstructionData>>
protected_instructions_;
// See WasmGraphBuilder::runtime_exception_support_.
const RuntimeExceptionSupport runtime_exception_support_;
// See ModuleEnv::runtime_exception_support_.
wasm::RuntimeExceptionSupport runtime_exception_support_;
DISALLOW_COPY_AND_ASSIGN(WasmCompilationData);
};
class WasmCompilationUnit final {
class TurbofanWasmCompilationUnit {
public:
enum class CompilationMode : uint8_t { kLiftoff, kTurbofan };
static CompilationMode GetDefaultCompilationMode();
explicit TurbofanWasmCompilationUnit(wasm::WasmCompilationUnit* wasm_unit)
: wasm_unit_(wasm_unit),
wasm_compilation_data_(wasm_unit->env_->runtime_exception_support) {}
// If constructing from a background thread, pass in a Counters*, and ensure
// that the Counters live at least as long as this compilation unit (which
// typically means to hold a std::shared_ptr<Counters>).
// If no such pointer is passed, Isolate::counters() will be called. This is
// only allowed to happen on the foreground thread.
WasmCompilationUnit(Isolate*, ModuleEnv*, wasm::NativeModule*,
wasm::FunctionBody, wasm::WasmName, int index,
Handle<Code> centry_stub,
CompilationMode = GetDefaultCompilationMode(),
Counters* = nullptr,
RuntimeExceptionSupport = kRuntimeExceptionSupport,
bool lower_simd = false);
~WasmCompilationUnit();
SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
void ExecuteCompilation();
wasm::WasmCode* FinishCompilation(wasm::ErrorThrower* thrower);
static wasm::WasmCode* CompileWasmFunction(
wasm::NativeModule* native_module, wasm::ErrorThrower* thrower,
Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env,
const wasm::WasmFunction* function,
CompilationMode = GetDefaultCompilationMode());
size_t memory_cost() const { return memory_cost_; }
wasm::NativeModule* native_module() const { return native_module_; }
wasm::WasmCode* FinishCompilation(wasm::ErrorThrower*);
private:
struct LiftoffData {
wasm::LiftoffAssembler asm_;
int safepoint_table_offset_;
SourcePositionTableBuilder source_position_table_builder_;
// The {codegen_zone_} needs to survive until FinishCompilation. It's only
// rarely used (e.g. for runtime calls), so it's only allocated when needed.
std::unique_ptr<Zone> codegen_zone_;
explicit LiftoffData(Isolate* isolate) : asm_(isolate) {}
};
struct TurbofanData {
// The graph zone is deallocated at the end of ExecuteCompilation by virtue
// of it being zone allocated.
JSGraph* jsgraph_ = nullptr;
// The compilation_zone_, info_, and job_ fields need to survive past
// ExecuteCompilation, onto FinishCompilation (which happens on the main
// thread).
std::unique_ptr<Zone> compilation_zone_;
std::unique_ptr<OptimizedCompilationInfo> info_;
std::unique_ptr<OptimizedCompilationJob> job_;
wasm::Result<wasm::DecodeStruct*> graph_construction_result_;
};
// Turbofan.
SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
void ExecuteTurbofanCompilation();
wasm::WasmCode* FinishTurbofanCompilation(wasm::ErrorThrower*);
// Liftoff.
bool ExecuteLiftoffCompilation();
wasm::WasmCode* FinishLiftoffCompilation(wasm::ErrorThrower*);
Isolate* isolate_;
ModuleEnv* env_;
wasm::FunctionBody func_body_;
wasm::WasmName func_name_;
Counters* counters_;
Handle<Code> centry_stub_;
int func_index_;
bool ok_ = true;
size_t memory_cost_ = 0;
wasm::NativeModule* native_module_;
bool lower_simd_;
wasm::WasmCompilationUnit* const wasm_unit_;
WasmCompilationData wasm_compilation_data_;
CompilationMode mode_;
// {liftoff_} is valid if mode_ == kLiftoff, tf_ if mode_ == kTurbofan.
union {
LiftoffData liftoff_;
TurbofanData tf_;
};
bool ok_ = true;
// The graph zone is deallocated at the end of {ExecuteCompilation} by virtue
// of it being zone allocated.
JSGraph* jsgraph_ = nullptr;
// The compilation_zone_, info_, and job_ fields need to survive past
// {ExecuteCompilation}, onto {FinishCompilation} (which happens on the main
// thread).
std::unique_ptr<Zone> compilation_zone_;
std::unique_ptr<OptimizedCompilationInfo> info_;
std::unique_ptr<OptimizedCompilationJob> job_;
wasm::Result<wasm::DecodeStruct*> graph_construction_result_;
Counters* counters() { return counters_; }
DISALLOW_COPY_AND_ASSIGN(WasmCompilationUnit);
DISALLOW_COPY_AND_ASSIGN(TurbofanWasmCompilationUnit);
};
// Wraps a JS function, producing a code object that can be called from wasm.
Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
wasm::FunctionSig* sig, uint32_t index,
wasm::ModuleOrigin origin,
bool use_trap_handler);
Handle<Code> CompileWasmToJSWrapper(Isolate*, Handle<JSReceiver> target,
wasm::FunctionSig*, uint32_t index,
wasm::ModuleOrigin, wasm::UseTrapHandler);
// Wraps a given wasm code object, producing a code object.
V8_EXPORT_PRIVATE Handle<Code> CompileJSToWasmWrapper(
Isolate* isolate, wasm::WasmModule* module, Handle<WeakCell> weak_instance,
wasm::WasmCode* wasm_code, uint32_t index, bool use_trap_handler);
Isolate*, wasm::WasmModule*, Handle<WeakCell> weak_instance,
wasm::WasmCode*, uint32_t index, wasm::UseTrapHandler);
// Compiles a stub that redirects a call to a wasm function to the wasm
// interpreter. It's ABI compatible with the compiled wasm function.
Handle<Code> CompileWasmInterpreterEntry(Isolate* isolate, uint32_t func_index,
wasm::FunctionSig* sig);
Handle<Code> CompileWasmInterpreterEntry(Isolate*, uint32_t func_index,
wasm::FunctionSig*);
// Helper function to get the offset into a fixed array for a given {index}.
// TODO(titzer): access-builder.h is not accessible outside compiler. Move?
@ -228,11 +150,10 @@ class WasmGraphBuilder {
public:
enum EnforceBoundsCheck : bool { kNeedsBoundsCheck, kCanOmitBoundsCheck };
WasmGraphBuilder(ModuleEnv* env, Zone* zone, JSGraph* graph,
WasmGraphBuilder(wasm::ModuleEnv* env, Zone* zone, JSGraph* graph,
Handle<Code> centry_stub, Handle<Oddball> anyref_null,
wasm::FunctionSig* sig,
compiler::SourcePositionTable* spt = nullptr,
RuntimeExceptionSupport res = kRuntimeExceptionSupport);
compiler::SourcePositionTable* spt = nullptr);
Node** Buffer(size_t count) {
if (count > cur_bufsize_) {
@ -423,7 +344,7 @@ class WasmGraphBuilder {
Node* const anyref_null_node_;
// env_ == nullptr means we're not compiling Wasm functions, such as for
// wrappers or interpreter stubs.
ModuleEnv* const env_ = nullptr;
wasm::ModuleEnv* const env_ = nullptr;
SetOncePointer<Node> instance_node_;
struct FunctionTableNodes {
Node* table_addr;
@ -439,10 +360,6 @@ class WasmGraphBuilder {
bool has_simd_ = false;
bool needs_stack_check_ = false;
const bool untrusted_code_mitigations_ = true;
// If the runtime doesn't support exception propagation,
// we won't generate stack checks, and trap handling will also
// be generated differently.
const RuntimeExceptionSupport runtime_exception_support_;
wasm::FunctionSig* const sig_;
SetOncePointer<const Operator> allocate_heap_number_operator_;

View File

@ -2,15 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/wasm/baseline/liftoff-assembler.h"
#include "src/wasm/baseline/liftoff-compiler.h"
#include "src/assembler-inl.h"
#include "src/base/optional.h"
// TODO(clemensh): Remove dependences on compiler stuff.
#include "src/compiler/linkage.h"
#include "src/compiler/wasm-compiler.h"
#include "src/counters.h"
#include "src/macro-assembler-inl.h"
#include "src/wasm/baseline/liftoff-assembler.h"
#include "src/wasm/function-body-decoder-impl.h"
#include "src/wasm/function-compiler.h"
#include "src/wasm/memory-tracing.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-opcodes.h"
@ -19,8 +22,6 @@ namespace v8 {
namespace internal {
namespace wasm {
using WasmCompilationData = compiler::WasmCompilationData;
constexpr auto kRegister = LiftoffAssembler::VarState::kRegister;
constexpr auto KIntConst = LiftoffAssembler::VarState::KIntConst;
constexpr auto kStack = LiftoffAssembler::VarState::kStack;
@ -122,10 +123,10 @@ class LiftoffCompiler {
};
LiftoffCompiler(LiftoffAssembler* liftoff_asm,
compiler::CallDescriptor* call_descriptor,
compiler::ModuleEnv* env,
compiler::CallDescriptor* call_descriptor, ModuleEnv* env,
SourcePositionTableBuilder* source_position_table_builder,
WasmCompilationData* wasm_compilation_data,
std::vector<trap_handler::ProtectedInstructionData>*
protected_instructions,
Zone* compilation_zone, std::unique_ptr<Zone>* codegen_zone,
WasmCode* const* code_table_entry)
: asm_(liftoff_asm),
@ -138,7 +139,7 @@ class LiftoffCompiler {
: wasm::kV8MaxWasmMemoryPages} *
wasm::kWasmPageSize),
source_position_table_builder_(source_position_table_builder),
wasm_compilation_data_(wasm_compilation_data),
protected_instructions_(protected_instructions),
compilation_zone_(compilation_zone),
codegen_zone_(codegen_zone),
safepoint_table_builder_(compilation_zone_),
@ -280,10 +281,7 @@ class LiftoffCompiler {
}
void StackCheck(wasm::WasmCodePosition position) {
if (FLAG_wasm_no_stack_checks ||
!wasm_compilation_data_->runtime_exception_support()) {
return;
}
if (FLAG_wasm_no_stack_checks || !env_->runtime_exception_support) return;
out_of_line_code_.push_back(
OutOfLineCode::StackCheck(position, __ cache_state()->used_registers));
OutOfLineCode& ool = out_of_line_code_.back();
@ -444,10 +442,11 @@ class LiftoffCompiler {
if (is_mem_out_of_bounds && env_->use_trap_handler) {
uint32_t pc = static_cast<uint32_t>(__ pc_offset());
DCHECK_EQ(pc, __ pc_offset());
wasm_compilation_data_->AddProtectedInstruction(ool.pc, pc);
protected_instructions_->emplace_back(
trap_handler::ProtectedInstructionData{ool.pc, pc});
}
if (!wasm_compilation_data_->runtime_exception_support()) {
if (!env_->runtime_exception_support) {
// We cannot test calls to the runtime in cctest/test-run-wasm.
// Therefore we emit a call to C here instead of a call to the runtime.
// In this mode, we never generate stack checks.
@ -1610,14 +1609,14 @@ class LiftoffCompiler {
private:
LiftoffAssembler* const asm_;
compiler::CallDescriptor* const descriptor_;
compiler::ModuleEnv* const env_;
ModuleEnv* const env_;
// {min_size_} and {max_size_} are cached values computed from the ModuleEnv.
const uint64_t min_size_;
const uint64_t max_size_;
bool ok_ = true;
std::vector<OutOfLineCode> out_of_line_code_;
SourcePositionTableBuilder* const source_position_table_builder_;
WasmCompilationData* wasm_compilation_data_;
std::vector<trap_handler::ProtectedInstructionData>* protected_instructions_;
// Zone used to store information during compilation. The result will be
// stored independently, such that this zone can die together with the
// LiftoffCompiler after compilation.
@ -1657,30 +1656,37 @@ class LiftoffCompiler {
};
} // namespace
} // namespace wasm
bool compiler::WasmCompilationUnit::ExecuteLiftoffCompilation() {
bool LiftoffCompilationUnit::ExecuteCompilation() {
base::ElapsedTimer compile_timer;
if (FLAG_trace_wasm_decode_time) {
compile_timer.Start();
}
Zone zone(isolate_->allocator(), "LiftoffCompilationZone");
const wasm::WasmModule* module = env_ ? env_->module : nullptr;
auto call_descriptor = compiler::GetWasmCallDescriptor(&zone, func_body_.sig);
Zone zone(wasm_unit_->isolate_->allocator(), "LiftoffCompilationZone");
const wasm::WasmModule* module =
wasm_unit_->env_ ? wasm_unit_->env_->module : nullptr;
auto call_descriptor =
compiler::GetWasmCallDescriptor(&zone, wasm_unit_->func_body_.sig);
base::Optional<TimedHistogramScope> liftoff_compile_time_scope(
base::in_place, counters()->liftoff_compile_time());
base::in_place, wasm_unit_->counters_->liftoff_compile_time());
wasm::WasmCode* const* code_table_entry =
native_module_->code_table().data() + func_index_;
wasm_unit_->native_module_->code_table().data() + wasm_unit_->func_index_;
DCHECK(!protected_instructions_);
protected_instructions_.reset(
new std::vector<trap_handler::ProtectedInstructionData>());
wasm::WasmFullDecoder<wasm::Decoder::kValidate, wasm::LiftoffCompiler>
decoder(&zone, module, func_body_, &liftoff_.asm_, call_descriptor, env_,
&liftoff_.source_position_table_builder_, &wasm_compilation_data_,
&zone, &liftoff_.codegen_zone_, code_table_entry);
decoder(&zone, module, wasm_unit_->func_body_, &asm_, call_descriptor,
wasm_unit_->env_, &source_position_table_builder_,
protected_instructions_.get(), &zone, &codegen_zone_,
code_table_entry);
decoder.Decode();
liftoff_compile_time_scope.reset();
if (!decoder.interface().ok()) {
// Liftoff compilation failed.
isolate_->counters()->liftoff_unsupported_functions()->Increment();
wasm_unit_->isolate_->counters()
->liftoff_unsupported_functions()
->Increment();
return false;
}
if (decoder.failed()) return false; // Validation error
@ -1690,22 +1696,46 @@ bool compiler::WasmCompilationUnit::ExecuteLiftoffCompilation() {
PrintF(
"wasm-compilation liftoff phase 1 ok: %u bytes, %0.3f ms decode and "
"compile\n",
static_cast<unsigned>(func_body_.end - func_body_.start), compile_ms);
static_cast<unsigned>(wasm_unit_->func_body_.end -
wasm_unit_->func_body_.start),
compile_ms);
}
// Record the memory cost this unit places on the system until
// it is finalized.
memory_cost_ = liftoff_.asm_.pc_offset();
liftoff_.safepoint_table_offset_ =
decoder.interface().GetSafepointTableOffset();
isolate_->counters()->liftoff_compiled_functions()->Increment();
wasm_unit_->memory_cost_ =
asm_.pc_offset() +
protected_instructions_->size() *
sizeof(trap_handler::ProtectedInstructionData) +
(codegen_zone_ ? codegen_zone_->allocation_size() : 0);
safepoint_table_offset_ = decoder.interface().GetSafepointTableOffset();
wasm_unit_->isolate_->counters()->liftoff_compiled_functions()->Increment();
return true;
}
wasm::WasmCode* LiftoffCompilationUnit::FinishCompilation(
wasm::ErrorThrower* thrower) {
CodeDesc desc;
asm_.GetCode(wasm_unit_->isolate_, &desc);
Handle<ByteArray> source_positions =
source_position_table_builder_.ToSourcePositionTable(
wasm_unit_->isolate_);
wasm::WasmCode* code = wasm_unit_->native_module_->AddCode(
desc, asm_.GetTotalFrameSlotCount(), wasm_unit_->func_index_,
safepoint_table_offset_, 0, std::move(protected_instructions_),
source_positions, wasm::WasmCode::kLiftoff);
return code;
}
#undef __
#undef TRACE
#undef WASM_INSTANCE_OBJECT_OFFSET
#undef LOAD_INSTANCE_FIELD
} // namespace wasm
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,45 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_WASM_BASELINE_LIFTOFF_COMPILER_H_
#define V8_WASM_BASELINE_LIFTOFF_COMPILER_H_
#include "src/source-position-table.h"
#include "src/trap-handler/trap-handler.h"
#include "src/wasm/baseline/liftoff-assembler.h"
#include "src/wasm/function-body-decoder.h"
#include "src/wasm/function-compiler.h"
namespace v8 {
namespace internal {
namespace wasm {
class LiftoffCompilationUnit final {
public:
explicit LiftoffCompilationUnit(WasmCompilationUnit* wasm_unit)
: wasm_unit_(wasm_unit), asm_(wasm_unit->isolate_) {}
bool ExecuteCompilation();
wasm::WasmCode* FinishCompilation(wasm::ErrorThrower*);
private:
WasmCompilationUnit* const wasm_unit_;
wasm::LiftoffAssembler asm_;
int safepoint_table_offset_;
SourcePositionTableBuilder source_position_table_builder_;
std::unique_ptr<std::vector<trap_handler::ProtectedInstructionData>>
protected_instructions_;
// The {codegen_zone_} needs to survive until FinishCompilation. It's only
// rarely used (e.g. for runtime calls), so it's only allocated when needed.
std::unique_ptr<Zone> codegen_zone_;
DISALLOW_COPY_AND_ASSIGN(LiftoffCompilationUnit);
};
} // namespace wasm
} // namespace internal
} // namespace v8
#endif // V8_WASM_BASELINE_LIFTOFF_COMPILER_H_

View File

@ -0,0 +1,133 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/wasm/function-compiler.h"
#include "src/code-stubs.h"
#include "src/compiler/wasm-compiler.h"
#include "src/counters.h"
#include "src/macro-assembler-inl.h"
#include "src/wasm/baseline/liftoff-compiler.h"
namespace v8 {
namespace internal {
namespace wasm {
// static
WasmCompilationUnit::CompilationMode
WasmCompilationUnit::GetDefaultCompilationMode() {
return FLAG_liftoff ? CompilationMode::kLiftoff : CompilationMode::kTurbofan;
}
WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate, ModuleEnv* env,
wasm::NativeModule* native_module,
wasm::FunctionBody body,
wasm::WasmName name, int index,
Handle<Code> centry_stub,
CompilationMode mode,
Counters* counters, bool lower_simd)
: isolate_(isolate),
env_(env),
func_body_(body),
func_name_(name),
counters_(counters ? counters : isolate->counters()),
centry_stub_(centry_stub),
func_index_(index),
native_module_(native_module),
lower_simd_(lower_simd),
mode_(mode) {
SwitchMode(mode);
}
// Declared here such that {LiftoffCompilationUnit} and
// {TurbofanWasmCompilationUnit} can be opaque in the header file.
WasmCompilationUnit::~WasmCompilationUnit() {}
void WasmCompilationUnit::ExecuteCompilation() {
auto size_histogram = env_->module->is_wasm()
? counters_->wasm_wasm_function_size_bytes()
: counters_->wasm_asm_function_size_bytes();
size_histogram->AddSample(
static_cast<int>(func_body_.end - func_body_.start));
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);
if (FLAG_trace_wasm_compiler) {
PrintF("Compiling wasm function %d\n\n", func_index_);
}
switch (mode_) {
case WasmCompilationUnit::CompilationMode::kLiftoff:
if (liftoff_unit_->ExecuteCompilation()) break;
// Otherwise, fall back to turbofan.
SwitchMode(CompilationMode::kTurbofan);
V8_FALLTHROUGH;
case WasmCompilationUnit::CompilationMode::kTurbofan:
turbofan_unit_->ExecuteCompilation();
break;
}
}
wasm::WasmCode* WasmCompilationUnit::FinishCompilation(
wasm::ErrorThrower* thrower) {
wasm::WasmCode* ret;
switch (mode_) {
case CompilationMode::kLiftoff:
ret = liftoff_unit_->FinishCompilation(thrower);
break;
case CompilationMode::kTurbofan:
ret = turbofan_unit_->FinishCompilation(thrower);
break;
default:
UNREACHABLE();
}
if (ret == nullptr) {
thrower->RuntimeError("Error finalizing code.");
}
return ret;
}
void WasmCompilationUnit::SwitchMode(CompilationMode new_mode) {
// This method is being called in the constructor, where neither
// {liftoff_unit_} nor {turbofan_unit_} are set, or to switch mode from
// kLiftoff to kTurbofan, in which case {liftoff_unit_} is already set.
mode_ = new_mode;
switch (new_mode) {
case CompilationMode::kLiftoff:
DCHECK(!turbofan_unit_);
DCHECK(!liftoff_unit_);
liftoff_unit_.reset(new LiftoffCompilationUnit(this));
return;
case CompilationMode::kTurbofan:
DCHECK(!turbofan_unit_);
liftoff_unit_.reset();
turbofan_unit_.reset(new compiler::TurbofanWasmCompilationUnit(this));
return;
}
UNREACHABLE();
}
// static
wasm::WasmCode* WasmCompilationUnit::CompileWasmFunction(
wasm::NativeModule* native_module, wasm::ErrorThrower* thrower,
Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env,
const wasm::WasmFunction* function, CompilationMode mode) {
wasm::FunctionBody function_body{
function->sig, function->code.offset(),
wire_bytes.start() + function->code.offset(),
wire_bytes.start() + function->code.end_offset()};
WasmCompilationUnit unit(isolate, env, native_module, function_body,
wire_bytes.GetNameOrNull(function, env->module),
function->func_index,
CEntryStub(isolate, 1).GetCode(), mode);
unit.ExecuteCompilation();
return unit.FinishCompilation(thrower);
}
} // namespace wasm
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,114 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_WASM_FUNCTION_COMPILER_H_
#define V8_WASM_FUNCTION_COMPILER_H_
#include "src/wasm/function-body-decoder.h"
namespace v8 {
namespace internal {
namespace compiler {
class TurbofanWasmCompilationUnit;
} // namespace compiler
namespace wasm {
class LiftoffCompilationUnit;
struct ModuleWireBytes;
class NativeModule;
class WasmCode;
struct WasmFunction;
enum RuntimeExceptionSupport : bool {
kRuntimeExceptionSupport = true,
kNoRuntimeExceptionSupport = false
};
enum UseTrapHandler : bool { kUseTrapHandler = true, kNoTrapHandler = false };
// The {ModuleEnv} encapsulates the module data that is used during compilation.
// ModuleEnvs are shareable across multiple compilations.
struct ModuleEnv {
// A pointer to the decoded module's static representation.
const WasmModule* const module;
// True if trap handling should be used in compiled code, rather than
// compiling in bounds checks for each memory access.
const UseTrapHandler use_trap_handler;
// If the runtime doesn't support exception propagation,
// we won't generate stack checks, and trap handling will also
// be generated differently.
const RuntimeExceptionSupport runtime_exception_support;
constexpr ModuleEnv(const WasmModule* module, UseTrapHandler use_trap_handler,
RuntimeExceptionSupport runtime_exception_support)
: module(module),
use_trap_handler(use_trap_handler),
runtime_exception_support(runtime_exception_support) {}
};
class WasmCompilationUnit final {
public:
enum class CompilationMode : uint8_t { kLiftoff, kTurbofan };
static CompilationMode GetDefaultCompilationMode();
// If constructing from a background thread, pass in a Counters*, and ensure
// that the Counters live at least as long as this compilation unit (which
// typically means to hold a std::shared_ptr<Counters>).
// If no such pointer is passed, Isolate::counters() will be called. This is
// only allowed to happen on the foreground thread.
WasmCompilationUnit(Isolate*, ModuleEnv*, wasm::NativeModule*,
wasm::FunctionBody, wasm::WasmName, int index,
Handle<Code> centry_stub,
CompilationMode = GetDefaultCompilationMode(),
Counters* = nullptr, bool lower_simd = false);
~WasmCompilationUnit();
void ExecuteCompilation();
wasm::WasmCode* FinishCompilation(wasm::ErrorThrower* thrower);
static wasm::WasmCode* CompileWasmFunction(
wasm::NativeModule* native_module, wasm::ErrorThrower* thrower,
Isolate* isolate, const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env,
const wasm::WasmFunction* function,
CompilationMode = GetDefaultCompilationMode());
size_t memory_cost() const { return memory_cost_; }
wasm::NativeModule* native_module() const { return native_module_; }
private:
friend class LiftoffCompilationUnit;
friend class compiler::TurbofanWasmCompilationUnit;
Isolate* isolate_;
ModuleEnv* env_;
wasm::FunctionBody func_body_;
wasm::WasmName func_name_;
Counters* counters_;
Handle<Code> centry_stub_;
int func_index_;
size_t memory_cost_ = 0;
wasm::NativeModule* native_module_;
// TODO(wasm): Put {lower_simd_} inside the {ModuleEnv}.
bool lower_simd_;
CompilationMode mode_;
// LiftoffCompilationUnit, set if {mode_ == kLiftoff}.
std::unique_ptr<LiftoffCompilationUnit> liftoff_unit_;
// TurbofanWasmCompilationUnit, set if {mode_ == kTurbofan}.
std::unique_ptr<compiler::TurbofanWasmCompilationUnit> turbofan_unit_;
void SwitchMode(CompilationMode new_mode);
DISALLOW_COPY_AND_ASSIGN(WasmCompilationUnit);
};
} // namespace wasm
} // namespace internal
} // namespace v8
#endif // V8_WASM_FUNCTION_COMPILER_H_

View File

@ -80,15 +80,14 @@ class CompilationState {
// Inserts new functions to compile and kicks off compilation.
void AddCompilationUnits(
std::vector<std::unique_ptr<compiler::WasmCompilationUnit>>& units);
std::unique_ptr<compiler::WasmCompilationUnit> GetNextCompilationUnit();
std::unique_ptr<compiler::WasmCompilationUnit> GetNextExecutedUnit();
std::vector<std::unique_ptr<WasmCompilationUnit>>& units);
std::unique_ptr<WasmCompilationUnit> GetNextCompilationUnit();
std::unique_ptr<WasmCompilationUnit> GetNextExecutedUnit();
bool HasCompilationUnitToFinish();
void OnError(Handle<Object> error, NotifyCompilationCallback notify);
void OnFinishedUnit(NotifyCompilationCallback notify);
void ScheduleUnitForFinishing(
std::unique_ptr<compiler::WasmCompilationUnit> unit);
void ScheduleUnitForFinishing(std::unique_ptr<WasmCompilationUnit> unit);
void CancelAndWait();
void OnBackgroundTaskStopped();
@ -122,13 +121,12 @@ class CompilationState {
//////////////////////////////////////////////////////////////////////////////
// Protected by {mutex_}:
std::vector<std::unique_ptr<compiler::WasmCompilationUnit>>
compilation_units_;
std::vector<std::unique_ptr<WasmCompilationUnit>> compilation_units_;
bool finisher_is_running_ = false;
bool failed_ = false;
size_t num_background_tasks_ = 0;
std::vector<std::unique_ptr<compiler::WasmCompilationUnit>> finish_units_;
std::vector<std::unique_ptr<WasmCompilationUnit>> finish_units_;
size_t allocated_memory_ = 0;
// End of fields protected by {mutex_}.
@ -152,11 +150,9 @@ namespace {
class JSToWasmWrapperCache {
public:
Handle<Code> CloneOrCompileJSToWasmWrapper(Isolate* isolate,
wasm::WasmModule* module,
wasm::WasmCode* wasm_code,
uint32_t index,
bool use_trap_handler) {
Handle<Code> CloneOrCompileJSToWasmWrapper(
Isolate* isolate, wasm::WasmModule* module, wasm::WasmCode* wasm_code,
uint32_t index, wasm::UseTrapHandler use_trap_handler) {
const wasm::WasmFunction* func = &module->functions[index];
int cached_idx = sig_map_.Find(func->sig);
if (cached_idx >= 0) {
@ -240,7 +236,10 @@ class InstanceBuilder {
Counters* counters() const { return async_counters().get(); }
bool use_trap_handler() const { return compiled_module_->use_trap_handler(); }
wasm::UseTrapHandler use_trap_handler() const {
return compiled_module_->use_trap_handler() ? kUseTrapHandler
: kNoTrapHandler;
}
// Helper routines to print out errors with imports.
#define ERROR_THROWER_WITH_MESSAGE(TYPE) \
@ -435,12 +434,13 @@ class IndirectPatcher {
int misses_ = 0;
};
compiler::ModuleEnv CreateModuleEnvFromCompiledModule(
ModuleEnv CreateModuleEnvFromCompiledModule(
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
DisallowHeapAllocation no_gc;
WasmModule* module = compiled_module->shared()->module();
compiler::ModuleEnv result(module, compiled_module->use_trap_handler());
return result;
wasm::UseTrapHandler use_trap_handler =
compiled_module->use_trap_handler() ? kUseTrapHandler : kNoTrapHandler;
return ModuleEnv(module, use_trap_handler, wasm::kRuntimeExceptionSupport);
}
const wasm::WasmCode* LazyCompileFunction(
@ -469,7 +469,7 @@ const wasm::WasmCode* LazyCompileFunction(
TRACE_LAZY("Compiling function %s, %d.\n", func_name.c_str(), func_index);
compiler::ModuleEnv module_env =
ModuleEnv module_env =
CreateModuleEnvFromCompiledModule(isolate, compiled_module);
const uint8_t* module_start =
@ -481,10 +481,10 @@ const wasm::WasmCode* LazyCompileFunction(
module_start + func->code.end_offset()};
ErrorThrower thrower(isolate, "WasmLazyCompile");
compiler::WasmCompilationUnit unit(isolate, &module_env,
compiled_module->GetNativeModule(), body,
CStrVector(func_name.c_str()), func_index,
CEntryStub(isolate, 1).GetCode());
WasmCompilationUnit unit(isolate, &module_env,
compiled_module->GetNativeModule(), body,
CStrVector(func_name.c_str()), func_index,
CEntryStub(isolate, 1).GetCode());
unit.ExecuteCompilation();
wasm::WasmCode* wasm_code = unit.FinishCompilation(&thrower);
@ -885,17 +885,17 @@ double MonotonicallyIncreasingTimeInMs() {
base::Time::kMillisecondsPerSecond;
}
std::unique_ptr<compiler::ModuleEnv> CreateDefaultModuleEnv(
Isolate* isolate, WasmModule* module) {
ModuleEnv CreateDefaultModuleEnv(Isolate* isolate, WasmModule* module) {
// TODO(kschimpf): Add module-specific policy handling here (see v8:7143)?
bool use_trap_handler = trap_handler::IsTrapHandlerEnabled();
return base::make_unique<compiler::ModuleEnv>(module, use_trap_handler);
UseTrapHandler use_trap_handler =
trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler : kNoTrapHandler;
return ModuleEnv(module, use_trap_handler, kRuntimeExceptionSupport);
}
Handle<WasmCompiledModule> NewCompiledModule(Isolate* isolate,
WasmModule* module,
Handle<FixedArray> export_wrappers,
compiler::ModuleEnv* env) {
ModuleEnv* env) {
Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New(
isolate, module, export_wrappers, env->use_trap_handler);
return compiled_module;
@ -913,7 +913,7 @@ size_t GetMaxUsableMemorySize(Isolate* isolate) {
class CompilationUnitBuilder {
public:
explicit CompilationUnitBuilder(NativeModule* native_module,
compiler::ModuleEnv* module_env,
ModuleEnv* module_env,
Handle<Code> centry_stub)
: native_module_(native_module),
compilation_state_(native_module->compilation_state()),
@ -922,12 +922,12 @@ class CompilationUnitBuilder {
void AddUnit(const WasmFunction* function, uint32_t buffer_offset,
Vector<const uint8_t> bytes, WasmName name) {
units_.emplace_back(new compiler::WasmCompilationUnit(
units_.emplace_back(new WasmCompilationUnit(
compilation_state_->isolate(), module_env_, native_module_,
wasm::FunctionBody{function->sig, buffer_offset, bytes.begin(),
bytes.end()},
name, function->func_index, centry_stub_,
compiler::WasmCompilationUnit::GetDefaultCompilationMode(),
WasmCompilationUnit::GetDefaultCompilationMode(),
compilation_state_->isolate()->async_counters().get()));
}
@ -943,9 +943,9 @@ class CompilationUnitBuilder {
private:
NativeModule* native_module_;
CompilationState* compilation_state_;
compiler::ModuleEnv* module_env_;
ModuleEnv* module_env_;
Handle<Code> centry_stub_;
std::vector<std::unique_ptr<compiler::WasmCompilationUnit>> units_;
std::vector<std::unique_ptr<WasmCompilationUnit>> units_;
};
// Run by each compilation task and by the main thread (i.e. in both
@ -958,7 +958,7 @@ bool FetchAndExecuteCompilationUnit(CompilationState* compilation_state) {
DisallowHandleDereference no_deref;
DisallowCodeDependencyChange no_dependency_change;
std::unique_ptr<compiler::WasmCompilationUnit> unit =
std::unique_ptr<WasmCompilationUnit> unit =
compilation_state->GetNextCompilationUnit();
if (unit == nullptr) return false;
@ -969,7 +969,7 @@ bool FetchAndExecuteCompilationUnit(CompilationState* compilation_state) {
}
size_t GetNumFunctionsToCompile(const std::vector<WasmFunction>& functions,
compiler::ModuleEnv* module_env) {
ModuleEnv* module_env) {
// TODO(kimanh): Remove, FLAG_skip_compiling_wasm_funcs: previously used for
// debugging, and now not necessarily working anymore.
uint32_t start = module_env->module->num_imported_functions +
@ -981,8 +981,7 @@ size_t GetNumFunctionsToCompile(const std::vector<WasmFunction>& functions,
void InitializeCompilationUnits(const std::vector<WasmFunction>& functions,
const ModuleWireBytes& wire_bytes,
compiler::ModuleEnv* module_env,
Handle<Code> centry_stub,
ModuleEnv* module_env, Handle<Code> centry_stub,
NativeModule* native_module) {
uint32_t start = module_env->module->num_imported_functions +
FLAG_skip_compiling_wasm_funcs;
@ -1006,7 +1005,7 @@ void FinishCompilationUnits(CompilationState* compilation_state,
ErrorThrower* thrower) {
while (true) {
if (compilation_state->failed()) break;
std::unique_ptr<compiler::WasmCompilationUnit> unit =
std::unique_ptr<WasmCompilationUnit> unit =
compilation_state->GetNextExecutedUnit();
if (unit == nullptr) break;
wasm::WasmCode* result = unit->FinishCompilation(thrower);
@ -1022,8 +1021,7 @@ void FinishCompilationUnits(CompilationState* compilation_state,
}
void CompileInParallel(Isolate* isolate, NativeModule* native_module,
const ModuleWireBytes& wire_bytes,
compiler::ModuleEnv* module_env,
const ModuleWireBytes& wire_bytes, ModuleEnv* module_env,
Handle<Code> centry_stub, ErrorThrower* thrower) {
const WasmModule* module = module_env->module;
// Data structures for the parallel compilation.
@ -1098,8 +1096,7 @@ void CompileInParallel(Isolate* isolate, NativeModule* native_module,
void CompileSequentially(Isolate* isolate, NativeModule* native_module,
const ModuleWireBytes& wire_bytes,
compiler::ModuleEnv* module_env,
ErrorThrower* thrower) {
ModuleEnv* module_env, ErrorThrower* thrower) {
DCHECK(!thrower->error());
const WasmModule* module = module_env->module;
@ -1109,7 +1106,7 @@ void CompileSequentially(Isolate* isolate, NativeModule* native_module,
if (func.imported) continue; // Imports are compiled at instantiation time.
// Compile the function.
wasm::WasmCode* code = compiler::WasmCompilationUnit::CompileWasmFunction(
wasm::WasmCode* code = WasmCompilationUnit::CompileWasmFunction(
native_module, thrower, isolate, wire_bytes, module_env, &func);
if (code == nullptr) {
TruncatedUserString<> name(wire_bytes.GetName(&func, module));
@ -1121,8 +1118,7 @@ void CompileSequentially(Isolate* isolate, NativeModule* native_module,
}
void ValidateSequentially(Isolate* isolate, const ModuleWireBytes& wire_bytes,
compiler::ModuleEnv* module_env,
ErrorThrower* thrower) {
ModuleEnv* module_env, ErrorThrower* thrower) {
DCHECK(!thrower->error());
const WasmModule* module = module_env->module;
@ -1209,14 +1205,14 @@ MaybeHandle<WasmModuleObject> CompileToModuleObjectInternal(
for (int i = 0, e = export_wrappers->length(); i < e; ++i) {
export_wrappers->set(i, *init_builtin);
}
auto env = CreateDefaultModuleEnv(isolate, wasm_module);
ModuleEnv env = CreateDefaultModuleEnv(isolate, wasm_module);
// 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 =
NewCompiledModule(isolate, shared->module(), export_wrappers, env.get());
NewCompiledModule(isolate, shared->module(), export_wrappers, &env);
NativeModule* native_module = compiled_module->GetNativeModule();
compiled_module->set_shared(*shared);
if (lazy_compile) {
@ -1227,7 +1223,7 @@ MaybeHandle<WasmModuleObject> 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(isolate, wire_bytes, env.get(), thrower);
ValidateSequentially(isolate, wire_bytes, &env, thrower);
if (thrower->error()) return {};
}
@ -1241,11 +1237,10 @@ MaybeHandle<WasmModuleObject> CompileToModuleObjectInternal(
V8::GetCurrentPlatform()->NumberOfWorkerThreads() > 0;
if (compile_parallel) {
CompileInParallel(isolate, native_module, wire_bytes, env.get(),
centry_stub, thrower);
CompileInParallel(isolate, native_module, wire_bytes, &env, centry_stub,
thrower);
} else {
CompileSequentially(isolate, native_module, wire_bytes, env.get(),
thrower);
CompileSequentially(isolate, native_module, wire_bytes, &env, thrower);
}
if (thrower->error()) return {};
@ -1297,7 +1292,7 @@ class FinishCompileTask : public CancelableTask {
while (true) {
compilation_state_->RestartBackgroundTasks();
std::unique_ptr<compiler::WasmCompilationUnit> unit =
std::unique_ptr<WasmCompilationUnit> unit =
compilation_state_->GetNextExecutedUnit();
if (unit == nullptr) {
@ -1676,8 +1671,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
native_module->GetIndirectlyCallableCode(start_index);
FunctionSig* sig = module_->functions[start_index].sig;
Handle<Code> wrapper_code = js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper(
isolate_, module_, start_code, start_index,
compiled_module_->use_trap_handler());
isolate_, module_, start_code, start_index, use_trap_handler());
start_function_ = WasmExportedFunction::New(
isolate_, instance, MaybeHandle<String>(), start_index,
static_cast<int>(sig->parameter_count()), wrapper_code);
@ -1928,8 +1922,7 @@ int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
Handle<JSReceiver> js_receiver(JSReceiver::cast(*value), isolate_);
Handle<Code> wrapper_code = compiler::CompileWasmToJSWrapper(
isolate_, js_receiver, expected_sig, func_index,
module_->origin(),
instance->compiled_module()->use_trap_handler());
module_->origin(), use_trap_handler());
RecordStats(*wrapper_code, counters());
WasmCode* wasm_code = native_module->AddCodeCopy(
@ -2396,7 +2389,7 @@ void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
Handle<Code> wrapper_code =
js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper(
isolate_, module_, wasm_code, func_index,
instance->compiled_module()->use_trap_handler());
use_trap_handler());
MaybeHandle<String> func_name;
if (module_->is_asm_js()) {
// For modules arising from asm.js, honor the names section.
@ -2698,7 +2691,9 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
Isolate* isolate = job_->isolate_;
job_->module_env_ = CreateDefaultModuleEnv(isolate, module_);
DCHECK_NULL(job_->module_env_);
job_->module_env_.reset(
new ModuleEnv(CreateDefaultModuleEnv(isolate, module_)));
Handle<Code> centry_stub = CEntryStub(isolate, 1).GetCode();
{
@ -3101,7 +3096,7 @@ void CompilationState::AddCallback(
}
void CompilationState::AddCompilationUnits(
std::vector<std::unique_ptr<compiler::WasmCompilationUnit>>& units) {
std::vector<std::unique_ptr<WasmCompilationUnit>>& units) {
{
base::LockGuard<base::Mutex> guard(&mutex_);
compilation_units_.insert(compilation_units_.end(),
@ -3111,25 +3106,23 @@ void CompilationState::AddCompilationUnits(
RestartBackgroundTasks(units.size());
}
std::unique_ptr<compiler::WasmCompilationUnit>
std::unique_ptr<WasmCompilationUnit>
CompilationState::GetNextCompilationUnit() {
base::LockGuard<base::Mutex> guard(&mutex_);
if (!compilation_units_.empty()) {
std::unique_ptr<compiler::WasmCompilationUnit> unit =
std::unique_ptr<WasmCompilationUnit> unit =
std::move(compilation_units_.back());
compilation_units_.pop_back();
return unit;
}
return std::unique_ptr<compiler::WasmCompilationUnit>();
return std::unique_ptr<WasmCompilationUnit>();
}
std::unique_ptr<compiler::WasmCompilationUnit>
CompilationState::GetNextExecutedUnit() {
std::unique_ptr<WasmCompilationUnit> CompilationState::GetNextExecutedUnit() {
base::LockGuard<base::Mutex> guard(&mutex_);
if (finish_units_.empty()) return {};
std::unique_ptr<compiler::WasmCompilationUnit> ret =
std::move(finish_units_.back());
std::unique_ptr<WasmCompilationUnit> ret = std::move(finish_units_.back());
finish_units_.pop_back();
allocated_memory_ -= ret->memory_cost();
return ret;
@ -3162,7 +3155,7 @@ void CompilationState::OnFinishedUnit(NotifyCompilationCallback notify) {
}
void CompilationState::ScheduleUnitForFinishing(
std::unique_ptr<compiler::WasmCompilationUnit> unit) {
std::unique_ptr<WasmCompilationUnit> unit) {
size_t cost = unit->memory_cost();
base::LockGuard<base::Mutex> guard(&mutex_);
finish_units_.push_back(std::move(unit));
@ -3258,13 +3251,15 @@ void CompileJsToWasmWrappers(Isolate* isolate,
Handle<FixedArray> export_wrappers(compiled_module->export_wrappers(),
isolate);
NativeModule* native_module = compiled_module->GetNativeModule();
wasm::UseTrapHandler use_trap_handler =
compiled_module->use_trap_handler() ? kUseTrapHandler : kNoTrapHandler;
for (auto exp : compiled_module->shared()->module()->export_table) {
if (exp.kind != kExternalFunction) continue;
wasm::WasmCode* wasm_code =
native_module->GetIndirectlyCallableCode(exp.index);
Handle<Code> wrapper_code = js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(
isolate, compiled_module->shared()->module(), wasm_code, exp.index,
compiled_module->use_trap_handler());
use_trap_handler);
export_wrappers->set(wrapper_index, *wrapper_code);
RecordStats(*wrapper_code, counters);
++wrapper_index;

View File

@ -20,9 +20,10 @@ namespace v8 {
namespace internal {
namespace wasm {
class ModuleCompiler;
class WasmCode;
class CompilationState;
class ModuleCompiler;
struct ModuleEnv;
class WasmCode;
struct CompilationStateDeleter {
void operator()(CompilationState* compilation_state) const;
@ -137,7 +138,7 @@ class AsyncCompileJob {
ModuleWireBytes wire_bytes_;
Handle<Context> context_;
Handle<JSPromise> module_promise_;
std::unique_ptr<compiler::ModuleEnv> module_env_;
std::unique_ptr<ModuleEnv> module_env_;
std::unique_ptr<WasmModule> module_;
std::vector<DeferredHandles*> deferred_handles_;

View File

@ -13,13 +13,10 @@
namespace v8 {
namespace internal {
namespace compiler {
struct ModuleEnv;
}
namespace wasm {
struct ModuleEnv;
inline bool IsValidSectionCode(uint8_t byte) {
return kTypeSectionCode <= byte && byte <= kLastKnownModuleSection;
}
@ -82,10 +79,9 @@ V8_EXPORT_PRIVATE FunctionResult SyncDecodeWasmFunction(
const WasmModule* module, const byte* function_start,
const byte* function_end);
V8_EXPORT_PRIVATE FunctionResult
AsyncDecodeWasmFunction(Isolate* isolate, Zone* zone, compiler::ModuleEnv* env,
const byte* function_start, const byte* function_end,
const std::shared_ptr<Counters> async_counters);
V8_EXPORT_PRIVATE FunctionResult AsyncDecodeWasmFunction(
Isolate* isolate, Zone* zone, ModuleEnv* env, const byte* function_start,
const byte* function_end, const std::shared_ptr<Counters> async_counters);
V8_EXPORT_PRIVATE WasmInitExpr DecodeWasmInitExprForTesting(const byte* start,
const byte* end);

View File

@ -1972,8 +1972,7 @@ static void TestBuildGraphForSimpleExpression(WasmOpcode opcode) {
byte code[] = {WASM_NO_LOCALS, kExprGetLocal, 0, static_cast<byte>(opcode),
WASM_END};
TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code,
code + arraysize(code),
compiler::kNoRuntimeExceptionSupport);
code + arraysize(code));
} else {
CHECK_EQ(2, sig->parameter_count());
byte code[] = {WASM_NO_LOCALS,
@ -1984,8 +1983,7 @@ static void TestBuildGraphForSimpleExpression(WasmOpcode opcode) {
static_cast<byte>(opcode),
WASM_END};
TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code,
code + arraysize(code),
compiler::kNoRuntimeExceptionSupport);
code + arraysize(code));
}
}

View File

@ -158,8 +158,7 @@ WASM_EXEC_TEST(CollectDetailedWasmStack_WasmError) {
int unreachable_pos = 1 << (8 * pos_shift);
TestSignatures sigs;
// Create a WasmRunner with stack checks and traps enabled.
WasmRunner<int> r(execution_mode, 0, "main",
compiler::kRuntimeExceptionSupport);
WasmRunner<int> r(execution_mode, 0, "main", kRuntimeExceptionSupport);
std::vector<byte> code(unreachable_pos + 1, kExprNop);
code[unreachable_pos] = kExprUnreachable;

View File

@ -70,8 +70,7 @@ void CheckExceptionInfos(v8::internal::Isolate* i_isolate, Handle<Object> exc,
// Trigger a trap for executing unreachable.
WASM_EXEC_TEST(Unreachable) {
// Create a WasmRunner with stack checks and traps enabled.
WasmRunner<void> r(execution_mode, 0, "main",
compiler::kRuntimeExceptionSupport);
WasmRunner<void> r(execution_mode, 0, "main", kRuntimeExceptionSupport);
TestSignatures sigs;
BUILD(r, WASM_UNREACHABLE);
@ -105,8 +104,7 @@ WASM_EXEC_TEST(Unreachable) {
// Trigger a trap for loading from out-of-bounds.
WASM_EXEC_TEST(IllegalLoad) {
WasmRunner<void> r(execution_mode, 0, "main",
compiler::kRuntimeExceptionSupport);
WasmRunner<void> r(execution_mode, 0, "main", kRuntimeExceptionSupport);
TestSignatures sigs;
r.builder().AddMemory(0L);

View File

@ -15,7 +15,7 @@ namespace wasm {
TestingModuleBuilder::TestingModuleBuilder(
Zone* zone, ManuallyImportedJSFunction* maybe_import,
WasmExecutionMode mode, compiler::RuntimeExceptionSupport exception_support,
WasmExecutionMode mode, RuntimeExceptionSupport exception_support,
LowerSimd lower_simd)
: test_module_ptr_(&test_module_),
isolate_(CcTest::InitIsolateOnce()),
@ -45,7 +45,8 @@ TestingModuleBuilder::TestingModuleBuilder(
Handle<Code> code = compiler::CompileWasmToJSWrapper(
isolate_, maybe_import->js_function, maybe_import->sig,
maybe_import_index, test_module_.origin(),
trap_handler::IsTrapHandlerEnabled());
trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler
: kNoTrapHandler);
native_module_->ResizeCodeTableForTesting(maybe_import_index + 1,
kMaxFunctions);
auto wasm_to_js_wrapper = native_module_->AddCodeCopy(
@ -126,7 +127,7 @@ Handle<JSFunction> TestingModuleBuilder::WrapCode(uint32_t index) {
isolate_);
Handle<Code> ret_code = compiler::CompileJSToWasmWrapper(
isolate_, &test_module_, weak_instance, code, index,
trap_handler::IsTrapHandlerEnabled());
trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler : kNoTrapHandler);
Handle<JSFunction> ret = WasmExportedFunction::New(
isolate_, instance_object(), MaybeHandle<String>(),
static_cast<int>(index),
@ -192,8 +193,11 @@ uint32_t TestingModuleBuilder::AddBytes(Vector<const byte> bytes) {
return bytes_offset;
}
compiler::ModuleEnv TestingModuleBuilder::CreateModuleEnv() {
return {&test_module_, trap_handler::IsTrapHandlerEnabled()};
ModuleEnv TestingModuleBuilder::CreateModuleEnv() {
return {
&test_module_,
trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler : kNoTrapHandler,
runtime_exception_support_};
}
const WasmGlobal* TestingModuleBuilder::AddGlobal(ValueType type) {
@ -263,22 +267,21 @@ void TestBuildingGraphWithBuilder(compiler::WasmGraphBuilder* builder,
}
}
void TestBuildingGraph(
Zone* zone, compiler::JSGraph* jsgraph, compiler::ModuleEnv* module,
FunctionSig* sig, compiler::SourcePositionTable* source_position_table,
const byte* start, const byte* end,
compiler::RuntimeExceptionSupport runtime_exception_support) {
void TestBuildingGraph(Zone* zone, compiler::JSGraph* jsgraph,
ModuleEnv* module, FunctionSig* sig,
compiler::SourcePositionTable* source_position_table,
const byte* start, const byte* end) {
if (module) {
compiler::WasmGraphBuilder builder(
module, zone, jsgraph, CEntryStub(jsgraph->isolate(), 1).GetCode(),
jsgraph->isolate()->factory()->null_value(), sig, source_position_table,
runtime_exception_support);
jsgraph->isolate()->factory()->null_value(), sig,
source_position_table);
TestBuildingGraphWithBuilder(&builder, zone, sig, start, end);
} else {
compiler::WasmGraphBuilder builder(
nullptr, zone, jsgraph, CEntryStub(jsgraph->isolate(), 1).GetCode(),
jsgraph->isolate()->factory()->null_value(), sig, source_position_table,
runtime_exception_support);
jsgraph->isolate()->factory()->null_value(), sig,
source_position_table);
TestBuildingGraphWithBuilder(&builder, zone, sig, start, end);
}
}
@ -422,7 +425,7 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) {
Handle<SeqOneByteString> wire_bytes(compiled_module->shared()->module_bytes(),
isolate());
compiler::ModuleEnv module_env = builder_->CreateModuleEnv();
ModuleEnv module_env = builder_->CreateModuleEnv();
ErrorThrower thrower(isolate(), "WasmFunctionCompiler::Build");
ScopedVector<uint8_t> func_wire_bytes(function_->code.length());
memcpy(func_wire_bytes.start(),
@ -436,15 +439,14 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) {
FunctionBody func_body{function_->sig, function_->code.offset(),
func_wire_bytes.start(), func_wire_bytes.end()};
compiler::WasmCompilationUnit::CompilationMode comp_mode =
WasmCompilationUnit::CompilationMode comp_mode =
builder_->execution_mode() == WasmExecutionMode::kExecuteLiftoff
? compiler::WasmCompilationUnit::CompilationMode::kLiftoff
: compiler::WasmCompilationUnit::CompilationMode::kTurbofan;
compiler::WasmCompilationUnit unit(
isolate(), &module_env, native_module, func_body, func_name,
function_->func_index, CEntryStub(isolate(), 1).GetCode(), comp_mode,
isolate()->counters(), builder_->runtime_exception_support(),
builder_->lower_simd());
? WasmCompilationUnit::CompilationMode::kLiftoff
: WasmCompilationUnit::CompilationMode::kTurbofan;
WasmCompilationUnit unit(isolate(), &module_env, native_module, func_body,
func_name, function_->func_index,
CEntryStub(isolate(), 1).GetCode(), comp_mode,
isolate()->counters(), builder_->lower_simd());
unit.ExecuteCompilation();
wasm::WasmCode* wasm_code = unit.FinishCompilation(&thrower);
if (wasm::WasmCode::ShouldBeLogged(isolate())) {

View File

@ -92,7 +92,7 @@ struct ManuallyImportedJSFunction {
class TestingModuleBuilder {
public:
TestingModuleBuilder(Zone*, ManuallyImportedJSFunction*, WasmExecutionMode,
compiler::RuntimeExceptionSupport, LowerSimd);
RuntimeExceptionSupport, LowerSimd);
void ChangeOriginToAsmjs() { test_module_.set_origin(kAsmJsOrigin); }
@ -215,11 +215,11 @@ class TestingModuleBuilder {
}
}
compiler::ModuleEnv CreateModuleEnv();
ModuleEnv CreateModuleEnv();
WasmExecutionMode execution_mode() const { return execution_mode_; }
compiler::RuntimeExceptionSupport runtime_exception_support() const {
RuntimeExceptionSupport runtime_exception_support() const {
return runtime_exception_support_;
}
@ -236,7 +236,7 @@ class TestingModuleBuilder {
Handle<WasmInstanceObject> instance_object_;
NativeModule* native_module_ = nullptr;
bool linked_ = false;
compiler::RuntimeExceptionSupport runtime_exception_support_;
RuntimeExceptionSupport runtime_exception_support_;
LowerSimd lower_simd_;
const WasmGlobal* AddGlobal(ValueType type);
@ -244,11 +244,10 @@ class TestingModuleBuilder {
Handle<WasmInstanceObject> InitInstanceObject();
};
void TestBuildingGraph(
Zone* zone, compiler::JSGraph* jsgraph, compiler::ModuleEnv* module,
FunctionSig* sig, compiler::SourcePositionTable* source_position_table,
const byte* start, const byte* end,
compiler::RuntimeExceptionSupport runtime_exception_support);
void TestBuildingGraph(Zone* zone, compiler::JSGraph* jsgraph,
ModuleEnv* module, FunctionSig* sig,
compiler::SourcePositionTable* source_position_table,
const byte* start, const byte* end);
class WasmFunctionWrapper : private compiler::GraphAndBuilders {
public:
@ -348,7 +347,7 @@ class WasmRunnerBase : public HandleAndZoneScope {
public:
WasmRunnerBase(ManuallyImportedJSFunction* maybe_import,
WasmExecutionMode execution_mode, int num_params,
compiler::RuntimeExceptionSupport runtime_exception_support,
RuntimeExceptionSupport runtime_exception_support,
LowerSimd lower_simd)
: zone_(&allocator_, ZONE_NAME),
builder_(&zone_, maybe_import, execution_mode,
@ -431,8 +430,8 @@ class WasmRunner : public WasmRunnerBase {
WasmRunner(WasmExecutionMode execution_mode,
ManuallyImportedJSFunction* maybe_import = nullptr,
const char* main_fn_name = "main",
compiler::RuntimeExceptionSupport runtime_exception_support =
compiler::kNoRuntimeExceptionSupport,
RuntimeExceptionSupport runtime_exception_support =
kNoRuntimeExceptionSupport,
LowerSimd lower_simd = kNoLowerSimd)
: WasmRunnerBase(maybe_import, execution_mode, sizeof...(ParamTypes),
runtime_exception_support, lower_simd) {
@ -443,8 +442,8 @@ class WasmRunner : public WasmRunnerBase {
}
WasmRunner(WasmExecutionMode execution_mode, LowerSimd lower_simd)
: WasmRunner(execution_mode, nullptr, "main",
compiler::kNoRuntimeExceptionSupport, lower_simd) {}
: WasmRunner(execution_mode, nullptr, "main", kNoRuntimeExceptionSupport,
lower_simd) {}
ReturnType Call(ParamTypes... p) {
DCHECK(compiled_);