Mercurial > hg > graal-compiler
annotate src/share/vm/code/dependencies.hpp @ 3992:d1bdeef3e3e2
7098282: G1: assert(interval >= 0) failed: Sanity check, referencePolicy.cpp: 76
Summary: There is a race between one thread successfully forwarding and copying the klass mirror for the SoftReference class (including the static master clock) and another thread attempting to use the master clock while attempting to discover a soft reference object. Maintain a shadow copy of the soft reference master clock and use the shadow during reference discovery and reference processing.
Reviewed-by: tonyp, brutisso, ysr
author | johnc |
---|---|
date | Wed, 12 Oct 2011 10:25:51 -0700 |
parents | b27c72d69fd1 |
children | da91efe96a93 |
rev | line source |
---|---|
0 | 1 /* |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
2 * Copyright (c) 2005, 2011, 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:
1123
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1123
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:
1123
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef SHARE_VM_CODE_DEPENDENCIES_HPP |
26 #define SHARE_VM_CODE_DEPENDENCIES_HPP | |
27 | |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
28 #include "ci/ciCallSite.hpp" |
1972 | 29 #include "ci/ciKlass.hpp" |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
30 #include "ci/ciMethodHandle.hpp" |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
31 #include "classfile/systemDictionary.hpp" |
1972 | 32 #include "code/compressedStream.hpp" |
33 #include "code/nmethod.hpp" | |
34 #include "utilities/growableArray.hpp" | |
35 | |
0 | 36 //** Dependencies represent assertions (approximate invariants) within |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
37 // the runtime system, e.g. class hierarchy changes. An example is an |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
38 // assertion that a given method is not overridden; another example is |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
39 // that a type has only one concrete subtype. Compiled code which |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
40 // relies on such assertions must be discarded if they are overturned |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
41 // by changes in the runtime system. We can think of these assertions |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
42 // as approximate invariants, because we expect them to be overturned |
0 | 43 // very infrequently. We are willing to perform expensive recovery |
44 // operations when they are overturned. The benefit, of course, is | |
45 // performing optimistic optimizations (!) on the object code. | |
46 // | |
47 // Changes in the class hierarchy due to dynamic linking or | |
48 // class evolution can violate dependencies. There is enough | |
49 // indexing between classes and nmethods to make dependency | |
50 // checking reasonably efficient. | |
51 | |
52 class ciEnv; | |
53 class nmethod; | |
54 class OopRecorder; | |
55 class xmlStream; | |
56 class CompileLog; | |
57 class DepChange; | |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
58 class KlassDepChange; |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
59 class CallSiteDepChange; |
0 | 60 class No_Safepoint_Verifier; |
61 | |
62 class Dependencies: public ResourceObj { | |
63 public: | |
64 // Note: In the comments on dependency types, most uses of the terms | |
65 // subtype and supertype are used in a "non-strict" or "inclusive" | |
66 // sense, and are starred to remind the reader of this fact. | |
67 // Strict uses of the terms use the word "proper". | |
68 // | |
69 // Specifically, every class is its own subtype* and supertype*. | |
70 // (This trick is easier than continually saying things like "Y is a | |
71 // subtype of X or X itself".) | |
72 // | |
73 // Sometimes we write X > Y to mean X is a proper supertype of Y. | |
74 // The notation X > {Y, Z} means X has proper subtypes Y, Z. | |
75 // The notation X.m > Y means that Y inherits m from X, while | |
76 // X.m > Y.m means Y overrides X.m. A star denotes abstractness, | |
77 // as *I > A, meaning (abstract) interface I is a super type of A, | |
78 // or A.*m > B.m, meaning B.m implements abstract method A.m. | |
79 // | |
80 // In this module, the terms "subtype" and "supertype" refer to | |
81 // Java-level reference type conversions, as detected by | |
82 // "instanceof" and performed by "checkcast" operations. The method | |
83 // Klass::is_subtype_of tests these relations. Note that "subtype" | |
84 // is richer than "subclass" (as tested by Klass::is_subclass_of), | |
85 // since it takes account of relations involving interface and array | |
86 // types. | |
87 // | |
88 // To avoid needless complexity, dependencies involving array types | |
89 // are not accepted. If you need to make an assertion about an | |
90 // array type, make the assertion about its corresponding element | |
91 // types. Any assertion that might change about an array type can | |
92 // be converted to an assertion about its element type. | |
93 // | |
94 // Most dependencies are evaluated over a "context type" CX, which | |
95 // stands for the set Subtypes(CX) of every Java type that is a subtype* | |
96 // of CX. When the system loads a new class or interface N, it is | |
97 // responsible for re-evaluating changed dependencies whose context | |
98 // type now includes N, that is, all super types of N. | |
99 // | |
100 enum DepType { | |
101 end_marker = 0, | |
102 | |
103 // An 'evol' dependency simply notes that the contents of the | |
104 // method were used. If it evolves (is replaced), the nmethod | |
105 // must be recompiled. No other dependencies are implied. | |
106 evol_method, | |
107 FIRST_TYPE = evol_method, | |
108 | |
109 // A context type CX is a leaf it if has no proper subtype. | |
110 leaf_type, | |
111 | |
112 // An abstract class CX has exactly one concrete subtype CC. | |
113 abstract_with_unique_concrete_subtype, | |
114 | |
115 // The type CX is purely abstract, with no concrete subtype* at all. | |
116 abstract_with_no_concrete_subtype, | |
117 | |
118 // The concrete CX is free of concrete proper subtypes. | |
119 concrete_with_no_concrete_subtype, | |
120 | |
121 // Given a method M1 and a context class CX, the set MM(CX, M1) of | |
122 // "concrete matching methods" in CX of M1 is the set of every | |
123 // concrete M2 for which it is possible to create an invokevirtual | |
124 // or invokeinterface call site that can reach either M1 or M2. | |
125 // That is, M1 and M2 share a name, signature, and vtable index. | |
126 // We wish to notice when the set MM(CX, M1) is just {M1}, or | |
127 // perhaps a set of two {M1,M2}, and issue dependencies on this. | |
128 | |
129 // The set MM(CX, M1) can be computed by starting with any matching | |
130 // concrete M2 that is inherited into CX, and then walking the | |
131 // subtypes* of CX looking for concrete definitions. | |
132 | |
133 // The parameters to this dependency are the method M1 and the | |
134 // context class CX. M1 must be either inherited in CX or defined | |
135 // in a subtype* of CX. It asserts that MM(CX, M1) is no greater | |
136 // than {M1}. | |
137 unique_concrete_method, // one unique concrete method under CX | |
138 | |
139 // An "exclusive" assertion concerns two methods or subtypes, and | |
140 // declares that there are at most two (or perhaps later N>2) | |
141 // specific items that jointly satisfy the restriction. | |
142 // We list all items explicitly rather than just giving their | |
143 // count, for robustness in the face of complex schema changes. | |
144 | |
145 // A context class CX (which may be either abstract or concrete) | |
146 // has two exclusive concrete subtypes* C1, C2 if every concrete | |
147 // subtype* of CX is either C1 or C2. Note that if neither C1 or C2 | |
148 // are equal to CX, then CX itself must be abstract. But it is | |
149 // also possible (for example) that C1 is CX (a concrete class) | |
150 // and C2 is a proper subtype of C1. | |
151 abstract_with_exclusive_concrete_subtypes_2, | |
152 | |
153 // This dependency asserts that MM(CX, M1) is no greater than {M1,M2}. | |
154 exclusive_concrete_methods_2, | |
155 | |
156 // This dependency asserts that no instances of class or it's | |
157 // subclasses require finalization registration. | |
158 no_finalizable_subclasses, | |
159 | |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
160 // This dependency asserts when the CallSite.target value changed. |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
161 call_site_target_value, |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
162 |
0 | 163 TYPE_LIMIT |
164 }; | |
165 enum { | |
166 LG2_TYPE_LIMIT = 4, // assert(TYPE_LIMIT <= (1<<LG2_TYPE_LIMIT)) | |
167 | |
168 // handy categorizations of dependency types: | |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
169 all_types = ((1 << TYPE_LIMIT) - 1) & ((-1) << FIRST_TYPE), |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
170 |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
171 non_klass_types = (1 << call_site_target_value), |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
172 klass_types = all_types & ~non_klass_types, |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
173 |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
174 non_ctxk_types = (1 << evol_method), |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
175 implicit_ctxk_types = (1 << call_site_target_value), |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
176 explicit_ctxk_types = all_types & ~(non_ctxk_types | implicit_ctxk_types), |
0 | 177 |
178 max_arg_count = 3, // current maximum number of arguments (incl. ctxk) | |
179 | |
180 // A "context type" is a class or interface that | |
181 // provides context for evaluating a dependency. | |
182 // When present, it is one of the arguments (dep_context_arg). | |
183 // | |
184 // If a dependency does not have a context type, there is a | |
185 // default context, depending on the type of the dependency. | |
186 // This bit signals that a default context has been compressed away. | |
187 default_context_type_bit = (1<<LG2_TYPE_LIMIT) | |
188 }; | |
189 | |
190 static const char* dep_name(DepType dept); | |
191 static int dep_args(DepType dept); | |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
192 |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
193 static bool is_klass_type( DepType dept) { return dept_in_mask(dept, klass_types ); } |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
194 |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
195 static bool has_explicit_context_arg(DepType dept) { return dept_in_mask(dept, explicit_ctxk_types); } |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
196 static bool has_implicit_context_arg(DepType dept) { return dept_in_mask(dept, implicit_ctxk_types); } |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
197 |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
198 static int dep_context_arg(DepType dept) { return has_explicit_context_arg(dept) ? 0 : -1; } |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
199 static int dep_implicit_context_arg(DepType dept) { return has_implicit_context_arg(dept) ? 0 : -1; } |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
200 |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
201 static void check_valid_dependency_type(DepType dept); |
0 | 202 |
203 private: | |
204 // State for writing a new set of dependencies: | |
205 GrowableArray<int>* _dep_seen; // (seen[h->ident] & (1<<dept)) | |
206 GrowableArray<ciObject*>* _deps[TYPE_LIMIT]; | |
207 | |
208 static const char* _dep_name[TYPE_LIMIT]; | |
209 static int _dep_args[TYPE_LIMIT]; | |
210 | |
211 static bool dept_in_mask(DepType dept, int mask) { | |
212 return (int)dept >= 0 && dept < TYPE_LIMIT && ((1<<dept) & mask) != 0; | |
213 } | |
214 | |
215 bool note_dep_seen(int dept, ciObject* x) { | |
216 assert(dept < BitsPerInt, "oob"); | |
217 int x_id = x->ident(); | |
218 assert(_dep_seen != NULL, "deps must be writable"); | |
219 int seen = _dep_seen->at_grow(x_id, 0); | |
220 _dep_seen->at_put(x_id, seen | (1<<dept)); | |
221 // return true if we've already seen dept/x | |
222 return (seen & (1<<dept)) != 0; | |
223 } | |
224 | |
225 bool maybe_merge_ctxk(GrowableArray<ciObject*>* deps, | |
226 int ctxk_i, ciKlass* ctxk); | |
227 | |
228 void sort_all_deps(); | |
229 size_t estimate_size_in_bytes(); | |
230 | |
231 // Initialize _deps, etc. | |
232 void initialize(ciEnv* env); | |
233 | |
234 // State for making a new set of dependencies: | |
235 OopRecorder* _oop_recorder; | |
236 | |
237 // Logging support | |
238 CompileLog* _log; | |
239 | |
240 address _content_bytes; // everything but the oop references, encoded | |
241 size_t _size_in_bytes; | |
242 | |
243 public: | |
244 // Make a new empty dependencies set. | |
245 Dependencies(ciEnv* env) { | |
246 initialize(env); | |
247 } | |
248 | |
249 private: | |
250 // Check for a valid context type. | |
251 // Enforce the restriction against array types. | |
252 static void check_ctxk(ciKlass* ctxk) { | |
253 assert(ctxk->is_instance_klass(), "java types only"); | |
254 } | |
255 static void check_ctxk_concrete(ciKlass* ctxk) { | |
256 assert(is_concrete_klass(ctxk->as_instance_klass()), "must be concrete"); | |
257 } | |
258 static void check_ctxk_abstract(ciKlass* ctxk) { | |
259 check_ctxk(ctxk); | |
260 assert(!is_concrete_klass(ctxk->as_instance_klass()), "must be abstract"); | |
261 } | |
262 | |
263 void assert_common_1(DepType dept, ciObject* x); | |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
264 void assert_common_2(DepType dept, ciObject* x0, ciObject* x1); |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
265 void assert_common_3(DepType dept, ciKlass* ctxk, ciObject* x1, ciObject* x2); |
0 | 266 |
267 public: | |
268 // Adding assertions to a new dependency set at compile time: | |
269 void assert_evol_method(ciMethod* m); | |
270 void assert_leaf_type(ciKlass* ctxk); | |
271 void assert_abstract_with_unique_concrete_subtype(ciKlass* ctxk, ciKlass* conck); | |
272 void assert_abstract_with_no_concrete_subtype(ciKlass* ctxk); | |
273 void assert_concrete_with_no_concrete_subtype(ciKlass* ctxk); | |
274 void assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm); | |
275 void assert_abstract_with_exclusive_concrete_subtypes(ciKlass* ctxk, ciKlass* k1, ciKlass* k2); | |
276 void assert_exclusive_concrete_methods(ciKlass* ctxk, ciMethod* m1, ciMethod* m2); | |
277 void assert_has_no_finalizable_subclasses(ciKlass* ctxk); | |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
278 void assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle); |
0 | 279 |
280 // Define whether a given method or type is concrete. | |
281 // These methods define the term "concrete" as used in this module. | |
282 // For this module, an "abstract" class is one which is non-concrete. | |
283 // | |
284 // Future optimizations may allow some classes to remain | |
285 // non-concrete until their first instantiation, and allow some | |
286 // methods to remain non-concrete until their first invocation. | |
287 // In that case, there would be a middle ground between concrete | |
288 // and abstract (as defined by the Java language and VM). | |
289 static bool is_concrete_klass(klassOop k); // k is instantiable | |
290 static bool is_concrete_method(methodOop m); // m is invocable | |
291 static Klass* find_finalizable_subclass(Klass* k); | |
292 | |
293 // These versions of the concreteness queries work through the CI. | |
294 // The CI versions are allowed to skew sometimes from the VM | |
295 // (oop-based) versions. The cost of such a difference is a | |
296 // (safely) aborted compilation, or a deoptimization, or a missed | |
297 // optimization opportunity. | |
298 // | |
299 // In order to prevent spurious assertions, query results must | |
300 // remain stable within any single ciEnv instance. (I.e., they must | |
301 // not go back into the VM to get their value; they must cache the | |
302 // bit in the CI, either eagerly or lazily.) | |
303 static bool is_concrete_klass(ciInstanceKlass* k); // k appears instantiable | |
304 static bool is_concrete_method(ciMethod* m); // m appears invocable | |
305 static bool has_finalizable_subclass(ciInstanceKlass* k); | |
306 | |
307 // As a general rule, it is OK to compile under the assumption that | |
308 // a given type or method is concrete, even if it at some future | |
309 // point becomes abstract. So dependency checking is one-sided, in | |
310 // that it permits supposedly concrete classes or methods to turn up | |
311 // as really abstract. (This shouldn't happen, except during class | |
312 // evolution, but that's the logic of the checking.) However, if a | |
313 // supposedly abstract class or method suddenly becomes concrete, a | |
314 // dependency on it must fail. | |
315 | |
316 // Checking old assertions at run-time (in the VM only): | |
317 static klassOop check_evol_method(methodOop m); | |
318 static klassOop check_leaf_type(klassOop ctxk); | |
319 static klassOop check_abstract_with_unique_concrete_subtype(klassOop ctxk, klassOop conck, | |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
320 KlassDepChange* changes = NULL); |
0 | 321 static klassOop check_abstract_with_no_concrete_subtype(klassOop ctxk, |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
322 KlassDepChange* changes = NULL); |
0 | 323 static klassOop check_concrete_with_no_concrete_subtype(klassOop ctxk, |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
324 KlassDepChange* changes = NULL); |
0 | 325 static klassOop check_unique_concrete_method(klassOop ctxk, methodOop uniqm, |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
326 KlassDepChange* changes = NULL); |
0 | 327 static klassOop check_abstract_with_exclusive_concrete_subtypes(klassOop ctxk, klassOop k1, klassOop k2, |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
328 KlassDepChange* changes = NULL); |
0 | 329 static klassOop check_exclusive_concrete_methods(klassOop ctxk, methodOop m1, methodOop m2, |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
330 KlassDepChange* changes = NULL); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
331 static klassOop check_has_no_finalizable_subclasses(klassOop ctxk, KlassDepChange* changes = NULL); |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
332 static klassOop check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes = NULL); |
0 | 333 // A returned klassOop is NULL if the dependency assertion is still |
334 // valid. A non-NULL klassOop is a 'witness' to the assertion | |
335 // failure, a point in the class hierarchy where the assertion has | |
336 // been proven false. For example, if check_leaf_type returns | |
337 // non-NULL, the value is a subtype of the supposed leaf type. This | |
338 // witness value may be useful for logging the dependency failure. | |
339 // Note that, when a dependency fails, there may be several possible | |
340 // witnesses to the failure. The value returned from the check_foo | |
341 // method is chosen arbitrarily. | |
342 | |
343 // The 'changes' value, if non-null, requests a limited spot-check | |
344 // near the indicated recent changes in the class hierarchy. | |
345 // It is used by DepStream::spot_check_dependency_at. | |
346 | |
347 // Detecting possible new assertions: | |
348 static klassOop find_unique_concrete_subtype(klassOop ctxk); | |
349 static methodOop find_unique_concrete_method(klassOop ctxk, methodOop m); | |
350 static int find_exclusive_concrete_subtypes(klassOop ctxk, int klen, klassOop k[]); | |
351 static int find_exclusive_concrete_methods(klassOop ctxk, int mlen, methodOop m[]); | |
352 | |
353 // Create the encoding which will be stored in an nmethod. | |
354 void encode_content_bytes(); | |
355 | |
356 address content_bytes() { | |
357 assert(_content_bytes != NULL, "encode it first"); | |
358 return _content_bytes; | |
359 } | |
360 size_t size_in_bytes() { | |
361 assert(_content_bytes != NULL, "encode it first"); | |
362 return _size_in_bytes; | |
363 } | |
364 | |
365 OopRecorder* oop_recorder() { return _oop_recorder; } | |
366 CompileLog* log() { return _log; } | |
367 | |
368 void copy_to(nmethod* nm); | |
369 | |
370 void log_all_dependencies(); | |
371 void log_dependency(DepType dept, int nargs, ciObject* args[]) { | |
372 write_dependency_to(log(), dept, nargs, args); | |
373 } | |
374 void log_dependency(DepType dept, | |
375 ciObject* x0, | |
376 ciObject* x1 = NULL, | |
377 ciObject* x2 = NULL) { | |
378 if (log() == NULL) return; | |
379 ciObject* args[max_arg_count]; | |
380 args[0] = x0; | |
381 args[1] = x1; | |
382 args[2] = x2; | |
383 assert(2 < max_arg_count, ""); | |
384 log_dependency(dept, dep_args(dept), args); | |
385 } | |
386 | |
387 static void write_dependency_to(CompileLog* log, | |
388 DepType dept, | |
389 int nargs, ciObject* args[], | |
390 klassOop witness = NULL); | |
391 static void write_dependency_to(CompileLog* log, | |
392 DepType dept, | |
393 int nargs, oop args[], | |
394 klassOop witness = NULL); | |
395 static void write_dependency_to(xmlStream* xtty, | |
396 DepType dept, | |
397 int nargs, oop args[], | |
398 klassOop witness = NULL); | |
399 static void print_dependency(DepType dept, | |
400 int nargs, oop args[], | |
401 klassOop witness = NULL); | |
402 | |
403 private: | |
404 // helper for encoding common context types as zero: | |
405 static ciKlass* ctxk_encoded_as_null(DepType dept, ciObject* x); | |
406 | |
407 static klassOop ctxk_encoded_as_null(DepType dept, oop x); | |
408 | |
409 public: | |
410 // Use this to iterate over an nmethod's dependency set. | |
411 // Works on new and old dependency sets. | |
412 // Usage: | |
413 // | |
414 // ; | |
415 // Dependencies::DepType dept; | |
416 // for (Dependencies::DepStream deps(nm); deps.next(); ) { | |
417 // ... | |
418 // } | |
419 // | |
420 // The caller must be in the VM, since oops are not wrapped in handles. | |
421 class DepStream { | |
422 private: | |
423 nmethod* _code; // null if in a compiler thread | |
424 Dependencies* _deps; // null if not in a compiler thread | |
425 CompressedReadStream _bytes; | |
426 #ifdef ASSERT | |
427 size_t _byte_limit; | |
428 #endif | |
429 | |
430 // iteration variables: | |
431 DepType _type; | |
432 int _xi[max_arg_count+1]; | |
433 | |
434 void initial_asserts(size_t byte_limit) NOT_DEBUG({}); | |
435 | |
436 inline oop recorded_oop_at(int i); | |
437 // => _code? _code->oop_at(i): *_deps->_oop_recorder->handle_at(i) | |
438 | |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
439 klassOop check_klass_dependency(KlassDepChange* changes); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
440 klassOop check_call_site_dependency(CallSiteDepChange* changes); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
441 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
442 void trace_and_log_witness(klassOop witness); |
0 | 443 |
444 public: | |
445 DepStream(Dependencies* deps) | |
446 : _deps(deps), | |
447 _code(NULL), | |
448 _bytes(deps->content_bytes()) | |
449 { | |
450 initial_asserts(deps->size_in_bytes()); | |
451 } | |
452 DepStream(nmethod* code) | |
453 : _deps(NULL), | |
454 _code(code), | |
455 _bytes(code->dependencies_begin()) | |
456 { | |
457 initial_asserts(code->dependencies_size()); | |
458 } | |
459 | |
460 bool next(); | |
461 | |
462 DepType type() { return _type; } | |
463 int argument_count() { return dep_args(type()); } | |
464 int argument_index(int i) { assert(0 <= i && i < argument_count(), "oob"); | |
465 return _xi[i]; } | |
466 oop argument(int i); // => recorded_oop_at(argument_index(i)) | |
467 klassOop context_type(); | |
468 | |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
469 bool is_klass_type() { return Dependencies::is_klass_type(type()); } |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
470 |
0 | 471 methodOop method_argument(int i) { |
472 oop x = argument(i); | |
473 assert(x->is_method(), "type"); | |
474 return (methodOop) x; | |
475 } | |
476 klassOop type_argument(int i) { | |
477 oop x = argument(i); | |
478 assert(x->is_klass(), "type"); | |
479 return (klassOop) x; | |
480 } | |
481 | |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
482 // The point of the whole exercise: Is this dep still OK? |
0 | 483 klassOop check_dependency() { |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
484 klassOop result = check_klass_dependency(NULL); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
485 if (result != NULL) return result; |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
486 return check_call_site_dependency(NULL); |
0 | 487 } |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
488 |
0 | 489 // A lighter version: Checks only around recent changes in a class |
490 // hierarchy. (See Universe::flush_dependents_on.) | |
491 klassOop spot_check_dependency_at(DepChange& changes); | |
492 | |
493 // Log the current dependency to xtty or compilation log. | |
494 void log_dependency(klassOop witness = NULL); | |
495 | |
496 // Print the current dependency to tty. | |
497 void print_dependency(klassOop witness = NULL, bool verbose = false); | |
498 }; | |
499 friend class Dependencies::DepStream; | |
500 | |
501 static void print_statistics() PRODUCT_RETURN; | |
502 }; | |
503 | |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
504 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
505 // Every particular DepChange is a sub-class of this class. |
0 | 506 class DepChange : public StackObj { |
1123
167c2986d91b
6843629: Make current hotspot build part of jdk5 control build
phh
parents:
0
diff
changeset
|
507 public: |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
508 // What kind of DepChange is this? |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
509 virtual bool is_klass_change() const { return false; } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
510 virtual bool is_call_site_change() const { return false; } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
511 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
512 // Subclass casting with assertions. |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
513 KlassDepChange* as_klass_change() { |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
514 assert(is_klass_change(), "bad cast"); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
515 return (KlassDepChange*) this; |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
516 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
517 CallSiteDepChange* as_call_site_change() { |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
518 assert(is_call_site_change(), "bad cast"); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
519 return (CallSiteDepChange*) this; |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
520 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
521 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
522 void print(); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
523 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
524 public: |
0 | 525 enum ChangeType { |
526 NO_CHANGE = 0, // an uninvolved klass | |
527 Change_new_type, // a newly loaded type | |
528 Change_new_sub, // a super with a new subtype | |
529 Change_new_impl, // an interface with a new implementation | |
530 CHANGE_LIMIT, | |
531 Start_Klass = CHANGE_LIMIT // internal indicator for ContextStream | |
532 }; | |
533 | |
534 // Usage: | |
535 // for (DepChange::ContextStream str(changes); str.next(); ) { | |
536 // klassOop k = str.klass(); | |
537 // switch (str.change_type()) { | |
538 // ... | |
539 // } | |
540 // } | |
541 class ContextStream : public StackObj { | |
542 private: | |
1123
167c2986d91b
6843629: Make current hotspot build part of jdk5 control build
phh
parents:
0
diff
changeset
|
543 DepChange& _changes; |
0 | 544 friend class DepChange; |
545 | |
546 // iteration variables: | |
1123
167c2986d91b
6843629: Make current hotspot build part of jdk5 control build
phh
parents:
0
diff
changeset
|
547 ChangeType _change_type; |
167c2986d91b
6843629: Make current hotspot build part of jdk5 control build
phh
parents:
0
diff
changeset
|
548 klassOop _klass; |
167c2986d91b
6843629: Make current hotspot build part of jdk5 control build
phh
parents:
0
diff
changeset
|
549 objArrayOop _ti_base; // i.e., transitive_interfaces |
167c2986d91b
6843629: Make current hotspot build part of jdk5 control build
phh
parents:
0
diff
changeset
|
550 int _ti_index; |
167c2986d91b
6843629: Make current hotspot build part of jdk5 control build
phh
parents:
0
diff
changeset
|
551 int _ti_limit; |
0 | 552 |
553 // start at the beginning: | |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
554 void start(); |
0 | 555 |
1123
167c2986d91b
6843629: Make current hotspot build part of jdk5 control build
phh
parents:
0
diff
changeset
|
556 public: |
0 | 557 ContextStream(DepChange& changes) |
558 : _changes(changes) | |
559 { start(); } | |
560 | |
561 ContextStream(DepChange& changes, No_Safepoint_Verifier& nsv) | |
562 : _changes(changes) | |
563 // the nsv argument makes it safe to hold oops like _klass | |
564 { start(); } | |
565 | |
566 bool next(); | |
567 | |
1123
167c2986d91b
6843629: Make current hotspot build part of jdk5 control build
phh
parents:
0
diff
changeset
|
568 ChangeType change_type() { return _change_type; } |
0 | 569 klassOop klass() { return _klass; } |
570 }; | |
571 friend class DepChange::ContextStream; | |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
572 }; |
0 | 573 |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
574 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
575 // A class hierarchy change coming through the VM (under the Compile_lock). |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
576 // The change is structured as a single new type with any number of supers |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
577 // and implemented interface types. Other than the new type, any of the |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
578 // super types can be context types for a relevant dependency, which the |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
579 // new type could invalidate. |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
580 class KlassDepChange : public DepChange { |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
581 private: |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
582 // each change set is rooted in exactly one new type (at present): |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
583 KlassHandle _new_type; |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
584 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
585 void initialize(); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
586 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
587 public: |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
588 // notes the new type, marks it and all its super-types |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
589 KlassDepChange(KlassHandle new_type) |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
590 : _new_type(new_type) |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
591 { |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
592 initialize(); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
593 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
594 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
595 // cleans up the marks |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
596 ~KlassDepChange(); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
597 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
598 // What kind of DepChange is this? |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
599 virtual bool is_klass_change() const { return true; } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
600 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
601 klassOop new_type() { return _new_type(); } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
602 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
603 // involves_context(k) is true if k is new_type or any of the super types |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
604 bool involves_context(klassOop k); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
605 }; |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
606 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
607 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
608 // A CallSite has changed its target. |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
609 class CallSiteDepChange : public DepChange { |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
610 private: |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
611 Handle _call_site; |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
612 Handle _method_handle; |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
613 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
614 public: |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
615 CallSiteDepChange(Handle call_site, Handle method_handle) |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
616 : _call_site(call_site), |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
617 _method_handle(method_handle) |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
618 { |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
619 assert(_call_site() ->is_a(SystemDictionary::CallSite_klass()), "must be"); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
620 assert(_method_handle()->is_a(SystemDictionary::MethodHandle_klass()), "must be"); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
621 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
622 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
623 // What kind of DepChange is this? |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
624 virtual bool is_call_site_change() const { return true; } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
625 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
626 oop call_site() const { return _call_site(); } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
1972
diff
changeset
|
627 oop method_handle() const { return _method_handle(); } |
0 | 628 }; |
1972 | 629 |
630 #endif // SHARE_VM_CODE_DEPENDENCIES_HPP |