11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_COMPILER_ESCAPE_ANALYSIS_REDUCER_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_ESCAPE_ANALYSIS_REDUCER_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/base/compiler-specific.h" 91cb0ef41Sopenharmony_ci#include "src/common/globals.h" 101cb0ef41Sopenharmony_ci#include "src/compiler/access-builder.h" 111cb0ef41Sopenharmony_ci#include "src/compiler/escape-analysis.h" 121cb0ef41Sopenharmony_ci#include "src/compiler/graph-reducer.h" 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_cinamespace v8 { 151cb0ef41Sopenharmony_cinamespace internal { 161cb0ef41Sopenharmony_cinamespace compiler { 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ciclass Deduplicator; 191cb0ef41Sopenharmony_ciclass JSGraph; 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci// Perform hash-consing when creating or mutating nodes. Used to avoid duplicate 221cb0ef41Sopenharmony_ci// nodes when creating ObjectState, StateValues and FrameState nodes 231cb0ef41Sopenharmony_ciclass NodeHashCache { 241cb0ef41Sopenharmony_ci public: 251cb0ef41Sopenharmony_ci NodeHashCache(Graph* graph, Zone* zone) 261cb0ef41Sopenharmony_ci : graph_(graph), cache_(zone), temp_nodes_(zone) {} 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci // Handle to a conceptually new mutable node. Tries to re-use existing nodes 291cb0ef41Sopenharmony_ci // and to recycle memory if possible. 301cb0ef41Sopenharmony_ci class Constructor { 311cb0ef41Sopenharmony_ci public: 321cb0ef41Sopenharmony_ci // Construct a new node as a clone of [from]. 331cb0ef41Sopenharmony_ci Constructor(NodeHashCache* cache, Node* from) 341cb0ef41Sopenharmony_ci : node_cache_(cache), from_(from), tmp_(nullptr) {} 351cb0ef41Sopenharmony_ci // Construct a new node from scratch. 361cb0ef41Sopenharmony_ci Constructor(NodeHashCache* cache, const Operator* op, int input_count, 371cb0ef41Sopenharmony_ci Node** inputs, Type type); 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci // Modify the new node. 401cb0ef41Sopenharmony_ci void ReplaceValueInput(Node* input, int i) { 411cb0ef41Sopenharmony_ci if (!tmp_ && input == NodeProperties::GetValueInput(from_, i)) return; 421cb0ef41Sopenharmony_ci Node* node = MutableNode(); 431cb0ef41Sopenharmony_ci NodeProperties::ReplaceValueInput(node, input, i); 441cb0ef41Sopenharmony_ci } 451cb0ef41Sopenharmony_ci void ReplaceInput(Node* input, int i) { 461cb0ef41Sopenharmony_ci if (!tmp_ && input == from_->InputAt(i)) return; 471cb0ef41Sopenharmony_ci Node* node = MutableNode(); 481cb0ef41Sopenharmony_ci node->ReplaceInput(i, input); 491cb0ef41Sopenharmony_ci } 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci // Obtain the mutated node or a cached copy. Invalidates the [Constructor]. 521cb0ef41Sopenharmony_ci Node* Get(); 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci private: 551cb0ef41Sopenharmony_ci Node* MutableNode(); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci NodeHashCache* node_cache_; 581cb0ef41Sopenharmony_ci // Original node, copied on write. 591cb0ef41Sopenharmony_ci Node* from_; 601cb0ef41Sopenharmony_ci // Temporary node used for mutations, can be recycled if cache is hit. 611cb0ef41Sopenharmony_ci Node* tmp_; 621cb0ef41Sopenharmony_ci }; 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci private: 651cb0ef41Sopenharmony_ci Node* Query(Node* node); 661cb0ef41Sopenharmony_ci void Insert(Node* node) { cache_.insert(node); } 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci Graph* graph_; 691cb0ef41Sopenharmony_ci struct NodeEquals { 701cb0ef41Sopenharmony_ci bool operator()(Node* a, Node* b) const { 711cb0ef41Sopenharmony_ci return NodeProperties::Equals(a, b); 721cb0ef41Sopenharmony_ci } 731cb0ef41Sopenharmony_ci }; 741cb0ef41Sopenharmony_ci struct NodeHashCode { 751cb0ef41Sopenharmony_ci size_t operator()(Node* n) const { return NodeProperties::HashCode(n); } 761cb0ef41Sopenharmony_ci }; 771cb0ef41Sopenharmony_ci ZoneUnorderedSet<Node*, NodeHashCode, NodeEquals> cache_; 781cb0ef41Sopenharmony_ci // Unused nodes whose memory can be recycled. 791cb0ef41Sopenharmony_ci ZoneVector<Node*> temp_nodes_; 801cb0ef41Sopenharmony_ci}; 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci// Modify the graph according to the information computed in the previous phase. 831cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE EscapeAnalysisReducer final 841cb0ef41Sopenharmony_ci : public NON_EXPORTED_BASE(AdvancedReducer) { 851cb0ef41Sopenharmony_ci public: 861cb0ef41Sopenharmony_ci EscapeAnalysisReducer(Editor* editor, JSGraph* jsgraph, JSHeapBroker* broker, 871cb0ef41Sopenharmony_ci EscapeAnalysisResult analysis_result, Zone* zone); 881cb0ef41Sopenharmony_ci EscapeAnalysisReducer(const EscapeAnalysisReducer&) = delete; 891cb0ef41Sopenharmony_ci EscapeAnalysisReducer& operator=(const EscapeAnalysisReducer&) = delete; 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci Reduction Reduce(Node* node) override; 921cb0ef41Sopenharmony_ci const char* reducer_name() const override { return "EscapeAnalysisReducer"; } 931cb0ef41Sopenharmony_ci void Finalize() override; 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci // Verifies that all virtual allocation nodes have been dealt with. Run it 961cb0ef41Sopenharmony_ci // after this reducer has been applied. 971cb0ef41Sopenharmony_ci void VerifyReplacement() const; 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci private: 1001cb0ef41Sopenharmony_ci void ReduceFrameStateInputs(Node* node); 1011cb0ef41Sopenharmony_ci Node* ReduceDeoptState(Node* node, Node* effect, Deduplicator* deduplicator); 1021cb0ef41Sopenharmony_ci Node* ObjectIdNode(const VirtualObject* vobject); 1031cb0ef41Sopenharmony_ci Reduction ReplaceNode(Node* original, Node* replacement); 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci JSGraph* jsgraph() const { return jsgraph_; } 1061cb0ef41Sopenharmony_ci Isolate* isolate() const { return jsgraph_->isolate(); } 1071cb0ef41Sopenharmony_ci EscapeAnalysisResult analysis_result() const { return analysis_result_; } 1081cb0ef41Sopenharmony_ci Zone* zone() const { return zone_; } 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci JSGraph* const jsgraph_; 1111cb0ef41Sopenharmony_ci JSHeapBroker* const broker_; 1121cb0ef41Sopenharmony_ci EscapeAnalysisResult analysis_result_; 1131cb0ef41Sopenharmony_ci ZoneVector<Node*> object_id_cache_; 1141cb0ef41Sopenharmony_ci NodeHashCache node_cache_; 1151cb0ef41Sopenharmony_ci ZoneSet<Node*> arguments_elements_; 1161cb0ef41Sopenharmony_ci Zone* const zone_; 1171cb0ef41Sopenharmony_ci}; 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci} // namespace compiler 1201cb0ef41Sopenharmony_ci} // namespace internal 1211cb0ef41Sopenharmony_ci} // namespace v8 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci#endif // V8_COMPILER_ESCAPE_ANALYSIS_REDUCER_H_ 124