vmIntrinsics::ID vmIntrinsics::for_boxing(BasicType type) {
return wrapper_intrinsic(type, false);
}
vmIntrinsics::ID vmIntrinsics::for_unboxing(BasicType type) {
return wrapper_intrinsic(type, true);
}
vmIntrinsics::ID vmIntrinsics::for_raw_conversion(BasicType src, BasicType dest) {
#define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d))
switch (SRC_DEST(src, dest)) {
case SRC_DEST(T_INT, T_FLOAT): return vmIntrinsics::_intBitsToFloat;
case SRC_DEST(T_FLOAT, T_INT): return vmIntrinsics::_floatToRawIntBits;
case SRC_DEST(T_LONG, T_DOUBLE): return vmIntrinsics::_longBitsToDouble;
case SRC_DEST(T_DOUBLE, T_LONG): return vmIntrinsics::_doubleToRawLongBits;
}
#undef SRC_DEST
return vmIntrinsics::_none;
}
bool vmIntrinsics::should_be_pinned(vmIntrinsics::ID id) {
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
switch(id) {
#ifdef JFR_HAVE_INTRINSICS
case vmIntrinsics::_counterTime:
#endif
case vmIntrinsics::_currentTimeMillis:
case vmIntrinsics::_nanoTime:
return true;
default:
return false;
}
}
#define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0"
static const char* vm_intrinsic_name_bodies =
VM_INTRINSICS_DO(VM_INTRINSIC_INITIALIZE,
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
static const char* vm_intrinsic_name_table[vmIntrinsics::ID_LIMIT];
const char* vmIntrinsics::name_at(vmIntrinsics::ID id) {
const char** nt = &vm_intrinsic_name_table[0];
if (nt[_none] == NULL) {
char* string = (char*) &vm_intrinsic_name_bodies[0];
for (int index = FIRST_ID; index < ID_LIMIT; index++) {
nt[index] = string;
string += strlen(string); // skip string body
string += 1; // skip trailing null
}
assert(!strcmp(nt[_hashCode], "_hashCode"), "lined up");
nt[_none] = "_none";
}
if ((uint)id < (uint)ID_LIMIT)
return vm_intrinsic_name_table[(uint)id];
else
return "(unknown intrinsic)";
}
inline bool match_F_R(jshort flags) {
const int req = 0;
const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED;
return (flags & (req | neg)) == req;
}
inline bool match_F_Y(jshort flags) {
const int req = JVM_ACC_SYNCHRONIZED;
const int neg = JVM_ACC_STATIC;
return (flags & (req | neg)) == req;
}
inline bool match_F_RN(jshort flags) {
const int req = JVM_ACC_NATIVE;
const int neg = JVM_ACC_STATIC | JVM_ACC_SYNCHRONIZED;
return (flags & (req | neg)) == req;
}
inline bool match_F_S(jshort flags) {
const int req = JVM_ACC_STATIC;
const int neg = JVM_ACC_SYNCHRONIZED;
return (flags & (req | neg)) == req;
}
inline bool match_F_SN(jshort flags) {
const int req = JVM_ACC_STATIC | JVM_ACC_NATIVE;
const int neg = JVM_ACC_SYNCHRONIZED;
return (flags & (req | neg)) == req;
}
inline bool match_F_RNY(jshort flags) {
const int req = JVM_ACC_NATIVE | JVM_ACC_SYNCHRONIZED;
const int neg = JVM_ACC_STATIC;
return (flags & (req | neg)) == req;
}
#define ID3(x, y, z) (( jlong)(z) + \
((jlong)(y) << vmSymbols::log2_SID_LIMIT) + \
((jlong)(x) << (2*vmSymbols::log2_SID_LIMIT)) )
#define SID_ENUM(n) vmSymbols::VM_SYMBOL_ENUM_NAME(n)
vmIntrinsics::ID vmIntrinsics::find_id_impl(vmSymbols::SID holder,
vmSymbols::SID name,
vmSymbols::SID sig,
jshort flags) {
assert((int)vmSymbols::SID_LIMIT <= (1<<vmSymbols::log2_SID_LIMIT), "must fit");
#define VM_INTRINSIC_CASE(id, klass, name, sig, fcode) \
case ID3(SID_ENUM(klass), SID_ENUM(name), SID_ENUM(sig)): \
if (!match_##fcode(flags)) break; \
return id;
switch (ID3(holder, name, sig)) {
VM_INTRINSICS_DO(VM_INTRINSIC_CASE,
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
}
return vmIntrinsics::_none;
#undef VM_INTRINSIC_CASE
}
const char* vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID id, char* buf, int buflen) {
const char* str = name_at(id);
#ifndef PRODUCT
const char* kname = vmSymbols::name_for(class_for(id));
const char* mname = vmSymbols::name_for(name_for(id));
const char* sname = vmSymbols::name_for(signature_for(id));
const char* fname = "";
switch (flags_for(id)) {
case F_Y: fname = "synchronized "; break;
case F_RN: fname = "native "; break;
case F_SN: fname = "native static "; break;
case F_S: fname = "static "; break;
case F_RNY:fname = "native synchronized "; break;
}
const char* kptr = strrchr(kname, '/');
if (kptr != NULL) kname = kptr + 1;
int len = jio_snprintf(buf, buflen, "%s: %s%s.%s%s",
str, fname, kname, mname, sname);
if (len < buflen)
str = buf;
#endif //PRODUCT
return str;
}
#define ID4(x, y, z, f) ((ID3(x, y, z) << vmIntrinsics::log2_FLAG_LIMIT) | (jlong) (f))
static const jlong intrinsic_info_array[vmIntrinsics::ID_LIMIT+1] = {
#define VM_INTRINSIC_INFO(ignore_id, klass, name, sig, fcode) \
ID4(SID_ENUM(klass), SID_ENUM(name), SID_ENUM(sig), vmIntrinsics::fcode),
0, VM_INTRINSICS_DO(VM_INTRINSIC_INFO,
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE)
0
#undef VM_INTRINSIC_INFO
};
inline jlong intrinsic_info(vmIntrinsics::ID id) {
return intrinsic_info_array[vmIntrinsics::ID_from((int)id)];
}
vmSymbols::SID vmIntrinsics::class_for(vmIntrinsics::ID id) {
jlong info = intrinsic_info(id);
int shift = 2*vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1021, "");
return vmSymbols::SID( (info >> shift) & mask );
}
vmSymbols::SID vmIntrinsics::name_for(vmIntrinsics::ID id) {
jlong info = intrinsic_info(id);
int shift = vmSymbols::log2_SID_LIMIT + log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1022, "");
return vmSymbols::SID( (info >> shift) & mask );
}
vmSymbols::SID vmIntrinsics::signature_for(vmIntrinsics::ID id) {
jlong info = intrinsic_info(id);
int shift = log2_FLAG_LIMIT, mask = right_n_bits(vmSymbols::log2_SID_LIMIT);
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 1023, "");
return vmSymbols::SID( (info >> shift) & mask );
}
vmIntrinsics::Flags vmIntrinsics::flags_for(vmIntrinsics::ID id) {
jlong info = intrinsic_info(id);
int shift = 0, mask = right_n_bits(log2_FLAG_LIMIT);
assert(((ID4(1021,1022,1023,15) >> shift) & mask) == 15, "");
return Flags( (info >> shift) & mask );
}
#ifndef PRODUCT
static bool match_method(Method* m, Symbol* n, Symbol* s) {
return (m->name() == n &&
m->signature() == s);
}
static vmIntrinsics::ID match_method_with_klass(Method* m, Symbol* mk) {
#define VM_INTRINSIC_MATCH(id, klassname, namepart, sigpart, flags) \
{ Symbol* k = vmSymbols::klassname(); \
if (mk == k) { \
Symbol* n = vmSymbols::namepart(); \
Symbol* s = vmSymbols::sigpart(); \
if (match_method(m, n, s)) \
return vmIntrinsics::id; \
} }
VM_INTRINSICS_DO(VM_INTRINSIC_MATCH,
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE);
return vmIntrinsics::_none;
#undef VM_INTRINSIC_MATCH
}
void vmIntrinsics::verify_method(ID actual_id, Method* m) {
Symbol* mk = m->method_holder()->name();
ID declared_id = match_method_with_klass(m, mk);
if (declared_id == actual_id) return; // success
if (declared_id == _none && actual_id != _none && mk == vmSymbols::java_lang_StrictMath()) {
switch (actual_id) {
case _min:
case _max:
case _dsqrt:
declared_id = match_method_with_klass(m, vmSymbols::java_lang_Math());
if (declared_id == actual_id) return; // acceptable alias
break;
}
}
const char* declared_name = name_at(declared_id);
const char* actual_name = name_at(actual_id);
methodHandle mh = m;
m = NULL;
ttyLocker ttyl;
if (xtty != NULL) {
xtty->begin_elem("intrinsic_misdeclared actual='%s' declared='%s'",
actual_name, declared_name);
xtty->method(mh);
xtty->end_elem("%s", "");
}
if (PrintMiscellaneous && (WizardMode || Verbose)) {
tty->print_cr("*** misidentified method; %s(%d) should be %s(%d):",
declared_name, declared_id, actual_name, actual_id);
mh()->print_short_name(tty);
tty->cr();
}
}
#endif //PRODUCT
C:\hotspot-69087d08d473\src\share\vm/classfile/vmSymbols.hpp
#ifndef SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
#define SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
#include "jfr/support/jfrIntrinsics.hpp"
#include "memory/iterator.hpp"
#include "oops/symbol.hpp"
#include "utilities/macros.hpp"
#define VM_SYMBOL_ENUM_NAME(name) name##_enum
#define VM_INTRINSIC_IGNORE(id, class, name, sig, flags) /*ignored*/
#define VM_SYMBOL_IGNORE(id, name) /*ignored*/
#define VM_ALIAS_IGNORE(id, id2) /*ignored*/
#define VM_SYMBOLS_DO(template, do_alias) \
template(java_lang_System, "java/lang/System") \
template(java_lang_Object, "java/lang/Object") \
template(java_lang_Class, "java/lang/Class") \
template(java_lang_String, "java/lang/String") \
template(java_lang_Thread, "java/lang/Thread") \
template(java_lang_ThreadGroup, "java/lang/ThreadGroup") \
template(java_lang_Cloneable, "java/lang/Cloneable") \
template(java_lang_Throwable, "java/lang/Throwable") \
template(java_lang_ClassLoader, "java/lang/ClassLoader") \
template(java_lang_ClassLoader_NativeLibrary, "java/lang/ClassLoader\x024NativeLibrary") \
template(java_lang_ThreadDeath, "java/lang/ThreadDeath") \
template(java_lang_Boolean, "java/lang/Boolean") \
template(java_lang_Character, "java/lang/Character") \
template(java_lang_Character_CharacterCache, "java/lang/Character$CharacterCache") \
template(java_lang_Float, "java/lang/Float") \
template(java_lang_Double, "java/lang/Double") \
template(java_lang_Byte, "java/lang/Byte") \
template(java_lang_Byte_ByteCache, "java/lang/Byte$ByteCache") \
template(java_lang_Short, "java/lang/Short") \
template(java_lang_Short_ShortCache, "java/lang/Short$ShortCache") \
template(java_lang_Integer, "java/lang/Integer") \
template(java_lang_Integer_IntegerCache, "java/lang/Integer$IntegerCache") \
template(java_lang_Long, "java/lang/Long") \
template(java_lang_Long_LongCache, "java/lang/Long$LongCache") \
template(java_lang_Shutdown, "java/lang/Shutdown") \
template(java_lang_ref_Reference, "java/lang/ref/Reference") \
template(java_lang_ref_SoftReference, "java/lang/ref/SoftReference") \
template(java_lang_ref_WeakReference, "java/lang/ref/WeakReference") \
template(java_lang_ref_FinalReference, "java/lang/ref/FinalReference") \
template(java_lang_ref_PhantomReference, "java/lang/ref/PhantomReference") \
template(sun_misc_Cleaner, "sun/misc/Cleaner") \
template(java_lang_ref_Finalizer, "java/lang/ref/Finalizer") \
template(java_lang_ref_ReferenceQueue, "java/lang/ref/ReferenceQueue") \
template(java_lang_reflect_AccessibleObject, "java/lang/reflect/AccessibleObject") \
template(java_lang_reflect_Method, "java/lang/reflect/Method") \
template(java_lang_reflect_Constructor, "java/lang/reflect/Constructor") \
template(java_lang_reflect_Field, "java/lang/reflect/Field") \
template(java_lang_reflect_Parameter, "java/lang/reflect/Parameter") \
template(java_lang_reflect_Array, "java/lang/reflect/Array") \
template(java_lang_StringBuffer, "java/lang/StringBuffer") \
template(java_lang_StringBuilder, "java/lang/StringBuilder") \
template(java_lang_CharSequence, "java/lang/CharSequence") \
template(java_lang_SecurityManager, "java/lang/SecurityManager") \
template(java_security_AccessControlContext, "java/security/AccessControlContext") \
template(java_security_CodeSource, "java/security/CodeSource") \
template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \
template(java_security_SecureClassLoader, "java/security/SecureClassLoader") \
template(java_net_URLClassLoader, "java/net/URLClassLoader") \
template(java_net_URL, "java/net/URL") \
template(java_util_jar_Manifest, "java/util/jar/Manifest") \
template(impliesCreateAccessControlContext_name, "impliesCreateAccessControlContext") \
template(java_io_OutputStream, "java/io/OutputStream") \
template(java_io_Reader, "java/io/Reader") \
template(java_io_BufferedReader, "java/io/BufferedReader") \
template(java_io_File, "java/io/File") \
template(java_io_FileInputStream, "java/io/FileInputStream") \
template(java_io_ByteArrayInputStream, "java/io/ByteArrayInputStream") \
template(java_io_Serializable, "java/io/Serializable") \
template(java_util_Arrays, "java/util/Arrays") \
template(java_util_Properties, "java/util/Properties") \
template(java_util_Vector, "java/util/Vector") \
template(java_util_AbstractList, "java/util/AbstractList") \
template(java_util_Hashtable, "java/util/Hashtable") \
template(java_lang_Compiler, "java/lang/Compiler") \
template(sun_misc_Signal, "sun/misc/Signal") \
template(sun_misc_Launcher, "sun/misc/Launcher") \
template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \
template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \
template(sun_misc_PostVMInitHook, "sun/misc/PostVMInitHook") \
template(sun_misc_Launcher_AppClassLoader, "sun/misc/Launcher$AppClassLoader") \
template(sun_misc_Launcher_ExtClassLoader, "sun/misc/Launcher$ExtClassLoader") \
\
template(sun_misc_Version, "sun/misc/Version") \
template(java_runtime_name_name, "java_runtime_name") \
template(java_runtime_version_name, "java_runtime_version") \
\
template(tag_source_file, "SourceFile") \
template(tag_inner_classes, "InnerClasses") \
template(tag_constant_value, "ConstantValue") \
template(tag_code, "Code") \
template(tag_exceptions, "Exceptions") \
template(tag_line_number_table, "LineNumberTable") \
template(tag_local_variable_table, "LocalVariableTable") \
template(tag_local_variable_type_table, "LocalVariableTypeTable") \
template(tag_method_parameters, "MethodParameters") \
template(tag_stack_map_table, "StackMapTable") \
template(tag_synthetic, "Synthetic") \
template(tag_deprecated, "Deprecated") \
template(tag_source_debug_extension, "SourceDebugExtension") \
template(tag_signature, "Signature") \
template(tag_runtime_visible_annotations, "RuntimeVisibleAnnotations") \
template(tag_runtime_invisible_annotations, "RuntimeInvisibleAnnotations") \
template(tag_runtime_visible_parameter_annotations, "RuntimeVisibleParameterAnnotations") \
template(tag_runtime_invisible_parameter_annotations,"RuntimeInvisibleParameterAnnotations") \
template(tag_annotation_default, "AnnotationDefault") \
template(tag_runtime_visible_type_annotations, "RuntimeVisibleTypeAnnotations") \
template(tag_runtime_invisible_type_annotations, "RuntimeInvisibleTypeAnnotations") \
template(tag_enclosing_method, "EnclosingMethod") \
template(tag_bootstrap_methods, "BootstrapMethods") \
\
template(java_lang_ArithmeticException, "java/lang/ArithmeticException") \
template(java_lang_ArrayIndexOutOfBoundsException, "java/lang/ArrayIndexOutOfBoundsException") \
template(java_lang_ArrayStoreException, "java/lang/ArrayStoreException") \
template(java_lang_ClassCastException, "java/lang/ClassCastException") \
template(java_lang_ClassNotFoundException, "java/lang/ClassNotFoundException") \
template(java_lang_CloneNotSupportedException, "java/lang/CloneNotSupportedException") \
template(java_lang_IllegalAccessException, "java/lang/IllegalAccessException") \
template(java_lang_IllegalArgumentException, "java/lang/IllegalArgumentException") \
template(java_lang_IllegalStateException, "java/lang/IllegalStateException") \
template(java_lang_IllegalMonitorStateException, "java/lang/IllegalMonitorStateException") \
template(java_lang_IllegalThreadStateException, "java/lang/IllegalThreadStateException") \
template(java_lang_IndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException") \
template(java_lang_InstantiationException, "java/lang/InstantiationException") \
template(java_lang_InstantiationError, "java/lang/InstantiationError") \
template(java_lang_InterruptedException, "java/lang/InterruptedException") \
template(java_lang_BootstrapMethodError, "java/lang/BootstrapMethodError") \
template(java_lang_LinkageError, "java/lang/LinkageError") \
template(java_lang_NegativeArraySizeException, "java/lang/NegativeArraySizeException") \
template(java_lang_NoSuchFieldException, "java/lang/NoSuchFieldException") \
template(java_lang_NoSuchMethodException, "java/lang/NoSuchMethodException") \
template(java_lang_NullPointerException, "java/lang/NullPointerException") \
template(java_lang_StringIndexOutOfBoundsException, "java/lang/StringIndexOutOfBoundsException")\
template(java_lang_UnsupportedOperationException, "java/lang/UnsupportedOperationException") \
template(java_lang_InvalidClassException, "java/lang/InvalidClassException") \
template(java_lang_reflect_InvocationTargetException, "java/lang/reflect/InvocationTargetException") \
template(java_lang_Exception, "java/lang/Exception") \
template(java_lang_RuntimeException, "java/lang/RuntimeException") \
template(java_io_IOException, "java/io/IOException") \
template(java_security_PrivilegedActionException, "java/security/PrivilegedActionException") \
\
template(java_lang_AbstractMethodError, "java/lang/AbstractMethodError") \
template(java_lang_ClassCircularityError, "java/lang/ClassCircularityError") \
template(java_lang_ClassFormatError, "java/lang/ClassFormatError") \
template(java_lang_UnsupportedClassVersionError, "java/lang/UnsupportedClassVersionError") \
template(java_lang_Error, "java/lang/Error") \
template(java_lang_ExceptionInInitializerError, "java/lang/ExceptionInInitializerError") \
template(java_lang_IllegalAccessError, "java/lang/IllegalAccessError") \
template(java_lang_IncompatibleClassChangeError, "java/lang/IncompatibleClassChangeError") \
template(java_lang_InternalError, "java/lang/InternalError") \
template(java_lang_NoClassDefFoundError, "java/lang/NoClassDefFoundError") \
template(java_lang_NoSuchFieldError, "java/lang/NoSuchFieldError") \
template(java_lang_NoSuchMethodError, "java/lang/NoSuchMethodError") \
template(java_lang_OutOfMemoryError, "java/lang/OutOfMemoryError") \
template(java_lang_UnsatisfiedLinkError, "java/lang/UnsatisfiedLinkError") \
template(java_lang_VerifyError, "java/lang/VerifyError") \
template(java_lang_SecurityException, "java/lang/SecurityException") \
template(java_lang_VirtualMachineError, "java/lang/VirtualMachineError") \
template(java_lang_StackOverflowError, "java/lang/StackOverflowError") \
template(java_lang_StackTraceElement, "java/lang/StackTraceElement") \
\
template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
template(java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl") \
template(java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater") \
template(java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater") \
template(java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl") \
template(sun_misc_Contended_signature, "Lsun/misc/Contended;") \
\
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, template, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \
\
\
template(sun_reflect_FieldInfo, "sun/reflect/FieldInfo") \
template(sun_reflect_MethodInfo, "sun/reflect/MethodInfo") \
template(sun_reflect_MagicAccessorImpl, "sun/reflect/MagicAccessorImpl") \
template(sun_reflect_MethodAccessorImpl, "sun/reflect/MethodAccessorImpl") \
template(sun_reflect_ConstructorAccessorImpl, "sun/reflect/ConstructorAccessorImpl") \
template(sun_reflect_SerializationConstructorAccessorImpl, "sun/reflect/SerializationConstructorAccessorImpl") \
template(sun_reflect_DelegatingClassLoader, "sun/reflect/DelegatingClassLoader") \
template(sun_reflect_Reflection, "sun/reflect/Reflection") \
template(sun_reflect_CallerSensitive, "sun/reflect/CallerSensitive") \
template(sun_reflect_CallerSensitive_signature, "Lsun/reflect/CallerSensitive;") \
template(checkedExceptions_name, "checkedExceptions") \
template(clazz_name, "clazz") \
template(exceptionTypes_name, "exceptionTypes") \
template(modifiers_name, "modifiers") \
template(newConstructor_name, "newConstructor") \
template(newConstructor_signature, "(Lsun/reflect/MethodInfo;)Ljava/lang/reflect/Constructor;") \
template(newField_name, "newField") \
template(newField_signature, "(Lsun/reflect/FieldInfo;)Ljava/lang/reflect/Field;") \
template(newMethod_name, "newMethod") \
template(newMethod_signature, "(Lsun/reflect/MethodInfo;)Ljava/lang/reflect/Method;") \
template(invokeBasic_name, "invokeBasic") \
template(linkToVirtual_name, "linkToVirtual") \
template(linkToStatic_name, "linkToStatic") \
template(linkToSpecial_name, "linkToSpecial") \
template(linkToInterface_name, "linkToInterface") \
template(compiledLambdaForm_name, "<compiledLambdaForm>") /*fake name*/ \
template(star_name, "*") /*not really a name*/ \
template(invoke_name, "invoke") \
template(override_name, "override") \
template(parameterTypes_name, "parameterTypes") \
template(returnType_name, "returnType") \
template(signature_name, "signature") \
template(slot_name, "slot") \
\
\
template(annotations_name, "annotations") \
template(index_name, "index") \
template(executable_name, "executable") \
template(parameter_annotations_name, "parameterAnnotations") \
template(annotation_default_name, "annotationDefault") \
template(sun_reflect_ConstantPool, "sun/reflect/ConstantPool") \
template(ConstantPool_name, "constantPoolOop") \
template(sun_reflect_UnsafeStaticFieldAccessorImpl, "sun/reflect/UnsafeStaticFieldAccessorImpl")\
template(base_name, "base") \
template(type_annotations_name, "typeAnnotations") \
\
\
template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \
template(java_lang_invoke_ConstantCallSite, "java/lang/invoke/ConstantCallSite") \
template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \
template(java_lang_invoke_MutableCallSite, "java/lang/invoke/MutableCallSite") \
template(java_lang_invoke_VolatileCallSite, "java/lang/invoke/VolatileCallSite") \
template(java_lang_invoke_MethodHandle, "java/lang/invoke/MethodHandle") \
template(java_lang_invoke_MethodType, "java/lang/invoke/MethodType") \
template(java_lang_invoke_MethodType_signature, "Ljava/lang/invoke/MethodType;") \
template(java_lang_invoke_MemberName_signature, "Ljava/lang/invoke/MemberName;") \
template(java_lang_invoke_LambdaForm_signature, "Ljava/lang/invoke/LambdaForm;") \
template(java_lang_invoke_MethodHandle_signature, "Ljava/lang/invoke/MethodHandle;") \
template(java_lang_invoke_MemberName, "java/lang/invoke/MemberName") \
template(java_lang_invoke_MethodHandleNatives, "java/lang/invoke/MethodHandleNatives") \
template(java_lang_invoke_LambdaForm, "java/lang/invoke/LambdaForm") \
template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \
template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \
template(java_lang_invoke_InjectedProfile_signature, "Ljava/lang/invoke/InjectedProfile;") \
template(java_lang_invoke_Stable_signature, "Ljava/lang/invoke/Stable;") \
template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \
template(findMethodHandleType_name, "findMethodHandleType") \
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
template(linkMethodHandleConstant_name, "linkMethodHandleConstant") \
template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \
template(linkMethod_name, "linkMethod") \
template(linkMethod_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName;") \
template(linkCallSite_name, "linkCallSite") \
template(linkCallSite_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName;") \
template(setTargetNormal_name, "setTargetNormal") \
template(setTargetVolatile_name, "setTargetVolatile") \
template(setTarget_signature, "(Ljava/lang/invoke/MethodHandle;)V") \
NOT_LP64( do_alias(intptr_signature, int_signature) ) \
LP64_ONLY( do_alias(intptr_signature, long_signature) ) \
\
template(object_initializer_name, "<init>") \
template(class_initializer_name, "<clinit>") \
template(println_name, "println") \
template(printStackTrace_name, "printStackTrace") \
template(main_name, "main") \
template(name_name, "name") \
template(priority_name, "priority") \
template(stillborn_name, "stillborn") \
template(group_name, "group") \
template(daemon_name, "daemon") \
template(eetop_name, "eetop") \
template(thread_status_name, "threadStatus") \
template(run_method_name, "run") \
template(exit_method_name, "exit") \
template(add_method_name, "add") \
template(remove_method_name, "remove") \
template(parent_name, "parent") \
template(threads_name, "threads") \
template(groups_name, "groups") \
template(maxPriority_name, "maxPriority") \
template(destroyed_name, "destroyed") \
template(vmAllowSuspension_name, "vmAllowSuspension") \
template(nthreads_name, "nthreads") \
template(ngroups_name, "ngroups") \
template(shutdown_method_name, "shutdown") \
template(finalize_method_name, "finalize") \
template(reference_lock_name, "lock") \
template(reference_discovered_name, "discovered") \
template(run_finalization_name, "runFinalization") \
template(run_finalizers_on_exit_name, "runFinalizersOnExit") \
template(uncaughtException_name, "uncaughtException") \
template(dispatchUncaughtException_name, "dispatchUncaughtException") \
template(initializeSystemClass_name, "initializeSystemClass") \
template(loadClass_name, "loadClass") \
template(loadClassInternal_name, "loadClassInternal") \
template(get_name, "get") \
template(put_name, "put") \
template(type_name, "type") \
template(findNative_name, "findNative") \
template(deadChild_name, "deadChild") \
template(addClass_name, "addClass") \
template(throwIllegalAccessError_name, "throwIllegalAccessError") \
template(getFromClass_name, "getFromClass") \
template(dispatch_name, "dispatch") \
template(getSystemClassLoader_name, "getSystemClassLoader") \
template(fillInStackTrace_name, "fillInStackTrace") \
template(fillInStackTrace0_name, "fillInStackTrace0") \
template(getCause_name, "getCause") \
template(initCause_name, "initCause") \
template(setProperty_name, "setProperty") \
template(getProperty_name, "getProperty") \
template(context_name, "context") \
template(privilegedContext_name, "privilegedContext") \
template(contextClassLoader_name, "contextClassLoader") \
template(inheritedAccessControlContext_name, "inheritedAccessControlContext") \
template(isPrivileged_name, "isPrivileged") \
template(isAuthorized_name, "isAuthorized") \
template(getClassContext_name, "getClassContext") \
template(wait_name, "wait") \
template(checkPackageAccess_name, "checkPackageAccess") \
template(stackSize_name, "stackSize") \
template(thread_id_name, "tid") \
template(newInstance0_name, "newInstance0") \
template(limit_name, "limit") \
template(member_name, "member") \
template(forName_name, "forName") \
template(forName0_name, "forName0") \
template(isJavaIdentifierStart_name, "isJavaIdentifierStart") \
template(isJavaIdentifierPart_name, "isJavaIdentifierPart") \
template(exclusive_owner_thread_name, "exclusiveOwnerThread") \
template(park_blocker_name, "parkBlocker") \
template(park_event_name, "nativeParkEventPointer") \
template(cache_field_name, "cache") \
template(value_name, "value") \
template(offset_name, "offset") \
template(count_name, "count") \
template(hash_name, "hash") \
template(numberOfLeadingZeros_name, "numberOfLeadingZeros") \
template(numberOfTrailingZeros_name, "numberOfTrailingZeros") \
template(bitCount_name, "bitCount") \
template(profile_name, "profile") \
template(equals_name, "equals") \
template(target_name, "target") \
template(toString_name, "toString") \
template(values_name, "values") \
template(receiver_name, "receiver") \
template(vmtarget_name, "vmtarget") \
template(next_target_name, "next_target") \
template(vmloader_name, "vmloader") \
template(vmindex_name, "vmindex") \
template(vmcount_name, "vmcount") \
template(vmentry_name, "vmentry") \
template(flags_name, "flags") \
template(rtype_name, "rtype") \
template(ptypes_name, "ptypes") \
template(form_name, "form") \
template(basicType_name, "basicType") \
template(append_name, "append") \
template(klass_name, "klass") \
template(array_klass_name, "array_klass") \
template(oop_size_name, "oop_size") \
template(static_oop_field_count_name, "static_oop_field_count") \
template(protection_domain_name, "protection_domain") \
template(init_lock_name, "init_lock") \
template(signers_name, "signers_name") \
template(loader_data_name, "loader_data") \
template(dependencies_name, "dependencies") \
template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \
template(getFileURL_name, "getFileURL") \
template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \
template(definePackageInternal_name, "definePackageInternal") \
template(definePackageInternal_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)V") \
template(getProtectionDomain_name, "getProtectionDomain") \
template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \
template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \
template(resolved_references_name, "<resolved_references>") \
template(referencequeue_null_name, "NULL") \
template(referencequeue_enqueued_name, "ENQUEUED") \
\
template(register_method_name, "register") \
do_alias(register_method_signature, object_void_signature) \
\
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, template, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \
\
template(void_method_signature, "()V") \
template(void_boolean_signature, "()Z") \
template(void_byte_signature, "()B") \
template(void_char_signature, "()C") \
template(void_short_signature, "()S") \
template(void_int_signature, "()I") \
template(void_long_signature, "()J") \
template(void_float_signature, "()F") \
template(void_double_signature, "()D") \
template(int_void_signature, "(I)V") \
template(int_int_signature, "(I)I") \
template(char_char_signature, "(C)C") \
template(short_short_signature, "(S)S") \
template(int_bool_signature, "(I)Z") \
template(float_int_signature, "(F)I") \
template(double_long_signature, "(D)J") \
template(double_double_signature, "(D)D") \
template(int_float_signature, "(I)F") \
template(long_int_signature, "(J)I") \
template(long_long_signature, "(J)J") \
template(long_double_signature, "(J)D") \
template(byte_signature, "B") \
template(char_signature, "C") \
template(double_signature, "D") \
template(float_signature, "F") \
template(int_signature, "I") \
template(long_signature, "J") \
template(short_signature, "S") \
template(bool_signature, "Z") \
template(void_signature, "V") \
template(byte_array_signature, "[B") \
template(char_array_signature, "[C") \
template(int_array_signature, "[I") \
template(object_void_signature, "(Ljava/lang/Object;)V") \
template(object_int_signature, "(Ljava/lang/Object;)I") \
template(object_boolean_signature, "(Ljava/lang/Object;)Z") \
template(string_void_signature, "(Ljava/lang/String;)V") \
template(string_int_signature, "(Ljava/lang/String;)I") \
template(throwable_void_signature, "(Ljava/lang/Throwable;)V") \
template(void_throwable_signature, "()Ljava/lang/Throwable;") \
template(throwable_throwable_signature, "(Ljava/lang/Throwable;)Ljava/lang/Throwable;") \
template(class_void_signature, "(Ljava/lang/Class;)V") \
template(class_int_signature, "(Ljava/lang/Class;)I") \
template(class_long_signature, "(Ljava/lang/Class;)J") \
template(class_boolean_signature, "(Ljava/lang/Class;)Z") \
template(throwable_string_void_signature, "(Ljava/lang/Throwable;Ljava/lang/String;)V") \
template(string_array_void_signature, "([Ljava/lang/String;)V") \
template(string_array_string_array_void_signature, "([Ljava/lang/String;[Ljava/lang/String;)V") \
template(thread_throwable_void_signature, "(Ljava/lang/Thread;Ljava/lang/Throwable;)V") \
template(thread_void_signature, "(Ljava/lang/Thread;)V") \
template(threadgroup_runnable_void_signature, "(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;)V") \
template(threadgroup_string_void_signature, "(Ljava/lang/ThreadGroup;Ljava/lang/String;)V") \
template(string_class_signature, "(Ljava/lang/String;)Ljava/lang/Class;") \
template(object_object_object_signature, "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") \
template(string_string_string_signature, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;") \
template(string_string_signature, "(Ljava/lang/String;)Ljava/lang/String;") \
template(classloader_string_long_signature, "(Ljava/lang/ClassLoader;Ljava/lang/String;)J") \
template(byte_array_void_signature, "([B)V") \
template(char_array_void_signature, "([C)V") \
template(int_int_void_signature, "(II)V") \
template(long_long_void_signature, "(JJ)V") \
template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \
template(void_object_signature, "()Ljava/lang/Object;") \
template(void_class_signature, "()Ljava/lang/Class;") \
template(void_class_array_signature, "()[Ljava/lang/Class;") \
template(void_string_signature, "()Ljava/lang/String;") \
template(object_array_object_signature, "([Ljava/lang/Object;)Ljava/lang/Object;") \
template(object_object_array_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
template(exception_void_signature, "(Ljava/lang/Exception;)V") \
template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \
template(accesscontrolcontext_signature, "Ljava/security/AccessControlContext;") \
template(class_protectiondomain_signature, "(Ljava/lang/Class;Ljava/security/ProtectionDomain;)V") \
template(thread_signature, "Ljava/lang/Thread;") \
template(thread_array_signature, "[Ljava/lang/Thread;") \
template(threadgroup_signature, "Ljava/lang/ThreadGroup;") \
template(threadgroup_array_signature, "[Ljava/lang/ThreadGroup;") \
template(class_array_signature, "[Ljava/lang/Class;") \
template(classloader_signature, "Ljava/lang/ClassLoader;") \
template(object_signature, "Ljava/lang/Object;") \
template(object_array_signature, "[Ljava/lang/Object;") \
template(class_signature, "Ljava/lang/Class;") \
template(string_signature, "Ljava/lang/String;") \
template(reference_signature, "Ljava/lang/ref/Reference;") \
template(referencequeue_signature, "Ljava/lang/ref/ReferenceQueue;") \
template(executable_signature, "Ljava/lang/reflect/Executable;") \
template(concurrenthashmap_signature, "Ljava/util/concurrent/ConcurrentHashMap;") \
template(String_StringBuilder_signature, "(Ljava/lang/String;)Ljava/lang/StringBuilder;") \
template(int_StringBuilder_signature, "(I)Ljava/lang/StringBuilder;") \
template(char_StringBuilder_signature, "(C)Ljava/lang/StringBuilder;") \
template(String_StringBuffer_signature, "(Ljava/lang/String;)Ljava/lang/StringBuffer;") \
template(int_StringBuffer_signature, "(I)Ljava/lang/StringBuffer;") \
template(char_StringBuffer_signature, "(C)Ljava/lang/StringBuffer;") \
template(int_String_signature, "(I)Ljava/lang/String;") \
template(codesource_permissioncollection_signature, "(Ljava/security/CodeSource;Ljava/security/PermissionCollection;)V") \
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE) \
\
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, do_alias) \
\
template(dummy_symbol, "illegal symbol") \
\
template(unknown_class_name, "<Unknown>") \
\
template(parallelCapable_name, "parallelLockMap") \
\
template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \
template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \
template(java_lang_management_MemoryUsage, "java/lang/management/MemoryUsage") \
template(java_lang_management_ThreadInfo, "java/lang/management/ThreadInfo") \
template(sun_management_ManagementFactory, "sun/management/ManagementFactory") \
template(sun_management_Sensor, "sun/management/Sensor") \
template(sun_management_Agent, "sun/management/Agent") \
template(sun_management_DiagnosticCommandImpl, "sun/management/DiagnosticCommandImpl") \
template(sun_management_GarbageCollectorImpl, "sun/management/GarbageCollectorImpl") \
template(sun_management_ManagementFactoryHelper, "sun/management/ManagementFactoryHelper") \
template(getDiagnosticCommandMBean_name, "getDiagnosticCommandMBean") \
template(getDiagnosticCommandMBean_signature, "()Lcom/sun/management/DiagnosticCommandMBean;") \
template(getGcInfoBuilder_name, "getGcInfoBuilder") \
template(getGcInfoBuilder_signature, "()Lsun/management/GcInfoBuilder;") \
template(com_sun_management_GcInfo, "com/sun/management/GcInfo") \
template(com_sun_management_GcInfo_constructor_signature, "(Lsun/management/GcInfoBuilder;JJJ[Ljava/lang/management/MemoryUsage;[Ljava/lang/management/MemoryUsage;[Ljava/lang/Object;)V") \
template(createGCNotification_name, "createGCNotification") \
template(createGCNotification_signature, "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/sun/management/GcInfo;)V") \
template(createDiagnosticFrameworkNotification_name, "createDiagnosticFrameworkNotification") \
template(createMemoryPoolMBean_name, "createMemoryPoolMBean") \
template(createMemoryManagerMBean_name, "createMemoryManagerMBean") \
template(createGarbageCollectorMBean_name, "createGarbageCollectorMBean") \
template(createMemoryPoolMBean_signature, "(Ljava/lang/String;ZJJ)Ljava/lang/management/MemoryPoolMBean;") \
template(createMemoryManagerMBean_signature, "(Ljava/lang/String;)Ljava/lang/management/MemoryManagerMBean;") \
template(createGarbageCollectorMBean_signature, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/management/GarbageCollectorMBean;") \
template(trigger_name, "trigger") \
template(clear_name, "clear") \
template(trigger_method_signature, "(ILjava/lang/management/MemoryUsage;)V") \
template(startAgent_name, "startAgent") \
template(startRemoteAgent_name, "startRemoteManagementAgent") \
template(startLocalAgent_name, "startLocalManagementAgent") \
template(stopRemoteAgent_name, "stopRemoteManagementAgent") \
template(java_lang_management_ThreadInfo_constructor_signature, "(Ljava/lang/Thread;ILjava/lang/Object;Ljava/lang/Thread;JJJJ[Ljava/lang/StackTraceElement;)V") \
template(java_lang_management_ThreadInfo_with_locks_constructor_signature, "(Ljava/lang/Thread;ILjava/lang/Object;Ljava/lang/Thread;JJJJ[Ljava/lang/StackTraceElement;[Ljava/lang/Object;[I[Ljava/lang/Object;)V") \
template(long_long_long_long_void_signature, "(JJJJ)V") \
template(finalizer_histogram_klass, "java/lang/ref/FinalizerHistogram") \
template(void_finalizer_histogram_entry_array_signature, "()[Ljava/lang/ref/FinalizerHistogram$Entry;") \
template(get_finalizer_histogram_name, "getFinalizerHistogram") \
template(finalizer_histogram_entry_name_field, "className") \
template(finalizer_histogram_entry_count_field, "instanceCount") \
\
template(java_lang_management_MemoryPoolMXBean, "java/lang/management/MemoryPoolMXBean") \
template(java_lang_management_MemoryManagerMXBean, "java/lang/management/MemoryManagerMXBean") \
template(java_lang_management_GarbageCollectorMXBean,"java/lang/management/GarbageCollectorMXBean") \
template(gcInfoBuilder_name, "gcInfoBuilder") \
template(createMemoryPool_name, "createMemoryPool") \
template(createMemoryManager_name, "createMemoryManager") \
template(createGarbageCollector_name, "createGarbageCollector") \
template(createMemoryPool_signature, "(Ljava/lang/String;ZJJ)Ljava/lang/management/MemoryPoolMXBean;") \
template(createMemoryManager_signature, "(Ljava/lang/String;)Ljava/lang/management/MemoryManagerMXBean;") \
template(createGarbageCollector_signature, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/management/GarbageCollectorMXBean;") \
template(addThreadDumpForMonitors_name, "addThreadDumpForMonitors") \
template(addThreadDumpForSynchronizers_name, "addThreadDumpForSynchronizers") \
template(addThreadDumpForMonitors_signature, "(Ljava/lang/management/ThreadInfo;[Ljava/lang/Object;[I)V") \
template(addThreadDumpForSynchronizers_signature, "(Ljava/lang/management/ThreadInfo;[Ljava/lang/Object;)V") \
\
template(sun_misc_VMSupport, "sun/misc/VMSupport") \
template(appendToClassPathForInstrumentation_name, "appendToClassPathForInstrumentation") \
do_alias(appendToClassPathForInstrumentation_signature, string_void_signature) \
template(serializePropertiesToByteArray_name, "serializePropertiesToByteArray") \
template(serializePropertiesToByteArray_signature, "()[B") \
template(serializeAgentPropertiesToByteArray_name, "serializeAgentPropertiesToByteArray") \
template(classRedefinedCount_name, "classRedefinedCount") \
template(classLoader_name, "classLoader") \
\
JFR_TEMPLATES(template) \
\
#define VM_INTRINSICS_DO(do_intrinsic, do_class, do_name, do_signature, do_alias) \
do_intrinsic(_hashCode, java_lang_Object, hashCode_name, void_int_signature, F_R) \
do_name( hashCode_name, "hashCode") \
do_intrinsic(_getClass, java_lang_Object, getClass_name, void_class_signature, F_R) \
do_name( getClass_name, "getClass") \
do_intrinsic(_clone, java_lang_Object, clone_name, void_object_signature, F_R) \
do_name( clone_name, "clone") \
\
do_class(java_lang_Math, "java/lang/Math") \
do_class(java_lang_StrictMath, "java/lang/StrictMath") \
do_signature(double2_double_signature, "(DD)D") \
do_signature(int2_int_signature, "(II)I") \
do_signature(long2_long_signature, "(JJ)J") \
\
do_name(abs_name,"abs") do_name(sin_name,"sin") do_name(cos_name,"cos") \
do_name(tan_name,"tan") do_name(atan2_name,"atan2") do_name(sqrt_name,"sqrt") \
do_name(log_name,"log") do_name(log10_name,"log10") do_name(pow_name,"pow") \
do_name(exp_name,"exp") do_name(min_name,"min") do_name(max_name,"max") \
\
do_name(addExact_name,"addExact") \
do_name(decrementExact_name,"decrementExact") \
do_name(incrementExact_name,"incrementExact") \
do_name(multiplyExact_name,"multiplyExact") \
do_name(negateExact_name,"negateExact") \
do_name(subtractExact_name,"subtractExact") \
\
do_intrinsic(_dabs, java_lang_Math, abs_name, double_double_signature, F_S) \
do_intrinsic(_dsin, java_lang_Math, sin_name, double_double_signature, F_S) \
do_intrinsic(_dcos, java_lang_Math, cos_name, double_double_signature, F_S) \
do_intrinsic(_dtan, java_lang_Math, tan_name, double_double_signature, F_S) \
do_intrinsic(_datan2, java_lang_Math, atan2_name, double2_double_signature, F_S) \
do_intrinsic(_dsqrt, java_lang_Math, sqrt_name, double_double_signature, F_S) \
do_intrinsic(_dlog, java_lang_Math, log_name, double_double_signature, F_S) \
do_intrinsic(_dlog10, java_lang_Math, log10_name, double_double_signature, F_S) \
do_intrinsic(_dpow, java_lang_Math, pow_name, double2_double_signature, F_S) \
do_intrinsic(_dexp, java_lang_Math, exp_name, double_double_signature, F_S) \
do_intrinsic(_min, java_lang_Math, min_name, int2_int_signature, F_S) \
do_intrinsic(_max, java_lang_Math, max_name, int2_int_signature, F_S) \
do_intrinsic(_addExactI, java_lang_Math, addExact_name, int2_int_signature, F_S) \
do_intrinsic(_addExactL, java_lang_Math, addExact_name, long2_long_signature, F_S) \
do_intrinsic(_decrementExactI, java_lang_Math, decrementExact_name, int_int_signature, F_S) \
do_intrinsic(_decrementExactL, java_lang_Math, decrementExact_name, long_long_signature, F_S) \
do_intrinsic(_incrementExactI, java_lang_Math, incrementExact_name, int_int_signature, F_S) \
do_intrinsic(_incrementExactL, java_lang_Math, incrementExact_name, long_long_signature, F_S) \
do_intrinsic(_multiplyExactI, java_lang_Math, multiplyExact_name, int2_int_signature, F_S) \
do_intrinsic(_multiplyExactL, java_lang_Math, multiplyExact_name, long2_long_signature, F_S) \
do_intrinsic(_negateExactI, java_lang_Math, negateExact_name, int_int_signature, F_S) \
do_intrinsic(_negateExactL, java_lang_Math, negateExact_name, long_long_signature, F_S) \
do_intrinsic(_subtractExactI, java_lang_Math, subtractExact_name, int2_int_signature, F_S) \
do_intrinsic(_subtractExactL, java_lang_Math, subtractExact_name, long2_long_signature, F_S) \
\
do_intrinsic(_floatToRawIntBits, java_lang_Float, floatToRawIntBits_name, float_int_signature, F_S) \
do_name( floatToRawIntBits_name, "floatToRawIntBits") \
do_intrinsic(_floatToIntBits, java_lang_Float, floatToIntBits_name, float_int_signature, F_S) \
do_name( floatToIntBits_name, "floatToIntBits") \
do_intrinsic(_intBitsToFloat, java_lang_Float, intBitsToFloat_name, int_float_signature, F_S) \
do_name( intBitsToFloat_name, "intBitsToFloat") \
do_intrinsic(_doubleToRawLongBits, java_lang_Double, doubleToRawLongBits_name, double_long_signature, F_S) \
do_name( doubleToRawLongBits_name, "doubleToRawLongBits") \
do_intrinsic(_doubleToLongBits, java_lang_Double, doubleToLongBits_name, double_long_signature, F_S) \
do_name( doubleToLongBits_name, "doubleToLongBits") \
do_intrinsic(_longBitsToDouble, java_lang_Double, longBitsToDouble_name, long_double_signature, F_S) \
do_name( longBitsToDouble_name, "longBitsToDouble") \
\
do_intrinsic(_numberOfLeadingZeros_i, java_lang_Integer, numberOfLeadingZeros_name,int_int_signature, F_S) \
do_intrinsic(_numberOfLeadingZeros_l, java_lang_Long, numberOfLeadingZeros_name,long_int_signature, F_S) \
\
do_intrinsic(_numberOfTrailingZeros_i, java_lang_Integer, numberOfTrailingZeros_name,int_int_signature, F_S) \
do_intrinsic(_numberOfTrailingZeros_l, java_lang_Long, numberOfTrailingZeros_name,long_int_signature, F_S) \
\
do_intrinsic(_bitCount_i, java_lang_Integer, bitCount_name, int_int_signature, F_S) \
do_intrinsic(_bitCount_l, java_lang_Long, bitCount_name, long_int_signature, F_S) \
\
do_intrinsic(_reverseBytes_i, java_lang_Integer, reverseBytes_name, int_int_signature, F_S) \
do_name( reverseBytes_name, "reverseBytes") \
do_intrinsic(_reverseBytes_l, java_lang_Long, reverseBytes_name, long_long_signature, F_S) \
do_intrinsic(_reverseBytes_c, java_lang_Character, reverseBytes_name, char_char_signature, F_S) \
do_intrinsic(_reverseBytes_s, java_lang_Short, reverseBytes_name, short_short_signature, F_S) \
\
do_intrinsic(_identityHashCode, java_lang_System, identityHashCode_name, object_int_signature, F_S) \
do_name( identityHashCode_name, "identityHashCode") \
do_intrinsic(_currentTimeMillis, java_lang_System, currentTimeMillis_name, void_long_signature, F_S) \
\
do_name( currentTimeMillis_name, "currentTimeMillis") \
do_intrinsic(_nanoTime, java_lang_System, nanoTime_name, void_long_signature, F_S) \
do_name( nanoTime_name, "nanoTime") \
\
JFR_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias) \
\
do_intrinsic(_arraycopy, java_lang_System, arraycopy_name, arraycopy_signature, F_S) \
do_name( arraycopy_name, "arraycopy") \
do_signature(arraycopy_signature, "(Ljava/lang/Object;ILjava/lang/Object;II)V") \
do_intrinsic(_isInterrupted, java_lang_Thread, isInterrupted_name, isInterrupted_signature, F_R) \
do_name( isInterrupted_name, "isInterrupted") \
do_signature(isInterrupted_signature, "(Z)Z") \
do_intrinsic(_currentThread, java_lang_Thread, currentThread_name, currentThread_signature, F_S) \
do_name( currentThread_name, "currentThread") \
do_signature(currentThread_signature, "()Ljava/lang/Thread;") \
\
do_intrinsic(_isAssignableFrom, java_lang_Class, isAssignableFrom_name, class_boolean_signature, F_RN) \
do_name( isAssignableFrom_name, "isAssignableFrom") \
do_intrinsic(_isInstance, java_lang_Class, isInstance_name, object_boolean_signature, F_RN) \
do_name( isInstance_name, "isInstance") \
do_intrinsic(_getModifiers, java_lang_Class, getModifiers_name, void_int_signature, F_RN) \
do_name( getModifiers_name, "getModifiers") \
do_intrinsic(_isInterface, java_lang_Class, isInterface_name, void_boolean_signature, F_RN) \
do_name( isInterface_name, "isInterface") \
do_intrinsic(_isArray, java_lang_Class, isArray_name, void_boolean_signature, F_RN) \
do_name( isArray_name, "isArray") \
do_intrinsic(_isPrimitive, java_lang_Class, isPrimitive_name, void_boolean_signature, F_RN) \
do_name( isPrimitive_name, "isPrimitive") \
do_intrinsic(_getSuperclass, java_lang_Class, getSuperclass_name, void_class_signature, F_RN) \
do_name( getSuperclass_name, "getSuperclass") \
do_intrinsic(_getComponentType, java_lang_Class, getComponentType_name, void_class_signature, F_RN) \
do_name( getComponentType_name, "getComponentType") \
\
do_intrinsic(_getClassAccessFlags, sun_reflect_Reflection, getClassAccessFlags_name, class_int_signature, F_SN) \
do_name( getClassAccessFlags_name, "getClassAccessFlags") \
do_intrinsic(_getLength, java_lang_reflect_Array, getLength_name, object_int_signature, F_SN) \
do_name( getLength_name, "getLength") \
\
do_intrinsic(_getCallerClass, sun_reflect_Reflection, getCallerClass_name, void_class_signature, F_SN) \
do_name( getCallerClass_name, "getCallerClass") \
\
do_intrinsic(_newArray, java_lang_reflect_Array, newArray_name, newArray_signature, F_SN) \
do_name( newArray_name, "newArray") \
do_signature(newArray_signature, "(Ljava/lang/Class;I)Ljava/lang/Object;") \
\
do_intrinsic(_copyOf, java_util_Arrays, copyOf_name, copyOf_signature, F_S) \
do_name( copyOf_name, "copyOf") \
do_signature(copyOf_signature, "([Ljava/lang/Object;ILjava/lang/Class;)[Ljava/lang/Object;") \
\
do_intrinsic(_copyOfRange, java_util_Arrays, copyOfRange_name, copyOfRange_signature, F_S) \
do_name( copyOfRange_name, "copyOfRange") \
do_signature(copyOfRange_signature, "([Ljava/lang/Object;IILjava/lang/Class;)[Ljava/lang/Object;") \
\
do_intrinsic(_equalsC, java_util_Arrays, equals_name, equalsC_signature, F_S) \
do_signature(equalsC_signature, "([C[C)Z") \
\
do_intrinsic(_compareTo, java_lang_String, compareTo_name, string_int_signature, F_R) \
do_name( compareTo_name, "compareTo") \
do_intrinsic(_indexOf, java_lang_String, indexOf_name, string_int_signature, F_R) \
do_name( indexOf_name, "indexOf") \
do_intrinsic(_equals, java_lang_String, equals_name, object_boolean_signature, F_R) \
\
do_class(java_nio_Buffer, "java/nio/Buffer") \
do_intrinsic(_checkIndex, java_nio_Buffer, checkIndex_name, int_int_signature, F_R) \
do_name( checkIndex_name, "checkIndex") \
\
do_class(sun_nio_cs_iso8859_1_Encoder, "sun/nio/cs/ISO_8859_1$Encoder") \
do_intrinsic(_encodeISOArray, sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S) \
do_name( encodeISOArray_name, "encodeISOArray") \
do_signature(encodeISOArray_signature, "([CI[BII)I") \
\
do_class(java_math_BigInteger, "java/math/BigInteger") \
do_intrinsic(_multiplyToLen, java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_S) \
do_name( multiplyToLen_name, "multiplyToLen") \
do_signature(multiplyToLen_signature, "([II[II[I)[I") \
\
do_intrinsic(_squareToLen, java_math_BigInteger, squareToLen_name, squareToLen_signature, F_S) \
do_name( squareToLen_name, "implSquareToLen") \
do_signature(squareToLen_signature, "([II[II)[I") \
\
do_intrinsic(_mulAdd, java_math_BigInteger, mulAdd_name, mulAdd_signature, F_S) \
do_name( mulAdd_name, "implMulAdd") \
do_signature(mulAdd_signature, "([I[IIII)I") \
\
do_intrinsic(_montgomeryMultiply, java_math_BigInteger, montgomeryMultiply_name, montgomeryMultiply_signature, F_S) \
do_name( montgomeryMultiply_name, "implMontgomeryMultiply") \
do_signature(montgomeryMultiply_signature, "([I[I[IIJ[I)[I") \
\
do_intrinsic(_montgomerySquare, java_math_BigInteger, montgomerySquare_name, montgomerySquare_signature, F_S) \
do_name( montgomerySquare_name, "implMontgomerySquare") \
do_signature(montgomerySquare_signature, "([I[IIJ[I)[I") \
\
do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \
\
do_class(com_sun_crypto_provider_aescrypt, "com/sun/crypto/provider/AESCrypt") \
do_intrinsic(_aescrypt_encryptBlock, com_sun_crypto_provider_aescrypt, encryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \
do_intrinsic(_aescrypt_decryptBlock, com_sun_crypto_provider_aescrypt, decryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \
do_name( encryptBlock_name, "implEncryptBlock") \
do_name( decryptBlock_name, "implDecryptBlock") \
do_signature(byteArray_int_byteArray_int_signature, "([BI[BI)V") \
\
do_class(com_sun_crypto_provider_cipherBlockChaining, "com/sun/crypto/provider/CipherBlockChaining") \
do_intrinsic(_cipherBlockChaining_encryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, encrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \
do_intrinsic(_cipherBlockChaining_decryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, decrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \
do_name( encrypt_name, "implEncrypt") \
do_name( decrypt_name, "implDecrypt") \
do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \
\
do_class(sun_security_provider_sha, "sun/security/provider/SHA") \
do_intrinsic(_sha_implCompress, sun_security_provider_sha, implCompress_name, implCompress_signature, F_R) \
do_name( implCompress_name, "implCompress0") \
do_signature(implCompress_signature, "([BI)V") \
\
do_class(sun_security_provider_sha2, "sun/security/provider/SHA2") \
do_intrinsic(_sha2_implCompress, sun_security_provider_sha2, implCompress_name, implCompress_signature, F_R) \
\
do_class(sun_security_provider_sha5, "sun/security/provider/SHA5") \
do_intrinsic(_sha5_implCompress, sun_security_provider_sha5, implCompress_name, implCompress_signature, F_R) \
\
do_class(sun_security_provider_digestbase, "sun/security/provider/DigestBase") \
do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, implCompressMB_signature, F_R) \
do_name( implCompressMB_name, "implCompressMultiBlock0") \
do_signature(implCompressMB_signature, "([BII)I") \
\
do_class(com_sun_crypto_provider_ghash, "com/sun/crypto/provider/GHASH") \
do_intrinsic(_ghash_processBlocks, com_sun_crypto_provider_ghash, processBlocks_name, ghash_processBlocks_signature, F_S) \
do_name(processBlocks_name, "processBlocks") \
do_signature(ghash_processBlocks_signature, "([BII[J[J)V") \
\
do_class(java_util_zip_CRC32, "java/util/zip/CRC32") \
do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \
do_name( update_name, "update") \
do_intrinsic(_updateBytesCRC32, java_util_zip_CRC32, updateBytes_name, updateBytes_signature, F_SN) \
do_name( updateBytes_name, "updateBytes") \
do_signature(updateBytes_signature, "(I[BII)I") \
do_intrinsic(_updateByteBufferCRC32, java_util_zip_CRC32, updateByteBuffer_name, updateByteBuffer_signature, F_SN) \
do_name( updateByteBuffer_name, "updateByteBuffer") \
do_signature(updateByteBuffer_signature, "(IJII)I") \
\
do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \
\
do_intrinsic(_allocateInstance, sun_misc_Unsafe, allocateInstance_name, allocateInstance_signature, F_RN) \
do_name( allocateInstance_name, "allocateInstance") \
do_signature(allocateInstance_signature, "(Ljava/lang/Class;)Ljava/lang/Object;") \
do_intrinsic(_copyMemory, sun_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \
do_name( copyMemory_name, "copyMemory") \
do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \
do_intrinsic(_park, sun_misc_Unsafe, park_name, park_signature, F_RN) \
do_name( park_name, "park") \
do_signature(park_signature, "(ZJ)V") \
do_intrinsic(_unpark, sun_misc_Unsafe, unpark_name, unpark_signature, F_RN) \
do_name( unpark_name, "unpark") \
do_alias( unpark_signature, /*(LObject;)V*/ object_void_signature) \
do_intrinsic(_loadFence, sun_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \
do_name( loadFence_name, "loadFence") \
do_alias( loadFence_signature, void_method_signature) \
do_intrinsic(_storeFence, sun_misc_Unsafe, storeFence_name, storeFence_signature, F_RN) \
do_name( storeFence_name, "storeFence") \
do_alias( storeFence_signature, void_method_signature) \
do_intrinsic(_fullFence, sun_misc_Unsafe, fullFence_name, fullFence_signature, F_RN) \
do_name( fullFence_name, "fullFence") \
do_alias( fullFence_signature, void_method_signature) \
\
do_class(java_lang_invoke_MethodHandleImpl, "java/lang/invoke/MethodHandleImpl") \
do_intrinsic(_profileBoolean, java_lang_invoke_MethodHandleImpl, profileBoolean_name, profileBoolean_signature, F_S) \
do_name( profileBoolean_name, "profileBoolean") \
do_signature(profileBoolean_signature, "(Z[I)Z") \
\
do_signature(getObject_signature, "(Ljava/lang/Object;J)Ljava/lang/Object;") \
do_signature(putObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)V") \
do_signature(getBoolean_signature, "(Ljava/lang/Object;J)Z") \
do_signature(putBoolean_signature, "(Ljava/lang/Object;JZ)V") \
do_signature(getByte_signature, "(Ljava/lang/Object;J)B") \
do_signature(putByte_signature, "(Ljava/lang/Object;JB)V") \
do_signature(getShort_signature, "(Ljava/lang/Object;J)S") \
do_signature(putShort_signature, "(Ljava/lang/Object;JS)V") \
do_signature(getChar_signature, "(Ljava/lang/Object;J)C") \
do_signature(putChar_signature, "(Ljava/lang/Object;JC)V") \
do_signature(getInt_signature, "(Ljava/lang/Object;J)I") \
do_signature(putInt_signature, "(Ljava/lang/Object;JI)V") \
do_signature(getLong_signature, "(Ljava/lang/Object;J)J") \
do_signature(putLong_signature, "(Ljava/lang/Object;JJ)V") \
do_signature(getFloat_signature, "(Ljava/lang/Object;J)F") \
do_signature(putFloat_signature, "(Ljava/lang/Object;JF)V") \
do_signature(getDouble_signature, "(Ljava/lang/Object;J)D") \
do_signature(putDouble_signature, "(Ljava/lang/Object;JD)V") \
\
do_name(getObject_name,"getObject") do_name(putObject_name,"putObject") \
do_name(getBoolean_name,"getBoolean") do_name(putBoolean_name,"putBoolean") \
do_name(getByte_name,"getByte") do_name(putByte_name,"putByte") \
do_name(getShort_name,"getShort") do_name(putShort_name,"putShort") \
do_name(getChar_name,"getChar") do_name(putChar_name,"putChar") \
do_name(getInt_name,"getInt") do_name(putInt_name,"putInt") \
do_name(getLong_name,"getLong") do_name(putLong_name,"putLong") \
do_name(getFloat_name,"getFloat") do_name(putFloat_name,"putFloat") \
do_name(getDouble_name,"getDouble") do_name(putDouble_name,"putDouble") \
\
do_intrinsic(_getObject, sun_misc_Unsafe, getObject_name, getObject_signature, F_RN) \
do_intrinsic(_getBoolean, sun_misc_Unsafe, getBoolean_name, getBoolean_signature, F_RN) \
do_intrinsic(_getByte, sun_misc_Unsafe, getByte_name, getByte_signature, F_RN) \
do_intrinsic(_getShort, sun_misc_Unsafe, getShort_name, getShort_signature, F_RN) \
do_intrinsic(_getChar, sun_misc_Unsafe, getChar_name, getChar_signature, F_RN) \
do_intrinsic(_getInt, sun_misc_Unsafe, getInt_name, getInt_signature, F_RN) \
do_intrinsic(_getLong, sun_misc_Unsafe, getLong_name, getLong_signature, F_RN) \
do_intrinsic(_getFloat, sun_misc_Unsafe, getFloat_name, getFloat_signature, F_RN) \
do_intrinsic(_getDouble, sun_misc_Unsafe, getDouble_name, getDouble_signature, F_RN) \
do_intrinsic(_putObject, sun_misc_Unsafe, putObject_name, putObject_signature, F_RN) \
do_intrinsic(_putBoolean, sun_misc_Unsafe, putBoolean_name, putBoolean_signature, F_RN) \
do_intrinsic(_putByte, sun_misc_Unsafe, putByte_name, putByte_signature, F_RN) \
do_intrinsic(_putShort, sun_misc_Unsafe, putShort_name, putShort_signature, F_RN) \
do_intrinsic(_putChar, sun_misc_Unsafe, putChar_name, putChar_signature, F_RN) \
do_intrinsic(_putInt, sun_misc_Unsafe, putInt_name, putInt_signature, F_RN) \
do_intrinsic(_putLong, sun_misc_Unsafe, putLong_name, putLong_signature, F_RN) \
do_intrinsic(_putFloat, sun_misc_Unsafe, putFloat_name, putFloat_signature, F_RN) \
do_intrinsic(_putDouble, sun_misc_Unsafe, putDouble_name, putDouble_signature, F_RN) \
\
do_name(getObjectVolatile_name,"getObjectVolatile") do_name(putObjectVolatile_name,"putObjectVolatile") \
do_name(getBooleanVolatile_name,"getBooleanVolatile") do_name(putBooleanVolatile_name,"putBooleanVolatile") \
do_name(getByteVolatile_name,"getByteVolatile") do_name(putByteVolatile_name,"putByteVolatile") \
do_name(getShortVolatile_name,"getShortVolatile") do_name(putShortVolatile_name,"putShortVolatile") \
do_name(getCharVolatile_name,"getCharVolatile") do_name(putCharVolatile_name,"putCharVolatile") \
do_name(getIntVolatile_name,"getIntVolatile") do_name(putIntVolatile_name,"putIntVolatile") \
do_name(getLongVolatile_name,"getLongVolatile") do_name(putLongVolatile_name,"putLongVolatile") \
do_name(getFloatVolatile_name,"getFloatVolatile") do_name(putFloatVolatile_name,"putFloatVolatile") \
do_name(getDoubleVolatile_name,"getDoubleVolatile") do_name(putDoubleVolatile_name,"putDoubleVolatile") \
\
do_intrinsic(_getObjectVolatile, sun_misc_Unsafe, getObjectVolatile_name, getObject_signature, F_RN) \
do_intrinsic(_getBooleanVolatile, sun_misc_Unsafe, getBooleanVolatile_name, getBoolean_signature, F_RN) \
do_intrinsic(_getByteVolatile, sun_misc_Unsafe, getByteVolatile_name, getByte_signature, F_RN) \
do_intrinsic(_getShortVolatile, sun_misc_Unsafe, getShortVolatile_name, getShort_signature, F_RN) \
do_intrinsic(_getCharVolatile, sun_misc_Unsafe, getCharVolatile_name, getChar_signature, F_RN) \
do_intrinsic(_getIntVolatile, sun_misc_Unsafe, getIntVolatile_name, getInt_signature, F_RN) \
do_intrinsic(_getLongVolatile, sun_misc_Unsafe, getLongVolatile_name, getLong_signature, F_RN) \
do_intrinsic(_getFloatVolatile, sun_misc_Unsafe, getFloatVolatile_name, getFloat_signature, F_RN) \
do_intrinsic(_getDoubleVolatile, sun_misc_Unsafe, getDoubleVolatile_name, getDouble_signature, F_RN) \
do_intrinsic(_putObjectVolatile, sun_misc_Unsafe, putObjectVolatile_name, putObject_signature, F_RN) \
do_intrinsic(_putBooleanVolatile, sun_misc_Unsafe, putBooleanVolatile_name, putBoolean_signature, F_RN) \
do_intrinsic(_putByteVolatile, sun_misc_Unsafe, putByteVolatile_name, putByte_signature, F_RN) \
do_intrinsic(_putShortVolatile, sun_misc_Unsafe, putShortVolatile_name, putShort_signature, F_RN) \
do_intrinsic(_putCharVolatile, sun_misc_Unsafe, putCharVolatile_name, putChar_signature, F_RN) \
do_intrinsic(_putIntVolatile, sun_misc_Unsafe, putIntVolatile_name, putInt_signature, F_RN) \
do_intrinsic(_putLongVolatile, sun_misc_Unsafe, putLongVolatile_name, putLong_signature, F_RN) \
do_intrinsic(_putFloatVolatile, sun_misc_Unsafe, putFloatVolatile_name, putFloat_signature, F_RN) \
do_intrinsic(_putDoubleVolatile, sun_misc_Unsafe, putDoubleVolatile_name, putDouble_signature, F_RN) \
\
do_signature(getByte_raw_signature, "(J)B") \
do_signature(putByte_raw_signature, "(JB)V") \
do_signature(getShort_raw_signature, "(J)S") \
do_signature(putShort_raw_signature, "(JS)V") \
do_signature(getChar_raw_signature, "(J)C") \
do_signature(putChar_raw_signature, "(JC)V") \
do_signature(putInt_raw_signature, "(JI)V") \
do_alias(getLong_raw_signature, /*(J)J*/ long_long_signature) \
do_alias(putLong_raw_signature, /*(JJ)V*/ long_long_void_signature) \
do_signature(getFloat_raw_signature, "(J)F") \
do_signature(putFloat_raw_signature, "(JF)V") \
do_alias(getDouble_raw_signature, /*(J)D*/ long_double_signature) \
do_signature(putDouble_raw_signature, "(JD)V") \
do_alias(getAddress_raw_signature, /*(J)J*/ long_long_signature) \
do_alias(putAddress_raw_signature, /*(JJ)V*/ long_long_void_signature) \
\
do_name( getAddress_name, "getAddress") \
do_name( putAddress_name, "putAddress") \
\
do_intrinsic(_getByte_raw, sun_misc_Unsafe, getByte_name, getByte_raw_signature, F_RN) \
do_intrinsic(_getShort_raw, sun_misc_Unsafe, getShort_name, getShort_raw_signature, F_RN) \
do_intrinsic(_getChar_raw, sun_misc_Unsafe, getChar_name, getChar_raw_signature, F_RN) \
do_intrinsic(_getInt_raw, sun_misc_Unsafe, getInt_name, long_int_signature, F_RN) \
do_intrinsic(_getLong_raw, sun_misc_Unsafe, getLong_name, getLong_raw_signature, F_RN) \
do_intrinsic(_getFloat_raw, sun_misc_Unsafe, getFloat_name, getFloat_raw_signature, F_RN) \
do_intrinsic(_getDouble_raw, sun_misc_Unsafe, getDouble_name, getDouble_raw_signature, F_RN) \
do_intrinsic(_getAddress_raw, sun_misc_Unsafe, getAddress_name, getAddress_raw_signature, F_RN) \
do_intrinsic(_putByte_raw, sun_misc_Unsafe, putByte_name, putByte_raw_signature, F_RN) \
do_intrinsic(_putShort_raw, sun_misc_Unsafe, putShort_name, putShort_raw_signature, F_RN) \
do_intrinsic(_putChar_raw, sun_misc_Unsafe, putChar_name, putChar_raw_signature, F_RN) \
do_intrinsic(_putInt_raw, sun_misc_Unsafe, putInt_name, putInt_raw_signature, F_RN) \
do_intrinsic(_putLong_raw, sun_misc_Unsafe, putLong_name, putLong_raw_signature, F_RN) \
do_intrinsic(_putFloat_raw, sun_misc_Unsafe, putFloat_name, putFloat_raw_signature, F_RN) \
do_intrinsic(_putDouble_raw, sun_misc_Unsafe, putDouble_name, putDouble_raw_signature, F_RN) \
do_intrinsic(_putAddress_raw, sun_misc_Unsafe, putAddress_name, putAddress_raw_signature, F_RN) \
\
do_intrinsic(_compareAndSwapObject, sun_misc_Unsafe, compareAndSwapObject_name, compareAndSwapObject_signature, F_RN) \
do_name( compareAndSwapObject_name, "compareAndSwapObject") \
do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
do_intrinsic(_compareAndSwapLong, sun_misc_Unsafe, compareAndSwapLong_name, compareAndSwapLong_signature, F_RN) \
do_name( compareAndSwapLong_name, "compareAndSwapLong") \
do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \
do_intrinsic(_compareAndSwapInt, sun_misc_Unsafe, compareAndSwapInt_name, compareAndSwapInt_signature, F_RN) \
do_name( compareAndSwapInt_name, "compareAndSwapInt") \
do_signature(compareAndSwapInt_signature, "(Ljava/lang/Object;JII)Z") \
do_intrinsic(_putOrderedObject, sun_misc_Unsafe, putOrderedObject_name, putOrderedObject_signature, F_RN) \
do_name( putOrderedObject_name, "putOrderedObject") \
do_alias( putOrderedObject_signature, /*(LObject;JLObject;)V*/ putObject_signature) \
do_intrinsic(_putOrderedLong, sun_misc_Unsafe, putOrderedLong_name, putOrderedLong_signature, F_RN) \
do_name( putOrderedLong_name, "putOrderedLong") \
do_alias( putOrderedLong_signature, /*(Ljava/lang/Object;JJ)V*/ putLong_signature) \
do_intrinsic(_putOrderedInt, sun_misc_Unsafe, putOrderedInt_name, putOrderedInt_signature, F_RN) \
do_name( putOrderedInt_name, "putOrderedInt") \
do_alias( putOrderedInt_signature, /*(Ljava/lang/Object;JI)V*/ putInt_signature) \
\
do_intrinsic(_getAndAddInt, sun_misc_Unsafe, getAndAddInt_name, getAndAddInt_signature, F_R) \
do_name( getAndAddInt_name, "getAndAddInt") \
do_signature(getAndAddInt_signature, "(Ljava/lang/Object;JI)I" ) \
do_intrinsic(_getAndAddLong, sun_misc_Unsafe, getAndAddLong_name, getAndAddLong_signature, F_R) \
do_name( getAndAddLong_name, "getAndAddLong") \
do_signature(getAndAddLong_signature, "(Ljava/lang/Object;JJ)J" ) \
do_intrinsic(_getAndSetInt, sun_misc_Unsafe, getAndSetInt_name, getAndSetInt_signature, F_R) \
do_name( getAndSetInt_name, "getAndSetInt") \
do_alias( getAndSetInt_signature, /*"(Ljava/lang/Object;JI)I"*/ getAndAddInt_signature) \
do_intrinsic(_getAndSetLong, sun_misc_Unsafe, getAndSetLong_name, getAndSetLong_signature, F_R) \
do_name( getAndSetLong_name, "getAndSetLong") \
do_alias( getAndSetLong_signature, /*"(Ljava/lang/Object;JJ)J"*/ getAndAddLong_signature) \
do_intrinsic(_getAndSetObject, sun_misc_Unsafe, getAndSetObject_name, getAndSetObject_signature, F_R)\
do_name( getAndSetObject_name, "getAndSetObject") \
do_signature(getAndSetObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \
\
do_signature( prefetch_signature, "(Ljava/lang/Object;J)V") \
\
do_intrinsic(_prefetchRead, sun_misc_Unsafe, prefetchRead_name, prefetch_signature, F_RN) \
do_name( prefetchRead_name, "prefetchRead") \
do_intrinsic(_prefetchWrite, sun_misc_Unsafe, prefetchWrite_name, prefetch_signature, F_RN) \
do_name( prefetchWrite_name, "prefetchWrite") \
do_intrinsic(_prefetchReadStatic, sun_misc_Unsafe, prefetchReadStatic_name, prefetch_signature, F_SN) \
do_name( prefetchReadStatic_name, "prefetchReadStatic") \
do_intrinsic(_prefetchWriteStatic, sun_misc_Unsafe, prefetchWriteStatic_name, prefetch_signature, F_SN) \
do_name( prefetchWriteStatic_name, "prefetchWriteStatic") \
\
do_intrinsic(_fillInStackTrace, java_lang_Throwable, fillInStackTrace_name, void_throwable_signature, F_RNY) \
\
do_intrinsic(_StringBuilder_void, java_lang_StringBuilder, object_initializer_name, void_method_signature, F_R) \
do_intrinsic(_StringBuilder_int, java_lang_StringBuilder, object_initializer_name, int_void_signature, F_R) \
do_intrinsic(_StringBuilder_String, java_lang_StringBuilder, object_initializer_name, string_void_signature, F_R) \
\
do_intrinsic(_StringBuilder_append_char, java_lang_StringBuilder, append_name, char_StringBuilder_signature, F_R) \
do_intrinsic(_StringBuilder_append_int, java_lang_StringBuilder, append_name, int_StringBuilder_signature, F_R) \
do_intrinsic(_StringBuilder_append_String, java_lang_StringBuilder, append_name, String_StringBuilder_signature, F_R) \
\
do_intrinsic(_StringBuilder_toString, java_lang_StringBuilder, toString_name, void_string_signature, F_R) \
\
do_intrinsic(_StringBuffer_void, java_lang_StringBuffer, object_initializer_name, void_method_signature, F_R) \
do_intrinsic(_StringBuffer_int, java_lang_StringBuffer, object_initializer_name, int_void_signature, F_R) \
do_intrinsic(_StringBuffer_String, java_lang_StringBuffer, object_initializer_name, string_void_signature, F_R) \
\
do_intrinsic(_StringBuffer_append_char, java_lang_StringBuffer, append_name, char_StringBuffer_signature, F_Y) \
do_intrinsic(_StringBuffer_append_int, java_lang_StringBuffer, append_name, int_StringBuffer_signature, F_Y) \
do_intrinsic(_StringBuffer_append_String, java_lang_StringBuffer, append_name, String_StringBuffer_signature, F_Y) \
\
do_intrinsic(_StringBuffer_toString, java_lang_StringBuffer, toString_name, void_string_signature, F_Y) \
\
do_intrinsic(_Integer_toString, java_lang_Integer, toString_name, int_String_signature, F_S) \
\
do_intrinsic(_String_String, java_lang_String, object_initializer_name, string_void_signature, F_R) \
\
do_intrinsic(_Object_init, java_lang_Object, object_initializer_name, void_method_signature, F_R) \
\
do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_object_array_object_signature, F_R) \
do_intrinsic(_invokeGeneric, java_lang_invoke_MethodHandle, invoke_name, star_name, F_RN) \
do_intrinsic(_invokeBasic, java_lang_invoke_MethodHandle, invokeBasic_name, star_name, F_RN) \
do_intrinsic(_linkToVirtual, java_lang_invoke_MethodHandle, linkToVirtual_name, star_name, F_SN) \
do_intrinsic(_linkToStatic, java_lang_invoke_MethodHandle, linkToStatic_name, star_name, F_SN) \
do_intrinsic(_linkToSpecial, java_lang_invoke_MethodHandle, linkToSpecial_name, star_name, F_SN) \
do_intrinsic(_linkToInterface, java_lang_invoke_MethodHandle, linkToInterface_name, star_name, F_SN) \
do_intrinsic(_compiledLambdaForm, java_lang_invoke_MethodHandle, compiledLambdaForm_name, star_name, F_RN) \
\
do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \
do_name( booleanValue_name, "booleanValue") \
do_intrinsic(_byteValue, java_lang_Byte, byteValue_name, void_byte_signature, F_R) \
do_name( byteValue_name, "byteValue") \
do_intrinsic(_charValue, java_lang_Character, charValue_name, void_char_signature, F_R) \
do_name( charValue_name, "charValue") \
do_intrinsic(_shortValue, java_lang_Short, shortValue_name, void_short_signature, F_R) \
do_name( shortValue_name, "shortValue") \
do_intrinsic(_intValue, java_lang_Integer, intValue_name, void_int_signature, F_R) \
do_name( intValue_name, "intValue") \
do_intrinsic(_longValue, java_lang_Long, longValue_name, void_long_signature, F_R) \
do_name( longValue_name, "longValue") \
do_intrinsic(_floatValue, java_lang_Float, floatValue_name, void_float_signature, F_R) \
do_name( floatValue_name, "floatValue") \
do_intrinsic(_doubleValue, java_lang_Double, doubleValue_name, void_double_signature, F_R) \
do_name( doubleValue_name, "doubleValue") \
\
do_name( valueOf_name, "valueOf") \
do_intrinsic(_Boolean_valueOf, java_lang_Boolean, valueOf_name, Boolean_valueOf_signature, F_S) \
do_name( Boolean_valueOf_signature, "(Z)Ljava/lang/Boolean;") \
do_intrinsic(_Byte_valueOf, java_lang_Byte, valueOf_name, Byte_valueOf_signature, F_S) \
do_name( Byte_valueOf_signature, "(B)Ljava/lang/Byte;") \
do_intrinsic(_Character_valueOf, java_lang_Character, valueOf_name, Character_valueOf_signature, F_S) \
do_name( Character_valueOf_signature, "(C)Ljava/lang/Character;") \
do_intrinsic(_Short_valueOf, java_lang_Short, valueOf_name, Short_valueOf_signature, F_S) \
do_name( Short_valueOf_signature, "(S)Ljava/lang/Short;") \
do_intrinsic(_Integer_valueOf, java_lang_Integer, valueOf_name, Integer_valueOf_signature, F_S) \
do_name( Integer_valueOf_signature, "(I)Ljava/lang/Integer;") \
do_intrinsic(_Long_valueOf, java_lang_Long, valueOf_name, Long_valueOf_signature, F_S) \
do_name( Long_valueOf_signature, "(J)Ljava/lang/Long;") \
do_intrinsic(_Float_valueOf, java_lang_Float, valueOf_name, Float_valueOf_signature, F_S) \
do_name( Float_valueOf_signature, "(F)Ljava/lang/Float;") \
do_intrinsic(_Double_valueOf, java_lang_Double, valueOf_name, Double_valueOf_signature, F_S) \
do_name( Double_valueOf_signature, "(D)Ljava/lang/Double;") \
\
class vmSymbols: AllStatic {
friend class vmIntrinsics;
friend class VMStructs;
public:
enum SID {
NO_SID = 0,
#define VM_SYMBOL_ENUM(name, string) VM_SYMBOL_ENUM_NAME(name),
VM_SYMBOLS_DO(VM_SYMBOL_ENUM, VM_ALIAS_IGNORE)
#undef VM_SYMBOL_ENUM
SID_LIMIT,
#define VM_ALIAS_ENUM(name, def) VM_SYMBOL_ENUM_NAME(name) = VM_SYMBOL_ENUM_NAME(def),
VM_SYMBOLS_DO(VM_SYMBOL_IGNORE, VM_ALIAS_ENUM)
#undef VM_ALIAS_ENUM
FIRST_SID = NO_SID + 1
};
enum {
log2_SID_LIMIT = 10 // checked by an assert at start-up
};
private:
static Symbol* _symbols[];
static Symbol* _type_signatures[T_VOID+1];
public:
static void initialize(TRAPS);
#define VM_SYMBOL_DECLARE(name, ignore) \
static Symbol* name() { \
return _symbols[VM_SYMBOL_ENUM_NAME(name)]; \
}
VM_SYMBOLS_DO(VM_SYMBOL_DECLARE, VM_SYMBOL_DECLARE)
#undef VM_SYMBOL_DECLARE
static void symbols_do(SymbolClosure* f);
static void serialize(SerializeClosure* soc);
static Symbol* type_signature(BasicType t) {
assert((uint)t < T_VOID+1, "range check");
assert(_type_signatures[t] != NULL, "domain check");
return _type_signatures[t];
}
static BasicType signature_type(Symbol* s);
static Symbol* symbol_at(SID id) {
assert(id >= FIRST_SID && id < SID_LIMIT, "oob");
assert(_symbols[id] != NULL, "init");
return _symbols[id];
}
static SID find_sid(Symbol* symbol);
static SID find_sid(const char* symbol_name);
#ifndef PRODUCT
static const char* name_for(SID sid);
#endif //PRODUCT
};
class vmIntrinsics: AllStatic {
friend class vmSymbols;
friend class ciObjectFactory;
public:
enum ID {
_none = 0, // not an intrinsic (default answer)
#define VM_INTRINSIC_ENUM(id, klass, name, sig, flags) id,
VM_INTRINSICS_DO(VM_INTRINSIC_ENUM,
VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE)
#undef VM_INTRINSIC_ENUM
ID_LIMIT,
LAST_COMPILER_INLINE = _prefetchWriteStatic,
FIRST_MH_SIG_POLY = _invokeGeneric,
FIRST_MH_STATIC = _linkToVirtual,
LAST_MH_SIG_POLY = _linkToInterface,
FIRST_ID = _none + 1
};
enum Flags {
F_none = 0,
F_R, // !static ?native !synchronized (R="regular")
F_S, // static ?native !synchronized
F_Y, // !static ?native synchronized
F_RN, // !static native !synchronized
F_SN, // static native !synchronized
F_RNY, // !static native synchronized
FLAG_LIMIT
};
enum {
log2_FLAG_LIMIT = 4 // checked by an assert at start-up
};
public:
static ID ID_from(int raw_id) {
assert(raw_id >= (int)_none && raw_id < (int)ID_LIMIT,
"must be a valid intrinsic ID");
return (ID)raw_id;
}
static const char* name_at(ID id);
private:
static ID find_id_impl(vmSymbols::SID holder,
vmSymbols::SID name,
vmSymbols::SID sig,
jshort flags);
public:
static ID find_id(vmSymbols::SID holder,
vmSymbols::SID name,
vmSymbols::SID sig,
jshort flags) {
ID id = find_id_impl(holder, name, sig, flags);
#ifdef ASSERT
if (id == _none) return id;
#endif
assert( class_for(id) == holder, "correct id");
assert( name_for(id) == name, "correct id");
assert(signature_for(id) == sig, "correct id");
return id;
}
static void verify_method(ID actual_id, Method* m) PRODUCT_RETURN;
static vmSymbols::SID class_for(ID id);
static vmSymbols::SID name_for(ID id);
static vmSymbols::SID signature_for(ID id);
static Flags flags_for(ID id);
static const char* short_name_as_C_string(ID id, char* buf, int size);
static ID for_boxing(BasicType type);
static ID for_unboxing(BasicType type);
static ID for_raw_conversion(BasicType src, BasicType dest);
static bool should_be_pinned(vmIntrinsics::ID id);
};
#endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
C:\hotspot-69087d08d473\src\share\vm/code/codeBlob.cpp
#include "precompiled.hpp"
#include "code/codeBlob.hpp"
#include "code/codeCache.hpp"
#include "code/relocInfo.hpp"
#include "compiler/disassembler.hpp"
#include "interpreter/bytecode.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/heap.hpp"
#include "oops/oop.inline.hpp"
#include "prims/forte.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/vframe.hpp"
#include "services/memoryService.hpp"
#ifdef TARGET_ARCH_x86
# include "nativeInst_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "nativeInst_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "nativeInst_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "nativeInst_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "nativeInst_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "nativeInst_ppc.hpp"
#endif
#ifdef COMPILER1
#include "c1/c1_Runtime1.hpp"
#endif
unsigned int CodeBlob::align_code_offset(int offset) {
return
((offset + (int)CodeHeap::header_size() + (CodeEntryAlignment-1)) & ~(CodeEntryAlignment-1))
- (int)CodeHeap::header_size();
}
unsigned int CodeBlob::allocation_size(CodeBuffer* cb, int header_size) {
unsigned int size = header_size;
size += round_to(cb->total_relocation_size(), oopSize);
size = align_code_offset(size);
size += round_to(cb->total_content_size(), oopSize);
size += round_to(cb->total_oop_size(), oopSize);
size += round_to(cb->total_metadata_size(), oopSize);
return size;
}
CodeBlob::CodeBlob(const char* name, int header_size, int size, int frame_complete, int locs_size) {
assert(size == round_to(size, oopSize), "unaligned size");
assert(locs_size == round_to(locs_size, oopSize), "unaligned size");
assert(header_size == round_to(header_size, oopSize), "unaligned size");
assert(!UseRelocIndex, "no space allocated for reloc index yet");
_name = name;
_size = size;
_frame_complete_offset = frame_complete;
_header_size = header_size;
_relocation_size = locs_size;
_content_offset = align_code_offset(header_size + _relocation_size);
_code_offset = _content_offset;
_data_offset = size;
_frame_size = 0;
set_oop_maps(NULL);
}
CodeBlob::CodeBlob(
const char* name,
CodeBuffer* cb,
int header_size,
int size,
int frame_complete,
int frame_size,
OopMapSet* oop_maps
) {
assert(size == round_to(size, oopSize), "unaligned size");
assert(header_size == round_to(header_size, oopSize), "unaligned size");
_name = name;
_size = size;
_frame_complete_offset = frame_complete;
_header_size = header_size;
_relocation_size = round_to(cb->total_relocation_size(), oopSize);
_content_offset = align_code_offset(header_size + _relocation_size);
_code_offset = _content_offset + cb->total_offset_of(cb->insts());
_data_offset = _content_offset + round_to(cb->total_content_size(), oopSize);
assert(_data_offset <= size, "codeBlob is too small");
cb->copy_code_and_locs_to(this);
set_oop_maps(oop_maps);
_frame_size = frame_size;
#ifdef COMPILER1
assert(_frame_size >= -1, "must use frame size or -1 for runtime stubs");
#endif // COMPILER1
}
void CodeBlob::set_oop_maps(OopMapSet* p) {
if (p != NULL) {
_oop_maps = (OopMapSet* )NEW_C_HEAP_ARRAY(unsigned char, p->heap_size(), mtCode);
p->copy_to((address)_oop_maps);
} else {
_oop_maps = NULL;
}
}
void CodeBlob::trace_new_stub(CodeBlob* stub, const char* name1, const char* name2) {
assert(!CodeCache_lock->owned_by_self(), "release CodeCache before registering the stub");
if (stub != NULL) {
char stub_id[256];
assert(strlen(name1) + strlen(name2) < sizeof(stub_id), "");
jio_snprintf(stub_id, sizeof(stub_id), "%s%s", name1, name2);
if (PrintStubCode) {
ttyLocker ttyl;
tty->print_cr("Decoding %s " INTPTR_FORMAT, stub_id, (intptr_t) stub);
Disassembler::decode(stub->code_begin(), stub->code_end());
tty->cr();
}
Forte::register_stub(stub_id, stub->code_begin(), stub->code_end());
if (JvmtiExport::should_post_dynamic_code_generated()) {
const char* stub_name = name2;
if (name2[0] == '\0') stub_name = name1;
JvmtiExport::post_dynamic_code_generated(stub_name, stub->code_begin(), stub->code_end());
}
}
MemoryService::track_code_cache_memory_usage();
}
void CodeBlob::flush() {
if (_oop_maps) {
FREE_C_HEAP_ARRAY(unsigned char, _oop_maps, mtCode);
_oop_maps = NULL;
}
_strings.free();
}
OopMap* CodeBlob::oop_map_for_return_address(address return_address) {
assert(oop_maps() != NULL, "nope");
return oop_maps()->find_map_at_offset((intptr_t) return_address - (intptr_t) code_begin());
}
void CodeBlob::print_code() {
HandleMark hm;
ResourceMark m;
Disassembler::decode(this, tty);
}
BufferBlob::BufferBlob(const char* name, int size)
: CodeBlob(name, sizeof(BufferBlob), size, CodeOffsets::frame_never_safe, /*locs_size:*/ 0)
{}
BufferBlob* BufferBlob::create(const char* name, int buffer_size) {
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
BufferBlob* blob = NULL;
unsigned int size = sizeof(BufferBlob);
size = align_code_offset(size);
size += round_to(buffer_size, oopSize);
assert(name != NULL, "must provide a name");
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
blob = new (size) BufferBlob(name, size);
}
MemoryService::track_code_cache_memory_usage();
return blob;
}
BufferBlob::BufferBlob(const char* name, int size, CodeBuffer* cb)
: CodeBlob(name, cb, sizeof(BufferBlob), size, CodeOffsets::frame_never_safe, 0, NULL)
{}
BufferBlob* BufferBlob::create(const char* name, CodeBuffer* cb) {
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
BufferBlob* blob = NULL;
unsigned int size = allocation_size(cb, sizeof(BufferBlob));
assert(name != NULL, "must provide a name");
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
blob = new (size) BufferBlob(name, size, cb);
}
MemoryService::track_code_cache_memory_usage();
return blob;
}
void* BufferBlob::operator new(size_t s, unsigned size, bool is_critical) throw() {
void* p = CodeCache::allocate(size, is_critical);
return p;
}
void BufferBlob::free( BufferBlob *blob ) {
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
blob->flush();
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
CodeCache::free((CodeBlob*)blob);
}
MemoryService::track_code_cache_memory_usage();
}
AdapterBlob::AdapterBlob(int size, CodeBuffer* cb) :
BufferBlob("I2C/C2I adapters", size, cb) {
CodeCache::commit(this);
}
AdapterBlob* AdapterBlob::create(CodeBuffer* cb) {
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
AdapterBlob* blob = NULL;
unsigned int size = allocation_size(cb, sizeof(AdapterBlob));
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
const bool is_critical = true;
blob = new (size, is_critical) AdapterBlob(size, cb);
}
MemoryService::track_code_cache_memory_usage();
return blob;
}
VtableBlob::VtableBlob(const char* name, int size) :
BufferBlob(name, size) {
}
VtableBlob* VtableBlob::create(const char* name, int buffer_size) {
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
VtableBlob* blob = NULL;
unsigned int size = sizeof(VtableBlob);
size = align_code_offset(size);
size += round_to(buffer_size, oopSize);
assert(name != NULL, "must provide a name");
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
blob = new (size) VtableBlob(name, size);
}
MemoryService::track_code_cache_memory_usage();
return blob;
}
MethodHandlesAdapterBlob* MethodHandlesAdapterBlob::create(int buffer_size) {
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
MethodHandlesAdapterBlob* blob = NULL;
unsigned int size = sizeof(MethodHandlesAdapterBlob);
size = align_code_offset(size);
size += round_to(buffer_size, oopSize);
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
const bool is_critical = true;
blob = new (size, is_critical) MethodHandlesAdapterBlob(size);
}
MemoryService::track_code_cache_memory_usage();
return blob;
}
RuntimeStub::RuntimeStub(
const char* name,
CodeBuffer* cb,
int size,
int frame_complete,
int frame_size,
OopMapSet* oop_maps,
bool caller_must_gc_arguments
)
: CodeBlob(name, cb, sizeof(RuntimeStub), size, frame_complete, frame_size, oop_maps)
{
_caller_must_gc_arguments = caller_must_gc_arguments;
}
RuntimeStub* RuntimeStub::new_runtime_stub(const char* stub_name,
CodeBuffer* cb,
int frame_complete,
int frame_size,
OopMapSet* oop_maps,
bool caller_must_gc_arguments)
{
RuntimeStub* stub = NULL;
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
unsigned int size = allocation_size(cb, sizeof(RuntimeStub));
stub = new (size) RuntimeStub(stub_name, cb, size, frame_complete, frame_size, oop_maps, caller_must_gc_arguments);
}
trace_new_stub(stub, "RuntimeStub - ", stub_name);
return stub;
}
void* RuntimeStub::operator new(size_t s, unsigned size) throw() {
void* p = CodeCache::allocate(size, true);
if (!p) fatal("Initial size of CodeCache is too small");
return p;
}
void* SingletonBlob::operator new(size_t s, unsigned size) throw() {
void* p = CodeCache::allocate(size, true);
if (!p) fatal("Initial size of CodeCache is too small");
return p;
}
DeoptimizationBlob::DeoptimizationBlob(
CodeBuffer* cb,
int size,
OopMapSet* oop_maps,
int unpack_offset,
int unpack_with_exception_offset,
int unpack_with_reexecution_offset,
int frame_size
)
: SingletonBlob("DeoptimizationBlob", cb, sizeof(DeoptimizationBlob), size, frame_size, oop_maps)
{
_unpack_offset = unpack_offset;
_unpack_with_exception = unpack_with_exception_offset;
_unpack_with_reexecution = unpack_with_reexecution_offset;
#ifdef COMPILER1
_unpack_with_exception_in_tls = -1;
#endif
}
DeoptimizationBlob* DeoptimizationBlob::create(
CodeBuffer* cb,
OopMapSet* oop_maps,
int unpack_offset,
int unpack_with_exception_offset,
int unpack_with_reexecution_offset,
int frame_size)
{
DeoptimizationBlob* blob = NULL;
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
unsigned int size = allocation_size(cb, sizeof(DeoptimizationBlob));
blob = new (size) DeoptimizationBlob(cb,
size,
oop_maps,
unpack_offset,
unpack_with_exception_offset,
unpack_with_reexecution_offset,
frame_size);
}
trace_new_stub(blob, "DeoptimizationBlob");
return blob;
}
#ifdef COMPILER2
UncommonTrapBlob::UncommonTrapBlob(
CodeBuffer* cb,
int size,
OopMapSet* oop_maps,
int frame_size
)
: SingletonBlob("UncommonTrapBlob", cb, sizeof(UncommonTrapBlob), size, frame_size, oop_maps)
{}
UncommonTrapBlob* UncommonTrapBlob::create(
CodeBuffer* cb,
OopMapSet* oop_maps,
int frame_size)
{
UncommonTrapBlob* blob = NULL;
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
unsigned int size = allocation_size(cb, sizeof(UncommonTrapBlob));
blob = new (size) UncommonTrapBlob(cb, size, oop_maps, frame_size);
}
trace_new_stub(blob, "UncommonTrapBlob");
return blob;
}
#endif // COMPILER2
#ifdef COMPILER2
ExceptionBlob::ExceptionBlob(
CodeBuffer* cb,
int size,
OopMapSet* oop_maps,
int frame_size
)
: SingletonBlob("ExceptionBlob", cb, sizeof(ExceptionBlob), size, frame_size, oop_maps)
{}
ExceptionBlob* ExceptionBlob::create(
CodeBuffer* cb,
OopMapSet* oop_maps,
int frame_size)
{
ExceptionBlob* blob = NULL;
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
unsigned int size = allocation_size(cb, sizeof(ExceptionBlob));
blob = new (size) ExceptionBlob(cb, size, oop_maps, frame_size);
}
trace_new_stub(blob, "ExceptionBlob");
return blob;
}
#endif // COMPILER2
SafepointBlob::SafepointBlob(
CodeBuffer* cb,
int size,
OopMapSet* oop_maps,
int frame_size
)
: SingletonBlob("SafepointBlob", cb, sizeof(SafepointBlob), size, frame_size, oop_maps)
{}
SafepointBlob* SafepointBlob::create(
CodeBuffer* cb,
OopMapSet* oop_maps,
int frame_size)
{
SafepointBlob* blob = NULL;
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
unsigned int size = allocation_size(cb, sizeof(SafepointBlob));
blob = new (size) SafepointBlob(cb, size, oop_maps, frame_size);
}
trace_new_stub(blob, "SafepointBlob");
return blob;
}
void CodeBlob::verify() {
ShouldNotReachHere();
}
void CodeBlob::print_on(outputStream* st) const {
st->print_cr("[CodeBlob (" INTPTR_FORMAT ")]", p2i(this));
st->print_cr("Framesize: %d", _frame_size);
}
void CodeBlob::print_value_on(outputStream* st) const {
st->print_cr("[CodeBlob]");
}
void BufferBlob::verify() {
}
void BufferBlob::print_on(outputStream* st) const {
CodeBlob::print_on(st);
print_value_on(st);
}
void BufferBlob::print_value_on(outputStream* st) const {
st->print_cr("BufferBlob (" INTPTR_FORMAT ") used for %s", p2i(this), name());
}
void RuntimeStub::verify() {
}
void RuntimeStub::print_on(outputStream* st) const {
ttyLocker ttyl;
CodeBlob::print_on(st);
st->print("Runtime Stub (" INTPTR_FORMAT "): ", p2i(this));
st->print_cr("%s", name());
Disassembler::decode((CodeBlob*)this, st);
}
void RuntimeStub::print_value_on(outputStream* st) const {
st->print("RuntimeStub (" INTPTR_FORMAT "): ", p2i(this)); st->print("%s", name());
}
void SingletonBlob::verify() {
}
void SingletonBlob::print_on(outputStream* st) const {
ttyLocker ttyl;
CodeBlob::print_on(st);
st->print_cr("%s", name());
Disassembler::decode((CodeBlob*)this, st);
}
void SingletonBlob::print_value_on(outputStream* st) const {
st->print_cr("%s", name());
}
void DeoptimizationBlob::print_value_on(outputStream* st) const {
st->print_cr("Deoptimization (frame not available)");
}
C:\hotspot-69087d08d473\src\share\vm/code/codeBlob.hpp
#ifndef SHARE_VM_CODE_CODEBLOB_HPP
#define SHARE_VM_CODE_CODEBLOB_HPP
#include "asm/codeBuffer.hpp"
#include "compiler/oopMap.hpp"
#include "runtime/frame.hpp"
#include "runtime/handles.hpp"
struct CodeBlobType {
enum {
All = 0, // All types (No code cache segmentation)
NumTypes = 1 // Number of CodeBlobTypes
};
};
class DeoptimizationBlob;
class CodeBlob VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
private:
const char* _name;
int _size; // total size of CodeBlob in bytes
int _header_size; // size of header (depends on subclass)
int _relocation_size; // size of relocation
int _content_offset; // offset to where content region begins (this includes consts, insts, stubs)
int _code_offset; // offset to where instructions region begins (this includes insts, stubs)
int _frame_complete_offset; // instruction offsets in [0.._frame_complete_offset) have
int _data_offset; // offset to where data region begins
int _frame_size; // size of stack frame
OopMapSet* _oop_maps; // OopMap for this CodeBlob
CodeStrings _strings;
public:
static unsigned int allocation_size(CodeBuffer* cb, int header_size);
static unsigned int align_code_offset(int offset);
CodeBlob(const char* name, int header_size, int size, int frame_complete, int locs_size);
CodeBlob(
const char* name,
CodeBuffer* cb,
int header_size,
int size,
int frame_complete,
int frame_size,
OopMapSet* oop_maps
);
void flush();
virtual bool is_buffer_blob() const { return false; }
virtual bool is_nmethod() const { return false; }
virtual bool is_runtime_stub() const { return false; }
virtual bool is_deoptimization_stub() const { return false; }
virtual bool is_uncommon_trap_stub() const { return false; }
virtual bool is_exception_stub() const { return false; }
virtual bool is_safepoint_stub() const { return false; }
virtual bool is_adapter_blob() const { return false; }
virtual bool is_vtable_blob() const { return false; }
virtual bool is_method_handles_adapter_blob() const { return false; }
virtual bool is_compiled_by_c2() const { return false; }
virtual bool is_compiled_by_c1() const { return false; }
nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; }
address header_begin() const { return (address) this; }
address header_end() const { return ((address) this) + _header_size; };
relocInfo* relocation_begin() const { return (relocInfo*) header_end(); };
relocInfo* relocation_end() const { return (relocInfo*)(header_end() + _relocation_size); }
address content_begin() const { return (address) header_begin() + _content_offset; }
address content_end() const { return (address) header_begin() + _data_offset; }
address code_begin() const { return (address) header_begin() + _code_offset; }
address code_end() const { return (address) header_begin() + _data_offset; }
address data_begin() const { return (address) header_begin() + _data_offset; }
address data_end() const { return (address) header_begin() + _size; }
int relocation_offset() const { return _header_size; }
int content_offset() const { return _content_offset; }
int code_offset() const { return _code_offset; }
int data_offset() const { return _data_offset; }
int size() const { return _size; }
int header_size() const { return _header_size; }
int relocation_size() const { return (address) relocation_end() - (address) relocation_begin(); }
int content_size() const { return content_end() - content_begin(); }
int code_size() const { return code_end() - code_begin(); }
int data_size() const { return data_end() - data_begin(); }
bool blob_contains(address addr) const { return header_begin() <= addr && addr < data_end(); }
bool relocation_contains(relocInfo* addr) const{ return relocation_begin() <= addr && addr < relocation_end(); }
bool content_contains(address addr) const { return content_begin() <= addr && addr < content_end(); }
bool code_contains(address addr) const { return code_begin() <= addr && addr < code_end(); }
bool data_contains(address addr) const { return data_begin() <= addr && addr < data_end(); }
bool contains(address addr) const { return content_contains(addr); }
bool is_frame_complete_at(address addr) const { return code_contains(addr) &&
addr >= code_begin() + _frame_complete_offset; }
virtual bool is_zombie() const { return false; }
virtual bool is_locked_by_vm() const { return false; }
virtual bool is_unloaded() const { return false; }
virtual bool is_not_entrant() const { return false; }
virtual bool is_alive() const = 0;
OopMapSet* oop_maps() const { return _oop_maps; }
void set_oop_maps(OopMapSet* p);
OopMap* oop_map_for_return_address(address return_address);
virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { ShouldNotReachHere(); }
int frame_size() const { return _frame_size; }
void set_frame_size(int size) { _frame_size = size; }
virtual bool caller_must_gc_arguments(JavaThread* thread) const { return false; }
const char* name() const { return _name; }
void set_name(const char* name) { _name = name; }
virtual void verify();
void print() const { print_on(tty); }
virtual void print_on(outputStream* st) const;
virtual void print_value_on(outputStream* st) const;
void print_code();
static void trace_new_stub(CodeBlob* blob, const char* name1, const char* name2 = "");
virtual void print_block_comment(outputStream* stream, address block_begin) const {
intptr_t offset = (intptr_t)(block_begin - code_begin());
_strings.print_block_comment(stream, offset);
}
void set_strings(CodeStrings& strings) {
_strings.assign(strings);
}
};
class BufferBlob: public CodeBlob {
friend class VMStructs;
friend class AdapterBlob;
friend class VtableBlob;
friend class MethodHandlesAdapterBlob;
friend class WhiteBox;
private:
BufferBlob(const char* name, int size);
BufferBlob(const char* name, int size, CodeBuffer* cb);
void* operator new(size_t s, unsigned size, bool is_critical = false) throw();
public:
static BufferBlob* create(const char* name, int buffer_size);
static BufferBlob* create(const char* name, CodeBuffer* cb);
static void free(BufferBlob* buf);
virtual bool is_buffer_blob() const { return true; }
void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ }
bool is_alive() const { return true; }
void verify();
void print_on(outputStream* st) const;
void print_value_on(outputStream* st) const;
};
class AdapterBlob: public BufferBlob {
private:
AdapterBlob(int size, CodeBuffer* cb);
public:
static AdapterBlob* create(CodeBuffer* cb);
virtual bool is_adapter_blob() const { return true; }
};
class VtableBlob: public BufferBlob {
private:
VtableBlob(const char*, int);
public:
static VtableBlob* create(const char* name, int buffer_size);
virtual bool is_vtable_blob() const { return true; }
};
class MethodHandlesAdapterBlob: public BufferBlob {
private:
MethodHandlesAdapterBlob(int size) : BufferBlob("MethodHandles adapters", size) {}
public:
static MethodHandlesAdapterBlob* create(int buffer_size);
virtual bool is_method_handles_adapter_blob() const { return true; }
};
class RuntimeStub: public CodeBlob {
friend class VMStructs;
private:
bool _caller_must_gc_arguments;
RuntimeStub(
const char* name,
CodeBuffer* cb,
int size,
int frame_complete,
int frame_size,
OopMapSet* oop_maps,
bool caller_must_gc_arguments
);
void* operator new(size_t s, unsigned size) throw();
public:
static RuntimeStub* new_runtime_stub(
const char* stub_name,
CodeBuffer* cb,
int frame_complete,
int frame_size,
OopMapSet* oop_maps,
bool caller_must_gc_arguments
);
bool is_runtime_stub() const { return true; }
bool caller_must_gc_arguments(JavaThread* thread) const { return _caller_must_gc_arguments; }
address entry_point() { return code_begin(); }
void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* nothing to do */ }
bool is_alive() const { return true; }
void verify();
void print_on(outputStream* st) const;
void print_value_on(outputStream* st) const;
};
class SingletonBlob: public CodeBlob {
friend class VMStructs;
protected:
void* operator new(size_t s, unsigned size) throw();
public:
SingletonBlob(
const char* name,
CodeBuffer* cb,
int header_size,
int size,
int frame_size,
OopMapSet* oop_maps
)
: CodeBlob(name, cb, header_size, size, CodeOffsets::frame_never_safe, frame_size, oop_maps)
{};
address entry_point() { return code_begin(); }
bool is_alive() const { return true; }
void verify(); // does nothing
void print_on(outputStream* st) const;
void print_value_on(outputStream* st) const;
};
class DeoptimizationBlob: public SingletonBlob {
friend class VMStructs;
private:
int _unpack_offset;
int _unpack_with_exception;
int _unpack_with_reexecution;
int _unpack_with_exception_in_tls;
DeoptimizationBlob(
CodeBuffer* cb,
int size,
OopMapSet* oop_maps,
int unpack_offset,
int unpack_with_exception_offset,
int unpack_with_reexecution_offset,
int frame_size
);
public:
static DeoptimizationBlob* create(
CodeBuffer* cb,
OopMapSet* oop_maps,
int unpack_offset,
int unpack_with_exception_offset,
int unpack_with_reexecution_offset,
int frame_size
);
bool is_deoptimization_stub() const { return true; }
bool exception_address_is_unpack_entry(address pc) const {
address unpack_pc = unpack();
return (pc == unpack_pc || (pc + frame::pc_return_offset) == unpack_pc);
}
void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* Nothing to do */ }
void print_value_on(outputStream* st) const;
address unpack() const { return code_begin() + _unpack_offset; }
address unpack_with_exception() const { return code_begin() + _unpack_with_exception; }
address unpack_with_reexecution() const { return code_begin() + _unpack_with_reexecution; }
void set_unpack_with_exception_in_tls_offset(int offset) {
_unpack_with_exception_in_tls = offset;
assert(code_contains(code_begin() + _unpack_with_exception_in_tls), "must be PC inside codeblob");
}
address unpack_with_exception_in_tls() const { return code_begin() + _unpack_with_exception_in_tls; }
};
#ifdef COMPILER2
class UncommonTrapBlob: public SingletonBlob {
friend class VMStructs;
private:
UncommonTrapBlob(
CodeBuffer* cb,
int size,
OopMapSet* oop_maps,
int frame_size
);
public:
static UncommonTrapBlob* create(
CodeBuffer* cb,
OopMapSet* oop_maps,
int frame_size
);
void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* nothing to do */ }
bool is_uncommon_trap_stub() const { return true; }
};
class ExceptionBlob: public SingletonBlob {
friend class VMStructs;
private:
ExceptionBlob(
CodeBuffer* cb,
int size,
OopMapSet* oop_maps,
int frame_size
);
public:
static ExceptionBlob* create(
CodeBuffer* cb,
OopMapSet* oop_maps,
int frame_size
);
void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ }
bool is_exception_stub() const { return true; }
};
#endif // COMPILER2
class SafepointBlob: public SingletonBlob {
friend class VMStructs;
private:
SafepointBlob(
CodeBuffer* cb,
int size,
OopMapSet* oop_maps,
int frame_size
);
public:
static SafepointBlob* create(
CodeBuffer* cb,
OopMapSet* oop_maps,
int frame_size
);
void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ }
bool is_safepoint_stub() const { return true; }
};
#endif // SHARE_VM_CODE_CODEBLOB_HPP
C:\hotspot-69087d08d473\src\share\vm/code/codeCache.cpp
#include "precompiled.hpp"
#include "code/codeBlob.hpp"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
#include "code/dependencies.hpp"
#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "code/pcDesc.hpp"
#include "compiler/compileBroker.hpp"
#include "gc_implementation/shared/markSweep.hpp"
#include "jfr/jfrEvents.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/gcLocker.hpp"
#include "memory/iterator.hpp"
#include "memory/resourceArea.hpp"
#include "oops/method.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/arguments.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/icache.hpp"
#include "runtime/java.hpp"
#include "runtime/mutexLocker.hpp"
#include "services/memoryService.hpp"
#include "utilities/xmlstream.hpp"
class CodeBlob_sizes {
private:
int count;
int total_size;
int header_size;
int code_size;
int stub_size;
int relocation_size;
int scopes_oop_size;
int scopes_metadata_size;
int scopes_data_size;
int scopes_pcs_size;
public:
CodeBlob_sizes() {
count = 0;
total_size = 0;
header_size = 0;
code_size = 0;
stub_size = 0;
relocation_size = 0;
scopes_oop_size = 0;
scopes_metadata_size = 0;
scopes_data_size = 0;
scopes_pcs_size = 0;
}
int total() { return total_size; }
bool is_empty() { return count == 0; }
void print(const char* title) {
tty->print_cr(" #%d %s = %dK (hdr %d%%, loc %d%%, code %d%%, stub %d%%, [oops %d%%, metadata %d%%, data %d%%, pcs %d%%])",
count,
title,
(int)(total() / K),
header_size * 100 / total_size,
relocation_size * 100 / total_size,
code_size * 100 / total_size,
stub_size * 100 / total_size,
scopes_oop_size * 100 / total_size,
scopes_metadata_size * 100 / total_size,
scopes_data_size * 100 / total_size,
scopes_pcs_size * 100 / total_size);
}
void add(CodeBlob* cb) {
count++;
total_size += cb->size();
header_size += cb->header_size();
relocation_size += cb->relocation_size();
if (cb->is_nmethod()) {
nmethod* nm = cb->as_nmethod_or_null();
code_size += nm->insts_size();
stub_size += nm->stub_size();
scopes_oop_size += nm->oops_size();
scopes_metadata_size += nm->metadata_size();
scopes_data_size += nm->scopes_data_size();
scopes_pcs_size += nm->scopes_pcs_size();
} else {
code_size += cb->code_size();
}
}
};
CodeHeap * CodeCache::_heap = new CodeHeap();
int CodeCache::_number_of_blobs = 0;
int CodeCache::_number_of_adapters = 0;
int CodeCache::_number_of_nmethods = 0;
int CodeCache::_number_of_nmethods_with_dependencies = 0;
bool CodeCache::_needs_cache_clean = false;
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
int CodeCache::_codemem_full_count = 0;
CodeBlob* CodeCache::first() {
assert_locked_or_safepoint(CodeCache_lock);
return (CodeBlob*)_heap->first();
}
CodeBlob* CodeCache::next(CodeBlob* cb) {
assert_locked_or_safepoint(CodeCache_lock);
return (CodeBlob*)_heap->next(cb);
}
CodeBlob* CodeCache::alive(CodeBlob *cb) {
assert_locked_or_safepoint(CodeCache_lock);
while (cb != NULL && !cb->is_alive()) cb = next(cb);
return cb;
}
nmethod* CodeCache::alive_nmethod(CodeBlob* cb) {
assert_locked_or_safepoint(CodeCache_lock);
while (cb != NULL && (!cb->is_alive() || !cb->is_nmethod())) cb = next(cb);
return (nmethod*)cb;
}
nmethod* CodeCache::first_nmethod() {
assert_locked_or_safepoint(CodeCache_lock);
CodeBlob* cb = first();
while (cb != NULL && !cb->is_nmethod()) {
cb = next(cb);
}
return (nmethod*)cb;
}
nmethod* CodeCache::next_nmethod (CodeBlob* cb) {
assert_locked_or_safepoint(CodeCache_lock);
cb = next(cb);
while (cb != NULL && !cb->is_nmethod()) {
cb = next(cb);
}
return (nmethod*)cb;
}
static size_t maxCodeCacheUsed = 0;
CodeBlob* CodeCache::allocate(int size, bool is_critical) {
guarantee(size >= 0, "allocation request must be reasonable");
assert_locked_or_safepoint(CodeCache_lock);
CodeBlob* cb = NULL;
_number_of_blobs++;
while (true) {
cb = (CodeBlob*)_heap->allocate(size, is_critical);
if (cb != NULL) break;
if (!_heap->expand_by(CodeCacheExpansionSize)) {
if (CodeCache_lock->owned_by_self()) {
MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
report_codemem_full();
} else {
report_codemem_full();
}
return NULL;
}
if (PrintCodeCacheExtension) {
ResourceMark rm;
tty->print_cr("code cache extended to [" INTPTR_FORMAT ", " INTPTR_FORMAT "] (" SSIZE_FORMAT " bytes)",
(intptr_t)_heap->low_boundary(), (intptr_t)_heap->high(),
(address)_heap->high() - (address)_heap->low_boundary());
}
}
maxCodeCacheUsed = MAX2(maxCodeCacheUsed, ((address)_heap->high_boundary() -
(address)_heap->low_boundary()) - unallocated_capacity());
verify_if_often();
print_trace("allocation", cb, size);
return cb;
}
void CodeCache::free(CodeBlob* cb) {
assert_locked_or_safepoint(CodeCache_lock);
verify_if_often();
print_trace("free", cb);
if (cb->is_nmethod()) {
_number_of_nmethods--;
if (((nmethod *)cb)->has_dependencies()) {
_number_of_nmethods_with_dependencies--;
}
}
if (cb->is_adapter_blob()) {
_number_of_adapters--;
}
_number_of_blobs--;
_heap->deallocate(cb);
verify_if_often();
assert(_number_of_blobs >= 0, "sanity check");
}
void CodeCache::commit(CodeBlob* cb) {
assert_locked_or_safepoint(CodeCache_lock);
if (cb->is_nmethod()) {
_number_of_nmethods++;
if (((nmethod *)cb)->has_dependencies()) {
_number_of_nmethods_with_dependencies++;
}
}
if (cb->is_adapter_blob()) {
_number_of_adapters++;
}
ICache::invalidate_range(cb->content_begin(), cb->content_size());
}
void CodeCache::flush() {
assert_locked_or_safepoint(CodeCache_lock);
Unimplemented();
}
#define FOR_ALL_BLOBS(var) for (CodeBlob *var = first() ; var != NULL; var = next(var) )
#define FOR_ALL_ALIVE_BLOBS(var) for (CodeBlob *var = alive(first()); var != NULL; var = alive(next(var)))
#define FOR_ALL_ALIVE_NMETHODS(var) for (nmethod *var = alive_nmethod(first()); var != NULL; var = alive_nmethod(next(var)))
bool CodeCache::contains(void *p) {
return _heap->contains(p);
}
CodeBlob* CodeCache::find_blob(void* start) {
CodeBlob* result = find_blob_unsafe(start);
if (result == NULL) return NULL;
guarantee(!result->is_zombie() || result->is_locked_by_vm() || is_error_reported(), "unsafe access to zombie method");
return result;
}
nmethod* CodeCache::find_nmethod(void* start) {
CodeBlob *cb = find_blob(start);
assert(cb == NULL || cb->is_nmethod(), "did not find an nmethod");
return (nmethod*)cb;
}
void CodeCache::blobs_do(void f(CodeBlob* nm)) {
assert_locked_or_safepoint(CodeCache_lock);
FOR_ALL_BLOBS(p) {
f(p);
}
}
void CodeCache::nmethods_do(void f(nmethod* nm)) {
assert_locked_or_safepoint(CodeCache_lock);
FOR_ALL_BLOBS(nm) {
if (nm->is_nmethod()) f((nmethod*)nm);
}
}
void CodeCache::alive_nmethods_do(void f(nmethod* nm)) {
assert_locked_or_safepoint(CodeCache_lock);
FOR_ALL_ALIVE_NMETHODS(nm) {
f(nm);
}
}
int CodeCache::alignment_unit() {
return (int)_heap->alignment_unit();
}
int CodeCache::alignment_offset() {
return (int)_heap->alignment_offset();
}
void CodeCache::do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred) {
assert_locked_or_safepoint(CodeCache_lock);
FOR_ALL_ALIVE_NMETHODS(nm) {
nm->do_unloading(is_alive, unloading_occurred);
}
}
void CodeCache::blobs_do(CodeBlobClosure* f) {
assert_locked_or_safepoint(CodeCache_lock);
FOR_ALL_ALIVE_BLOBS(cb) {
f->do_code_blob(cb);
#ifdef ASSERT
if (cb->is_nmethod())
((nmethod*)cb)->verify_scavenge_root_oops();
#endif //ASSERT
}
}
void CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure* f) {
assert_locked_or_safepoint(CodeCache_lock);
if (UseG1GC) {
return;
}
const bool fix_relocations = f->fix_relocations();
debug_only(mark_scavenge_root_nmethods());
nmethod* prev = NULL;
nmethod* cur = scavenge_root_nmethods();
while (cur != NULL) {
debug_only(cur->clear_scavenge_root_marked());
assert(cur->scavenge_root_not_marked(), "");
assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
bool is_live = (!cur->is_zombie() && !cur->is_unloaded());
#ifndef PRODUCT
if (TraceScavenge) {
cur->print_on(tty, is_live ? "scavenge root" : "dead scavenge root"); tty->cr();
}
#endif //PRODUCT
if (is_live) {
f->do_code_blob(cur);
}
nmethod* const next = cur->scavenge_root_link();
if (fix_relocations) {
if (!is_live || !cur->detect_scavenge_root_oops()) {
unlink_scavenge_root_nmethod(cur, prev);
} else {
prev = cur;
}
}
cur = next;
}
debug_only(verify_perm_nmethods(NULL));
}
void CodeCache::add_scavenge_root_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
if (UseG1GC) {
return;
}
nm->set_on_scavenge_root_list();
nm->set_scavenge_root_link(_scavenge_root_nmethods);
set_scavenge_root_nmethods(nm);
print_trace("add_scavenge_root", nm);
}
void CodeCache::unlink_scavenge_root_nmethod(nmethod* nm, nmethod* prev) {
assert_locked_or_safepoint(CodeCache_lock);
assert((prev == NULL && scavenge_root_nmethods() == nm) ||
(prev != NULL && prev->scavenge_root_link() == nm), "precondition");
assert(!UseG1GC, "G1 does not use the scavenge_root_nmethods list");
print_trace("unlink_scavenge_root", nm);
if (prev == NULL) {
set_scavenge_root_nmethods(nm->scavenge_root_link());
} else {
prev->set_scavenge_root_link(nm->scavenge_root_link());
}
nm->set_scavenge_root_link(NULL);
nm->clear_on_scavenge_root_list();
}
void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
if (UseG1GC) {
return;
}
print_trace("drop_scavenge_root", nm);
nmethod* prev = NULL;
for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
if (cur == nm) {
unlink_scavenge_root_nmethod(cur, prev);
return;
}
prev = cur;
}
assert(false, "should have been on list");
}
void CodeCache::prune_scavenge_root_nmethods() {
assert_locked_or_safepoint(CodeCache_lock);
if (UseG1GC) {
return;
}
debug_only(mark_scavenge_root_nmethods());
nmethod* last = NULL;
nmethod* cur = scavenge_root_nmethods();
while (cur != NULL) {
nmethod* next = cur->scavenge_root_link();
debug_only(cur->clear_scavenge_root_marked());
assert(cur->scavenge_root_not_marked(), "");
assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
if (!cur->is_zombie() && !cur->is_unloaded()
&& cur->detect_scavenge_root_oops()) {
last = cur;
} else {
print_trace("prune_scavenge_root", cur);
unlink_scavenge_root_nmethod(cur, last);
}
cur = next;
}
debug_only(verify_perm_nmethods(NULL));
}
#ifndef PRODUCT
void CodeCache::asserted_non_scavengable_nmethods_do(CodeBlobClosure* f) {
if (UseG1GC) {
return;
}
mark_scavenge_root_nmethods();
for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
cur->clear_scavenge_root_marked();
}
verify_perm_nmethods(f);
}
void CodeCache::mark_scavenge_root_nmethods() {
FOR_ALL_ALIVE_BLOBS(cb) {
if (cb->is_nmethod()) {
nmethod *nm = (nmethod*)cb;
assert(nm->scavenge_root_not_marked(), "clean state");
if (nm->on_scavenge_root_list())
nm->set_scavenge_root_marked();
}
}
}
void CodeCache::verify_perm_nmethods(CodeBlobClosure* f_or_null) {
FOR_ALL_ALIVE_BLOBS(cb) {
bool call_f = (f_or_null != NULL);
if (cb->is_nmethod()) {
nmethod *nm = (nmethod*)cb;
assert(nm->scavenge_root_not_marked(), "must be already processed");
if (nm->on_scavenge_root_list())
call_f = false; // don't show this one to the client
nm->verify_scavenge_root_oops();
} else {
call_f = false; // not an nmethod
}
if (call_f) f_or_null->do_code_blob(cb);
}
}
#endif //PRODUCT
void CodeCache::verify_clean_inline_caches() {
#ifdef ASSERT
FOR_ALL_ALIVE_BLOBS(cb) {
if (cb->is_nmethod()) {
nmethod* nm = (nmethod*)cb;
assert(!nm->is_unloaded(), "Tautology");
nm->verify_clean_inline_caches();
nm->verify();
}
}
#endif
}
void CodeCache::verify_icholder_relocations() {
#ifdef ASSERT
int count = 0;
FOR_ALL_BLOBS(cb) {
if (cb->is_nmethod()) {
nmethod* nm = (nmethod*)cb;
count += nm->verify_icholder_relocations();
}
}
assert(count + InlineCacheBuffer::pending_icholder_count() + CompiledICHolder::live_not_claimed_count() ==
CompiledICHolder::live_count(), "must agree");
#endif
}
void CodeCache::gc_prologue() {
}
void CodeCache::gc_epilogue() {
assert_locked_or_safepoint(CodeCache_lock);
NOT_DEBUG(if (needs_cache_clean())) {
FOR_ALL_ALIVE_BLOBS(cb) {
if (cb->is_nmethod()) {
nmethod *nm = (nmethod*)cb;
assert(!nm->is_unloaded(), "Tautology");
DEBUG_ONLY(if (needs_cache_clean())) {
nm->cleanup_inline_caches();
}
DEBUG_ONLY(nm->verify());
DEBUG_ONLY(nm->verify_oop_relocations());
}
}
}
set_needs_cache_clean(false);
prune_scavenge_root_nmethods();
verify_icholder_relocations();
}
void CodeCache::verify_oops() {
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
VerifyOopClosure voc;
FOR_ALL_ALIVE_BLOBS(cb) {
if (cb->is_nmethod()) {
nmethod *nm = (nmethod*)cb;
nm->oops_do(&voc);
nm->verify_oop_relocations();
}
}
}
address CodeCache::first_address() {
assert_locked_or_safepoint(CodeCache_lock);
return (address)_heap->low_boundary();
}
address CodeCache::last_address() {
assert_locked_or_safepoint(CodeCache_lock);
return (address)_heap->high();
}
double CodeCache::reverse_free_ratio() {
double unallocated_capacity = (double)(CodeCache::unallocated_capacity() - CodeCacheMinimumFreeSpace);
double max_capacity = (double)CodeCache::max_capacity();
return max_capacity / unallocated_capacity;
}
void icache_init();
void CodeCache::initialize() {
assert(CodeCacheSegmentSize >= (uintx)CodeEntryAlignment, "CodeCacheSegmentSize must be large enough to align entry points");
#ifdef COMPILER2
assert(CodeCacheSegmentSize >= (uintx)OptoLoopAlignment, "CodeCacheSegmentSize must be large enough to align inner loops");
#endif
assert(CodeCacheSegmentSize >= sizeof(jdouble), "CodeCacheSegmentSize must be large enough to align constants");
CodeCacheExpansionSize = round_to(CodeCacheExpansionSize, os::vm_page_size());
InitialCodeCacheSize = round_to(InitialCodeCacheSize, os::vm_page_size());
ReservedCodeCacheSize = round_to(ReservedCodeCacheSize, os::vm_page_size());
if (!_heap->reserve(ReservedCodeCacheSize, InitialCodeCacheSize, CodeCacheSegmentSize)) {
vm_exit_during_initialization("Could not reserve enough space for code cache");
}
MemoryService::add_code_heap_memory_pool(_heap);
icache_init();
os::register_code_area(_heap->low_boundary(), _heap->high_boundary());
}
void codeCache_init() {
CodeCache::initialize();
}
int CodeCache::number_of_nmethods_with_dependencies() {
return _number_of_nmethods_with_dependencies;
}
void CodeCache::clear_inline_caches() {
assert_locked_or_safepoint(CodeCache_lock);
FOR_ALL_ALIVE_NMETHODS(nm) {
nm->clear_inline_caches();
}
}
#ifndef PRODUCT
static elapsedTimer dependentCheckTime;
static int dependentCheckCount = 0;
#endif // PRODUCT
int CodeCache::mark_for_deoptimization(DepChange& changes) {
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
#ifndef PRODUCT
dependentCheckTime.start();
dependentCheckCount++;
#endif // PRODUCT
int number_of_marked_CodeBlobs = 0;
{ No_Safepoint_Verifier nsv;
for (DepChange::ContextStream str(changes, nsv); str.next(); ) {
Klass* d = str.klass();
number_of_marked_CodeBlobs += InstanceKlass::cast(d)->mark_dependent_nmethods(changes);
}
}
if (VerifyDependencies) {
NOT_PRODUCT( FlagSetting fs(TraceDependencies, false) );
FOR_ALL_ALIVE_NMETHODS(nm) {
if (!nm->is_marked_for_deoptimization() &&
nm->check_all_dependencies()) {
ResourceMark rm;
tty->print_cr("Should have been marked for deoptimization:");
changes.print();
nm->print();
nm->print_dependencies();
}
}
}
#ifndef PRODUCT
dependentCheckTime.stop();
#endif // PRODUCT
return number_of_marked_CodeBlobs;
}
#ifdef HOTSWAP
int CodeCache::mark_for_evol_deoptimization(instanceKlassHandle dependee) {
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
int number_of_marked_CodeBlobs = 0;
Array<Method*>* old_methods = dependee->methods();
for (int i = 0; i < old_methods->length(); i++) {
ResourceMark rm;
Method* old_method = old_methods->at(i);
nmethod *nm = old_method->code();
if (nm != NULL) {
nm->mark_for_deoptimization();
number_of_marked_CodeBlobs++;
}
}
FOR_ALL_ALIVE_NMETHODS(nm) {
if (nm->is_marked_for_deoptimization()) {
} else if (nm->is_evol_dependent_on(dependee())) {
ResourceMark rm;
nm->mark_for_deoptimization();
number_of_marked_CodeBlobs++;
} else {
nm->clear_inline_caches();
}
}
return number_of_marked_CodeBlobs;
}
#endif // HOTSWAP
void CodeCache::mark_all_nmethods_for_deoptimization() {
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
FOR_ALL_ALIVE_NMETHODS(nm) {
if (!nm->method()->is_method_handle_intrinsic()) {
nm->mark_for_deoptimization();
}
}
}
int CodeCache::mark_for_deoptimization(Method* dependee) {
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
int number_of_marked_CodeBlobs = 0;
FOR_ALL_ALIVE_NMETHODS(nm) {
if (nm->is_dependent_on_method(dependee)) {
ResourceMark rm;
nm->mark_for_deoptimization();
number_of_marked_CodeBlobs++;
}
}
return number_of_marked_CodeBlobs;
}
void CodeCache::make_marked_nmethods_not_entrant() {
assert_locked_or_safepoint(CodeCache_lock);
FOR_ALL_ALIVE_NMETHODS(nm) {
if (nm->is_marked_for_deoptimization()) {
nm->make_not_entrant();
}
}
}
void CodeCache::verify() {
_heap->verify();
FOR_ALL_ALIVE_BLOBS(p) {
p->verify();
}
}
void CodeCache::report_codemem_full() {
_codemem_full_count++;
EventCodeCacheFull event;
if (event.should_commit()) {
event.set_codeBlobType((u1)CodeBlobType::All);
event.set_startAddress((u8)low_bound());
event.set_commitedTopAddress((u8)high());
event.set_reservedTopAddress((u8)high_bound());
event.set_entryCount(nof_blobs());
event.set_methodCount(nof_nmethods());
event.set_adaptorCount(nof_adapters());
event.set_unallocatedCapacity(unallocated_capacity()/K);
event.set_fullCount(_codemem_full_count);
event.commit();
}
}
#ifndef PRODUCT
void CodeCache::verify_if_often() {
if (VerifyCodeCacheOften) {
_heap->verify();
}
}
void CodeCache::print_trace(const char* event, CodeBlob* cb, int size) {
if (PrintCodeCache2) { // Need to add a new flag
ResourceMark rm;
if (size == 0) size = cb->size();
tty->print_cr("CodeCache %s: addr: " INTPTR_FORMAT ", size: 0x%x", event, p2i(cb), size);
}
}
void CodeCache::print_internals() {
int nmethodCount = 0;
int runtimeStubCount = 0;
int adapterCount = 0;
int deoptimizationStubCount = 0;
int uncommonTrapStubCount = 0;
int bufferBlobCount = 0;
int total = 0;
int nmethodAlive = 0;
int nmethodNotEntrant = 0;
int nmethodZombie = 0;
int nmethodUnloaded = 0;
int nmethodJava = 0;
int nmethodNative = 0;
int maxCodeSize = 0;
ResourceMark rm;
CodeBlob *cb;
for (cb = first(); cb != NULL; cb = next(cb)) {
total++;
if (cb->is_nmethod()) {
nmethod* nm = (nmethod*)cb;
if (Verbose && nm->method() != NULL) {
ResourceMark rm;
char *method_name = nm->method()->name_and_sig_as_C_string();
tty->print("%s", method_name);
if(nm->is_alive()) { tty->print_cr(" alive"); }
if(nm->is_not_entrant()) { tty->print_cr(" not-entrant"); }
if(nm->is_zombie()) { tty->print_cr(" zombie"); }
}
nmethodCount++;
if(nm->is_alive()) { nmethodAlive++; }
if(nm->is_not_entrant()) { nmethodNotEntrant++; }
if(nm->is_zombie()) { nmethodZombie++; }
if(nm->is_unloaded()) { nmethodUnloaded++; }
if(nm->is_native_method()) { nmethodNative++; }
if(nm->method() != NULL && nm->is_java_method()) {
nmethodJava++;
if (nm->insts_size() > maxCodeSize) {
maxCodeSize = nm->insts_size();
}
}
} else if (cb->is_runtime_stub()) {
runtimeStubCount++;
} else if (cb->is_deoptimization_stub()) {
deoptimizationStubCount++;
} else if (cb->is_uncommon_trap_stub()) {
uncommonTrapStubCount++;
} else if (cb->is_adapter_blob()) {
adapterCount++;
} else if (cb->is_buffer_blob()) {
bufferBlobCount++;
}
}
int bucketSize = 512;
int bucketLimit = maxCodeSize / bucketSize + 1;
int *buckets = NEW_C_HEAP_ARRAY(int, bucketLimit, mtCode);
memset(buckets,0,sizeof(int) * bucketLimit);
for (cb = first(); cb != NULL; cb = next(cb)) {
if (cb->is_nmethod()) {
nmethod* nm = (nmethod*)cb;
if(nm->is_java_method()) {
buckets[nm->insts_size() / bucketSize]++;
}
}
}
tty->print_cr("Code Cache Entries (total of %d)",total);
tty->print_cr("-------------------------------------------------");
tty->print_cr("nmethods: %d",nmethodCount);
tty->print_cr("\talive: %d",nmethodAlive);
tty->print_cr("\tnot_entrant: %d",nmethodNotEntrant);
tty->print_cr("\tzombie: %d",nmethodZombie);
tty->print_cr("\tunloaded: %d",nmethodUnloaded);
tty->print_cr("\tjava: %d",nmethodJava);
tty->print_cr("\tnative: %d",nmethodNative);
tty->print_cr("runtime_stubs: %d",runtimeStubCount);
tty->print_cr("adapters: %d",adapterCount);
tty->print_cr("buffer blobs: %d",bufferBlobCount);
tty->print_cr("deoptimization_stubs: %d",deoptimizationStubCount);
tty->print_cr("uncommon_traps: %d",uncommonTrapStubCount);
tty->print_cr("\nnmethod size distribution (non-zombie java)");
tty->print_cr("-------------------------------------------------");
for(int i=0; i<bucketLimit; i++) {
if(buckets[i] != 0) {
tty->print("%d - %d bytes",i*bucketSize,(i+1)*bucketSize);
tty->fill_to(40);
tty->print_cr("%d",buckets[i]);
}
}
FREE_C_HEAP_ARRAY(int, buckets, mtCode);
}
#endif // !PRODUCT
void CodeCache::print() {
print_summary(tty);
#ifndef PRODUCT
if (!Verbose) return;
CodeBlob_sizes live;
CodeBlob_sizes dead;
FOR_ALL_BLOBS(p) {
if (!p->is_alive()) {
dead.add(p);
} else {
live.add(p);
}
}
tty->print_cr("CodeCache:");
tty->print_cr("nmethod dependency checking time %f, per dependent %f", dependentCheckTime.seconds(),
dependentCheckTime.seconds() / dependentCheckCount);
if (!live.is_empty()) {
live.print("live");
}
if (!dead.is_empty()) {
dead.print("dead");
}
if (WizardMode) {
int code_size = 0;
int number_of_blobs = 0;
int number_of_oop_maps = 0;
int map_size = 0;
FOR_ALL_BLOBS(p) {
if (p->is_alive()) {
number_of_blobs++;
code_size += p->code_size();
OopMapSet* set = p->oop_maps();
if (set != NULL) {
number_of_oop_maps += set->size();
map_size += set->heap_size();
}
}
}
tty->print_cr("OopMaps");
tty->print_cr(" #blobs = %d", number_of_blobs);
tty->print_cr(" code size = %d", code_size);
tty->print_cr(" #oop_maps = %d", number_of_oop_maps);
tty->print_cr(" map size = %d", map_size);
}
#endif // !PRODUCT
}
void CodeCache::print_summary(outputStream* st, bool detailed) {
size_t total = (_heap->high_boundary() - _heap->low_boundary());
st->print_cr("CodeCache: size=" SIZE_FORMAT "Kb used=" SIZE_FORMAT
"Kb max_used=" SIZE_FORMAT "Kb free=" SIZE_FORMAT "Kb",
total/K, (total - unallocated_capacity())/K,
maxCodeCacheUsed/K, unallocated_capacity()/K);
if (detailed) {
st->print_cr(" bounds [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT "]",
p2i(_heap->low_boundary()),
p2i(_heap->high()),
p2i(_heap->high_boundary()));
st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT
" adapters=" UINT32_FORMAT,
nof_blobs(), nof_nmethods(), nof_adapters());
st->print_cr(" compilation: %s", CompileBroker::should_compile_new_jobs() ?
"enabled" : Arguments::mode() == Arguments::_int ?
"disabled (interpreter mode)" :
"disabled (not enough contiguous free space left)");
}
}
void CodeCache::log_state(outputStream* st) {
st->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
" adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
nof_blobs(), nof_nmethods(), nof_adapters(),
unallocated_capacity());
}
C:\hotspot-69087d08d473\src\share\vm/code/codeCache.hpp
#ifndef SHARE_VM_CODE_CODECACHE_HPP
#define SHARE_VM_CODE_CODECACHE_HPP
#include "code/codeBlob.hpp"
#include "memory/allocation.hpp"
#include "memory/heap.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oopsHierarchy.hpp"
class OopClosure;
class DepChange;
class CodeCache : AllStatic {
friend class VMStructs;
private:
static CodeHeap * _heap;
static int _number_of_blobs;
static int _number_of_adapters;
static int _number_of_nmethods;
static int _number_of_nmethods_with_dependencies;
static bool _needs_cache_clean;
static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link()
static void verify_if_often() PRODUCT_RETURN;
static void mark_scavenge_root_nmethods() PRODUCT_RETURN;
static void verify_perm_nmethods(CodeBlobClosure* f_or_null) PRODUCT_RETURN;
static int _codemem_full_count;
static void set_scavenge_root_nmethods(nmethod* nm) { _scavenge_root_nmethods = nm; }
static void prune_scavenge_root_nmethods();
static void unlink_scavenge_root_nmethod(nmethod* nm, nmethod* prev);
public:
static void initialize();
static void report_codemem_full();
static CodeBlob* allocate(int size, bool is_critical = false); // allocates a new CodeBlob
static void commit(CodeBlob* cb); // called when the allocated CodeBlob has been filled
static int alignment_unit(); // guaranteed alignment of all CodeBlobs
static int alignment_offset(); // guaranteed offset of first CodeBlob byte within alignment unit (i.e., allocation header)
static void free(CodeBlob* cb); // frees a CodeBlob
static void flush(); // flushes all CodeBlobs
static bool contains(void *p); // returns whether p is included
static void blobs_do(void f(CodeBlob* cb)); // iterates over all CodeBlobs
static void blobs_do(CodeBlobClosure* f); // iterates over all CodeBlobs
static void nmethods_do(void f(nmethod* nm)); // iterates over all nmethods
static void alive_nmethods_do(void f(nmethod* nm)); // iterates over all alive nmethods
static CodeBlob* find_blob(void* start);
static nmethod* find_nmethod(void* start);
static CodeBlob* find_blob_unsafe(void* start) {
if (_heap == NULL) return NULL;
CodeBlob* result = (CodeBlob*)_heap->find_start(start);
if (result != NULL && !result->blob_contains((address)start)) {
result = NULL;
}
return result;
}
static CodeBlob* first();
static CodeBlob* next (CodeBlob* cb);
static CodeBlob* alive(CodeBlob *cb);
static nmethod* alive_nmethod(CodeBlob *cb);
static nmethod* first_nmethod();
static nmethod* next_nmethod (CodeBlob* cb);
static int nof_blobs() { return _number_of_blobs; }
static int nof_adapters() { return _number_of_adapters; }
static int nof_nmethods() { return _number_of_nmethods; }
static void gc_epilogue();
static void gc_prologue();
static void verify_oops();
static void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
static void asserted_non_scavengable_nmethods_do(CodeBlobClosure* f = NULL) PRODUCT_RETURN;
static void scavenge_root_nmethods_do(CodeBlobToOopClosure* f);
static nmethod* scavenge_root_nmethods() { return _scavenge_root_nmethods; }
static void add_scavenge_root_nmethod(nmethod* nm);
static void drop_scavenge_root_nmethod(nmethod* nm);
static void print(); // prints summary
static void print_internals();
static void verify(); // verifies the code cache
static void print_trace(const char* event, CodeBlob* cb, int size = 0) PRODUCT_RETURN;
static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage
static void log_state(outputStream* st);
static address low_bound() { return (address) _heap->low_boundary(); }
static address high_bound() { return (address) _heap->high_boundary(); }
static address high() { return (address) _heap->high(); }
static address first_address(); // first address used for CodeBlobs
static address last_address(); // last address used for CodeBlobs
static size_t capacity() { return _heap->capacity(); }
static size_t max_capacity() { return _heap->max_capacity(); }
static size_t unallocated_capacity() { return _heap->unallocated_capacity(); }
static double reverse_free_ratio();
static bool needs_cache_clean() { return _needs_cache_clean; }
static void set_needs_cache_clean(bool v) { _needs_cache_clean = v; }
static void clear_inline_caches(); // clear all inline caches
static void verify_clean_inline_caches();
static void verify_icholder_relocations();
static int mark_for_deoptimization(DepChange& changes);
#ifdef HOTSWAP
static int mark_for_evol_deoptimization(instanceKlassHandle dependee);
#endif // HOTSWAP
static void mark_all_nmethods_for_deoptimization();
static int mark_for_deoptimization(Method* dependee);
static void make_marked_nmethods_not_entrant();
static int number_of_nmethods_with_dependencies();
static int get_codemem_full_count() { return _codemem_full_count; }
};
#endif // SHARE_VM_CODE_CODECACHE_HPP
C:\hotspot-69087d08d473\src\share\vm/code/compiledIC.cpp
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/oopFactory.hpp"
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/icache.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/events.hpp"
void* CompiledIC::cached_value() const {
assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
assert (!is_optimized(), "an optimized virtual call does not have a cached metadata");
if (!is_in_transition_state()) {
void* data = (void*)_value->data();
assert(data != NULL || Universe::non_oop_word() == NULL,
"no raw nulls in CompiledIC metadatas, because of patching races");
return (data == (void*)Universe::non_oop_word()) ? NULL : data;
} else {
return InlineCacheBuffer::cached_value_for((CompiledIC *)this);
}
}
void CompiledIC::internal_set_ic_destination(address entry_point, bool is_icstub, void* cache, bool is_icholder) {
assert(entry_point != NULL, "must set legal entry point");
assert(CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
assert (!is_optimized() || cache == NULL, "an optimized virtual call does not have a cached metadata");
assert (cache == NULL || cache != (Metadata*)badOopVal, "invalid metadata");
assert(!is_icholder || is_icholder_entry(entry_point), "must be");
if (is_icholder_entry(_ic_call->destination())) {
InlineCacheBuffer::queue_for_release((CompiledICHolder*)_value->data());
}
if (TraceCompiledIC) {
tty->print(" ");
print_compiled_ic();
tty->print(" changing destination to " INTPTR_FORMAT, p2i(entry_point));
if (!is_optimized()) {
tty->print(" changing cached %s to " INTPTR_FORMAT, is_icholder ? "icholder" : "metadata", p2i((address)cache));
}
if (is_icstub) {
tty->print(" (icstub)");
}
tty->cr();
}
{
MutexLockerEx pl(SafepointSynchronize::is_at_safepoint() ? NULL : Patching_lock, Mutex::_no_safepoint_check_flag);
#ifdef ASSERT
CodeBlob* cb = CodeCache::find_blob_unsafe(_ic_call);
assert(cb != NULL && cb->is_nmethod(), "must be nmethod");
#endif
_ic_call->set_destination_mt_safe(entry_point);
}
if (is_optimized() || is_icstub) {
assert(cache == NULL, "must be null");
return;
}
if (cache == NULL) cache = (void*)Universe::non_oop_word();
_value->set_data((intptr_t)cache);
}
void CompiledIC::set_ic_destination(ICStub* stub) {
internal_set_ic_destination(stub->code_begin(), true, NULL, false);
}
address CompiledIC::ic_destination() const {
assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
if (!is_in_transition_state()) {
return _ic_call->destination();
} else {
return InlineCacheBuffer::ic_destination_for((CompiledIC *)this);
}
}
bool CompiledIC::is_in_transition_state() const {
assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
return InlineCacheBuffer::contains(_ic_call->destination());
}
bool CompiledIC::is_icholder_call() const {
assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
return !_is_optimized && is_icholder_entry(ic_destination());
}
address CompiledIC::stub_address() const {
assert(is_in_transition_state(), "should only be called when we are in a transition state");
return _ic_call->destination();
}
void CompiledIC::clear_ic_stub() {
if (is_in_transition_state()) {
ICStub* stub = ICStub_from_destination_address(stub_address());
stub->clear();
}
}
void CompiledIC::initialize_from_iter(RelocIterator* iter) {
assert(iter->addr() == _ic_call->instruction_address(), "must find ic_call");
if (iter->type() == relocInfo::virtual_call_type) {
virtual_call_Relocation* r = iter->virtual_call_reloc();
_is_optimized = false;
_value = nativeMovConstReg_at(r->cached_value());
} else {
assert(iter->type() == relocInfo::opt_virtual_call_type, "must be a virtual call");
_is_optimized = true;
_value = NULL;
}
}
CompiledIC::CompiledIC(nmethod* nm, NativeCall* call)
: _ic_call(call)
{
address ic_call = _ic_call->instruction_address();
assert(ic_call != NULL, "ic_call address must be set");
assert(nm != NULL, "must pass nmethod");
assert(nm->contains(ic_call), "must be in nmethod");
RelocIterator iter(nm, ic_call, ic_call+1);
bool ret = iter.next();
assert(ret == true, "relocInfo must exist at this address");
assert(iter.addr() == ic_call, "must find ic_call");
initialize_from_iter(&iter);
}
CompiledIC::CompiledIC(RelocIterator* iter)
: _ic_call(nativeCall_at(iter->addr()))
{
address ic_call = _ic_call->instruction_address();
nmethod* nm = iter->code();
assert(ic_call != NULL, "ic_call address must be set");
assert(nm != NULL, "must pass nmethod");
assert(nm->contains(ic_call), "must be in nmethod");
initialize_from_iter(iter);
}
bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS) {
assert(CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
assert(!is_optimized(), "cannot set an optimized virtual call to megamorphic");
assert(is_call_to_compiled() || is_call_to_interpreted(), "going directly to megamorphic?");
address entry;
if (call_info->call_kind() == CallInfo::itable_call) {
assert(bytecode == Bytecodes::_invokeinterface, "");
int itable_index = call_info->itable_index();
entry = VtableStubs::find_itable_stub(itable_index);
if (entry == false) {
return false;
}
#ifdef ASSERT
int index = call_info->resolved_method()->itable_index();
assert(index == itable_index, "CallInfo pre-computes this");
InstanceKlass* k = call_info->resolved_method()->method_holder();
assert(k->verify_itable_index(itable_index), "sanity check");
#endif //ASSERT
CompiledICHolder* holder = new CompiledICHolder(call_info->resolved_method()->method_holder(),
call_info->resolved_klass()(), false);
holder->claim();
InlineCacheBuffer::create_transition_stub(this, holder, entry);
} else {
assert(call_info->call_kind() == CallInfo::vtable_call, "either itable or vtable");
int vtable_index = call_info->vtable_index();
assert(call_info->resolved_klass()->verify_vtable_index(vtable_index), "sanity check");
entry = VtableStubs::find_vtable_stub(vtable_index);
if (entry == NULL) {
return false;
}
InlineCacheBuffer::create_transition_stub(this, NULL, entry);
}
if (TraceICs) {
ResourceMark rm;
tty->print_cr ("IC@" INTPTR_FORMAT ": to megamorphic %s entry: " INTPTR_FORMAT,
p2i(instruction_address()), call_info->selected_method()->print_value_string(), p2i(entry));
}
return true;
}
bool CompiledIC::is_megamorphic() const {
assert(CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
assert(!is_optimized(), "an optimized call cannot be megamorphic");
return VtableStubs::entry_point(ic_destination()) != NULL;
}
bool CompiledIC::is_call_to_compiled() const {
assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
CodeBlob* cb = CodeCache::find_blob_unsafe(ic_destination());
bool is_monomorphic = (cb != NULL && cb->is_nmethod());
#ifdef ASSERT
CodeBlob* caller = CodeCache::find_blob_unsafe(instruction_address());
bool is_c1_method = caller->is_compiled_by_c1();
assert( is_c1_method ||
!is_monomorphic ||
is_optimized() ||
!caller->is_alive() ||
(cached_metadata() != NULL && cached_metadata()->is_klass()), "sanity check");
#endif // ASSERT
return is_monomorphic;
}
bool CompiledIC::is_call_to_interpreted() const {
assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
bool is_call_to_interpreted = false;
if (!is_optimized()) {
CodeBlob* cb = CodeCache::find_blob_unsafe(ic_destination());
is_call_to_interpreted = (cb != NULL && cb->is_adapter_blob());
assert(!is_call_to_interpreted || (is_icholder_call() && cached_icholder() != NULL), "sanity check");
} else {
CodeBlob* cb = CodeCache::find_blob(_ic_call->instruction_address());
address dest = ic_destination();
#ifdef ASSERT
{
CodeBlob* db = CodeCache::find_blob_unsafe(dest);
assert(!db->is_adapter_blob(), "must use stub!");
}
#endif /* ASSERT */
is_call_to_interpreted = cb->contains(dest);
}
return is_call_to_interpreted;
}
void CompiledIC::set_to_clean(bool in_use) {
assert(SafepointSynchronize::is_at_safepoint() || CompiledIC_lock->is_locked() , "MT-unsafe call");
if (TraceInlineCacheClearing || TraceICs) {
tty->print_cr("IC@" INTPTR_FORMAT ": set to clean", p2i(instruction_address()));
print();
}
address entry;
if (is_optimized()) {
entry = SharedRuntime::get_resolve_opt_virtual_call_stub();
} else {
entry = SharedRuntime::get_resolve_virtual_call_stub();
}
bool safe_transition = !in_use || is_optimized() || SafepointSynchronize::is_at_safepoint();
if (safe_transition) {
clear_ic_stub();
if (is_optimized()) {
set_ic_destination(entry);
} else {
set_ic_destination_and_value(entry, (void*)NULL);
}
} else {
InlineCacheBuffer::create_transition_stub(this, NULL, entry);
}
}
bool CompiledIC::is_clean() const {
assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
bool is_clean = false;
address dest = ic_destination();
is_clean = dest == SharedRuntime::get_resolve_opt_virtual_call_stub() ||
dest == SharedRuntime::get_resolve_virtual_call_stub();
assert(!is_clean || is_optimized() || cached_value() == NULL, "sanity check");
return is_clean;
}
void CompiledIC::set_to_monomorphic(CompiledICInfo& info) {
assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
Thread *thread = Thread::current();
if (info.to_interpreter()) {
if (info.is_optimized() && is_optimized()) {
assert(is_clean(), "unsafe IC path");
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
assert(info.cached_metadata() != NULL && info.cached_metadata()->is_method(), "sanity check");
CompiledStaticCall* csc = compiledStaticCall_at(instruction_address());
methodHandle method (thread, (Method*)info.cached_metadata());
csc->set_to_interpreted(method, info.entry());
if (TraceICs) {
ResourceMark rm(thread);
tty->print_cr ("IC@" INTPTR_FORMAT ": monomorphic to interpreter: %s",
p2i(instruction_address()),
method->print_value_string());
}
} else {
InlineCacheBuffer::create_transition_stub(this, info.claim_cached_icholder(), info.entry());
if (TraceICs) {
ResourceMark rm(thread);
tty->print_cr ("IC@" INTPTR_FORMAT ": monomorphic to interpreter via icholder ", p2i(instruction_address()));
}
}
} else {
bool static_bound = info.is_optimized() || (info.cached_metadata() == NULL);
#ifdef ASSERT
CodeBlob* cb = CodeCache::find_blob_unsafe(info.entry());
assert (cb->is_nmethod(), "must be compiled!");
#endif /* ASSERT */
bool safe = SafepointSynchronize::is_at_safepoint() ||
(!is_in_transition_state() && (info.is_optimized() || static_bound || is_clean()));
if (!safe) {
InlineCacheBuffer::create_transition_stub(this, info.cached_metadata(), info.entry());
} else {
if (is_optimized()) {
set_ic_destination(info.entry());
} else {
set_ic_destination_and_value(info.entry(), info.cached_metadata());
}
}
if (TraceICs) {
ResourceMark rm(thread);
assert(info.cached_metadata() == NULL || info.cached_metadata()->is_klass(), "must be");
tty->print_cr ("IC@" INTPTR_FORMAT ": monomorphic to compiled (rcvr klass) %s: %s",
p2i(instruction_address()),
((Klass*)info.cached_metadata())->print_value_string(),
(safe) ? "" : "via stub");
}
}
}
void CompiledIC::compute_monomorphic_entry(methodHandle method,
KlassHandle receiver_klass,
bool is_optimized,
bool static_bound,
CompiledICInfo& info,
TRAPS) {
nmethod* method_code = method->code();
address entry = NULL;
if (method_code != NULL && method_code->is_in_use()) {
if (static_bound || is_optimized) {
entry = method_code->verified_entry_point();
} else {
entry = method_code->entry_point();
}
}
if (entry != NULL) {
info.set_compiled_entry(entry, (static_bound || is_optimized) ? NULL : receiver_klass(), is_optimized);
} else {
#ifdef COMPILER2
#ifdef TIERED
#if defined(ASSERT)
#endif // ASSERT
#else
assert(!static_bound || is_optimized, "static_bound should imply is_optimized");
#endif // TIERED
#endif // COMPILER2
if (is_optimized) {
info.set_interpreter_entry(method()->get_c2i_entry(), method());
} else {
CompiledICHolder* holder = new CompiledICHolder(method(), receiver_klass());
info.set_icholder_entry(method()->get_c2i_unverified_entry(), holder);
}
}
assert(info.is_optimized() == is_optimized, "must agree");
}
bool CompiledIC::is_icholder_entry(address entry) {
CodeBlob* cb = CodeCache::find_blob_unsafe(entry);
if (cb != NULL && cb->is_adapter_blob()) {
return true;
}
if (cb != NULL && cb->is_vtable_blob()) {
VtableStub* s = VtableStubs::entry_point(entry);
return (s != NULL) && s->is_itable_stub();
}
return false;
}
void CompiledStaticCall::set_to_clean() {
assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
MutexLockerEx pl(SafepointSynchronize::is_at_safepoint() ? NULL : Patching_lock, Mutex::_no_safepoint_check_flag);
#ifdef ASSERT
CodeBlob* cb = CodeCache::find_blob_unsafe(this);
assert(cb != NULL && cb->is_nmethod(), "must be nmethod");
#endif
set_destination_mt_safe(SharedRuntime::get_resolve_static_call_stub());
}
bool CompiledStaticCall::is_clean() const {
return destination() == SharedRuntime::get_resolve_static_call_stub();
}
bool CompiledStaticCall::is_call_to_compiled() const {
return CodeCache::contains(destination());
}
bool CompiledStaticCall::is_call_to_interpreted() const {
nmethod* nm = CodeCache::find_nmethod(instruction_address());
return nm->stub_contains(destination());
}
void CompiledStaticCall::set(const StaticCallInfo& info) {
assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
assert(is_clean(), "do not update a call entry - use clean");
if (info._to_interpreter) {
set_to_interpreted(info.callee(), info.entry());
} else {
if (TraceICs) {
ResourceMark rm;
tty->print_cr("CompiledStaticCall@" INTPTR_FORMAT ": set_to_compiled " INTPTR_FORMAT,
p2i(instruction_address()),
p2i(info.entry()));
}
assert (CodeCache::contains(info.entry()), "wrong entry point");
set_destination_mt_safe(info.entry());
}
}
void CompiledStaticCall::compute_entry(methodHandle m, StaticCallInfo& info) {
nmethod* m_code = m->code();
info._callee = m;
if (m_code != NULL && m_code->is_in_use()) {
info._to_interpreter = false;
info._entry = m_code->verified_entry_point();
} else {
assert(!m->is_method_handle_intrinsic(), "Compiled code should never call interpreter MH intrinsics");
info._to_interpreter = true;
info._entry = m()->get_c2i_entry();
}
}
address CompiledStaticCall::find_stub() {
RelocIterator iter((nmethod*)NULL, instruction_address());
while (iter.next()) {
if (iter.addr() == instruction_address()) {
switch(iter.type()) {
case relocInfo::static_call_type:
return iter.static_call_reloc()->static_stub();
case relocInfo::opt_virtual_call_type:
return iter.opt_virtual_call_reloc()->static_stub();
case relocInfo::poll_type:
case relocInfo::poll_return_type: // A safepoint can't overlap a call.
default:
ShouldNotReachHere();
}
}
}
return NULL;
}
#ifndef PRODUCT
void CompiledIC::verify() {
_ic_call->verify();
if (os::is_MP()) {
_ic_call->verify_alignment();
}
assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted()
|| is_optimized() || is_megamorphic(), "sanity check");
}
void CompiledIC::print() {
print_compiled_ic();
tty->cr();
}
void CompiledIC::print_compiled_ic() {
tty->print("Inline cache at " INTPTR_FORMAT ", calling %s " INTPTR_FORMAT " cached_value " INTPTR_FORMAT,
p2i(instruction_address()), is_call_to_interpreted() ? "interpreted " : "", p2i(ic_destination()), p2i(is_optimized() ? NULL : cached_value()));
}
void CompiledStaticCall::print() {
tty->print("static call at " INTPTR_FORMAT " -> ", p2i(instruction_address()));
if (is_clean()) {
tty->print("clean");
} else if (is_call_to_compiled()) {
tty->print("compiled");
} else if (is_call_to_interpreted()) {
tty->print("interpreted");
}
tty->cr();
}
#endif // !PRODUCT
C:\hotspot-69087d08d473\src\share\vm/code/compiledIC.hpp
#ifndef SHARE_VM_CODE_COMPILEDIC_HPP
#define SHARE_VM_CODE_COMPILEDIC_HPP
#include "interpreter/linkResolver.hpp"
#include "oops/compiledICHolder.hpp"
#ifdef TARGET_ARCH_x86
# include "nativeInst_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "nativeInst_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "nativeInst_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "nativeInst_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "nativeInst_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "nativeInst_ppc.hpp"
#endif
class CompiledIC;
class ICStub;
class CompiledICInfo : public StackObj {
private:
address _entry; // entry point for call
void* _cached_value; // Value of cached_value (either in stub or inline cache)
bool _is_icholder; // Is the cached value a CompiledICHolder*
bool _is_optimized; // it is an optimized virtual call (i.e., can be statically bound)
bool _to_interpreter; // Call it to interpreter
bool _release_icholder;
public:
address entry() const { return _entry; }
Metadata* cached_metadata() const { assert(!_is_icholder, ""); return (Metadata*)_cached_value; }
CompiledICHolder* claim_cached_icholder() {
assert(_is_icholder, "");
assert(_cached_value != NULL, "must be non-NULL");
_release_icholder = false;
CompiledICHolder* icholder = (CompiledICHolder*)_cached_value;
icholder->claim();
return icholder;
}
bool is_optimized() const { return _is_optimized; }
bool to_interpreter() const { return _to_interpreter; }
void set_compiled_entry(address entry, Klass* klass, bool is_optimized) {
_entry = entry;
_cached_value = (void*)klass;
_to_interpreter = false;
_is_icholder = false;
_is_optimized = is_optimized;
_release_icholder = false;
}
void set_interpreter_entry(address entry, Method* method) {
_entry = entry;
_cached_value = (void*)method;
_to_interpreter = true;
_is_icholder = false;
_is_optimized = true;
_release_icholder = false;
}
void set_icholder_entry(address entry, CompiledICHolder* icholder) {
_entry = entry;
_cached_value = (void*)icholder;
_to_interpreter = true;
_is_icholder = true;
_is_optimized = false;
_release_icholder = true;
}
CompiledICInfo(): _entry(NULL), _cached_value(NULL), _is_icholder(false),
_to_interpreter(false), _is_optimized(false), _release_icholder(false) {
}
~CompiledICInfo() {
if (_release_icholder) {
assert(_is_icholder, "must be");
CompiledICHolder* icholder = (CompiledICHolder*)_cached_value;
icholder->claim();
delete icholder;
}
}
};
class CompiledIC: public ResourceObj {
friend class InlineCacheBuffer;
friend class ICStub;
private:
NativeCall* _ic_call; // the call instruction
NativeMovConstReg* _value; // patchable value cell for this IC
bool _is_optimized; // an optimized virtual call (i.e., no compiled IC)
CompiledIC(nmethod* nm, NativeCall* ic_call);
CompiledIC(RelocIterator* iter);
void initialize_from_iter(RelocIterator* iter);
static bool is_icholder_entry(address entry);
void internal_set_ic_destination(address entry_point, bool is_icstub, void* cache, bool is_icholder);
void set_ic_destination(ICStub* stub);
void set_ic_destination(address entry_point) {
assert(_is_optimized, "use set_ic_destination_and_value instead");
internal_set_ic_destination(entry_point, false, NULL, false);
}
void set_ic_destination_and_value(address entry_point, void* value) {
internal_set_ic_destination(entry_point, false, value, is_icholder_entry(entry_point));
}
void set_ic_destination_and_value(address entry_point, Metadata* value) {
internal_set_ic_destination(entry_point, false, value, false);
}
void set_ic_destination_and_value(address entry_point, CompiledICHolder* value) {
internal_set_ic_destination(entry_point, false, value, true);
}
address stub_address() const;
bool is_in_transition_state() const; // Use InlineCacheBuffer
public:
friend CompiledIC* CompiledIC_before(nmethod* nm, address return_addr);
friend CompiledIC* CompiledIC_at(nmethod* nm, address call_site);
friend CompiledIC* CompiledIC_at(Relocation* call_site);
friend CompiledIC* CompiledIC_at(RelocIterator* reloc_iter);
static void cleanup_call_site(virtual_call_Relocation* call_site);
static bool is_icholder_call_site(virtual_call_Relocation* call_site);
void* cached_value() const;
CompiledICHolder* cached_icholder() const {
assert(is_icholder_call(), "must be");
return (CompiledICHolder*) cached_value();
}
Metadata* cached_metadata() const {
assert(!is_icholder_call(), "must be");
return (Metadata*) cached_value();
}
address ic_destination() const;
bool is_optimized() const { return _is_optimized; }
bool is_clean() const;
bool is_megamorphic() const;
bool is_call_to_compiled() const;
bool is_call_to_interpreted() const;
bool is_icholder_call() const;
address end_of_call() { return _ic_call->return_address(); }
void set_to_clean(bool in_use = true);
void set_to_monomorphic(CompiledICInfo& info);
void clear_ic_stub();
bool set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS);
static void compute_monomorphic_entry(methodHandle method, KlassHandle receiver_klass,
bool is_optimized, bool static_bound, CompiledICInfo& info, TRAPS);
address instruction_address() const { return _ic_call->instruction_address(); }
void print() PRODUCT_RETURN;
void print_compiled_ic() PRODUCT_RETURN;
void verify() PRODUCT_RETURN;
};
inline CompiledIC* CompiledIC_before(nmethod* nm, address return_addr) {
CompiledIC* c_ic = new CompiledIC(nm, nativeCall_before(return_addr));
c_ic->verify();
return c_ic;
}
inline CompiledIC* CompiledIC_at(nmethod* nm, address call_site) {
CompiledIC* c_ic = new CompiledIC(nm, nativeCall_at(call_site));
c_ic->verify();
return c_ic;
}
inline CompiledIC* CompiledIC_at(Relocation* call_site) {
assert(call_site->type() == relocInfo::virtual_call_type ||
call_site->type() == relocInfo::opt_virtual_call_type, "wrong reloc. info");
CompiledIC* c_ic = new CompiledIC(call_site->code(), nativeCall_at(call_site->addr()));
c_ic->verify();
return c_ic;
}
inline CompiledIC* CompiledIC_at(RelocIterator* reloc_iter) {
assert(reloc_iter->type() == relocInfo::virtual_call_type ||
reloc_iter->type() == relocInfo::opt_virtual_call_type, "wrong reloc. info");
CompiledIC* c_ic = new CompiledIC(reloc_iter);
c_ic->verify();
return c_ic;
}
class CompiledStaticCall;
class StaticCallInfo {
private:
address _entry; // Entrypoint
methodHandle _callee; // Callee (used when calling interpreter)
bool _to_interpreter; // call to interpreted method (otherwise compiled)
friend class CompiledStaticCall;
public:
address entry() const { return _entry; }
methodHandle callee() const { return _callee; }
};
class CompiledStaticCall: public NativeCall {
friend class CompiledIC;
void set_to_interpreted(methodHandle callee, address entry);
bool is_optimized_virtual();
public:
friend CompiledStaticCall* compiledStaticCall_before(address return_addr);
friend CompiledStaticCall* compiledStaticCall_at(address native_call);
friend CompiledStaticCall* compiledStaticCall_at(Relocation* call_site);
#if defined(AARCH64) && !defined(ZERO)
static address emit_to_interp_stub(CodeBuffer &cbuf, address mark);
#else
static address emit_to_interp_stub(CodeBuffer &cbuf);
#endif
static int to_interp_stub_size();
static int reloc_to_interp_stub();
bool is_clean() const;
bool is_call_to_compiled() const;
bool is_call_to_interpreted() const;
void set_to_clean();
void set(const StaticCallInfo& info);
static void compute_entry(methodHandle m, StaticCallInfo& info);
address find_stub();
static void set_stub_to_clean(static_stub_Relocation* static_stub);
void print() PRODUCT_RETURN;
void verify() PRODUCT_RETURN;
};
inline CompiledStaticCall* compiledStaticCall_before(address return_addr) {
CompiledStaticCall* st = (CompiledStaticCall*)nativeCall_before(return_addr);
st->verify();
return st;
}
inline CompiledStaticCall* compiledStaticCall_at(address native_call) {
CompiledStaticCall* st = (CompiledStaticCall*)native_call;
st->verify();
return st;
}
inline CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) {
return compiledStaticCall_at(call_site->addr());
}
#endif // SHARE_VM_CODE_COMPILEDIC_HPP
C:\hotspot-69087d08d473\src\share\vm/code/compressedStream.cpp
#include "precompiled.hpp"
#include "code/compressedStream.hpp"
#include "utilities/ostream.hpp"
inline juint CompressedStream::encode_sign(jint value) {
return (value << 1) ^ (value >> 31);
}
inline jint CompressedStream::decode_sign(juint value) {
return (value >> 1) ^ -(jint)(value & 1);
}
inline juint CompressedStream::reverse_int(juint i) {
i = (i & 0x55555555) << 1 | (i >> 1) & 0x55555555;
i = (i & 0x33333333) << 2 | (i >> 2) & 0x33333333;
i = (i & 0x0f0f0f0f) << 4 | (i >> 4) & 0x0f0f0f0f;
i = (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
return i;
}
jint CompressedReadStream::read_signed_int() {
return decode_sign(read_int());
}
jfloat CompressedReadStream::read_float() {
int rf = read_int();
int f = reverse_int(rf);
return jfloat_cast(f);
}
jdouble CompressedReadStream::read_double() {
jint rh = read_int();
jint rl = read_int();
jint h = reverse_int(rh);
jint l = reverse_int(rl);
return jdouble_cast(jlong_from(h, l));
}
jlong CompressedReadStream::read_long() {
jint low = read_signed_int();
jint high = read_signed_int();
return jlong_from(high, low);
}
CompressedWriteStream::CompressedWriteStream(int initial_size) : CompressedStream(NULL, 0) {
_buffer = NEW_RESOURCE_ARRAY(u_char, initial_size);
_size = initial_size;
_position = 0;
}
void CompressedWriteStream::grow() {
u_char* _new_buffer = NEW_RESOURCE_ARRAY(u_char, _size * 2);
memcpy(_new_buffer, _buffer, _position);
_buffer = _new_buffer;
_size = _size * 2;
}
void CompressedWriteStream::write_signed_int(jint value) {
write_int(encode_sign(value));
}
void CompressedWriteStream::write_float(jfloat value) {
juint f = jint_cast(value);
juint rf = reverse_int(f);
assert(f == reverse_int(rf), "can re-read same bits");
write_int(rf);
}
void CompressedWriteStream::write_double(jdouble value) {
juint h = high(jlong_cast(value));
juint l = low( jlong_cast(value));
juint rh = reverse_int(h);
juint rl = reverse_int(l);
assert(h == reverse_int(rh), "can re-read same bits");
assert(l == reverse_int(rl), "can re-read same bits");
write_int(rh);
write_int(rl);
}
void CompressedWriteStream::write_long(jlong value) {
write_signed_int(low(value));
write_signed_int(high(value));
}
#ifndef PRODUCT
void test_compressed_stream(int trace);
bool test_compressed_stream_enabled = false;
#endif
jint CompressedReadStream::read_int_mb(jint b0) {
int pos = position() - 1;
u_char* buf = buffer() + pos;
assert(buf[0] == b0 && b0 >= L, "correctly called");
jint sum = b0;
int lg_H_i = lg_H;
for (int i = 0; ; ) {
jint b_i = buf[++i]; // b_i = read(); ++i;
sum += b_i << lg_H_i; // sum += b[i]*(64**i)
if (b_i < L || i == MAX_i) {
set_position(pos+i+1);
return sum;
}
lg_H_i += lg_H;
}
}
void CompressedWriteStream::write_int_mb(jint value) {
debug_only(int pos1 = position());
juint sum = value;
for (int i = 0; ; ) {
if (sum < L || i == MAX_i) {
assert(sum == (u_char)sum, "valid byte");
write((u_char)sum);
break;
}
sum -= L;
int b_i = L + (sum % H); // this is a "high code"
sum >>= lg_H; // extracted 6 bits
write(b_i); ++i;
}
#ifndef PRODUCT
if (test_compressed_stream_enabled) { // hack to enable this stress test
test_compressed_stream_enabled = false;
test_compressed_stream(0);
}
#endif
}
#ifndef PRODUCT
#if defined(_MSC_VER) && _MSC_VER >=1400 && !defined(_WIN64)
#pragma optimize("", off)
#pragma warning(disable: 4748)
#endif
enum { stretch_limit = (1<<16) * (64-16+1) };
static jlong stretch(jint x, int bits) {
jlong h = (jlong)((x >> (16-4))) << (bits - 4);
jlong l = ((jlong)x << (64-12)) >> (64-12);
l <<= (x >> 16);
return h ^ l;
}
PRAGMA_DIAG_PUSH
PRAGMA_FORMAT_IGNORED // Someone needs to deal with this.
void test_compressed_stream(int trace) {
CompressedWriteStream bytes(stretch_limit * 100);
jint n;
int step = 0, fails = 0;
#define CHECKXY(x, y, fmt) { \
++step; \
int xlen = (pos = decode.position()) - lastpos; lastpos = pos; \
if (trace > 0 && (step % trace) == 0) { \
tty->print_cr("step %d, n=%08x: value=" fmt " (len=%d)", \
step, n, x, xlen); } \
if (x != y) { \
tty->print_cr("step %d, n=%d: " fmt " != " fmt, step, n, x, y); \
fails++; \
} }
for (n = 0; n < (1<<8); n++) {
jbyte x = (jbyte)n;
bytes.write_byte(x); ++step;
}
for (n = 0; n < stretch_limit; n++) {
jint x = (jint)stretch(n, 32);
bytes.write_int(x); ++step;
bytes.write_signed_int(x); ++step;
bytes.write_float(jfloat_cast(x)); ++step;
}
for (n = 0; n < stretch_limit; n++) {
jlong x = stretch(n, 64);
bytes.write_long(x); ++step;
bytes.write_double(jdouble_cast(x)); ++step;
}
int length = bytes.position();
if (trace != 0)
tty->print_cr("set up test of %d stream values, size %d", step, length);
step = 0;
CompressedReadStream decode(bytes.buffer());
int pos, lastpos = decode.position();
for (n = 0; n < (1<<8); n++) {
jbyte x = (jbyte)n;
jbyte y = decode.read_byte();
CHECKXY(x, y, "%db");
}
for (n = 0; n < stretch_limit; n++) {
jint x = (jint)stretch(n, 32);
jint y1 = decode.read_int();
CHECKXY(x, y1, "%du");
jint y2 = decode.read_signed_int();
CHECKXY(x, y2, "%di");
jint y3 = jint_cast(decode.read_float());
CHECKXY(x, y3, "%df");
}
for (n = 0; n < stretch_limit; n++) {
jlong x = stretch(n, 64);
jlong y1 = decode.read_long();
CHECKXY(x, y1, INT64_FORMAT "l");
jlong y2 = jlong_cast(decode.read_double());
CHECKXY(x, y2, INT64_FORMAT "d");
}
int length2 = decode.position();
if (trace != 0)
tty->print_cr("finished test of %d stream values, size %d", step, length2);
guarantee(length == length2, "bad length");
guarantee(fails == 0, "test failures");
}
PRAGMA_DIAG_POP
#if defined(_MSC_VER) &&_MSC_VER >=1400 && !defined(_WIN64)
#pragma warning(default: 4748)
#pragma optimize("", on)
#endif
#endif // PRODUCT
C:\hotspot-69087d08d473\src\share\vm/code/compressedStream.hpp
#ifndef SHARE_VM_CODE_COMPRESSEDSTREAM_HPP
#define SHARE_VM_CODE_COMPRESSEDSTREAM_HPP
#include "memory/allocation.hpp"
class CompressedStream : public ResourceObj {
friend class VMStructs;
protected:
u_char* _buffer;
int _position;
enum {
lg_H = 6, H = 1<<lg_H, // number of high codes (64)
L = (1<<BitsPerByte)-H, // number of low codes (192)
MAX_i = 4 // bytes are numbered in (0..4), max 5 bytes
};
static inline juint encode_sign(jint value); // for Pack200 SIGNED5
static inline jint decode_sign(juint value); // for Pack200 SIGNED5
static inline juint reverse_int(juint bits); // to trim trailing float 0's
public:
CompressedStream(u_char* buffer, int position = 0) {
_buffer = buffer;
_position = position;
}
u_char* buffer() const { return _buffer; }
int position() const { return _position; }
void set_position(int position) { _position = position; }
};
class CompressedReadStream : public CompressedStream {
private:
inline u_char read() { return _buffer[_position++]; }
jint read_int_mb(jint b0); // UNSIGNED5 coding, 2-5 byte cases
public:
CompressedReadStream(u_char* buffer, int position = 0)
: CompressedStream(buffer, position) {}
jboolean read_bool() { return (jboolean) read(); }
jbyte read_byte() { return (jbyte ) read(); }
jchar read_char() { return (jchar ) read_int(); }
jshort read_short() { return (jshort ) read_signed_int(); }
jint read_int() { jint b0 = read();
if (b0 < L) return b0;
else return read_int_mb(b0);
}
jint read_signed_int();
jfloat read_float(); // jfloat_cast(reverse_int(read_int()))
jdouble read_double(); // jdouble_cast(2*reverse_int(read_int))
jlong read_long(); // jlong_from(2*read_signed_int())
};
class CompressedWriteStream : public CompressedStream {
private:
bool full() {
return _position >= _size;
}
void store(u_char b) {
_buffer[_position++] = b;
}
void write(u_char b) {
if (full()) grow();
store(b);
}
void grow();
void write_int_mb(jint value); // UNSIGNED5 coding, 1-5 byte cases
protected:
int _size;
public:
CompressedWriteStream(int initial_size);
CompressedWriteStream(u_char* buffer, int initial_size, int position = 0)
: CompressedStream(buffer, position) { _size = initial_size; }
void write_bool(jboolean value) { write(value); }
void write_byte(jbyte value) { write(value); }
void write_char(jchar value) { write_int(value); }
void write_short(jshort value) { write_signed_int(value); }
void write_int(jint value) { if ((juint)value < L && !full())
store((u_char)value);
else write_int_mb(value); }
void write_signed_int(jint value); // write_int(encode_sign(value))
void write_float(jfloat value); // write_int(reverse_int(jint_cast(v)))
void write_double(jdouble value); // write_int(reverse_int(<low,high>))
void write_long(jlong value); // write_signed_int(<low,high>)
};
#endif // SHARE_VM_CODE_COMPRESSEDSTREAM_HPP
C:\hotspot-69087d08d473\src\share\vm/code/debugInfo.cpp
#include "precompiled.hpp"
#include "code/debugInfo.hpp"
#include "code/debugInfoRec.hpp"
#include "code/nmethod.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/thread.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
DebugInfoWriteStream::DebugInfoWriteStream(DebugInformationRecorder* recorder, int initial_size)
: CompressedWriteStream(initial_size) {
_recorder = recorder;
}
void DebugInfoWriteStream::write_handle(jobject h) {
write_int(recorder()->oop_recorder()->find_index(h));
}
void DebugInfoWriteStream::write_metadata(Metadata* h) {
write_int(recorder()->oop_recorder()->find_index(h));
}
ScopeValue* DebugInfoReadStream::read_object_value() {
int id = read_int();
#ifdef ASSERT
assert(_obj_pool != NULL, "object pool does not exist");
for (int i = _obj_pool->length() - 1; i >= 0; i--) {
assert(((ObjectValue*) _obj_pool->at(i))->id() != id, "should not be read twice");
}
#endif
ObjectValue* result = new ObjectValue(id);
_obj_pool->push(result);
result->read_object(this);
return result;
}
ScopeValue* DebugInfoReadStream::get_cached_object() {
int id = read_int();
assert(_obj_pool != NULL, "object pool does not exist");
for (int i = _obj_pool->length() - 1; i >= 0; i--) {
ObjectValue* ov = (ObjectValue*) _obj_pool->at(i);
if (ov->id() == id) {
return ov;
}
}
ShouldNotReachHere();
return NULL;
}
enum { LOCATION_CODE = 0, CONSTANT_INT_CODE = 1, CONSTANT_OOP_CODE = 2,
CONSTANT_LONG_CODE = 3, CONSTANT_DOUBLE_CODE = 4,
OBJECT_CODE = 5, OBJECT_ID_CODE = 6 };
ScopeValue* ScopeValue::read_from(DebugInfoReadStream* stream) {
ScopeValue* result = NULL;
switch(stream->read_int()) {
case LOCATION_CODE: result = new LocationValue(stream); break;
case CONSTANT_INT_CODE: result = new ConstantIntValue(stream); break;
case CONSTANT_OOP_CODE: result = new ConstantOopReadValue(stream); break;
case CONSTANT_LONG_CODE: result = new ConstantLongValue(stream); break;
case CONSTANT_DOUBLE_CODE: result = new ConstantDoubleValue(stream); break;
case OBJECT_CODE: result = stream->read_object_value(); break;
case OBJECT_ID_CODE: result = stream->get_cached_object(); break;
default: ShouldNotReachHere();
}
return result;
}
LocationValue::LocationValue(DebugInfoReadStream* stream) {
_location = Location(stream);
}
void LocationValue::write_on(DebugInfoWriteStream* stream) {
stream->write_int(LOCATION_CODE);
location().write_on(stream);
}
void LocationValue::print_on(outputStream* st) const {
location().print_on(st);
}
void ObjectValue::read_object(DebugInfoReadStream* stream) {
_klass = read_from(stream);
assert(_klass->is_constant_oop(), "should be constant java mirror oop");
int length = stream->read_int();
for (int i = 0; i < length; i++) {
ScopeValue* val = read_from(stream);
_field_values.append(val);
}
}
void ObjectValue::write_on(DebugInfoWriteStream* stream) {
if (_visited) {
stream->write_int(OBJECT_ID_CODE);
stream->write_int(_id);
} else {
_visited = true;
stream->write_int(OBJECT_CODE);
stream->write_int(_id);
_klass->write_on(stream);
int length = _field_values.length();
stream->write_int(length);
for (int i = 0; i < length; i++) {
_field_values.at(i)->write_on(stream);
}
}
}
void ObjectValue::print_on(outputStream* st) const {
st->print("obj[%d]", _id);
}
void ObjectValue::print_fields_on(outputStream* st) const {
#ifndef PRODUCT
if (_field_values.length() > 0) {
_field_values.at(0)->print_on(st);
}
for (int i = 1; i < _field_values.length(); i++) {
st->print(", ");
_field_values.at(i)->print_on(st);
}
#endif
}
ConstantIntValue::ConstantIntValue(DebugInfoReadStream* stream) {
_value = stream->read_signed_int();
}
void ConstantIntValue::write_on(DebugInfoWriteStream* stream) {
stream->write_int(CONSTANT_INT_CODE);
stream->write_signed_int(value());
}
void ConstantIntValue::print_on(outputStream* st) const {
st->print("%d", value());
}
ConstantLongValue::ConstantLongValue(DebugInfoReadStream* stream) {
_value = stream->read_long();
}
void ConstantLongValue::write_on(DebugInfoWriteStream* stream) {
stream->write_int(CONSTANT_LONG_CODE);
stream->write_long(value());
}
void ConstantLongValue::print_on(outputStream* st) const {
st->print(INT64_FORMAT, value());
}
ConstantDoubleValue::ConstantDoubleValue(DebugInfoReadStream* stream) {
_value = stream->read_double();
}
void ConstantDoubleValue::write_on(DebugInfoWriteStream* stream) {
stream->write_int(CONSTANT_DOUBLE_CODE);
stream->write_double(value());
}
void ConstantDoubleValue::print_on(outputStream* st) const {
st->print("%f", value());
}
void ConstantOopWriteValue::write_on(DebugInfoWriteStream* stream) {
#ifdef ASSERT
{
ThreadInVMfromUnknown tiv;
assert(JNIHandles::resolve(value()) == NULL ||
Universe::heap()->is_in_reserved(JNIHandles::resolve(value())),
"Should be in heap");
}
#endif
stream->write_int(CONSTANT_OOP_CODE);
stream->write_handle(value());
}
void ConstantOopWriteValue::print_on(outputStream* st) const {
ThreadInVMfromUnknown tiv;
JNIHandles::resolve(value())->print_value_on(st);
}
ConstantOopReadValue::ConstantOopReadValue(DebugInfoReadStream* stream) {
_value = Handle(stream->read_oop());
assert(_value() == NULL ||
Universe::heap()->is_in_reserved(_value()), "Should be in heap");
}
void ConstantOopReadValue::write_on(DebugInfoWriteStream* stream) {
ShouldNotReachHere();
}
void ConstantOopReadValue::print_on(outputStream* st) const {
value()()->print_value_on(st);
}
MonitorValue::MonitorValue(ScopeValue* owner, Location basic_lock, bool eliminated) {
_owner = owner;
_basic_lock = basic_lock;
_eliminated = eliminated;
}
MonitorValue::MonitorValue(DebugInfoReadStream* stream) {
_basic_lock = Location(stream);
_owner = ScopeValue::read_from(stream);
_eliminated = (stream->read_bool() != 0);
}
void MonitorValue::write_on(DebugInfoWriteStream* stream) {
_basic_lock.write_on(stream);
_owner->write_on(stream);
stream->write_bool(_eliminated);
}
#ifndef PRODUCT
void MonitorValue::print_on(outputStream* st) const {
st->print("monitor{");
owner()->print_on(st);
st->print(",");
basic_lock().print_on(st);
st->print("}");
if (_eliminated) {
st->print(" (eliminated)");
}
}
#endif
C:\hotspot-69087d08d473\src\share\vm/code/debugInfo.hpp
#ifndef SHARE_VM_CODE_DEBUGINFO_HPP
#define SHARE_VM_CODE_DEBUGINFO_HPP
#include "code/compressedStream.hpp"
#include "code/location.hpp"
#include "code/nmethod.hpp"
#include "code/oopRecorder.hpp"
#include "runtime/stackValue.hpp"
#include "utilities/growableArray.hpp"
class ConstantOopReadValue;
class ScopeValue: public ResourceObj {
public:
virtual bool is_location() const { return false; }
virtual bool is_object() const { return false; }
virtual bool is_constant_int() const { return false; }
virtual bool is_constant_double() const { return false; }
virtual bool is_constant_long() const { return false; }
virtual bool is_constant_oop() const { return false; }
virtual bool equals(ScopeValue* other) const { return false; }
ConstantOopReadValue* as_ConstantOopReadValue() {
assert(is_constant_oop(), "must be");
return (ConstantOopReadValue*) this;
}
virtual void write_on(DebugInfoWriteStream* stream) = 0;
static ScopeValue* read_from(DebugInfoReadStream* stream);
};
class LocationValue: public ScopeValue {
private:
Location _location;
public:
LocationValue(Location location) { _location = location; }
bool is_location() const { return true; }
Location location() const { return _location; }
LocationValue(DebugInfoReadStream* stream);
void write_on(DebugInfoWriteStream* stream);
void print_on(outputStream* st) const;
};
class ObjectValue: public ScopeValue {
private:
int _id;
ScopeValue* _klass;
GrowableArray<ScopeValue*> _field_values;
Handle _value;
bool _visited;
public:
ObjectValue(int id, ScopeValue* klass)
: _id(id)
, _klass(klass)
, _field_values()
, _value()
, _visited(false) {
assert(klass->is_constant_oop(), "should be constant java mirror oop");
}
ObjectValue(int id)
: _id(id)
, _klass(NULL)
, _field_values()
, _value()
, _visited(false) {}
bool is_object() const { return true; }
int id() const { return _id; }
ScopeValue* klass() const { return _klass; }
GrowableArray<ScopeValue*>* field_values() { return &_field_values; }
ScopeValue* field_at(int i) const { return _field_values.at(i); }
int field_size() { return _field_values.length(); }
Handle value() const { return _value; }
bool is_visited() const { return _visited; }
void set_value(oop value) { _value = Handle(value); }
void set_visited(bool visited) { _visited = false; }
void read_object(DebugInfoReadStream* stream);
void write_on(DebugInfoWriteStream* stream);
void print_on(outputStream* st) const;
void print_fields_on(outputStream* st) const;
};
class ConstantIntValue: public ScopeValue {
private:
jint _value;
public:
ConstantIntValue(jint value) { _value = value; }
jint value() const { return _value; }
bool is_constant_int() const { return true; }
bool equals(ScopeValue* other) const { return false; }
ConstantIntValue(DebugInfoReadStream* stream);
void write_on(DebugInfoWriteStream* stream);
void print_on(outputStream* st) const;
};
class ConstantLongValue: public ScopeValue {
private:
jlong _value;
public:
ConstantLongValue(jlong value) { _value = value; }
jlong value() const { return _value; }
bool is_constant_long() const { return true; }
bool equals(ScopeValue* other) const { return false; }
ConstantLongValue(DebugInfoReadStream* stream);
void write_on(DebugInfoWriteStream* stream);
void print_on(outputStream* st) const;
};
class ConstantDoubleValue: public ScopeValue {
private:
jdouble _value;
public:
ConstantDoubleValue(jdouble value) { _value = value; }
jdouble value() const { return _value; }
bool is_constant_double() const { return true; }
bool equals(ScopeValue* other) const { return false; }
ConstantDoubleValue(DebugInfoReadStream* stream);
void write_on(DebugInfoWriteStream* stream);
void print_on(outputStream* st) const;
};
class ConstantOopWriteValue: public ScopeValue {
private:
jobject _value;
public:
ConstantOopWriteValue(jobject value) { _value = value; }
jobject value() const { return _value; }
bool is_constant_oop() const { return true; }
bool equals(ScopeValue* other) const { return false; }
void write_on(DebugInfoWriteStream* stream);
void print_on(outputStream* st) const;
};
class ConstantOopReadValue: public ScopeValue {
private:
Handle _value;
public:
Handle value() const { return _value; }
bool is_constant_oop() const { return true; }
bool equals(ScopeValue* other) const { return false; }
ConstantOopReadValue(DebugInfoReadStream* stream);
void write_on(DebugInfoWriteStream* stream);
void print_on(outputStream* st) const;
};
class MonitorValue: public ResourceObj {
private:
ScopeValue* _owner;
Location _basic_lock;
bool _eliminated;
public:
MonitorValue(ScopeValue* owner, Location basic_lock, bool eliminated = false);
ScopeValue* owner() const { return _owner; }
Location basic_lock() const { return _basic_lock; }
bool eliminated() const { return _eliminated; }
MonitorValue(DebugInfoReadStream* stream);
void write_on(DebugInfoWriteStream* stream);
void print_on(outputStream* st) const;
};
class DebugInfoReadStream : public CompressedReadStream {
private:
const nmethod* _code;
const nmethod* code() const { return _code; }
GrowableArray<ScopeValue*>* _obj_pool;
public:
DebugInfoReadStream(const nmethod* code, int offset, GrowableArray<ScopeValue*>* obj_pool = NULL) :
CompressedReadStream(code->scopes_data_begin(), offset) {
_code = code;
_obj_pool = obj_pool;
} ;
oop read_oop() {
oop o = code()->oop_at(read_int());
assert(o == NULL || o->is_oop(), "oop only");
return o;
}
Method* read_method() {
Method* o = (Method*)(code()->metadata_at(read_int()));
assert(o == NULL || o->is_metadata(), "meta data only");
return o;
}
ScopeValue* read_object_value();
ScopeValue* get_cached_object();
int read_bci() { return read_int() + InvocationEntryBci; }
};
class DebugInfoWriteStream : public CompressedWriteStream {
private:
DebugInformationRecorder* _recorder;
DebugInformationRecorder* recorder() const { return _recorder; }
public:
DebugInfoWriteStream(DebugInformationRecorder* recorder, int initial_size);
void write_handle(jobject h);
void write_bci(int bci) { write_int(bci - InvocationEntryBci); }
void write_metadata(Metadata* m);
};
#endif // SHARE_VM_CODE_DEBUGINFO_HPP
C:\hotspot-69087d08d473\src\share\vm/code/debugInfoRec.cpp
#include "precompiled.hpp"
#include "code/debugInfoRec.hpp"
#include "code/scopeDesc.hpp"
#include "prims/jvmtiExport.hpp"
class DIR_Chunk {
friend class DebugInformationRecorder;
int _offset; // location in the stream of this scope
int _length; // number of bytes in the stream
int _hash; // hash of stream bytes (for quicker reuse)
void* operator new(size_t ignore, DebugInformationRecorder* dir) throw() {
assert(ignore == sizeof(DIR_Chunk), "");
if (dir->_next_chunk >= dir->_next_chunk_limit) {
const int CHUNK = 100;
dir->_next_chunk = NEW_RESOURCE_ARRAY(DIR_Chunk, CHUNK);
dir->_next_chunk_limit = dir->_next_chunk + CHUNK;
}
return dir->_next_chunk++;
}
DIR_Chunk(int offset, int length, DebugInformationRecorder* dir) {
_offset = offset;
_length = length;
unsigned int hash = 0;
address p = dir->stream()->buffer() + _offset;
for (int i = 0; i < length; i++) {
if (i == 6) break;
hash *= 127;
hash += p[i];
}
_hash = hash;
}
DIR_Chunk* find_match(GrowableArray<DIR_Chunk*>* arr,
int start_index,
DebugInformationRecorder* dir) {
int end_index = arr->length();
int hash = this->_hash, length = this->_length;
address buf = dir->stream()->buffer();
for (int i = end_index; --i >= start_index; ) {
DIR_Chunk* that = arr->at(i);
if (hash == that->_hash &&
length == that->_length &&
0 == memcmp(buf + this->_offset, buf + that->_offset, length)) {
return that;
}
}
return NULL;
}
};
static inline bool compute_recording_non_safepoints() {
if (JvmtiExport::should_post_compiled_method_load()
&& FLAG_IS_DEFAULT(DebugNonSafepoints)) {
return true;
}
return DebugNonSafepoints;
}
DebugInformationRecorder::DebugInformationRecorder(OopRecorder* oop_recorder)
: _recording_non_safepoints(compute_recording_non_safepoints())
{
_pcs_size = 100;
_pcs = NEW_RESOURCE_ARRAY(PcDesc, _pcs_size);
_pcs_length = 0;
_prev_safepoint_pc = PcDesc::lower_offset_limit;
_stream = new DebugInfoWriteStream(this, 10 * K);
_stream->write_byte((jbyte)0xFF);
assert(_stream->position() > serialized_null, "sanity");
_oop_recorder = oop_recorder;
_all_chunks = new GrowableArray<DIR_Chunk*>(300);
_shared_chunks = new GrowableArray<DIR_Chunk*>(30);
_next_chunk = _next_chunk_limit = NULL;
add_new_pc_offset(PcDesc::lower_offset_limit); // sentinel record
debug_only(_recording_state = rs_null);
}
void DebugInformationRecorder::add_oopmap(int pc_offset, OopMap* map) {
_oopmaps->add_gc_map(pc_offset, map);
}
void DebugInformationRecorder::add_safepoint(int pc_offset, OopMap* map) {
assert(!_oop_recorder->is_complete(), "not frozen yet");
add_oopmap(pc_offset, map);
add_new_pc_offset(pc_offset);
assert(_recording_state == rs_null, "nesting of recording calls");
debug_only(_recording_state = rs_safepoint);
}
void DebugInformationRecorder::add_non_safepoint(int pc_offset) {
assert(!_oop_recorder->is_complete(), "not frozen yet");
assert(_recording_non_safepoints, "must be recording non-safepoints");
add_new_pc_offset(pc_offset);
assert(_recording_state == rs_null, "nesting of recording calls");
debug_only(_recording_state = rs_non_safepoint);
}
void DebugInformationRecorder::add_new_pc_offset(int pc_offset) {
assert(_pcs_length == 0 || last_pc()->pc_offset() < pc_offset,
"must specify a new, larger pc offset");
if (_pcs_length == _pcs_size) {
int new_pcs_size = _pcs_size * 2;
PcDesc* new_pcs = NEW_RESOURCE_ARRAY(PcDesc, new_pcs_size);
for (int index = 0; index < _pcs_length; index++) {
new_pcs[index] = _pcs[index];
}
_pcs_size = new_pcs_size;
_pcs = new_pcs;
}
assert(_pcs_size > _pcs_length, "There must be room for after expanding");
_pcs[_pcs_length++] = PcDesc(pc_offset, DebugInformationRecorder::serialized_null,
DebugInformationRecorder::serialized_null);
}
int DebugInformationRecorder::serialize_monitor_values(GrowableArray<MonitorValue*>* monitors) {
if (monitors == NULL || monitors->is_empty()) return DebugInformationRecorder::serialized_null;
assert(_recording_state == rs_safepoint, "must be recording a safepoint");
int result = stream()->position();
stream()->write_int(monitors->length());
for (int index = 0; index < monitors->length(); index++) {
monitors->at(index)->write_on(stream());
}
assert(result != serialized_null, "sanity");
int shared_result = find_sharable_decode_offset(result);
if (shared_result != serialized_null) {
stream()->set_position(result);
result = shared_result;
}
return result;
}
int DebugInformationRecorder::serialize_scope_values(GrowableArray<ScopeValue*>* values) {
if (values == NULL || values->is_empty()) return DebugInformationRecorder::serialized_null;
assert(_recording_state == rs_safepoint, "must be recording a safepoint");
int result = stream()->position();
assert(result != serialized_null, "sanity");
stream()->write_int(values->length());
for (int index = 0; index < values->length(); index++) {
values->at(index)->write_on(stream());
}
int shared_result = find_sharable_decode_offset(result);
if (shared_result != serialized_null) {
stream()->set_position(result);
result = shared_result;
}
return result;
}
#ifndef PRODUCT
static
struct dir_stats_struct {
int chunks_queried;
int chunks_shared;
int chunks_reshared;
int chunks_elided;
void print() {
tty->print_cr("Debug Data Chunks: %d, shared %d+%d, non-SP's elided %d",
chunks_queried,
chunks_shared, chunks_reshared,
chunks_elided);
}
} dir_stats;
#endif //PRODUCT
int DebugInformationRecorder::find_sharable_decode_offset(int stream_offset) {
if (!recording_non_safepoints())
return serialized_null;
NOT_PRODUCT(++dir_stats.chunks_queried);
int stream_length = stream()->position() - stream_offset;
assert(stream_offset != serialized_null, "should not be null");
assert(stream_length != 0, "should not be empty");
DIR_Chunk* ns = new(this) DIR_Chunk(stream_offset, stream_length, this);
DIR_Chunk* ms = ns->find_match(_shared_chunks, 0, this);
if (ms != NULL) {
NOT_PRODUCT(++dir_stats.chunks_reshared);
assert(ns+1 == _next_chunk, "");
_next_chunk = ns;
return ms->_offset;
}
const int MAX_RECENT = 50;
int start_index = _all_chunks->length() - MAX_RECENT;
if (start_index < 0) start_index = 0;
ms = ns->find_match(_all_chunks, start_index, this);
if (ms != NULL) {
NOT_PRODUCT(++dir_stats.chunks_shared);
_shared_chunks->append(ms);
assert(ns+1 == _next_chunk, "");
_next_chunk = ns;
return ms->_offset;
}
_all_chunks->append(ns);
return serialized_null;
}
void DebugInformationRecorder::describe_scope(int pc_offset,
ciMethod* method,
int bci,
bool reexecute,
bool is_method_handle_invoke,
bool return_oop,
DebugToken* locals,
DebugToken* expressions,
DebugToken* monitors) {
assert(_recording_state != rs_null, "nesting of recording calls");
PcDesc* last_pd = last_pc();
assert(last_pd->pc_offset() == pc_offset, "must be last pc");
int sender_stream_offset = last_pd->scope_decode_offset();
int stream_offset = stream()->position();
last_pd->set_scope_decode_offset(stream_offset);
last_pd->set_should_reexecute(reexecute);
last_pd->set_is_method_handle_invoke(is_method_handle_invoke);
last_pd->set_return_oop(return_oop);
stream()->write_int(sender_stream_offset);
Metadata* method_enc = (method == NULL)? NULL: method->constant_encoding();
stream()->write_int(oop_recorder()->find_index(method_enc));
stream()->write_bci(bci);
assert(method == NULL ||
(method->is_native() && bci == 0) ||
(!method->is_native() && 0 <= bci && bci < method->code_size()) ||
(method->is_compiled_lambda_form() && bci == -99) || // this might happen in C1
bci == -1, "illegal bci");
stream()->write_int((intptr_t) locals);
stream()->write_int((intptr_t) expressions);
stream()->write_int((intptr_t) monitors);
int shared_stream_offset = find_sharable_decode_offset(stream_offset);
if (shared_stream_offset != serialized_null) {
stream()->set_position(stream_offset);
last_pd->set_scope_decode_offset(shared_stream_offset);
}
}
void DebugInformationRecorder::dump_object_pool(GrowableArray<ScopeValue*>* objects) {
guarantee( _pcs_length > 0, "safepoint must exist before describing scopes");
PcDesc* last_pd = &_pcs[_pcs_length-1];
if (objects != NULL) {
for (int i = objects->length() - 1; i >= 0; i--) {
((ObjectValue*) objects->at(i))->set_visited(false);
}
}
int offset = serialize_scope_values(objects);
last_pd->set_obj_decode_offset(offset);
}
void DebugInformationRecorder::end_scopes(int pc_offset, bool is_safepoint) {
assert(_recording_state == (is_safepoint? rs_safepoint: rs_non_safepoint),
"nesting of recording calls");
debug_only(_recording_state = rs_null);
if (_pcs_length >= 2 && recording_non_safepoints()) {
PcDesc* last = last_pc();
PcDesc* prev = prev_pc();
if (_prev_safepoint_pc < prev->pc_offset() && prev->is_same_info(last)) {
assert(prev == last-1, "sane");
prev->set_pc_offset(pc_offset);
_pcs_length -= 1;
NOT_PRODUCT(++dir_stats.chunks_elided);
}
}
if (is_safepoint) {
_prev_safepoint_pc = pc_offset;
}
}
#ifdef ASSERT
bool DebugInformationRecorder::recorders_frozen() {
return _oop_recorder->is_complete() || _oop_recorder->is_complete();
}
void DebugInformationRecorder::mark_recorders_frozen() {
_oop_recorder->freeze();
}
#endif // PRODUCT
DebugToken* DebugInformationRecorder::create_scope_values(GrowableArray<ScopeValue*>* values) {
assert(!recorders_frozen(), "not frozen yet");
return (DebugToken*) (intptr_t) serialize_scope_values(values);
}
DebugToken* DebugInformationRecorder::create_monitor_values(GrowableArray<MonitorValue*>* monitors) {
assert(!recorders_frozen(), "not frozen yet");
return (DebugToken*) (intptr_t) serialize_monitor_values(monitors);
}
int DebugInformationRecorder::data_size() {
debug_only(mark_recorders_frozen()); // mark it "frozen" for asserts
return _stream->position();
}
int DebugInformationRecorder::pcs_size() {
debug_only(mark_recorders_frozen()); // mark it "frozen" for asserts
if (last_pc()->pc_offset() != PcDesc::upper_offset_limit)
add_new_pc_offset(PcDesc::upper_offset_limit);
return _pcs_length * sizeof(PcDesc);
}
void DebugInformationRecorder::copy_to(nmethod* nm) {
nm->copy_scopes_data(stream()->buffer(), stream()->position());
nm->copy_scopes_pcs(_pcs, _pcs_length);
}
void DebugInformationRecorder::verify(const nmethod* code) {
Unimplemented();
}
#ifndef PRODUCT
void DebugInformationRecorder::print_statistics() {
dir_stats.print();
}
#endif //PRODUCT
C:\hotspot-69087d08d473\src\share\vm/code/debugInfoRec.hpp
#ifndef SHARE_VM_CODE_DEBUGINFOREC_HPP
#define SHARE_VM_CODE_DEBUGINFOREC_HPP
#include "ci/ciClassList.hpp"
#include "ci/ciInstanceKlass.hpp"
#include "ci/ciMethod.hpp"
#include "code/debugInfo.hpp"
#include "code/location.hpp"
#include "code/pcDesc.hpp"
#include "compiler/oopMap.hpp"
#include "oops/oop.hpp"
#include "utilities/growableArray.hpp"
class DebugToken; // Opaque datatype for stored:
const int SynchronizationEntryBCI = InvocationEntryBci;
class DIR_Chunk; // private class, a nugget of collected information
class DebugInformationRecorder: public ResourceObj {
public:
DebugInformationRecorder(OopRecorder* oop_recorder);
void add_oopmap(int pc_offset, OopMap* map);
void add_safepoint(int pc_offset, OopMap* map);
void add_non_safepoint(int pc_offset);
void describe_scope(int pc_offset,
ciMethod* method,
int bci,
bool reexecute,
bool is_method_handle_invoke = false,
bool return_oop = false,
DebugToken* locals = NULL,
DebugToken* expressions = NULL,
DebugToken* monitors = NULL);
void dump_object_pool(GrowableArray<ScopeValue*>* objects);
void end_safepoint(int pc_offset) { end_scopes(pc_offset, true); }
void end_non_safepoint(int pc_offset) { end_scopes(pc_offset, false); }
DebugToken* create_scope_values(GrowableArray<ScopeValue*>* values);
DebugToken* create_monitor_values(GrowableArray<MonitorValue*>* monitors);
int data_size();
int pcs_size();
int oop_size() { return oop_recorder()->oop_size(); }
int metadata_size() { return oop_recorder()->metadata_size(); }
void copy_to(nmethod* nm);
void verify(const nmethod* code);
static void print_statistics() PRODUCT_RETURN;
OopMapSet *_oopmaps;
void set_oopmaps(OopMapSet *oopmaps) { _oopmaps = oopmaps; }
OopRecorder* oop_recorder() { return _oop_recorder; }
int last_pc_offset() { return last_pc()->pc_offset(); }
bool recording_non_safepoints() { return _recording_non_safepoints; }
private:
friend class ScopeDesc;
friend class vframeStreamCommon;
friend class DIR_Chunk;
const bool _recording_non_safepoints;
DebugInfoWriteStream* _stream;
DebugInfoWriteStream* stream() const { return _stream; }
OopRecorder* _oop_recorder;
GrowableArray<DIR_Chunk*>* _all_chunks;
GrowableArray<DIR_Chunk*>* _shared_chunks;
DIR_Chunk* _next_chunk;
DIR_Chunk* _next_chunk_limit;
#ifdef ASSERT
enum { rs_null, rs_safepoint, rs_non_safepoint };
int _recording_state;
#endif
PcDesc* _pcs;
int _pcs_size;
int _pcs_length;
int _prev_safepoint_pc;
PcDesc* last_pc() {
guarantee(_pcs_length > 0, "a safepoint must be declared already");
return &_pcs[_pcs_length-1];
}
PcDesc* prev_pc() {
guarantee(_pcs_length > 1, "a safepoint must be declared already");
return &_pcs[_pcs_length-2];
}
void add_new_pc_offset(int pc_offset);
void end_scopes(int pc_offset, bool is_safepoint);
int serialize_monitor_values(GrowableArray<MonitorValue*>* monitors);
int serialize_scope_values(GrowableArray<ScopeValue*>* values);
int find_sharable_decode_offset(int stream_offset);
#ifndef PRODUCT
bool recorders_frozen();
void mark_recorders_frozen();
#endif // PRODUCT
public:
enum { serialized_null = 0 };
};
#endif // SHARE_VM_CODE_DEBUGINFOREC_HPP
C:\hotspot-69087d08d473\src\share\vm/code/dependencies.cpp
#include "precompiled.hpp"
#include "ci/ciArrayKlass.hpp"
#include "ci/ciEnv.hpp"
#include "ci/ciKlass.hpp"
#include "ci/ciMethod.hpp"
#include "code/dependencies.hpp"
#include "compiler/compileLog.hpp"
#include "oops/klass.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/copy.hpp"
#ifdef ASSERT
static bool must_be_in_vm() {
Thread* thread = Thread::current();
if (thread->is_Java_thread())
return ((JavaThread*)thread)->thread_state() == _thread_in_vm;
else
return true; //something like this: thread->is_VM_thread();
}
#endif //ASSERT
void Dependencies::initialize(ciEnv* env) {
Arena* arena = env->arena();
_oop_recorder = env->oop_recorder();
_log = env->log();
_dep_seen = new(arena) GrowableArray<int>(arena, 500, 0, 0);
DEBUG_ONLY(_deps[end_marker] = NULL);
for (int i = (int)FIRST_TYPE; i < (int)TYPE_LIMIT; i++) {
_deps[i] = new(arena) GrowableArray<ciBaseObject*>(arena, 10, 0, 0);
}
_content_bytes = NULL;
_size_in_bytes = (size_t)-1;
assert(TYPE_LIMIT <= (1<<LG2_TYPE_LIMIT), "sanity");
}
void Dependencies::assert_evol_method(ciMethod* m) {
assert_common_1(evol_method, m);
}
void Dependencies::assert_leaf_type(ciKlass* ctxk) {
if (ctxk->is_array_klass()) {
ciType* elemt = ctxk->as_array_klass()->base_element_type();
if (!elemt->is_instance_klass()) return; // Ex: int[][]
ctxk = elemt->as_instance_klass();
}
check_ctxk(ctxk);
assert_common_1(leaf_type, ctxk);
}
void Dependencies::assert_abstract_with_unique_concrete_subtype(ciKlass* ctxk, ciKlass* conck) {
check_ctxk_abstract(ctxk);
assert_common_2(abstract_with_unique_concrete_subtype, ctxk, conck);
}
void Dependencies::assert_abstract_with_no_concrete_subtype(ciKlass* ctxk) {
check_ctxk_abstract(ctxk);
assert_common_1(abstract_with_no_concrete_subtype, ctxk);
}
void Dependencies::assert_concrete_with_no_concrete_subtype(ciKlass* ctxk) {
check_ctxk_concrete(ctxk);
assert_common_1(concrete_with_no_concrete_subtype, ctxk);
}
void Dependencies::assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm) {
check_ctxk(ctxk);
assert_common_2(unique_concrete_method, ctxk, uniqm);
}
void Dependencies::assert_abstract_with_exclusive_concrete_subtypes(ciKlass* ctxk, ciKlass* k1, ciKlass* k2) {
check_ctxk(ctxk);
assert_common_3(abstract_with_exclusive_concrete_subtypes_2, ctxk, k1, k2);
}
void Dependencies::assert_exclusive_concrete_methods(ciKlass* ctxk, ciMethod* m1, ciMethod* m2) {
check_ctxk(ctxk);
assert_common_3(exclusive_concrete_methods_2, ctxk, m1, m2);
}
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(ciCallSite* call_site, ciMethodHandle* method_handle) {
check_ctxk(call_site->klass());
assert_common_2(call_site_target_value, call_site, method_handle);
}
bool Dependencies::maybe_merge_ctxk(GrowableArray<ciBaseObject*>* deps,
int ctxk_i, ciKlass* ctxk2) {
ciKlass* ctxk1 = deps->at(ctxk_i)->as_metadata()->as_klass();
if (ctxk2->is_subtype_of(ctxk1)) {
return true; // success, and no need to change
} else if (ctxk1->is_subtype_of(ctxk2)) {
deps->at_put(ctxk_i, ctxk2);
return true;
} else {
return false;
}
}
void Dependencies::assert_common_1(DepType dept, ciBaseObject* x) {
assert(dep_args(dept) == 1, "sanity");
log_dependency(dept, x);
GrowableArray<ciBaseObject*>* deps = _deps[dept];
if (note_dep_seen(dept, x)) {
assert(deps->find(x) >= 0, "sanity");
} else {
deps->append(x);
}
}
void Dependencies::assert_common_2(DepType dept,
ciBaseObject* x0, ciBaseObject* x1) {
assert(dep_args(dept) == 2, "sanity");
log_dependency(dept, x0, x1);
GrowableArray<ciBaseObject*>* deps = _deps[dept];
bool has_ctxk = has_explicit_context_arg(dept);
if (has_ctxk) {
assert(dep_context_arg(dept) == 0, "sanity");
if (note_dep_seen(dept, x1)) {
const int stride = 2;
for (int i = deps->length(); (i -= stride) >= 0; ) {
ciBaseObject* y1 = deps->at(i+1);
if (x1 == y1) { // same subject; check the context
if (maybe_merge_ctxk(deps, i+0, x0->as_metadata()->as_klass())) {
return;
}
}
}
}
} else {
assert(dep_implicit_context_arg(dept) == 0, "sanity");
if (note_dep_seen(dept, x0) && note_dep_seen(dept, x1)) {
const int stride = 2;
for (int i = deps->length(); (i -= stride) >= 0; ) {
ciBaseObject* y0 = deps->at(i+0);
ciBaseObject* y1 = deps->at(i+1);
if (x0 == y0 && x1 == y1) {
return;
}
}
}
}
deps->append(x0);
deps->append(x1);
}
void Dependencies::assert_common_3(DepType dept,
ciKlass* ctxk, ciBaseObject* x, ciBaseObject* x2) {
assert(dep_context_arg(dept) == 0, "sanity");
assert(dep_args(dept) == 3, "sanity");
log_dependency(dept, ctxk, x, x2);
GrowableArray<ciBaseObject*>* deps = _deps[dept];
bool swap = false;
switch (dept) {
case abstract_with_exclusive_concrete_subtypes_2:
swap = (x->ident() > x2->ident() && x->as_metadata()->as_klass() != ctxk);
break;
case exclusive_concrete_methods_2:
swap = (x->ident() > x2->ident() && x->as_metadata()->as_method()->holder() != ctxk);
break;
}
if (swap) { ciBaseObject* t = x; x = x2; x2 = t; }
if (note_dep_seen(dept, x) && note_dep_seen(dept, x2)) {
const int stride = 3;
for (int i = deps->length(); (i -= stride) >= 0; ) {
ciBaseObject* y = deps->at(i+1);
ciBaseObject* y2 = deps->at(i+2);
if (x == y && x2 == y2) { // same subjects; check the context
if (maybe_merge_ctxk(deps, i+0, ctxk)) {
return;
}
}
}
}
deps->append(ctxk);
deps->append(x);
deps->append(x2);
}
void Dependencies::copy_to(nmethod* nm) {
address beg = nm->dependencies_begin();
address end = nm->dependencies_end();
guarantee(end - beg >= (ptrdiff_t) size_in_bytes(), "bad sizing");
Copy::disjoint_words((HeapWord*) content_bytes(),
(HeapWord*) beg,
size_in_bytes() / sizeof(HeapWord));
assert(size_in_bytes() % sizeof(HeapWord) == 0, "copy by words");
}
static int sort_dep(ciBaseObject** p1, ciBaseObject** p2, int narg) {
for (int i = 0; i < narg; i++) {
int diff = p1[i]->ident() - p2[i]->ident();
if (diff != 0) return diff;
}
return 0;
}
static int sort_dep_arg_1(ciBaseObject** p1, ciBaseObject** p2)
{ return sort_dep(p1, p2, 1); }
static int sort_dep_arg_2(ciBaseObject** p1, ciBaseObject** p2)
{ return sort_dep(p1, p2, 2); }
static int sort_dep_arg_3(ciBaseObject** p1, ciBaseObject** p2)
{ return sort_dep(p1, p2, 3); }
void Dependencies::sort_all_deps() {
for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
DepType dept = (DepType)deptv;
GrowableArray<ciBaseObject*>* deps = _deps[dept];
if (deps->length() <= 1) continue;
switch (dep_args(dept)) {
case 1: deps->sort(sort_dep_arg_1, 1); break;
case 2: deps->sort(sort_dep_arg_2, 2); break;
case 3: deps->sort(sort_dep_arg_3, 3); break;
default: ShouldNotReachHere();
}
}
}
size_t Dependencies::estimate_size_in_bytes() {
size_t est_size = 100;
for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
DepType dept = (DepType)deptv;
GrowableArray<ciBaseObject*>* deps = _deps[dept];
est_size += deps->length()*2; // tags and argument(s)
}
return est_size;
}
ciKlass* Dependencies::ctxk_encoded_as_null(DepType dept, ciBaseObject* x) {
switch (dept) {
case abstract_with_exclusive_concrete_subtypes_2:
return x->as_metadata()->as_klass();
case unique_concrete_method:
case exclusive_concrete_methods_2:
return x->as_metadata()->as_method()->holder();
}
return NULL; // let NULL be NULL
}
Klass* Dependencies::ctxk_encoded_as_null(DepType dept, Metadata* x) {
assert(must_be_in_vm(), "raw oops here");
switch (dept) {
case abstract_with_exclusive_concrete_subtypes_2:
assert(x->is_klass(), "sanity");
return (Klass*) x;
case unique_concrete_method:
case exclusive_concrete_methods_2:
assert(x->is_method(), "sanity");
return ((Method*)x)->method_holder();
}
return NULL; // let NULL be NULL
}
void Dependencies::encode_content_bytes() {
sort_all_deps();
CompressedWriteStream bytes((int)estimate_size_in_bytes());
for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
DepType dept = (DepType)deptv;
GrowableArray<ciBaseObject*>* deps = _deps[dept];
if (deps->length() == 0) continue;
int stride = dep_args(dept);
int ctxkj = dep_context_arg(dept); // -1 if no context arg
assert(stride > 0, "sanity");
for (int i = 0; i < deps->length(); i += stride) {
jbyte code_byte = (jbyte)dept;
int skipj = -1;
if (ctxkj >= 0 && ctxkj+1 < stride) {
ciKlass* ctxk = deps->at(i+ctxkj+0)->as_metadata()->as_klass();
ciBaseObject* x = deps->at(i+ctxkj+1); // following argument
if (ctxk == ctxk_encoded_as_null(dept, x)) {
skipj = ctxkj; // we win: maybe one less oop to keep track of
code_byte |= default_context_type_bit;
}
}
bytes.write_byte(code_byte);
for (int j = 0; j < stride; j++) {
if (j == skipj) continue;
ciBaseObject* v = deps->at(i+j);
int idx;
if (v->is_object()) {
idx = _oop_recorder->find_index(v->as_object()->constant_encoding());
} else {
ciMetadata* meta = v->as_metadata();
idx = _oop_recorder->find_index(meta->constant_encoding());
}
bytes.write_int(idx);
}
}
}
bytes.write_byte(end_marker);
while (bytes.position() % sizeof(HeapWord) != 0) {
bytes.write_byte(end_marker);
}
assert((jbyte)default_context_type_bit != 0, "byte overflow");
_content_bytes = bytes.buffer();
_size_in_bytes = bytes.position();
}
const char* Dependencies::_dep_name[TYPE_LIMIT] = {
"end_marker",
"evol_method",
"leaf_type",
"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",
"call_site_target_value"
};
int Dependencies::_dep_args[TYPE_LIMIT] = {
-1,// end_marker
1, // evol_method m
1, // leaf_type ctxk
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
2 // call_site_target_value 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];
}
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) {
guarantee(FIRST_TYPE <= dept && dept < TYPE_LIMIT, err_msg("invalid dependency type: %d", (int) dept));
}
void Dependencies::log_all_dependencies() {
if (log() == NULL) return;
ResourceMark rm;
for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
DepType dept = (DepType)deptv;
GrowableArray<ciBaseObject*>* deps = _deps[dept];
int deplen = deps->length();
if (deplen == 0) {
continue;
}
int stride = dep_args(dept);
GrowableArray<ciBaseObject*>* ciargs = new GrowableArray<ciBaseObject*>(stride);
for (int i = 0; i < deps->length(); i += stride) {
for (int j = 0; j < stride; j++) {
ciargs->push(deps->at(i+j));
}
write_dependency_to(log(), dept, ciargs);
ciargs->clear();
}
guarantee(deplen == deps->length(), "deps array cannot grow inside nested ResoureMark scope");
}
}
void Dependencies::write_dependency_to(CompileLog* log,
DepType dept,
GrowableArray<DepArgument>* args,
Klass* witness) {
if (log == NULL) {
return;
}
ResourceMark rm;
ciEnv* env = ciEnv::current();
GrowableArray<ciBaseObject*>* ciargs = new GrowableArray<ciBaseObject*>(args->length());
for (GrowableArrayIterator<DepArgument> it = args->begin(); it != args->end(); ++it) {
DepArgument arg = *it;
if (arg.is_oop()) {
ciargs->push(env->get_object(arg.oop_value()));
} else {
ciargs->push(env->get_metadata(arg.metadata_value()));
}
}
int argslen = ciargs->length();
Dependencies::write_dependency_to(log, dept, ciargs, witness);
guarantee(argslen == ciargs->length(), "ciargs array cannot grow inside nested ResoureMark scope");
}
void Dependencies::write_dependency_to(CompileLog* log,
DepType dept,
GrowableArray<ciBaseObject*>* args,
Klass* witness) {
if (log == NULL) {
return;
}
ResourceMark rm;
GrowableArray<int>* argids = new GrowableArray<int>(args->length());
for (GrowableArrayIterator<ciBaseObject*> it = args->begin(); it != args->end(); ++it) {
ciBaseObject* obj = *it;
if (obj->is_object()) {
argids->push(log->identify(obj->as_object()));
} else {
argids->push(log->identify(obj->as_metadata()));
}
}
if (witness != NULL) {
log->begin_elem("dependency_failed");
} else {
log->begin_elem("dependency");
}
log->print(" type='%s'", dep_name(dept));
const int ctxkj = dep_context_arg(dept); // -1 if no context arg
if (ctxkj >= 0 && ctxkj < argids->length()) {
log->print(" ctxk='%d'", argids->at(ctxkj));
}
for (int j = 0; j < argids->length(); j++) {
if (j == ctxkj) continue; // already logged
if (j == 1) {
log->print( " x='%d'", argids->at(j));
} else {
log->print(" x%d='%d'", j, argids->at(j));
}
}
if (witness != NULL) {
log->object("witness", witness);
log->stamp();
}
log->end_elem();
}
void Dependencies::write_dependency_to(xmlStream* xtty,
DepType dept,
GrowableArray<DepArgument>* args,
Klass* witness) {
if (xtty == NULL) {
return;
}
ResourceMark rm;
ttyLocker ttyl;
int ctxkj = dep_context_arg(dept); // -1 if no context arg
if (witness != NULL) {
xtty->begin_elem("dependency_failed");
} else {
xtty->begin_elem("dependency");
}
xtty->print(" type='%s'", dep_name(dept));
if (ctxkj >= 0) {
xtty->object("ctxk", args->at(ctxkj).metadata_value());
}
for (int j = 0; j < args->length(); j++) {
if (j == ctxkj) continue; // already logged
DepArgument arg = args->at(j);
if (j == 1) {
if (arg.is_oop()) {
xtty->object("x", arg.oop_value());
} else {
xtty->object("x", arg.metadata_value());
}
} else {
char xn[12]; sprintf(xn, "x%d", j);
if (arg.is_oop()) {
xtty->object(xn, arg.oop_value());
} else {
xtty->object(xn, arg.metadata_value());
}
}
}
if (witness != NULL) {
xtty->object("witness", witness);
xtty->stamp();
}
xtty->end_elem();
}
void Dependencies::print_dependency(DepType dept, GrowableArray<DepArgument>* args,
Klass* witness) {
ResourceMark rm;
ttyLocker ttyl; // keep the following output all in one block
tty->print_cr("%s of type %s",
(witness == NULL)? "Dependency": "Failed dependency",
dep_name(dept));
int ctxkj = dep_context_arg(dept); // -1 if no context arg
for (int j = 0; j < args->length(); j++) {
DepArgument arg = args->at(j);
bool put_star = false;
if (arg.is_null()) continue;
const char* what;
if (j == ctxkj) {
assert(arg.is_metadata(), "must be");
what = "context";
put_star = !Dependencies::is_concrete_klass((Klass*)arg.metadata_value());
} else if (arg.is_method()) {
what = "method ";
put_star = !Dependencies::is_concrete_method((Method*)arg.metadata_value(), NULL);
} else if (arg.is_klass()) {
what = "class ";
} else {
what = "object ";
}
tty->print(" %s = %s", what, (put_star? "*": ""));
if (arg.is_klass())
tty->print("%s", ((Klass*)arg.metadata_value())->external_name());
else if (arg.is_method())
((Method*)arg.metadata_value())->print_value();
else
ShouldNotReachHere(); // Provide impl for this type.
tty->cr();
}
if (witness != NULL) {
bool put_star = !Dependencies::is_concrete_klass(witness);
tty->print_cr(" witness = %s%s",
(put_star? "*": ""),
witness->external_name());
}
}
void Dependencies::DepStream::log_dependency(Klass* witness) {
if (_deps == NULL && xtty == NULL) return; // fast cutout for runtime
ResourceMark rm;
const int nargs = argument_count();
GrowableArray<DepArgument>* args = new GrowableArray<DepArgument>(nargs);
for (int j = 0; j < nargs; j++) {
if (type() == call_site_target_value) {
args->push(argument_oop(j));
} else {
args->push(argument(j));
}
}
int argslen = args->length();
if (_deps != NULL && _deps->log() != NULL) {
Dependencies::write_dependency_to(_deps->log(), type(), args, witness);
} else {
Dependencies::write_dependency_to(xtty, type(), args, witness);
}
guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope");
}
void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose) {
ResourceMark rm;
int nargs = argument_count();
GrowableArray<DepArgument>* args = new GrowableArray<DepArgument>(nargs);
for (int j = 0; j < nargs; j++) {
args->push(argument(j));
}
int argslen = args->length();
Dependencies::print_dependency(type(), args, witness);
if (verbose) {
if (_code != NULL) {
tty->print(" code: ");
_code->print_value_on(tty);
tty->cr();
}
}
guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope");
}
#ifdef ASSERT
void Dependencies::DepStream::initial_asserts(size_t byte_limit) {
assert(must_be_in_vm(), "raw oops here");
_byte_limit = byte_limit;
_type = (DepType)(end_marker-1); // defeat "already at end" assert
assert((_code!=NULL) + (_deps!=NULL) == 1, "one or t'other");
}
#endif //ASSERT
bool Dependencies::DepStream::next() {
assert(_type != end_marker, "already at end");
if (_bytes.position() == 0 && _code != NULL
&& _code->dependencies_size() == 0) {
return false;
}
int code_byte = (_bytes.read_byte() & 0xFF);
if (code_byte == end_marker) {
DEBUG_ONLY(_type = end_marker);
return false;
} else {
int ctxk_bit = (code_byte & Dependencies::default_context_type_bit);
code_byte -= ctxk_bit;
DepType dept = (DepType)code_byte;
_type = dept;
Dependencies::check_valid_dependency_type(dept);
int stride = _dep_args[dept];
assert(stride == dep_args(dept), "sanity");
int skipj = -1;
if (ctxk_bit != 0) {
skipj = 0; // currently the only context argument is at zero
assert(skipj == dep_context_arg(dept), "zero arg always ctxk");
}
for (int j = 0; j < stride; j++) {
_xi[j] = (j == skipj)? 0: _bytes.read_int();
}
DEBUG_ONLY(_xi[stride] = -1); // help detect overruns
return true;
}
}
inline Metadata* Dependencies::DepStream::recorded_metadata_at(int i) {
Metadata* o = NULL;
if (_code != NULL) {
o = _code->metadata_at(i);
} else {
o = _deps->oop_recorder()->metadata_at(i);
}
return o;
}
inline oop Dependencies::DepStream::recorded_oop_at(int i) {
return (_code != NULL)
? _code->oop_at(i)
: JNIHandles::resolve(_deps->oop_recorder()->oop_at(i));
}
Metadata* Dependencies::DepStream::argument(int i) {
Metadata* result = recorded_metadata_at(argument_index(i));
if (result == NULL) { // Explicit context argument can be compressed
int ctxkj = dep_context_arg(type()); // -1 if no explicit context arg
if (ctxkj >= 0 && i == ctxkj && ctxkj+1 < argument_count()) {
result = ctxk_encoded_as_null(type(), argument(ctxkj+1));
}
}
assert(result == NULL || result->is_klass() || result->is_method(), "must be");
return result;
}
oop Dependencies::DepStream::argument_oop(int i) {
oop result = recorded_oop_at(argument_index(i));
assert(result == NULL || result->is_oop(), "must be");
return result;
}
Klass* Dependencies::DepStream::context_type() {
assert(must_be_in_vm(), "raw oops here");
{
int ctxkj = dep_context_arg(type()); // -1 if no explicit context arg
if (ctxkj >= 0) {
Metadata* k = argument(ctxkj);
assert(k != NULL && k->is_klass(), "type check");
return (Klass*)k;
}
}
{
int ctxkj = dep_implicit_context_arg(type());
if (ctxkj >= 0) {
Klass* k = argument_oop(ctxkj)->klass();
assert(k != NULL && k->is_klass(), "type check");
return (Klass*) k;
}
}
return NULL;
}
class ClassHierarchyWalker {
public:
enum { PARTICIPANT_LIMIT = 3 };
private:
Symbol* _name;
Symbol* _signature;
Klass* _participants[PARTICIPANT_LIMIT+1];
int _num_participants;
Method* _found_methods[PARTICIPANT_LIMIT+1];
int _record_witnesses;
void initialize(Klass* participant) {
_record_witnesses = 0;
_participants[0] = participant;
_found_methods[0] = NULL;
_num_participants = 0;
if (participant != NULL) {
_participants[1] = NULL;
_found_methods[1] = NULL;
_num_participants = 1;
}
}
void initialize_from_method(Method* m) {
assert(m != NULL && m->is_method(), "sanity");
_name = m->name();
_signature = m->signature();
}
public:
ClassHierarchyWalker(Klass* participant, Method* m) {
initialize_from_method(m);
initialize(participant);
}
ClassHierarchyWalker(Method* m) {
initialize_from_method(m);
initialize(NULL);
}
ClassHierarchyWalker(Klass* participant = NULL) {
_name = NULL;
_signature = NULL;
initialize(participant);
}
ClassHierarchyWalker(Klass* participants[], int num_participants) {
_name = NULL;
_signature = NULL;
initialize(NULL);
for (int i = 0; i < num_participants; ++i) {
add_participant(participants[i]);
}
}
bool doing_subtype_search() {
return _name == NULL;
}
int num_participants() { return _num_participants; }
Klass* participant(int n) {
assert((uint)n <= (uint)_num_participants, "oob");
return _participants[n];
}
Method* found_method(int n) {
assert((uint)n <= (uint)_num_participants, "oob");
Method* fm = _found_methods[n];
assert(n == _num_participants || fm != NULL, "proper usage");
if (fm != NULL && fm->method_holder() != _participants[n]) {
assert(fm->is_default_method(), "sanity");
return NULL;
}
return fm;
}
#ifdef ASSERT
bool check_method_context(Klass* ctxk, Method* m) {
if (m->method_holder() == ctxk)
return true; // Quick win.
if (m->is_private())
return false; // Quick lose. Should not happen.
if (!(m->is_public() || m->is_protected()))
return true; // Must punt the assertion to true.
Klass* k = ctxk;
Method* lm = k->lookup_method(m->name(), m->signature());
if (lm == NULL && k->oop_is_instance()) {
lm = ((InstanceKlass*)k)->lookup_method_in_ordered_interfaces(m->name(),
m->signature());
}
if (lm == m)
return true;
if (lm != NULL) {
if (!(lm->is_public() || lm->is_protected())) {
return true; // Must punt the assertion to true.
}
if (lm->is_static()) {
return true;
}
if ( !Dependencies::is_concrete_method(lm, k)
&& !Dependencies::is_concrete_method(m, ctxk)
&& lm->method_holder()->is_subtype_of(m->method_holder()))
return true;
}
ResourceMark rm;
tty->print_cr("Dependency method not found in the associated context:");
tty->print_cr(" context = %s", ctxk->external_name());
tty->print( " method = "); m->print_short_name(tty); tty->cr();
if (lm != NULL) {
tty->print( " found = "); lm->print_short_name(tty); tty->cr();
}
return false;
}
#endif
void add_participant(Klass* participant) {
assert(_num_participants + _record_witnesses < PARTICIPANT_LIMIT, "oob");
int np = _num_participants++;
_participants[np] = participant;
_participants[np+1] = NULL;
_found_methods[np+1] = NULL;
}
void record_witnesses(int add) {
if (add > PARTICIPANT_LIMIT) add = PARTICIPANT_LIMIT;
assert(_num_participants + add < PARTICIPANT_LIMIT, "oob");
_record_witnesses = add;
}
bool is_witness(Klass* k) {
if (doing_subtype_search()) {
return Dependencies::is_concrete_klass(k);
} else if (!k->oop_is_instance()) {
return false; // no methods to find in an array type
} else {
Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature, Klass::skip_private);
if (!Dependencies::is_concrete_method(m, k)) {
if (!k->is_interface() && m != NULL && m->is_abstract()) {
ClassHierarchyWalker wf(_participants, _num_participants);
Klass* w = wf.find_witness_subtype(k);
if (w != NULL) {
Method* wm = InstanceKlass::cast(w)->find_instance_method(_name, _signature, Klass::skip_private);
if (!Dependencies::is_concrete_method(wm, w)) {
_found_methods[_num_participants] = m;
return true;
}
}
}
Array<Method*>* default_methods = InstanceKlass::cast(k)->default_methods();
if (default_methods == NULL)
return false;
m = InstanceKlass::cast(k)->find_method(default_methods, _name, _signature);
if (!Dependencies::is_concrete_method(m, NULL))
return false;
}
_found_methods[_num_participants] = m;
return true;
}
}
bool is_participant(Klass* k) {
if (k == _participants[0]) {
return true;
} else if (_num_participants <= 1) {
return false;
} else {
return in_list(k, &_participants[1]);
}
}
bool ignore_witness(Klass* witness) {
if (_record_witnesses == 0) {
return false;
} else {
--_record_witnesses;
add_participant(witness);
return true;
}
}
static bool in_list(Klass* x, Klass** list) {
for (int i = 0; ; i++) {
Klass* y = list[i];
if (y == NULL) break;
if (y == x) return true;
}
return false; // not in list
}
private:
Klass* find_witness_anywhere(Klass* context_type,
bool participants_hide_witnesses,
bool top_level_call = true);
Klass* find_witness_in(KlassDepChange& changes,
Klass* context_type,
bool participants_hide_witnesses);
public:
bool witnessed_reabstraction_in_supers(Klass* k);
Klass* find_witness_subtype(Klass* context_type, KlassDepChange* changes = NULL) {
assert(doing_subtype_search(), "must set up a subtype search");
const bool participants_hide_witnesses = true;
if (changes != NULL) {
return find_witness_in(*changes, context_type, participants_hide_witnesses);
} else {
return find_witness_anywhere(context_type, participants_hide_witnesses);
}
}
Klass* find_witness_definer(Klass* context_type, KlassDepChange* changes = NULL) {
assert(!doing_subtype_search(), "must set up a method definer search");
const bool participants_hide_witnesses = true;
if (changes != NULL) {
return find_witness_in(*changes, context_type, !participants_hide_witnesses);
} else {
return find_witness_anywhere(context_type, !participants_hide_witnesses);
}
}
};
#ifndef PRODUCT
static int deps_find_witness_calls = 0;
static int deps_find_witness_steps = 0;
static int deps_find_witness_recursions = 0;
static int deps_find_witness_singles = 0;
static int deps_find_witness_print = 0; // set to -1 to force a final print
static bool count_find_witness_calls() {
if (TraceDependencies || LogCompilation) {
int pcount = deps_find_witness_print + 1;
bool final_stats = (pcount == 0);
bool initial_call = (pcount == 1);
bool occasional_print = ((pcount & ((1<<10) - 1)) == 0);
if (pcount < 0) pcount = 1; // crude overflow protection
deps_find_witness_print = pcount;
if (VerifyDependencies && initial_call) {
tty->print_cr("Warning: TraceDependencies results may be inflated by VerifyDependencies");
}
if (occasional_print || final_stats) {
if (xtty != NULL) {
ttyLocker ttyl;
xtty->elem("deps_find_witness calls='%d' steps='%d' recursions='%d' singles='%d'",
deps_find_witness_calls,
deps_find_witness_steps,
deps_find_witness_recursions,
deps_find_witness_singles);
}
if (final_stats || (TraceDependencies && WizardMode)) {
ttyLocker ttyl;
tty->print_cr("Dependency check (find_witness) "
"calls=%d, steps=%d (avg=%.1f), recursions=%d, singles=%d",
deps_find_witness_calls,
deps_find_witness_steps,
(double)deps_find_witness_steps / deps_find_witness_calls,
deps_find_witness_recursions,
deps_find_witness_singles);
}
}
return true;
}
return false;
}
#else
#define count_find_witness_calls() (0)
#endif //PRODUCT
Klass* ClassHierarchyWalker::find_witness_in(KlassDepChange& changes,
Klass* context_type,
bool participants_hide_witnesses) {
assert(changes.involves_context(context_type), "irrelevant dependency");
Klass* new_type = changes.new_type();
(void)count_find_witness_calls();
NOT_PRODUCT(deps_find_witness_singles++);
assert(must_be_in_vm(), "raw oops here");
assert_locked_or_safepoint(Compile_lock);
int nof_impls = InstanceKlass::cast(context_type)->nof_implementors();
if (nof_impls > 1) {
return context_type;
}
assert(!is_participant(new_type), "only old classes are participants");
if (participants_hide_witnesses) {
for (int i = 0; i < num_participants(); i++) {
Klass* part = participant(i);
if (part == NULL) continue;
assert(changes.involves_context(part) == new_type->is_subtype_of(part),
"correct marking of participants, b/c new_type is unique");
if (changes.involves_context(part)) {
return NULL;
}
}
}
if (is_witness(new_type) && !ignore_witness(new_type)) {
return new_type;
}
return NULL;
}
Klass* ClassHierarchyWalker::find_witness_anywhere(Klass* context_type,
bool participants_hide_witnesses,
bool top_level_call) {
assert(must_be_in_vm(), "raw oops here");
assert_locked_or_safepoint(Compile_lock);
bool do_counts = count_find_witness_calls();
if (top_level_call) {
if (do_counts) {
NOT_PRODUCT(deps_find_witness_calls++);
NOT_PRODUCT(deps_find_witness_steps++);
}
if (is_participant(context_type)) {
if (participants_hide_witnesses) return NULL;
} else if (is_witness(context_type) && !ignore_witness(context_type)) {
return context_type;
}
}
const int CHAINMAX = 100; // >= 1 + InstanceKlass::implementors_limit
Klass* chains[CHAINMAX];
int chaini = 0; // index into worklist
Klass* chain; // scratch variable
#define ADD_SUBCLASS_CHAIN(k) { \
assert(chaini < CHAINMAX, "oob"); \
chain = k->subklass(); \
if (chain != NULL) chains[chaini++] = chain; }
ADD_SUBCLASS_CHAIN(context_type);
if (top_level_call) {
int nof_impls = InstanceKlass::cast(context_type)->nof_implementors();
if (nof_impls > 1) {
return context_type;
}
if (nof_impls > 0) {
Klass* impl = InstanceKlass::cast(context_type)->implementor();
assert(impl != NULL, "just checking");
if (impl == context_type) {
return context_type; // report an inexact witness to this sad affair
}
if (do_counts)
{ NOT_PRODUCT(deps_find_witness_steps++); }
if (is_participant(impl)) {
if (!participants_hide_witnesses) {
ADD_SUBCLASS_CHAIN(impl);
}
} else if (is_witness(impl) && !ignore_witness(impl)) {
return impl;
} else {
ADD_SUBCLASS_CHAIN(impl);
}
}
}
while (chaini > 0) {
Klass* chain = chains[--chaini];
for (Klass* sub = chain; sub != NULL; sub = sub->next_sibling()) {
if (do_counts) { NOT_PRODUCT(deps_find_witness_steps++); }
if (is_participant(sub)) {
if (participants_hide_witnesses) continue;
} else if (is_witness(sub) && !ignore_witness(sub)) {
return sub;
}
if (chaini < (VerifyDependencies? 2: CHAINMAX)) {
ADD_SUBCLASS_CHAIN(sub);
} else {
if (do_counts) { NOT_PRODUCT(deps_find_witness_recursions++); }
Klass* witness = find_witness_anywhere(sub,
participants_hide_witnesses,
if (witness != NULL) return witness;
}
}
}
return NULL;
#undef ADD_SUBCLASS_CHAIN
}
bool ClassHierarchyWalker::witnessed_reabstraction_in_supers(Klass* k) {
if (!k->oop_is_instance()) {
return false; // no methods to find in an array type
} else {
if (Dependencies::is_concrete_klass(k) && !k->is_interface()) {
Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature, Klass::skip_private);
if (m != NULL) {
return false; // no reabstraction possible: local method found
}
for (InstanceKlass* super = InstanceKlass::cast(k)->java_super(); super != NULL; super = super->java_super()) {
m = super->find_instance_method(_name, _signature, Klass::skip_private);
if (m != NULL) { // inherited method found
if (m->is_abstract() || m->is_overpass()) {
_found_methods[_num_participants] = m;
return true; // abstract method found
}
return false;
}
}
assert(false, "root method not found");
return true;
}
return false;
}
}
bool Dependencies::is_concrete_klass(Klass* k) {
if (k->is_abstract()) return false;
return true;
}
bool Dependencies::is_concrete_method(Method* m, Klass * k) {
return ! ( m == NULL || m -> is_static() || m -> is_abstract() ||
m->is_overpass() && k != NULL && k -> is_abstract() );
}
Klass* Dependencies::find_finalizable_subclass(Klass* k) {
if (k->is_interface()) return NULL;
if (k->has_finalizer()) return k;
k = k->subklass();
while (k != NULL) {
Klass* result = find_finalizable_subclass(k);
if (result != NULL) return result;
k = k->next_sibling();
}
return NULL;
}
bool Dependencies::is_concrete_klass(ciInstanceKlass* k) {
if (k->is_abstract()) return false;
return true;
}
bool Dependencies::has_finalizable_subclass(ciInstanceKlass* k) {
return k->has_finalizable_subclass();
}
Klass* Dependencies::check_evol_method(Method* m) {
assert(must_be_in_vm(), "raw oops here");
if (m->is_old()
|| m->number_of_breakpoints() > 0) {
return m->method_holder();
} else {
return NULL;
}
}
Klass* Dependencies::check_leaf_type(Klass* ctxk) {
assert(must_be_in_vm(), "raw oops here");
assert_locked_or_safepoint(Compile_lock);
InstanceKlass* ctx = InstanceKlass::cast(ctxk);
Klass* sub = ctx->subklass();
if (sub != NULL) {
return sub;
} else if (ctx->nof_implementors() != 0) {
Klass* impl = ctx->implementor();
assert(impl != NULL, "must be set");
return impl;
} else {
return NULL;
}
}
Klass* Dependencies::check_abstract_with_unique_concrete_subtype(Klass* ctxk,
Klass* conck,
KlassDepChange* changes) {
ClassHierarchyWalker wf(conck);
return wf.find_witness_subtype(ctxk, changes);
}
Klass* Dependencies::check_abstract_with_no_concrete_subtype(Klass* ctxk,
KlassDepChange* changes) {
ClassHierarchyWalker wf;
return wf.find_witness_subtype(ctxk, changes);
}
Klass* Dependencies::check_concrete_with_no_concrete_subtype(Klass* ctxk,
KlassDepChange* changes) {
ClassHierarchyWalker wf(ctxk);
return wf.find_witness_subtype(ctxk, changes);
}
ssssssssss17
最新推荐文章于 2024-09-08 12:41:07 发布