Commit a69be08a authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

Revert "[wasm] Compile big functions first"

This reverts commit 2ce5da9a.

Reason for revert: Fails on several bots, e.g. https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20TSAN/26607

Original change's description:
> [wasm] Compile big functions first
> 
> Add a special queue to {CompilationUnitQueues} to handle big functions
> specially. They are organized in a priority queue (ordered by their
> body size), and all threads check this queue first, before executing
> the tasks from their own queue. In some benchmarks, this shortens
> overall compilation time by 10-20 percent.
> 
> R=​ahaas@chromium.org
> 
> Bug: v8:8916, chromium:950493
> Change-Id: I45f36a05304e2f1c4f3ce6b8821ddd4bd08fbba3
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1622122
> Reviewed-by: Andreas Haas <ahaas@chromium.org>
> Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#61746}

TBR=ahaas@chromium.org,clemensh@chromium.org

Change-Id: Ib47b23ff878d4a561df1993d532e5eeafea64ff6
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:8916, chromium:950493
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1624797Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61749}
parent f0bb837f
...@@ -70,7 +70,6 @@ class V8_EXPORT_PRIVATE WasmCompilationUnit final { ...@@ -70,7 +70,6 @@ class V8_EXPORT_PRIVATE WasmCompilationUnit final {
Counters*, WasmFeatures* detected); Counters*, WasmFeatures* detected);
ExecutionTier tier() const { return tier_; } ExecutionTier tier() const { return tier_; }
int func_index() const { return func_index_; }
static void CompileWasmFunction(Isolate*, NativeModule*, static void CompileWasmFunction(Isolate*, NativeModule*,
WasmFeatures* detected, const WasmFunction*, WasmFeatures* detected, const WasmFunction*,
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#include "src/wasm/module-compiler.h" #include "src/wasm/module-compiler.h"
#include <algorithm> #include <algorithm>
#include <queue>
#include "src/api/api.h" #include "src/api/api.h"
#include "src/asmjs/asm-js.h" #include "src/asmjs/asm-js.h"
...@@ -165,20 +164,39 @@ class CompilationUnitQueues { ...@@ -165,20 +164,39 @@ class CompilationUnitQueues {
// before executing own higher-tier units. // before executing own higher-tier units.
int max_tier = baseline_only ? kBaseline : kTopTier; int max_tier = baseline_only ? kBaseline : kTopTier;
for (int tier = GetLowestTierWithUnits(); tier <= max_tier; ++tier) { for (int tier = GetLowestTierWithUnits(); tier <= max_tier; ++tier) {
if (auto unit = GetNextUnitOfTier(task_id, tier)) { Queue* queue = &queues_[task_id];
size_t old_units_count = // First, check whether our own queue has a unit of the wanted tier. If
num_units_[tier].fetch_sub(1, std::memory_order_relaxed); // so, return it, otherwise get the task id to steal from.
DCHECK_LE(1, old_units_count); int steal_task_id;
USE(old_units_count); {
return unit; base::MutexGuard mutex_guard(&queue->mutex);
if (!queue->units[tier].empty()) {
auto unit = queue->units[tier].back();
queue->units[tier].pop_back();
DecrementUnitCount(tier);
return unit;
}
steal_task_id = queue->next_steal_task_id;
}
// Try to steal from all other queues. If none of this succeeds, the outer
// loop increases the tier and retries.
size_t steal_trials = queues_.size();
for (; steal_trials > 0;
--steal_trials, steal_task_id = next_task_id(steal_task_id)) {
if (steal_task_id == task_id) continue;
if (auto maybe_unit =
StealUnitsAndGetFirst(task_id, steal_task_id, tier)) {
DecrementUnitCount(tier);
return maybe_unit;
}
} }
} }
return {}; return {};
} }
void AddUnits(Vector<WasmCompilationUnit> baseline_units, void AddUnits(Vector<WasmCompilationUnit> baseline_units,
Vector<WasmCompilationUnit> top_tier_units, Vector<WasmCompilationUnit> top_tier_units) {
const WasmModule* module) {
DCHECK_LT(0, baseline_units.size() + top_tier_units.size()); DCHECK_LT(0, baseline_units.size() + top_tier_units.size());
// Add to the individual queues in a round-robin fashion. No special care is // Add to the individual queues in a round-robin fashion. No special care is
// taken to balance them; they will be balanced by work stealing. // taken to balance them; they will be balanced by work stealing.
...@@ -190,26 +208,19 @@ class CompilationUnitQueues { ...@@ -190,26 +208,19 @@ class CompilationUnitQueues {
Queue* queue = &queues_[queue_to_add]; Queue* queue = &queues_[queue_to_add];
base::MutexGuard guard(&queue->mutex); base::MutexGuard guard(&queue->mutex);
base::Optional<base::MutexGuard> big_units_guard; if (!baseline_units.empty()) {
for (auto pair : {std::make_pair(int{kBaseline}, baseline_units), queue->units[kBaseline].insert(queue->units[kBaseline].end(),
std::make_pair(int{kTopTier}, top_tier_units)}) { baseline_units.begin(),
int tier = pair.first; baseline_units.end());
Vector<WasmCompilationUnit> units = pair.second; num_units_[kBaseline].fetch_add(baseline_units.size(),
if (units.empty()) continue; std::memory_order_relaxed);
num_units_[tier].fetch_add(units.size(), std::memory_order_relaxed); }
for (WasmCompilationUnit unit : units) { if (!top_tier_units.empty()) {
size_t func_size = module->functions[unit.func_index()].code.length(); queue->units[kTopTier].insert(queue->units[kTopTier].end(),
if (func_size <= kBigUnitsLimit) { top_tier_units.begin(),
queue->units[tier].push_back(unit); top_tier_units.end());
} else { num_units_[kTopTier].fetch_add(top_tier_units.size(),
if (!big_units_guard) { std::memory_order_relaxed);
big_units_guard.emplace(&big_units_queue_.mutex);
}
big_units_queue_.has_units[tier].store(true,
std::memory_order_relaxed);
big_units_queue_.units[tier].emplace(func_size, unit);
}
}
} }
} }
...@@ -230,10 +241,6 @@ class CompilationUnitQueues { ...@@ -230,10 +241,6 @@ class CompilationUnitQueues {
static constexpr int kTopTier = 1; static constexpr int kTopTier = 1;
static constexpr int kNumTiers = kTopTier + 1; static constexpr int kNumTiers = kTopTier + 1;
// Functions bigger than {kBigUnitsLimit} will be compiled first, in ascending
// order of their function body size.
static constexpr size_t kBigUnitsLimit = 4096;
struct Queue { struct Queue {
base::Mutex mutex; base::Mutex mutex;
...@@ -243,30 +250,7 @@ class CompilationUnitQueues { ...@@ -243,30 +250,7 @@ class CompilationUnitQueues {
// End of fields protected by {mutex}. // End of fields protected by {mutex}.
}; };
struct BigUnit {
BigUnit(size_t func_size, WasmCompilationUnit unit)
: func_size{func_size}, unit(unit) {}
size_t func_size;
WasmCompilationUnit unit;
bool operator<(const BigUnit& other) const {
return func_size < other.func_size;
}
};
struct BigUnitsQueue {
base::Mutex mutex;
// Can be read concurrently to check whether any elements are in the queue.
std::atomic<bool> has_units[kNumTiers];
// Protected by {mutex}:
std::priority_queue<BigUnit> units[kNumTiers];
};
std::vector<Queue> queues_; std::vector<Queue> queues_;
BigUnitsQueue big_units_queue_;
std::atomic<size_t> num_units_[kNumTiers]; std::atomic<size_t> num_units_[kNumTiers];
std::atomic<int> next_queue_to_add{0}; std::atomic<int> next_queue_to_add{0};
...@@ -283,52 +267,10 @@ class CompilationUnitQueues { ...@@ -283,52 +267,10 @@ class CompilationUnitQueues {
return kNumTiers; return kNumTiers;
} }
base::Optional<WasmCompilationUnit> GetNextUnitOfTier(int task_id, int tier) { void DecrementUnitCount(int tier) {
Queue* queue = &queues_[task_id]; size_t old_units_count = num_units_[tier].fetch_sub(1);
// First check whether there is a big unit of that tier. Execute that first. DCHECK_LE(1, old_units_count);
if (auto unit = GetBigUnitOfTier(tier)) return unit; USE(old_units_count);
// Then check whether our own queue has a unit of the wanted tier. If
// so, return it, otherwise get the task id to steal from.
int steal_task_id;
{
base::MutexGuard mutex_guard(&queue->mutex);
if (!queue->units[tier].empty()) {
auto unit = queue->units[tier].back();
queue->units[tier].pop_back();
return unit;
}
steal_task_id = queue->next_steal_task_id;
}
// Try to steal from all other queues. If this succeeds, return one of the
// stolen units.
size_t steal_trials = queues_.size();
for (; steal_trials > 0;
--steal_trials, steal_task_id = next_task_id(steal_task_id)) {
if (steal_task_id == task_id) continue;
if (auto unit = StealUnitsAndGetFirst(task_id, steal_task_id, tier)) {
return unit;
}
}
// If we reach here, we didn't find any unit of the requested tier.
return {};
}
base::Optional<WasmCompilationUnit> GetBigUnitOfTier(int tier) {
// Fast-path without locking.
if (!big_units_queue_.has_units[tier].load(std::memory_order_relaxed)) {
return {};
}
base::MutexGuard guard(&big_units_queue_.mutex);
if (big_units_queue_.units[tier].empty()) return {};
WasmCompilationUnit unit = big_units_queue_.units[tier].top().unit;
big_units_queue_.units[tier].pop();
if (big_units_queue_.units[tier].empty()) {
big_units_queue_.has_units[tier].store(false, std::memory_order_relaxed);
}
return unit;
} }
// Steal units of {wanted_tier} from {steal_from_task_id} to {task_id}. Return // Steal units of {wanted_tier} from {steal_from_task_id} to {task_id}. Return
...@@ -2060,8 +2002,7 @@ void CompilationStateImpl::AddCallback(CompilationState::callback_t callback) { ...@@ -2060,8 +2002,7 @@ void CompilationStateImpl::AddCallback(CompilationState::callback_t callback) {
void CompilationStateImpl::AddCompilationUnits( void CompilationStateImpl::AddCompilationUnits(
Vector<WasmCompilationUnit> baseline_units, Vector<WasmCompilationUnit> baseline_units,
Vector<WasmCompilationUnit> top_tier_units) { Vector<WasmCompilationUnit> top_tier_units) {
compilation_unit_queues_.AddUnits(baseline_units, top_tier_units, compilation_unit_queues_.AddUnits(baseline_units, top_tier_units);
native_module_->module());
RestartBackgroundTasks(); RestartBackgroundTasks();
} }
......
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