Commit fc9a73e8 authored by sigurds's avatar sigurds Committed by Commit bot

[turbofan] Various performance enhancements for escape analysis

This bug improves performance of escape analysis.

* A allocation discovery phase  (EscapeAnalysis::AssignAliases)
  ensures compact representation of virtual state
* Node revisiting in EscapeStatusAnalysis has been improved
* Escape analysis no longer requires a trimmed graph

BUG=v8:4586
LOG=n

Review URL: https://codereview.chromium.org/1559123003

Cr-Commit-Position: refs/heads/master@{#33267}
parent 0830ac7c
...@@ -108,13 +108,17 @@ class Flags final { ...@@ -108,13 +108,17 @@ class Flags final {
ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \ ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \
inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) { \ inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) { \
return Type(lhs) ^ rhs; \ return Type(lhs) ^ rhs; \
} inline Type operator^(Type::flag_type lhs, const Type& rhs) \ } inline Type \
operator^(Type::flag_type lhs, const Type& rhs) \
ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \ ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \
inline Type operator^(Type::flag_type lhs, const Type& rhs) { \ inline Type operator^(Type::flag_type lhs, const Type& rhs) { \
return rhs ^ lhs; \ return rhs ^ lhs; \
} inline void operator^(Type::flag_type lhs, Type::mask_type rhs) \ } inline void \
ALLOW_UNUSED_TYPE; \ operator^(Type::flag_type lhs, Type::mask_type rhs) ALLOW_UNUSED_TYPE; \
inline void operator^(Type::flag_type lhs, Type::mask_type rhs) {} inline void operator^(Type::flag_type lhs, Type::mask_type rhs) { \
} inline Type \
operator~(Type::flag_type val)ALLOW_UNUSED_TYPE; \
inline Type operator~(Type::flag_type val) { return ~Type(val); }
} // namespace base } // namespace base
} // namespace v8 } // namespace v8
......
This diff is collapsed.
...@@ -26,10 +26,12 @@ class EscapeStatusAnalysis { ...@@ -26,10 +26,12 @@ class EscapeStatusAnalysis {
enum EscapeStatusFlag { enum EscapeStatusFlag {
kUnknown = 0u, kUnknown = 0u,
kVirtual = 1u << 0, kTracked = 1u << 0,
kEscaped = 1u << 1, kEscaped = 1u << 1,
kOnStack = 1u << 2,
kVisited = 1u << 3,
}; };
typedef base::Flags<EscapeStatusFlag> EscapeStatusFlags; typedef base::Flags<EscapeStatusFlag, unsigned char> EscapeStatusFlags;
void Run(); void Run();
...@@ -67,7 +69,7 @@ class EscapeStatusAnalysis { ...@@ -67,7 +69,7 @@ class EscapeStatusAnalysis {
EscapeAnalysis* object_analysis_; EscapeAnalysis* object_analysis_;
Graph* const graph_; Graph* const graph_;
Zone* const zone_; Zone* const zone_;
ZoneVector<EscapeStatusFlags> info_; ZoneVector<EscapeStatusFlags> status_;
ZoneDeque<Node*> queue_; ZoneDeque<Node*> queue_;
DISALLOW_COPY_AND_ASSIGN(EscapeStatusAnalysis); DISALLOW_COPY_AND_ASSIGN(EscapeStatusAnalysis);
...@@ -85,6 +87,8 @@ class MergeCache; ...@@ -85,6 +87,8 @@ class MergeCache;
// an object is virtual and eliminated. // an object is virtual and eliminated.
class EscapeAnalysis { class EscapeAnalysis {
public: public:
typedef NodeId Alias;
EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, Zone* zone); EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, Zone* zone);
~EscapeAnalysis(); ~EscapeAnalysis();
...@@ -98,6 +102,7 @@ class EscapeAnalysis { ...@@ -98,6 +102,7 @@ class EscapeAnalysis {
private: private:
void RunObjectAnalysis(); void RunObjectAnalysis();
void AssignAliases();
bool Process(Node* node); bool Process(Node* node);
void ProcessLoadField(Node* node); void ProcessLoadField(Node* node);
void ProcessStoreField(Node* node); void ProcessStoreField(Node* node);
...@@ -129,14 +134,21 @@ class EscapeAnalysis { ...@@ -129,14 +134,21 @@ class EscapeAnalysis {
bool SetReplacement(Node* node, Node* rep); bool SetReplacement(Node* node, Node* rep);
bool UpdateReplacement(VirtualState* state, Node* node, Node* rep); bool UpdateReplacement(VirtualState* state, Node* node, Node* rep);
VirtualObject* GetVirtualObject(VirtualState* state, Node* node);
void DebugPrint(); void DebugPrint();
void DebugPrintState(VirtualState* state); void DebugPrintState(VirtualState* state);
void DebugPrintObject(VirtualObject* state, NodeId id); void DebugPrintObject(VirtualObject* state, Alias id);
Alias NextAlias() { return next_free_alias_++; }
Alias AliasCount() const { return next_free_alias_; }
Graph* graph() const { return graph_; } Graph* graph() const { return graph_; }
CommonOperatorBuilder* common() const { return common_; } CommonOperatorBuilder* common() const { return common_; }
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
static const Alias kNotReachable;
static const Alias kUntrackable;
Graph* const graph_; Graph* const graph_;
CommonOperatorBuilder* const common_; CommonOperatorBuilder* const common_;
Zone* const zone_; Zone* const zone_;
...@@ -144,6 +156,8 @@ class EscapeAnalysis { ...@@ -144,6 +156,8 @@ class EscapeAnalysis {
ZoneVector<Node*> replacements_; ZoneVector<Node*> replacements_;
EscapeStatusAnalysis escape_status_; EscapeStatusAnalysis escape_status_;
MergeCache* cache_; MergeCache* cache_;
ZoneVector<Alias> aliases_;
Alias next_free_alias_;
DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis); DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis);
}; };
......
...@@ -1165,9 +1165,6 @@ Handle<Code> Pipeline::GenerateCode() { ...@@ -1165,9 +1165,6 @@ Handle<Code> Pipeline::GenerateCode() {
} }
if (FLAG_turbo_escape) { if (FLAG_turbo_escape) {
// TODO(sigurds): EscapeAnalysis needs a trimmed graph at the moment,
// because it does a forwards traversal of the effect edges.
Run<EarlyGraphTrimmingPhase>();
Run<EscapeAnalysisPhase>(); Run<EscapeAnalysisPhase>();
RunPrintAndVerify("Escape Analysed"); RunPrintAndVerify("Escape Analysed");
} }
......
...@@ -190,6 +190,7 @@ TEST_F(EscapeAnalysisTest, StraightNonEscape) { ...@@ -190,6 +190,7 @@ TEST_F(EscapeAnalysisTest, StraightNonEscape) {
Node* load = Load(AccessAtIndex(0), finish); Node* load = Load(AccessAtIndex(0), finish);
Node* result = Return(load); Node* result = Return(load);
EndGraph(); EndGraph();
Analysis(); Analysis();
ExpectVirtual(allocation); ExpectVirtual(allocation);
...@@ -210,6 +211,8 @@ TEST_F(EscapeAnalysisTest, StraightEscape) { ...@@ -210,6 +211,8 @@ TEST_F(EscapeAnalysisTest, StraightEscape) {
Node* load = Load(AccessAtIndex(0), finish); Node* load = Load(AccessAtIndex(0), finish);
Node* result = Return(allocation); Node* result = Return(allocation);
EndGraph(); EndGraph();
graph()->end()->AppendInput(zone(), load);
Analysis(); Analysis();
ExpectEscaped(allocation); ExpectEscaped(allocation);
...@@ -266,6 +269,8 @@ TEST_F(EscapeAnalysisTest, BranchNonEscape) { ...@@ -266,6 +269,8 @@ TEST_F(EscapeAnalysisTest, BranchNonEscape) {
Node* load = Load(AccessAtIndex(0), finish, phi, merge); Node* load = Load(AccessAtIndex(0), finish, phi, merge);
Node* result = Return(load, phi); Node* result = Return(load, phi);
EndGraph(); EndGraph();
graph()->end()->AppendInput(zone(), result);
Analysis(); Analysis();
ExpectVirtual(allocation); ExpectVirtual(allocation);
...@@ -284,10 +289,12 @@ TEST_F(EscapeAnalysisTest, DanglingLoadOrder) { ...@@ -284,10 +289,12 @@ TEST_F(EscapeAnalysisTest, DanglingLoadOrder) {
Node* allocation = Allocate(Constant(kPointerSize)); Node* allocation = Allocate(Constant(kPointerSize));
Node* store1 = Store(AccessAtIndex(0), allocation, object1); Node* store1 = Store(AccessAtIndex(0), allocation, object1);
Node* load1 = Load(AccessAtIndex(0), allocation); Node* load1 = Load(AccessAtIndex(0), allocation);
Store(AccessAtIndex(0), allocation, object2); Node* store2 = Store(AccessAtIndex(0), allocation, object2);
Node* load2 = Load(AccessAtIndex(0), allocation, store1); Node* load2 = Load(AccessAtIndex(0), allocation, store1);
Node* result = Return(load2); Node* result = Return(load2);
EndGraph(); EndGraph();
graph()->end()->AppendInput(zone(), store2);
graph()->end()->AppendInput(zone(), load1);
Analysis(); Analysis();
......
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