Commit 0da7ec58 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[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: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52684}
parent a0c59cbf
......@@ -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",
......
This diff is collapsed.
......@@ -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();
// 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();
explicit TurbofanWasmCompilationUnit(wasm::WasmCompilationUnit* wasm_unit)
: wasm_unit_(wasm_unit),
wasm_compilation_data_(wasm_unit->env_->runtime_exception_support) {}
void ExecuteCompilation();
wasm::WasmCode* FinishCompilation(wasm::ErrorThrower* thrower);
SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
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());
void ExecuteCompilation();
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_;
};
Counters* counters() { return counters_; }
DISALLOW_COPY_AND_ASSIGN(WasmCompilationUnit);
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_;
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_;
......
......@@ -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
// 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_
// 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
// 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_
This diff is collapsed.
......@@ -20,9 +20,10 @@ namespace v8 {
namespace internal {
namespace wasm {
class CompilationState;
class ModuleCompiler;
struct ModuleEnv;
class WasmCode;
class CompilationState;
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_;
......
......@@ -13,12 +13,9 @@
namespace v8 {
namespace internal {
namespace wasm {
namespace compiler {
struct ModuleEnv;
}
namespace wasm {
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);
......
......@@ -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));
}
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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())) {
......
......@@ -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_);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment