< prev index next >

src/hotspot/share/opto/escape.hpp

Print this page

355 private:
356   // Address of an element in _nodes.  Used when the element is to be modified
357   PointsToNode* ptnode_adr(int idx) const {
358     // There should be no new ideal nodes during ConnectionGraph build,
359     // growableArray::at() will throw assert otherwise.
360     return _nodes.at(idx);
361   }
362   uint nodes_size() const { return _nodes.length(); }
363 
364   uint next_pidx() { return _next_pidx++; }
365 
366   // Add nodes to ConnectionGraph.
367   void add_local_var(Node* n, PointsToNode::EscapeState es);
368   PointsToNode* add_java_object(Node* n, PointsToNode::EscapeState es);
369   void add_field(Node* n, PointsToNode::EscapeState es, int offset);
370   void add_arraycopy(Node* n, PointsToNode::EscapeState es, PointsToNode* src, PointsToNode* dst);
371 
372   // Compute the escape state for arguments to a call.
373   void process_call_arguments(CallNode *call);
374 


375   // Add PointsToNode node corresponding to a call
376   void add_call_node(CallNode* call);
377 
378   // Create PointsToNode node and add it to Connection Graph.
379   void add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist);
380 
381   // Add final simple edges to graph.
382   void add_final_edges(Node *n);
383 
384   // Finish Graph construction.
385   bool complete_connection_graph(GrowableArray<PointsToNode*>&   ptnodes_worklist,
386                                  GrowableArray<JavaObjectNode*>& non_escaped_worklist,
387                                  GrowableArray<JavaObjectNode*>& java_objects_worklist,
388                                  GrowableArray<FieldNode*>&      oop_fields_worklist);
389 
390 #ifdef ASSERT
391   void verify_connection_graph(GrowableArray<PointsToNode*>&   ptnodes_worklist,
392                                GrowableArray<JavaObjectNode*>& non_escaped_worklist,
393                                GrowableArray<JavaObjectNode*>& java_objects_worklist,
394                                GrowableArray<Node*>& addp_worklist);

468   }
469 
470   // Propagate GlobalEscape and ArgEscape escape states to all nodes
471   // and check that we still have non-escaping java objects.
472   bool find_non_escaped_objects(GrowableArray<PointsToNode*>& ptnodes_worklist,
473                                 GrowableArray<JavaObjectNode*>& non_escaped_worklist,
474                                 bool print_method = true);
475 
476   // Adjust scalar_replaceable state after Connection Graph is built.
477   void adjust_scalar_replaceable_state(JavaObjectNode* jobj, Unique_Node_List &reducible_merges);
478 
479   // Reevaluate Phis reducible status after 'obj' became NSR.
480   void revisit_reducible_phi_status(JavaObjectNode* jobj, Unique_Node_List& reducible_merges);
481 
482   // Propagate NSR (Not scalar replaceable) state.
483   void find_scalar_replaceable_allocs(GrowableArray<JavaObjectNode*>& jobj_worklist, Unique_Node_List &reducible_merges);
484 
485   // Optimize ideal graph.
486   void optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklist,
487                             GrowableArray<MemBarStoreStoreNode*>& storestore_worklist);


