Skip to content

Commit 413d9e9

Browse files
aamCommit Queue
authored andcommitted
[vm] Fix liveness calculation to correctly account for try-catch flow.
Ensure that liveness analysis as part of register allocation takes into account try-catch implicit data flow. Fixes #60017 TEST=nested_try_throw_environment_test Change-Id: I6013942f8f4b78655938765e11859008c28cb9e2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/408421 Reviewed-by: Slava Egorov <[email protected]> Commit-Queue: Alexander Aprelev <[email protected]>
1 parent 39c6099 commit 413d9e9

File tree

5 files changed

+51
-42
lines changed

5 files changed

+51
-42
lines changed

runtime/vm/compiler/backend/flow_graph.cc

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -709,15 +709,16 @@ bool FlowGraph::VerifyRedefinitions() {
709709
return true;
710710
}
711711

712-
LivenessAnalysis::LivenessAnalysis(
713-
intptr_t variable_count,
714-
const GrowableArray<BlockEntryInstr*>& postorder)
712+
LivenessAnalysis::LivenessAnalysis(const FlowGraph* flow_graph,
713+
const intptr_t variable_count)
715714
: zone_(Thread::Current()->zone()),
715+
flow_graph_(flow_graph),
716716
variable_count_(variable_count),
717-
postorder_(postorder),
718-
live_out_(postorder.length()),
719-
kill_(postorder.length()),
720-
live_in_(postorder.length()) {}
717+
postorder_(flow_graph->postorder()),
718+
live_out_(postorder_.length()),
719+
kill_(postorder_.length()),
720+
live_in_(postorder_.length()),
721+
does_block_have_throw(zone_, postorder_.length()) {}
721722

722723
bool LivenessAnalysis::UpdateLiveOut(const BlockEntryInstr& block) {
723724
BitVector* live_out = live_out_[block.postorder_number()];
@@ -731,14 +732,29 @@ bool LivenessAnalysis::UpdateLiveOut(const BlockEntryInstr& block) {
731732
changed = true;
732733
}
733734
}
734-
return changed;
735+
return changed || block.InsideTryBlock();
735736
}
736737

737738
bool LivenessAnalysis::UpdateLiveIn(const BlockEntryInstr& block) {
738739
BitVector* live_out = live_out_[block.postorder_number()];
739740
BitVector* kill = kill_[block.postorder_number()];
740741
BitVector* live_in = live_in_[block.postorder_number()];
741-
return live_in->KillAndAdd(kill, live_out);
742+
bool changed = live_in->KillAndAdd(kill, live_out);
743+
744+
// if [block] contains [Throw] instruction, then make sure corresponding
745+
// [catch_block] live_in is also part of this [block] live_in.
746+
if (block.InsideTryBlock()) {
747+
if (does_block_have_throw.Contains(block.postorder_number())) {
748+
BitVector* live_in = live_in_[block.postorder_number()];
749+
CatchBlockEntryInstr* catch_block =
750+
flow_graph_->GetCatchBlockByTryIndex(block.try_index());
751+
auto catch_live_in = live_in_[catch_block->postorder_number()];
752+
if (live_in->AddAll(catch_live_in)) {
753+
changed = true;
754+
}
755+
}
756+
}
757+
return changed;
742758
}
743759

