8148195: Some InstanceKlass and MethodCounters fields can be excluded when JVMTI is not supported
Summary: Removed "previous version", "cached class file", and breakpoint related fields and code when JVMTI is not supported
Reviewed-by: coleenp, sspitsyn
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/BreakpointInfo.java Thu Apr 21 20:11:40 2016 +0000
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/BreakpointInfo.java Thu Apr 21 20:49:11 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016 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
@@ -46,6 +46,11 @@
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
+ if (!VM.getVM().isJvmtiSupported()) {
+ // no BreakpointInfo support without JVMTI
+ return;
+ }
+
Type type = db.lookupType("BreakpointInfo");
origBytecodeField = type.getCIntegerField("_orig_bytecode");
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Thu Apr 21 20:11:40 2016 +0000
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Thu Apr 21 20:49:11 2016 -0700
@@ -85,7 +85,9 @@
isMarkedDependent = new CIntField(type.getCIntegerField("_is_marked_dependent"), 0);
initState = new CIntField(type.getCIntegerField("_init_state"), 0);
itableLen = new CIntField(type.getCIntegerField("_itable_len"), 0);
- breakpoints = type.getAddressField("_breakpoints");
+ if (VM.getVM().isJvmtiSupported()) {
+ breakpoints = type.getAddressField("_breakpoints");
+ }
genericSignatureIndex = new CIntField(type.getCIntegerField("_generic_signature_index"), 0);
majorVersion = new CIntField(type.getCIntegerField("_major_version"), 0);
minorVersion = new CIntField(type.getCIntegerField("_minor_version"), 0);
@@ -837,6 +839,9 @@
/** Breakpoint support (see methods on Method* for details) */
public BreakpointInfo getBreakpoints() {
+ if (!VM.getVM().isJvmtiSupported()) {
+ return null;
+ }
Address addr = getAddress().getAddressAt(breakpoints.getOffset());
return (BreakpointInfo) VMObjectFactory.newObject(BreakpointInfo.class, addr);
}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java Thu Apr 21 20:11:40 2016 +0000
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java Thu Apr 21 20:49:11 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -87,6 +87,8 @@
private StubRoutines stubRoutines;
private Bytes bytes;
+ /** Flag indicating if JVMTI support is included in the build */
+ private boolean isJvmtiSupported;
/** Flags indicating whether we are attached to a core, C1, or C2 build */
private boolean usingClientCompiler;
private boolean usingServerCompiler;
@@ -336,6 +338,16 @@
stackBias = db.lookupIntConstant("STACK_BIAS").intValue();
invocationEntryBCI = db.lookupIntConstant("InvocationEntryBci").intValue();
+ // We infer the presence of JVMTI from the presence of the InstanceKlass::_breakpoints field.
+ {
+ Type type = db.lookupType("InstanceKlass");
+ if (type.getField("_breakpoints", false, false) == null) {
+ isJvmtiSupported = false;
+ } else {
+ isJvmtiSupported = true;
+ }
+ }
+
// We infer the presence of C1 or C2 from a couple of fields we
// already have present in the type database
{
@@ -701,6 +713,11 @@
return isBigEndian;
}
+ /** Returns true if JVMTI is supported, false otherwise */
+ public boolean isJvmtiSupported() {
+ return isJvmtiSupported;
+ }
+
/** Returns true if this is a "core" build, false if either C1 or C2
is present */
public boolean isCore() {
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Thu Apr 21 20:11:40 2016 +0000
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Thu Apr 21 20:49:11 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -202,6 +202,7 @@
_code = (address)arena->Amalloc(code_size());
memcpy(_code, me->code_base(), code_size());
+#if INCLUDE_JVMTI
// Revert any breakpoint bytecodes in ci's copy
if (me->number_of_breakpoints() > 0) {
BreakpointInfo* bp = me->method_holder()->breakpoints();
@@ -211,6 +212,7 @@
}
}
}
+#endif
// And load the exception table.
ExceptionTable exc_table(me);
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Apr 21 20:11:40 2016 +0000
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Apr 21 20:49:11 2016 -0700
@@ -2032,10 +2032,11 @@
return (old_state != is_in_error_state());
}
+#if INCLUDE_JVMTI
static void clear_all_breakpoints(Method* m) {
m->clear_all_breakpoints();
}
-
+#endif
void InstanceKlass::notify_unload_class(InstanceKlass* ik) {
// notify the debugger
@@ -2097,6 +2098,7 @@
// DC::remove_all_dependents() when it touches unloaded nmethod.
dependencies().wipe();
+#if INCLUDE_JVMTI
// Deallocate breakpoint records
if (breakpoints() != 0x0) {
methods_do(clear_all_breakpoints);
@@ -2108,6 +2110,7 @@
os::free(_cached_class_file);
_cached_class_file = NULL;
}
+#endif
// Decrement symbol reference counts associated with the unloaded class.
if (_name != NULL) _name->decrement_refcount();
@@ -2841,7 +2844,7 @@
{
bool have_pv = false;
// previous versions are linked together through the InstanceKlass
- for (InstanceKlass* pv_node = _previous_versions;
+ for (InstanceKlass* pv_node = previous_versions();
pv_node != NULL;
pv_node = pv_node->previous_versions()) {
if (!have_pv)
@@ -3334,7 +3337,7 @@
}
#endif
-
+#if INCLUDE_JVMTI
// RedefineClasses() support for previous versions:
int InstanceKlass::_previous_version_count = 0;
@@ -3549,6 +3552,7 @@
_previous_version_count++;
} // end add_previous_version()
+#endif // INCLUDE_JVMTI
Method* InstanceKlass::method_with_idnum(int idnum) {
Method* m = NULL;
@@ -3598,7 +3602,7 @@
return method;
}
-
+#if INCLUDE_JVMTI
jint InstanceKlass::get_cached_class_file_len() {
return VM_RedefineClasses::get_cached_class_file_len(_cached_class_file);
}
@@ -3606,3 +3610,4 @@
unsigned char * InstanceKlass::get_cached_class_file_bytes() {
return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
}
+#endif
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Apr 21 20:11:40 2016 +0000
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Apr 21 20:49:11 2016 -0700
@@ -57,7 +57,9 @@
// forward declaration for class -- see below for definition
+#if INCLUDE_JVMTI
class BreakpointInfo;
+#endif
class ClassFileParser;
class KlassDepChange;
class DependencyContext;
@@ -230,12 +232,14 @@
jmethodID* _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none
intptr_t _dep_context; // packed DependencyContext structure
nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class
+#if INCLUDE_JVMTI
BreakpointInfo* _breakpoints; // bpt lists, managed by Method*
// Linked instanceKlasses of previous versions
InstanceKlass* _previous_versions;
// JVMTI fields can be moved to their own structure - see 6315920
// JVMTI: cached class file, before retransformable agent modified it in CFLH
JvmtiCachedClassFileData* _cached_class_file;
+#endif
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
@@ -245,7 +249,9 @@
u1 _init_state; // state of class
u1 _reference_type; // reference type
+#if INCLUDE_JVMTI
JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration
+#endif
NOT_PRODUCT(int _verify_count;) // to avoid redundant verifies
@@ -687,10 +693,14 @@
_nonstatic_oop_map_size = words;
}
+#if INCLUDE_JVMTI
// RedefineClasses() support for previous versions:
void add_previous_version(instanceKlassHandle ikh, int emcp_method_count);
InstanceKlass* previous_versions() const { return _previous_versions; }
+#else
+ InstanceKlass* previous_versions() const { return NULL; }
+#endif
InstanceKlass* get_klass_version(int version) {
for (InstanceKlass* ik = this; ik != NULL; ik = ik->previous_versions()) {
@@ -738,6 +748,8 @@
bool is_mirror_instance_klass() const { return is_kind(_misc_kind_mirror); }
bool is_class_loader_instance_klass() const { return is_kind(_misc_kind_class_loader); }
+#if INCLUDE_JVMTI
+
void init_previous_versions() {
_previous_versions = NULL;
}
@@ -764,6 +776,16 @@
return _jvmti_cached_class_field_map;
}
+#else // INCLUDE_JVMTI
+
+ static void purge_previous_versions(InstanceKlass* ik) { return; };
+ static bool has_previous_versions() { return false; }
+
+ void set_cached_class_file(JvmtiCachedClassFileData *data) { ShouldNotReachHere(); }
+ JvmtiCachedClassFileData * get_cached_class_file() { return (JvmtiCachedClassFileData *)NULL; }
+
+#endif // INCLUDE_JVMTI
+
bool has_default_methods() const {
return (_misc_flags & _misc_has_default_methods) != 0;
}
@@ -882,9 +904,11 @@
int mark_osr_nmethods(const Method* m);
nmethod* lookup_osr_nmethod(const Method* m, int bci, int level, bool match_level) const;
+#if INCLUDE_JVMTI
// Breakpoint support (see methods on Method* for details)
BreakpointInfo* breakpoints() const { return _breakpoints; };
void set_breakpoints(BreakpointInfo* bps) { _breakpoints = bps; };
+#endif
// support for stub routines
static ByteSize init_state_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_state)); }
@@ -1253,9 +1277,11 @@
// Free CHeap allocated fields.
void release_C_heap_structures();
+#if INCLUDE_JVMTI
// RedefineClasses support
void link_previous_versions(InstanceKlass* pv) { _previous_versions = pv; }
void mark_newly_obsolete_methods(Array<Method*>* old_methods, int emcp_method_count);
+#endif
public:
// CDS support - remove and restore oops from metadata. Oops are not shared.
virtual void remove_unshareable_info();
--- a/hotspot/src/share/vm/oops/method.cpp Thu Apr 21 20:11:40 2016 +0000
+++ b/hotspot/src/share/vm/oops/method.cpp Thu Apr 21 20:49:11 2016 -0700
@@ -1639,6 +1639,7 @@
return true;
}
+#if INCLUDE_JVMTI
Bytecodes::Code Method::orig_bytecode_at(int bci) const {
BreakpointInfo* bp = method_holder()->breakpoints();
@@ -1719,6 +1720,7 @@
clear_matches(this, -1);
}
+#endif // INCLUDE_JVMTI
int Method::invocation_count() {
MethodCounters *mcs = method_counters();
@@ -1784,6 +1786,8 @@
}
}
+#if INCLUDE_JVMTI
+
BreakpointInfo::BreakpointInfo(Method* m, int bci) {
_bci = bci;
_name_index = m->name_index();
@@ -1821,6 +1825,8 @@
method->decr_number_of_breakpoints(Thread::current());
}
+#endif // INCLUDE_JVMTI
+
// jmethodID handling
// This is a block allocating object, sort of like JNIHandleBlock, only a
--- a/hotspot/src/share/vm/oops/method.hpp Thu Apr 21 20:11:40 2016 +0000
+++ b/hotspot/src/share/vm/oops/method.hpp Thu Apr 21 20:49:11 2016 -0700
@@ -195,8 +195,18 @@
}
// JVMTI breakpoints
+#if !INCLUDE_JVMTI
+ Bytecodes::Code orig_bytecode_at(int bci) const {
+ ShouldNotReachHere();
+ return Bytecodes::_shouldnotreachhere;
+ }
+ void set_orig_bytecode_at(int bci, Bytecodes::Code code) {
+ ShouldNotReachHere();
+ };
+ u2 number_of_breakpoints() const {return 0;}
+#else // !INCLUDE_JVMTI
Bytecodes::Code orig_bytecode_at(int bci) const;
- void set_orig_bytecode_at(int bci, Bytecodes::Code code);
+ void set_orig_bytecode_at(int bci, Bytecodes::Code code);
void set_breakpoint(int bci);
void clear_breakpoint(int bci);
void clear_all_breakpoints();
@@ -229,6 +239,7 @@
mcs->clear_number_of_breakpoints();
}
}
+#endif // !INCLUDE_JVMTI
// index into InstanceKlass methods() array
// note: also used by jfr
@@ -1046,6 +1057,8 @@
};
+#if INCLUDE_JVMTI
+
/// Fast Breakpoints.
// If this structure gets more complicated (because bpts get numerous),
@@ -1090,6 +1103,8 @@
void clear(Method* method);
};
+#endif // INCLUDE_JVMTI
+
// Utility class for access exception handlers
class ExceptionTable : public StackObj {
private:
--- a/hotspot/src/share/vm/oops/methodCounters.hpp Thu Apr 21 20:11:40 2016 +0000
+++ b/hotspot/src/share/vm/oops/methodCounters.hpp Thu Apr 21 20:49:11 2016 -0700
@@ -38,7 +38,9 @@
int _interpreter_invocation_count; // Count of times invoked (reused as prev_event_count in tiered)
u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
#endif
+#if INCLUDE_JVMTI
u2 _number_of_breakpoints; // fullspeed debugging support
+#endif
InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations
InvocationCounter _backedge_counter; // Incremented before each backedge taken - used to trigger frequencey-based optimizations
// NMethod age is a counter for warm methods detection in the code cache sweeper.
@@ -62,8 +64,7 @@
u1 _highest_osr_comp_level; // Same for OSR level
#endif
- MethodCounters(methodHandle mh) : _number_of_breakpoints(0),
- _nmethod_age(INT_MAX)
+ MethodCounters(methodHandle mh) : _nmethod_age(INT_MAX)
#ifdef TIERED
, _rate(0),
_prev_time(0),
@@ -73,6 +74,7 @@
{
set_interpreter_invocation_count(0);
set_interpreter_throwout_count(0);
+ JVMTI_ONLY(clear_number_of_breakpoints());
invocation_counter()->init();
backedge_counter()->init();
@@ -153,10 +155,12 @@
#endif // defined(COMPILER2) || INCLUDE_JVMCI
+#if INCLUDE_JVMTI
u2 number_of_breakpoints() const { return _number_of_breakpoints; }
void incr_number_of_breakpoints() { ++_number_of_breakpoints; }
void decr_number_of_breakpoints() { --_number_of_breakpoints; }
void clear_number_of_breakpoints() { _number_of_breakpoints = 0; }
+#endif
#ifdef TIERED
jlong prev_time() const { return _prev_time; }
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Apr 21 20:11:40 2016 +0000
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Apr 21 20:49:11 2016 -0700
@@ -337,7 +337,7 @@
volatile_nonstatic_field(InstanceKlass, _oop_map_cache, OopMapCache*) \
nonstatic_field(InstanceKlass, _jni_ids, JNIid*) \
nonstatic_field(InstanceKlass, _osr_nmethods_head, nmethod*) \
- nonstatic_field(InstanceKlass, _breakpoints, BreakpointInfo*) \
+ JVMTI_ONLY(nonstatic_field(InstanceKlass, _breakpoints, BreakpointInfo*)) \
nonstatic_field(InstanceKlass, _generic_signature_index, u2) \
nonstatic_field(InstanceKlass, _methods_jmethod_ids, jmethodID*) \
volatile_nonstatic_field(InstanceKlass, _idnum_allocated_count, u2) \
@@ -387,7 +387,7 @@
nonstatic_field(MethodCounters, _backedge_mask, int) \
COMPILER2_OR_JVMCI_PRESENT(nonstatic_field(MethodCounters, _interpreter_invocation_count, int)) \
COMPILER2_OR_JVMCI_PRESENT(nonstatic_field(MethodCounters, _interpreter_throwout_count, u2)) \
- nonstatic_field(MethodCounters, _number_of_breakpoints, u2) \
+ JVMTI_ONLY(nonstatic_field(MethodCounters, _number_of_breakpoints, u2)) \
nonstatic_field(MethodCounters, _invocation_counter, InvocationCounter) \
nonstatic_field(MethodCounters, _backedge_counter, InvocationCounter) \
nonstatic_field(Method, _constMethod, ConstMethod*) \
@@ -447,11 +447,11 @@
nonstatic_field(ExceptionTableElement, end_pc, u2) \
nonstatic_field(ExceptionTableElement, handler_pc, u2) \
nonstatic_field(ExceptionTableElement, catch_type_index, u2) \
- nonstatic_field(BreakpointInfo, _orig_bytecode, Bytecodes::Code) \
- nonstatic_field(BreakpointInfo, _bci, int) \
- nonstatic_field(BreakpointInfo, _name_index, u2) \
- nonstatic_field(BreakpointInfo, _signature_index, u2) \
- nonstatic_field(BreakpointInfo, _next, BreakpointInfo*) \
+ JVMTI_ONLY(nonstatic_field(BreakpointInfo, _orig_bytecode, Bytecodes::Code)) \
+ JVMTI_ONLY(nonstatic_field(BreakpointInfo, _bci, int)) \
+ JVMTI_ONLY(nonstatic_field(BreakpointInfo, _name_index, u2)) \
+ JVMTI_ONLY(nonstatic_field(BreakpointInfo, _signature_index, u2)) \
+ JVMTI_ONLY(nonstatic_field(BreakpointInfo, _next, BreakpointInfo*)) \
/***********/ \
/* JNI IDs */ \
/***********/ \