src/share/vm/code/dependencies.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** old/src/share/vm/code/dependencies.cpp	Fri Aug 12 04:58:51 2011
--- new/src/share/vm/code/dependencies.cpp	Fri Aug 12 04:58:51 2011

*** 111,120 **** --- 111,125 ---- void Dependencies::assert_has_no_finalizable_subclasses(ciKlass* ctxk) { check_ctxk(ctxk); assert_common_1(no_finalizable_subclasses, ctxk); } + void Dependencies::assert_call_site_target_value(ciKlass* ctxk, ciCallSite* call_site, ciMethodHandle* method_handle) { + check_ctxk(ctxk); + assert_common_3(call_site_target_value, ctxk, call_site, method_handle); + } + // Helper function. If we are adding a new dep. under ctxk2, // try to find an old dep. under a broader* ctxk1. If there is // bool Dependencies::maybe_merge_ctxk(GrowableArray<ciObject*>* deps, int ctxk_i, ciKlass* ctxk2) {
*** 339,349 **** --- 344,355 ---- "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", + "call_site_target_value" }; int Dependencies::_dep_args[TYPE_LIMIT] = { -1,// end_marker 1, // evol_method m
*** 352,362 **** --- 358,369 ---- 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 ! 1, // no_finalizable_subclasses ctxk + 3 // call_site_target_value ctxk, call_site, method_handle }; const char* Dependencies::dep_name(Dependencies::DepType dept) { if (!dept_in_mask(dept, all_types)) return "?bad-dep?"; return _dep_name[dept];
*** 365,374 **** --- 372,388 ---- int Dependencies::dep_args(Dependencies::DepType dept) { if (!dept_in_mask(dept, all_types)) return -1; return _dep_args[dept]; } + void Dependencies::check_valid_dependency_type(DepType dept) { + for (int deptv = (int) FIRST_TYPE; deptv < (int) TYPE_LIMIT; deptv++) { + if (dept == ((DepType) deptv)) return; + } + ShouldNotReachHere(); + } + // for the sake of the compiler log, print out current dependencies: void Dependencies::log_all_dependencies() { if (log() == NULL) return; ciObject* args[max_arg_count]; for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
*** 798,812 **** --- 812,826 ---- // the actual search method: klassOop find_witness_anywhere(klassOop context_type, bool participants_hide_witnesses, bool top_level_call = true); // the spot-checking version: ! klassOop find_witness_in(KlassDepChange& changes, klassOop context_type, bool participants_hide_witnesses); public: ! klassOop find_witness_subtype(klassOop context_type, KlassDepChange* changes = NULL) { assert(doing_subtype_search(), "must set up a subtype search"); // When looking for unexpected concrete types, // do not look beneath expected ones. const bool participants_hide_witnesses = true; // CX > CC > C' is OK, even if C' is new.
*** 815,825 **** --- 829,839 ---- return find_witness_in(*changes, context_type, participants_hide_witnesses); } else { return find_witness_anywhere(context_type, participants_hide_witnesses); } } ! klassOop find_witness_definer(klassOop context_type, KlassDepChange* changes = NULL) { assert(!doing_subtype_search(), "must set up a method definer search"); // When looking for unexpected concrete methods, // look beneath expected ones, to see if there are overrides. const bool participants_hide_witnesses = true; // CX.m > CC.m > C'.m is not OK, if C'.m is new, and C' is the witness.
*** 876,886 **** --- 890,900 ---- #else #define count_find_witness_calls() (0) #endif //PRODUCT ! klassOop ClassHierarchyWalker::find_witness_in(KlassDepChange& changes, klassOop context_type, bool participants_hide_witnesses) { assert(changes.involves_context(context_type), "irrelevant dependency"); klassOop new_type = changes.new_type();
*** 1135,1164 **** --- 1149,1178 ---- // 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. klassOop Dependencies::check_abstract_with_unique_concrete_subtype(klassOop ctxk, klassOop conck, ! KlassDepChange* changes) { ClassHierarchyWalker wf(conck); return wf.find_witness_subtype(ctxk, changes); } // 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. klassOop Dependencies::check_abstract_with_no_concrete_subtype(klassOop ctxk, ! KlassDepChange* changes) { // Find any concrete subtype, with no participants: ClassHierarchyWalker wf; return wf.find_witness_subtype(ctxk, changes); } // If a concrete class has no concrete subtypes, it can always be // exactly typed. This allows the use of a cheaper type test. klassOop Dependencies::check_concrete_with_no_concrete_subtype(klassOop ctxk, ! KlassDepChange* changes) { // Find any concrete subtype, with only the ctxk as participant: ClassHierarchyWalker wf(ctxk); return wf.find_witness_subtype(ctxk, changes); }
*** 1215,1225 **** --- 1229,1239 ---- // allowed to have further concrete subtypes. klassOop Dependencies::check_abstract_with_exclusive_concrete_subtypes( klassOop ctxk, klassOop k1, klassOop k2, ! KlassDepChange* changes) { ClassHierarchyWalker wf; wf.add_participant(k1); wf.add_participant(k2); return wf.find_witness_subtype(ctxk, changes); }
*** 1276,1286 **** --- 1290,1300 ---- } // If a class (or interface) has a unique concrete method uniqm, return NULL. // Otherwise, return a class that contains an interfering method. klassOop Dependencies::check_unique_concrete_method(klassOop ctxk, methodOop uniqm, ! KlassDepChange* changes) { // 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".) ClassHierarchyWalker wf(uniqm->method_holder(), uniqm);
*** 1319,1329 **** --- 1333,1343 ---- } klassOop Dependencies::check_exclusive_concrete_methods(klassOop ctxk, methodOop m1, methodOop m2, ! KlassDepChange* changes) { ClassHierarchyWalker wf(m1); wf.add_participant(m1->method_holder()); wf.add_participant(m2->method_holder()); return wf.find_witness_definer(ctxk, changes); }
*** 1381,1391 **** --- 1395,1405 ---- #endif //PRODUCT return mfill; } ! klassOop Dependencies::check_has_no_finalizable_subclasses(klassOop ctxk, KlassDepChange* changes) { Klass* search_at = ctxk->klass_part(); if (changes != NULL) search_at = changes->new_type()->klass_part(); // just look at the new bit Klass* result = find_finalizable_subclass(search_at); if (result == NULL) {
*** 1393,1503 **** --- 1407,1556 ---- } return result->as_klassOop(); } ! klassOop Dependencies::DepStream::check_dependency_impl(DepChange* changes) { ! klassOop Dependencies::check_call_site_target_value(klassOop ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes) { + assert(call_site ->is_a(SystemDictionary::CallSite_klass()), "sanity"); + assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "sanity"); + if (changes == NULL) { + // Validate all CallSites + if (java_lang_invoke_CallSite::target(call_site) != method_handle) + return ctxk; // assertion failed + } else { + // Validate the given CallSite + if (call_site == changes->call_site() && java_lang_invoke_CallSite::target(call_site) != changes->method_handle()) { + assert(method_handle != changes->method_handle(), "must be"); + return ctxk; // assertion failed + } + } + assert(java_lang_invoke_CallSite::target(call_site) == method_handle, "should still be valid"); + return NULL; // assertion still valid + } + + + void Dependencies::DepStream::trace_and_log_witness(klassOop witness) { + if (witness != NULL) { + if (TraceDependencies) { + print_dependency(witness, /*verbose=*/ true); + } + // The following is a no-op unless logging is enabled: + log_dependency(witness); + } + } + + + klassOop Dependencies::DepStream::check_klass_dependency(KlassDepChange* changes) { assert_locked_or_safepoint(Compile_lock); + Dependencies::check_valid_dependency_type(type()); klassOop witness = NULL; switch (type()) { case evol_method: witness = check_evol_method(method_argument(0)); break; case leaf_type: witness = check_leaf_type(context_type()); break; case abstract_with_unique_concrete_subtype: ! witness = check_abstract_with_unique_concrete_subtype(context_type(), type_argument(1), changes); type_argument(1), changes); break; case abstract_with_no_concrete_subtype: ! witness = check_abstract_with_no_concrete_subtype(context_type(), changes); changes); break; case concrete_with_no_concrete_subtype: ! witness = check_concrete_with_no_concrete_subtype(context_type(), changes); changes); break; case unique_concrete_method: ! witness = check_unique_concrete_method(context_type(), method_argument(1), changes); method_argument(1), changes); break; case abstract_with_exclusive_concrete_subtypes_2: ! witness = check_abstract_with_exclusive_concrete_subtypes(context_type(), type_argument(1), type_argument(2), changes); type_argument(1), type_argument(2), changes); break; case exclusive_concrete_methods_2: ! witness = check_exclusive_concrete_methods(context_type(), method_argument(1), method_argument(2), changes); method_argument(1), method_argument(2), changes); break; case no_finalizable_subclasses: ! witness = check_has_no_finalizable_subclasses(context_type(), changes); changes); break; default: witness = NULL; ShouldNotReachHere(); break; } if (witness != NULL) { if (TraceDependencies) { print_dependency(witness, /*verbose=*/ true); } // The following is a no-op unless logging is enabled: log_dependency(witness); + trace_and_log_witness(witness); + return witness; + } + + + klassOop Dependencies::DepStream::check_call_site_dependency(CallSiteDepChange* changes) { + assert_locked_or_safepoint(Compile_lock); + Dependencies::check_valid_dependency_type(type()); + + klassOop witness = NULL; + switch (type()) { + case call_site_target_value: + witness = check_call_site_target_value(context_type(), argument(1), argument(2), changes); + break; + default: + witness = NULL; + break; } + trace_and_log_witness(witness); return witness; } klassOop Dependencies::DepStream::spot_check_dependency_at(DepChange& changes) { if (!changes.involves_context(context_type())) + // Handle klass dependency + if (changes.is_klass_change() && changes.as_klass_change()->involves_context(context_type())) + return check_klass_dependency(changes.as_klass_change()); + + // Handle CallSite dependency + if (changes.is_call_site_change()) + return check_call_site_dependency(changes.as_call_site_change()); + // irrelevant dependency; skip it return NULL; return check_dependency_impl(&changes); } ! void DepChange::initialize() { // entire transaction must be under this lock: assert_lock_strong(Compile_lock); // Mark all dependee and all its superclasses // Mark transitive interfaces ! void DepChange::print() { + int nsup = 0, nint = 0; for (ContextStream str(*this); str.next(); ) { ! klassOop d = str.klass(); assert(!instanceKlass::cast(d)->is_marked_dependent(), "checking"); instanceKlass::cast(d)->set_is_marked_dependent(true); ! klassOop k = str.klass(); + switch (str.change_type()) { + case Change_new_type: + tty->print_cr(" dependee = %s", instanceKlass::cast(k)->external_name()); + break; + case Change_new_sub: + if (!WizardMode) { + ++nsup; + } else { + tty->print_cr(" context super = %s", instanceKlass::cast(k)->external_name()); } } ! DepChange::~DepChange() { // Unmark all dependee and all its superclasses // Unmark transitive interfaces for (ContextStream str(*this); str.next(); ) { klassOop d = str.klass(); ! instanceKlass::cast(d)->set_is_marked_dependent(false); + break; + case Change_new_impl: ! if (!WizardMode) { + ++nint; + } else { + tty->print_cr(" context interface = %s", instanceKlass::cast(k)->external_name()); + } ! break; + } + } + if (nsup + nint != 0) { + tty->print_cr(" context supers = %d, interfaces = %d", nsup, nint); } } ! bool DepChange::involves_context(klassOop k) { if (k == NULL || !Klass::cast(k)->oop_is_instance()) { ! return false; } ! instanceKlass* ik = instanceKlass::cast(k); ! bool is_contained = ik->is_marked_dependent(); assert(is_contained == Klass::cast(new_type())->is_subtype_of(k), "correct marking of potential context types"); return is_contained; ! void DepChange::ContextStream::start() { + klassOop new_type = _changes.is_klass_change() ? _changes.as_klass_change()->new_type() : (klassOop) NULL; ! _change_type = (new_type == NULL ? NO_CHANGE : Start_Klass); + _klass = new_type; ! _ti_base = NULL; ! _ti_index = 0; + _ti_limit = 0; } bool DepChange::ContextStream::next() { switch (_change_type) { case Start_Klass: // initial state; _klass is the new type
*** 1532,1568 **** --- 1585,1625 ---- ShouldNotReachHere(); } return false; } ! void DepChange::print() { int nsup = 0, nint = 0; ! void KlassDepChange::initialize() { + // entire transaction must be under this lock: + assert_lock_strong(Compile_lock); + + // Mark all dependee and all its superclasses + // Mark transitive interfaces for (ContextStream str(*this); str.next(); ) { ! klassOop k = str.klass(); switch (str.change_type()) { case Change_new_type: tty->print_cr(" dependee = %s", instanceKlass::cast(k)->external_name()); break; case Change_new_sub: if (!WizardMode) { ++nsup; } else { tty->print_cr(" context super = %s", instanceKlass::cast(k)->external_name()); } break; case Change_new_impl: if (!WizardMode) { ++nint; } else { tty->print_cr(" context interface = %s", instanceKlass::cast(k)->external_name()); } break; ! klassOop d = str.klass(); + assert(!instanceKlass::cast(d)->is_marked_dependent(), "checking"); + instanceKlass::cast(d)->set_is_marked_dependent(true); } + } + + KlassDepChange::~KlassDepChange() { + // Unmark all dependee and all its superclasses + // Unmark transitive interfaces + for (ContextStream str(*this); str.next(); ) { + klassOop d = str.klass(); + instanceKlass::cast(d)->set_is_marked_dependent(false); } if (nsup + nint != 0) { tty->print_cr(" context supers = %d, interfaces = %d", nsup, nint); + } + + bool KlassDepChange::involves_context(klassOop k) { + if (k == NULL || !Klass::cast(k)->oop_is_instance()) { + return false; } + instanceKlass* ik = instanceKlass::cast(k); + bool is_contained = ik->is_marked_dependent(); + assert(is_contained == Klass::cast(new_type())->is_subtype_of(k), + "correct marking of potential context types"); + return is_contained; } #ifndef PRODUCT void Dependencies::print_statistics() { if (deps_find_witness_print != 0) {

src/share/vm/code/dependencies.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File