dependencies.cpp revision 1879
2362N/A * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 0N/A * published by the Free Software Foundation. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA return true;
//something like this: thread->is_VM_thread(); // As a special case, support this assertion on an array type, // which reduces to an assertion on its element type. // Note that this cannot be done with assertions that // relate to concreteness or abstractness. //if (ctxk->is_final()) return; // Ex: String[][] // Helper function. If we are adding a new dep. under ctxk2, // try to find an old dep. under a broader* ctxk1. If there is return true;
// success, and no need to change // new context class fully subsumes previous one // see if the same (or a similar) dep is already recorded // see if the same (or a similar) dep is already recorded // look in this bucket for redundant assertions if (x ==
x1) {
// same subject; check the context // append the assertion in the correct bucket: // try to normalize an unordered pair: // see if the same (or a similar) dep is already recorded // look in this bucket for redundant assertions if (x == y &&
x2 ==
y2) {
// same subjects; check the context // append the assertion in the correct bucket: /// Support for encoding dependencies into an nmethod: for (
int i = 0; i <
narg; i++) {
int diff =
p1[i]->
ident() -
p2[i]->
ident();
return NULL;
// let NULL be NULL return NULL;
// let NULL be NULL // cast is safe, no deps can overflow INT_MAX skipj =
ctxkj;
// we win: maybe one less oop to keep track of for (
int j = 0; j <
stride; j++) {
if (j ==
skipj)
continue;
// write a sentinel byte to mark the end // round it out to a word boundary // check whether the dept byte encoding really works "abstract_with_unique_concrete_subtype",
"abstract_with_no_concrete_subtype",
"concrete_with_no_concrete_subtype",
"unique_concrete_method",
"abstract_with_exclusive_concrete_subtypes_2",
"exclusive_concrete_methods_2",
"no_finalizable_subclasses" 2,
// abstract_with_unique_concrete_subtype ctxk, k 1,
// abstract_with_no_concrete_subtype ctxk 1,
// concrete_with_no_concrete_subtype ctxk 2,
// unique_concrete_method ctxk, m 3,
// unique_concrete_subtypes_2 ctxk, k1, k2 3,
// unique_concrete_methods_2 ctxk, m1, m2 1 // no_finalizable_subclasses ctxk // for the sake of the compiler log, print out current dependencies: for (
int j = 0; j <
stride; j++) {
// flush out the identities before printing for (
int j = 0; j <
nargs; j++) {
for (j = 0; j <
nargs; j++) {
// write remaining arguments, if any. for (j = 0; j <
nargs; j++) {
if (j ==
ctxkj)
continue;
// already logged // write remaining arguments, if any. for (
int j = 0; j <
nargs; j++) {
if (j ==
ctxkj)
continue;
// already logged for (
int j = 0; j <
nargs; j++) {
for (
int j = 0; j <
nargs; j++) {
for (
int j = 0; j <
nargs; j++) {
/// Dependency stream support (decodes dependencies from an nmethod): // Method has no dependencies at all. "bad dependency type tag");
skipj = 0;
// currently the only context argument is at zero for (
int j = 0; j <
stride; j++) {
return NULL;
// for example, evol_method if (k !=
NULL) {
// context type was not compressed away }
else {
// recompute "default" context type/// Checking dependencies: // This hierarchy walker inspects subtypes of a given type, // trying to find a "bad" class which breaks a dependency. // Such a class is called a "witness" to the broken dependency. // While searching around, we ignore "participants", which // are already known to the dependency. // optional method descriptor to check for: // special classes which are not allowed to be witnesses: // cache of method lookups // if non-zero, tells how many witnesses to convert to participants // The walker is initialized to recognize certain methods and/or types // as friendly participants. // This is common code for two searches: One for concrete subtypes, // the other for concrete method implementations and overrides. // Note: If n==num_participants, returns NULL. // Assert that m is inherited into ctxk, without intervening overrides. // (May return true even if this is not true, in corner cases where we punt.) return true;
// Quick win. return false;
// Quick lose. Should not happen. // The override story is complex when packages get involved. return true;
// Must punt the assertion to true. // It might be an abstract interface method, devoid of mirandas. // Method m is inherited into ctxk. // Method is [package-]private, so the override story is complex. return true;
// Must punt the assertion to true. // Method m is overridden by lm, but both are non-concrete. tty->
print_cr(
"Dependency method not found in the associated context:");
// Note: If add_participant(k) is called, // the method m will already be memoized for it. return false;
// not in list // the actual search method: // the spot-checking version: // When looking for unexpected concrete types, // do not look beneath expected ones. // CX > CC > C' is OK, even if C' is new. // CX > { CC, C' } is not OK if C' is new, and C' is the witness. // When looking for unexpected concrete methods, // look beneath expected ones, to see if there are overrides. // CX.m > CC.m > C'.m is not OK, if C'.m is new, and C' is the witness. tty->
print_cr(
"Warning: TraceDependencies results may be inflated by VerifyDependencies");
// Every now and then dump a little info about dependency searching. xtty->
elem(
"deps_find_witness calls='%d' steps='%d' recursions='%d' singles='%d'",
"calls=%d, steps=%d (avg=%.1f), recursions=%d, singles=%d",
// Current thread must be in VM (not native mode, as in CI): // Must not move the class hierarchy during this check: // Avoid this case: *I.m > { A.m, C }; B.m > C // %%% Until this is fixed more systematically, bail out. // See corresponding comment in find_witness_anywhere. // If the new type is a subtype of a participant, we are done. "correct marking of participants, b/c new_type is unique");
// new guy is protected from this check by previous participant // Walk hierarchy under a context type, looking for unexpected types. // Do not report participant types, and recursively walk beneath // them only if participants_hide_witnesses is false. // If top_level_call is false, skip testing the context type, // because the caller has already considered it. // Current thread must be in VM (not native mode, as in CI): // Must not move the class hierarchy during this check: // Check the root of the sub-hierarchy first. // else fall through to search loop... // The context is an abstract class or interface, to start with. // Now we must check each implementor and each subclass. // Use a short worklist to avoid blowing the stack. // Each worklist entry is a *chain* of subklass siblings to process. const int CHAINMAX =
100;
// >= 1 + instanceKlass::implementors_limit int chaini = 0;
// index into worklist // Look for non-abstract subclasses. // (Note: Interfaces do not have subclasses.) // If it is an interface, search its direct implementors. // (Their subclasses are additional indirect implementors. // See instanceKlass::add_implementor.) // (Note: nof_implementors is always zero for non-interfaces.) // Avoid this case: *I.m > { A.m, C }; B.m > C // Here, I.m has 2 concrete implementations, but m appears unique // as A.m, because the search misses B.m when checking C. // The inherited method B.m was getting missed by the walker // when interface 'I' was the starting point. // %%% Until this is fixed more systematically, bail out. // (Old CHA had the same limitation.) // implementors array overflowed => no exact info. return context_type;
// report an inexact witness to this sad affair // else fall through to process this guy's subclasses // Recursively process each non-trivial sibling chain. // else fall through to process this guy's subclasses // Fast path. (Partially disabled if VerifyDependencies.) // Worklist overflow. Do a recursive call. Should be rare. // The recursive call will have its own worklist, of course. // (Note that sub has already been tested, so that there is // no need for the recursive call to re-test. That's handy, // since the recursive call sees sub as the context_type.) /*top_level_call=*/ false);
// No witness found. The dependency remains unbroken. // %%% We could treat classes which are concrete but // have not yet been instantiated as virtually abstract. // This would require a deoptimization barrier on first instantiation. //if (k->is_not_instantiated()) return false; // %%% We could treat unexecuted methods as virtually abstract also. // This would require a deoptimization barrier on first execution. // We could return also false if k does not yet appear to be // instantiated, if the VM version supports this distinction also. //if (k->is_not_instantiated()) return false; // Statics are irrelevant to virtual call sites. // We could return also false if m does not yet appear to be // executed, if the VM version supports this distinction also. // Any use of the contents (bytecodes) of a method must be // marked by an "evol_method" dependency, if those contents // can change. (Note: A method is always dependent on itself.) // Did somebody do a JVMTI RedefineClasses while our backs were turned? // Or is there a now a breakpoint? // (Assumes compiled code cannot handle bkpts; change if UseFastBreakpoints.) // This is a strong assertion: It is that the given type // has no subtypes whatever. It is most useful for // optimizing checks on reflected types or on array types. // (Checks on types which are derived from real instances // can be optimized more strongly than this, because we // know that the checked type comes from a concrete type, // and therefore we can disregard abstract types.) // if it is an interface, it must be unimplemented // (if it is not an interface, nof_implementors is always zero) // Test the assertion that conck is the only concrete subtype* of ctxk. // The type conck itself is allowed to have have further concrete subtypes. // This allows the compiler to narrow occurrences of ctxk by conck, // when dealing with the types of actual instances. // If a non-concrete class has no concrete subtypes, it is not (yet) // instantiatable. This can allow the compiler to make some paths go // dead, if they are gated by a test of the type. // Find any concrete subtype, with no participants: // If a concrete class has no concrete subtypes, it can always be // exactly typed. This allows the use of a cheaper type test. // Find any concrete subtype, with only the ctxk as participant: // Find the unique concrete proper subtype of ctxk, or NULL if there // is more than one concrete proper subtype. If there are no concrete // proper subtypes, return ctxk itself, whether it is concrete or not. // The returned subtype is allowed to have have further concrete subtypes. // That is, return CC1 for CX > CC1 > CC2, but NULL for CX > { CC1, CC2 }. // Make sure the dependency mechanism will pass this discovery: // Turn off dependency tracing while actually testing deps. return ctxk;
// Return ctxk as a flag for "no subtypes". // Make sure the dependency mechanism will pass this discovery: // Turn off dependency tracing while actually testing deps. // Test the assertion that the k[12] are the only concrete subtypes of ctxk, // except possibly for further subtypes of k[12] themselves. // The context type must be abstract. The types k1 and k2 are themselves // allowed to have further concrete subtypes. // Search ctxk for concrete implementations. If there are klen or fewer, // pack them into the given array and return the number. // Otherwise, return -1, meaning the given array would overflow. // (Note that a return of 0 means there are exactly no concrete subtypes.) // In this search, if ctxk is concrete, it will be reported alone. // For any type CC reported, no proper subtypes of CC will be reported. if (
wit !=
NULL)
return -
1;
// Too many witnesses. // Pack the result array with the good news. for (
int i = 0; i <
num; i++)
// Make sure the dependency mechanism will pass this discovery: // Turn off dependency tracing while actually testing deps. case -
1:
// ctxk was itself concrete // If a class (or interface) has a unique concrete method uniqm, return NULL. // Otherwise, return a class that contains an interfering method. // Here is a missing optimization: If uniqm->is_final(), // we don't really need to search beneath it for overrides. // This is probably not important, since we don't use dependencies // to track final methods. (They can't be "definalized".) // Find the set of all non-abstract methods under ctxk that match m. // (The method m must be defined or inherited in ctxk.) // Include m itself in the set, unless it is abstract. // If this set has exactly one element, return that element. // It turns out that m was always the only implementation. // Two conflicting implementations after all. // (This can happen if m is inherited into ctxk and fm overrides it.) // Make sure the dependency mechanism will pass this discovery: // Find the set of all non-abstract methods under ctxk that match m[0]. // (The method m[0] must be defined or inherited in ctxk.) // Include m itself in the set, unless it is abstract. // Fill the given array m[0..(mlen-1)] with this set, and return the length. // (The length may be zero if no concrete methods are found anywhere.) // If there are too many concrete methods to fit in marray, return -1. if (
wit !=
NULL)
return -
1;
// Too many witnesses. // Keep track of whether m is also part of the result set. mfill++;
// keep m0 as marray[0], the first result for (
int i = 0; i <
num; i++) {
if (
fm ==
m0)
continue;
// Already put this guy in the list. return -
1;
// Oops. Too many methods after all! // Make sure the dependency mechanism will pass this discovery: // Turn off dependency tracing while actually testing deps. // The following is a no-op unless logging is enabled: // irrelevant dependency; skip it // entire transaction must be under this lock: // Mark all dependee and all its superclasses // Mark transitive interfaces // Unmark all dependee and all its superclasses // Unmark transitive interfaces "correct marking of potential context types");
case Start_Klass:
// initial state; _klass is the new type // 6598190: brackets workaround Sun Studio C++ compiler bug 6629277 // else set up _ti_limit and fall through: // Call one final time, to flush out the data.