Mercurial > hg > graal-compiler
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 }; |