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