488   // Optimize objects compare.
489   const TypeInt* optimize_ptr_compare(Node* left, Node* right);
490 
491   // Returns unique corresponding java object or null.
492   JavaObjectNode* unique_java_object(Node *n) const;
493 
494   // Add an edge of the specified type pointing to the specified target.
495   bool add_edge(PointsToNode* from, PointsToNode* to) {
496     assert(!from->is_Field() || from->as_Field()->is_oop(), "sanity");
497 
498     if (to == phantom_obj) {
499       if (from->has_unknown_ptr()) {
500         return false; // already points to phantom_obj
501       }
502       from->set_has_unknown_ptr();
503     }
504 
505     bool is_new = from->add_edge(to);
506     assert(to != phantom_obj || is_new, "sanity");
507     if (is_new) { // New edge?

641 #endif
642 
643 public:
644   ConnectionGraph(Compile *C, PhaseIterGVN *igvn, int iteration);
645 
646   // Verify that SafePointScalarMerge nodes are correctly connected
647   static void verify_ram_nodes(Compile* C, Node* root);
648 
649   // Check for non-escaping candidates
650   static bool has_candidates(Compile *C);
651 
652   // Perform escape analysis
653   static void do_analysis(Compile *C, PhaseIterGVN *igvn);
654 
655   bool not_global_escape(Node *n);
656 
657   bool can_eliminate_lock(AbstractLockNode* alock);
658 
659   // To be used by, e.g., BarrierSetC2 impls
660   Node* get_addp_base(Node* addp);

661 
662   // Utility function for nodes that load an object
663   void add_objload_to_connection_graph(Node* n, Unique_Node_List* delayed_worklist);
664 


665   // Add LocalVar node and edge if possible
666   void add_local_var_and_edge(Node* n, PointsToNode::EscapeState es, Node* to,
667                               Unique_Node_List *delayed_worklist) {
668     PointsToNode* ptn = ptnode_adr(to->_idx);
669     if (delayed_worklist != nullptr) { // First iteration of CG construction
670       add_local_var(n, es);
671       if (ptn == nullptr) {
672         delayed_worklist->push(n);
673         return; // Process it later.
674       }
675     } else {
676       assert(ptn != nullptr, "node should be registered");
677     }
678     add_edge(ptnode_adr(n->_idx), ptn);
679   }
680 
681   // Map ideal node to existing PointsTo node (usually phantom_object).
682   void map_ideal_node(Node *n, PointsToNode* ptn) {
683     assert(ptn != nullptr, "only existing PointsTo node");
684     _nodes.at_put(n->_idx, ptn);
685   }
686 
687   void add_to_congraph_unsafe_access(Node* n, uint opcode, Unique_Node_List* delayed_worklist);
688   bool add_final_edges_unsafe_access(Node* n, uint opcode);
689 


690 #ifndef PRODUCT
691   static int _no_escape_counter;
692   static int _arg_escape_counter;
693   static int _global_escape_counter;
694   void dump(GrowableArray<PointsToNode*>& ptnodes_worklist);
695   static void print_statistics();
696   void escape_state_statistics(GrowableArray<JavaObjectNode*>& java_objects_worklist);
697 #endif
698 };
699 
700 inline PointsToNode::PointsToNode(ConnectionGraph *CG, Node* n, EscapeState es, NodeType type):
701   _edges(CG->_compile->comp_arena(), 2, 0, nullptr),
702   _uses (CG->_compile->comp_arena(), 2, 0, nullptr),
703   _type((u1)type),
704   _flags(ScalarReplaceable),
705   _escape((u1)es),
706   _fields_escape((u1)es),
707   _node(n),
708   _idx(n->_idx),
709   _pidx(CG->next_pidx()) {

355 private:
356   // Address of an element in _nodes.  Used when the element is to be modified
357   PointsToNode* ptnode_adr(int idx) const {
358     // There should be no new ideal nodes during ConnectionGraph build,
359     // growableArray::at() will throw assert otherwise.
360     return _nodes.at(idx);
361   }
362   uint nodes_size() const { return _nodes.length(); }
363 
364   uint next_pidx() { return _next_pidx++; }
365 
366   // Add nodes to ConnectionGraph.
367   void add_local_var(Node* n, PointsToNode::EscapeState es);
368   PointsToNode* add_java_object(Node* n, PointsToNode::EscapeState es);
369   void add_field(Node* n, PointsToNode::EscapeState es, int offset);
370   void add_arraycopy(Node* n, PointsToNode::EscapeState es, PointsToNode* src, PointsToNode* dst);
371 
372   // Compute the escape state for arguments to a call.
373   void process_call_arguments(CallNode *call);
374 
375   bool returns_an_argument(CallNode* call);
376 
377   // Add PointsToNode node corresponding to a call
378   void add_call_node(CallNode* call);
379 
380   // Create PointsToNode node and add it to Connection Graph.
381   void add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist);
382 
383   // Add final simple edges to graph.
384   void add_final_edges(Node *n);
385 
386   // Finish Graph construction.
387   bool complete_connection_graph(GrowableArray<PointsToNode*>&   ptnodes_worklist,
388                                  GrowableArray<JavaObjectNode*>& non_escaped_worklist,
389                                  GrowableArray<JavaObjectNode*>& java_objects_worklist,
390                                  GrowableArray<FieldNode*>&      oop_fields_worklist);
391 
392 #ifdef ASSERT
393   void verify_connection_graph(GrowableArray<PointsToNode*>&   ptnodes_worklist,
394                                GrowableArray<JavaObjectNode*>& non_escaped_worklist,
395                                GrowableArray<JavaObjectNode*>& java_objects_worklist,
396                                GrowableArray<Node*>& addp_worklist);

470   }
471 
472   // Propagate GlobalEscape and ArgEscape escape states to all nodes
473   // and check that we still have non-escaping java objects.
474   bool find_non_escaped_objects(GrowableArray<PointsToNode*>& ptnodes_worklist,
475                                 GrowableArray<JavaObjectNode*>& non_escaped_worklist,
476                                 bool print_method = true);
477 
478   // Adjust scalar_replaceable state after Connection Graph is built.
479   void adjust_scalar_replaceable_state(JavaObjectNode* jobj, Unique_Node_List &reducible_merges);
480 
481   // Reevaluate Phis reducible status after 'obj' became NSR.
482   void revisit_reducible_phi_status(JavaObjectNode* jobj, Unique_Node_List& reducible_merges);
483 
484   // Propagate NSR (Not scalar replaceable) state.
485   void find_scalar_replaceable_allocs(GrowableArray<JavaObjectNode*>& jobj_worklist, Unique_Node_List &reducible_merges);
486 
487   // Optimize ideal graph.
488   void optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklist,
489                             GrowableArray<MemBarStoreStoreNode*>& storestore_worklist);
490   // Expand flat accesses to accesses to each component if the object does not escape
491   void optimize_flat_accesses(GrowableArray<SafePointNode*>& sfn_worklist);
492   // Optimize objects compare.
493   const TypeInt* optimize_ptr_compare(Node* left, Node* right);
494 
495   // Returns unique corresponding java object or null.
496   JavaObjectNode* unique_java_object(Node *n) const;
497 
498   // Add an edge of the specified type pointing to the specified target.
499   bool add_edge(PointsToNode* from, PointsToNode* to) {
500     assert(!from->is_Field() || from->as_Field()->is_oop(), "sanity");
501 
502     if (to == phantom_obj) {
503       if (from->has_unknown_ptr()) {
504         return false; // already points to phantom_obj
505       }
506       from->set_has_unknown_ptr();
507     }
508 
509     bool is_new = from->add_edge(to);
510     assert(to != phantom_obj || is_new, "sanity");
511     if (is_new) { // New edge?

645 #endif
646 
647 public:
648   ConnectionGraph(Compile *C, PhaseIterGVN *igvn, int iteration);
649 
650   // Verify that SafePointScalarMerge nodes are correctly connected
651   static void verify_ram_nodes(Compile* C, Node* root);
652 
653   // Check for non-escaping candidates
654   static bool has_candidates(Compile *C);
655 
656   // Perform escape analysis
657   static void do_analysis(Compile *C, PhaseIterGVN *igvn);
658 
659   bool not_global_escape(Node *n);
660 
661   bool can_eliminate_lock(AbstractLockNode* alock);
662 
663   // To be used by, e.g., BarrierSetC2 impls
664   Node* get_addp_base(Node* addp);
665   DEBUG_ONLY(static bool is_load_array_klass_related(const Node* uncast_base));
666 
667   // Utility function for nodes that load an object
668   void add_objload_to_connection_graph(Node* n, Unique_Node_List* delayed_worklist);
669 
670   void add_proj(Node* n, Unique_Node_List* delayed_worklist);
671 
672   // Add LocalVar node and edge if possible
673   void add_local_var_and_edge(Node* n, PointsToNode::EscapeState es, Node* to,
674                               Unique_Node_List *delayed_worklist) {
675     PointsToNode* ptn = ptnode_adr(to->_idx);
676     if (delayed_worklist != nullptr) { // First iteration of CG construction
677       add_local_var(n, es);
678       if (ptn == nullptr) {
679         delayed_worklist->push(n);
680         return; // Process it later.
681       }
682     } else {
683       assert(ptn != nullptr, "node should be registered");
684     }
685     add_edge(ptnode_adr(n->_idx), ptn);
686   }
687 
688   // Map ideal node to existing PointsTo node (usually phantom_object).
689   void map_ideal_node(Node *n, PointsToNode* ptn) {
690     assert(ptn != nullptr, "only existing PointsTo node");
691     _nodes.at_put(n->_idx, ptn);
692   }
693 
694   void add_to_congraph_unsafe_access(Node* n, uint opcode, Unique_Node_List* delayed_worklist);
695   bool add_final_edges_unsafe_access(Node* n, uint opcode);
696 
697   bool compatible_return(CallJavaNode* call, uint k);
698 
699 #ifndef PRODUCT
700   static int _no_escape_counter;
701   static int _arg_escape_counter;
702   static int _global_escape_counter;
703   void dump(GrowableArray<PointsToNode*>& ptnodes_worklist);
704   static void print_statistics();
705   void escape_state_statistics(GrowableArray<JavaObjectNode*>& java_objects_worklist);
706 #endif
707 };
708 
709 inline PointsToNode::PointsToNode(ConnectionGraph *CG, Node* n, EscapeState es, NodeType type):
710   _edges(CG->_compile->comp_arena(), 2, 0, nullptr),
711   _uses (CG->_compile->comp_arena(), 2, 0, nullptr),
712   _type((u1)type),
713   _flags(ScalarReplaceable),
714   _escape((u1)es),
715   _fields_escape((u1)es),
716   _node(n),
717   _idx(n->_idx),
718   _pidx(CG->next_pidx()) {
< prev index next >