Mercurial > hg > truffle
annotate src/share/vm/ci/bcEscapeAnalyzer.cpp @ 1145:e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking.
Reviewed-by: jmasa
author | ysr |
---|---|
date | Wed, 23 Dec 2009 09:23:54 -0800 |
parents | bd02caa94611 |
children | b4776199210f |
rev | line source |
---|---|
0 | 1 /* |
844 | 2 * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 | |
26 #include "incls/_precompiled.incl" | |
27 #include "incls/_bcEscapeAnalyzer.cpp.incl" | |
28 | |
29 | |
30 #ifndef PRODUCT | |
31 #define TRACE_BCEA(level, code) \ | |
32 if (EstimateArgEscape && BCEATraceLevel >= level) { \ | |
33 code; \ | |
34 } | |
35 #else | |
36 #define TRACE_BCEA(level, code) | |
37 #endif | |
38 | |
39 // Maintain a map of which aguments a local variable or | |
40 // stack slot may contain. In addition to tracking | |
41 // arguments, it tracks two special values, "allocated" | |
42 // which represents any object allocated in the current | |
43 // method, and "unknown" which is any other object. | |
44 // Up to 30 arguments are handled, with the last one | |
45 // representing summary information for any extra arguments | |
46 class BCEscapeAnalyzer::ArgumentMap { | |
47 uint _bits; | |
48 enum {MAXBIT = 29, | |
49 ALLOCATED = 1, | |
50 UNKNOWN = 2}; | |
51 | |
52 uint int_to_bit(uint e) const { | |
53 if (e > MAXBIT) | |
54 e = MAXBIT; | |
55 return (1 << (e + 2)); | |
56 } | |
57 | |
58 public: | |
59 ArgumentMap() { _bits = 0;} | |
60 void set_bits(uint bits) { _bits = bits;} | |
61 uint get_bits() const { return _bits;} | |
62 void clear() { _bits = 0;} | |
63 void set_all() { _bits = ~0u; } | |
64 bool is_empty() const { return _bits == 0; } | |
65 bool contains(uint var) const { return (_bits & int_to_bit(var)) != 0; } | |
66 bool is_singleton(uint var) const { return (_bits == int_to_bit(var)); } | |
67 bool contains_unknown() const { return (_bits & UNKNOWN) != 0; } | |
68 bool contains_allocated() const { return (_bits & ALLOCATED) != 0; } | |
69 bool contains_vars() const { return (_bits & (((1 << MAXBIT) -1) << 2)) != 0; } | |
70 void set(uint var) { _bits = int_to_bit(var); } | |
71 void add(uint var) { _bits |= int_to_bit(var); } | |
72 void add_unknown() { _bits = UNKNOWN; } | |
73 void add_allocated() { _bits = ALLOCATED; } | |
74 void set_union(const ArgumentMap &am) { _bits |= am._bits; } | |
75 void set_intersect(const ArgumentMap &am) { _bits |= am._bits; } | |
76 void set_difference(const ArgumentMap &am) { _bits &= ~am._bits; } | |
77 void operator=(const ArgumentMap &am) { _bits = am._bits; } | |
78 bool operator==(const ArgumentMap &am) { return _bits == am._bits; } | |
79 bool operator!=(const ArgumentMap &am) { return _bits != am._bits; } | |
80 }; | |
81 | |
82 class BCEscapeAnalyzer::StateInfo { | |
83 public: | |
84 ArgumentMap *_vars; | |
85 ArgumentMap *_stack; | |
86 short _stack_height; | |
87 short _max_stack; | |
88 bool _initialized; | |
89 ArgumentMap empty_map; | |
90 | |
91 StateInfo() { | |
92 empty_map.clear(); | |
93 } | |
94 | |
95 ArgumentMap raw_pop() { assert(_stack_height > 0, "stack underflow"); return _stack[--_stack_height]; } | |
96 ArgumentMap apop() { return raw_pop(); } | |
97 void spop() { raw_pop(); } | |
98 void lpop() { spop(); spop(); } | |
99 void raw_push(ArgumentMap i) { assert(_stack_height < _max_stack, "stack overflow"); _stack[_stack_height++] = i; } | |
100 void apush(ArgumentMap i) { raw_push(i); } | |
101 void spush() { raw_push(empty_map); } | |
102 void lpush() { spush(); spush(); } | |
103 | |
104 }; | |
105 | |
106 void BCEscapeAnalyzer::set_returned(ArgumentMap vars) { | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
107 for (int i = 0; i < _arg_size; i++) { |
0 | 108 if (vars.contains(i)) |
109 _arg_returned.set_bit(i); | |
110 } | |
111 _return_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated()); | |
112 _return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars()); | |
113 } | |
114 | |
115 // return true if any element of vars is an argument | |
116 bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) { | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
117 for (int i = 0; i < _arg_size; i++) { |
0 | 118 if (vars.contains(i)) |
119 return true; | |
120 } | |
121 return false; | |
122 } | |
123 | |
124 // return true if any element of vars is an arg_stack argument | |
125 bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){ | |
126 if (_conservative) | |
127 return true; | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
128 for (int i = 0; i < _arg_size; i++) { |
0 | 129 if (vars.contains(i) && _arg_stack.at(i)) |
130 return true; | |
131 } | |
132 return false; | |
133 } | |
134 | |
135 void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) { | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
136 for (int i = 0; i < _arg_size; i++) { |
0 | 137 if (vars.contains(i)) { |
138 bm.clear_bit(i); | |
139 } | |
140 } | |
141 } | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
142 |
0 | 143 void BCEscapeAnalyzer::set_method_escape(ArgumentMap vars) { |
144 clear_bits(vars, _arg_local); | |
145 } | |
146 | |
147 void BCEscapeAnalyzer::set_global_escape(ArgumentMap vars) { | |
148 clear_bits(vars, _arg_local); | |
149 clear_bits(vars, _arg_stack); | |
150 if (vars.contains_allocated()) | |
151 _allocated_escapes = true; | |
152 } | |
153 | |
154 void BCEscapeAnalyzer::set_dirty(ArgumentMap vars) { | |
155 clear_bits(vars, _dirty); | |
156 } | |
157 | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
158 void BCEscapeAnalyzer::set_modified(ArgumentMap vars, int offs, int size) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
159 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
160 for (int i = 0; i < _arg_size; i++) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
161 if (vars.contains(i)) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
162 set_arg_modified(i, offs, size); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
163 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
164 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
165 if (vars.contains_unknown()) |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
166 _unknown_modified = true; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
167 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
168 |
0 | 169 bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) { |
170 for (BCEscapeAnalyzer* scope = this; scope != NULL; scope = scope->_parent) { | |
171 if (scope->method() == callee) { | |
172 return true; | |
173 } | |
174 } | |
175 return false; | |
176 } | |
177 | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
178 bool BCEscapeAnalyzer::is_arg_modified(int arg, int offset, int size_in_bytes) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
179 if (offset == OFFSET_ANY) |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
180 return _arg_modified[arg] != 0; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
181 assert(arg >= 0 && arg < _arg_size, "must be an argument."); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
182 bool modified = false; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
183 int l = offset / HeapWordSize; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
184 int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
185 if (l > ARG_OFFSET_MAX) |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
186 l = ARG_OFFSET_MAX; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
187 if (h > ARG_OFFSET_MAX+1) |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
188 h = ARG_OFFSET_MAX + 1; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
189 for (int i = l; i < h; i++) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
190 modified = modified || (_arg_modified[arg] & (1 << i)) != 0; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
191 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
192 return modified; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
193 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
194 |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
195 void BCEscapeAnalyzer::set_arg_modified(int arg, int offset, int size_in_bytes) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
196 if (offset == OFFSET_ANY) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
197 _arg_modified[arg] = (uint) -1; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
198 return; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
199 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
200 assert(arg >= 0 && arg < _arg_size, "must be an argument."); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
201 int l = offset / HeapWordSize; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
202 int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
203 if (l > ARG_OFFSET_MAX) |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
204 l = ARG_OFFSET_MAX; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
205 if (h > ARG_OFFSET_MAX+1) |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
206 h = ARG_OFFSET_MAX + 1; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
207 for (int i = l; i < h; i++) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
208 _arg_modified[arg] |= (1 << i); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
209 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
210 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
211 |
0 | 212 void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder) { |
213 int i; | |
214 | |
215 // retrieve information about the callee | |
216 ciInstanceKlass* klass = target->holder(); | |
217 ciInstanceKlass* calling_klass = method()->holder(); | |
218 ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder); | |
219 ciInstanceKlass* actual_recv = callee_holder; | |
220 | |
154
09c2ba680204
6700102: c2 assertion "counter_changed,"failed dependencies, but counter didn't change")" with AggressiveOpts
kvn
parents:
78
diff
changeset
|
221 // some methods are obviously bindable without any type checks so |
09c2ba680204
6700102: c2 assertion "counter_changed,"failed dependencies, but counter didn't change")" with AggressiveOpts
kvn
parents:
78
diff
changeset
|
222 // convert them directly to an invokespecial. |
09c2ba680204
6700102: c2 assertion "counter_changed,"failed dependencies, but counter didn't change")" with AggressiveOpts
kvn
parents:
78
diff
changeset
|
223 if (target->is_loaded() && !target->is_abstract() && |
09c2ba680204
6700102: c2 assertion "counter_changed,"failed dependencies, but counter didn't change")" with AggressiveOpts
kvn
parents:
78
diff
changeset
|
224 target->can_be_statically_bound() && code == Bytecodes::_invokevirtual) { |
09c2ba680204
6700102: c2 assertion "counter_changed,"failed dependencies, but counter didn't change")" with AggressiveOpts
kvn
parents:
78
diff
changeset
|
225 code = Bytecodes::_invokespecial; |
09c2ba680204
6700102: c2 assertion "counter_changed,"failed dependencies, but counter didn't change")" with AggressiveOpts
kvn
parents:
78
diff
changeset
|
226 } |
09c2ba680204
6700102: c2 assertion "counter_changed,"failed dependencies, but counter didn't change")" with AggressiveOpts
kvn
parents:
78
diff
changeset
|
227 |
0 | 228 // compute size of arguments |
229 int arg_size = target->arg_size(); | |
230 if (!target->is_loaded() && code == Bytecodes::_invokestatic) { | |
231 arg_size--; | |
232 } | |
233 int arg_base = MAX2(state._stack_height - arg_size, 0); | |
234 | |
235 // direct recursive calls are skipped if they can be bound statically without introducing | |
236 // dependencies and if parameters are passed at the same position as in the current method | |
237 // other calls are skipped if there are no unescaped arguments passed to them | |
238 bool directly_recursive = (method() == target) && | |
239 (code != Bytecodes::_invokevirtual || target->is_final_method() || state._stack[arg_base] .is_empty()); | |
240 | |
241 // check if analysis of callee can safely be skipped | |
242 bool skip_callee = true; | |
243 for (i = state._stack_height - 1; i >= arg_base && skip_callee; i--) { | |
244 ArgumentMap arg = state._stack[i]; | |
245 skip_callee = !is_argument(arg) || !is_arg_stack(arg) || (directly_recursive && arg.is_singleton(i - arg_base)); | |
246 } | |
247 if (skip_callee) { | |
248 TRACE_BCEA(3, tty->print_cr("[EA] skipping method %s::%s", holder->name()->as_utf8(), target->name()->as_utf8())); | |
249 for (i = 0; i < arg_size; i++) { | |
250 set_method_escape(state.raw_pop()); | |
251 } | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
252 _unknown_modified = true; // assume the worst since we don't analyze the called method |
0 | 253 return; |
254 } | |
255 | |
256 // determine actual method (use CHA if necessary) | |
257 ciMethod* inline_target = NULL; | |
258 if (target->is_loaded() && klass->is_loaded() | |
259 && (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized()) | |
260 && target->will_link(klass, callee_holder, code)) { | |
261 if (code == Bytecodes::_invokestatic | |
262 || code == Bytecodes::_invokespecial | |
263 || code == Bytecodes::_invokevirtual && target->is_final_method()) { | |
264 inline_target = target; | |
265 } else { | |
266 inline_target = target->find_monomorphic_target(calling_klass, callee_holder, actual_recv); | |
267 } | |
268 } | |
269 | |
270 if (inline_target != NULL && !is_recursive_call(inline_target)) { | |
271 // analyze callee | |
272 BCEscapeAnalyzer analyzer(inline_target, this); | |
273 | |
274 // adjust escape state of actual parameters | |
275 bool must_record_dependencies = false; | |
276 for (i = arg_size - 1; i >= 0; i--) { | |
277 ArgumentMap arg = state.raw_pop(); | |
278 if (!is_argument(arg)) | |
279 continue; | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
280 for (int j = 0; j < _arg_size; j++) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
281 if (arg.contains(j)) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
282 _arg_modified[j] |= analyzer._arg_modified[i]; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
283 } |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
284 } |
0 | 285 if (!is_arg_stack(arg)) { |
286 // arguments have already been recognized as escaping | |
287 } else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) { | |
288 set_method_escape(arg); | |
289 must_record_dependencies = true; | |
290 } else { | |
291 set_global_escape(arg); | |
292 } | |
293 } | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
294 _unknown_modified = _unknown_modified || analyzer.has_non_arg_side_affects(); |
0 | 295 |
296 // record dependencies if at least one parameter retained stack-allocatable | |
297 if (must_record_dependencies) { | |
298 if (code == Bytecodes::_invokeinterface || code == Bytecodes::_invokevirtual && !target->is_final_method()) { | |
299 _dependencies.append(actual_recv); | |
300 _dependencies.append(inline_target); | |
301 } | |
302 _dependencies.appendAll(analyzer.dependencies()); | |
303 } | |
304 } else { | |
305 TRACE_BCEA(1, tty->print_cr("[EA] virtual method %s is not monomorphic.", | |
306 target->name()->as_utf8())); | |
307 // conservatively mark all actual parameters as escaping globally | |
308 for (i = 0; i < arg_size; i++) { | |
309 ArgumentMap arg = state.raw_pop(); | |
310 if (!is_argument(arg)) | |
311 continue; | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
312 set_modified(arg, OFFSET_ANY, type2size[T_INT]*HeapWordSize); |
0 | 313 set_global_escape(arg); |
314 } | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
315 _unknown_modified = true; // assume the worst since we don't know the called method |
0 | 316 } |
317 } | |
318 | |
319 bool BCEscapeAnalyzer::contains(uint arg_set1, uint arg_set2) { | |
320 return ((~arg_set1) | arg_set2) == 0; | |
321 } | |
322 | |
323 | |
324 void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, GrowableArray<ciBlock *> &successors) { | |
325 | |
326 blk->set_processed(); | |
327 ciBytecodeStream s(method()); | |
328 int limit_bci = blk->limit_bci(); | |
329 bool fall_through = false; | |
330 ArgumentMap allocated_obj; | |
331 allocated_obj.add_allocated(); | |
332 ArgumentMap unknown_obj; | |
333 unknown_obj.add_unknown(); | |
334 ArgumentMap empty_map; | |
335 | |
336 s.reset_to_bci(blk->start_bci()); | |
337 while (s.next() != ciBytecodeStream::EOBC() && s.cur_bci() < limit_bci) { | |
338 fall_through = true; | |
339 switch (s.cur_bc()) { | |
340 case Bytecodes::_nop: | |
341 break; | |
342 case Bytecodes::_aconst_null: | |
343 state.apush(empty_map); | |
344 break; | |
345 case Bytecodes::_iconst_m1: | |
346 case Bytecodes::_iconst_0: | |
347 case Bytecodes::_iconst_1: | |
348 case Bytecodes::_iconst_2: | |
349 case Bytecodes::_iconst_3: | |
350 case Bytecodes::_iconst_4: | |
351 case Bytecodes::_iconst_5: | |
352 case Bytecodes::_fconst_0: | |
353 case Bytecodes::_fconst_1: | |
354 case Bytecodes::_fconst_2: | |
355 case Bytecodes::_bipush: | |
356 case Bytecodes::_sipush: | |
357 state.spush(); | |
358 break; | |
359 case Bytecodes::_lconst_0: | |
360 case Bytecodes::_lconst_1: | |
361 case Bytecodes::_dconst_0: | |
362 case Bytecodes::_dconst_1: | |
363 state.lpush(); | |
364 break; | |
365 case Bytecodes::_ldc: | |
366 case Bytecodes::_ldc_w: | |
367 case Bytecodes::_ldc2_w: | |
368 if (type2size[s.get_constant().basic_type()] == 1) { | |
369 state.spush(); | |
370 } else { | |
371 state.lpush(); | |
372 } | |
373 break; | |
374 case Bytecodes::_aload: | |
375 state.apush(state._vars[s.get_index()]); | |
376 break; | |
377 case Bytecodes::_iload: | |
378 case Bytecodes::_fload: | |
379 case Bytecodes::_iload_0: | |
380 case Bytecodes::_iload_1: | |
381 case Bytecodes::_iload_2: | |
382 case Bytecodes::_iload_3: | |
383 case Bytecodes::_fload_0: | |
384 case Bytecodes::_fload_1: | |
385 case Bytecodes::_fload_2: | |
386 case Bytecodes::_fload_3: | |
387 state.spush(); | |
388 break; | |
389 case Bytecodes::_lload: | |
390 case Bytecodes::_dload: | |
391 case Bytecodes::_lload_0: | |
392 case Bytecodes::_lload_1: | |
393 case Bytecodes::_lload_2: | |
394 case Bytecodes::_lload_3: | |
395 case Bytecodes::_dload_0: | |
396 case Bytecodes::_dload_1: | |
397 case Bytecodes::_dload_2: | |
398 case Bytecodes::_dload_3: | |
399 state.lpush(); | |
400 break; | |
401 case Bytecodes::_aload_0: | |
402 state.apush(state._vars[0]); | |
403 break; | |
404 case Bytecodes::_aload_1: | |
405 state.apush(state._vars[1]); | |
406 break; | |
407 case Bytecodes::_aload_2: | |
408 state.apush(state._vars[2]); | |
409 break; | |
410 case Bytecodes::_aload_3: | |
411 state.apush(state._vars[3]); | |
412 break; | |
413 case Bytecodes::_iaload: | |
414 case Bytecodes::_faload: | |
415 case Bytecodes::_baload: | |
416 case Bytecodes::_caload: | |
417 case Bytecodes::_saload: | |
418 state.spop(); | |
419 set_method_escape(state.apop()); | |
420 state.spush(); | |
421 break; | |
422 case Bytecodes::_laload: | |
423 case Bytecodes::_daload: | |
424 state.spop(); | |
425 set_method_escape(state.apop()); | |
426 state.lpush(); | |
427 break; | |
428 case Bytecodes::_aaload: | |
429 { state.spop(); | |
430 ArgumentMap array = state.apop(); | |
431 set_method_escape(array); | |
432 state.apush(unknown_obj); | |
433 set_dirty(array); | |
434 } | |
435 break; | |
436 case Bytecodes::_istore: | |
437 case Bytecodes::_fstore: | |
438 case Bytecodes::_istore_0: | |
439 case Bytecodes::_istore_1: | |
440 case Bytecodes::_istore_2: | |
441 case Bytecodes::_istore_3: | |
442 case Bytecodes::_fstore_0: | |
443 case Bytecodes::_fstore_1: | |
444 case Bytecodes::_fstore_2: | |
445 case Bytecodes::_fstore_3: | |
446 state.spop(); | |
447 break; | |
448 case Bytecodes::_lstore: | |
449 case Bytecodes::_dstore: | |
450 case Bytecodes::_lstore_0: | |
451 case Bytecodes::_lstore_1: | |
452 case Bytecodes::_lstore_2: | |
453 case Bytecodes::_lstore_3: | |
454 case Bytecodes::_dstore_0: | |
455 case Bytecodes::_dstore_1: | |
456 case Bytecodes::_dstore_2: | |
457 case Bytecodes::_dstore_3: | |
458 state.lpop(); | |
459 break; | |
460 case Bytecodes::_astore: | |
461 state._vars[s.get_index()] = state.apop(); | |
462 break; | |
463 case Bytecodes::_astore_0: | |
464 state._vars[0] = state.apop(); | |
465 break; | |
466 case Bytecodes::_astore_1: | |
467 state._vars[1] = state.apop(); | |
468 break; | |
469 case Bytecodes::_astore_2: | |
470 state._vars[2] = state.apop(); | |
471 break; | |
472 case Bytecodes::_astore_3: | |
473 state._vars[3] = state.apop(); | |
474 break; | |
475 case Bytecodes::_iastore: | |
476 case Bytecodes::_fastore: | |
477 case Bytecodes::_bastore: | |
478 case Bytecodes::_castore: | |
479 case Bytecodes::_sastore: | |
480 { | |
481 state.spop(); | |
482 state.spop(); | |
483 ArgumentMap arr = state.apop(); | |
484 set_method_escape(arr); | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
485 set_modified(arr, OFFSET_ANY, type2size[T_INT]*HeapWordSize); |
0 | 486 break; |
487 } | |
488 case Bytecodes::_lastore: | |
489 case Bytecodes::_dastore: | |
490 { | |
491 state.lpop(); | |
492 state.spop(); | |
493 ArgumentMap arr = state.apop(); | |
494 set_method_escape(arr); | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
495 set_modified(arr, OFFSET_ANY, type2size[T_LONG]*HeapWordSize); |
0 | 496 break; |
497 } | |
498 case Bytecodes::_aastore: | |
499 { | |
500 set_global_escape(state.apop()); | |
501 state.spop(); | |
502 ArgumentMap arr = state.apop(); | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
503 set_modified(arr, OFFSET_ANY, type2size[T_OBJECT]*HeapWordSize); |
0 | 504 break; |
505 } | |
506 case Bytecodes::_pop: | |
507 state.raw_pop(); | |
508 break; | |
509 case Bytecodes::_pop2: | |
510 state.raw_pop(); | |
511 state.raw_pop(); | |
512 break; | |
513 case Bytecodes::_dup: | |
514 { ArgumentMap w1 = state.raw_pop(); | |
515 state.raw_push(w1); | |
516 state.raw_push(w1); | |
517 } | |
518 break; | |
519 case Bytecodes::_dup_x1: | |
520 { ArgumentMap w1 = state.raw_pop(); | |
521 ArgumentMap w2 = state.raw_pop(); | |
522 state.raw_push(w1); | |
523 state.raw_push(w2); | |
524 state.raw_push(w1); | |
525 } | |
526 break; | |
527 case Bytecodes::_dup_x2: | |
528 { ArgumentMap w1 = state.raw_pop(); | |
529 ArgumentMap w2 = state.raw_pop(); | |
530 ArgumentMap w3 = state.raw_pop(); | |
531 state.raw_push(w1); | |
532 state.raw_push(w3); | |
533 state.raw_push(w2); | |
534 state.raw_push(w1); | |
535 } | |
536 break; | |
537 case Bytecodes::_dup2: | |
538 { ArgumentMap w1 = state.raw_pop(); | |
539 ArgumentMap w2 = state.raw_pop(); | |
540 state.raw_push(w2); | |
541 state.raw_push(w1); | |
542 state.raw_push(w2); | |
543 state.raw_push(w1); | |
544 } | |
545 break; | |
546 case Bytecodes::_dup2_x1: | |
547 { ArgumentMap w1 = state.raw_pop(); | |
548 ArgumentMap w2 = state.raw_pop(); | |
549 ArgumentMap w3 = state.raw_pop(); | |
550 state.raw_push(w2); | |
551 state.raw_push(w1); | |
552 state.raw_push(w3); | |
553 state.raw_push(w2); | |
554 state.raw_push(w1); | |
555 } | |
556 break; | |
557 case Bytecodes::_dup2_x2: | |
558 { ArgumentMap w1 = state.raw_pop(); | |
559 ArgumentMap w2 = state.raw_pop(); | |
560 ArgumentMap w3 = state.raw_pop(); | |
561 ArgumentMap w4 = state.raw_pop(); | |
562 state.raw_push(w2); | |
563 state.raw_push(w1); | |
564 state.raw_push(w4); | |
565 state.raw_push(w3); | |
566 state.raw_push(w2); | |
567 state.raw_push(w1); | |
568 } | |
569 break; | |
570 case Bytecodes::_swap: | |
571 { ArgumentMap w1 = state.raw_pop(); | |
572 ArgumentMap w2 = state.raw_pop(); | |
573 state.raw_push(w1); | |
574 state.raw_push(w2); | |
575 } | |
576 break; | |
577 case Bytecodes::_iadd: | |
578 case Bytecodes::_fadd: | |
579 case Bytecodes::_isub: | |
580 case Bytecodes::_fsub: | |
581 case Bytecodes::_imul: | |
582 case Bytecodes::_fmul: | |
583 case Bytecodes::_idiv: | |
584 case Bytecodes::_fdiv: | |
585 case Bytecodes::_irem: | |
586 case Bytecodes::_frem: | |
587 case Bytecodes::_iand: | |
588 case Bytecodes::_ior: | |
589 case Bytecodes::_ixor: | |
590 state.spop(); | |
591 state.spop(); | |
592 state.spush(); | |
593 break; | |
594 case Bytecodes::_ladd: | |
595 case Bytecodes::_dadd: | |
596 case Bytecodes::_lsub: | |
597 case Bytecodes::_dsub: | |
598 case Bytecodes::_lmul: | |
599 case Bytecodes::_dmul: | |
600 case Bytecodes::_ldiv: | |
601 case Bytecodes::_ddiv: | |
602 case Bytecodes::_lrem: | |
603 case Bytecodes::_drem: | |
604 case Bytecodes::_land: | |
605 case Bytecodes::_lor: | |
606 case Bytecodes::_lxor: | |
607 state.lpop(); | |
608 state.lpop(); | |
609 state.lpush(); | |
610 break; | |
611 case Bytecodes::_ishl: | |
612 case Bytecodes::_ishr: | |
613 case Bytecodes::_iushr: | |
614 state.spop(); | |
615 state.spop(); | |
616 state.spush(); | |
617 break; | |
618 case Bytecodes::_lshl: | |
619 case Bytecodes::_lshr: | |
620 case Bytecodes::_lushr: | |
621 state.spop(); | |
622 state.lpop(); | |
623 state.lpush(); | |
624 break; | |
625 case Bytecodes::_ineg: | |
626 case Bytecodes::_fneg: | |
627 state.spop(); | |
628 state.spush(); | |
629 break; | |
630 case Bytecodes::_lneg: | |
631 case Bytecodes::_dneg: | |
632 state.lpop(); | |
633 state.lpush(); | |
634 break; | |
635 case Bytecodes::_iinc: | |
636 break; | |
637 case Bytecodes::_i2l: | |
638 case Bytecodes::_i2d: | |
639 case Bytecodes::_f2l: | |
640 case Bytecodes::_f2d: | |
641 state.spop(); | |
642 state.lpush(); | |
643 break; | |
644 case Bytecodes::_i2f: | |
645 case Bytecodes::_f2i: | |
646 state.spop(); | |
647 state.spush(); | |
648 break; | |
649 case Bytecodes::_l2i: | |
650 case Bytecodes::_l2f: | |
651 case Bytecodes::_d2i: | |
652 case Bytecodes::_d2f: | |
653 state.lpop(); | |
654 state.spush(); | |
655 break; | |
656 case Bytecodes::_l2d: | |
657 case Bytecodes::_d2l: | |
658 state.lpop(); | |
659 state.lpush(); | |
660 break; | |
661 case Bytecodes::_i2b: | |
662 case Bytecodes::_i2c: | |
663 case Bytecodes::_i2s: | |
664 state.spop(); | |
665 state.spush(); | |
666 break; | |
667 case Bytecodes::_lcmp: | |
668 case Bytecodes::_dcmpl: | |
669 case Bytecodes::_dcmpg: | |
670 state.lpop(); | |
671 state.lpop(); | |
672 state.spush(); | |
673 break; | |
674 case Bytecodes::_fcmpl: | |
675 case Bytecodes::_fcmpg: | |
676 state.spop(); | |
677 state.spop(); | |
678 state.spush(); | |
679 break; | |
680 case Bytecodes::_ifeq: | |
681 case Bytecodes::_ifne: | |
682 case Bytecodes::_iflt: | |
683 case Bytecodes::_ifge: | |
684 case Bytecodes::_ifgt: | |
685 case Bytecodes::_ifle: | |
686 { | |
687 state.spop(); | |
688 int dest_bci = s.get_dest(); | |
689 assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); | |
690 assert(s.next_bci() == limit_bci, "branch must end block"); | |
691 successors.push(_methodBlocks->block_containing(dest_bci)); | |
692 break; | |
693 } | |
694 case Bytecodes::_if_icmpeq: | |
695 case Bytecodes::_if_icmpne: | |
696 case Bytecodes::_if_icmplt: | |
697 case Bytecodes::_if_icmpge: | |
698 case Bytecodes::_if_icmpgt: | |
699 case Bytecodes::_if_icmple: | |
700 { | |
701 state.spop(); | |
702 state.spop(); | |
703 int dest_bci = s.get_dest(); | |
704 assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); | |
705 assert(s.next_bci() == limit_bci, "branch must end block"); | |
706 successors.push(_methodBlocks->block_containing(dest_bci)); | |
707 break; | |
708 } | |
709 case Bytecodes::_if_acmpeq: | |
710 case Bytecodes::_if_acmpne: | |
711 { | |
712 set_method_escape(state.apop()); | |
713 set_method_escape(state.apop()); | |
714 int dest_bci = s.get_dest(); | |
715 assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); | |
716 assert(s.next_bci() == limit_bci, "branch must end block"); | |
717 successors.push(_methodBlocks->block_containing(dest_bci)); | |
718 break; | |
719 } | |
720 case Bytecodes::_goto: | |
721 { | |
722 int dest_bci = s.get_dest(); | |
723 assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); | |
724 assert(s.next_bci() == limit_bci, "branch must end block"); | |
725 successors.push(_methodBlocks->block_containing(dest_bci)); | |
726 fall_through = false; | |
727 break; | |
728 } | |
729 case Bytecodes::_jsr: | |
730 { | |
731 int dest_bci = s.get_dest(); | |
732 assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); | |
733 assert(s.next_bci() == limit_bci, "branch must end block"); | |
734 state.apush(empty_map); | |
735 successors.push(_methodBlocks->block_containing(dest_bci)); | |
736 fall_through = false; | |
737 break; | |
738 } | |
739 case Bytecodes::_ret: | |
740 // we don't track the destination of a "ret" instruction | |
741 assert(s.next_bci() == limit_bci, "branch must end block"); | |
742 fall_through = false; | |
743 break; | |
744 case Bytecodes::_return: | |
745 assert(s.next_bci() == limit_bci, "return must end block"); | |
746 fall_through = false; | |
747 break; | |
748 case Bytecodes::_tableswitch: | |
749 { | |
750 state.spop(); | |
751 Bytecode_tableswitch* switch_ = Bytecode_tableswitch_at(s.cur_bcp()); | |
752 int len = switch_->length(); | |
753 int dest_bci; | |
754 for (int i = 0; i < len; i++) { | |
755 dest_bci = s.cur_bci() + switch_->dest_offset_at(i); | |
756 assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); | |
757 successors.push(_methodBlocks->block_containing(dest_bci)); | |
758 } | |
759 dest_bci = s.cur_bci() + switch_->default_offset(); | |
760 assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); | |
761 successors.push(_methodBlocks->block_containing(dest_bci)); | |
762 assert(s.next_bci() == limit_bci, "branch must end block"); | |
763 fall_through = false; | |
764 break; | |
765 } | |
766 case Bytecodes::_lookupswitch: | |
767 { | |
768 state.spop(); | |
769 Bytecode_lookupswitch* switch_ = Bytecode_lookupswitch_at(s.cur_bcp()); | |
770 int len = switch_->number_of_pairs(); | |
771 int dest_bci; | |
772 for (int i = 0; i < len; i++) { | |
773 dest_bci = s.cur_bci() + switch_->pair_at(i)->offset(); | |
774 assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); | |
775 successors.push(_methodBlocks->block_containing(dest_bci)); | |
776 } | |
777 dest_bci = s.cur_bci() + switch_->default_offset(); | |
778 assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); | |
779 successors.push(_methodBlocks->block_containing(dest_bci)); | |
780 fall_through = false; | |
781 break; | |
782 } | |
783 case Bytecodes::_ireturn: | |
784 case Bytecodes::_freturn: | |
785 state.spop(); | |
786 fall_through = false; | |
787 break; | |
788 case Bytecodes::_lreturn: | |
789 case Bytecodes::_dreturn: | |
790 state.lpop(); | |
791 fall_through = false; | |
792 break; | |
793 case Bytecodes::_areturn: | |
794 set_returned(state.apop()); | |
795 fall_through = false; | |
796 break; | |
797 case Bytecodes::_getstatic: | |
798 case Bytecodes::_getfield: | |
799 { bool will_link; | |
800 ciField* field = s.get_field(will_link); | |
801 BasicType field_type = field->type()->basic_type(); | |
802 if (s.cur_bc() != Bytecodes::_getstatic) { | |
803 set_method_escape(state.apop()); | |
804 } | |
805 if (field_type == T_OBJECT || field_type == T_ARRAY) { | |
806 state.apush(unknown_obj); | |
807 } else if (type2size[field_type] == 1) { | |
808 state.spush(); | |
809 } else { | |
810 state.lpush(); | |
811 } | |
812 } | |
813 break; | |
814 case Bytecodes::_putstatic: | |
815 case Bytecodes::_putfield: | |
816 { bool will_link; | |
817 ciField* field = s.get_field(will_link); | |
818 BasicType field_type = field->type()->basic_type(); | |
819 if (field_type == T_OBJECT || field_type == T_ARRAY) { | |
820 set_global_escape(state.apop()); | |
821 } else if (type2size[field_type] == 1) { | |
822 state.spop(); | |
823 } else { | |
824 state.lpop(); | |
825 } | |
826 if (s.cur_bc() != Bytecodes::_putstatic) { | |
827 ArgumentMap p = state.apop(); | |
828 set_method_escape(p); | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
829 set_modified(p, will_link ? field->offset() : OFFSET_ANY, type2size[field_type]*HeapWordSize); |
0 | 830 } |
831 } | |
832 break; | |
833 case Bytecodes::_invokevirtual: | |
834 case Bytecodes::_invokespecial: | |
835 case Bytecodes::_invokestatic: | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
196
diff
changeset
|
836 case Bytecodes::_invokedynamic: |
0 | 837 case Bytecodes::_invokeinterface: |
838 { bool will_link; | |
839 ciMethod* target = s.get_method(will_link); | |
840 ciKlass* holder = s.get_declared_method_holder(); | |
841 invoke(state, s.cur_bc(), target, holder); | |
842 ciType* return_type = target->return_type(); | |
843 if (!return_type->is_primitive_type()) { | |
844 state.apush(unknown_obj); | |
845 } else if (return_type->is_one_word()) { | |
846 state.spush(); | |
847 } else if (return_type->is_two_word()) { | |
848 state.lpush(); | |
849 } | |
850 } | |
851 break; | |
852 case Bytecodes::_new: | |
853 state.apush(allocated_obj); | |
854 break; | |
855 case Bytecodes::_newarray: | |
856 case Bytecodes::_anewarray: | |
857 state.spop(); | |
858 state.apush(allocated_obj); | |
859 break; | |
860 case Bytecodes::_multianewarray: | |
861 { int i = s.cur_bcp()[3]; | |
862 while (i-- > 0) state.spop(); | |
863 state.apush(allocated_obj); | |
864 } | |
865 break; | |
866 case Bytecodes::_arraylength: | |
867 set_method_escape(state.apop()); | |
868 state.spush(); | |
869 break; | |
870 case Bytecodes::_athrow: | |
871 set_global_escape(state.apop()); | |
872 fall_through = false; | |
873 break; | |
874 case Bytecodes::_checkcast: | |
875 { ArgumentMap obj = state.apop(); | |
876 set_method_escape(obj); | |
877 state.apush(obj); | |
878 } | |
879 break; | |
880 case Bytecodes::_instanceof: | |
881 set_method_escape(state.apop()); | |
882 state.spush(); | |
883 break; | |
884 case Bytecodes::_monitorenter: | |
885 case Bytecodes::_monitorexit: | |
886 state.apop(); | |
887 break; | |
888 case Bytecodes::_wide: | |
889 ShouldNotReachHere(); | |
890 break; | |
891 case Bytecodes::_ifnull: | |
892 case Bytecodes::_ifnonnull: | |
893 { | |
894 set_method_escape(state.apop()); | |
895 int dest_bci = s.get_dest(); | |
896 assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); | |
897 assert(s.next_bci() == limit_bci, "branch must end block"); | |
898 successors.push(_methodBlocks->block_containing(dest_bci)); | |
899 break; | |
900 } | |
901 case Bytecodes::_goto_w: | |
902 { | |
903 int dest_bci = s.get_far_dest(); | |
904 assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); | |
905 assert(s.next_bci() == limit_bci, "branch must end block"); | |
906 successors.push(_methodBlocks->block_containing(dest_bci)); | |
907 fall_through = false; | |
908 break; | |
909 } | |
910 case Bytecodes::_jsr_w: | |
911 { | |
912 int dest_bci = s.get_far_dest(); | |
913 assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block"); | |
914 assert(s.next_bci() == limit_bci, "branch must end block"); | |
915 state.apush(empty_map); | |
916 successors.push(_methodBlocks->block_containing(dest_bci)); | |
917 fall_through = false; | |
918 break; | |
919 } | |
920 case Bytecodes::_breakpoint: | |
921 break; | |
922 default: | |
923 ShouldNotReachHere(); | |
924 break; | |
925 } | |
926 | |
927 } | |
928 if (fall_through) { | |
929 int fall_through_bci = s.cur_bci(); | |
930 if (fall_through_bci < _method->code_size()) { | |
931 assert(_methodBlocks->is_block_start(fall_through_bci), "must fall through to block start."); | |
932 successors.push(_methodBlocks->block_containing(fall_through_bci)); | |
933 } | |
934 } | |
935 } | |
936 | |
937 void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) { | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
938 StateInfo *d_state = blockstates + dest->index(); |
0 | 939 int nlocals = _method->max_locals(); |
940 | |
941 // exceptions may cause transfer of control to handlers in the middle of a | |
942 // block, so we don't merge the incoming state of exception handlers | |
943 if (dest->is_handler()) | |
944 return; | |
945 if (!d_state->_initialized ) { | |
946 // destination not initialized, just copy | |
947 for (int i = 0; i < nlocals; i++) { | |
948 d_state->_vars[i] = s_state->_vars[i]; | |
949 } | |
950 for (int i = 0; i < s_state->_stack_height; i++) { | |
951 d_state->_stack[i] = s_state->_stack[i]; | |
952 } | |
953 d_state->_stack_height = s_state->_stack_height; | |
954 d_state->_max_stack = s_state->_max_stack; | |
955 d_state->_initialized = true; | |
956 } else if (!dest->processed()) { | |
957 // we have not yet walked the bytecodes of dest, we can merge | |
958 // the states | |
959 assert(d_state->_stack_height == s_state->_stack_height, "computed stack heights must match"); | |
960 for (int i = 0; i < nlocals; i++) { | |
961 d_state->_vars[i].set_union(s_state->_vars[i]); | |
962 } | |
963 for (int i = 0; i < s_state->_stack_height; i++) { | |
964 d_state->_stack[i].set_union(s_state->_stack[i]); | |
965 } | |
966 } else { | |
967 // the bytecodes of dest have already been processed, mark any | |
968 // arguments in the source state which are not in the dest state | |
969 // as global escape. | |
970 // Future refinement: we only need to mark these variable to the | |
971 // maximum escape of any variables in dest state | |
972 assert(d_state->_stack_height == s_state->_stack_height, "computed stack heights must match"); | |
973 ArgumentMap extra_vars; | |
974 for (int i = 0; i < nlocals; i++) { | |
975 ArgumentMap t; | |
976 t = s_state->_vars[i]; | |
977 t.set_difference(d_state->_vars[i]); | |
978 extra_vars.set_union(t); | |
979 } | |
980 for (int i = 0; i < s_state->_stack_height; i++) { | |
981 ArgumentMap t; | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
982 //extra_vars |= !d_state->_vars[i] & s_state->_vars[i]; |
0 | 983 t.clear(); |
984 t = s_state->_stack[i]; | |
985 t.set_difference(d_state->_stack[i]); | |
986 extra_vars.set_union(t); | |
987 } | |
988 set_global_escape(extra_vars); | |
989 } | |
990 } | |
991 | |
992 void BCEscapeAnalyzer::iterate_blocks(Arena *arena) { | |
993 int numblocks = _methodBlocks->num_blocks(); | |
994 int stkSize = _method->max_stack(); | |
995 int numLocals = _method->max_locals(); | |
996 StateInfo state; | |
997 | |
998 int datacount = (numblocks + 1) * (stkSize + numLocals); | |
999 int datasize = datacount * sizeof(ArgumentMap); | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1000 StateInfo *blockstates = (StateInfo *) arena->Amalloc(numblocks * sizeof(StateInfo)); |
0 | 1001 ArgumentMap *statedata = (ArgumentMap *) arena->Amalloc(datasize); |
1002 for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap(); | |
1003 ArgumentMap *dp = statedata; | |
1004 state._vars = dp; | |
1005 dp += numLocals; | |
1006 state._stack = dp; | |
1007 dp += stkSize; | |
1008 state._initialized = false; | |
1009 state._max_stack = stkSize; | |
1010 for (int i = 0; i < numblocks; i++) { | |
1011 blockstates[i]._vars = dp; | |
1012 dp += numLocals; | |
1013 blockstates[i]._stack = dp; | |
1014 dp += stkSize; | |
1015 blockstates[i]._initialized = false; | |
1016 blockstates[i]._stack_height = 0; | |
1017 blockstates[i]._max_stack = stkSize; | |
1018 } | |
1019 GrowableArray<ciBlock *> worklist(arena, numblocks / 4, 0, NULL); | |
1020 GrowableArray<ciBlock *> successors(arena, 4, 0, NULL); | |
1021 | |
1022 _methodBlocks->clear_processed(); | |
1023 | |
1024 // initialize block 0 state from method signature | |
1025 ArgumentMap allVars; // all oop arguments to method | |
1026 ciSignature* sig = method()->signature(); | |
1027 int j = 0; | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1028 ciBlock* first_blk = _methodBlocks->block_containing(0); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1029 int fb_i = first_blk->index(); |
0 | 1030 if (!method()->is_static()) { |
1031 // record information for "this" | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1032 blockstates[fb_i]._vars[j].set(j); |
0 | 1033 allVars.add(j); |
1034 j++; | |
1035 } | |
1036 for (int i = 0; i < sig->count(); i++) { | |
1037 ciType* t = sig->type_at(i); | |
1038 if (!t->is_primitive_type()) { | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1039 blockstates[fb_i]._vars[j].set(j); |
0 | 1040 allVars.add(j); |
1041 } | |
1042 j += t->size(); | |
1043 } | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1044 blockstates[fb_i]._initialized = true; |
0 | 1045 assert(j == _arg_size, "just checking"); |
1046 | |
1047 ArgumentMap unknown_map; | |
1048 unknown_map.add_unknown(); | |
1049 | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1050 worklist.push(first_blk); |
0 | 1051 while(worklist.length() > 0) { |
1052 ciBlock *blk = worklist.pop(); | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1053 StateInfo *blkState = blockstates + blk->index(); |
0 | 1054 if (blk->is_handler() || blk->is_ret_target()) { |
1055 // for an exception handler or a target of a ret instruction, we assume the worst case, | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1056 // that any variable could contain any argument |
0 | 1057 for (int i = 0; i < numLocals; i++) { |
1058 state._vars[i] = allVars; | |
1059 } | |
1060 if (blk->is_handler()) { | |
1061 state._stack_height = 1; | |
1062 } else { | |
1063 state._stack_height = blkState->_stack_height; | |
1064 } | |
1065 for (int i = 0; i < state._stack_height; i++) { | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1066 // ??? should this be unknown_map ??? |
0 | 1067 state._stack[i] = allVars; |
1068 } | |
1069 } else { | |
1070 for (int i = 0; i < numLocals; i++) { | |
1071 state._vars[i] = blkState->_vars[i]; | |
1072 } | |
1073 for (int i = 0; i < blkState->_stack_height; i++) { | |
1074 state._stack[i] = blkState->_stack[i]; | |
1075 } | |
1076 state._stack_height = blkState->_stack_height; | |
1077 } | |
1078 iterate_one_block(blk, state, successors); | |
1079 // if this block has any exception handlers, push them | |
1080 // onto successor list | |
1081 if (blk->has_handler()) { | |
1082 DEBUG_ONLY(int handler_count = 0;) | |
1083 int blk_start = blk->start_bci(); | |
1084 int blk_end = blk->limit_bci(); | |
1085 for (int i = 0; i < numblocks; i++) { | |
1086 ciBlock *b = _methodBlocks->block(i); | |
1087 if (b->is_handler()) { | |
1088 int ex_start = b->ex_start_bci(); | |
1089 int ex_end = b->ex_limit_bci(); | |
1090 if ((ex_start >= blk_start && ex_start < blk_end) || | |
1091 (ex_end > blk_start && ex_end <= blk_end)) { | |
1092 successors.push(b); | |
1093 } | |
1094 DEBUG_ONLY(handler_count++;) | |
1095 } | |
1096 } | |
1097 assert(handler_count > 0, "must find at least one handler"); | |
1098 } | |
1099 // merge computed variable state with successors | |
1100 while(successors.length() > 0) { | |
1101 ciBlock *succ = successors.pop(); | |
1102 merge_block_states(blockstates, succ, &state); | |
1103 if (!succ->processed()) | |
1104 worklist.push(succ); | |
1105 } | |
1106 } | |
1107 } | |
1108 | |
1109 bool BCEscapeAnalyzer::do_analysis() { | |
1110 Arena* arena = CURRENT_ENV->arena(); | |
1111 // identify basic blocks | |
1112 _methodBlocks = _method->get_method_blocks(); | |
1113 | |
1114 iterate_blocks(arena); | |
1115 // TEMPORARY | |
1116 return true; | |
1117 } | |
1118 | |
1119 vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() { | |
1120 vmIntrinsics::ID iid = method()->intrinsic_id(); | |
1121 | |
1122 if (iid == vmIntrinsics::_getClass || | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1123 iid == vmIntrinsics::_fillInStackTrace || |
0 | 1124 iid == vmIntrinsics::_hashCode) |
1125 return iid; | |
1126 else | |
1127 return vmIntrinsics::_none; | |
1128 } | |
1129 | |
1130 bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) { | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1131 ArgumentMap arg; |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1132 arg.clear(); |
0 | 1133 switch (iid) { |
1134 case vmIntrinsics::_getClass: | |
1135 _return_local = false; | |
1136 break; | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1137 case vmIntrinsics::_fillInStackTrace: |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1138 arg.set(0); // 'this' |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1139 set_returned(arg); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1140 break; |
0 | 1141 case vmIntrinsics::_hashCode: |
1142 // initialized state is correct | |
1143 break; | |
1144 default: | |
1145 assert(false, "unexpected intrinsic"); | |
1146 } | |
1147 return true; | |
1148 } | |
1149 | |
1150 void BCEscapeAnalyzer::initialize() { | |
1151 int i; | |
1152 | |
1153 // clear escape information (method may have been deoptimized) | |
1154 methodData()->clear_escape_info(); | |
1155 | |
1156 // initialize escape state of object parameters | |
1157 ciSignature* sig = method()->signature(); | |
1158 int j = 0; | |
1159 if (!method()->is_static()) { | |
1160 _arg_local.set_bit(0); | |
1161 _arg_stack.set_bit(0); | |
1162 j++; | |
1163 } | |
1164 for (i = 0; i < sig->count(); i++) { | |
1165 ciType* t = sig->type_at(i); | |
1166 if (!t->is_primitive_type()) { | |
1167 _arg_local.set_bit(j); | |
1168 _arg_stack.set_bit(j); | |
1169 } | |
1170 j += t->size(); | |
1171 } | |
1172 assert(j == _arg_size, "just checking"); | |
1173 | |
1174 // start with optimistic assumption | |
1175 ciType *rt = _method->return_type(); | |
1176 if (rt->is_primitive_type()) { | |
1177 _return_local = false; | |
1178 _return_allocated = false; | |
1179 } else { | |
1180 _return_local = true; | |
1181 _return_allocated = true; | |
1182 } | |
1183 _allocated_escapes = false; | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1184 _unknown_modified = false; |
0 | 1185 } |
1186 | |
1187 void BCEscapeAnalyzer::clear_escape_info() { | |
1188 ciSignature* sig = method()->signature(); | |
1189 int arg_count = sig->count(); | |
1190 ArgumentMap var; | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1191 if (!method()->is_static()) { |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1192 arg_count++; // allow for "this" |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1193 } |
0 | 1194 for (int i = 0; i < arg_count; i++) { |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1195 set_arg_modified(i, OFFSET_ANY, 4); |
0 | 1196 var.clear(); |
1197 var.set(i); | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1198 set_modified(var, OFFSET_ANY, 4); |
0 | 1199 set_global_escape(var); |
1200 } | |
1201 _arg_local.clear(); | |
1202 _arg_stack.clear(); | |
1203 _arg_returned.clear(); | |
1204 _return_local = false; | |
1205 _return_allocated = false; | |
1206 _allocated_escapes = true; | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1207 _unknown_modified = true; |
0 | 1208 } |
1209 | |
1210 | |
1211 void BCEscapeAnalyzer::compute_escape_info() { | |
1212 int i; | |
1213 assert(!methodData()->has_escape_info(), "do not overwrite escape info"); | |
1214 | |
1215 vmIntrinsics::ID iid = known_intrinsic(); | |
1216 | |
1217 // check if method can be analyzed | |
1218 if (iid == vmIntrinsics::_none && (method()->is_abstract() || method()->is_native() || !method()->holder()->is_initialized() | |
1219 || _level > MaxBCEAEstimateLevel | |
1220 || method()->code_size() > MaxBCEAEstimateSize)) { | |
1221 if (BCEATraceLevel >= 1) { | |
1222 tty->print("Skipping method because: "); | |
1223 if (method()->is_abstract()) | |
1224 tty->print_cr("method is abstract."); | |
1225 else if (method()->is_native()) | |
1226 tty->print_cr("method is native."); | |
1227 else if (!method()->holder()->is_initialized()) | |
1228 tty->print_cr("class of method is not initialized."); | |
1229 else if (_level > MaxBCEAEstimateLevel) | |
1230 tty->print_cr("level (%d) exceeds MaxBCEAEstimateLevel (%d).", | |
1231 _level, MaxBCEAEstimateLevel); | |
1232 else if (method()->code_size() > MaxBCEAEstimateSize) | |
1233 tty->print_cr("code size (%d) exceeds MaxBCEAEstimateSize.", | |
1234 method()->code_size(), MaxBCEAEstimateSize); | |
1235 else | |
1236 ShouldNotReachHere(); | |
1237 } | |
1238 clear_escape_info(); | |
1239 | |
1240 return; | |
1241 } | |
1242 | |
1243 if (BCEATraceLevel >= 1) { | |
1244 tty->print("[EA] estimating escape information for"); | |
1245 if (iid != vmIntrinsics::_none) | |
1246 tty->print(" intrinsic"); | |
1247 method()->print_short_name(); | |
1248 tty->print_cr(" (%d bytes)", method()->code_size()); | |
1249 } | |
1250 | |
1251 bool success; | |
1252 | |
1253 initialize(); | |
1254 | |
78
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1255 // Do not scan method if it has no object parameters and |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1256 // does not returns an object (_return_allocated is set in initialize()). |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1257 if (_arg_local.is_empty() && !_return_allocated) { |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1258 // Clear all info since method's bytecode was not analysed and |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1259 // set pessimistic escape information. |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1260 clear_escape_info(); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1261 methodData()->set_eflag(methodDataOopDesc::allocated_escapes); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1262 methodData()->set_eflag(methodDataOopDesc::unknown_modified); |
0 | 1263 methodData()->set_eflag(methodDataOopDesc::estimated); |
1264 return; | |
1265 } | |
1266 | |
1267 if (iid != vmIntrinsics::_none) | |
1268 success = compute_escape_for_intrinsic(iid); | |
1269 else { | |
1270 success = do_analysis(); | |
1271 } | |
1272 | |
78
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1273 // don't store interprocedural escape information if it introduces |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1274 // dependencies or if method data is empty |
0 | 1275 // |
1276 if (!has_dependencies() && !methodData()->is_empty()) { | |
1277 for (i = 0; i < _arg_size; i++) { | |
1278 if (_arg_local.at(i)) { | |
1279 assert(_arg_stack.at(i), "inconsistent escape info"); | |
1280 methodData()->set_arg_local(i); | |
1281 methodData()->set_arg_stack(i); | |
1282 } else if (_arg_stack.at(i)) { | |
1283 methodData()->set_arg_stack(i); | |
1284 } | |
1285 if (_arg_returned.at(i)) { | |
1286 methodData()->set_arg_returned(i); | |
1287 } | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1288 methodData()->set_arg_modified(i, _arg_modified[i]); |
0 | 1289 } |
1290 if (_return_local) { | |
1291 methodData()->set_eflag(methodDataOopDesc::return_local); | |
1292 } | |
78
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1293 if (_return_allocated) { |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1294 methodData()->set_eflag(methodDataOopDesc::return_allocated); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1295 } |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1296 if (_allocated_escapes) { |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1297 methodData()->set_eflag(methodDataOopDesc::allocated_escapes); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1298 } |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1299 if (_unknown_modified) { |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1300 methodData()->set_eflag(methodDataOopDesc::unknown_modified); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1301 } |
0 | 1302 methodData()->set_eflag(methodDataOopDesc::estimated); |
1303 } | |
1304 } | |
1305 | |
1306 void BCEscapeAnalyzer::read_escape_info() { | |
1307 assert(methodData()->has_escape_info(), "no escape info available"); | |
1308 | |
1309 // read escape information from method descriptor | |
1310 for (int i = 0; i < _arg_size; i++) { | |
1311 _arg_local.at_put(i, methodData()->is_arg_local(i)); | |
1312 _arg_stack.at_put(i, methodData()->is_arg_stack(i)); | |
1313 _arg_returned.at_put(i, methodData()->is_arg_returned(i)); | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1314 _arg_modified[i] = methodData()->arg_modified(i); |
0 | 1315 } |
1316 _return_local = methodData()->eflag_set(methodDataOopDesc::return_local); | |
78
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1317 _return_allocated = methodData()->eflag_set(methodDataOopDesc::return_allocated); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1318 _allocated_escapes = methodData()->eflag_set(methodDataOopDesc::allocated_escapes); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1319 _unknown_modified = methodData()->eflag_set(methodDataOopDesc::unknown_modified); |
0 | 1320 |
1321 } | |
1322 | |
78
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1323 #ifndef PRODUCT |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1324 void BCEscapeAnalyzer::dump() { |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1325 tty->print("[EA] estimated escape information for"); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1326 method()->print_short_name(); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1327 tty->print_cr(has_dependencies() ? " (not stored)" : ""); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1328 tty->print(" non-escaping args: "); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1329 _arg_local.print_on(tty); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1330 tty->print(" stack-allocatable args: "); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1331 _arg_stack.print_on(tty); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1332 if (_return_local) { |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1333 tty->print(" returned args: "); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1334 _arg_returned.print_on(tty); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1335 } else if (is_return_allocated()) { |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1336 tty->print_cr(" return allocated value"); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1337 } else { |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1338 tty->print_cr(" return non-local value"); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1339 } |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1340 tty->print(" modified args: "); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1341 for (int i = 0; i < _arg_size; i++) { |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1342 if (_arg_modified[i] == 0) |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1343 tty->print(" 0"); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1344 else |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1345 tty->print(" 0x%x", _arg_modified[i]); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1346 } |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1347 tty->cr(); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1348 tty->print(" flags: "); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1349 if (_return_allocated) |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1350 tty->print(" return_allocated"); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1351 if (_allocated_escapes) |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1352 tty->print(" allocated_escapes"); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1353 if (_unknown_modified) |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1354 tty->print(" unknown_modified"); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1355 tty->cr(); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1356 } |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1357 #endif |
0 | 1358 |
1359 BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent) | |
1360 : _conservative(method == NULL || !EstimateArgEscape) | |
1361 , _method(method) | |
1362 , _methodData(method ? method->method_data() : NULL) | |
1363 , _arg_size(method ? method->arg_size() : 0) | |
1364 , _stack() | |
1365 , _arg_local(_arg_size) | |
1366 , _arg_stack(_arg_size) | |
1367 , _arg_returned(_arg_size) | |
1368 , _dirty(_arg_size) | |
1369 , _return_local(false) | |
1370 , _return_allocated(false) | |
1371 , _allocated_escapes(false) | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1372 , _unknown_modified(false) |
0 | 1373 , _dependencies() |
1374 , _parent(parent) | |
1375 , _level(parent == NULL ? 0 : parent->level() + 1) { | |
1376 if (!_conservative) { | |
1377 _arg_local.clear(); | |
1378 _arg_stack.clear(); | |
1379 _arg_returned.clear(); | |
1380 _dirty.clear(); | |
1381 Arena* arena = CURRENT_ENV->arena(); | |
45
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1382 _arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint)); |
48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
kvn
parents:
0
diff
changeset
|
1383 Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint)); |
0 | 1384 |
1385 if (methodData() == NULL) | |
1386 return; | |
1387 bool printit = _method->should_print_assembly(); | |
1388 if (methodData()->has_escape_info()) { | |
1389 TRACE_BCEA(2, tty->print_cr("[EA] Reading previous results for %s.%s", | |
1390 method->holder()->name()->as_utf8(), | |
1391 method->name()->as_utf8())); | |
1392 read_escape_info(); | |
1393 } else { | |
1394 TRACE_BCEA(2, tty->print_cr("[EA] computing results for %s.%s", | |
1395 method->holder()->name()->as_utf8(), | |
1396 method->name()->as_utf8())); | |
1397 | |
1398 compute_escape_info(); | |
1399 methodData()->update_escape_info(); | |
1400 } | |
78
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1401 #ifndef PRODUCT |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1402 if (BCEATraceLevel >= 3) { |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1403 // dump escape information |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1404 dump(); |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1405 } |
e1e86702e43e
6680665: bytecode Escape Analyzer produces incorrect escape information for methods without oop arguments
kvn
parents:
45
diff
changeset
|
1406 #endif |
0 | 1407 } |
1408 } | |
1409 | |
1410 void BCEscapeAnalyzer::copy_dependencies(Dependencies *deps) { | |
1411 if(!has_dependencies()) | |
1412 return; | |
1413 for (int i = 0; i < _dependencies.length(); i+=2) { | |
1414 ciKlass *k = _dependencies[i]->as_klass(); | |
1415 ciMethod *m = _dependencies[i+1]->as_method(); | |
1416 deps->assert_unique_concrete_method(k, m); | |
1417 } | |
1418 } |