[turbofan] introduce a deterministic tick measurement and assert optimization doesn't take too long

This adds a simple counter to Turbofan that's incremented throughout the compilation, hopefully
frequently enough so we can use it to detect divergence and performance bugs.
In addition, we assert that this counter never gets too high. That's the equivalent of a simple
timeout, just more deterministic. The limitations on Turbofan input size should guarantee that
we never exceed this limit. Since we probably do exceed it rarely, this check is only a DCHECK and
intended to detect performance and divergence issues, but not supposed to be performed in release
builds.

In addition, this CL adds UMA stats to observe the real world distribution of the tick measurement.

Bug: v8:9444

Change-Id: I182dac6ecac64715e3f5885ff5c7c17549351cd0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1695475
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Michael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62754}
This commit is contained in:
Tobias Tebbi 2019-07-16 23:46:08 +02:00 committed by Commit Bot
parent d4d28b73cb
commit 4f48d04f97
54 changed files with 398 additions and 143 deletions

View File

@ -2107,6 +2107,8 @@ v8_source_set("v8_base_without_compiler") {
"src/codegen/source-position.h",
"src/codegen/string-constants.cc",
"src/codegen/string-constants.h",
"src/codegen/tick-counter.cc",
"src/codegen/tick-counter.h",
"src/codegen/turbo-assembler.cc",
"src/codegen/turbo-assembler.h",
"src/codegen/unoptimized-compilation-info.cc",

View File

@ -320,6 +320,8 @@ void OptimizedCompilationJob::RecordCompilationStats(CompilationMode mode,
counters->turbofan_optimize_total_foreground()->AddSample(
static_cast<int>(time_foreground.InMicroseconds()));
}
counters->turbofan_ticks()->AddSample(static_cast<int>(
compilation_info()->tick_counter().CurrentTicks() / 1000));
}
}

View File

@ -9,6 +9,7 @@
#include "src/codegen/bailout-reason.h"
#include "src/codegen/source-position-table.h"
#include "src/codegen/tick-counter.h"
#include "src/common/globals.h"
#include "src/execution/frames.h"
#include "src/handles/handles.h"
@ -289,6 +290,8 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
std::unique_ptr<v8::tracing::TracedValue> ToTracedValue();
TickCounter& tick_counter() { return tick_counter_; }
private:
OptimizedCompilationInfo(Code::Kind code_kind, Zone* zone);
void ConfigureFlags();
@ -341,6 +344,8 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
Vector<const char> debug_name_;
std::unique_ptr<char[]> trace_turbo_filename_;
TickCounter tick_counter_;
DISALLOW_COPY_AND_ASSIGN(OptimizedCompilationInfo);
};

View File

