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()) {
|