Commit ab6d5ed5 authored by Ben L. Titzer's avatar Ben L. Titzer Committed by Commit Bot

Reland "[wasm] Add feature counter for threads and shared memory"

This is a reland of b10a967f

Original change's description:
> [wasm] Add feature counter for threads and shared memory
> 
> This adds a feature counter for WASM shared memory (i.e. the presence
> of the "shared" bit in a WASM module's memory section) and the usage
> of WASM threads opcodes (i.e. wake/wait and atomics).
> 
> This CL also plumbs the WasmFeatures through the compilation pipeline
> to detect features as functions are being compiled.
> 
> R=ahaas@chromium.org, ulan@chromium.org
> BUG=chromium:868844
> 
> Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
> Change-Id: I854f932d3adb16e4fd87196fe2a193950295b856
> Reviewed-on: https://chromium-review.googlesource.com/1186329
> Reviewed-by: Andreas Haas <ahaas@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Commit-Queue: Ben Titzer <titzer@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#55337}

Bug: chromium:868844
Change-Id: Iac3a38d80fa71aadd7147704669a8fd671ecfae8
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/1186343
Commit-Queue: Ben Titzer <titzer@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55363}
parent 50e142c9
...@@ -5031,7 +5031,8 @@ TurbofanWasmCompilationUnit::TurbofanWasmCompilationUnit( ...@@ -5031,7 +5031,8 @@ TurbofanWasmCompilationUnit::TurbofanWasmCompilationUnit(
TurbofanWasmCompilationUnit::~TurbofanWasmCompilationUnit() = default; TurbofanWasmCompilationUnit::~TurbofanWasmCompilationUnit() = default;
SourcePositionTable* TurbofanWasmCompilationUnit::BuildGraphForWasmFunction( SourcePositionTable* TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
double* decode_ms, MachineGraph* mcgraph, NodeOriginTable* node_origins) { wasm::WasmFeatures* detected, double* decode_ms, 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();
...@@ -5042,14 +5043,10 @@ SourcePositionTable* TurbofanWasmCompilationUnit::BuildGraphForWasmFunction( ...@@ -5042,14 +5043,10 @@ SourcePositionTable* TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
new (mcgraph->zone()) SourcePositionTable(mcgraph->graph()); new (mcgraph->zone()) SourcePositionTable(mcgraph->graph());
WasmGraphBuilder builder(wasm_unit_->env_, mcgraph->zone(), mcgraph, WasmGraphBuilder builder(wasm_unit_->env_, mcgraph->zone(), mcgraph,
wasm_unit_->func_body_.sig, source_position_table); wasm_unit_->func_body_.sig, source_position_table);
// TODO(titzer): gather detected features into a per-module location
// in order to increment an embedder feature use count.
wasm::WasmFeatures unused_detected_features;
graph_construction_result_ = wasm::BuildTFGraph( 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(), wasm_unit_->env_->module,
&builder, &unused_detected_features, wasm_unit_->func_body_, &builder, detected, wasm_unit_->func_body_, node_origins);
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: "
...@@ -5102,7 +5099,8 @@ Vector<const char> GetDebugName(Zone* zone, wasm::WasmName name, int index) { ...@@ -5102,7 +5099,8 @@ Vector<const char> GetDebugName(Zone* zone, wasm::WasmName name, int index) {
} // namespace } // namespace
void TurbofanWasmCompilationUnit::ExecuteCompilation() { void TurbofanWasmCompilationUnit::ExecuteCompilation(
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;
...@@ -5134,7 +5132,7 @@ void TurbofanWasmCompilationUnit::ExecuteCompilation() { ...@@ -5134,7 +5132,7 @@ void TurbofanWasmCompilationUnit::ExecuteCompilation() {
NodeOriginTable(mcgraph->graph()) NodeOriginTable(mcgraph->graph())
: nullptr; : nullptr;
SourcePositionTable* source_positions = SourcePositionTable* source_positions =
BuildGraphForWasmFunction(&decode_ms, mcgraph, node_origins); BuildGraphForWasmFunction(detected, &decode_ms, mcgraph, node_origins);
if (graph_construction_result_.failed()) { if (graph_construction_result_.failed()) {
ok_ = false; ok_ = false;
......
...@@ -40,6 +40,7 @@ struct DecodeStruct; ...@@ -40,6 +40,7 @@ struct DecodeStruct;
typedef compiler::Node TFNode; typedef compiler::Node TFNode;
typedef compiler::MachineGraph TFGraph; typedef compiler::MachineGraph TFGraph;
class WasmCode; class WasmCode;
struct WasmFeatures;
} // namespace wasm } // namespace wasm
namespace compiler { namespace compiler {
...@@ -49,11 +50,12 @@ class TurbofanWasmCompilationUnit { ...@@ -49,11 +50,12 @@ class TurbofanWasmCompilationUnit {
explicit TurbofanWasmCompilationUnit(wasm::WasmCompilationUnit* wasm_unit); explicit TurbofanWasmCompilationUnit(wasm::WasmCompilationUnit* wasm_unit);
~TurbofanWasmCompilationUnit(); ~TurbofanWasmCompilationUnit();
SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms, SourcePositionTable* BuildGraphForWasmFunction(wasm::WasmFeatures* detected,
double* decode_ms,
MachineGraph* mcgraph, MachineGraph* mcgraph,
NodeOriginTable* node_origins); NodeOriginTable* node_origins);
void ExecuteCompilation(); void ExecuteCompilation(wasm::WasmFeatures* detected);
wasm::WasmCode* FinishCompilation(wasm::ErrorThrower*); wasm::WasmCode* FinishCompilation(wasm::ErrorThrower*);
......
...@@ -1835,7 +1835,7 @@ class LiftoffCompiler { ...@@ -1835,7 +1835,7 @@ class LiftoffCompiler {
} // namespace } // namespace
bool LiftoffCompilationUnit::ExecuteCompilation() { bool LiftoffCompilationUnit::ExecuteCompilation(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;
...@@ -1850,11 +1850,9 @@ bool LiftoffCompilationUnit::ExecuteCompilation() { ...@@ -1850,11 +1850,9 @@ bool LiftoffCompilationUnit::ExecuteCompilation() {
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());
WasmFeatures unused_detected_features;
WasmFullDecoder<Decoder::kValidate, LiftoffCompiler> decoder( WasmFullDecoder<Decoder::kValidate, LiftoffCompiler> decoder(
&zone, module, wasm_unit_->native_module_->enabled_features(), &zone, module, wasm_unit_->native_module_->enabled_features(), detected,
&unused_detected_features, wasm_unit_->func_body_, call_descriptor, wasm_unit_->func_body_, call_descriptor, wasm_unit_->env_, &zone);
wasm_unit_->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,6 +11,7 @@ namespace v8 { ...@@ -11,6 +11,7 @@ namespace v8 {
namespace internal { namespace internal {
namespace wasm { namespace wasm {
struct WasmFeatures;
class ErrorThrower; class ErrorThrower;
class WasmCode; class WasmCode;
class WasmCompilationUnit; class WasmCompilationUnit;
...@@ -20,7 +21,7 @@ class LiftoffCompilationUnit final { ...@@ -20,7 +21,7 @@ class LiftoffCompilationUnit final {
explicit LiftoffCompilationUnit(WasmCompilationUnit* wasm_unit) explicit LiftoffCompilationUnit(WasmCompilationUnit* wasm_unit)
: wasm_unit_(wasm_unit) {} : wasm_unit_(wasm_unit) {}
bool ExecuteCompilation(); bool ExecuteCompilation(WasmFeatures* detected);
WasmCode* FinishCompilation(ErrorThrower*); WasmCode* FinishCompilation(ErrorThrower*);
private: private:
......
...@@ -73,7 +73,7 @@ WasmCompilationUnit::WasmCompilationUnit(WasmEngine* wasm_engine, ...@@ -73,7 +73,7 @@ WasmCompilationUnit::WasmCompilationUnit(WasmEngine* wasm_engine,
// {TurbofanWasmCompilationUnit} can be opaque in the header file. // {TurbofanWasmCompilationUnit} can be opaque in the header file.
WasmCompilationUnit::~WasmCompilationUnit() {} WasmCompilationUnit::~WasmCompilationUnit() {}
void WasmCompilationUnit::ExecuteCompilation() { void WasmCompilationUnit::ExecuteCompilation(WasmFeatures* detected) {
auto size_histogram = SELECT_WASM_COUNTER(counters_, env_->module->origin, auto size_histogram = SELECT_WASM_COUNTER(counters_, env_->module->origin,
wasm, function_size_bytes); wasm, function_size_bytes);
size_histogram->AddSample( size_histogram->AddSample(
...@@ -89,12 +89,12 @@ void WasmCompilationUnit::ExecuteCompilation() { ...@@ -89,12 +89,12 @@ void WasmCompilationUnit::ExecuteCompilation() {
switch (mode_) { switch (mode_) {
case ExecutionTier::kBaseline: case ExecutionTier::kBaseline:
if (liftoff_unit_->ExecuteCompilation()) break; if (liftoff_unit_->ExecuteCompilation(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(); turbofan_unit_->ExecuteCompilation(detected);
break; break;
case ExecutionTier::kInterpreter: case ExecutionTier::kInterpreter:
UNREACHABLE(); // TODO(titzer): compile interpreter entry stub. UNREACHABLE(); // TODO(titzer): compile interpreter entry stub.
...@@ -145,8 +145,9 @@ void WasmCompilationUnit::SwitchMode(ExecutionTier new_mode) { ...@@ -145,8 +145,9 @@ void WasmCompilationUnit::SwitchMode(ExecutionTier new_mode) {
// static // static
WasmCode* WasmCompilationUnit::CompileWasmFunction( WasmCode* WasmCompilationUnit::CompileWasmFunction(
NativeModule* native_module, ErrorThrower* thrower, Isolate* isolate, Isolate* isolate, NativeModule* native_module, WasmFeatures* detected,
ModuleEnv* env, const WasmFunction* function, ExecutionTier mode) { ErrorThrower* thrower, ModuleEnv* env, const WasmFunction* function,
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(),
...@@ -156,7 +157,7 @@ WasmCode* WasmCompilationUnit::CompileWasmFunction( ...@@ -156,7 +157,7 @@ WasmCode* WasmCompilationUnit::CompileWasmFunction(
function_body, function_body,
wire_bytes.GetNameOrNull(function, env->module), wire_bytes.GetNameOrNull(function, env->module),
function->func_index, isolate->counters(), mode); function->func_index, isolate->counters(), mode);
unit.ExecuteCompilation(); unit.ExecuteCompilation(detected);
return unit.FinishCompilation(thrower); return unit.FinishCompilation(thrower);
} }
......
...@@ -91,12 +91,12 @@ class WasmCompilationUnit final { ...@@ -91,12 +91,12 @@ class WasmCompilationUnit final {
~WasmCompilationUnit(); ~WasmCompilationUnit();
void ExecuteCompilation(); void ExecuteCompilation(WasmFeatures* detected);
WasmCode* FinishCompilation(ErrorThrower* thrower); WasmCode* FinishCompilation(ErrorThrower* thrower);
static WasmCode* CompileWasmFunction( static WasmCode* CompileWasmFunction(
NativeModule* native_module, ErrorThrower* thrower, Isolate* isolate, Isolate* isolate, NativeModule* native_module, WasmFeatures* detected,
ModuleEnv* env, const WasmFunction* function, ErrorThrower* thrower, ModuleEnv* env, const WasmFunction* function,
ExecutionTier = GetDefaultExecutionTier()); ExecutionTier = GetDefaultExecutionTier());
NativeModule* native_module() const { return native_module_; } NativeModule* native_module() const { return native_module_; }
......
...@@ -90,7 +90,8 @@ class CompilationState { ...@@ -90,7 +90,8 @@ class CompilationState {
void ScheduleUnitForFinishing(std::unique_ptr<WasmCompilationUnit> unit, void ScheduleUnitForFinishing(std::unique_ptr<WasmCompilationUnit> unit,
ExecutionTier mode); ExecutionTier mode);
void OnBackgroundTaskStopped(); void OnBackgroundTaskStopped(const WasmFeatures& detected);
void PublishDetectedFeatures(Isolate* isolate, const WasmFeatures& detected);
void RestartBackgroundTasks(size_t max = std::numeric_limits<size_t>::max()); void RestartBackgroundTasks(size_t max = std::numeric_limits<size_t>::max());
// Only one foreground thread (finisher) is allowed to run at a time. // Only one foreground thread (finisher) is allowed to run at a time.
// {SetFinisherIsRunning} returns whether the flag changed its state. // {SetFinisherIsRunning} returns whether the flag changed its state.
...@@ -113,6 +114,7 @@ class CompilationState { ...@@ -113,6 +114,7 @@ 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_; } ModuleEnv* module_env() { return &module_env_; }
WasmFeatures* detected_features() { return &detected_features_; }
private: private:
void NotifyOnEvent(CompilationEvent event, ErrorThrower* thrower); void NotifyOnEvent(CompilationEvent event, ErrorThrower* thrower);
...@@ -148,6 +150,10 @@ class CompilationState { ...@@ -148,6 +150,10 @@ class CompilationState {
std::vector<std::unique_ptr<WasmCompilationUnit>> baseline_finish_units_; std::vector<std::unique_ptr<WasmCompilationUnit>> baseline_finish_units_;
std::vector<std::unique_ptr<WasmCompilationUnit>> tiering_finish_units_; std::vector<std::unique_ptr<WasmCompilationUnit>> tiering_finish_units_;
// Features detected to be used in this module. Features can be detected
// as a module is being compiled.
WasmFeatures detected_features_ = kNoWasmFeatures;
// End of fields protected by {mutex_}. // End of fields protected by {mutex_}.
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
...@@ -166,6 +172,12 @@ class CompilationState { ...@@ -166,6 +172,12 @@ class CompilationState {
namespace { namespace {
void UpdateFeatureUseCounts(Isolate* isolate, const WasmFeatures& detected) {
if (detected.threads) {
isolate->CountUsage(v8::Isolate::UseCounterFeature::kWasmThreadOpcodes);
}
}
class JSToWasmWrapperCache { class JSToWasmWrapperCache {
public: public:
Handle<Code> GetOrCompileJSToWasmWrapper(Isolate* isolate, Handle<Code> GetOrCompileJSToWasmWrapper(Isolate* isolate,
...@@ -359,7 +371,8 @@ WasmCode* LazyCompileFunction(Isolate* isolate, NativeModule* native_module, ...@@ -359,7 +371,8 @@ WasmCode* LazyCompileFunction(Isolate* isolate, NativeModule* native_module,
ErrorThrower thrower(isolate, "WasmLazyCompile"); ErrorThrower thrower(isolate, "WasmLazyCompile");
WasmCompilationUnit unit(isolate->wasm_engine(), module_env, native_module, WasmCompilationUnit unit(isolate->wasm_engine(), module_env, native_module,
body, func_name, func_index, isolate->counters()); body, func_name, func_index, isolate->counters());
unit.ExecuteCompilation(); unit.ExecuteCompilation(
native_module->compilation_state()->detected_features());
WasmCode* wasm_code = unit.FinishCompilation(&thrower); WasmCode* wasm_code = unit.FinishCompilation(&thrower);
if (WasmCode::ShouldBeLogged(isolate)) wasm_code->LogCode(isolate); if (WasmCode::ShouldBeLogged(isolate)) wasm_code->LogCode(isolate);
...@@ -500,7 +513,8 @@ class CompilationUnitBuilder { ...@@ -500,7 +513,8 @@ class CompilationUnitBuilder {
// 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(CompilationState* compilation_state,
WasmFeatures* detected) {
DisallowHeapAccess no_heap_access; DisallowHeapAccess no_heap_access;
std::unique_ptr<WasmCompilationUnit> unit = std::unique_ptr<WasmCompilationUnit> unit =
...@@ -513,7 +527,7 @@ bool FetchAndExecuteCompilationUnit(CompilationState* compilation_state) { ...@@ -513,7 +527,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(); unit->ExecuteCompilation(detected);
compilation_state->ScheduleUnitForFinishing(std::move(unit), mode); compilation_state->ScheduleUnitForFinishing(std::move(unit), mode);
return true; return true;
...@@ -614,7 +628,9 @@ void CompileInParallel(Isolate* isolate, NativeModule* native_module, ...@@ -614,7 +628,9 @@ void CompileInParallel(Isolate* isolate, NativeModule* native_module,
// result is enqueued in {baseline_finish_units_}. // result is enqueued in {baseline_finish_units_}.
// 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).
while (FetchAndExecuteCompilationUnit(compilation_state) && WasmFeatures detected_features;
while (
FetchAndExecuteCompilationUnit(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
...@@ -636,6 +652,9 @@ void CompileInParallel(Isolate* isolate, NativeModule* native_module, ...@@ -636,6 +652,9 @@ void CompileInParallel(Isolate* isolate, NativeModule* native_module,
if (compilation_state->baseline_compilation_finished()) break; if (compilation_state->baseline_compilation_finished()) break;
} }
// Publish features from the foreground and background tasks.
compilation_state->PublishDetectedFeatures(isolate, detected_features);
// 4) If tiering-compilation is enabled, we need to set the finisher // 4) If tiering-compilation is enabled, we need to set the finisher
// to false, such that the background threads will spawn a foreground // to false, such that the background threads will spawn a foreground
// thread to finish the top-tier compilation units. // thread to finish the top-tier compilation units.
...@@ -652,13 +671,14 @@ void CompileSequentially(Isolate* isolate, NativeModule* native_module, ...@@ -652,13 +671,14 @@ void CompileSequentially(Isolate* isolate, NativeModule* native_module,
ModuleWireBytes wire_bytes(native_module->wire_bytes()); ModuleWireBytes wire_bytes(native_module->wire_bytes());
const WasmModule* module = module_env->module; const WasmModule* module = module_env->module;
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];
if (func.imported) continue; // Imports are compiled at instantiation time. if (func.imported) continue; // Imports are compiled at instantiation time.
// Compile the function. // Compile the function.
WasmCode* code = WasmCompilationUnit::CompileWasmFunction( WasmCode* code = WasmCompilationUnit::CompileWasmFunction(
native_module, thrower, isolate, module_env, &func); isolate, native_module, &detected, thrower, module_env, &func);
if (code == nullptr) { if (code == nullptr) {
TruncatedUserString<> name(wire_bytes.GetName(&func, module)); TruncatedUserString<> name(wire_bytes.GetName(&func, module));
thrower->CompileError("Compilation of #%d:%.*s failed.", i, name.length(), thrower->CompileError("Compilation of #%d:%.*s failed.", i, name.length(),
...@@ -666,6 +686,7 @@ void CompileSequentially(Isolate* isolate, NativeModule* native_module, ...@@ -666,6 +686,7 @@ void CompileSequentially(Isolate* isolate, NativeModule* native_module,
break; break;
} }
} }
UpdateFeatureUseCounts(isolate, detected);
} }
void ValidateSequentially(Isolate* isolate, NativeModule* native_module, void ValidateSequentially(Isolate* isolate, NativeModule* native_module,
...@@ -831,15 +852,17 @@ class BackgroundCompileTask : public CancelableTask { ...@@ -831,15 +852,17 @@ class BackgroundCompileTask : public CancelableTask {
// 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()) { while (!compilation_state_->failed()) {
if (!FetchAndExecuteCompilationUnit(compilation_state_)) { if (!FetchAndExecuteCompilationUnit(compilation_state_,
&detected_features_)) {
break; break;
} }
} }
compilation_state_->OnBackgroundTaskStopped(); compilation_state_->OnBackgroundTaskStopped(detected_features_);
} }
private: private:
CompilationState* compilation_state_; CompilationState* compilation_state_;
WasmFeatures detected_features_ = kNoWasmFeatures;
}; };
} // namespace } // namespace
...@@ -851,6 +874,12 @@ MaybeHandle<WasmModuleObject> CompileToModuleObject( ...@@ -851,6 +874,12 @@ MaybeHandle<WasmModuleObject> CompileToModuleObject(
const WasmModule* wasm_module = module.get(); const WasmModule* wasm_module = module.get();
TimedHistogramScope wasm_compile_module_time_scope(SELECT_WASM_COUNTER( TimedHistogramScope wasm_compile_module_time_scope(SELECT_WASM_COUNTER(
isolate->counters(), wasm_module->origin, wasm_compile, module_time)); isolate->counters(), wasm_module->origin, wasm_compile, module_time));
// Embedder usage count for declared shared memories.
if (wasm_module->has_shared_memory) {
isolate->CountUsage(v8::Isolate::UseCounterFeature::kWasmSharedMemory);
}
// TODO(6792): No longer needed once WebAssembly code is off heap. Use // TODO(6792): No longer needed once WebAssembly code is off heap. Use
// base::Optional to be able to close the scope before notifying the debugger. // base::Optional to be able to close the scope before notifying the debugger.
base::Optional<CodeSpaceMemoryModificationScope> modification_scope( base::Optional<CodeSpaceMemoryModificationScope> modification_scope(
...@@ -2191,6 +2220,11 @@ void AsyncCompileJob::FinishCompile() { ...@@ -2191,6 +2220,11 @@ void AsyncCompileJob::FinishCompile() {
// Log the code within the generated module for profiling. // Log the code within the generated module for profiling.
native_module_->LogWasmCodes(isolate_); native_module_->LogWasmCodes(isolate_);
// We can only update the feature counts once the entire compile is done.
auto compilation_state = native_module_->compilation_state();
compilation_state->PublishDetectedFeatures(
isolate_, *compilation_state->detected_features());
// TODO(wasm): compiling wrappers should be made async as well. // TODO(wasm): compiling wrappers should be made async as well.
DoSync<CompileWrappers>(); DoSync<CompileWrappers>();
} }
...@@ -2376,6 +2410,12 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep { ...@@ -2376,6 +2410,12 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
// is done. // is done.
job_->background_task_manager_.CancelAndWait(); job_->background_task_manager_.CancelAndWait();
// Embedder usage count for declared shared memories.
if (job_->module_->has_shared_memory) {
job_->isolate_->CountUsage(
v8::Isolate::UseCounterFeature::kWasmSharedMemory);
}
// Create heap objects for script and module bytes to be stored in the // Create heap objects for script and module bytes to be stored in the
// module object. Asm.js is not compiled asynchronously. // module object. Asm.js is not compiled asynchronously.
Handle<Script> script = CreateWasmScript(job_->isolate_, job_->wire_bytes_); Handle<Script> script = CreateWasmScript(job_->isolate_, job_->wire_bytes_);
...@@ -2876,10 +2916,21 @@ void CompilationState::ScheduleUnitForFinishing( ...@@ -2876,10 +2916,21 @@ void CompilationState::ScheduleUnitForFinishing(
} }
} }
void CompilationState::OnBackgroundTaskStopped() { void CompilationState::OnBackgroundTaskStopped(const WasmFeatures& detected) {
base::LockGuard<base::Mutex> guard(&mutex_); base::LockGuard<base::Mutex> guard(&mutex_);
DCHECK_LE(1, num_background_tasks_); DCHECK_LE(1, num_background_tasks_);
--num_background_tasks_; --num_background_tasks_;
UnionFeaturesInto(&detected_features_, detected);
}
void CompilationState::PublishDetectedFeatures(Isolate* isolate,
const WasmFeatures& detected) {
// Notifying the isolate of the feature counts must take place under
// the mutex, because even if we have finished baseline compilation,
// tiering compilations may still occur in the background.
base::LockGuard<base::Mutex> guard(&mutex_);
UnionFeaturesInto(&detected_features_, detected);
UpdateFeatureUseCounts(isolate, detected_features_);
} }
void CompilationState::RestartBackgroundTasks(size_t max) { void CompilationState::RestartBackgroundTasks(size_t max) {
......
...@@ -171,8 +171,10 @@ std::shared_ptr<StreamingDecoder> WasmEngine::StartStreamingCompilation( ...@@ -171,8 +171,10 @@ std::shared_ptr<StreamingDecoder> WasmEngine::StartStreamingCompilation(
bool WasmEngine::CompileFunction(Isolate* isolate, NativeModule* native_module, bool WasmEngine::CompileFunction(Isolate* isolate, NativeModule* native_module,
uint32_t function_index, ExecutionTier tier) { uint32_t function_index, ExecutionTier tier) {
ErrorThrower thrower(isolate, "Manually requested tier up"); ErrorThrower thrower(isolate, "Manually requested tier up");
// Note we assume that "one-off" compilations can discard detected features.
WasmFeatures detected = kNoWasmFeatures;
WasmCode* ret = WasmCompilationUnit::CompileWasmFunction( WasmCode* ret = WasmCompilationUnit::CompileWasmFunction(
native_module, &thrower, isolate, isolate, native_module, &detected, &thrower,
GetModuleEnv(native_module->compilation_state()), 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;
......
...@@ -13,11 +13,11 @@ namespace wasm { ...@@ -13,11 +13,11 @@ namespace wasm {
#define COMMA , #define COMMA ,
#define SPACE #define SPACE
#define DO_UNION(feat, desc, val) dst->feat |= src->feat; #define DO_UNION(feat, desc, val) dst->feat |= src.feat;
#define FLAG_REF(feat, desc, val) FLAG_experimental_wasm_##feat #define FLAG_REF(feat, desc, val) FLAG_experimental_wasm_##feat
void UnionFeaturesInto(WasmFeatures* dst, WasmFeatures* src) { void UnionFeaturesInto(WasmFeatures* dst, const WasmFeatures& src) {
FOREACH_WASM_FEATURE(DO_UNION, SPACE) FOREACH_WASM_FEATURE(DO_UNION, SPACE);
} }
WasmFeatures WasmFeaturesFromFlags() { WasmFeatures WasmFeaturesFromFlags() {
......
...@@ -57,7 +57,8 @@ V8_EXPORT_PRIVATE WasmFeatures WasmFeaturesFromFlags(); ...@@ -57,7 +57,8 @@ V8_EXPORT_PRIVATE WasmFeatures WasmFeaturesFromFlags();
// Precondition: A valid context must be set in {isolate->context()}. // Precondition: A valid context must be set in {isolate->context()}.
V8_EXPORT_PRIVATE WasmFeatures WasmFeaturesFromIsolate(Isolate* isolate); V8_EXPORT_PRIVATE WasmFeatures WasmFeaturesFromIsolate(Isolate* isolate);
V8_EXPORT_PRIVATE void UnionFeaturesInto(WasmFeatures* dst, WasmFeatures* src); V8_EXPORT_PRIVATE void UnionFeaturesInto(WasmFeatures* dst,
const WasmFeatures& src);
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
......
...@@ -352,8 +352,9 @@ TEST(SharedEngineRunThreadedTierUp) { ...@@ -352,8 +352,9 @@ TEST(SharedEngineRunThreadedTierUp) {
HandleScope scope(isolate.isolate()); HandleScope scope(isolate.isolate());
Handle<WasmInstanceObject> instance = isolate.ImportInstance(module); Handle<WasmInstanceObject> instance = isolate.ImportInstance(module);
ErrorThrower thrower(isolate.isolate(), "Forced Tier Up"); ErrorThrower thrower(isolate.isolate(), "Forced Tier Up");
WasmFeatures detected = kNoWasmFeatures;
WasmCompilationUnit::CompileWasmFunction( WasmCompilationUnit::CompileWasmFunction(
module.get(), &thrower, isolate.isolate(), isolate.isolate(), module.get(), &detected, &thrower,
GetModuleEnv(module->compilation_state()), 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));
......
...@@ -432,7 +432,8 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) { ...@@ -432,7 +432,8 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) {
WasmCompilationUnit unit(isolate()->wasm_engine(), &module_env, native_module, WasmCompilationUnit unit(isolate()->wasm_engine(), &module_env, native_module,
func_body, func_name, function_->func_index, func_body, func_name, function_->func_index,
isolate()->counters(), tier); isolate()->counters(), tier);
unit.ExecuteCompilation(); WasmFeatures unused_detected_features;
unit.ExecuteCompilation(&unused_detected_features);
WasmCode* wasm_code = unit.FinishCompilation(&thrower); WasmCode* wasm_code = unit.FinishCompilation(&thrower);
if (WasmCode::ShouldBeLogged(isolate())) { if (WasmCode::ShouldBeLogged(isolate())) {
wasm_code->LogCode(isolate()); wasm_code->LogCode(isolate());
......
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