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

src/share/vm/code/dependencies.hpp

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 23,44 **** */ #ifndef SHARE_VM_CODE_DEPENDENCIES_HPP #define SHARE_VM_CODE_DEPENDENCIES_HPP #include "ci/ciKlass.hpp" #include "code/compressedStream.hpp" #include "code/nmethod.hpp" #include "utilities/growableArray.hpp" //** Dependencies represent assertions (approximate invariants) within ! // the class hierarchy. An example is an assertion that a given ! // method is not overridden; another example is that a type has only ! // one concrete subtype. Compiled code which relies on such ! // assertions must be discarded if they are overturned by changes in ! // the class hierarchy. We can think of these assertions as ! // approximate invariants, because we expect them to be overturned // very infrequently. We are willing to perform expensive recovery // operations when they are overturned. The benefit, of course, is // performing optimistic optimizations (!) on the object code. // // Changes in the class hierarchy due to dynamic linking or --- 23,47 ---- */ #ifndef SHARE_VM_CODE_DEPENDENCIES_HPP #define SHARE_VM_CODE_DEPENDENCIES_HPP + #include "ci/ciCallSite.hpp" #include "ci/ciKlass.hpp" + #include "ci/ciMethodHandle.hpp" + #include "classfile/systemDictionary.hpp" #include "code/compressedStream.hpp" #include "code/nmethod.hpp" #include "utilities/growableArray.hpp" //** Dependencies represent assertions (approximate invariants) within ! // the runtime system, e.g. class hierarchy changes. An example is an ! // assertion that a given method is not overridden; another example is ! // that a type has only one concrete subtype. Compiled code which ! // relies on such assertions must be discarded if they are overturned ! // by changes in the runtime system. We can think of these assertions ! // as approximate invariants, because we expect them to be overturned // very infrequently. We are willing to perform expensive recovery // operations when they are overturned. The benefit, of course, is // performing optimistic optimizations (!) on the object code. // // Changes in the class hierarchy due to dynamic linking or
*** 50,59 **** --- 53,64 ---- class nmethod; class OopRecorder; class xmlStream; class CompileLog; class DepChange; + class KlassDepChange; + class CallSiteDepChange; class No_Safepoint_Verifier; class Dependencies: public ResourceObj { public: // Note: In the comments on dependency types, most uses of the terms
*** 150,159 **** --- 155,167 ---- // This dependency asserts that no instances of class or it's // subclasses require finalization registration. no_finalizable_subclasses, + // This dependency asserts when the CallSite.target value changed. + call_site_target_value, + TYPE_LIMIT }; enum { LG2_TYPE_LIMIT = 4, // assert(TYPE_LIMIT <= (1<<LG2_TYPE_LIMIT))
*** 177,186 **** --- 185,195 ---- static const char* dep_name(DepType dept); static int dep_args(DepType dept); static int dep_context_arg(DepType dept) { return dept_in_mask(dept, ctxk_types)? 0: -1; } + static void check_valid_dependency_type(DepType dept); private: // State for writing a new set of dependencies: GrowableArray<int>* _dep_seen; // (seen[h->ident] & (1<<dept)) GrowableArray<ciObject*>* _deps[TYPE_LIMIT];
*** 253,262 **** --- 262,272 ---- void assert_concrete_with_no_concrete_subtype(ciKlass* ctxk); void assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm); void assert_abstract_with_exclusive_concrete_subtypes(ciKlass* ctxk, ciKlass* k1, ciKlass* k2); void assert_exclusive_concrete_methods(ciKlass* ctxk, ciMethod* m1, ciMethod* m2); void assert_has_no_finalizable_subclasses(ciKlass* ctxk); + void assert_call_site_target_value(ciKlass* ctxk, ciCallSite* call_site, ciMethodHandle* method_handle); // Define whether a given method or type is concrete. // These methods define the term "concrete" as used in this module. // For this module, an "abstract" class is one which is non-concrete. //
*** 294,316 **** // Checking old assertions at run-time (in the VM only): static klassOop check_evol_method(methodOop m); static klassOop check_leaf_type(klassOop ctxk); static klassOop check_abstract_with_unique_concrete_subtype(klassOop ctxk, klassOop conck, ! DepChange* changes = NULL); static klassOop check_abstract_with_no_concrete_subtype(klassOop ctxk, ! DepChange* changes = NULL); static klassOop check_concrete_with_no_concrete_subtype(klassOop ctxk, ! DepChange* changes = NULL); static klassOop check_unique_concrete_method(klassOop ctxk, methodOop uniqm, ! DepChange* changes = NULL); static klassOop check_abstract_with_exclusive_concrete_subtypes(klassOop ctxk, klassOop k1, klassOop k2, ! DepChange* changes = NULL); static klassOop check_exclusive_concrete_methods(klassOop ctxk, methodOop m1, methodOop m2, ! DepChange* changes = NULL); ! static klassOop check_has_no_finalizable_subclasses(klassOop ctxk, ! DepChange* changes = NULL); // A returned klassOop is NULL if the dependency assertion is still // valid. A non-NULL klassOop is a 'witness' to the assertion // failure, a point in the class hierarchy where the assertion has // been proven false. For example, if check_leaf_type returns // non-NULL, the value is a subtype of the supposed leaf type. This --- 304,326 ---- // Checking old assertions at run-time (in the VM only): static klassOop check_evol_method(methodOop m); static klassOop check_leaf_type(klassOop ctxk); static klassOop check_abstract_with_unique_concrete_subtype(klassOop ctxk, klassOop conck, ! KlassDepChange* changes = NULL); static klassOop check_abstract_with_no_concrete_subtype(klassOop ctxk, ! KlassDepChange* changes = NULL); static klassOop check_concrete_with_no_concrete_subtype(klassOop ctxk, ! KlassDepChange* changes = NULL); static klassOop check_unique_concrete_method(klassOop ctxk, methodOop uniqm, ! KlassDepChange* changes = NULL); static klassOop check_abstract_with_exclusive_concrete_subtypes(klassOop ctxk, klassOop k1, klassOop k2, ! KlassDepChange* changes = NULL); static klassOop check_exclusive_concrete_methods(klassOop ctxk, methodOop m1, methodOop m2, ! KlassDepChange* changes = NULL); ! static klassOop check_has_no_finalizable_subclasses(klassOop ctxk, KlassDepChange* changes = NULL); ! static klassOop check_call_site_target_value(klassOop ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes = NULL); // A returned klassOop is NULL if the dependency assertion is still // valid. A non-NULL klassOop is a 'witness' to the assertion // failure, a point in the class hierarchy where the assertion has // been proven false. For example, if check_leaf_type returns // non-NULL, the value is a subtype of the supposed leaf type. This
*** 413,423 **** void initial_asserts(size_t byte_limit) NOT_DEBUG({}); inline oop recorded_oop_at(int i); // => _code? _code->oop_at(i): *_deps->_oop_recorder->handle_at(i) ! klassOop check_dependency_impl(DepChange* changes); public: DepStream(Dependencies* deps) : _deps(deps), _code(NULL), --- 423,436 ---- void initial_asserts(size_t byte_limit) NOT_DEBUG({}); inline oop recorded_oop_at(int i); // => _code? _code->oop_at(i): *_deps->_oop_recorder->handle_at(i) ! klassOop check_klass_dependency(KlassDepChange* changes); ! klassOop check_call_site_dependency(CallSiteDepChange* changes); ! ! void trace_and_log_witness(klassOop witness); public: DepStream(Dependencies* deps) : _deps(deps), _code(NULL),
*** 451,464 **** oop x = argument(i); assert(x->is_klass(), "type"); return (klassOop) x; } ! // The point of the whole exercise: Is this dep is still OK? klassOop check_dependency() { ! return check_dependency_impl(NULL); } // A lighter version: Checks only around recent changes in a class // hierarchy. (See Universe::flush_dependents_on.) klassOop spot_check_dependency_at(DepChange& changes); // Log the current dependency to xtty or compilation log. --- 464,480 ---- oop x = argument(i); assert(x->is_klass(), "type"); return (klassOop) x; } ! // The point of the whole exercise: Is this dep still OK? klassOop check_dependency() { ! klassOop result = check_klass_dependency(NULL); ! if (result != NULL) return result; ! return check_call_site_dependency(NULL); } + // A lighter version: Checks only around recent changes in a class // hierarchy. (See Universe::flush_dependents_on.) klassOop spot_check_dependency_at(DepChange& changes); // Log the current dependency to xtty or compilation log.
*** 470,517 **** friend class Dependencies::DepStream; static void print_statistics() PRODUCT_RETURN; }; ! // A class hierarchy change coming through the VM (under the Compile_lock). ! // The change is structured as a single new type with any number of supers ! // and implemented interface types. Other than the new type, any of the ! // super types can be context types for a relevant dependency, which the ! // new type could invalidate. class DepChange : public StackObj { public: enum ChangeType { NO_CHANGE = 0, // an uninvolved klass Change_new_type, // a newly loaded type Change_new_sub, // a super with a new subtype Change_new_impl, // an interface with a new implementation CHANGE_LIMIT, Start_Klass = CHANGE_LIMIT // internal indicator for ContextStream }; - private: - // each change set is rooted in exactly one new type (at present): - KlassHandle _new_type; - - void initialize(); - - public: - // notes the new type, marks it and all its super-types - DepChange(KlassHandle new_type) - : _new_type(new_type) - { - initialize(); - } - - // cleans up the marks - ~DepChange(); - - klassOop new_type() { return _new_type(); } - - // involves_context(k) is true if k is new_type or any of the super types - bool involves_context(klassOop k); - // Usage: // for (DepChange::ContextStream str(changes); str.next(); ) { // klassOop k = str.klass(); // switch (str.change_type()) { // ... --- 486,525 ---- friend class Dependencies::DepStream; static void print_statistics() PRODUCT_RETURN; }; ! ! // Every particular DepChange is a sub-class of this class. class DepChange : public StackObj { public: + // What kind of DepChange is this? + virtual bool is_klass_change() const { return false; } + virtual bool is_call_site_change() const { return false; } + + // Subclass casting with assertions. + KlassDepChange* as_klass_change() { + assert(is_klass_change(), "bad cast"); + return (KlassDepChange*) this; + } + CallSiteDepChange* as_call_site_change() { + assert(is_call_site_change(), "bad cast"); + return (CallSiteDepChange*) this; + } + + void print(); + + public: enum ChangeType { NO_CHANGE = 0, // an uninvolved klass Change_new_type, // a newly loaded type Change_new_sub, // a super with a new subtype Change_new_impl, // an interface with a new implementation CHANGE_LIMIT, Start_Klass = CHANGE_LIMIT // internal indicator for ContextStream }; // Usage: // for (DepChange::ContextStream str(changes); str.next(); ) { // klassOop k = str.klass(); // switch (str.change_type()) { // ...
*** 528,545 **** objArrayOop _ti_base; // i.e., transitive_interfaces int _ti_index; int _ti_limit; // start at the beginning: ! void start() { ! klassOop new_type = _changes.new_type(); ! _change_type = (new_type == NULL ? NO_CHANGE: Start_Klass); ! _klass = new_type; ! _ti_base = NULL; ! _ti_index = 0; ! _ti_limit = 0; ! } public: ContextStream(DepChange& changes) : _changes(changes) { start(); } --- 536,546 ---- objArrayOop _ti_base; // i.e., transitive_interfaces int _ti_index; int _ti_limit; // start at the beginning: ! void start(); public: ContextStream(DepChange& changes) : _changes(changes) { start(); }
*** 553,562 **** ChangeType change_type() { return _change_type; } klassOop klass() { return _klass; } }; friend class DepChange::ContextStream; ! void print(); }; #endif // SHARE_VM_CODE_DEPENDENCIES_HPP --- 554,617 ---- ChangeType change_type() { return _change_type; } klassOop klass() { return _klass; } }; friend class DepChange::ContextStream; + }; ! ! // A class hierarchy change coming through the VM (under the Compile_lock). ! // The change is structured as a single new type with any number of supers ! // and implemented interface types. Other than the new type, any of the ! // super types can be context types for a relevant dependency, which the ! // new type could invalidate. ! class KlassDepChange : public DepChange { ! private: ! // each change set is rooted in exactly one new type (at present): ! KlassHandle _new_type; ! ! void initialize(); ! ! public: ! // notes the new type, marks it and all its super-types ! KlassDepChange(KlassHandle new_type) ! : _new_type(new_type) ! { ! initialize(); ! } ! ! // cleans up the marks ! ~KlassDepChange(); ! ! // What kind of DepChange is this? ! virtual bool is_klass_change() const { return true; } ! ! klassOop new_type() { return _new_type(); } ! ! // involves_context(k) is true if k is new_type or any of the super types ! bool involves_context(klassOop k); ! }; ! ! ! // A CallSite has changed its target. ! class CallSiteDepChange : public DepChange { ! private: ! Handle _call_site; ! Handle _method_handle; ! ! public: ! CallSiteDepChange(Handle call_site, Handle method_handle) ! : _call_site(call_site), ! _method_handle(method_handle) ! { ! assert(_call_site() ->is_a(SystemDictionary::CallSite_klass()), "must be"); ! assert(_method_handle()->is_a(SystemDictionary::MethodHandle_klass()), "must be"); ! } ! ! // What kind of DepChange is this? ! virtual bool is_call_site_change() const { return true; } ! ! oop call_site() const { return _call_site(); } ! oop method_handle() const { return _method_handle(); } }; #endif // SHARE_VM_CODE_DEPENDENCIES_HPP
src/share/vm/code/dependencies.hpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File