comparison src/share/vm/opto/escape.hpp @ 4058:59e515ee9354

7059047: EA: can't find initializing store with several CheckCastPP Summary: Split adjust_escape_state() method into two methods to find initializing stores. Reviewed-by: never
author kvn
date Mon, 07 Nov 2011 14:33:57 -0800
parents 3763ca6579b7
children 8c57262447d3
comparison
equal deleted inserted replaced
4057:1feb272af3a7 4058:59e515ee9354
72 // to the static memory. 72 // to the static memory.
73 // 73 //
74 // C2 does not have local variables. However for the purposes of constructing 74 // C2 does not have local variables. However for the purposes of constructing
75 // the connection graph, the following IR nodes are treated as local variables: 75 // the connection graph, the following IR nodes are treated as local variables:
76 // Phi (pointer values) 76 // Phi (pointer values)
77 // LoadP 77 // LoadP, LoadN
78 // Proj#5 (value returned from callnodes including allocations) 78 // Proj#5 (value returned from callnodes including allocations)
79 // CheckCastPP, CastPP 79 // CheckCastPP, CastPP
80 // 80 //
81 // The LoadP, Proj and CheckCastPP behave like variables assigned to only once. 81 // The LoadP, Proj and CheckCastPP behave like variables assigned to only once.
82 // Only a Phi can have multiple assignments. Each input to a Phi is treated 82 // Only a Phi can have multiple assignments. Each input to a Phi is treated
83 // as an assignment to it. 83 // as an assignment to it.
84 // 84 //
85 // The following node types are JavaObject: 85 // The following node types are JavaObject:
86 // 86 //
87 // top() 87 // phantom_object (general globally escaped object)
88 // Allocate 88 // Allocate
89 // AllocateArray 89 // AllocateArray
90 // Parm (for incoming arguments) 90 // Parm (for incoming arguments)
91 // CastX2P ("unsafe" operations) 91 // CastX2P ("unsafe" operations)
92 // CreateEx 92 // CreateEx
93 // ConP 93 // ConP
94 // LoadKlass 94 // LoadKlass
95 // ThreadLocal 95 // ThreadLocal
96 // CallStaticJava (which returns Object)
96 // 97 //
97 // AddP nodes are fields. 98 // AddP nodes are fields.
98 // 99 //
99 // After building the graph, a pass is made over the nodes, deleting deferred 100 // After building the graph, a pass is made over the nodes, deleting deferred
100 // nodes and copying the edges from the target of the deferred edge to the 101 // nodes and copying the edges from the target of the deferred edge to the
128 Field = 3 129 Field = 3
129 } NodeType; 130 } NodeType;
130 131
131 typedef enum { 132 typedef enum {
132 UnknownEscape = 0, 133 UnknownEscape = 0,
133 NoEscape = 1, // A scalar replaceable object with unique type. 134 NoEscape = 1, // An object does not escape method or thread and it is
134 ArgEscape = 2, // An object passed as argument or referenced by 135 // not passed to call. It could be replaced with scalar.
135 // argument (and not globally escape during call). 136 ArgEscape = 2, // An object does not escape method or thread but it is
136 GlobalEscape = 3 // An object escapes the method and thread. 137 // passed as argument to call or referenced by argument
138 // and it does not escape during call.
139 GlobalEscape = 3 // An object escapes the method or thread.
137 } EscapeState; 140 } EscapeState;
138 141
139 typedef enum { 142 typedef enum {
140 UnknownEdge = 0, 143 UnknownEdge = 0,
141 PointsToEdge = 1, 144 PointsToEdge = 1,
151 INITIAL_EDGE_COUNT = 4 154 INITIAL_EDGE_COUNT = 4
152 }; 155 };
153 156
154 NodeType _type; 157 NodeType _type;
155 EscapeState _escape; 158 EscapeState _escape;
156 GrowableArray<uint>* _edges; // outgoing edges 159 GrowableArray<uint>* _edges; // outgoing edges
160 Node* _node; // Ideal node corresponding to this PointsTo node.
161 int _offset; // Object fields offsets.
162 bool _scalar_replaceable; // Not escaped object could be replaced with scalar
157 163
158 public: 164 public:
159 Node* _node; // Ideal node corresponding to this PointsTo node.
160 int _offset; // Object fields offsets.
161 bool _scalar_replaceable;// Not escaped object could be replaced with scalar
162 bool _hidden_alias; // This node is an argument to a function.
163 // which may return it creating a hidden alias.
164
165 PointsToNode(): 165 PointsToNode():
166 _type(UnknownType), 166 _type(UnknownType),
167 _escape(UnknownEscape), 167 _escape(UnknownEscape),
168 _edges(NULL), 168 _edges(NULL),
169 _node(NULL), 169 _node(NULL),
170 _offset(-1), 170 _offset(-1),
171 _scalar_replaceable(true), 171 _scalar_replaceable(true) {}
172 _hidden_alias(false) {}
173 172
174 173
175 EscapeState escape_state() const { return _escape; } 174 EscapeState escape_state() const { return _escape; }
176 NodeType node_type() const { return _type;} 175 NodeType node_type() const { return _type;}
177 int offset() { return _offset;} 176 int offset() { return _offset;}
177 bool scalar_replaceable() { return _scalar_replaceable;}
178 178
179 void set_offset(int offs) { _offset = offs;} 179 void set_offset(int offs) { _offset = offs;}
180 void set_escape_state(EscapeState state) { _escape = state; } 180 void set_escape_state(EscapeState state) { _escape = state; }
181 void set_node_type(NodeType ntype) { 181 void set_node_type(NodeType ntype) {
182 assert(_type == UnknownType || _type == ntype, "Can't change node type"); 182 assert(_type == UnknownType || _type == ntype, "Can't change node type");
183 _type = ntype; 183 _type = ntype;
184 } 184 }
185 void set_scalar_replaceable(bool v) { _scalar_replaceable = v; }
185 186
186 // count of outgoing edges 187 // count of outgoing edges
187 uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); } 188 uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); }
188 189
189 // node index of target of outgoing edge "e" 190 // node index of target of outgoing edge "e"
231 232
232 uint _phantom_object; // Index of globally escaping object 233 uint _phantom_object; // Index of globally escaping object
233 // that pointer values loaded from 234 // that pointer values loaded from
234 // a field which has not been set 235 // a field which has not been set
235 // are assumed to point to. 236 // are assumed to point to.
236 uint _oop_null; // ConP(#NULL) 237 uint _oop_null; // ConP(#NULL)->_idx
237 uint _noop_null; // ConN(#NULL) 238 uint _noop_null; // ConN(#NULL)->_idx
238 239
239 Compile * _compile; // Compile object for current compilation 240 Compile * _compile; // Compile object for current compilation
240 PhaseIterGVN * _igvn; // Value numbering 241 PhaseIterGVN * _igvn; // Value numbering
241 242
242 // Address of an element in _nodes. Used when the element is to be modified 243 // Address of an element in _nodes. Used when the element is to be modified
337 } 338 }
338 339
339 // Set the escape state of a node 340 // Set the escape state of a node
340 void set_escape_state(uint ni, PointsToNode::EscapeState es); 341 void set_escape_state(uint ni, PointsToNode::EscapeState es);
341 342
343 // Find fields initializing values for allocations.
344 void find_init_values(Node* n, VectorSet* visited, PhaseTransform* phase);
345
342 // Adjust escape state after Connection Graph is built. 346 // Adjust escape state after Connection Graph is built.
343 void adjust_escape_state(int nidx, PhaseTransform* phase); 347 void adjust_escape_state(Node* n);
348
349 // Propagate escape states to referenced nodes.
350 bool propagate_escape_state(GrowableArray<int>* cg_worklist,
351 GrowableArray<uint>* worklist,
352 PointsToNode::EscapeState esc_state);
344 353
345 // Compute the escape information 354 // Compute the escape information
346 bool compute_escape(); 355 bool compute_escape();
347 356
348 public: 357 public:
354 // Perform escape analysis 363 // Perform escape analysis
355 static void do_analysis(Compile *C, PhaseIterGVN *igvn); 364 static void do_analysis(Compile *C, PhaseIterGVN *igvn);
356 365
357 // escape state of a node 366 // escape state of a node
358 PointsToNode::EscapeState escape_state(Node *n); 367 PointsToNode::EscapeState escape_state(Node *n);
359
360 // other information we have collected
361 bool is_scalar_replaceable(Node *n) {
362 if (_collecting || (n->_idx >= nodes_size()))
363 return false;
364 PointsToNode* ptn = ptnode_adr(n->_idx);
365 return ptn->escape_state() == PointsToNode::NoEscape && ptn->_scalar_replaceable;
366 }
367
368 bool hidden_alias(Node *n) {
369 if (_collecting || (n->_idx >= nodes_size()))
370 return true;
371 PointsToNode* ptn = ptnode_adr(n->_idx);
372 return (ptn->escape_state() != PointsToNode::NoEscape) || ptn->_hidden_alias;
373 }
374 368
375 #ifndef PRODUCT 369 #ifndef PRODUCT
376 void dump(); 370 void dump();
377 #endif 371 #endif
378 }; 372 };