@ -0,0 +1,23 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/codegen/tick-counter.h"
#include "src/base/logging.h"
#include "src/base/macros.h"
namespace v8 {
namespace internal {
void TickCounter::DoTick() {
++ticks_;
// Magical number to detect performance bugs or compiler divergence.
// Selected as being roughly 10x of what's needed frequently.
constexpr size_t kMaxTicks = 100000000;
USE(kMaxTicks);
DCHECK_LT(ticks_, kMaxTicks);
}
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,28 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_CODEGEN_TICK_COUNTER_H_
#define V8_CODEGEN_TICK_COUNTER_H_
#include <cstddef>
namespace v8 {
namespace internal {
// A deterministic correlate of time, used to detect performance or
// divergence bugs in Turbofan. DoTick() should be called frequently
// thoughout the compilation.
class TickCounter {
public:
void DoTick();
size_t CurrentTicks() const { return ticks_; }
private:
size_t ticks_ = 0;
};
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_TICK_COUNTER_H_

View File

@ -8,6 +8,7 @@
#include "src/base/adapters.h"
#include "src/codegen/assembler-inl.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/backend/instruction-selector-impl.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/node-matchers.h"
@ -24,7 +25,7 @@ InstructionSelector::InstructionSelector(
Zone* zone, size_t node_count, Linkage* linkage,
InstructionSequence* sequence, Schedule* schedule,
SourcePositionTable* source_positions, Frame* frame,
EnableSwitchJumpTable enable_switch_jump_table,
EnableSwitchJumpTable enable_switch_jump_table, TickCounter* tick_counter,
SourcePositionMode source_position_mode, Features features,
EnableScheduling enable_scheduling,
EnableRootsRelativeAddressing enable_roots_relative_addressing,
@ -54,7 +55,8 @@ InstructionSelector::InstructionSelector(
frame_(frame),
instruction_selection_failed_(false),
instr_origins_(sequence->zone()),
trace_turbo_(trace_turbo) {
trace_turbo_(trace_turbo),
tick_counter_(tick_counter) {
instructions_.reserve(node_count);
continuation_inputs_.reserve(5);
continuation_outputs_.reserve(2);
@ -1251,6 +1253,7 @@ void InstructionSelector::MarkPairProjectionsAsWord32(Node* node) {
}
void InstructionSelector::VisitNode(Node* node) {
tick_counter_->DoTick();
DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes.
switch (node->opcode()) {
case IrOpcode::kStart:

View File

@ -19,6 +19,9 @@
namespace v8 {
namespace internal {
class TickCounter;
namespace compiler {
// Forward declarations.
@ -266,7 +269,7 @@ class V8_EXPORT_PRIVATE InstructionSelector final {
Zone* zone, size_t node_count, Linkage* linkage,
InstructionSequence* sequence, Schedule* schedule,
SourcePositionTable* source_positions, Frame* frame,
EnableSwitchJumpTable enable_switch_jump_table,
EnableSwitchJumpTable enable_switch_jump_table, TickCounter* tick_counter,
SourcePositionMode source_position_mode = kCallSourcePositions,
Features features = SupportedFeatures(),
EnableScheduling enable_scheduling = FLAG_turbo_instruction_scheduling
@ -778,6 +781,7 @@ class V8_EXPORT_PRIVATE InstructionSelector final {
bool instruction_selection_failed_;
ZoneVector<std::pair<int, int>> instr_origins_;
EnableTraceTurboJson trace_turbo_;
TickCounter* const tick_counter_;
};
} // namespace compiler

View File

@ -9,6 +9,7 @@
#include "src/base/adapters.h"
#include "src/base/small-vector.h"
#include "src/codegen/assembler-inl.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/linkage.h"
#include "src/strings/string-stream.h"
#include "src/utils/vector.h"
@ -1470,7 +1471,7 @@ void RegisterAllocationData::PhiMapValue::CommitAssignment(
RegisterAllocationData::RegisterAllocationData(
const RegisterConfiguration* config, Zone* zone, Frame* frame,
InstructionSequence* code, RegisterAllocationFlags flags,
const char* debug_name)
TickCounter* tick_counter, const char* debug_name)
: allocation_zone_(zone),
frame_(frame),
code_(code),
@ -1497,7 +1498,8 @@ RegisterAllocationData::RegisterAllocationData(
preassigned_slot_ranges_(zone),
spill_state_(code->InstructionBlockCount(), ZoneVector<LiveRange*>(zone),
zone),
flags_(flags) {
flags_(flags),
tick_counter_(tick_counter) {
if (!kSimpleFPAliasing) {
fixed_float_live_ranges_.resize(
kNumberOfFixedRangesPerRegister * this->config()->num_float_registers(),
@ -1816,6 +1818,7 @@ InstructionOperand* ConstraintBuilder::AllocateFixed(
void ConstraintBuilder::MeetRegisterConstraints() {
for (InstructionBlock* block : code()->instruction_blocks()) {
data_->tick_counter()->DoTick();
MeetRegisterConstraints(block);
}
}
@ -1981,6 +1984,7 @@ void ConstraintBuilder::MeetConstraintsBefore(int instr_index) {
void ConstraintBuilder::ResolvePhis() {
// Process the blocks in reverse order.
for (InstructionBlock* block : base::Reversed(code()->instruction_blocks())) {
data_->tick_counter()->DoTick();
ResolvePhis(block);
}
}
@ -2586,6 +2590,7 @@ void LiveRangeBuilder::BuildLiveRanges() {
// Process the blocks in reverse order.
for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0;
--block_id) {
data_->tick_counter()->DoTick();
InstructionBlock* block =
code()->InstructionBlockAt(RpoNumber::FromInt(block_id));
BitVector* live = ComputeLiveOut(block, data());
@ -2605,6 +2610,7 @@ void LiveRangeBuilder::BuildLiveRanges() {
// Postprocess the ranges.
const size_t live_ranges_size = data()->live_ranges().size();
for (TopLevelLiveRange* range : data()->live_ranges()) {
data_->tick_counter()->DoTick();
CHECK_EQ(live_ranges_size,
data()->live_ranges().size()); // TODO(neis): crbug.com/831822
if (range == nullptr) continue;
@ -3643,6 +3649,7 @@ void LinearScanAllocator::AllocateRegisters() {
while (!unhandled_live_ranges().empty() ||
(data()->is_turbo_control_flow_aware_allocation() &&
last_block < max_blocks)) {
data()->tick_counter()->DoTick();
LiveRange* current = unhandled_live_ranges().empty()
? nullptr
: *unhandled_live_ranges().begin();
@ -4610,6 +4617,7 @@ OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {}
void OperandAssigner::DecideSpillingMode() {
if (data()->is_turbo_control_flow_aware_allocation()) {
for (auto range : data()->live_ranges()) {
data()->tick_counter()->DoTick();
int max_blocks = data()->code()->InstructionBlockCount();
if (range != nullptr && range->IsSpilledOnlyInDeferredBlocks(data())) {
// If the range is spilled only in deferred blocks and starts in
@ -4638,6 +4646,7 @@ void OperandAssigner::DecideSpillingMode() {
void OperandAssigner::AssignSpillSlots() {
for (auto range : data()->live_ranges()) {
data()->tick_counter()->DoTick();
if (range != nullptr && range->get_bundle() != nullptr) {
range->get_bundle()->MergeSpillRanges();
}
@ -4645,6 +4654,7 @@ void OperandAssigner::AssignSpillSlots() {
ZoneVector<SpillRange*>& spill_ranges = data()->spill_ranges();
// Merge disjoint spill ranges
for (size_t i = 0; i < spill_ranges.size(); ++i) {
data()->tick_counter()->DoTick();
SpillRange* range = spill_ranges[i];
if (range == nullptr) continue;
if (range->IsEmpty()) continue;
@ -4657,6 +4667,7 @@ void OperandAssigner::AssignSpillSlots() {
}
// Allocate slots for the merged spill ranges.
for (SpillRange* range : spill_ranges) {
data()->tick_counter()->DoTick();
if (range == nullptr || range->IsEmpty()) continue;
// Allocate a new operand referring to the spill slot.
if (!range->HasSlot()) {
@ -4669,6 +4680,7 @@ void OperandAssigner::AssignSpillSlots() {
void OperandAssigner::CommitAssignment() {
const size_t live_ranges_size = data()->live_ranges().size();
for (TopLevelLiveRange* top_range : data()->live_ranges()) {
data()->tick_counter()->DoTick();
CHECK_EQ(live_ranges_size,
data()->live_ranges().size()); // TODO(neis): crbug.com/831822
if (top_range == nullptr || top_range->IsEmpty()) continue;
@ -4868,6 +4880,7 @@ void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) {
BitVector* live = live_in_sets[block->rpo_number().ToInt()];
BitVector::Iterator iterator(live);
while (!iterator.Done()) {
data()->tick_counter()->DoTick();
int vreg = iterator.Current();
LiveRangeBoundArray* array = finder.ArrayFor(vreg);
for (const RpoNumber& pred : block->predecessors()) {

View File

@ -16,6 +16,9 @@
namespace v8 {
namespace internal {
class TickCounter;
namespace compiler {
static const int32_t kUnassignedRegister = RegisterConfiguration::kMaxRegisters;
@ -243,6 +246,7 @@ class RegisterAllocationData final : public ZoneObject {
Zone* allocation_zone, Frame* frame,
InstructionSequence* code,
RegisterAllocationFlags flags,
TickCounter* tick_counter,
const char* debug_name = nullptr);
const ZoneVector<TopLevelLiveRange*>& live_ranges() const {
@ -333,6 +337,8 @@ class RegisterAllocationData final : public ZoneObject {
void ResetSpillState() { spill_state_.clear(); }
TickCounter* tick_counter() { return tick_counter_; }
private:
int GetNextLiveRangeId();
@ -359,6 +365,7 @@ class RegisterAllocationData final : public ZoneObject {
RangesWithPreassignedSlots preassigned_slot_ranges_;
ZoneVector<ZoneVector<LiveRange*>> spill_state_;
RegisterAllocationFlags flags_;
TickCounter* const tick_counter_;
DISALLOW_COPY_AND_ASSIGN(RegisterAllocationData);
};

View File

@ -6,6 +6,7 @@
#include "src/ast/ast.h"
#include "src/codegen/source-position-table.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/bytecode-analysis.h"
#include "src/compiler/compiler-source-position-table.h"
@ -40,7 +41,8 @@ class BytecodeGraphBuilder {
CallFrequency const& invocation_frequency,
SourcePositionTable* source_positions,
Handle<NativeContext> native_context, int inlining_id,
BytecodeGraphBuilderFlags flags);
BytecodeGraphBuilderFlags flags,
TickCounter* tick_counter);
// Creates a graph by visiting bytecodes.
void CreateGraph();
@ -434,6 +436,8 @@ class BytecodeGraphBuilder {
// The native context for which we optimize.
Handle<NativeContext> const native_context_;
TickCounter* const tick_counter_;
static int const kBinaryOperationHintIndex = 1;
static int const kCountOperationHintIndex = 0;
static int const kBinaryOperationSmiHintIndex = 1;
@ -938,7 +942,7 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
BailoutId osr_offset, JSGraph* jsgraph,
CallFrequency const& invocation_frequency,
SourcePositionTable* source_positions, Handle<NativeContext> native_context,
int inlining_id, BytecodeGraphBuilderFlags flags)
int inlining_id, BytecodeGraphBuilderFlags flags, TickCounter* tick_counter)
: broker_(broker),
local_zone_(local_zone),
jsgraph_(jsgraph),
@ -977,7 +981,8 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
source_positions_(source_positions),
start_position_(shared_info->StartPosition(), inlining_id),
shared_info_(shared_info),
native_context_(native_context) {
native_context_(native_context),
tick_counter_(tick_counter) {
if (FLAG_concurrent_inlining) {
// With concurrent inlining on, the source position address doesn't change
// because it's been copied from the heap.
@ -1265,6 +1270,7 @@ void BytecodeGraphBuilder::AdvanceToOsrEntryAndPeelLoops() {
}
void BytecodeGraphBuilder::VisitSingleBytecode() {
tick_counter_->DoTick();
int current_offset = bytecode_iterator().current_offset();
UpdateSourcePosition(current_offset);
ExitThenEnterExceptionHandlers(current_offset);
@ -4018,14 +4024,15 @@ void BuildGraphFromBytecode(JSHeapBroker* broker, Zone* local_zone,
CallFrequency const& invocation_frequency,
SourcePositionTable* source_positions,
Handle<NativeContext> native_context,
int inlining_id, BytecodeGraphBuilderFlags flags) {
int inlining_id, BytecodeGraphBuilderFlags flags,
TickCounter* tick_counter) {
BytecodeArrayRef bytecode_array_ref(broker, bytecode_array);
DCHECK(bytecode_array_ref.IsSerializedForCompilation());
FeedbackVectorRef feedback_vector_ref(broker, feedback_vector);
BytecodeGraphBuilder builder(broker, local_zone, bytecode_array_ref, shared,
feedback_vector_ref, osr_offset, jsgraph,
invocation_frequency, source_positions,
native_context, inlining_id, flags);
BytecodeGraphBuilder builder(
broker, local_zone, bytecode_array_ref, shared, feedback_vector_ref,
osr_offset, jsgraph, invocation_frequency, source_positions,
native_context, inlining_id, flags, tick_counter);
builder.CreateGraph();
}

View File

@ -11,6 +11,9 @@
#include "src/handles/handles.h"
namespace v8 {
class TickCounter;
namespace internal {
class BytecodeArray;
@ -43,7 +46,8 @@ void BuildGraphFromBytecode(JSHeapBroker* broker, Zone* local_zone,
CallFrequency const& invocation_frequency,
SourcePositionTable* source_positions,
Handle<NativeContext> native_context,
int inlining_id, BytecodeGraphBuilderFlags flags);
int inlining_id, BytecodeGraphBuilderFlags flags,
TickCounter* tick_counter);
} // namespace compiler
} // namespace internal

View File

@ -4,6 +4,7 @@
#include "src/compiler/control-flow-optimizer.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
#include "src/compiler/node-matchers.h"
@ -16,18 +17,20 @@ namespace compiler {
ControlFlowOptimizer::ControlFlowOptimizer(Graph* graph,
CommonOperatorBuilder* common,
MachineOperatorBuilder* machine,
TickCounter* tick_counter,
Zone* zone)
: graph_(graph),
common_(common),
machine_(machine),
queue_(zone),
queued_(graph, 2),
zone_(zone) {}
zone_(zone),
tick_counter_(tick_counter) {}
void ControlFlowOptimizer::Optimize() {
Enqueue(graph()->start());
while (!queue_.empty()) {
tick_counter_->DoTick();
Node* node = queue_.front();
queue_.pop();
if (node->IsDead()) continue;

View File

@ -11,6 +11,9 @@
namespace v8 {
namespace internal {
class TickCounter;
namespace compiler {
// Forward declarations.
@ -22,7 +25,8 @@ class Node;
class V8_EXPORT_PRIVATE ControlFlowOptimizer final {
public:
ControlFlowOptimizer(Graph* graph, CommonOperatorBuilder* common,
MachineOperatorBuilder* machine, Zone* zone);
MachineOperatorBuilder* machine,
TickCounter* tick_counter, Zone* zone);
void Optimize();
@ -45,6 +49,7 @@ class V8_EXPORT_PRIVATE ControlFlowOptimizer final {
ZoneQueue<Node*> queue_;
NodeMarker<bool> queued_;
Zone* const zone_;
TickCounter* const tick_counter_;
DISALLOW_COPY_AND_ASSIGN(ControlFlowOptimizer);
};

View File

@ -4,6 +4,7 @@
#include "src/compiler/escape-analysis.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/linkage.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/operator-properties.h"
@ -153,6 +154,7 @@ class VariableTracker {
ZoneVector<Node*> buffer_;
EffectGraphReducer* reducer_;
int next_variable_ = 0;
TickCounter* const tick_counter_;
DISALLOW_COPY_AND_ASSIGN(VariableTracker);
};
@ -279,12 +281,14 @@ class EscapeAnalysisTracker : public ZoneObject {
};
EffectGraphReducer::EffectGraphReducer(
Graph* graph, std::function<void(Node*, Reduction*)> reduce, Zone* zone)
Graph* graph, std::function<void(Node*, Reduction*)> reduce,
TickCounter* tick_counter, Zone* zone)
: graph_(graph),
state_(graph, kNumStates),
revisit_(zone),
stack_(zone),
reduce_(std::move(reduce)) {}
reduce_(std::move(reduce)),
tick_counter_(tick_counter) {}
void EffectGraphReducer::ReduceFrom(Node* node) {
// Perform DFS and eagerly trigger revisitation as soon as possible.
@ -293,6 +297,7 @@ void EffectGraphReducer::ReduceFrom(Node* node) {
DCHECK(stack_.empty());
stack_.push({node, 0});
while (!stack_.empty()) {
tick_counter_->DoTick();
Node* current = stack_.top().node;
int& input_index = stack_.top().input_index;
if (input_index < current->InputCount()) {
@ -357,7 +362,8 @@ VariableTracker::VariableTracker(JSGraph* graph, EffectGraphReducer* reducer,
graph_(graph),
table_(zone, State(zone)),
buffer_(zone),
reducer_(reducer) {}
reducer_(reducer),
tick_counter_(reducer->tick_counter()) {}
VariableTracker::Scope::Scope(VariableTracker* states, Node* node,
Reduction* reduction)
@ -406,6 +412,7 @@ VariableTracker::State VariableTracker::MergeInputs(Node* effect_phi) {
State first_input = table_.Get(NodeProperties::GetEffectInput(effect_phi, 0));
State result = first_input;
for (std::pair<Variable, Node*> var_value : first_input) {
tick_counter_->DoTick();
if (Node* value = var_value.second) {
Variable var = var_value.first;
TRACE("var %i:\n", var.id_);
@ -817,11 +824,12 @@ void EscapeAnalysis::Reduce(Node* node, Reduction* reduction) {
ReduceNode(op, &current, jsgraph());
}
EscapeAnalysis::EscapeAnalysis(JSGraph* jsgraph, Zone* zone)
EscapeAnalysis::EscapeAnalysis(JSGraph* jsgraph, TickCounter* tick_counter,
Zone* zone)
: EffectGraphReducer(
jsgraph->graph(),
[this](Node* node, Reduction* reduction) { Reduce(node, reduction); },
zone),
tick_counter, zone),
tracker_(new (zone) EscapeAnalysisTracker(jsgraph, this, zone)),
jsgraph_(jsgraph) {}

View File

@ -14,6 +14,9 @@
namespace v8 {
namespace internal {
class TickCounter;
namespace compiler {
class CommonOperatorBuilder;
@ -38,7 +41,8 @@ class EffectGraphReducer {
};
EffectGraphReducer(Graph* graph,
std::function<void(Node*, Reduction*)> reduce, Zone* zone);
std::function<void(Node*, Reduction*)> reduce,
TickCounter* tick_counter, Zone* zone);
void ReduceGraph() { ReduceFrom(graph_->end()); }
@ -56,6 +60,8 @@ class EffectGraphReducer {
bool Complete() { return stack_.empty() && revisit_.empty(); }
TickCounter* tick_counter() const { return tick_counter_; }
private:
struct NodeState {
Node* node;
@ -69,6 +75,7 @@ class EffectGraphReducer {
ZoneStack<Node*> revisit_;
ZoneStack<NodeState> stack_;
std::function<void(Node*, Reduction*)> reduce_;
TickCounter* const tick_counter_;
};
// A variable is an abstract storage location, which is lowered to SSA values
@ -164,7 +171,7 @@ class EscapeAnalysisResult {
class V8_EXPORT_PRIVATE EscapeAnalysis final
: public NON_EXPORTED_BASE(EffectGraphReducer) {
public:
EscapeAnalysis(JSGraph* jsgraph, Zone* zone);
EscapeAnalysis(JSGraph* jsgraph, TickCounter* tick_counter, Zone* zone);
EscapeAnalysisResult analysis_result() {
DCHECK(Complete());

View File

@ -5,10 +5,11 @@
#include <functional>
#include <limits>
#include "src/compiler/graph.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/node.h"
#include "src/compiler/graph.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/node.h"
#include "src/compiler/verifier.h"
namespace v8 {
@ -25,13 +26,15 @@ enum class GraphReducer::State : uint8_t {
void Reducer::Finalize() {}
GraphReducer::GraphReducer(Zone* zone, Graph* graph, Node* dead)
GraphReducer::GraphReducer(Zone* zone, Graph* graph, TickCounter* tick_counter,
Node* dead)
: graph_(graph),
dead_(dead),
state_(graph, 4),
reducers_(zone),
revisit_(zone),
stack_(zone) {
stack_(zone),
tick_counter_(tick_counter) {
if (dead != nullptr) {
NodeProperties::SetType(dead_, Type::None());
}
@ -82,6 +85,7 @@ Reduction GraphReducer::Reduce(Node* const node) {
auto skip = reducers_.end();
for (auto i = reducers_.begin(); i != reducers_.end();) {
if (i != skip) {
tick_counter_->DoTick();
Reduction reduction = (*i)->Reduce(node);
if (!reduction.Changed()) {
// No change from this reducer.

View File

@ -12,13 +12,15 @@
namespace v8 {
namespace internal {
class TickCounter;
namespace compiler {
// Forward declarations.
class Graph;
class Node;
// NodeIds are identifying numbers for nodes that can be used to index auxiliary
// out-of-line data associated with each node.
using NodeId = uint32_t;
@ -129,7 +131,8 @@ class AdvancedReducer : public Reducer {
class V8_EXPORT_PRIVATE GraphReducer
: public NON_EXPORTED_BASE(AdvancedReducer::Editor) {
public:
GraphReducer(Zone* zone, Graph* graph, Node* dead = nullptr);
GraphReducer(Zone* zone, Graph* graph, TickCounter* tick_counter,
Node* dead = nullptr);
~GraphReducer() override;
Graph* graph() const { return graph_; }
@ -181,6 +184,7 @@ class V8_EXPORT_PRIVATE GraphReducer
ZoneVector<Reducer*> reducers_;
ZoneQueue<Node*> revisit_;
ZoneStack<NodeState> stack_;
TickCounter* const tick_counter_;
DISALLOW_COPY_AND_ASSIGN(GraphReducer);
};

View File

@ -7,6 +7,7 @@
#include "src/ast/ast.h"
#include "src/codegen/compiler.h"
#include "src/codegen/optimized-compilation-info.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/all-nodes.h"
#include "src/compiler/bytecode-graph-builder.h"
#include "src/compiler/common-operator.h"
@ -469,11 +470,11 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
AllowCodeDependencyChange allow_code_dep_change;
CallFrequency frequency = call.frequency();
Handle<NativeContext> native_context(info_->native_context(), isolate());
BuildGraphFromBytecode(broker(), zone(), bytecode_array.object(),
shared_info.value().object(),
feedback_vector.object(), BailoutId::None(),
jsgraph(), frequency, source_positions_,
native_context, inlining_id, flags);
BuildGraphFromBytecode(
broker(), zone(), bytecode_array.object(),
shared_info.value().object(), feedback_vector.object(),
BailoutId::None(), jsgraph(), frequency, source_positions_,
native_context, inlining_id, flags, &info_->tick_counter());
}
// Extract the inlinee start/end nodes.

View File

@ -4,6 +4,7 @@
#include "src/compiler/loop-analysis.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/graph.h"
#include "src/compiler/node-marker.h"
#include "src/compiler/node-properties.h"
@ -12,6 +13,9 @@
namespace v8 {
namespace internal {
class TickCounter;
namespace compiler {
#define OFFSET(x) ((x)&0x1F)
@ -51,7 +55,8 @@ struct TempLoopInfo {
// marks on edges into/out-of the loop header nodes.
class LoopFinderImpl {
public:
LoopFinderImpl(Graph* graph, LoopTree* loop_tree, Zone* zone)
LoopFinderImpl(Graph* graph, LoopTree* loop_tree, TickCounter* tick_counter,
Zone* zone)
: zone_(zone),
end_(graph->end()),
queue_(zone),
@ -63,7 +68,8 @@ class LoopFinderImpl {
loops_found_(0),
width_(0),
backward_(nullptr),
forward_(nullptr) {}
forward_(nullptr),
tick_counter_(tick_counter) {}
void Run() {
PropagateBackward();
@ -116,6 +122,7 @@ class LoopFinderImpl {
int width_;
uint32_t* backward_;
uint32_t* forward_;
TickCounter* const tick_counter_;
int num_nodes() {
return static_cast<int>(loop_tree_->node_to_loop_num_.size());
@ -183,6 +190,7 @@ class LoopFinderImpl {
Queue(end_);
while (!queue_.empty()) {
tick_counter_->DoTick();
Node* node = queue_.front();
info(node);
queue_.pop_front();
@ -301,6 +309,7 @@ class LoopFinderImpl {
}
// Propagate forward on paths that were backward reachable from backedges.
while (!queue_.empty()) {
tick_counter_->DoTick();
Node* node = queue_.front();
queue_.pop_front();
queued_.Set(node, false);
@ -512,11 +521,11 @@ class LoopFinderImpl {
}
};
LoopTree* LoopFinder::BuildLoopTree(Graph* graph, Zone* zone) {
LoopTree* LoopFinder::BuildLoopTree(Graph* graph, TickCounter* tick_counter,
Zone* zone) {
LoopTree* loop_tree =
new (graph->zone()) LoopTree(graph->NodeCount(), graph->zone());
LoopFinderImpl finder(graph, loop_tree, zone);
LoopFinderImpl finder(graph, loop_tree, tick_counter, zone);
finder.Run();
if (FLAG_trace_turbo_loop) {
finder.Print();
@ -524,7 +533,6 @@ LoopTree* LoopFinder::BuildLoopTree(Graph* graph, Zone* zone) {
return loop_tree;
}
Node* LoopTree::HeaderNode(Loop* loop) {
Node* first = *HeaderNodes(loop).begin();
if (first->opcode() == IrOpcode::kLoop) return first;

View File

@ -13,6 +13,9 @@
namespace v8 {
namespace internal {
class TickCounter;
namespace compiler {
// TODO(titzer): don't assume entry edges have a particular index.
@ -156,7 +159,8 @@ class LoopTree : public ZoneObject {
class V8_EXPORT_PRIVATE LoopFinder {
public:
// Build a loop tree for the entire graph.
static LoopTree* BuildLoopTree(Graph* graph, Zone* temp_zone);
static LoopTree* BuildLoopTree(Graph* graph, TickCounter* tick_counter,
Zone* temp_zone);
};

View File

@ -5,6 +5,7 @@
#include "src/compiler/memory-optimizer.h"
#include "src/codegen/interface-descriptors.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/node-matchers.h"
@ -20,7 +21,8 @@ namespace compiler {
MemoryOptimizer::MemoryOptimizer(JSGraph* jsgraph, Zone* zone,
PoisoningMitigationLevel poisoning_level,
AllocationFolding allocation_folding,
const char* function_debug_name)
const char* function_debug_name,
TickCounter* tick_counter)
: jsgraph_(jsgraph),
empty_state_(AllocationState::Empty(zone)),
pending_(zone),
@ -29,7 +31,8 @@ MemoryOptimizer::MemoryOptimizer(JSGraph* jsgraph, Zone* zone,
graph_assembler_(jsgraph, nullptr, nullptr, zone),
poisoning_level_(poisoning_level),
allocation_folding_(allocation_folding),
function_debug_name_(function_debug_name) {}
function_debug_name_(function_debug_name),
tick_counter_(tick_counter) {}
void MemoryOptimizer::Optimize() {
EnqueueUses(graph()->start(), empty_state());
@ -216,6 +219,7 @@ Node* EffectPhiForPhi(Node* phi) {
} // namespace
void MemoryOptimizer::VisitNode(Node* node, AllocationState const* state) {
tick_counter_->DoTick();
DCHECK(!node->IsDead());
DCHECK_LT(0, node->op()->EffectInputCount());
switch (node->opcode()) {

View File

@ -10,6 +10,9 @@
namespace v8 {
namespace internal {
class TickCounter;
namespace compiler {
// Forward declarations.
@ -36,7 +39,7 @@ class MemoryOptimizer final {
MemoryOptimizer(JSGraph* jsgraph, Zone* zone,
PoisoningMitigationLevel poisoning_level,
AllocationFolding allocation_folding,
const char* function_debug_name);
const char* function_debug_name, TickCounter* tick_counter);
~MemoryOptimizer() = default;
void Optimize();
@ -158,6 +161,7 @@ class MemoryOptimizer final {
PoisoningMitigationLevel poisoning_level_;
AllocationFolding allocation_folding_;
const char* function_debug_name_;
TickCounter* const tick_counter_;
DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryOptimizer);
};

View File

@ -327,7 +327,8 @@ class PipelineData {
Typer* CreateTyper() {
DCHECK_NULL(typer_);
typer_ = new Typer(broker(), typer_flags_, graph());
typer_ =
new Typer(broker(), typer_flags_, graph(), &info()->tick_counter());
return typer_;
}
@ -412,7 +413,8 @@ class PipelineData {
DCHECK_NULL(register_allocation_data_);
register_allocation_data_ = new (register_allocation_zone())
RegisterAllocationData(config, register_allocation_zone(), frame(),
sequence(), flags, debug_name());
sequence(), flags, &info()->tick_counter(),
debug_name());
}
void InitializeOsrHelper() {
@ -1182,7 +1184,7 @@ struct GraphBuilderPhase {
handle(data->info()->closure()->feedback_vector(), data->isolate()),
data->info()->osr_offset(), data->jsgraph(), frequency,
data->source_positions(), data->native_context(),
SourcePosition::kNotInlined, flags);
SourcePosition::kNotInlined, flags, &data->info()->tick_counter());
}
};
@ -1219,7 +1221,7 @@ struct InliningPhase {
void Run(PipelineData* data, Zone* temp_zone) {
Isolate* isolate = data->isolate();
OptimizedCompilationInfo* info = data->info();
GraphReducer graph_reducer(temp_zone, data->graph(),
GraphReducer graph_reducer(temp_zone, data->graph(), &info->tick_counter(),
data->jsgraph()->Dead());
DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common(), temp_zone);
@ -1313,6 +1315,7 @@ struct UntyperPhase {
}
GraphReducer graph_reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
RemoveTypeReducer remove_type_reducer;
AddReducer(data, &graph_reducer, &remove_type_reducer);
@ -1333,6 +1336,7 @@ struct CopyMetadataForConcurrentCompilePhase {
void Run(PipelineData* data, Zone* temp_zone) {
GraphReducer graph_reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
JSHeapCopyReducer heap_copy_reducer(data->broker());
AddReducer(data, &graph_reducer, &heap_copy_reducer);
@ -1375,6 +1379,7 @@ struct TypedLoweringPhase {
void Run(PipelineData* data, Zone* temp_zone) {
GraphReducer graph_reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common(), temp_zone);
@ -1410,9 +1415,12 @@ struct EscapeAnalysisPhase {
static const char* phase_name() { return "V8.TFEscapeAnalysis"; }
void Run(PipelineData* data, Zone* temp_zone) {
EscapeAnalysis escape_analysis(data->jsgraph(), temp_zone);
EscapeAnalysis escape_analysis(data->jsgraph(),
&data->info()->tick_counter(), temp_zone);
escape_analysis.ReduceGraph();
GraphReducer reducer(temp_zone, data->graph(), data->jsgraph()->Dead());
GraphReducer reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
EscapeAnalysisReducer escape_reducer(&reducer, data->jsgraph(),
escape_analysis.analysis_result(),
temp_zone);
@ -1428,6 +1436,7 @@ struct TypeAssertionsPhase {
void Run(PipelineData* data, Zone* temp_zone) {
GraphReducer graph_reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
AddTypeAssertionsReducer type_assertions(&graph_reducer, data->jsgraph(),
temp_zone);
@ -1442,7 +1451,8 @@ struct SimplifiedLoweringPhase {
void Run(PipelineData* data, Zone* temp_zone) {
SimplifiedLowering lowering(data->jsgraph(), data->broker(), temp_zone,
data->source_positions(), data->node_origins(),
data->info()->GetPoisoningMitigationLevel());
data->info()->GetPoisoningMitigationLevel(),
&data->info()->tick_counter());
lowering.LowerAllNodes();
}
};
@ -1456,8 +1466,8 @@ struct LoopPeelingPhase {
data->jsgraph()->GetCachedNodes(&roots);
trimmer.TrimGraph(roots.begin(), roots.end());
LoopTree* loop_tree =
LoopFinder::BuildLoopTree(data->jsgraph()->graph(), temp_zone);
LoopTree* loop_tree = LoopFinder::BuildLoopTree(
data->jsgraph()->graph(), &data->info()->tick_counter(), temp_zone);
LoopPeeler(data->graph(), data->common(), loop_tree, temp_zone,
data->source_positions(), data->node_origins())
.PeelInnerLoopsOfTree();
@ -1477,6 +1487,7 @@ struct GenericLoweringPhase {
void Run(PipelineData* data, Zone* temp_zone) {
GraphReducer graph_reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
JSGenericLowering generic_lowering(data->jsgraph(), &graph_reducer);
AddReducer(data, &graph_reducer, &generic_lowering);
@ -1489,6 +1500,7 @@ struct EarlyOptimizationPhase {
void Run(PipelineData* data, Zone* temp_zone) {
GraphReducer graph_reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common(), temp_zone);
@ -1515,7 +1527,8 @@ struct ControlFlowOptimizationPhase {
void Run(PipelineData* data, Zone* temp_zone) {
ControlFlowOptimizer optimizer(data->graph(), data->common(),
data->machine(), temp_zone);
data->machine(),
&data->info()->tick_counter(), temp_zone);
optimizer.Optimize();
}
};
@ -1537,8 +1550,9 @@ struct EffectControlLinearizationPhase {
// fix the effect and control flow for nodes with low-level side
// effects (such as changing representation to tagged or
// 'floating' allocation regions.)
Schedule* schedule = Scheduler::ComputeSchedule(temp_zone, data->graph(),
Scheduler::kTempSchedule);
Schedule* schedule = Scheduler::ComputeSchedule(
temp_zone, data->graph(), Scheduler::kTempSchedule,
&data->info()->tick_counter());
if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule);
TraceSchedule(data->info(), data, schedule,
"effect linearization schedule");
@ -1564,6 +1578,7 @@ struct EffectControlLinearizationPhase {
// doing a common operator reducer and dead code elimination just before
// it, to eliminate conditional deopts with a constant condition.
GraphReducer graph_reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
data->common(), temp_zone);
@ -1586,7 +1601,8 @@ struct StoreStoreEliminationPhase {
data->jsgraph()->GetCachedNodes(&roots);
trimmer.TrimGraph(roots.begin(), roots.end());
StoreStoreElimination::Run(data->jsgraph(), temp_zone);
StoreStoreElimination::Run(data->jsgraph(), &data->info()->tick_counter(),
temp_zone);
}
};
@ -1595,6 +1611,7 @@ struct LoadEliminationPhase {
void Run(PipelineData* data, Zone* temp_zone) {
GraphReducer graph_reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
BranchElimination branch_condition_elimination(&graph_reducer,
data->jsgraph(), temp_zone);
@ -1644,7 +1661,7 @@ struct MemoryOptimizationPhase {
data->info()->is_allocation_folding_enabled()
? MemoryOptimizer::AllocationFolding::kDoAllocationFolding
: MemoryOptimizer::AllocationFolding::kDontAllocationFolding,
data->debug_name());
data->debug_name(), &data->info()->tick_counter());
optimizer.Optimize();
}
};
@ -1654,6 +1671,7 @@ struct LateOptimizationPhase {
void Run(PipelineData* data, Zone* temp_zone) {
GraphReducer graph_reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
BranchElimination branch_condition_elimination(&graph_reducer,
data->jsgraph(), temp_zone);
@ -1686,6 +1704,7 @@ struct MachineOperatorOptimizationPhase {
void Run(PipelineData* data, Zone* temp_zone) {
GraphReducer graph_reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
ValueNumberingReducer value_numbering(temp_zone, data->graph()->zone());
MachineOperatorReducer machine_reducer(&graph_reducer, data->jsgraph());
@ -1701,6 +1720,7 @@ struct CsaEarlyOptimizationPhase {
void Run(PipelineData* data, Zone* temp_zone) {
GraphReducer graph_reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
BranchElimination branch_condition_elimination(&graph_reducer,
data->jsgraph(), temp_zone);
@ -1726,6 +1746,7 @@ struct CsaOptimizationPhase {
void Run(PipelineData* data, Zone* temp_zone) {
GraphReducer graph_reducer(temp_zone, data->graph(),
&data->info()->tick_counter(),
data->jsgraph()->Dead());
BranchElimination branch_condition_elimination(&graph_reducer,
data->jsgraph(), temp_zone);
@ -1777,9 +1798,10 @@ struct ComputeSchedulePhase {
void Run(PipelineData* data, Zone* temp_zone) {
Schedule* schedule = Scheduler::ComputeSchedule(
temp_zone, data->graph(), data->info()->is_splitting_enabled()
? Scheduler::kSplitNodes
: Scheduler::kNoFlags);
temp_zone, data->graph(),
data->info()->is_splitting_enabled() ? Scheduler::kSplitNodes
: Scheduler::kNoFlags,
&data->info()->tick_counter());
if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule);
data->set_schedule(schedule);
}
@ -1827,6 +1849,7 @@ struct InstructionSelectionPhase {
data->info()->switch_jump_table_enabled()
? InstructionSelector::kEnableSwitchJumpTable
: InstructionSelector::kDisableSwitchJumpTable,
&data->info()->tick_counter(),
data->info()->is_source_positions_enabled()
? InstructionSelector::kAllSourcePositions
: InstructionSelector::kCallSourcePositions,
@ -2076,7 +2099,8 @@ struct PrintGraphPhase {
Schedule* schedule = data->schedule();
if (schedule == nullptr) {
schedule = Scheduler::ComputeSchedule(temp_zone, data->graph(),
Scheduler::kNoFlags);
Scheduler::kNoFlags,
&info->tick_counter());
}
AllowHandleDereference allow_deref;
@ -2609,6 +2633,7 @@ void Pipeline::GenerateCodeForWasmFunction(
if (FLAG_wasm_opt || is_asm_js) {
PipelineRunScope scope(&data, "V8.WasmFullOptimization");
GraphReducer graph_reducer(scope.zone(), data.graph(),
&data.info()->tick_counter(),
data.mcgraph()->Dead());
DeadCodeElimination dead_code_elimination(&graph_reducer, data.graph(),
data.common(), scope.zone());
@ -2627,6 +2652,7 @@ void Pipeline::GenerateCodeForWasmFunction(
} else {
PipelineRunScope scope(&data, "V8.WasmBaseOptimization");
GraphReducer graph_reducer(scope.zone(), data.graph(),
&data.info()->tick_counter(),
data.mcgraph()->Dead());
ValueNumberingReducer value_numbering(scope.zone(), data.graph()->zone());
AddReducer(&data, &graph_reducer, &value_numbering);

View File

@ -7,6 +7,7 @@
#include <iomanip>
#include "src/base/adapters.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/control-equivalence.h"
#include "src/compiler/graph.h"
@ -26,7 +27,7 @@ namespace compiler {
} while (false)
Scheduler::Scheduler(Zone* zone, Graph* graph, Schedule* schedule, Flags flags,
size_t node_count_hint)
size_t node_count_hint, TickCounter* tick_counter)
: zone_(zone),
graph_(graph),
schedule_(schedule),
@ -34,12 +35,14 @@ Scheduler::Scheduler(Zone* zone, Graph* graph, Schedule* schedule, Flags flags,
scheduled_nodes_(zone),
schedule_root_nodes_(zone),
schedule_queue_(zone),
node_data_(zone) {
node_data_(zone),
tick_counter_(tick_counter) {
node_data_.reserve(node_count_hint);
node_data_.resize(graph->NodeCount(), DefaultSchedulerData());
}
Schedule* Scheduler::ComputeSchedule(Zone* zone, Graph* graph, Flags flags) {
Schedule* Scheduler::ComputeSchedule(Zone* zone, Graph* graph, Flags flags,
TickCounter* tick_counter) {
Zone* schedule_zone =
(flags & Scheduler::kTempSchedule) ? zone : graph->zone();
@ -50,7 +53,8 @@ Schedule* Scheduler::ComputeSchedule(Zone* zone, Graph* graph, Flags flags) {
Schedule* schedule =
new (schedule_zone) Schedule(schedule_zone, node_count_hint);
Scheduler scheduler(zone, graph, schedule, flags, node_count_hint);
Scheduler scheduler(zone, graph, schedule, flags, node_count_hint,
tick_counter);
scheduler.BuildCFG();
scheduler.ComputeSpecialRPONumbering();
@ -65,7 +69,6 @@ Schedule* Scheduler::ComputeSchedule(Zone* zone, Graph* graph, Flags flags) {
return schedule;
}
Scheduler::SchedulerData Scheduler::DefaultSchedulerData() {
SchedulerData def = {schedule_->start(), 0, kUnknown};
return def;
@ -258,6 +261,7 @@ class CFGBuilder : public ZoneObject {
Queue(scheduler_->graph_->end());
while (!queue_.empty()) { // Breadth-first backwards traversal.
scheduler_->tick_counter_->DoTick();
Node* node = queue_.front();
queue_.pop();
int max = NodeProperties::PastControlIndex(node);
@ -283,6 +287,7 @@ class CFGBuilder : public ZoneObject {
component_end_ = schedule_->block(exit);
scheduler_->equivalence_->Run(exit);
while (!queue_.empty()) { // Breadth-first backwards traversal.
scheduler_->tick_counter_->DoTick();
Node* node = queue_.front();
queue_.pop();
@ -1234,6 +1239,7 @@ void Scheduler::PrepareUses() {
visited[node->id()] = true;
stack.push(node->input_edges().begin());
while (!stack.empty()) {
tick_counter_->DoTick();
Edge edge = *stack.top();
Node* node = edge.to();
if (visited[node->id()]) {
@ -1262,6 +1268,7 @@ class ScheduleEarlyNodeVisitor {
for (Node* const root : *roots) {
queue_.push(root);
while (!queue_.empty()) {
scheduler_->tick_counter_->DoTick();
VisitNode(queue_.front());
queue_.pop();
}
@ -1388,6 +1395,7 @@ class ScheduleLateNodeVisitor {
queue->push(node);
do {
scheduler_->tick_counter_->DoTick();
Node* const node = queue->front();
queue->pop();
VisitNode(node);

View File

@ -15,6 +15,9 @@
namespace v8 {
namespace internal {
class TickCounter;
namespace compiler {
// Forward declarations.
@ -23,7 +26,6 @@ class ControlEquivalence;
class Graph;
class SpecialRPONumberer;
// Computes a schedule from a graph, placing nodes into basic blocks and
// ordering the basic blocks in the special RPO order.
class V8_EXPORT_PRIVATE Scheduler {
@ -34,7 +36,8 @@ class V8_EXPORT_PRIVATE Scheduler {
// The complete scheduling algorithm. Creates a new schedule and places all
// nodes from the graph into it.
static Schedule* ComputeSchedule(Zone* temp_zone, Graph* graph, Flags flags);
static Schedule* ComputeSchedule(Zone* temp_zone, Graph* graph, Flags flags,
TickCounter* tick_counter);
// Compute the RPO of blocks in an existing schedule.
static BasicBlockVector* ComputeSpecialRPO(Zone* zone, Schedule* schedule);
@ -78,9 +81,10 @@ class V8_EXPORT_PRIVATE Scheduler {
CFGBuilder* control_flow_builder_; // Builds basic blocks for controls.
SpecialRPONumberer* special_rpo_; // Special RPO numbering of blocks.
ControlEquivalence* equivalence_; // Control dependence equivalence.
TickCounter* const tick_counter_;
Scheduler(Zone* zone, Graph* graph, Schedule* schedule, Flags flags,
size_t node_count_hint_);
size_t node_count_hint_, TickCounter* tick_counter);
inline SchedulerData DefaultSchedulerData();
inline SchedulerData* GetData(Node* node);

View File

@ -8,6 +8,7 @@
#include "src/base/bits.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/compiler-source-position-table.h"
@ -22,8 +23,8 @@
#include "src/compiler/simplified-operator.h"
#include "src/compiler/type-cache.h"
#include "src/numbers/conversions-inl.h"
#include "src/utils/address-map.h"
#include "src/objects/objects.h"
#include "src/utils/address-map.h"
namespace v8 {
namespace internal {
@ -279,7 +280,8 @@ class RepresentationSelector {
RepresentationSelector(JSGraph* jsgraph, JSHeapBroker* broker, Zone* zone,
RepresentationChanger* changer,
SourcePositionTable* source_positions,
NodeOriginTable* node_origins)
NodeOriginTable* node_origins,
TickCounter* tick_counter)
: jsgraph_(jsgraph),
zone_(zone),
count_(jsgraph->graph()->NodeCount()),
@ -296,7 +298,8 @@ class RepresentationSelector {
source_positions_(source_positions),
node_origins_(node_origins),
type_cache_(TypeCache::Get()),
op_typer_(broker, graph_zone()) {
op_typer_(broker, graph_zone()),
tick_counter_(tick_counter) {
}
// Forward propagation of types from type feedback.
@ -1683,6 +1686,8 @@ class RepresentationSelector {
// Depending on the operator, propagate new usage info to the inputs.
void VisitNode(Node* node, Truncation truncation,
SimplifiedLowering* lowering) {
tick_counter_->DoTick();
// Unconditionally eliminate unused pure nodes (only relevant if there's
// a pure operation in between two effectful ones, where the last one
// is unused).
@ -3656,6 +3661,7 @@ class RepresentationSelector {
NodeOriginTable* node_origins_;
TypeCache const* type_cache_;
OperationTyper op_typer_; // helper for the feedback typer
TickCounter* const tick_counter_;
NodeInfo* GetInfo(Node* node) {
DCHECK(node->id() < count_);
@ -3669,19 +3675,22 @@ SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, JSHeapBroker* broker,
Zone* zone,
SourcePositionTable* source_positions,
NodeOriginTable* node_origins,
PoisoningMitigationLevel poisoning_level)
PoisoningMitigationLevel poisoning_level,
TickCounter* tick_counter)
: jsgraph_(jsgraph),
broker_(broker),
zone_(zone),
type_cache_(TypeCache::Get()),
source_positions_(source_positions),
node_origins_(node_origins),
poisoning_level_(poisoning_level) {}
poisoning_level_(poisoning_level),
tick_counter_(tick_counter) {}
void SimplifiedLowering::LowerAllNodes() {
RepresentationChanger changer(jsgraph(), broker_);
RepresentationSelector selector(jsgraph(), broker_, zone_, &changer,
source_positions_, node_origins_);
source_positions_, node_origins_,
tick_counter_);
selector.Run(this);
}

View File

@ -12,6 +12,9 @@
namespace v8 {
namespace internal {
class TickCounter;
namespace compiler {
// Forward declarations.
@ -26,7 +29,8 @@ class V8_EXPORT_PRIVATE SimplifiedLowering final {
SimplifiedLowering(JSGraph* jsgraph, JSHeapBroker* broker, Zone* zone,
SourcePositionTable* source_position,
NodeOriginTable* node_origins,
PoisoningMitigationLevel poisoning_level);
PoisoningMitigationLevel poisoning_level,
TickCounter* tick_counter);
~SimplifiedLowering() = default;
void LowerAllNodes();
@ -67,6 +71,8 @@ class V8_EXPORT_PRIVATE SimplifiedLowering final {
PoisoningMitigationLevel poisoning_level_;
TickCounter* const tick_counter_;
Node* Float64Round(Node* const node);
Node* Float64Sign(Node* const node);
Node* Int32Abs(Node* const node);

View File

@ -6,6 +6,7 @@
#include "src/compiler/store-store-elimination.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/all-nodes.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-properties.h"
@ -129,7 +130,8 @@ namespace {
class RedundantStoreFinder final {
public:
RedundantStoreFinder(JSGraph* js_graph, Zone* temp_zone);
RedundantStoreFinder(JSGraph* js_graph, TickCounter* tick_counter,
Zone* temp_zone);
void Find();
@ -157,6 +159,7 @@ class RedundantStoreFinder final {
ZoneSet<Node*>& to_remove() { return to_remove_; }
JSGraph* const jsgraph_;
TickCounter* const tick_counter_;
Zone* const temp_zone_;
ZoneStack<Node*> revisit_;
@ -199,6 +202,7 @@ void RedundantStoreFinder::Find() {
Visit(jsgraph()->graph()->end());
while (!revisit_.empty()) {
tick_counter_->DoTick();
Node* next = revisit_.top();
revisit_.pop();
DCHECK_LT(next->id(), in_revisit_.size());
@ -230,9 +234,10 @@ bool RedundantStoreFinder::HasBeenVisited(Node* node) {
return !unobservable_for_id(node->id()).IsUnvisited();
}
void StoreStoreElimination::Run(JSGraph* js_graph, Zone* temp_zone) {
void StoreStoreElimination::Run(JSGraph* js_graph, TickCounter* tick_counter,
Zone* temp_zone) {
// Find superfluous nodes
RedundantStoreFinder finder(js_graph, temp_zone);
RedundantStoreFinder finder(js_graph, tick_counter, temp_zone);
finder.Find();
// Remove superfluous nodes
@ -336,8 +341,11 @@ bool RedundantStoreFinder::CannotObserveStoreField(Node* node) {
}
// Initialize unobservable_ with js_graph->graph->NodeCount() empty sets.
RedundantStoreFinder::RedundantStoreFinder(JSGraph* js_graph, Zone* temp_zone)
RedundantStoreFinder::RedundantStoreFinder(JSGraph* js_graph,
TickCounter* tick_counter,
Zone* temp_zone)
: jsgraph_(js_graph),
tick_counter_(tick_counter),
temp_zone_(temp_zone),
revisit_(temp_zone),
in_revisit_(js_graph->graph()->NodeCount(), temp_zone),

View File

@ -11,11 +11,15 @@
namespace v8 {
namespace internal {
class TickCounter;
namespace compiler {
class StoreStoreElimination final {
public:
static void Run(JSGraph* js_graph, Zone* temp_zone);
static void Run(JSGraph* js_graph, TickCounter* tick_counter,
Zone* temp_zone);
};
} // namespace compiler

View File

@ -7,6 +7,7 @@
#include <iomanip>
#include "src/base/flags.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-operator.h"
@ -33,13 +34,15 @@ class Typer::Decorator final : public GraphDecorator {
Typer* const typer_;
};
Typer::Typer(JSHeapBroker* broker, Flags flags, Graph* graph)
Typer::Typer(JSHeapBroker* broker, Flags flags, Graph* graph,
TickCounter* tick_counter)
: flags_(flags),
graph_(graph),
decorator_(nullptr),
cache_(TypeCache::Get()),
broker_(broker),
operation_typer_(broker, zone()) {
operation_typer_(broker, zone()),
tick_counter_(tick_counter) {
singleton_false_ = operation_typer_.singleton_false();
singleton_true_ = operation_typer_.singleton_true();
@ -47,7 +50,6 @@ Typer::Typer(JSHeapBroker* broker, Flags flags, Graph* graph)
graph_->AddDecorator(decorator_);
}
Typer::~Typer() {
graph_->RemoveDecorator(decorator_);
}
@ -422,7 +424,7 @@ void Typer::Run(const NodeVector& roots,
induction_vars->ChangeToInductionVariablePhis();
}
Visitor visitor(this, induction_vars);
GraphReducer graph_reducer(zone(), graph());
GraphReducer graph_reducer(zone(), graph(), tick_counter_);
graph_reducer.AddReducer(&visitor);
for (Node* const root : roots) graph_reducer.ReduceNode(root);
graph_reducer.ReduceGraph();

View File

@ -11,6 +11,9 @@
namespace v8 {
namespace internal {
class TickCounter;
namespace compiler {
// Forward declarations.
@ -25,7 +28,8 @@ class V8_EXPORT_PRIVATE Typer {
};
using Flags = base::Flags<Flag>;
Typer(JSHeapBroker* broker, Flags flags, Graph* graph);
Typer(JSHeapBroker* broker, Flags flags, Graph* graph,
TickCounter* tick_counter);
~Typer();
void Run();
@ -49,6 +53,7 @@ class V8_EXPORT_PRIVATE Typer {
TypeCache const* cache_;
JSHeapBroker* broker_;
OperationTyper operation_typer_;
TickCounter* const tick_counter_;
Type singleton_false_;
Type singleton_true_;

View File

@ -91,7 +91,9 @@ namespace internal {
HR(wasm_module_num_triggered_code_gcs, \
V8.WasmModuleNumberOfCodeGCsTriggered, 1, 128, 20) \
/* bailout reason if Liftoff failed, or {kSuccess} (per function) */ \
HR(liftoff_bailout_reasons, V8.LiftoffBailoutReasons, 0, 20, 21)
HR(liftoff_bailout_reasons, V8.LiftoffBailoutReasons, 0, 20, 21) \
/* Ticks observed in a single Turbofan compilation, in 1K */ \
HR(turbofan_ticks, V8.TurboFan1KTicks, 0, 100000, 200)
#define HISTOGRAM_TIMER_LIST(HT) \
/* Timer histograms, not thread safe: HT(name, caption, max, unit) */ \

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/codegen/tick-counter.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/js-context-specialization.h"
#include "src/compiler/js-graph.h"
@ -31,7 +32,7 @@ class ContextSpecializationTester : public HandleAndZoneScope {
simplified_(main_zone()),
jsgraph_(main_isolate(), graph(), common(), &javascript_, &simplified_,
&machine_),
reducer_(main_zone(), graph()),
reducer_(main_zone(), graph(), &tick_counter_),
js_heap_broker_(main_isolate(), main_zone(), FLAG_trace_heap_broker),
spec_(&reducer_, jsgraph(), &js_heap_broker_, context,
MaybeHandle<JSFunction>()) {}
@ -52,6 +53,7 @@ class ContextSpecializationTester : public HandleAndZoneScope {
size_t expected_new_depth);
private:
TickCounter tick_counter_;
CanonicalHandleScope canonical_;
Graph* graph_;
CommonOperatorBuilder common_;

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/codegen/tick-counter.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-heap-broker.h"
#include "src/compiler/js-typed-lowering.h"
@ -33,7 +34,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
simplified(main_zone()),
common(main_zone()),
graph(main_zone()),
typer(&js_heap_broker, Typer::kNoFlags, &graph),
typer(&js_heap_broker, Typer::kNoFlags, &graph, &tick_counter),
context_node(nullptr) {
graph.SetStart(graph.NewNode(common.Start(num_parameters)));
graph.SetEnd(graph.NewNode(common.End(1), graph.start()));
@ -41,6 +42,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
}
Isolate* isolate;
TickCounter tick_counter;
CanonicalHandleScope canonical;
JSHeapBroker js_heap_broker;
const Operator* binop;
@ -90,7 +92,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
JSGraph jsgraph(main_isolate(), &graph, &common, &javascript, &simplified,
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(main_zone(), &graph);
GraphReducer graph_reducer(main_zone(), &graph, &tick_counter);
JSTypedLowering reducer(&graph_reducer, &jsgraph, &js_heap_broker,
main_zone());
Reduction reduction = reducer.Reduce(node);

View File

@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/codegen/tick-counter.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/graph.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/loop-analysis.h"
@ -57,6 +58,7 @@ class LoopFinderTester : HandleAndZoneScope {
}
Isolate* isolate;
TickCounter tick_counter;
CommonOperatorBuilder common;
Graph graph;
JSGraph jsgraph;
@ -128,7 +130,7 @@ class LoopFinderTester : HandleAndZoneScope {
StdoutStream{} << AsRPO(graph);
}
Zone zone(main_isolate()->allocator(), ZONE_NAME);
loop_tree = LoopFinder::BuildLoopTree(&graph, &zone);
loop_tree = LoopFinder::BuildLoopTree(&graph, &tick_counter, &zone);
}
return loop_tree;
}

View File

@ -4,6 +4,7 @@
#include "src/base/overflowing-math.h"
#include "src/base/utils/random-number-generator.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/machine-operator-reducer.h"
#include "src/compiler/operator-properties.h"
@ -86,12 +87,13 @@ class ReducerTester : public HandleAndZoneScope {
javascript(main_zone()),
jsgraph(isolate, &graph, &common, &javascript, nullptr, &machine),
maxuint32(Constant<int32_t>(kMaxUInt32)),
graph_reducer(main_zone(), &graph, jsgraph.Dead()) {
graph_reducer(main_zone(), &graph, &tick_counter, jsgraph.Dead()) {
Node* s = graph.NewNode(common.Start(num_parameters));
graph.SetStart(s);
}
Isolate* isolate;
TickCounter tick_counter;
const Operator* binop;
const Operator* unop;
MachineOperatorBuilder machine;

View File

@ -5,6 +5,7 @@
#include "test/unittests/compiler/backend/instruction-selector-unittest.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/graph.h"
#include "src/compiler/schedule.h"
@ -38,11 +39,12 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
InstructionSequence sequence(test_->isolate(), test_->zone(),
instruction_blocks);
SourcePositionTable source_position_table(graph());
TickCounter tick_counter;
InstructionSelector selector(
test_->zone(), node_count, &linkage, &sequence, schedule,
&source_position_table, nullptr,
InstructionSelector::kEnableSwitchJumpTable, source_position_mode,
features, InstructionSelector::kDisableScheduling,
InstructionSelector::kEnableSwitchJumpTable, &tick_counter,
source_position_mode, features, InstructionSelector::kDisableScheduling,
InstructionSelector::kEnableRootsRelativeAddressing,
PoisoningMitigationLevel::kPoisonAll);
selector.SelectInstructions();

View File

@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "src/compiler/branch-elimination.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/node-properties.h"
@ -27,7 +28,7 @@ class BranchEliminationTest : public GraphTest {
JSOperatorBuilder javascript(zone());
JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
machine());
GraphReducer graph_reducer(zone(), graph(), jsgraph.Dead());
GraphReducer graph_reducer(zone(), graph(), tick_counter(), jsgraph.Dead());
BranchElimination branch_condition_elimination(&graph_reducer, &jsgraph,
zone());
graph_reducer.AddReducer(&branch_condition_elimination);

View File

@ -75,7 +75,7 @@ class ConstantFoldingReducerTest : public TypedGraphTest {
JSGraph jsgraph(isolate(), graph(), common(), &javascript, simplified(),
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
GraphReducer graph_reducer(zone(), graph(), tick_counter());
ConstantFoldingReducer reducer(&graph_reducer, &jsgraph, broker());
return reducer.Reduce(node);
}

View File

@ -25,7 +25,8 @@ class ControlFlowOptimizerTest : public GraphTest {
protected:
void Optimize() {
ControlFlowOptimizer optimizer(graph(), common(), machine(), zone());
ControlFlowOptimizer optimizer(graph(), common(), machine(), tick_counter(),
zone());
optimizer.Optimize();
}

View File

@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "test/unittests/compiler/graph-reducer-unittest.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
#include "src/compiler/node.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/node.h"
#include "src/compiler/operator.h"
#include "test/unittests/compiler/graph-reducer-unittest.h"
#include "test/unittests/test-utils.h"
using testing::_;
@ -237,9 +238,11 @@ class AdvancedReducerTest : public TestWithZone {
protected:
Graph* graph() { return &graph_; }
TickCounter* tick_counter() { return &tick_counter_; }
private:
Graph graph_;
TickCounter tick_counter_;
};
@ -368,7 +371,7 @@ TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse2) {
Node* exception = graph()->NewNode(common.IfException(), effect, node);
Node* use_control = graph()->NewNode(common.Merge(1), success);
Node* replacement = graph()->NewNode(&kMockOperator);
GraphReducer graph_reducer(zone(), graph(), dead);
GraphReducer graph_reducer(zone(), graph(), tick_counter(), dead);
ReplaceWithValueReducer r(&graph_reducer);
r.ReplaceWithValue(node, replacement);
EXPECT_EQ(start, use_control->InputAt(0));
@ -392,7 +395,7 @@ TEST_F(AdvancedReducerTest, ReplaceWithValue_ControlUse3) {
Node* exception = graph()->NewNode(common.IfException(), effect, node);
Node* use_control = graph()->NewNode(common.Merge(1), success);
Node* replacement = graph()->NewNode(&kMockOperator);
GraphReducer graph_reducer(zone(), graph(), dead);
GraphReducer graph_reducer(zone(), graph(), tick_counter(), dead);
ReplaceWithValueReducer r(&graph_reducer);
r.ReplaceWithValue(node, replacement);
EXPECT_EQ(start, use_control->InputAt(0));
@ -422,20 +425,20 @@ class GraphReducerTest : public TestWithZone {
protected:
void ReduceNode(Node* node, Reducer* r) {
GraphReducer reducer(zone(), graph());
GraphReducer reducer(zone(), graph(), tick_counter());
reducer.AddReducer(r);
reducer.ReduceNode(node);
}
void ReduceNode(Node* node, Reducer* r1, Reducer* r2) {
GraphReducer reducer(zone(), graph());
GraphReducer reducer(zone(), graph(), tick_counter());
reducer.AddReducer(r1);
reducer.AddReducer(r2);
reducer.ReduceNode(node);
}
void ReduceNode(Node* node, Reducer* r1, Reducer* r2, Reducer* r3) {
GraphReducer reducer(zone(), graph());
GraphReducer reducer(zone(), graph(), tick_counter());
reducer.AddReducer(r1);
reducer.AddReducer(r2);
reducer.AddReducer(r3);
@ -443,20 +446,20 @@ class GraphReducerTest : public TestWithZone {
}
void ReduceGraph(Reducer* r1) {
GraphReducer reducer(zone(), graph());
GraphReducer reducer(zone(), graph(), tick_counter());
reducer.AddReducer(r1);
reducer.ReduceGraph();
}
void ReduceGraph(Reducer* r1, Reducer* r2) {
GraphReducer reducer(zone(), graph());
GraphReducer reducer(zone(), graph(), tick_counter());
reducer.AddReducer(r1);
reducer.AddReducer(r2);
reducer.ReduceGraph();
}
void ReduceGraph(Reducer* r1, Reducer* r2, Reducer* r3) {
GraphReducer reducer(zone(), graph());
GraphReducer reducer(zone(), graph(), tick_counter());
reducer.AddReducer(r1);
reducer.AddReducer(r2);
reducer.AddReducer(r3);
@ -464,9 +467,11 @@ class GraphReducerTest : public TestWithZone {
}
Graph* graph() { return &graph_; }
TickCounter* tick_counter() { return &tick_counter_; }
private:
Graph graph_;
TickCounter tick_counter_;
};

View File

@ -116,7 +116,8 @@ Matcher<Node*> GraphTest::IsUndefinedConstant() {
}
TypedGraphTest::TypedGraphTest(int num_parameters)
: GraphTest(num_parameters), typer_(broker(), Typer::kNoFlags, graph()) {}
: GraphTest(num_parameters),
typer_(broker(), Typer::kNoFlags, graph(), tick_counter()) {}
TypedGraphTest::~TypedGraphTest() = default;

View File

@ -5,6 +5,7 @@
#ifndef V8_UNITTESTS_COMPILER_GRAPH_UNITTEST_H_
#define V8_UNITTESTS_COMPILER_GRAPH_UNITTEST_H_
#include "src/codegen/tick-counter.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/graph.h"
@ -63,6 +64,7 @@ class GraphTest : public TestWithNativeContextAndZone {
SourcePositionTable* source_positions() { return &source_positions_; }
NodeOriginTable* node_origins() { return &node_origins_; }
JSHeapBroker* broker() { return &broker_; }
TickCounter* tick_counter() { return &tick_counter_; }
private:
CanonicalHandleScope canonical_;
@ -71,6 +73,7 @@ class GraphTest : public TestWithNativeContextAndZone {
JSHeapBroker broker_;
SourcePositionTable source_positions_;
NodeOriginTable node_origins_;
TickCounter tick_counter_;
};

View File

@ -4,6 +4,7 @@
#include <cctype>
#include "src/codegen/tick-counter.h"
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/js-call-reducer.h"
#include "src/compiler/js-graph.h"
@ -33,7 +34,7 @@ class JSCallReducerTest : public TypedGraphTest {
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
GraphReducer graph_reducer(zone(), graph(), tick_counter());
JSCallReducer reducer(&graph_reducer, &jsgraph, broker(),
JSCallReducer::kNoFlags, &deps_);

View File

@ -4,6 +4,7 @@
#include "src/compiler/js-create-lowering.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/js-graph.h"
@ -43,7 +44,7 @@ class JSCreateLoweringTest : public TypedGraphTest {
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
GraphReducer graph_reducer(zone(), graph(), tick_counter());
JSCreateLowering reducer(&graph_reducer, &deps_, &jsgraph, broker(),
zone());
return reducer.Reduce(node);

View File

@ -36,7 +36,7 @@ class JSIntrinsicLoweringTest : public GraphTest {
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
GraphReducer graph_reducer(zone(), graph(), tick_counter());
JSIntrinsicLowering reducer(&graph_reducer, &jsgraph);
return reducer.Reduce(node);
}

View File

@ -47,7 +47,7 @@ class JSTypedLoweringTest : public TypedGraphTest {
JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
GraphReducer graph_reducer(zone(), graph(), tick_counter());
JSTypedLowering reducer(&graph_reducer, &jsgraph, broker(), zone());
return reducer.Reduce(node);
}

View File

@ -66,7 +66,7 @@ class LoopPeelingTest : public GraphTest {
StdoutStream{} << AsRPO(*graph());
}
Zone zone(isolate()->allocator(), ZONE_NAME);
return LoopFinder::BuildLoopTree(graph(), &zone);
return LoopFinder::BuildLoopTree(graph(), tick_counter(), &zone);
}

View File

@ -33,7 +33,7 @@ class MachineOperatorReducerTest : public GraphTest {
javascript_(zone()),
jsgraph_(isolate(), graph(), &common_, &javascript_, nullptr,
&machine_),
graph_reducer_(zone(), graph(), jsgraph_.Dead()) {}
graph_reducer_(zone(), graph(), tick_counter(), jsgraph_.Dead()) {}
protected:
Reduction Reduce(Node* node) {

View File

@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "src/compiler/redundancy-elimination.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/common-operator.h"
#include "test/unittests/compiler/graph-reducer-unittest.h"
#include "test/unittests/compiler/graph-unittest.h"
@ -938,7 +939,7 @@ TEST_F(RedundancyEliminationTest, CheckedUint64ToTaggedSigned) {
TEST_F(RedundancyEliminationTest,
SpeculativeNumberEqualWithCheckBoundsBetterType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
Node* lhs = Parameter(Type::Any(), 0);
@ -974,7 +975,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberEqualWithCheckBoundsSameType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
Node* lhs = Parameter(Type::UnsignedSmall(), 0);
@ -1013,7 +1014,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberLessThanWithCheckBoundsBetterType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
Node* lhs = Parameter(Type::Any(), 0);
@ -1049,7 +1050,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberLessThanWithCheckBoundsSameType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
Node* lhs = Parameter(Type::UnsignedSmall(), 0);
@ -1088,7 +1089,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberLessThanOrEqualWithCheckBoundsBetterType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
Node* lhs = Parameter(Type::Any(), 0);
@ -1124,7 +1125,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberLessThanOrEqualWithCheckBoundsSameType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
Node* lhs = Parameter(Type::UnsignedSmall(), 0);
@ -1163,7 +1164,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberAddWithCheckBoundsBetterType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Any(), 0);
@ -1189,7 +1190,7 @@ TEST_F(RedundancyEliminationTest,
}
TEST_F(RedundancyEliminationTest, SpeculativeNumberAddWithCheckBoundsSameType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Range(42.0, 42.0, zone()), 0);
@ -1219,7 +1220,7 @@ TEST_F(RedundancyEliminationTest, SpeculativeNumberAddWithCheckBoundsSameType) {
TEST_F(RedundancyEliminationTest,
SpeculativeNumberSubtractWithCheckBoundsBetterType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Any(), 0);
@ -1247,7 +1248,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberSubtractWithCheckBoundsSameType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Range(42.0, 42.0, zone()), 0);
@ -1278,7 +1279,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeSafeIntegerAddWithCheckBoundsBetterType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Any(), 0);
@ -1306,7 +1307,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeSafeIntegerAddWithCheckBoundsSameType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Range(42.0, 42.0, zone()), 0);
@ -1337,7 +1338,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeSafeIntegerSubtractWithCheckBoundsBetterType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Any(), 0);
@ -1365,7 +1366,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeSafeIntegerSubtractWithCheckBoundsSameType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Range(42.0, 42.0, zone()), 0);
@ -1396,7 +1397,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeToNumberWithCheckBoundsBetterType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
@ -1424,7 +1425,7 @@ TEST_F(RedundancyEliminationTest,
}
TEST_F(RedundancyEliminationTest, SpeculativeToNumberWithCheckBoundsSameType) {
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {

View File

@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "src/compiler/scheduler.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/compiler-source-position-table.h"
@ -38,8 +39,8 @@ class SchedulerTest : public TestWithIsolateAndZone {
StdoutStream{} << AsJSON(*graph(), &table, &table2);
}
Schedule* schedule =
Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kSplitNodes);
Schedule* schedule = Scheduler::ComputeSchedule(
zone(), graph(), Scheduler::kSplitNodes, tick_counter());
if (FLAG_trace_turbo_scheduler) {
StdoutStream{} << *schedule << std::endl;
@ -62,8 +63,10 @@ class SchedulerTest : public TestWithIsolateAndZone {
CommonOperatorBuilder* common() { return &common_; }
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
JSOperatorBuilder* js() { return &js_; }
TickCounter* tick_counter() { return &tick_counter_; }
private:
TickCounter tick_counter_;
Graph graph_;
CommonOperatorBuilder common_;
SimplifiedOperatorBuilder simplified_;
@ -88,7 +91,8 @@ const Operator kMockTailCall(IrOpcode::kTailCall, Operator::kNoProperties,
TEST_F(SchedulerTest, BuildScheduleEmpty) {
graph()->SetStart(graph()->NewNode(common()->Start(0)));
graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start()));
USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags));
USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags,
tick_counter()));
}
@ -102,7 +106,8 @@ TEST_F(SchedulerTest, BuildScheduleOneParameter) {
graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags));
USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags,
tick_counter()));
}

View File

@ -4,6 +4,7 @@
#include "src/compiler/simplified-lowering.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/simplified-operator.h"
@ -42,13 +43,13 @@ class SimplifiedLoweringTest : public GraphTest {
{
// Simplified lowering needs to run w/o the typer decorator so make sure
// the object is not live at the same time.
Typer typer(broker(), Typer::kNoFlags, graph());
Typer typer(broker(), Typer::kNoFlags, graph(), tick_counter());
typer.Run();
}
SimplifiedLowering lowering(jsgraph(), broker(), zone(), source_positions(),
node_origins(),
PoisoningMitigationLevel::kDontPoison);
SimplifiedLowering lowering(
jsgraph(), broker(), zone(), source_positions(), node_origins(),
PoisoningMitigationLevel::kDontPoison, tick_counter());
lowering.LowerAllNodes();
}

View File

@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "src/compiler/simplified-operator-reducer.h"
#include "src/codegen/tick-counter.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-properties.h"
@ -34,7 +35,7 @@ class SimplifiedOperatorReducerTest : public GraphTest {
JSOperatorBuilder javascript(zone());
JSGraph jsgraph(isolate(), graph(), common(), &javascript, simplified(),
&machine);
GraphReducer graph_reducer(zone(), graph());
GraphReducer graph_reducer(zone(), graph(), tick_counter());
SimplifiedOperatorReducer reducer(&graph_reducer, &jsgraph, &broker);
return reducer.Reduce(node);
}

View File

@ -37,7 +37,7 @@ class TypedOptimizationTest : public TypedGraphTest {
JSGraph jsgraph(isolate(), graph(), common(), &javascript, simplified(),
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
GraphReducer graph_reducer(zone(), graph(), tick_counter());
TypedOptimization reducer(&graph_reducer, &deps_, &jsgraph, broker());
return reducer.Reduce(node);
}