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