< 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?

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

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


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


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

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