744760
void LivenessAnalysis::ComputeLiveInAndLiveOutSets() {
@@ -803,9 +819,8 @@ void LivenessAnalysis::Dump() {
803819
// Computes liveness information for local variables.
804820
class VariableLivenessAnalysis : public LivenessAnalysis {
805821
public:
806-
explicit VariableLivenessAnalysis(FlowGraph* flow_graph)
807-
: LivenessAnalysis(flow_graph->variable_count(), flow_graph->postorder()),
808-
flow_graph_(flow_graph),
822+
explicit VariableLivenessAnalysis(const FlowGraph* flow_graph)
823+
: LivenessAnalysis(flow_graph, flow_graph->variable_count()),
809824
assigned_vars_() {}
810825

811826
// For every block (in preorder) compute and return set of variables that
@@ -879,10 +894,7 @@ class VariableLivenessAnalysis : public LivenessAnalysis {
879894

880895
private:
881896
virtual void ComputeInitialSets();
882-
virtual bool UpdateLiveOut(const BlockEntryInstr& block);
883-
virtual bool UpdateLiveIn(const BlockEntryInstr& block);
884897

885-
const FlowGraph* flow_graph_;
886898
GrowableArray<BitVector*> assigned_vars_;
887899
};
888900

@@ -902,6 +914,10 @@ void VariableLivenessAnalysis::ComputeInitialSets() {
902914
for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) {
903915
Instruction* current = it.Current();
904916

917+
if (current->MayThrow()) {
918+
does_block_have_throw.Add(i);
919+
}
920+
905921
LoadLocalInstr* load = current->AsLoadLocal();
906922
if (load != nullptr) {
907923
const intptr_t index = flow_graph_->EnvIndex(&load->local());
@@ -965,24 +981,6 @@ void VariableLivenessAnalysis::ComputeInitialSets() {
965981
}
966982
}
967983

968-
bool VariableLivenessAnalysis::UpdateLiveIn(const BlockEntryInstr& block) {
969-
bool changed = LivenessAnalysis::UpdateLiveIn(block);
970-
if (block.InsideTryBlock()) {
971-
BitVector* live_in = live_in_[block.postorder_number()];
972-
CatchBlockEntryInstr* catch_block =
973-
flow_graph_->GetCatchBlockByTryIndex(block.try_index());
974-
auto catch_live_in = live_in_[catch_block->postorder_number()];
975-
if (live_in->AddAll(catch_live_in)) {
976-
changed = true;
977-
}
978-
}
979-
return changed;
980-
}
981-
982-
bool VariableLivenessAnalysis::UpdateLiveOut(const BlockEntryInstr& block) {
983-
return LivenessAnalysis::UpdateLiveOut(block) || block.InsideTryBlock();
984-
}
985-
986984
void FlowGraph::ComputeSSA(
987985
ZoneGrowableArray<Definition*>* inlining_parameters) {
988986
GrowableArray<BitVector*> dominance_frontier;

runtime/vm/compiler/backend/flow_graph.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -803,8 +803,7 @@ class FlowGraph : public ZoneAllocated {
803803

804804
class LivenessAnalysis : public ValueObject {
805805
public:
806-
LivenessAnalysis(intptr_t variable_count,
807-
const GrowableArray<BlockEntryInstr*>& postorder);
806+
LivenessAnalysis(const FlowGraph* flow_graph, const intptr_t variable_count);
808807

809808
void Analyze();
810809

@@ -835,18 +834,20 @@ class LivenessAnalysis : public ValueObject {
835834

836835
protected:
837836
// Compute initial values for live-out, kill and live-in sets.
837+
//
838+
// It's also responsible for populating [does_block_have_throw] set.
838839
virtual void ComputeInitialSets() = 0;
839840

840841
// Update live-out set for the given block: live-out should contain
841842
// all values that are live-in for block's successors.
842843
// Returns true if live-out set was changed.
843-
virtual bool UpdateLiveOut(const BlockEntryInstr& instr);
844+
bool UpdateLiveOut(const BlockEntryInstr& instr);
844845

845846
// Update live-in set for the given block: live-in should contain
846847
// all values that are live-out from the block and are not defined
847848
// by this block.
848849
// Returns true if live-in set was changed.
849-
virtual bool UpdateLiveIn(const BlockEntryInstr& instr);
850+
bool UpdateLiveIn(const BlockEntryInstr& instr);
850851

851852
// Perform fix-point iteration updating live-out and live-in sets
852853
// for blocks until they stop changing.
@@ -856,6 +857,8 @@ class LivenessAnalysis : public ValueObject {
856857

857858
Zone* zone_;
858859

860+
const FlowGraph* flow_graph_;
861+
859862
const intptr_t variable_count_;
860863

861864
const GrowableArray<BlockEntryInstr*>& postorder_;
@@ -873,6 +876,10 @@ class LivenessAnalysis : public ValueObject {
873876
// Live-in sets for each block. They contain indices of variables
874877
// that are used by this block or its successors.
875878
GrowableArray<BitVector*> live_in_;
879+
880+
// Given block's postoroder index indicates whether block has any
881+
// instructions that throw.
882+
BitVector does_block_have_throw;
876883
};
877884

878885
class DefinitionWorklist : public ValueObject {

runtime/vm/compiler/backend/linearscan.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph,
9595
instructions_(),
9696
block_entries_(),
9797
extra_loop_info_(),
98-
liveness_(flow_graph),
98+
liveness_(&flow_graph),
9999
vreg_count_(flow_graph.max_vreg()),
100100
live_ranges_(flow_graph.max_vreg()),
101101
unallocated_cpu_(),
@@ -180,6 +180,10 @@ void SSALivenessAnalysis::ComputeInitialSets() {
180180
for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) {
181181
Instruction* current = it.Current();
182182

183+
if (current->MayThrow()) {
184+
does_block_have_throw.Add(i);
185+
}
186+
183187
// Initialize location summary for instruction.
184188
current->InitializeLocationSummary(zone(), true); // opt
185189

runtime/vm/compiler/backend/linearscan.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ class ReachingDefs : public ValueObject {
3838

3939
class SSALivenessAnalysis : public LivenessAnalysis {
4040
public:
41-
explicit SSALivenessAnalysis(const FlowGraph& flow_graph)
42-
: LivenessAnalysis(flow_graph.max_vreg(), flow_graph.postorder()),
43-
graph_entry_(flow_graph.graph_entry()) {}
41+
explicit SSALivenessAnalysis(const FlowGraph* flow_graph)
42+
: LivenessAnalysis(flow_graph, flow_graph->max_vreg()),
43+
graph_entry_(flow_graph->graph_entry()) {}
4444

4545
private:
4646
// Compute initial values for live-out, kill and live-in sets.

runtime/vm/compiler/backend/redundancy_elimination.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3115,7 +3115,7 @@ class StoreOptimizer : public LivenessAnalysis {
31153115
StoreOptimizer(FlowGraph* graph,
31163116
AliasedSet* aliased_set,
31173117
PointerSet<Place>* map)
3118-
: LivenessAnalysis(aliased_set->max_place_id(), graph->postorder()),
3118+
: LivenessAnalysis(graph, aliased_set->max_place_id()),
31193119
graph_(graph),
31203120
map_(map),
31213121
aliased_set_(aliased_set),

0 commit comments

Comments
 (0)