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