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

543   bool has_oop_node_outs(Node* n);
544   static Node* find_second_addp(Node* addp, Node* n);
545   // offset of a field reference
546   int address_offset(Node* adr, PhaseValues* phase);
547 
548   bool is_captured_store_address(Node* addp);
549 
550   // Propagate unique types created for non-escaped allocated objects through the graph
551   void split_unique_types(GrowableArray<Node *>  &alloc_worklist,
552                           GrowableArray<ArrayCopyNode*> &arraycopy_worklist,
553                           GrowableArray<MergeMemNode*> &mergemem_worklist,
554                           Unique_Node_List &reducible_merges);
555 
556   // Helper methods for unique types split.
557   bool split_AddP(Node *addp, Node *base);
558 
559   PhiNode* create_split_phi(PhiNode* orig_phi, int alias_idx, Unique_Node_List& orig_phi_worklist, bool& new_created);
560   PhiNode* split_memory_phi(PhiNode* orig_phi, int alias_idx, Unique_Node_List& orig_phi_worklist, uint rec_depth);
561 
562   void  move_inst_mem(Node* n, Unique_Node_List& orig_phis);

563   Node* find_inst_mem(Node* mem, int alias_idx, Unique_Node_List& orig_phi_worklist, uint rec_depth = 0);
564   Node* step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop);
565 
566   Node_Array _node_map; // used for bookkeeping during type splitting
567                         // Used for the following purposes:
568                         // Memory Phi    - most recent unique Phi split out
569                         //                 from this Phi
570                         // MemNode       - new memory input for this node
571                         // CheckCastPP   - allocation that this is a cast of
572                         // allocation    - CheckCastPP of the allocation
573                         // NarrowMem     - newly created projection (type includes instance_id) from projection created
574                         //                 before EA
575 
576   // manage entries in _node_map
577 
578   void  set_map(Node* from, Node* to)  {
579     ideal_nodes.push(from);
580     _node_map.map(from->_idx, to);
581   }
582 

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?

547   bool has_oop_node_outs(Node* n);
548   static Node* find_second_addp(Node* addp, Node* n);
549   // offset of a field reference
550   int address_offset(Node* adr, PhaseValues* phase);
551 
552   bool is_captured_store_address(Node* addp);
553 
554   // Propagate unique types created for non-escaped allocated objects through the graph
555   void split_unique_types(GrowableArray<Node *>  &alloc_worklist,
556                           GrowableArray<ArrayCopyNode*> &arraycopy_worklist,
557                           GrowableArray<MergeMemNode*> &mergemem_worklist,
558                           Unique_Node_List &reducible_merges);
559 
560   // Helper methods for unique types split.
561   bool split_AddP(Node *addp, Node *base);
562 
563   PhiNode* create_split_phi(PhiNode* orig_phi, int alias_idx, Unique_Node_List& orig_phi_worklist, bool& new_created);
564   PhiNode* split_memory_phi(PhiNode* orig_phi, int alias_idx, Unique_Node_List& orig_phi_worklist, uint rec_depth);
565 
566   void  move_inst_mem(Node* n, Unique_Node_List& orig_phis);
567   bool flat_access_aliases_with(Node* flat_access, const TypeOopPtr *toop);
568   Node* find_inst_mem(Node* mem, int alias_idx, Unique_Node_List& orig_phi_worklist, uint rec_depth = 0);
569   Node* step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop);
570 
571   Node_Array _node_map; // used for bookkeeping during type splitting
572                         // Used for the following purposes:
573                         // Memory Phi    - most recent unique Phi split out
574                         //                 from this Phi
575                         // MemNode       - new memory input for this node
576                         // CheckCastPP   - allocation that this is a cast of
577                         // allocation    - CheckCastPP of the allocation
578                         // NarrowMem     - newly created projection (type includes instance_id) from projection created
579                         //                 before EA
580 
581   // manage entries in _node_map
582 
583   void  set_map(Node* from, Node* to)  {
584     ideal_nodes.push(from);
585     _node_map.map(from->_idx, to);
586   }
587 

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