[wasm] Do not store ModuleEnv
Instead, create it when needed and pass it down to the actual compilation. This saves memory by making the WasmCompilationUnit smaller and will eventually allow us to implement the trap handler fallback correctly by using an updated ModuleEnv in background compilation and tier up. R=mstarzinger@chromium.org Bug: v8:5277, v8:8343 Change-Id: I0dc3a37fb88e54eb4822dc99d58ff024f4b2a367 Reviewed-on: https://chromium-review.googlesource.com/c/1293953 Commit-Queue: Clemens Hammacher <clemensh@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#56896}
This commit is contained in:
parent
6d28125e1c
commit
9716f689b8
@ -5144,8 +5144,8 @@ TurbofanWasmCompilationUnit::TurbofanWasmCompilationUnit(
|
|||||||
TurbofanWasmCompilationUnit::~TurbofanWasmCompilationUnit() = default;
|
TurbofanWasmCompilationUnit::~TurbofanWasmCompilationUnit() = default;
|
||||||
|
|
||||||
SourcePositionTable* TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
|
SourcePositionTable* TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
|
||||||
wasm::WasmFeatures* detected, double* decode_ms, MachineGraph* mcgraph,
|
wasm::ModuleEnv* env, wasm::WasmFeatures* detected, double* decode_ms,
|
||||||
NodeOriginTable* node_origins) {
|
MachineGraph* mcgraph, NodeOriginTable* node_origins) {
|
||||||
base::ElapsedTimer decode_timer;
|
base::ElapsedTimer decode_timer;
|
||||||
if (FLAG_trace_wasm_decode_time) {
|
if (FLAG_trace_wasm_decode_time) {
|
||||||
decode_timer.Start();
|
decode_timer.Start();
|
||||||
@ -5154,12 +5154,12 @@ SourcePositionTable* TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
|
|||||||
// Create a TF graph during decoding.
|
// Create a TF graph during decoding.
|
||||||
SourcePositionTable* source_position_table =
|
SourcePositionTable* source_position_table =
|
||||||
new (mcgraph->zone()) SourcePositionTable(mcgraph->graph());
|
new (mcgraph->zone()) SourcePositionTable(mcgraph->graph());
|
||||||
WasmGraphBuilder builder(wasm_unit_->env_, mcgraph->zone(), mcgraph,
|
WasmGraphBuilder builder(env, mcgraph->zone(), mcgraph,
|
||||||
wasm_unit_->func_body_.sig, source_position_table);
|
wasm_unit_->func_body_.sig, source_position_table);
|
||||||
wasm::VoidResult graph_construction_result = wasm::BuildTFGraph(
|
wasm::VoidResult graph_construction_result = wasm::BuildTFGraph(
|
||||||
wasm_unit_->wasm_engine_->allocator(),
|
wasm_unit_->wasm_engine_->allocator(),
|
||||||
wasm_unit_->native_module_->enabled_features(), wasm_unit_->env_->module,
|
wasm_unit_->native_module_->enabled_features(), env->module, &builder,
|
||||||
&builder, detected, wasm_unit_->func_body_, node_origins);
|
detected, wasm_unit_->func_body_, node_origins);
|
||||||
if (graph_construction_result.failed()) {
|
if (graph_construction_result.failed()) {
|
||||||
if (FLAG_trace_wasm_compiler) {
|
if (FLAG_trace_wasm_compiler) {
|
||||||
StdoutStream{} << "Compilation failed: "
|
StdoutStream{} << "Compilation failed: "
|
||||||
@ -5172,7 +5172,7 @@ SourcePositionTable* TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
|
|||||||
builder.LowerInt64();
|
builder.LowerInt64();
|
||||||
|
|
||||||
if (builder.has_simd() &&
|
if (builder.has_simd() &&
|
||||||
(!CpuFeatures::SupportsWasmSimd128() || wasm_unit_->env_->lower_simd)) {
|
(!CpuFeatures::SupportsWasmSimd128() || env->lower_simd)) {
|
||||||
SimdScalarLowering(
|
SimdScalarLowering(
|
||||||
mcgraph,
|
mcgraph,
|
||||||
CreateMachineSignature(mcgraph->zone(), wasm_unit_->func_body_.sig))
|
CreateMachineSignature(mcgraph->zone(), wasm_unit_->func_body_.sig))
|
||||||
@ -5182,8 +5182,7 @@ SourcePositionTable* TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
|
|||||||
if (wasm_unit_->func_index_ >= FLAG_trace_wasm_ast_start &&
|
if (wasm_unit_->func_index_ >= FLAG_trace_wasm_ast_start &&
|
||||||
wasm_unit_->func_index_ < FLAG_trace_wasm_ast_end) {
|
wasm_unit_->func_index_ < FLAG_trace_wasm_ast_end) {
|
||||||
PrintRawWasmCode(wasm_unit_->wasm_engine_->allocator(),
|
PrintRawWasmCode(wasm_unit_->wasm_engine_->allocator(),
|
||||||
wasm_unit_->func_body_, wasm_unit_->env_->module,
|
wasm_unit_->func_body_, env->module, wasm::kPrintLocals);
|
||||||
wasm::kPrintLocals);
|
|
||||||
}
|
}
|
||||||
if (FLAG_trace_wasm_decode_time) {
|
if (FLAG_trace_wasm_decode_time) {
|
||||||
*decode_ms = decode_timer.Elapsed().InMillisecondsF();
|
*decode_ms = decode_timer.Elapsed().InMillisecondsF();
|
||||||
@ -5207,7 +5206,7 @@ Vector<const char> GetDebugName(Zone* zone, int index) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void TurbofanWasmCompilationUnit::ExecuteCompilation(
|
void TurbofanWasmCompilationUnit::ExecuteCompilation(
|
||||||
wasm::WasmFeatures* detected) {
|
wasm::ModuleEnv* env, wasm::WasmFeatures* detected) {
|
||||||
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
|
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
|
||||||
"ExecuteTurbofanCompilation");
|
"ExecuteTurbofanCompilation");
|
||||||
double decode_ms = 0;
|
double decode_ms = 0;
|
||||||
@ -5223,7 +5222,7 @@ void TurbofanWasmCompilationUnit::ExecuteCompilation(
|
|||||||
|
|
||||||
OptimizedCompilationInfo info(GetDebugName(&zone, wasm_unit_->func_index_),
|
OptimizedCompilationInfo info(GetDebugName(&zone, wasm_unit_->func_index_),
|
||||||
&zone, Code::WASM_FUNCTION);
|
&zone, Code::WASM_FUNCTION);
|
||||||
if (wasm_unit_->env_->runtime_exception_support) {
|
if (env->runtime_exception_support) {
|
||||||
info.SetWasmRuntimeExceptionSupport();
|
info.SetWasmRuntimeExceptionSupport();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5236,8 +5235,8 @@ void TurbofanWasmCompilationUnit::ExecuteCompilation(
|
|||||||
? new (&zone)
|
? new (&zone)
|
||||||
NodeOriginTable(mcgraph->graph())
|
NodeOriginTable(mcgraph->graph())
|
||||||
: nullptr;
|
: nullptr;
|
||||||
SourcePositionTable* source_positions =
|
SourcePositionTable* source_positions = BuildGraphForWasmFunction(
|
||||||
BuildGraphForWasmFunction(detected, &decode_ms, mcgraph, node_origins);
|
env, detected, &decode_ms, mcgraph, node_origins);
|
||||||
|
|
||||||
if (wasm_unit_->failed()) return;
|
if (wasm_unit_->failed()) return;
|
||||||
|
|
||||||
@ -5261,9 +5260,8 @@ void TurbofanWasmCompilationUnit::ExecuteCompilation(
|
|||||||
std::unique_ptr<OptimizedCompilationJob> job(Pipeline::NewWasmCompilationJob(
|
std::unique_ptr<OptimizedCompilationJob> job(Pipeline::NewWasmCompilationJob(
|
||||||
&info, wasm_unit_->wasm_engine_, mcgraph, call_descriptor,
|
&info, wasm_unit_->wasm_engine_, mcgraph, call_descriptor,
|
||||||
source_positions, node_origins, wasm_unit_->func_body_,
|
source_positions, node_origins, wasm_unit_->func_body_,
|
||||||
const_cast<wasm::WasmModule*>(wasm_unit_->env_->module),
|
const_cast<wasm::WasmModule*>(env->module), wasm_unit_->native_module_,
|
||||||
wasm_unit_->native_module_, wasm_unit_->func_index_,
|
wasm_unit_->func_index_, env->module->origin));
|
||||||
wasm_unit_->env_->module->origin));
|
|
||||||
if (job->ExecuteJob() == CompilationJob::SUCCEEDED) {
|
if (job->ExecuteJob() == CompilationJob::SUCCEEDED) {
|
||||||
wasm_unit_->SetResult(info.wasm_code());
|
wasm_unit_->SetResult(info.wasm_code());
|
||||||
}
|
}
|
||||||
|
@ -50,12 +50,13 @@ class TurbofanWasmCompilationUnit {
|
|||||||
explicit TurbofanWasmCompilationUnit(wasm::WasmCompilationUnit* wasm_unit);
|
explicit TurbofanWasmCompilationUnit(wasm::WasmCompilationUnit* wasm_unit);
|
||||||
~TurbofanWasmCompilationUnit();
|
~TurbofanWasmCompilationUnit();
|
||||||
|
|
||||||
SourcePositionTable* BuildGraphForWasmFunction(wasm::WasmFeatures* detected,
|
SourcePositionTable* BuildGraphForWasmFunction(wasm::ModuleEnv* env,
|
||||||
|
wasm::WasmFeatures* detected,
|
||||||
double* decode_ms,
|
double* decode_ms,
|
||||||
MachineGraph* mcgraph,
|
MachineGraph* mcgraph,
|
||||||
NodeOriginTable* node_origins);
|
NodeOriginTable* node_origins);
|
||||||
|
|
||||||
void ExecuteCompilation(wasm::WasmFeatures* detected);
|
void ExecuteCompilation(wasm::ModuleEnv* env, wasm::WasmFeatures* detected);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wasm::WasmCompilationUnit* const wasm_unit_;
|
wasm::WasmCompilationUnit* const wasm_unit_;
|
||||||
|
@ -1872,7 +1872,8 @@ class LiftoffCompiler {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool LiftoffCompilationUnit::ExecuteCompilation(WasmFeatures* detected) {
|
bool LiftoffCompilationUnit::ExecuteCompilation(ModuleEnv* env,
|
||||||
|
WasmFeatures* detected) {
|
||||||
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
|
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
|
||||||
"ExecuteLiftoffCompilation");
|
"ExecuteLiftoffCompilation");
|
||||||
base::ElapsedTimer compile_timer;
|
base::ElapsedTimer compile_timer;
|
||||||
@ -1881,15 +1882,14 @@ bool LiftoffCompilationUnit::ExecuteCompilation(WasmFeatures* detected) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Zone zone(wasm_unit_->wasm_engine_->allocator(), "LiftoffCompilationZone");
|
Zone zone(wasm_unit_->wasm_engine_->allocator(), "LiftoffCompilationZone");
|
||||||
const WasmModule* module =
|
const WasmModule* module = env ? env->module : nullptr;
|
||||||
wasm_unit_->env_ ? wasm_unit_->env_->module : nullptr;
|
|
||||||
auto call_descriptor =
|
auto call_descriptor =
|
||||||
compiler::GetWasmCallDescriptor(&zone, wasm_unit_->func_body_.sig);
|
compiler::GetWasmCallDescriptor(&zone, wasm_unit_->func_body_.sig);
|
||||||
base::Optional<TimedHistogramScope> liftoff_compile_time_scope(
|
base::Optional<TimedHistogramScope> liftoff_compile_time_scope(
|
||||||
base::in_place, wasm_unit_->counters_->liftoff_compile_time());
|
base::in_place, wasm_unit_->counters_->liftoff_compile_time());
|
||||||
WasmFullDecoder<Decoder::kValidate, LiftoffCompiler> decoder(
|
WasmFullDecoder<Decoder::kValidate, LiftoffCompiler> decoder(
|
||||||
&zone, module, wasm_unit_->native_module_->enabled_features(), detected,
|
&zone, module, wasm_unit_->native_module_->enabled_features(), detected,
|
||||||
wasm_unit_->func_body_, call_descriptor, wasm_unit_->env_, &zone);
|
wasm_unit_->func_body_, call_descriptor, env, &zone);
|
||||||
decoder.Decode();
|
decoder.Decode();
|
||||||
liftoff_compile_time_scope.reset();
|
liftoff_compile_time_scope.reset();
|
||||||
LiftoffCompiler* compiler = &decoder.interface();
|
LiftoffCompiler* compiler = &decoder.interface();
|
||||||
|
@ -11,17 +11,16 @@ namespace v8 {
|
|||||||
namespace internal {
|
namespace internal {
|
||||||
namespace wasm {
|
namespace wasm {
|
||||||
|
|
||||||
struct WasmFeatures;
|
struct ModuleEnv;
|
||||||
class ErrorThrower;
|
|
||||||
class WasmCode;
|
|
||||||
class WasmCompilationUnit;
|
class WasmCompilationUnit;
|
||||||
|
struct WasmFeatures;
|
||||||
|
|
||||||
class LiftoffCompilationUnit final {
|
class LiftoffCompilationUnit final {
|
||||||
public:
|
public:
|
||||||
explicit LiftoffCompilationUnit(WasmCompilationUnit* wasm_unit)
|
explicit LiftoffCompilationUnit(WasmCompilationUnit* wasm_unit)
|
||||||
: wasm_unit_(wasm_unit) {}
|
: wasm_unit_(wasm_unit) {}
|
||||||
|
|
||||||
bool ExecuteCompilation(WasmFeatures* detected);
|
bool ExecuteCompilation(ModuleEnv*, WasmFeatures* detected);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WasmCompilationUnit* const wasm_unit_;
|
WasmCompilationUnit* const wasm_unit_;
|
||||||
|
@ -80,9 +80,7 @@ struct CompilationStateDeleter {
|
|||||||
// Wrapper to create a CompilationState exists in order to avoid having
|
// Wrapper to create a CompilationState exists in order to avoid having
|
||||||
// the CompilationState in the header file.
|
// the CompilationState in the header file.
|
||||||
std::unique_ptr<CompilationState, CompilationStateDeleter> NewCompilationState(
|
std::unique_ptr<CompilationState, CompilationStateDeleter> NewCompilationState(
|
||||||
Isolate*, const ModuleEnv&);
|
Isolate*, NativeModule*);
|
||||||
|
|
||||||
ModuleEnv* GetModuleEnv(CompilationState* compilation_state);
|
|
||||||
|
|
||||||
} // namespace wasm
|
} // namespace wasm
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
@ -36,23 +36,22 @@ ExecutionTier WasmCompilationUnit::GetDefaultExecutionTier() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WasmCompilationUnit::WasmCompilationUnit(WasmEngine* wasm_engine,
|
WasmCompilationUnit::WasmCompilationUnit(WasmEngine* wasm_engine,
|
||||||
ModuleEnv* env,
|
|
||||||
NativeModule* native_module,
|
NativeModule* native_module,
|
||||||
FunctionBody body, int index,
|
FunctionBody body, int index,
|
||||||
Counters* counters, ExecutionTier mode)
|
Counters* counters, ExecutionTier mode)
|
||||||
: env_(env),
|
: wasm_engine_(wasm_engine),
|
||||||
wasm_engine_(wasm_engine),
|
|
||||||
func_body_(body),
|
func_body_(body),
|
||||||
counters_(counters),
|
counters_(counters),
|
||||||
func_index_(index),
|
func_index_(index),
|
||||||
native_module_(native_module),
|
native_module_(native_module),
|
||||||
mode_(mode) {
|
mode_(mode) {
|
||||||
DCHECK_GE(index, env->module->num_imported_functions);
|
const WasmModule* module = native_module->module();
|
||||||
DCHECK_LT(index, env->module->functions.size());
|
DCHECK_GE(index, module->num_imported_functions);
|
||||||
|
DCHECK_LT(index, module->functions.size());
|
||||||
// Always disable Liftoff for asm.js, for two reasons:
|
// Always disable Liftoff for asm.js, for two reasons:
|
||||||
// 1) asm-specific opcodes are not implemented, and
|
// 1) asm-specific opcodes are not implemented, and
|
||||||
// 2) tier-up does not work with lazy compilation.
|
// 2) tier-up does not work with lazy compilation.
|
||||||
if (env->module->origin == kAsmJsOrigin) mode = ExecutionTier::kOptimized;
|
if (module->origin == kAsmJsOrigin) mode = ExecutionTier::kOptimized;
|
||||||
if (V8_UNLIKELY(FLAG_wasm_tier_mask_for_testing) && index < 32 &&
|
if (V8_UNLIKELY(FLAG_wasm_tier_mask_for_testing) && index < 32 &&
|
||||||
(FLAG_wasm_tier_mask_for_testing & (1 << index))) {
|
(FLAG_wasm_tier_mask_for_testing & (1 << index))) {
|
||||||
mode = ExecutionTier::kOptimized;
|
mode = ExecutionTier::kOptimized;
|
||||||
@ -64,12 +63,14 @@ WasmCompilationUnit::WasmCompilationUnit(WasmEngine* wasm_engine,
|
|||||||
// {TurbofanWasmCompilationUnit} can be opaque in the header file.
|
// {TurbofanWasmCompilationUnit} can be opaque in the header file.
|
||||||
WasmCompilationUnit::~WasmCompilationUnit() = default;
|
WasmCompilationUnit::~WasmCompilationUnit() = default;
|
||||||
|
|
||||||
void WasmCompilationUnit::ExecuteCompilation(WasmFeatures* detected) {
|
void WasmCompilationUnit::ExecuteCompilation(ModuleEnv* env,
|
||||||
auto size_histogram = SELECT_WASM_COUNTER(counters_, env_->module->origin,
|
WasmFeatures* detected) {
|
||||||
wasm, function_size_bytes);
|
const WasmModule* module = native_module_->module();
|
||||||
|
auto size_histogram =
|
||||||
|
SELECT_WASM_COUNTER(counters_, module->origin, wasm, function_size_bytes);
|
||||||
size_histogram->AddSample(
|
size_histogram->AddSample(
|
||||||
static_cast<int>(func_body_.end - func_body_.start));
|
static_cast<int>(func_body_.end - func_body_.start));
|
||||||
auto timed_histogram = SELECT_WASM_COUNTER(counters_, env_->module->origin,
|
auto timed_histogram = SELECT_WASM_COUNTER(counters_, module->origin,
|
||||||
wasm_compile, function_time);
|
wasm_compile, function_time);
|
||||||
TimedHistogramScope wasm_compile_function_time_scope(timed_histogram);
|
TimedHistogramScope wasm_compile_function_time_scope(timed_histogram);
|
||||||
|
|
||||||
@ -80,12 +81,12 @@ void WasmCompilationUnit::ExecuteCompilation(WasmFeatures* detected) {
|
|||||||
|
|
||||||
switch (mode_) {
|
switch (mode_) {
|
||||||
case ExecutionTier::kBaseline:
|
case ExecutionTier::kBaseline:
|
||||||
if (liftoff_unit_->ExecuteCompilation(detected)) break;
|
if (liftoff_unit_->ExecuteCompilation(env, detected)) break;
|
||||||
// Otherwise, fall back to turbofan.
|
// Otherwise, fall back to turbofan.
|
||||||
SwitchMode(ExecutionTier::kOptimized);
|
SwitchMode(ExecutionTier::kOptimized);
|
||||||
V8_FALLTHROUGH;
|
V8_FALLTHROUGH;
|
||||||
case ExecutionTier::kOptimized:
|
case ExecutionTier::kOptimized:
|
||||||
turbofan_unit_->ExecuteCompilation(detected);
|
turbofan_unit_->ExecuteCompilation(env, detected);
|
||||||
break;
|
break;
|
||||||
case ExecutionTier::kInterpreter:
|
case ExecutionTier::kInterpreter:
|
||||||
UNREACHABLE(); // TODO(titzer): compile interpreter entry stub.
|
UNREACHABLE(); // TODO(titzer): compile interpreter entry stub.
|
||||||
@ -136,17 +137,16 @@ void WasmCompilationUnit::SwitchMode(ExecutionTier new_mode) {
|
|||||||
// static
|
// static
|
||||||
WasmCode* WasmCompilationUnit::CompileWasmFunction(
|
WasmCode* WasmCompilationUnit::CompileWasmFunction(
|
||||||
Isolate* isolate, NativeModule* native_module, WasmFeatures* detected,
|
Isolate* isolate, NativeModule* native_module, WasmFeatures* detected,
|
||||||
ErrorThrower* thrower, ModuleEnv* env, const WasmFunction* function,
|
ErrorThrower* thrower, const WasmFunction* function, ExecutionTier mode) {
|
||||||
ExecutionTier mode) {
|
|
||||||
ModuleWireBytes wire_bytes(native_module->wire_bytes());
|
ModuleWireBytes wire_bytes(native_module->wire_bytes());
|
||||||
FunctionBody function_body{function->sig, function->code.offset(),
|
FunctionBody function_body{function->sig, function->code.offset(),
|
||||||
wire_bytes.start() + function->code.offset(),
|
wire_bytes.start() + function->code.offset(),
|
||||||
wire_bytes.start() + function->code.end_offset()};
|
wire_bytes.start() + function->code.end_offset()};
|
||||||
|
|
||||||
WasmCompilationUnit unit(isolate->wasm_engine(), env, native_module,
|
WasmCompilationUnit unit(isolate->wasm_engine(), native_module, function_body,
|
||||||
function_body,
|
|
||||||
function->func_index, isolate->counters(), mode);
|
function->func_index, isolate->counters(), mode);
|
||||||
unit.ExecuteCompilation(detected);
|
ModuleEnv env = native_module->CreateModuleEnv();
|
||||||
|
unit.ExecuteCompilation(&env, detected);
|
||||||
if (unit.failed()) {
|
if (unit.failed()) {
|
||||||
unit.ReportError(thrower);
|
unit.ReportError(thrower);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -37,13 +37,12 @@ class WasmCompilationUnit final {
|
|||||||
// typically means to hold a std::shared_ptr<Counters>).
|
// typically means to hold a std::shared_ptr<Counters>).
|
||||||
// If used exclusively from a foreground thread, Isolate::counters() may be
|
// If used exclusively from a foreground thread, Isolate::counters() may be
|
||||||
// used by callers to pass Counters.
|
// used by callers to pass Counters.
|
||||||
WasmCompilationUnit(WasmEngine* wasm_engine, ModuleEnv*, NativeModule*,
|
WasmCompilationUnit(WasmEngine*, NativeModule*, FunctionBody, int index,
|
||||||
FunctionBody, int index, Counters*,
|
Counters*, ExecutionTier = GetDefaultExecutionTier());
|
||||||
ExecutionTier = GetDefaultExecutionTier());
|
|
||||||
|
|
||||||
~WasmCompilationUnit();
|
~WasmCompilationUnit();
|
||||||
|
|
||||||
void ExecuteCompilation(WasmFeatures* detected);
|
void ExecuteCompilation(ModuleEnv*, WasmFeatures* detected);
|
||||||
|
|
||||||
NativeModule* native_module() const { return native_module_; }
|
NativeModule* native_module() const { return native_module_; }
|
||||||
ExecutionTier mode() const { return mode_; }
|
ExecutionTier mode() const { return mode_; }
|
||||||
@ -58,14 +57,13 @@ class WasmCompilationUnit final {
|
|||||||
|
|
||||||
static WasmCode* CompileWasmFunction(
|
static WasmCode* CompileWasmFunction(
|
||||||
Isolate* isolate, NativeModule* native_module, WasmFeatures* detected,
|
Isolate* isolate, NativeModule* native_module, WasmFeatures* detected,
|
||||||
ErrorThrower* thrower, ModuleEnv* env, const WasmFunction* function,
|
ErrorThrower* thrower, const WasmFunction* function,
|
||||||
ExecutionTier = GetDefaultExecutionTier());
|
ExecutionTier = GetDefaultExecutionTier());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class LiftoffCompilationUnit;
|
friend class LiftoffCompilationUnit;
|
||||||
friend class compiler::TurbofanWasmCompilationUnit;
|
friend class compiler::TurbofanWasmCompilationUnit;
|
||||||
|
|
||||||
ModuleEnv* env_;
|
|
||||||
WasmEngine* wasm_engine_;
|
WasmEngine* wasm_engine_;
|
||||||
FunctionBody func_body_;
|
FunctionBody func_body_;
|
||||||
Counters* counters_;
|
Counters* counters_;
|
||||||
|
@ -65,7 +65,7 @@ enum class CompileMode : uint8_t { kRegular, kTiering };
|
|||||||
// compilation of functions.
|
// compilation of functions.
|
||||||
class CompilationState {
|
class CompilationState {
|
||||||
public:
|
public:
|
||||||
CompilationState(internal::Isolate*, const ModuleEnv&);
|
CompilationState(internal::Isolate*, NativeModule*);
|
||||||
~CompilationState();
|
~CompilationState();
|
||||||
|
|
||||||
// Set the number of compilations unit expected to be executed. Needs to be
|
// Set the number of compilations unit expected to be executed. Needs to be
|
||||||
@ -115,7 +115,6 @@ class CompilationState {
|
|||||||
|
|
||||||
WasmEngine* wasm_engine() const { return wasm_engine_; }
|
WasmEngine* wasm_engine() const { return wasm_engine_; }
|
||||||
CompileMode compile_mode() const { return compile_mode_; }
|
CompileMode compile_mode() const { return compile_mode_; }
|
||||||
ModuleEnv* module_env() { return &module_env_; }
|
|
||||||
WasmFeatures* detected_features() { return &detected_features_; }
|
WasmFeatures* detected_features() { return &detected_features_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -130,8 +129,7 @@ class CompilationState {
|
|||||||
// can be shared across multiple Isolates.
|
// can be shared across multiple Isolates.
|
||||||
Isolate* const isolate_;
|
Isolate* const isolate_;
|
||||||
WasmEngine* const wasm_engine_;
|
WasmEngine* const wasm_engine_;
|
||||||
// TODO(clemensh): Remove ModuleEnv, generate it when needed.
|
NativeModule* const native_module_;
|
||||||
ModuleEnv module_env_;
|
|
||||||
const CompileMode compile_mode_;
|
const CompileMode compile_mode_;
|
||||||
bool baseline_compilation_finished_ = false;
|
bool baseline_compilation_finished_ = false;
|
||||||
|
|
||||||
@ -347,21 +345,20 @@ WasmCode* LazyCompileFunction(Isolate* isolate, NativeModule* native_module,
|
|||||||
|
|
||||||
compilation_timer.Start();
|
compilation_timer.Start();
|
||||||
|
|
||||||
ModuleEnv* module_env = native_module->compilation_state()->module_env();
|
|
||||||
|
|
||||||
TRACE_LAZY("Compiling wasm-function#%d.\n", func_index);
|
TRACE_LAZY("Compiling wasm-function#%d.\n", func_index);
|
||||||
|
|
||||||
const uint8_t* module_start = native_module->wire_bytes().start();
|
const uint8_t* module_start = native_module->wire_bytes().start();
|
||||||
|
|
||||||
const WasmFunction* func = &module_env->module->functions[func_index];
|
const WasmFunction* func = &native_module->module()->functions[func_index];
|
||||||
FunctionBody body{func->sig, func->code.offset(),
|
FunctionBody body{func->sig, func->code.offset(),
|
||||||
module_start + func->code.offset(),
|
module_start + func->code.offset(),
|
||||||
module_start + func->code.end_offset()};
|
module_start + func->code.end_offset()};
|
||||||
|
|
||||||
WasmCompilationUnit unit(isolate->wasm_engine(), module_env, native_module,
|
WasmCompilationUnit unit(isolate->wasm_engine(), native_module, body,
|
||||||
body, func_index, isolate->counters());
|
func_index, isolate->counters());
|
||||||
|
ModuleEnv env = native_module->CreateModuleEnv();
|
||||||
unit.ExecuteCompilation(
|
unit.ExecuteCompilation(
|
||||||
native_module->compilation_state()->detected_features());
|
&env, native_module->compilation_state()->detected_features());
|
||||||
|
|
||||||
// If there is a pending error, something really went wrong. The module was
|
// If there is a pending error, something really went wrong. The module was
|
||||||
// verified before starting execution with lazy compilation.
|
// verified before starting execution with lazy compilation.
|
||||||
@ -449,8 +446,7 @@ class CompilationUnitBuilder {
|
|||||||
Vector<const uint8_t> bytes,
|
Vector<const uint8_t> bytes,
|
||||||
ExecutionTier mode) {
|
ExecutionTier mode) {
|
||||||
return base::make_unique<WasmCompilationUnit>(
|
return base::make_unique<WasmCompilationUnit>(
|
||||||
compilation_state_->wasm_engine(), compilation_state_->module_env(),
|
compilation_state_->wasm_engine(), native_module_,
|
||||||
native_module_,
|
|
||||||
FunctionBody{function->sig, buffer_offset, bytes.begin(), bytes.end()},
|
FunctionBody{function->sig, buffer_offset, bytes.begin(), bytes.end()},
|
||||||
function->func_index,
|
function->func_index,
|
||||||
compilation_state_->isolate()->async_counters().get(), mode);
|
compilation_state_->isolate()->async_counters().get(), mode);
|
||||||
@ -489,20 +485,12 @@ double MonotonicallyIncreasingTimeInMs() {
|
|||||||
base::Time::kMillisecondsPerSecond;
|
base::Time::kMillisecondsPerSecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleEnv CreateDefaultModuleEnv(const WasmModule* module,
|
|
||||||
bool allow_trap_handler = true) {
|
|
||||||
UseTrapHandler use_trap_handler =
|
|
||||||
trap_handler::IsTrapHandlerEnabled() && allow_trap_handler
|
|
||||||
? kUseTrapHandler
|
|
||||||
: kNoTrapHandler;
|
|
||||||
return ModuleEnv(module, use_trap_handler, kRuntimeExceptionSupport);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run by each compilation task and by the main thread (i.e. in both
|
// Run by each compilation task and by the main thread (i.e. in both
|
||||||
// foreground and background threads). The no_finisher_callback is called
|
// foreground and background threads). The no_finisher_callback is called
|
||||||
// within the result_mutex_ lock when no finishing task is running, i.e. when
|
// within the result_mutex_ lock when no finishing task is running, i.e. when
|
||||||
// the finisher_is_running_ flag is not set.
|
// the finisher_is_running_ flag is not set.
|
||||||
bool FetchAndExecuteCompilationUnit(CompilationState* compilation_state,
|
bool FetchAndExecuteCompilationUnit(ModuleEnv* env,
|
||||||
|
CompilationState* compilation_state,
|
||||||
WasmFeatures* detected) {
|
WasmFeatures* detected) {
|
||||||
DisallowHeapAccess no_heap_access;
|
DisallowHeapAccess no_heap_access;
|
||||||
|
|
||||||
@ -516,7 +504,7 @@ bool FetchAndExecuteCompilationUnit(CompilationState* compilation_state,
|
|||||||
// later as soon as Liftoff can compile any function. Then, we can directly
|
// later as soon as Liftoff can compile any function. Then, we can directly
|
||||||
// access {unit->mode()} within {ScheduleUnitForFinishing()}.
|
// access {unit->mode()} within {ScheduleUnitForFinishing()}.
|
||||||
ExecutionTier mode = unit->mode();
|
ExecutionTier mode = unit->mode();
|
||||||
unit->ExecuteCompilation(detected);
|
unit->ExecuteCompilation(env, detected);
|
||||||
compilation_state->ScheduleUnitForFinishing(std::move(unit), mode);
|
compilation_state->ScheduleUnitForFinishing(std::move(unit), mode);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -615,8 +603,9 @@ void CompileInParallel(Isolate* isolate, NativeModule* native_module,
|
|||||||
// The foreground task bypasses waiting on memory threshold, because
|
// The foreground task bypasses waiting on memory threshold, because
|
||||||
// its results will immediately be converted to code (below).
|
// its results will immediately be converted to code (below).
|
||||||
WasmFeatures detected_features;
|
WasmFeatures detected_features;
|
||||||
while (
|
ModuleEnv env = native_module->CreateModuleEnv();
|
||||||
FetchAndExecuteCompilationUnit(compilation_state, &detected_features) &&
|
while (FetchAndExecuteCompilationUnit(&env, compilation_state,
|
||||||
|
&detected_features) &&
|
||||||
!compilation_state->baseline_compilation_finished()) {
|
!compilation_state->baseline_compilation_finished()) {
|
||||||
// 2.b) If {baseline_finish_units_} contains a compilation unit, the main
|
// 2.b) If {baseline_finish_units_} contains a compilation unit, the main
|
||||||
// thread dequeues it and finishes the compilation unit. Compilation
|
// thread dequeues it and finishes the compilation unit. Compilation
|
||||||
@ -652,11 +641,11 @@ void CompileInParallel(Isolate* isolate, NativeModule* native_module,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CompileSequentially(Isolate* isolate, NativeModule* native_module,
|
void CompileSequentially(Isolate* isolate, NativeModule* native_module,
|
||||||
ModuleEnv* module_env, ErrorThrower* thrower) {
|
ErrorThrower* thrower) {
|
||||||
DCHECK(!thrower->error());
|
DCHECK(!thrower->error());
|
||||||
|
|
||||||
ModuleWireBytes wire_bytes(native_module->wire_bytes());
|
ModuleWireBytes wire_bytes(native_module->wire_bytes());
|
||||||
const WasmModule* module = module_env->module;
|
const WasmModule* module = native_module->module();
|
||||||
WasmFeatures detected = kNoWasmFeatures;
|
WasmFeatures detected = kNoWasmFeatures;
|
||||||
for (uint32_t i = 0; i < module->functions.size(); ++i) {
|
for (uint32_t i = 0; i < module->functions.size(); ++i) {
|
||||||
const WasmFunction& func = module->functions[i];
|
const WasmFunction& func = module->functions[i];
|
||||||
@ -664,7 +653,7 @@ void CompileSequentially(Isolate* isolate, NativeModule* native_module,
|
|||||||
|
|
||||||
// Compile the function.
|
// Compile the function.
|
||||||
WasmCode* code = WasmCompilationUnit::CompileWasmFunction(
|
WasmCode* code = WasmCompilationUnit::CompileWasmFunction(
|
||||||
isolate, native_module, &detected, thrower, module_env, &func);
|
isolate, native_module, &detected, thrower, &func);
|
||||||
if (code == nullptr) {
|
if (code == nullptr) {
|
||||||
TruncatedUserString<> name(wire_bytes.GetNameOrNull(&func, module));
|
TruncatedUserString<> name(wire_bytes.GetNameOrNull(&func, module));
|
||||||
thrower->CompileError("Compilation of #%d:%.*s failed.", i, name.length(),
|
thrower->CompileError("Compilation of #%d:%.*s failed.", i, name.length(),
|
||||||
@ -713,7 +702,7 @@ void ValidateSequentially(Isolate* isolate, NativeModule* native_module,
|
|||||||
|
|
||||||
void CompileNativeModule(Isolate* isolate, ErrorThrower* thrower,
|
void CompileNativeModule(Isolate* isolate, ErrorThrower* thrower,
|
||||||
Handle<WasmModuleObject> module_object,
|
Handle<WasmModuleObject> module_object,
|
||||||
const WasmModule* wasm_module, ModuleEnv* env) {
|
const WasmModule* wasm_module) {
|
||||||
NativeModule* const native_module = module_object->native_module();
|
NativeModule* const native_module = module_object->native_module();
|
||||||
ModuleWireBytes wire_bytes(native_module->wire_bytes());
|
ModuleWireBytes wire_bytes(native_module->wire_bytes());
|
||||||
|
|
||||||
@ -741,7 +730,7 @@ void CompileNativeModule(Isolate* isolate, ErrorThrower* thrower,
|
|||||||
if (compile_parallel) {
|
if (compile_parallel) {
|
||||||
CompileInParallel(isolate, native_module, module_object, thrower);
|
CompileInParallel(isolate, native_module, module_object, thrower);
|
||||||
} else {
|
} else {
|
||||||
CompileSequentially(isolate, native_module, env, thrower);
|
CompileSequentially(isolate, native_module, thrower);
|
||||||
}
|
}
|
||||||
if (thrower->error()) return;
|
if (thrower->error()) return;
|
||||||
}
|
}
|
||||||
@ -829,25 +818,27 @@ class FinishCompileTask : public CancelableTask {
|
|||||||
// The runnable task that performs compilations in the background.
|
// The runnable task that performs compilations in the background.
|
||||||
class BackgroundCompileTask : public CancelableTask {
|
class BackgroundCompileTask : public CancelableTask {
|
||||||
public:
|
public:
|
||||||
explicit BackgroundCompileTask(CompilationState* compilation_state,
|
explicit BackgroundCompileTask(NativeModule* native_module,
|
||||||
CancelableTaskManager* task_manager)
|
CancelableTaskManager* task_manager)
|
||||||
: CancelableTask(task_manager), compilation_state_(compilation_state) {}
|
: CancelableTask(task_manager), native_module_(native_module) {}
|
||||||
|
|
||||||
void RunInternal() override {
|
void RunInternal() override {
|
||||||
TRACE_COMPILE("(3b) Compiling...\n");
|
TRACE_COMPILE("(3b) Compiling...\n");
|
||||||
// The number of currently running background tasks is reduced in
|
// The number of currently running background tasks is reduced in
|
||||||
// {OnBackgroundTaskStopped}.
|
// {OnBackgroundTaskStopped}.
|
||||||
while (!compilation_state_->failed()) {
|
ModuleEnv env = native_module_->CreateModuleEnv();
|
||||||
if (!FetchAndExecuteCompilationUnit(compilation_state_,
|
auto* compilation_state = native_module_->compilation_state();
|
||||||
|
while (!compilation_state->failed()) {
|
||||||
|
if (!FetchAndExecuteCompilationUnit(&env, compilation_state,
|
||||||
&detected_features_)) {
|
&detected_features_)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compilation_state_->OnBackgroundTaskStopped(detected_features_);
|
compilation_state->OnBackgroundTaskStopped(detected_features_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CompilationState* compilation_state_;
|
NativeModule* const native_module_;
|
||||||
WasmFeatures detected_features_ = kNoWasmFeatures;
|
WasmFeatures detected_features_ = kNoWasmFeatures;
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -893,16 +884,15 @@ MaybeHandle<WasmModuleObject> CompileToModuleObject(
|
|||||||
// TODO(clemensh): For the same module (same bytes / same hash), we should
|
// TODO(clemensh): For the same module (same bytes / same hash), we should
|
||||||
// only have one WasmModuleObject. Otherwise, we might only set
|
// only have one WasmModuleObject. Otherwise, we might only set
|
||||||
// breakpoints on a (potentially empty) subset of the instances.
|
// breakpoints on a (potentially empty) subset of the instances.
|
||||||
ModuleEnv env = CreateDefaultModuleEnv(wasm_module);
|
|
||||||
|
|
||||||
// Create the compiled module object and populate with compiled functions
|
// Create the compiled module object and populate with compiled functions
|
||||||
// and information needed at instantiation time. This object needs to be
|
// and information needed at instantiation time. This object needs to be
|
||||||
// serializable. Instantiation may occur off a deserialized version of this
|
// serializable. Instantiation may occur off a deserialized version of this
|
||||||
// object.
|
// object.
|
||||||
Handle<WasmModuleObject> module_object = WasmModuleObject::New(
|
Handle<WasmModuleObject> module_object = WasmModuleObject::New(
|
||||||
isolate, enabled, std::move(module), env, std::move(wire_bytes_copy),
|
isolate, enabled, std::move(module), std::move(wire_bytes_copy), script,
|
||||||
script, asm_js_offset_table);
|
asm_js_offset_table);
|
||||||
CompileNativeModule(isolate, thrower, module_object, wasm_module, &env);
|
CompileNativeModule(isolate, thrower, module_object, wasm_module);
|
||||||
if (thrower->error()) return {};
|
if (thrower->error()) return {};
|
||||||
|
|
||||||
// Compile JS->wasm wrappers for exported functions.
|
// Compile JS->wasm wrappers for exported functions.
|
||||||
@ -1013,14 +1003,15 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
|
|||||||
|
|
||||||
TRACE("Recompiling module without bounds checks\n");
|
TRACE("Recompiling module without bounds checks\n");
|
||||||
constexpr bool allow_trap_handler = false;
|
constexpr bool allow_trap_handler = false;
|
||||||
ModuleEnv env = CreateDefaultModuleEnv(module_, allow_trap_handler);
|
// TODO(wasm): Fix this before enabling the trap handler fallback.
|
||||||
|
USE(allow_trap_handler);
|
||||||
// Disable trap handlers on this native module.
|
// Disable trap handlers on this native module.
|
||||||
NativeModule* native_module = module_object_->native_module();
|
NativeModule* native_module = module_object_->native_module();
|
||||||
native_module->DisableTrapHandler();
|
native_module->DisableTrapHandler();
|
||||||
|
|
||||||
// Recompile all functions in this native module.
|
// Recompile all functions in this native module.
|
||||||
ErrorThrower thrower(isolate_, "recompile");
|
ErrorThrower thrower(isolate_, "recompile");
|
||||||
CompileNativeModule(isolate_, &thrower, module_object_, module_, &env);
|
CompileNativeModule(isolate_, &thrower, module_object_, module_);
|
||||||
if (thrower.error()) {
|
if (thrower.error()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -2483,7 +2474,6 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
|
|||||||
module->source_map_url);
|
module->source_map_url);
|
||||||
Handle<ByteArray> asm_js_offset_table;
|
Handle<ByteArray> asm_js_offset_table;
|
||||||
|
|
||||||
ModuleEnv env = CreateDefaultModuleEnv(module);
|
|
||||||
// TODO(wasm): Improve efficiency of storing module wire bytes. Only store
|
// TODO(wasm): Improve efficiency of storing module wire bytes. Only store
|
||||||
// relevant sections, not function bodies
|
// relevant sections, not function bodies
|
||||||
|
|
||||||
@ -2494,7 +2484,7 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
|
|||||||
// breakpoints on a (potentially empty) subset of the instances.
|
// breakpoints on a (potentially empty) subset of the instances.
|
||||||
// Create the module object.
|
// Create the module object.
|
||||||
job_->module_object_ = WasmModuleObject::New(
|
job_->module_object_ = WasmModuleObject::New(
|
||||||
job_->isolate_, job_->enabled_features_, module_, env,
|
job_->isolate_, job_->enabled_features_, module_,
|
||||||
{std::move(job_->bytes_copy_), job_->wire_bytes_.length()}, script,
|
{std::move(job_->bytes_copy_), job_->wire_bytes_.length()}, script,
|
||||||
asm_js_offset_table);
|
asm_js_offset_table);
|
||||||
job_->native_module_ = job_->module_object_->native_module();
|
job_->native_module_ = job_->module_object_->native_module();
|
||||||
@ -2850,21 +2840,18 @@ void CompilationStateDeleter::operator()(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CompilationState, CompilationStateDeleter> NewCompilationState(
|
std::unique_ptr<CompilationState, CompilationStateDeleter> NewCompilationState(
|
||||||
Isolate* isolate, const ModuleEnv& env) {
|
Isolate* isolate, NativeModule* native_module) {
|
||||||
return std::unique_ptr<CompilationState, CompilationStateDeleter>(
|
return std::unique_ptr<CompilationState, CompilationStateDeleter>(
|
||||||
new CompilationState(isolate, env));
|
new CompilationState(isolate, native_module));
|
||||||
}
|
|
||||||
|
|
||||||
ModuleEnv* GetModuleEnv(CompilationState* compilation_state) {
|
|
||||||
return compilation_state->module_env();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CompilationState::CompilationState(internal::Isolate* isolate,
|
CompilationState::CompilationState(internal::Isolate* isolate,
|
||||||
const ModuleEnv& env)
|
NativeModule* native_module)
|
||||||
: isolate_(isolate),
|
: isolate_(isolate),
|
||||||
wasm_engine_(isolate->wasm_engine()),
|
wasm_engine_(isolate->wasm_engine()),
|
||||||
module_env_(env),
|
native_module_(native_module),
|
||||||
compile_mode_(FLAG_wasm_tier_up && env.module->origin == kWasmOrigin
|
compile_mode_(FLAG_wasm_tier_up &&
|
||||||
|
native_module->module()->origin == kWasmOrigin
|
||||||
? CompileMode::kTiering
|
? CompileMode::kTiering
|
||||||
: CompileMode::kRegular),
|
: CompileMode::kRegular),
|
||||||
max_background_tasks_(std::max(
|
max_background_tasks_(std::max(
|
||||||
@ -3042,7 +3029,7 @@ void CompilationState::RestartBackgroundTasks(size_t max) {
|
|||||||
|
|
||||||
for (; num_restart > 0; --num_restart) {
|
for (; num_restart > 0; --num_restart) {
|
||||||
auto task = base::make_unique<BackgroundCompileTask>(
|
auto task = base::make_unique<BackgroundCompileTask>(
|
||||||
this, &background_task_manager_);
|
native_module_, &background_task_manager_);
|
||||||
|
|
||||||
// If --wasm-num-compilation-tasks=0 is passed, do only spawn foreground
|
// If --wasm-num-compilation-tasks=0 is passed, do only spawn foreground
|
||||||
// tasks. This is used to make timing deterministic.
|
// tasks. This is used to make timing deterministic.
|
||||||
|
@ -150,9 +150,8 @@ void WasmCode::LogCode(Isolate* isolate) const {
|
|||||||
|
|
||||||
ModuleWireBytes wire_bytes(native_module()->wire_bytes());
|
ModuleWireBytes wire_bytes(native_module()->wire_bytes());
|
||||||
// TODO(herhut): Allow to log code without on-heap round-trip of the name.
|
// TODO(herhut): Allow to log code without on-heap round-trip of the name.
|
||||||
ModuleEnv* module_env = GetModuleEnv(native_module()->compilation_state());
|
|
||||||
WireBytesRef name_ref =
|
WireBytesRef name_ref =
|
||||||
module_env->module->LookupFunctionName(wire_bytes, index());
|
native_module()->module()->LookupFunctionName(wire_bytes, index());
|
||||||
WasmName name_vec = wire_bytes.GetNameOrNull(name_ref);
|
WasmName name_vec = wire_bytes.GetNameOrNull(name_ref);
|
||||||
if (!name_vec.is_empty()) {
|
if (!name_vec.is_empty()) {
|
||||||
MaybeHandle<String> maybe_name = isolate->factory()->NewStringFromUtf8(
|
MaybeHandle<String> maybe_name = isolate->factory()->NewStringFromUtf8(
|
||||||
@ -339,18 +338,17 @@ WasmCode::~WasmCode() {
|
|||||||
NativeModule::NativeModule(Isolate* isolate, const WasmFeatures& enabled,
|
NativeModule::NativeModule(Isolate* isolate, const WasmFeatures& enabled,
|
||||||
bool can_request_more, VirtualMemory code_space,
|
bool can_request_more, VirtualMemory code_space,
|
||||||
WasmCodeManager* code_manager,
|
WasmCodeManager* code_manager,
|
||||||
std::shared_ptr<const WasmModule> module,
|
std::shared_ptr<const WasmModule> module)
|
||||||
const ModuleEnv& env)
|
|
||||||
: enabled_features_(enabled),
|
: enabled_features_(enabled),
|
||||||
module_(std::move(module)),
|
module_(std::move(module)),
|
||||||
compilation_state_(NewCompilationState(isolate, env)),
|
compilation_state_(NewCompilationState(isolate, this)),
|
||||||
import_wrapper_cache_(std::unique_ptr<WasmImportWrapperCache>(
|
import_wrapper_cache_(std::unique_ptr<WasmImportWrapperCache>(
|
||||||
new WasmImportWrapperCache(this))),
|
new WasmImportWrapperCache(this))),
|
||||||
free_code_space_(code_space.region()),
|
free_code_space_(code_space.region()),
|
||||||
wasm_code_manager_(code_manager),
|
wasm_code_manager_(code_manager),
|
||||||
can_request_more_memory_(can_request_more),
|
can_request_more_memory_(can_request_more),
|
||||||
use_trap_handler_(env.use_trap_handler) {
|
use_trap_handler_(trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler
|
||||||
DCHECK_EQ(module_.get(), env.module);
|
: kNoTrapHandler) {
|
||||||
DCHECK_NOT_NULL(module_);
|
DCHECK_NOT_NULL(module_);
|
||||||
owned_code_space_.emplace_back(std::move(code_space));
|
owned_code_space_.emplace_back(std::move(code_space));
|
||||||
owned_code_.reserve(num_functions());
|
owned_code_.reserve(num_functions());
|
||||||
@ -386,6 +384,10 @@ void NativeModule::LogWasmCodes(Isolate* isolate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModuleEnv NativeModule::CreateModuleEnv() const {
|
||||||
|
return {module(), use_trap_handler_, kRuntimeExceptionSupport};
|
||||||
|
}
|
||||||
|
|
||||||
WasmCode* NativeModule::AddOwnedCode(
|
WasmCode* NativeModule::AddOwnedCode(
|
||||||
uint32_t index, Vector<const byte> instructions, uint32_t stack_slots,
|
uint32_t index, Vector<const byte> instructions, uint32_t stack_slots,
|
||||||
size_t safepoint_table_offset, size_t handler_table_offset,
|
size_t safepoint_table_offset, size_t handler_table_offset,
|
||||||
@ -932,8 +934,7 @@ bool WasmCodeManager::ShouldForceCriticalMemoryPressureNotification() {
|
|||||||
|
|
||||||
std::unique_ptr<NativeModule> WasmCodeManager::NewNativeModule(
|
std::unique_ptr<NativeModule> WasmCodeManager::NewNativeModule(
|
||||||
Isolate* isolate, const WasmFeatures& enabled, size_t memory_estimate,
|
Isolate* isolate, const WasmFeatures& enabled, size_t memory_estimate,
|
||||||
bool can_request_more, std::shared_ptr<const WasmModule> module,
|
bool can_request_more, std::shared_ptr<const WasmModule> module) {
|
||||||
const ModuleEnv& env) {
|
|
||||||
if (ShouldForceCriticalMemoryPressureNotification()) {
|
if (ShouldForceCriticalMemoryPressureNotification()) {
|
||||||
(reinterpret_cast<v8::Isolate*>(isolate))
|
(reinterpret_cast<v8::Isolate*>(isolate))
|
||||||
->MemoryPressureNotification(MemoryPressureLevel::kCritical);
|
->MemoryPressureNotification(MemoryPressureLevel::kCritical);
|
||||||
@ -963,7 +964,7 @@ std::unique_ptr<NativeModule> WasmCodeManager::NewNativeModule(
|
|||||||
Address end = mem.end();
|
Address end = mem.end();
|
||||||
std::unique_ptr<NativeModule> ret(
|
std::unique_ptr<NativeModule> ret(
|
||||||
new NativeModule(isolate, enabled, can_request_more, std::move(mem), this,
|
new NativeModule(isolate, enabled, can_request_more, std::move(mem), this,
|
||||||
std::move(module), env));
|
std::move(module)));
|
||||||
TRACE_HEAP("New NativeModule %p: Mem: %" PRIuPTR ",+%zu\n", this, start,
|
TRACE_HEAP("New NativeModule %p: Mem: %" PRIuPTR ",+%zu\n", this, start,
|
||||||
size);
|
size);
|
||||||
AssignRangesAndAddModule(start, end, ret.get());
|
AssignRangesAndAddModule(start, end, ret.get());
|
||||||
|
@ -314,6 +314,10 @@ class V8_EXPORT_PRIVATE NativeModule final {
|
|||||||
|
|
||||||
CompilationState* compilation_state() { return compilation_state_.get(); }
|
CompilationState* compilation_state() { return compilation_state_.get(); }
|
||||||
|
|
||||||
|
// Create a {ModuleEnv} object for compilation. Only valid as long as this
|
||||||
|
// {NativeModule} is alive.
|
||||||
|
ModuleEnv CreateModuleEnv() const;
|
||||||
|
|
||||||
uint32_t num_functions() const {
|
uint32_t num_functions() const {
|
||||||
return module_->num_declared_functions + module_->num_imported_functions;
|
return module_->num_declared_functions + module_->num_imported_functions;
|
||||||
}
|
}
|
||||||
@ -349,7 +353,7 @@ class V8_EXPORT_PRIVATE NativeModule final {
|
|||||||
NativeModule(Isolate* isolate, const WasmFeatures& enabled_features,
|
NativeModule(Isolate* isolate, const WasmFeatures& enabled_features,
|
||||||
bool can_request_more, VirtualMemory code_space,
|
bool can_request_more, VirtualMemory code_space,
|
||||||
WasmCodeManager* code_manager,
|
WasmCodeManager* code_manager,
|
||||||
std::shared_ptr<const WasmModule> module, const ModuleEnv& env);
|
std::shared_ptr<const WasmModule> module);
|
||||||
|
|
||||||
WasmCode* AddAnonymousCode(Handle<Code>, WasmCode::Kind kind,
|
WasmCode* AddAnonymousCode(Handle<Code>, WasmCode::Kind kind,
|
||||||
const char* name = nullptr);
|
const char* name = nullptr);
|
||||||
@ -473,7 +477,7 @@ class V8_EXPORT_PRIVATE WasmCodeManager final {
|
|||||||
std::unique_ptr<NativeModule> NewNativeModule(
|
std::unique_ptr<NativeModule> NewNativeModule(
|
||||||
Isolate* isolate, const WasmFeatures& enabled_features,
|
Isolate* isolate, const WasmFeatures& enabled_features,
|
||||||
size_t memory_estimate, bool can_request_more,
|
size_t memory_estimate, bool can_request_more,
|
||||||
std::shared_ptr<const WasmModule> module, const ModuleEnv& env);
|
std::shared_ptr<const WasmModule> module);
|
||||||
|
|
||||||
NativeModule* LookupNativeModule(Address pc) const;
|
NativeModule* LookupNativeModule(Address pc) const;
|
||||||
WasmCode* LookupCode(Address pc) const;
|
WasmCode* LookupCode(Address pc) const;
|
||||||
|
@ -178,7 +178,6 @@ bool WasmEngine::CompileFunction(Isolate* isolate, NativeModule* native_module,
|
|||||||
WasmFeatures detected = kNoWasmFeatures;
|
WasmFeatures detected = kNoWasmFeatures;
|
||||||
WasmCode* ret = WasmCompilationUnit::CompileWasmFunction(
|
WasmCode* ret = WasmCompilationUnit::CompileWasmFunction(
|
||||||
isolate, native_module, &detected, &thrower,
|
isolate, native_module, &detected, &thrower,
|
||||||
GetModuleEnv(native_module->compilation_state()),
|
|
||||||
&native_module->module()->functions[function_index], tier);
|
&native_module->module()->functions[function_index], tier);
|
||||||
return ret != nullptr;
|
return ret != nullptr;
|
||||||
}
|
}
|
||||||
|
@ -175,19 +175,16 @@ enum DispatchTableElements : int {
|
|||||||
// static
|
// static
|
||||||
Handle<WasmModuleObject> WasmModuleObject::New(
|
Handle<WasmModuleObject> WasmModuleObject::New(
|
||||||
Isolate* isolate, const wasm::WasmFeatures& enabled,
|
Isolate* isolate, const wasm::WasmFeatures& enabled,
|
||||||
std::shared_ptr<const wasm::WasmModule> shared_module, wasm::ModuleEnv& env,
|
std::shared_ptr<const wasm::WasmModule> shared_module,
|
||||||
OwnedVector<const uint8_t> wire_bytes, Handle<Script> script,
|
OwnedVector<const uint8_t> wire_bytes, Handle<Script> script,
|
||||||
Handle<ByteArray> asm_js_offset_table) {
|
Handle<ByteArray> asm_js_offset_table) {
|
||||||
DCHECK_EQ(shared_module.get(), env.module);
|
|
||||||
|
|
||||||
// Create a new {NativeModule} first.
|
// Create a new {NativeModule} first.
|
||||||
size_t native_memory_estimate =
|
size_t native_memory_estimate =
|
||||||
isolate->wasm_engine()->code_manager()->EstimateNativeModuleSize(
|
isolate->wasm_engine()->code_manager()->EstimateNativeModuleSize(
|
||||||
env.module);
|
shared_module.get());
|
||||||
auto native_module = isolate->wasm_engine()->code_manager()->NewNativeModule(
|
auto native_module = isolate->wasm_engine()->code_manager()->NewNativeModule(
|
||||||
isolate, enabled, native_memory_estimate,
|
isolate, enabled, native_memory_estimate,
|
||||||
wasm::NativeModule::kCanAllocateMoreMemory, std::move(shared_module),
|
wasm::NativeModule::kCanAllocateMoreMemory, std::move(shared_module));
|
||||||
env);
|
|
||||||
native_module->set_wire_bytes(std::move(wire_bytes));
|
native_module->set_wire_bytes(std::move(wire_bytes));
|
||||||
native_module->SetRuntimeStubs(isolate);
|
native_module->SetRuntimeStubs(isolate);
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ class WasmModuleObject : public JSObject {
|
|||||||
// Creates a new {WasmModuleObject} with a new {NativeModule} underneath.
|
// Creates a new {WasmModuleObject} with a new {NativeModule} underneath.
|
||||||
static Handle<WasmModuleObject> New(
|
static Handle<WasmModuleObject> New(
|
||||||
Isolate* isolate, const wasm::WasmFeatures& enabled,
|
Isolate* isolate, const wasm::WasmFeatures& enabled,
|
||||||
std::shared_ptr<const wasm::WasmModule> module, wasm::ModuleEnv& env,
|
std::shared_ptr<const wasm::WasmModule> module,
|
||||||
OwnedVector<const uint8_t> wire_bytes, Handle<Script> script,
|
OwnedVector<const uint8_t> wire_bytes, Handle<Script> script,
|
||||||
Handle<ByteArray> asm_js_offset_table);
|
Handle<ByteArray> asm_js_offset_table);
|
||||||
|
|
||||||
|
@ -268,6 +268,9 @@ size_t NativeModuleSerializer::Measure() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NativeModuleSerializer::WriteHeader(Writer* writer) {
|
void NativeModuleSerializer::WriteHeader(Writer* writer) {
|
||||||
|
// TODO(eholk): We need to properly preserve the flag whether the trap
|
||||||
|
// handler was used or not when serializing.
|
||||||
|
|
||||||
writer->Write(native_module_->num_functions());
|
writer->Write(native_module_->num_functions());
|
||||||
writer->Write(native_module_->num_imported_functions());
|
writer->Write(native_module_->num_imported_functions());
|
||||||
}
|
}
|
||||||
@ -555,17 +558,10 @@ MaybeHandle<WasmModuleObject> DeserializeNativeModule(
|
|||||||
Handle<Script> script =
|
Handle<Script> script =
|
||||||
CreateWasmScript(isolate, wire_bytes, module->source_map_url);
|
CreateWasmScript(isolate, wire_bytes, module->source_map_url);
|
||||||
|
|
||||||
// TODO(eholk): We need to properly preserve the flag whether the trap
|
|
||||||
// handler was used or not when serializing.
|
|
||||||
UseTrapHandler use_trap_handler =
|
|
||||||
trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler : kNoTrapHandler;
|
|
||||||
ModuleEnv env(module, use_trap_handler,
|
|
||||||
RuntimeExceptionSupport::kRuntimeExceptionSupport);
|
|
||||||
|
|
||||||
OwnedVector<uint8_t> wire_bytes_copy = OwnedVector<uint8_t>::Of(wire_bytes);
|
OwnedVector<uint8_t> wire_bytes_copy = OwnedVector<uint8_t>::Of(wire_bytes);
|
||||||
|
|
||||||
Handle<WasmModuleObject> module_object = WasmModuleObject::New(
|
Handle<WasmModuleObject> module_object = WasmModuleObject::New(
|
||||||
isolate, enabled_features, std::move(decode_result).value(), env,
|
isolate, enabled_features, std::move(decode_result).value(),
|
||||||
std::move(wire_bytes_copy), script, Handle<ByteArray>::null());
|
std::move(wire_bytes_copy), script, Handle<ByteArray>::null());
|
||||||
NativeModule* native_module = module_object->native_module();
|
NativeModule* native_module = module_object->native_module();
|
||||||
|
|
||||||
|
@ -123,15 +123,11 @@ std::unique_ptr<wasm::NativeModule> AllocateNativeModule(Isolate* isolate,
|
|||||||
size_t code_size) {
|
size_t code_size) {
|
||||||
std::shared_ptr<wasm::WasmModule> module(new wasm::WasmModule());
|
std::shared_ptr<wasm::WasmModule> module(new wasm::WasmModule());
|
||||||
module->num_declared_functions = 1;
|
module->num_declared_functions = 1;
|
||||||
wasm::ModuleEnv env(
|
|
||||||
module.get(), wasm::UseTrapHandler::kNoTrapHandler,
|
|
||||||
wasm::RuntimeExceptionSupport::kNoRuntimeExceptionSupport);
|
|
||||||
// We have to add the code object to a NativeModule, because the
|
// We have to add the code object to a NativeModule, because the
|
||||||
// WasmCallDescriptor assumes that code is on the native heap and not
|
// WasmCallDescriptor assumes that code is on the native heap and not
|
||||||
// within a code object.
|
// within a code object.
|
||||||
return isolate->wasm_engine()->code_manager()->NewNativeModule(
|
return isolate->wasm_engine()->code_manager()->NewNativeModule(
|
||||||
isolate, wasm::kAllWasmFeatures, code_size, false, std::move(module),
|
isolate, wasm::kAllWasmFeatures, code_size, false, std::move(module));
|
||||||
env);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestReturnMultipleValues(MachineType type) {
|
void TestReturnMultipleValues(MachineType type) {
|
||||||
|
@ -22,11 +22,8 @@ std::unique_ptr<NativeModule> NewModule(Isolate* isolate) {
|
|||||||
std::shared_ptr<WasmModule> module(new WasmModule);
|
std::shared_ptr<WasmModule> module(new WasmModule);
|
||||||
bool can_request_more = false;
|
bool can_request_more = false;
|
||||||
size_t size = 100;
|
size_t size = 100;
|
||||||
ModuleEnv env(module.get(), UseTrapHandler::kNoTrapHandler,
|
auto native_module = manager->NewNativeModule(
|
||||||
RuntimeExceptionSupport::kNoRuntimeExceptionSupport);
|
isolate, kAllWasmFeatures, size, can_request_more, std::move(module));
|
||||||
auto native_module =
|
|
||||||
manager->NewNativeModule(isolate, kAllWasmFeatures, size,
|
|
||||||
can_request_more, std::move(module), env);
|
|
||||||
native_module->SetRuntimeStubs(isolate);
|
native_module->SetRuntimeStubs(isolate);
|
||||||
return native_module;
|
return native_module;
|
||||||
}
|
}
|
||||||
|
@ -354,7 +354,6 @@ TEST(SharedEngineRunThreadedTierUp) {
|
|||||||
WasmFeatures detected = kNoWasmFeatures;
|
WasmFeatures detected = kNoWasmFeatures;
|
||||||
WasmCompilationUnit::CompileWasmFunction(
|
WasmCompilationUnit::CompileWasmFunction(
|
||||||
isolate.isolate(), module.get(), &detected, &thrower,
|
isolate.isolate(), module.get(), &detected, &thrower,
|
||||||
GetModuleEnv(module->compilation_state()),
|
|
||||||
&module->module()->functions[0], ExecutionTier::kOptimized);
|
&module->module()->functions[0], ExecutionTier::kOptimized);
|
||||||
CHECK_EQ(23, isolate.Run(instance));
|
CHECK_EQ(23, isolate.Run(instance));
|
||||||
});
|
});
|
||||||
|
@ -209,9 +209,8 @@ Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() {
|
|||||||
Handle<Script> script =
|
Handle<Script> script =
|
||||||
isolate_->factory()->NewScript(isolate_->factory()->empty_string());
|
isolate_->factory()->NewScript(isolate_->factory()->empty_string());
|
||||||
script->set_type(Script::TYPE_WASM);
|
script->set_type(Script::TYPE_WASM);
|
||||||
ModuleEnv env = CreateModuleEnv();
|
|
||||||
Handle<WasmModuleObject> module_object =
|
Handle<WasmModuleObject> module_object =
|
||||||
WasmModuleObject::New(isolate_, enabled_features_, test_module_, env, {},
|
WasmModuleObject::New(isolate_, enabled_features_, test_module_, {},
|
||||||
script, Handle<ByteArray>::null());
|
script, Handle<ByteArray>::null());
|
||||||
// This method is called when we initialize TestEnvironment. We don't
|
// This method is called when we initialize TestEnvironment. We don't
|
||||||
// have a memory yet, so we won't create it here. We'll update the
|
// have a memory yet, so we won't create it here. We'll update the
|
||||||
@ -411,7 +410,7 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) {
|
|||||||
->native_module()
|
->native_module()
|
||||||
->wire_bytes();
|
->wire_bytes();
|
||||||
|
|
||||||
ModuleEnv module_env = builder_->CreateModuleEnv();
|
ModuleEnv env = builder_->CreateModuleEnv();
|
||||||
ScopedVector<uint8_t> func_wire_bytes(function_->code.length());
|
ScopedVector<uint8_t> func_wire_bytes(function_->code.length());
|
||||||
memcpy(func_wire_bytes.start(), wire_bytes.start() + function_->code.offset(),
|
memcpy(func_wire_bytes.start(), wire_bytes.start() + function_->code.offset(),
|
||||||
func_wire_bytes.length());
|
func_wire_bytes.length());
|
||||||
@ -420,11 +419,10 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) {
|
|||||||
func_wire_bytes.start(), func_wire_bytes.end()};
|
func_wire_bytes.start(), func_wire_bytes.end()};
|
||||||
NativeModule* native_module =
|
NativeModule* native_module =
|
||||||
builder_->instance_object()->module_object()->native_module();
|
builder_->instance_object()->module_object()->native_module();
|
||||||
WasmCompilationUnit unit(isolate()->wasm_engine(), &module_env, native_module,
|
WasmCompilationUnit unit(isolate()->wasm_engine(), native_module, func_body,
|
||||||
func_body, function_->func_index,
|
function_->func_index, isolate()->counters(), tier);
|
||||||
isolate()->counters(), tier);
|
|
||||||
WasmFeatures unused_detected_features;
|
WasmFeatures unused_detected_features;
|
||||||
unit.ExecuteCompilation(&unused_detected_features);
|
unit.ExecuteCompilation(&env, &unused_detected_features);
|
||||||
CHECK(!unit.failed());
|
CHECK(!unit.failed());
|
||||||
if (WasmCode::ShouldBeLogged(isolate())) unit.result()->LogCode(isolate());
|
if (WasmCode::ShouldBeLogged(isolate())) unit.result()->LogCode(isolate());
|
||||||
}
|
}
|
||||||
|
@ -138,16 +138,12 @@ std::unique_ptr<wasm::NativeModule> AllocateNativeModule(i::Isolate* isolate,
|
|||||||
size_t code_size) {
|
size_t code_size) {
|
||||||
std::shared_ptr<wasm::WasmModule> module(new wasm::WasmModule);
|
std::shared_ptr<wasm::WasmModule> module(new wasm::WasmModule);
|
||||||
module->num_declared_functions = 1;
|
module->num_declared_functions = 1;
|
||||||
wasm::ModuleEnv env(
|
|
||||||
module.get(), wasm::UseTrapHandler::kNoTrapHandler,
|
|
||||||
wasm::RuntimeExceptionSupport::kNoRuntimeExceptionSupport);
|
|
||||||
|
|
||||||
// We have to add the code object to a NativeModule, because the
|
// We have to add the code object to a NativeModule, because the
|
||||||
// WasmCallDescriptor assumes that code is on the native heap and not
|
// WasmCallDescriptor assumes that code is on the native heap and not
|
||||||
// within a code object.
|
// within a code object.
|
||||||
return isolate->wasm_engine()->code_manager()->NewNativeModule(
|
return isolate->wasm_engine()->code_manager()->NewNativeModule(
|
||||||
isolate, i::wasm::kAllWasmFeatures, code_size, false, std::move(module),
|
isolate, i::wasm::kAllWasmFeatures, code_size, false, std::move(module));
|
||||||
env);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
|
@ -165,10 +165,8 @@ class WasmCodeManagerTest : public TestWithContext,
|
|||||||
std::shared_ptr<WasmModule> module(new WasmModule);
|
std::shared_ptr<WasmModule> module(new WasmModule);
|
||||||
module->num_declared_functions = kNumFunctions;
|
module->num_declared_functions = kNumFunctions;
|
||||||
bool can_request_more = style == Growable;
|
bool can_request_more = style == Growable;
|
||||||
ModuleEnv env(module.get(), UseTrapHandler::kNoTrapHandler,
|
|
||||||
RuntimeExceptionSupport::kNoRuntimeExceptionSupport);
|
|
||||||
return manager->NewNativeModule(i_isolate(), kAllWasmFeatures, size,
|
return manager->NewNativeModule(i_isolate(), kAllWasmFeatures, size,
|
||||||
can_request_more, std::move(module), env);
|
can_request_more, std::move(module));
|
||||||
}
|
}
|
||||||
|
|
||||||
WasmCode* AddCode(NativeModule* native_module, uint32_t index, size_t size) {
|
WasmCode* AddCode(NativeModule* native_module, uint32_t index, size_t size) {
|
||||||
|
Loading…
Reference in New Issue
Block a user