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