Merge
This commit is contained in:
commit
f421c295bd
@ -306,4 +306,5 @@ cb8a4e04bc8c104de8a2f67463c7e31232bf8d68 jdk8-b69
|
||||
e94068d4ff52849c8aa0786a53a59b63d1312a39 jdk8-b70
|
||||
0847210f85480bf3848dc90bc2ab23c0a4791b55 jdk8-b71
|
||||
d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72
|
||||
1e129851479e4f5df439109fca2c7be1f1613522 hs25-b15
|
||||
11619f33cd683c2f1d6ef72f1c6ff3dacf5a9f1c jdk8-b73
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# @(#)mapfile-vers-debug 1.18 07/10/25 16:47:35
|
||||
# @(#)mapfile-vers-debug 1.18 07/10/25 16:47:35
|
||||
#
|
||||
|
||||
#
|
||||
@ -126,8 +126,9 @@ SUNWprivate_1.1 {
|
||||
JVM_GetClassModifiers;
|
||||
JVM_GetClassName;
|
||||
JVM_GetClassNameUTF;
|
||||
JVM_GetClassSignature;
|
||||
JVM_GetClassSignature;
|
||||
JVM_GetClassSigners;
|
||||
JVM_GetClassTypeAnnotations;
|
||||
JVM_GetComponentType;
|
||||
JVM_GetDeclaredClasses;
|
||||
JVM_GetDeclaringClass;
|
||||
@ -154,6 +155,7 @@ SUNWprivate_1.1 {
|
||||
JVM_GetMethodIxNameUTF;
|
||||
JVM_GetMethodIxSignatureUTF;
|
||||
JVM_GetMethodParameterAnnotations;
|
||||
JVM_GetMethodParameters;
|
||||
JVM_GetPrimitiveArrayElement;
|
||||
JVM_GetProtectionDomain;
|
||||
JVM_GetSockName;
|
||||
@ -283,7 +285,7 @@ SUNWprivate_1.1 {
|
||||
# This is for Forte Analyzer profiling support.
|
||||
AsyncGetCallTrace;
|
||||
|
||||
# INSERT VTABLE SYMBOLS HERE
|
||||
# INSERT VTABLE SYMBOLS HERE
|
||||
|
||||
local:
|
||||
*;
|
||||
|
@ -128,6 +128,7 @@ SUNWprivate_1.1 {
|
||||
JVM_GetClassNameUTF;
|
||||
JVM_GetClassSignature;
|
||||
JVM_GetClassSigners;
|
||||
JVM_GetClassTypeAnnotations;
|
||||
JVM_GetComponentType;
|
||||
JVM_GetDeclaredClasses;
|
||||
JVM_GetDeclaringClass;
|
||||
@ -154,6 +155,7 @@ SUNWprivate_1.1 {
|
||||
JVM_GetMethodIxNameUTF;
|
||||
JVM_GetMethodIxSignatureUTF;
|
||||
JVM_GetMethodParameterAnnotations;
|
||||
JVM_GetMethodParameters;
|
||||
JVM_GetPrimitiveArrayElement;
|
||||
JVM_GetProtectionDomain;
|
||||
JVM_GetSockName;
|
||||
|
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2012
|
||||
|
||||
HS_MAJOR_VER=25
|
||||
HS_MINOR_VER=0
|
||||
HS_BUILD_NUMBER=14
|
||||
HS_BUILD_NUMBER=15
|
||||
|
||||
JDK_MAJOR_VER=1
|
||||
JDK_MINOR_VER=8
|
||||
|
@ -124,6 +124,7 @@ SUNWprivate_1.1 {
|
||||
JVM_GetClassNameUTF;
|
||||
JVM_GetClassSignature;
|
||||
JVM_GetClassSigners;
|
||||
JVM_GetClassTypeAnnotations;
|
||||
JVM_GetComponentType;
|
||||
JVM_GetDeclaredClasses;
|
||||
JVM_GetDeclaringClass;
|
||||
@ -150,6 +151,7 @@ SUNWprivate_1.1 {
|
||||
JVM_GetMethodIxNameUTF;
|
||||
JVM_GetMethodIxSignatureUTF;
|
||||
JVM_GetMethodParameterAnnotations;
|
||||
JVM_GetMethodParameters;
|
||||
JVM_GetPrimitiveArrayElement;
|
||||
JVM_GetProtectionDomain;
|
||||
JVM_GetSockName;
|
||||
|
@ -124,6 +124,7 @@ SUNWprivate_1.1 {
|
||||
JVM_GetClassNameUTF;
|
||||
JVM_GetClassSignature;
|
||||
JVM_GetClassSigners;
|
||||
JVM_GetClassTypeAnnotations;
|
||||
JVM_GetComponentType;
|
||||
JVM_GetDeclaredClasses;
|
||||
JVM_GetDeclaringClass;
|
||||
@ -150,6 +151,7 @@ SUNWprivate_1.1 {
|
||||
JVM_GetMethodIxNameUTF;
|
||||
JVM_GetMethodIxSignatureUTF;
|
||||
JVM_GetMethodParameterAnnotations;
|
||||
JVM_GetMethodParameters;
|
||||
JVM_GetPrimitiveArrayElement;
|
||||
JVM_GetProtectionDomain;
|
||||
JVM_GetSockName;
|
||||
|
@ -26,235 +26,237 @@
|
||||
|
||||
SUNWprivate_1.1 {
|
||||
global:
|
||||
# JNI
|
||||
# JNI
|
||||
JNI_CreateJavaVM;
|
||||
JNI_GetCreatedJavaVMs;
|
||||
JNI_GetDefaultJavaVMInitArgs;
|
||||
|
||||
# JVM
|
||||
JVM_Accept;
|
||||
JVM_ActiveProcessorCount;
|
||||
JVM_AllocateNewArray;
|
||||
JVM_AllocateNewObject;
|
||||
JVM_ArrayCopy;
|
||||
JVM_AssertionStatusDirectives;
|
||||
JVM_Available;
|
||||
JVM_Bind;
|
||||
JVM_ClassDepth;
|
||||
JVM_ClassLoaderDepth;
|
||||
JVM_Clone;
|
||||
JVM_Close;
|
||||
JVM_CX8Field;
|
||||
JVM_CompileClass;
|
||||
JVM_CompileClasses;
|
||||
JVM_CompilerCommand;
|
||||
JVM_Connect;
|
||||
JVM_ConstantPoolGetClassAt;
|
||||
JVM_ConstantPoolGetClassAtIfLoaded;
|
||||
JVM_ConstantPoolGetDoubleAt;
|
||||
JVM_ConstantPoolGetFieldAt;
|
||||
JVM_ConstantPoolGetFieldAtIfLoaded;
|
||||
JVM_ConstantPoolGetFloatAt;
|
||||
JVM_ConstantPoolGetIntAt;
|
||||
JVM_ConstantPoolGetLongAt;
|
||||
JVM_ConstantPoolGetMethodAt;
|
||||
JVM_ConstantPoolGetMethodAtIfLoaded;
|
||||
JVM_ConstantPoolGetMemberRefInfoAt;
|
||||
JVM_ConstantPoolGetSize;
|
||||
JVM_ConstantPoolGetStringAt;
|
||||
JVM_ConstantPoolGetUTF8At;
|
||||
JVM_CountStackFrames;
|
||||
JVM_CurrentClassLoader;
|
||||
JVM_CurrentLoadedClass;
|
||||
JVM_CurrentThread;
|
||||
JVM_CurrentTimeMillis;
|
||||
JVM_DefineClass;
|
||||
JVM_DefineClassWithSource;
|
||||
JVM_DefineClassWithSourceCond;
|
||||
JVM_DesiredAssertionStatus;
|
||||
JVM_DisableCompiler;
|
||||
JVM_DoPrivileged;
|
||||
JVM_DTraceGetVersion;
|
||||
JVM_DTraceActivate;
|
||||
JVM_DTraceIsProbeEnabled;
|
||||
JVM_DTraceIsSupported;
|
||||
JVM_DTraceDispose;
|
||||
JVM_DumpAllStacks;
|
||||
JVM_DumpThreads;
|
||||
JVM_EnableCompiler;
|
||||
JVM_Exit;
|
||||
JVM_FillInStackTrace;
|
||||
JVM_FindClassFromClass;
|
||||
JVM_FindClassFromClassLoader;
|
||||
JVM_FindClassFromBootLoader;
|
||||
JVM_FindLibraryEntry;
|
||||
JVM_FindLoadedClass;
|
||||
JVM_FindPrimitiveClass;
|
||||
JVM_FindSignal;
|
||||
JVM_FreeMemory;
|
||||
JVM_GC;
|
||||
JVM_GetAllThreads;
|
||||
JVM_GetArrayElement;
|
||||
JVM_GetArrayLength;
|
||||
JVM_GetCPClassNameUTF;
|
||||
JVM_GetCPFieldClassNameUTF;
|
||||
JVM_GetCPFieldModifiers;
|
||||
JVM_GetCPFieldNameUTF;
|
||||
JVM_GetCPFieldSignatureUTF;
|
||||
JVM_GetCPMethodClassNameUTF;
|
||||
JVM_GetCPMethodModifiers;
|
||||
JVM_GetCPMethodNameUTF;
|
||||
JVM_GetCPMethodSignatureUTF;
|
||||
JVM_GetCallerClass;
|
||||
JVM_GetClassAccessFlags;
|
||||
JVM_GetClassAnnotations;
|
||||
JVM_GetClassCPEntriesCount;
|
||||
JVM_GetClassCPTypes;
|
||||
JVM_GetClassConstantPool;
|
||||
JVM_GetClassContext;
|
||||
JVM_GetClassDeclaredConstructors;
|
||||
JVM_GetClassDeclaredFields;
|
||||
JVM_GetClassDeclaredMethods;
|
||||
JVM_GetClassFieldsCount;
|
||||
JVM_GetClassInterfaces;
|
||||
JVM_GetClassLoader;
|
||||
JVM_GetClassMethodsCount;
|
||||
JVM_GetClassModifiers;
|
||||
JVM_GetClassName;
|
||||
JVM_GetClassNameUTF;
|
||||
JVM_GetClassSignature;
|
||||
JVM_GetClassSigners;
|
||||
JVM_GetComponentType;
|
||||
JVM_GetDeclaredClasses;
|
||||
JVM_GetDeclaringClass;
|
||||
JVM_GetEnclosingMethodInfo;
|
||||
JVM_GetFieldAnnotations;
|
||||
JVM_GetFieldIxModifiers;
|
||||
JVM_GetHostName;
|
||||
JVM_GetInheritedAccessControlContext;
|
||||
JVM_GetInterfaceVersion;
|
||||
JVM_GetLastErrorString;
|
||||
JVM_GetManagement;
|
||||
JVM_GetMethodAnnotations;
|
||||
JVM_GetMethodDefaultAnnotationValue;
|
||||
JVM_GetMethodIxArgsSize;
|
||||
JVM_GetMethodIxByteCode;
|
||||
JVM_GetMethodIxByteCodeLength;
|
||||
JVM_GetMethodIxExceptionIndexes;
|
||||
JVM_GetMethodIxExceptionTableEntry;
|
||||
JVM_GetMethodIxExceptionTableLength;
|
||||
JVM_GetMethodIxExceptionsCount;
|
||||
JVM_GetMethodIxLocalsCount;
|
||||
JVM_GetMethodIxMaxStack;
|
||||
JVM_GetMethodIxModifiers;
|
||||
JVM_GetMethodIxNameUTF;
|
||||
JVM_GetMethodIxSignatureUTF;
|
||||
JVM_GetMethodParameterAnnotations;
|
||||
JVM_GetPrimitiveArrayElement;
|
||||
JVM_GetProtectionDomain;
|
||||
JVM_GetSockName;
|
||||
JVM_GetSockOpt;
|
||||
JVM_GetStackAccessControlContext;
|
||||
JVM_GetStackTraceDepth;
|
||||
JVM_GetStackTraceElement;
|
||||
JVM_GetSystemPackage;
|
||||
JVM_GetSystemPackages;
|
||||
JVM_GetThreadStateNames;
|
||||
JVM_GetThreadStateValues;
|
||||
JVM_GetVersionInfo;
|
||||
JVM_Halt;
|
||||
JVM_HoldsLock;
|
||||
JVM_IHashCode;
|
||||
JVM_InitAgentProperties;
|
||||
JVM_InitProperties;
|
||||
JVM_InitializeCompiler;
|
||||
JVM_InitializeSocketLibrary;
|
||||
JVM_InternString;
|
||||
JVM_Interrupt;
|
||||
JVM_InvokeMethod;
|
||||
JVM_IsArrayClass;
|
||||
JVM_IsConstructorIx;
|
||||
JVM_IsInterface;
|
||||
JVM_IsInterrupted;
|
||||
JVM_IsNaN;
|
||||
JVM_IsPrimitiveClass;
|
||||
JVM_IsSameClassPackage;
|
||||
JVM_IsSilentCompiler;
|
||||
JVM_IsSupportedJNIVersion;
|
||||
JVM_IsThreadAlive;
|
||||
JVM_LatestUserDefinedLoader;
|
||||
JVM_Listen;
|
||||
JVM_LoadClass0;
|
||||
JVM_LoadLibrary;
|
||||
JVM_Lseek;
|
||||
JVM_MaxObjectInspectionAge;
|
||||
JVM_MaxMemory;
|
||||
JVM_MonitorNotify;
|
||||
JVM_MonitorNotifyAll;
|
||||
JVM_MonitorWait;
|
||||
JVM_NativePath;
|
||||
JVM_NanoTime;
|
||||
JVM_NewArray;
|
||||
JVM_NewInstanceFromConstructor;
|
||||
JVM_NewMultiArray;
|
||||
JVM_OnExit;
|
||||
JVM_Open;
|
||||
JVM_PrintStackTrace;
|
||||
JVM_RaiseSignal;
|
||||
JVM_RawMonitorCreate;
|
||||
JVM_RawMonitorDestroy;
|
||||
JVM_RawMonitorEnter;
|
||||
JVM_RawMonitorExit;
|
||||
JVM_Read;
|
||||
JVM_Recv;
|
||||
JVM_RecvFrom;
|
||||
JVM_RegisterSignal;
|
||||
JVM_ReleaseUTF;
|
||||
JVM_ResolveClass;
|
||||
JVM_ResumeThread;
|
||||
JVM_Send;
|
||||
JVM_SendTo;
|
||||
JVM_SetArrayElement;
|
||||
JVM_SetClassSigners;
|
||||
JVM_SetLength;
|
||||
|
||||
# JVM
|
||||
JVM_Accept;
|
||||
JVM_ActiveProcessorCount;
|
||||
JVM_AllocateNewArray;
|
||||
JVM_AllocateNewObject;
|
||||
JVM_ArrayCopy;
|
||||
JVM_AssertionStatusDirectives;
|
||||
JVM_Available;
|
||||
JVM_Bind;
|
||||
JVM_ClassDepth;
|
||||
JVM_ClassLoaderDepth;
|
||||
JVM_Clone;
|
||||
JVM_Close;
|
||||
JVM_CX8Field;
|
||||
JVM_CompileClass;
|
||||
JVM_CompileClasses;
|
||||
JVM_CompilerCommand;
|
||||
JVM_Connect;
|
||||
JVM_ConstantPoolGetClassAt;
|
||||
JVM_ConstantPoolGetClassAtIfLoaded;
|
||||
JVM_ConstantPoolGetDoubleAt;
|
||||
JVM_ConstantPoolGetFieldAt;
|
||||
JVM_ConstantPoolGetFieldAtIfLoaded;
|
||||
JVM_ConstantPoolGetFloatAt;
|
||||
JVM_ConstantPoolGetIntAt;
|
||||
JVM_ConstantPoolGetLongAt;
|
||||
JVM_ConstantPoolGetMethodAt;
|
||||
JVM_ConstantPoolGetMethodAtIfLoaded;
|
||||
JVM_ConstantPoolGetMemberRefInfoAt;
|
||||
JVM_ConstantPoolGetSize;
|
||||
JVM_ConstantPoolGetStringAt;
|
||||
JVM_ConstantPoolGetUTF8At;
|
||||
JVM_CountStackFrames;
|
||||
JVM_CurrentClassLoader;
|
||||
JVM_CurrentLoadedClass;
|
||||
JVM_CurrentThread;
|
||||
JVM_CurrentTimeMillis;
|
||||
JVM_DefineClass;
|
||||
JVM_DefineClassWithSource;
|
||||
JVM_DefineClassWithSourceCond;
|
||||
JVM_DesiredAssertionStatus;
|
||||
JVM_DisableCompiler;
|
||||
JVM_DoPrivileged;
|
||||
JVM_DTraceGetVersion;
|
||||
JVM_DTraceActivate;
|
||||
JVM_DTraceIsProbeEnabled;
|
||||
JVM_DTraceIsSupported;
|
||||
JVM_DTraceDispose;
|
||||
JVM_DumpAllStacks;
|
||||
JVM_DumpThreads;
|
||||
JVM_EnableCompiler;
|
||||
JVM_Exit;
|
||||
JVM_FillInStackTrace;
|
||||
JVM_FindClassFromClass;
|
||||
JVM_FindClassFromClassLoader;
|
||||
JVM_FindClassFromBootLoader;
|
||||
JVM_FindLibraryEntry;
|
||||
JVM_FindLoadedClass;
|
||||
JVM_FindPrimitiveClass;
|
||||
JVM_FindSignal;
|
||||
JVM_FreeMemory;
|
||||
JVM_GC;
|
||||
JVM_GetAllThreads;
|
||||
JVM_GetArrayElement;
|
||||
JVM_GetArrayLength;
|
||||
JVM_GetCPClassNameUTF;
|
||||
JVM_GetCPFieldClassNameUTF;
|
||||
JVM_GetCPFieldModifiers;
|
||||
JVM_GetCPFieldNameUTF;
|
||||
JVM_GetCPFieldSignatureUTF;
|
||||
JVM_GetCPMethodClassNameUTF;
|
||||
JVM_GetCPMethodModifiers;
|
||||
JVM_GetCPMethodNameUTF;
|
||||
JVM_GetCPMethodSignatureUTF;
|
||||
JVM_GetCallerClass;
|
||||
JVM_GetClassAccessFlags;
|
||||
JVM_GetClassAnnotations;
|
||||
JVM_GetClassCPEntriesCount;
|
||||
JVM_GetClassCPTypes;
|
||||
JVM_GetClassConstantPool;
|
||||
JVM_GetClassContext;
|
||||
JVM_GetClassDeclaredConstructors;
|
||||
JVM_GetClassDeclaredFields;
|
||||
JVM_GetClassDeclaredMethods;
|
||||
JVM_GetClassFieldsCount;
|
||||
JVM_GetClassInterfaces;
|
||||
JVM_GetClassLoader;
|
||||
JVM_GetClassMethodsCount;
|
||||
JVM_GetClassModifiers;
|
||||
JVM_GetClassName;
|
||||
JVM_GetClassNameUTF;
|
||||
JVM_GetClassSignature;
|
||||
JVM_GetClassSigners;
|
||||
JVM_GetComponentType;
|
||||
JVM_GetClassTypeAnnotations;
|
||||
JVM_GetDeclaredClasses;
|
||||
JVM_GetDeclaringClass;
|
||||
JVM_GetEnclosingMethodInfo;
|
||||
JVM_GetFieldAnnotations;
|
||||
JVM_GetFieldIxModifiers;
|
||||
JVM_GetHostName;
|
||||
JVM_GetInheritedAccessControlContext;
|
||||
JVM_GetInterfaceVersion;
|
||||
JVM_GetLastErrorString;
|
||||
JVM_GetManagement;
|
||||
JVM_GetMethodAnnotations;
|
||||
JVM_GetMethodDefaultAnnotationValue;
|
||||
JVM_GetMethodIxArgsSize;
|
||||
JVM_GetMethodIxByteCode;
|
||||
JVM_GetMethodIxByteCodeLength;
|
||||
JVM_GetMethodIxExceptionIndexes;
|
||||
JVM_GetMethodIxExceptionTableEntry;
|
||||
JVM_GetMethodIxExceptionTableLength;
|
||||
JVM_GetMethodIxExceptionsCount;
|
||||
JVM_GetMethodIxLocalsCount;
|
||||
JVM_GetMethodIxMaxStack;
|
||||
JVM_GetMethodIxModifiers;
|
||||
JVM_GetMethodIxNameUTF;
|
||||
JVM_GetMethodIxSignatureUTF;
|
||||
JVM_GetMethodParameterAnnotations;
|
||||
JVM_GetMethodParameters;
|
||||
JVM_GetPrimitiveArrayElement;
|
||||
JVM_GetProtectionDomain;
|
||||
JVM_GetSockName;
|
||||
JVM_GetSockOpt;
|
||||
JVM_GetStackAccessControlContext;
|
||||
JVM_GetStackTraceDepth;
|
||||
JVM_GetStackTraceElement;
|
||||
JVM_GetSystemPackage;
|
||||
JVM_GetSystemPackages;
|
||||
JVM_GetThreadStateNames;
|
||||
JVM_GetThreadStateValues;
|
||||
JVM_GetVersionInfo;
|
||||
JVM_Halt;
|
||||
JVM_HoldsLock;
|
||||
JVM_IHashCode;
|
||||
JVM_InitAgentProperties;
|
||||
JVM_InitProperties;
|
||||
JVM_InitializeCompiler;
|
||||
JVM_InitializeSocketLibrary;
|
||||
JVM_InternString;
|
||||
JVM_Interrupt;
|
||||
JVM_InvokeMethod;
|
||||
JVM_IsArrayClass;
|
||||
JVM_IsConstructorIx;
|
||||
JVM_IsInterface;
|
||||
JVM_IsInterrupted;
|
||||
JVM_IsNaN;
|
||||
JVM_IsPrimitiveClass;
|
||||
JVM_IsSameClassPackage;
|
||||
JVM_IsSilentCompiler;
|
||||
JVM_IsSupportedJNIVersion;
|
||||
JVM_IsThreadAlive;
|
||||
JVM_LatestUserDefinedLoader;
|
||||
JVM_Listen;
|
||||
JVM_LoadClass0;
|
||||
JVM_LoadLibrary;
|
||||
JVM_Lseek;
|
||||
JVM_MaxObjectInspectionAge;
|
||||
JVM_MaxMemory;
|
||||
JVM_MonitorNotify;
|
||||
JVM_MonitorNotifyAll;
|
||||
JVM_MonitorWait;
|
||||
JVM_NativePath;
|
||||
JVM_NanoTime;
|
||||
JVM_NewArray;
|
||||
JVM_NewInstanceFromConstructor;
|
||||
JVM_NewMultiArray;
|
||||
JVM_OnExit;
|
||||
JVM_Open;
|
||||
JVM_PrintStackTrace;
|
||||
JVM_RaiseSignal;
|
||||
JVM_RawMonitorCreate;
|
||||
JVM_RawMonitorDestroy;
|
||||
JVM_RawMonitorEnter;
|
||||
JVM_RawMonitorExit;
|
||||
JVM_Read;
|
||||
JVM_Recv;
|
||||
JVM_RecvFrom;
|
||||
JVM_RegisterSignal;
|
||||
JVM_ReleaseUTF;
|
||||
JVM_ResolveClass;
|
||||
JVM_ResumeThread;
|
||||
JVM_Send;
|
||||
JVM_SendTo;
|
||||
JVM_SetArrayElement;
|
||||
JVM_SetClassSigners;
|
||||
JVM_SetLength;
|
||||
JVM_SetNativeThreadName;
|
||||
JVM_SetPrimitiveArrayElement;
|
||||
JVM_SetProtectionDomain;
|
||||
JVM_SetSockOpt;
|
||||
JVM_SetThreadPriority;
|
||||
JVM_Sleep;
|
||||
JVM_Socket;
|
||||
JVM_SocketAvailable;
|
||||
JVM_SocketClose;
|
||||
JVM_SocketShutdown;
|
||||
JVM_StartThread;
|
||||
JVM_StopThread;
|
||||
JVM_SuspendThread;
|
||||
JVM_SupportsCX8;
|
||||
JVM_Sync;
|
||||
JVM_Timeout;
|
||||
JVM_TotalMemory;
|
||||
JVM_TraceInstructions;
|
||||
JVM_TraceMethodCalls;
|
||||
JVM_UnloadLibrary;
|
||||
JVM_Write;
|
||||
JVM_Yield;
|
||||
JVM_handle_solaris_signal;
|
||||
JVM_SetPrimitiveArrayElement;
|
||||
JVM_SetProtectionDomain;
|
||||
JVM_SetSockOpt;
|
||||
JVM_SetThreadPriority;
|
||||
JVM_Sleep;
|
||||
JVM_Socket;
|
||||
JVM_SocketAvailable;
|
||||
JVM_SocketClose;
|
||||
JVM_SocketShutdown;
|
||||
JVM_StartThread;
|
||||
JVM_StopThread;
|
||||
JVM_SuspendThread;
|
||||
JVM_SupportsCX8;
|
||||
JVM_Sync;
|
||||
JVM_Timeout;
|
||||
JVM_TotalMemory;
|
||||
JVM_TraceInstructions;
|
||||
JVM_TraceMethodCalls;
|
||||
JVM_UnloadLibrary;
|
||||
JVM_Write;
|
||||
JVM_Yield;
|
||||
JVM_handle_solaris_signal;
|
||||
|
||||
# miscellaneous functions
|
||||
jio_fprintf;
|
||||
jio_printf;
|
||||
jio_snprintf;
|
||||
jio_vfprintf;
|
||||
jio_vsnprintf;
|
||||
# miscellaneous functions
|
||||
jio_fprintf;
|
||||
jio_printf;
|
||||
jio_snprintf;
|
||||
jio_vfprintf;
|
||||
jio_vsnprintf;
|
||||
|
||||
# Needed because there is no JVM interface for this.
|
||||
sysThreadAvailableStackWithSlack;
|
||||
# Needed because there is no JVM interface for this.
|
||||
sysThreadAvailableStackWithSlack;
|
||||
|
||||
# This is for Forte Analyzer profiling support.
|
||||
AsyncGetCallTrace;
|
||||
# This is for Forte Analyzer profiling support.
|
||||
AsyncGetCallTrace;
|
||||
|
||||
# INSERT VTABLE SYMBOLS HERE
|
||||
# INSERT VTABLE SYMBOLS HERE
|
||||
|
||||
local:
|
||||
*;
|
||||
|
@ -675,8 +675,8 @@ public:
|
||||
AbstractAssembler::flush();
|
||||
}
|
||||
|
||||
inline void emit_long(int); // shadows AbstractAssembler::emit_long
|
||||
inline void emit_data(int x) { emit_long(x); }
|
||||
inline void emit_int32(int); // shadows AbstractAssembler::emit_int32
|
||||
inline void emit_data(int x) { emit_int32(x); }
|
||||
inline void emit_data(int, RelocationHolder const&);
|
||||
inline void emit_data(int, relocInfo::relocType rtype);
|
||||
// helper for above fcns
|
||||
@ -691,12 +691,12 @@ public:
|
||||
inline void add(Register s1, Register s2, Register d );
|
||||
inline void add(Register s1, int simm13a, Register d );
|
||||
|
||||
void addcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void addcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void addc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void addc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void addccc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void addccc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void addcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void addcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void addc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(addc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void addc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(addc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void addccc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(addc_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void addccc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(addc_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
|
||||
// pp 136
|
||||
@ -749,76 +749,76 @@ public:
|
||||
// at address s1 is swapped with the data in d. If the values are not equal,
|
||||
// the the contents of memory at s1 is loaded into d, without the swap.
|
||||
|
||||
void casa( Register s1, Register s2, Register d, int ia = -1 ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(casa_op3 ) | rs1(s1) | (ia == -1 ? immed(true) : imm_asi(ia)) | rs2(s2)); }
|
||||
void casxa( Register s1, Register s2, Register d, int ia = -1 ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(casxa_op3) | rs1(s1) | (ia == -1 ? immed(true) : imm_asi(ia)) | rs2(s2)); }
|
||||
void casa( Register s1, Register s2, Register d, int ia = -1 ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(casa_op3 ) | rs1(s1) | (ia == -1 ? immed(true) : imm_asi(ia)) | rs2(s2)); }
|
||||
void casxa( Register s1, Register s2, Register d, int ia = -1 ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(casxa_op3) | rs1(s1) | (ia == -1 ? immed(true) : imm_asi(ia)) | rs2(s2)); }
|
||||
|
||||
// pp 152
|
||||
|
||||
void udiv( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(udiv_op3 ) | rs1(s1) | rs2(s2)); }
|
||||
void udiv( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(udiv_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void sdiv( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sdiv_op3 ) | rs1(s1) | rs2(s2)); }
|
||||
void sdiv( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sdiv_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void udivcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(udiv_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); }
|
||||
void udivcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(udiv_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void sdivcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sdiv_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); }
|
||||
void sdivcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sdiv_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void udiv( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(udiv_op3 ) | rs1(s1) | rs2(s2)); }
|
||||
void udiv( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(udiv_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void sdiv( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sdiv_op3 ) | rs1(s1) | rs2(s2)); }
|
||||
void sdiv( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sdiv_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void udivcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(udiv_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); }
|
||||
void udivcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(udiv_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void sdivcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sdiv_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); }
|
||||
void sdivcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sdiv_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 155
|
||||
|
||||
void done() { v9_only(); cti(); emit_long( op(arith_op) | fcn(0) | op3(done_op3) ); }
|
||||
void retry() { v9_only(); cti(); emit_long( op(arith_op) | fcn(1) | op3(retry_op3) ); }
|
||||
void done() { v9_only(); cti(); emit_int32( op(arith_op) | fcn(0) | op3(done_op3) ); }
|
||||
void retry() { v9_only(); cti(); emit_int32( op(arith_op) | fcn(1) | op3(retry_op3) ); }
|
||||
|
||||
// pp 156
|
||||
|
||||
void fadd( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x40 + w) | fs2(s2, w)); }
|
||||
void fsub( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x44 + w) | fs2(s2, w)); }
|
||||
void fadd( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x40 + w) | fs2(s2, w)); }
|
||||
void fsub( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x44 + w) | fs2(s2, w)); }
|
||||
|
||||
// pp 157
|
||||
|
||||
void fcmp( FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2) { v8_no_cc(cc); emit_long( op(arith_op) | cmpcc(cc) | op3(fpop2_op3) | fs1(s1, w) | opf(0x50 + w) | fs2(s2, w)); }
|
||||
void fcmpe( FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2) { v8_no_cc(cc); emit_long( op(arith_op) | cmpcc(cc) | op3(fpop2_op3) | fs1(s1, w) | opf(0x54 + w) | fs2(s2, w)); }
|
||||
void fcmp( FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2) { v8_no_cc(cc); emit_int32( op(arith_op) | cmpcc(cc) | op3(fpop2_op3) | fs1(s1, w) | opf(0x50 + w) | fs2(s2, w)); }
|
||||
void fcmpe( FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2) { v8_no_cc(cc); emit_int32( op(arith_op) | cmpcc(cc) | op3(fpop2_op3) | fs1(s1, w) | opf(0x54 + w) | fs2(s2, w)); }
|
||||
|
||||
// pp 159
|
||||
|
||||
void ftox( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(fpop1_op3) | opf(0x80 + w) | fs2(s, w)); }
|
||||
void ftoi( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(fpop1_op3) | opf(0xd0 + w) | fs2(s, w)); }
|
||||
void ftox( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(fpop1_op3) | opf(0x80 + w) | fs2(s, w)); }
|
||||
void ftoi( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(fpop1_op3) | opf(0xd0 + w) | fs2(s, w)); }
|
||||
|
||||
// pp 160
|
||||
|
||||
void ftof( FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, dw) | op3(fpop1_op3) | opf(0xc0 + sw + dw*4) | fs2(s, sw)); }
|
||||
void ftof( FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, dw) | op3(fpop1_op3) | opf(0xc0 + sw + dw*4) | fs2(s, sw)); }
|
||||
|
||||
// pp 161
|
||||
|
||||
void fxtof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w*4) | fs2(s, FloatRegisterImpl::D)); }
|
||||
void fitof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xc0 + w*4) | fs2(s, FloatRegisterImpl::S)); }
|
||||
void fxtof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w*4) | fs2(s, FloatRegisterImpl::D)); }
|
||||
void fitof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xc0 + w*4) | fs2(s, FloatRegisterImpl::S)); }
|
||||
|
||||
// pp 162
|
||||
|
||||
void fmov( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v8_s_only(w); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x00 + w) | fs2(s, w)); }
|
||||
void fmov( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v8_s_only(w); emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x00 + w) | fs2(s, w)); }
|
||||
|
||||
void fneg( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v8_s_only(w); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x04 + w) | fs2(s, w)); }
|
||||
void fneg( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v8_s_only(w); emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x04 + w) | fs2(s, w)); }
|
||||
|
||||
// page 144 sparc v8 architecture (double prec works on v8 if the source and destination registers are the same). fnegs is the only instruction available
|
||||
// on v8 to do negation of single, double and quad precision floats.
|
||||
|
||||
void fneg( FloatRegisterImpl::Width w, FloatRegister sd ) { if (VM_Version::v9_instructions_work()) emit_long( op(arith_op) | fd(sd, w) | op3(fpop1_op3) | opf(0x04 + w) | fs2(sd, w)); else emit_long( op(arith_op) | fd(sd, w) | op3(fpop1_op3) | opf(0x05) | fs2(sd, w)); }
|
||||
void fneg( FloatRegisterImpl::Width w, FloatRegister sd ) { if (VM_Version::v9_instructions_work()) emit_int32( op(arith_op) | fd(sd, w) | op3(fpop1_op3) | opf(0x04 + w) | fs2(sd, w)); else emit_int32( op(arith_op) | fd(sd, w) | op3(fpop1_op3) | opf(0x05) | fs2(sd, w)); }
|
||||
|
||||
void fabs( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v8_s_only(w); emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x08 + w) | fs2(s, w)); }
|
||||
void fabs( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v8_s_only(w); emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x08 + w) | fs2(s, w)); }
|
||||
|
||||
// page 144 sparc v8 architecture (double prec works on v8 if the source and destination registers are the same). fabss is the only instruction available
|
||||
// on v8 to do abs operation on single/double/quad precision floats.
|
||||
|
||||
void fabs( FloatRegisterImpl::Width w, FloatRegister sd ) { if (VM_Version::v9_instructions_work()) emit_long( op(arith_op) | fd(sd, w) | op3(fpop1_op3) | opf(0x08 + w) | fs2(sd, w)); else emit_long( op(arith_op) | fd(sd, w) | op3(fpop1_op3) | opf(0x09) | fs2(sd, w)); }
|
||||
void fabs( FloatRegisterImpl::Width w, FloatRegister sd ) { if (VM_Version::v9_instructions_work()) emit_int32( op(arith_op) | fd(sd, w) | op3(fpop1_op3) | opf(0x08 + w) | fs2(sd, w)); else emit_int32( op(arith_op) | fd(sd, w) | op3(fpop1_op3) | opf(0x09) | fs2(sd, w)); }
|
||||
|
||||
// pp 163
|
||||
|
||||
void fmul( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x48 + w) | fs2(s2, w)); }
|
||||
void fmul( FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_long( op(arith_op) | fd(d, dw) | op3(fpop1_op3) | fs1(s1, sw) | opf(0x60 + sw + dw*4) | fs2(s2, sw)); }
|
||||
void fdiv( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x4c + w) | fs2(s2, w)); }
|
||||
void fmul( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x48 + w) | fs2(s2, w)); }
|
||||
void fmul( FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, dw) | op3(fpop1_op3) | fs1(s1, sw) | opf(0x60 + sw + dw*4) | fs2(s2, sw)); }
|
||||
void fdiv( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x4c + w) | fs2(s2, w)); }
|
||||
|
||||
// pp 164
|
||||
|
||||
void fsqrt( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_long( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x28 + w) | fs2(s, w)); }
|
||||
void fsqrt( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x28 + w) | fs2(s, w)); }
|
||||
|
||||
// pp 165
|
||||
|
||||
@ -827,22 +827,22 @@ public:
|
||||
|
||||
// pp 167
|
||||
|
||||
void flushw() { v9_only(); emit_long( op(arith_op) | op3(flushw_op3) ); }
|
||||
void flushw() { v9_only(); emit_int32( op(arith_op) | op3(flushw_op3) ); }
|
||||
|
||||
// pp 168
|
||||
|
||||
void illtrap( int const22a) { if (const22a != 0) v9_only(); emit_long( op(branch_op) | u_field(const22a, 21, 0) ); }
|
||||
void illtrap( int const22a) { if (const22a != 0) v9_only(); emit_int32( op(branch_op) | u_field(const22a, 21, 0) ); }
|
||||
// v8 unimp == illtrap(0)
|
||||
|
||||
// pp 169
|
||||
|
||||
void impdep1( int id1, int const19a ) { v9_only(); emit_long( op(arith_op) | fcn(id1) | op3(impdep1_op3) | u_field(const19a, 18, 0)); }
|
||||
void impdep2( int id1, int const19a ) { v9_only(); emit_long( op(arith_op) | fcn(id1) | op3(impdep2_op3) | u_field(const19a, 18, 0)); }
|
||||
void impdep1( int id1, int const19a ) { v9_only(); emit_int32( op(arith_op) | fcn(id1) | op3(impdep1_op3) | u_field(const19a, 18, 0)); }
|
||||
void impdep2( int id1, int const19a ) { v9_only(); emit_int32( op(arith_op) | fcn(id1) | op3(impdep2_op3) | u_field(const19a, 18, 0)); }
|
||||
|
||||
// pp 149 (v8)
|
||||
|
||||
void cpop1( int opc, int cr1, int cr2, int crd ) { v8_only(); emit_long( op(arith_op) | fcn(crd) | op3(impdep1_op3) | u_field(cr1, 18, 14) | opf(opc) | u_field(cr2, 4, 0)); }
|
||||
void cpop2( int opc, int cr1, int cr2, int crd ) { v8_only(); emit_long( op(arith_op) | fcn(crd) | op3(impdep2_op3) | u_field(cr1, 18, 14) | opf(opc) | u_field(cr2, 4, 0)); }
|
||||
void cpop1( int opc, int cr1, int cr2, int crd ) { v8_only(); emit_int32( op(arith_op) | fcn(crd) | op3(impdep1_op3) | u_field(cr1, 18, 14) | opf(opc) | u_field(cr2, 4, 0)); }
|
||||
void cpop2( int opc, int cr1, int cr2, int crd ) { v8_only(); emit_int32( op(arith_op) | fcn(crd) | op3(impdep2_op3) | u_field(cr1, 18, 14) | opf(opc) | u_field(cr2, 4, 0)); }
|
||||
|
||||
// pp 170
|
||||
|
||||
@ -872,8 +872,8 @@ public:
|
||||
|
||||
// 173
|
||||
|
||||
void ldfa( FloatRegisterImpl::Width w, Register s1, Register s2, int ia, FloatRegister d ) { v9_only(); emit_long( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3 | alt_bit_op3, w) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldfa( FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d ) { v9_only(); emit_long( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3 | alt_bit_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void ldfa( FloatRegisterImpl::Width w, Register s1, Register s2, int ia, FloatRegister d ) { v9_only(); emit_int32( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3 | alt_bit_op3, w) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldfa( FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d ) { v9_only(); emit_int32( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3 | alt_bit_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 175, lduw is ld on v8
|
||||
|
||||
@ -896,22 +896,22 @@ public:
|
||||
|
||||
// pp 177
|
||||
|
||||
void ldsba( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldsba( Register s1, int simm13a, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void ldsha( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldsh_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldsha( Register s1, int simm13a, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldsh_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void ldswa( Register s1, Register s2, int ia, Register d ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(ldsw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldswa( Register s1, int simm13a, Register d ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(ldsw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void lduba( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldub_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void lduba( Register s1, int simm13a, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldub_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void lduha( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(lduh_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void lduha( Register s1, int simm13a, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(lduh_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void lduwa( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(lduw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void lduwa( Register s1, int simm13a, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(lduw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void ldxa( Register s1, Register s2, int ia, Register d ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(ldx_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldxa( Register s1, int simm13a, Register d ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(ldx_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void ldda( Register s1, Register s2, int ia, Register d ) { v9_dep(); emit_long( op(ldst_op) | rd(d) | op3(ldd_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldda( Register s1, int simm13a, Register d ) { v9_dep(); emit_long( op(ldst_op) | rd(d) | op3(ldd_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void ldsba( Register s1, Register s2, int ia, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldsba( Register s1, int simm13a, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void ldsha( Register s1, Register s2, int ia, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldsh_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldsha( Register s1, int simm13a, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldsh_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void ldswa( Register s1, Register s2, int ia, Register d ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(ldsw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldswa( Register s1, int simm13a, Register d ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(ldsw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void lduba( Register s1, Register s2, int ia, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldub_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void lduba( Register s1, int simm13a, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldub_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void lduha( Register s1, Register s2, int ia, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(lduh_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void lduha( Register s1, int simm13a, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(lduh_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void lduwa( Register s1, Register s2, int ia, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(lduw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void lduwa( Register s1, int simm13a, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(lduw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void ldxa( Register s1, Register s2, int ia, Register d ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(ldx_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldxa( Register s1, int simm13a, Register d ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(ldx_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void ldda( Register s1, Register s2, int ia, Register d ) { v9_dep(); emit_int32( op(ldst_op) | rd(d) | op3(ldd_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldda( Register s1, int simm13a, Register d ) { v9_dep(); emit_int32( op(ldst_op) | rd(d) | op3(ldd_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 179
|
||||
|
||||
@ -920,111 +920,111 @@ public:
|
||||
|
||||
// pp 180
|
||||
|
||||
void ldstuba( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldstub_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldstuba( Register s1, int simm13a, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldstub_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void ldstuba( Register s1, Register s2, int ia, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldstub_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void ldstuba( Register s1, int simm13a, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldstub_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 181
|
||||
|
||||
void and3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void and3( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void andcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void andcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void andn( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void andn( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void andncc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void andncc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void or3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void or3( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void orcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void orcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(or_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void orn( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(orn_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void orn( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(orn_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void orncc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(orn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void orncc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(orn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void xor3( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void xor3( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void xorcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void xorcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xor_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void xnor( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xnor_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void xnor( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xnor_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void xnorcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xnor_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void xnorcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(xnor_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void and3( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(and_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void and3( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(and_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void andcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void andcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void andn( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(andn_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void andn( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(andn_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void andncc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void andncc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void or3( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void or3( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void orcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(or_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void orcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(or_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void orn( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(orn_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void orn( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(orn_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void orncc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(orn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void orncc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(orn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void xor3( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xor_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void xor3( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xor_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void xorcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xor_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void xorcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xor_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void xnor( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xnor_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void xnor( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xnor_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void xnorcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xnor_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void xnorcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xnor_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 183
|
||||
|
||||
void membar( Membar_mask_bits const7a ) { v9_only(); emit_long( op(arith_op) | op3(membar_op3) | rs1(O7) | immed(true) | u_field( int(const7a), 6, 0)); }
|
||||
void membar( Membar_mask_bits const7a ) { v9_only(); emit_int32( op(arith_op) | op3(membar_op3) | rs1(O7) | immed(true) | u_field( int(const7a), 6, 0)); }
|
||||
|
||||
// pp 185
|
||||
|
||||
void fmov( FloatRegisterImpl::Width w, Condition c, bool floatCC, CC cca, FloatRegister s2, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop2_op3) | cond_mov(c) | opf_cc(cca, floatCC) | opf_low6(w) | fs2(s2, w)); }
|
||||
void fmov( FloatRegisterImpl::Width w, Condition c, bool floatCC, CC cca, FloatRegister s2, FloatRegister d ) { v9_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fpop2_op3) | cond_mov(c) | opf_cc(cca, floatCC) | opf_low6(w) | fs2(s2, w)); }
|
||||
|
||||
// pp 189
|
||||
|
||||
void fmov( FloatRegisterImpl::Width w, RCondition c, Register s1, FloatRegister s2, FloatRegister d ) { v9_only(); emit_long( op(arith_op) | fd(d, w) | op3(fpop2_op3) | rs1(s1) | rcond(c) | opf_low5(4 + w) | fs2(s2, w)); }
|
||||
void fmov( FloatRegisterImpl::Width w, RCondition c, Register s1, FloatRegister s2, FloatRegister d ) { v9_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fpop2_op3) | rs1(s1) | rcond(c) | opf_low5(4 + w) | fs2(s2, w)); }
|
||||
|
||||
// pp 191
|
||||
|
||||
void movcc( Condition c, bool floatCC, CC cca, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(movcc_op3) | mov_cc(cca, floatCC) | cond_mov(c) | rs2(s2) ); }
|
||||
void movcc( Condition c, bool floatCC, CC cca, int simm11a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(movcc_op3) | mov_cc(cca, floatCC) | cond_mov(c) | immed(true) | simm(simm11a, 11) ); }
|
||||
void movcc( Condition c, bool floatCC, CC cca, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(movcc_op3) | mov_cc(cca, floatCC) | cond_mov(c) | rs2(s2) ); }
|
||||
void movcc( Condition c, bool floatCC, CC cca, int simm11a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(movcc_op3) | mov_cc(cca, floatCC) | cond_mov(c) | immed(true) | simm(simm11a, 11) ); }
|
||||
|
||||
// pp 195
|
||||
|
||||
void movr( RCondition c, Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(movr_op3) | rs1(s1) | rcond(c) | rs2(s2) ); }
|
||||
void movr( RCondition c, Register s1, int simm10a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(movr_op3) | rs1(s1) | rcond(c) | immed(true) | simm(simm10a, 10) ); }
|
||||
void movr( RCondition c, Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(movr_op3) | rs1(s1) | rcond(c) | rs2(s2) ); }
|
||||
void movr( RCondition c, Register s1, int simm10a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(movr_op3) | rs1(s1) | rcond(c) | immed(true) | simm(simm10a, 10) ); }
|
||||
|
||||
// pp 196
|
||||
|
||||
void mulx( Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(mulx_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void mulx( Register s1, int simm13a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(mulx_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void sdivx( Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(sdivx_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void sdivx( Register s1, int simm13a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(sdivx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void udivx( Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(udivx_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void udivx( Register s1, int simm13a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(udivx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void mulx( Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(mulx_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void mulx( Register s1, int simm13a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(mulx_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void sdivx( Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(sdivx_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void sdivx( Register s1, int simm13a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(sdivx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void udivx( Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(udivx_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void udivx( Register s1, int simm13a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(udivx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 197
|
||||
|
||||
void umul( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(umul_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void umul( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(umul_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void smul( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(smul_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void smul( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(smul_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void umulcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(umul_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void umulcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(umul_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void smulcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(smul_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void smulcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(smul_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void umul( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(umul_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void umul( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(umul_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void smul( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(smul_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void smul( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(smul_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void umulcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(umul_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void umulcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(umul_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void smulcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(smul_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void smulcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(smul_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 199
|
||||
|
||||
void mulscc( Register s1, Register s2, Register d ) { v9_dep(); emit_long( op(arith_op) | rd(d) | op3(mulscc_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void mulscc( Register s1, int simm13a, Register d ) { v9_dep(); emit_long( op(arith_op) | rd(d) | op3(mulscc_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void mulscc( Register s1, Register s2, Register d ) { v9_dep(); emit_int32( op(arith_op) | rd(d) | op3(mulscc_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void mulscc( Register s1, int simm13a, Register d ) { v9_dep(); emit_int32( op(arith_op) | rd(d) | op3(mulscc_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 201
|
||||
|
||||
void nop() { emit_long( op(branch_op) | op2(sethi_op2) ); }
|
||||
void nop() { emit_int32( op(branch_op) | op2(sethi_op2) ); }
|
||||
|
||||
|
||||
// pp 202
|
||||
|
||||
void popc( Register s, Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(popc_op3) | rs2(s)); }
|
||||
void popc( int simm13a, Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(popc_op3) | immed(true) | simm(simm13a, 13)); }
|
||||
void popc( Register s, Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(popc_op3) | rs2(s)); }
|
||||
void popc( int simm13a, Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(popc_op3) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
// pp 203
|
||||
|
||||
void prefetch( Register s1, Register s2, PrefetchFcn f) { v9_only(); emit_long( op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void prefetch( Register s1, Register s2, PrefetchFcn f) { v9_only(); emit_int32( op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void prefetch( Register s1, int simm13a, PrefetchFcn f) { v9_only(); emit_data( op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
void prefetcha( Register s1, Register s2, int ia, PrefetchFcn f ) { v9_only(); emit_long( op(ldst_op) | fcn(f) | op3(prefetch_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void prefetcha( Register s1, int simm13a, PrefetchFcn f ) { v9_only(); emit_long( op(ldst_op) | fcn(f) | op3(prefetch_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void prefetcha( Register s1, Register s2, int ia, PrefetchFcn f ) { v9_only(); emit_int32( op(ldst_op) | fcn(f) | op3(prefetch_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void prefetcha( Register s1, int simm13a, PrefetchFcn f ) { v9_only(); emit_int32( op(ldst_op) | fcn(f) | op3(prefetch_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 208
|
||||
|
||||
// not implementing read privileged register
|
||||
|
||||
inline void rdy( Register d) { v9_dep(); emit_long( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(0, 18, 14)); }
|
||||
inline void rdccr( Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(2, 18, 14)); }
|
||||
inline void rdasi( Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(3, 18, 14)); }
|
||||
inline void rdtick( Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(4, 18, 14)); } // Spoon!
|
||||
inline void rdpc( Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(5, 18, 14)); }
|
||||
inline void rdfprs( Register d) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(6, 18, 14)); }
|
||||
inline void rdy( Register d) { v9_dep(); emit_int32( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(0, 18, 14)); }
|
||||
inline void rdccr( Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(2, 18, 14)); }
|
||||
inline void rdasi( Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(3, 18, 14)); }
|
||||
inline void rdtick( Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(4, 18, 14)); } // Spoon!
|
||||
inline void rdpc( Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(5, 18, 14)); }
|
||||
inline void rdfprs( Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(6, 18, 14)); }
|
||||
|
||||
// pp 213
|
||||
|
||||
@ -1033,47 +1033,47 @@ public:
|
||||
|
||||
// pp 214
|
||||
|
||||
void save( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(save_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void save( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(save_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void save( Register s1, int simm13a, Register d ) {
|
||||
// make sure frame is at least large enough for the register save area
|
||||
assert(-simm13a >= 16 * wordSize, "frame too small");
|
||||
emit_long( op(arith_op) | rd(d) | op3(save_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) );
|
||||
emit_int32( op(arith_op) | rd(d) | op3(save_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) );
|
||||
}
|
||||
|
||||
void restore( Register s1 = G0, Register s2 = G0, Register d = G0 ) { emit_long( op(arith_op) | rd(d) | op3(restore_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void restore( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(restore_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void restore( Register s1 = G0, Register s2 = G0, Register d = G0 ) { emit_int32( op(arith_op) | rd(d) | op3(restore_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void restore( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(restore_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 216
|
||||
|
||||
void saved() { v9_only(); emit_long( op(arith_op) | fcn(0) | op3(saved_op3)); }
|
||||
void restored() { v9_only(); emit_long( op(arith_op) | fcn(1) | op3(saved_op3)); }
|
||||
void saved() { v9_only(); emit_int32( op(arith_op) | fcn(0) | op3(saved_op3)); }
|
||||
void restored() { v9_only(); emit_int32( op(arith_op) | fcn(1) | op3(saved_op3)); }
|
||||
|
||||
// pp 217
|
||||
|
||||
inline void sethi( int imm22a, Register d, RelocationHolder const& rspec = RelocationHolder() );
|
||||
// pp 218
|
||||
|
||||
void sll( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(0) | rs2(s2) ); }
|
||||
void sll( Register s1, int imm5a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0) ); }
|
||||
void srl( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(0) | rs2(s2) ); }
|
||||
void srl( Register s1, int imm5a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0) ); }
|
||||
void sra( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(0) | rs2(s2) ); }
|
||||
void sra( Register s1, int imm5a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0) ); }
|
||||
void sll( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(0) | rs2(s2) ); }
|
||||
void sll( Register s1, int imm5a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0) ); }
|
||||
void srl( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(0) | rs2(s2) ); }
|
||||
void srl( Register s1, int imm5a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0) ); }
|
||||
void sra( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(0) | rs2(s2) ); }
|
||||
void sra( Register s1, int imm5a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0) ); }
|
||||
|
||||
void sllx( Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(1) | rs2(s2) ); }
|
||||
void sllx( Register s1, int imm6a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0) ); }
|
||||
void srlx( Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(1) | rs2(s2) ); }
|
||||
void srlx( Register s1, int imm6a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0) ); }
|
||||
void srax( Register s1, Register s2, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(1) | rs2(s2) ); }
|
||||
void srax( Register s1, int imm6a, Register d ) { v9_only(); emit_long( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0) ); }
|
||||
void sllx( Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(1) | rs2(s2) ); }
|
||||
void sllx( Register s1, int imm6a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0) ); }
|
||||
void srlx( Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(1) | rs2(s2) ); }
|
||||
void srlx( Register s1, int imm6a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0) ); }
|
||||
void srax( Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(1) | rs2(s2) ); }
|
||||
void srax( Register s1, int imm6a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0) ); }
|
||||
|
||||
// pp 220
|
||||
|
||||
void sir( int simm13a ) { emit_long( op(arith_op) | fcn(15) | op3(sir_op3) | immed(true) | simm(simm13a, 13)); }
|
||||
void sir( int simm13a ) { emit_int32( op(arith_op) | fcn(15) | op3(sir_op3) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
// pp 221
|
||||
|
||||
void stbar() { emit_long( op(arith_op) | op3(membar_op3) | u_field(15, 18, 14)); }
|
||||
void stbar() { emit_int32( op(arith_op) | op3(membar_op3) | u_field(15, 18, 14)); }
|
||||
|
||||
// pp 222
|
||||
|
||||
@ -1087,8 +1087,8 @@ public:
|
||||
|
||||
// pp 224
|
||||
|
||||
void stfa( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2, int ia ) { v9_only(); emit_long( op(ldst_op) | fd(d, w) | alt_op3(stf_op3 | alt_bit_op3, w) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void stfa( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a ) { v9_only(); emit_long( op(ldst_op) | fd(d, w) | alt_op3(stf_op3 | alt_bit_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void stfa( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2, int ia ) { v9_only(); emit_int32( op(ldst_op) | fd(d, w) | alt_op3(stf_op3 | alt_bit_op3, w) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void stfa( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a ) { v9_only(); emit_int32( op(ldst_op) | fd(d, w) | alt_op3(stf_op3 | alt_bit_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// p 226
|
||||
|
||||
@ -1105,16 +1105,16 @@ public:
|
||||
|
||||
// pp 177
|
||||
|
||||
void stba( Register d, Register s1, Register s2, int ia ) { emit_long( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void stba( Register d, Register s1, int simm13a ) { emit_long( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void stha( Register d, Register s1, Register s2, int ia ) { emit_long( op(ldst_op) | rd(d) | op3(sth_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void stha( Register d, Register s1, int simm13a ) { emit_long( op(ldst_op) | rd(d) | op3(sth_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void stwa( Register d, Register s1, Register s2, int ia ) { emit_long( op(ldst_op) | rd(d) | op3(stw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void stwa( Register d, Register s1, int simm13a ) { emit_long( op(ldst_op) | rd(d) | op3(stw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void stxa( Register d, Register s1, Register s2, int ia ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(stx_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void stxa( Register d, Register s1, int simm13a ) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(stx_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void stda( Register d, Register s1, Register s2, int ia ) { emit_long( op(ldst_op) | rd(d) | op3(std_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void stda( Register d, Register s1, int simm13a ) { emit_long( op(ldst_op) | rd(d) | op3(std_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void stba( Register d, Register s1, Register s2, int ia ) { emit_int32( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void stba( Register d, Register s1, int simm13a ) { emit_int32( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void stha( Register d, Register s1, Register s2, int ia ) { emit_int32( op(ldst_op) | rd(d) | op3(sth_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void stha( Register d, Register s1, int simm13a ) { emit_int32( op(ldst_op) | rd(d) | op3(sth_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void stwa( Register d, Register s1, Register s2, int ia ) { emit_int32( op(ldst_op) | rd(d) | op3(stw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void stwa( Register d, Register s1, int simm13a ) { emit_int32( op(ldst_op) | rd(d) | op3(stw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void stxa( Register d, Register s1, Register s2, int ia ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(stx_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void stxa( Register d, Register s1, int simm13a ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(stx_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void stda( Register d, Register s1, Register s2, int ia ) { emit_int32( op(ldst_op) | rd(d) | op3(std_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void stda( Register d, Register s1, int simm13a ) { emit_int32( op(ldst_op) | rd(d) | op3(std_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 97 (v8)
|
||||
|
||||
@ -1129,15 +1129,15 @@ public:
|
||||
|
||||
// pp 230
|
||||
|
||||
void sub( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void sub( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void sub( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void sub( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
void subcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void subcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void subc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void subc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void subccc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void subccc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void subcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void subcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void subc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(subc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void subc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(subc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void subccc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(subc_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void subccc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(subc_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 231
|
||||
|
||||
@ -1146,55 +1146,55 @@ public:
|
||||
|
||||
// pp 232
|
||||
|
||||
void swapa( Register s1, Register s2, int ia, Register d ) { v9_dep(); emit_long( op(ldst_op) | rd(d) | op3(swap_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void swapa( Register s1, int simm13a, Register d ) { v9_dep(); emit_long( op(ldst_op) | rd(d) | op3(swap_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void swapa( Register s1, Register s2, int ia, Register d ) { v9_dep(); emit_int32( op(ldst_op) | rd(d) | op3(swap_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
|
||||
void swapa( Register s1, int simm13a, Register d ) { v9_dep(); emit_int32( op(ldst_op) | rd(d) | op3(swap_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 234, note op in book is wrong, see pp 268
|
||||
|
||||
void taddcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(taddcc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void taddcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(taddcc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void taddcctv( Register s1, Register s2, Register d ) { v9_dep(); emit_long( op(arith_op) | rd(d) | op3(taddcctv_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void taddcctv( Register s1, int simm13a, Register d ) { v9_dep(); emit_long( op(arith_op) | rd(d) | op3(taddcctv_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void taddcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(taddcc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void taddcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(taddcc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void taddcctv( Register s1, Register s2, Register d ) { v9_dep(); emit_int32( op(arith_op) | rd(d) | op3(taddcctv_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void taddcctv( Register s1, int simm13a, Register d ) { v9_dep(); emit_int32( op(arith_op) | rd(d) | op3(taddcctv_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 235
|
||||
|
||||
void tsubcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(tsubcc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void tsubcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(tsubcc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void tsubcctv( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(tsubcctv_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void tsubcctv( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(tsubcctv_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void tsubcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(tsubcc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
void tsubcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(tsubcc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
void tsubcctv( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(tsubcctv_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void tsubcctv( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(tsubcctv_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
// pp 237
|
||||
|
||||
void trap( Condition c, CC cc, Register s1, Register s2 ) { v8_no_cc(cc); emit_long( op(arith_op) | cond(c) | op3(trap_op3) | rs1(s1) | trapcc(cc) | rs2(s2)); }
|
||||
void trap( Condition c, CC cc, Register s1, int trapa ) { v8_no_cc(cc); emit_long( op(arith_op) | cond(c) | op3(trap_op3) | rs1(s1) | trapcc(cc) | immed(true) | u_field(trapa, 6, 0)); }
|
||||
void trap( Condition c, CC cc, Register s1, Register s2 ) { v8_no_cc(cc); emit_int32( op(arith_op) | cond(c) | op3(trap_op3) | rs1(s1) | trapcc(cc) | rs2(s2)); }
|
||||
void trap( Condition c, CC cc, Register s1, int trapa ) { v8_no_cc(cc); emit_int32( op(arith_op) | cond(c) | op3(trap_op3) | rs1(s1) | trapcc(cc) | immed(true) | u_field(trapa, 6, 0)); }
|
||||
// simple uncond. trap
|
||||
void trap( int trapa ) { trap( always, icc, G0, trapa ); }
|
||||
|
||||
// pp 239 omit write priv register for now
|
||||
|
||||
inline void wry( Register d) { v9_dep(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(0, 29, 25)); }
|
||||
inline void wrccr(Register s) { v9_only(); emit_long( op(arith_op) | rs1(s) | op3(wrreg_op3) | u_field(2, 29, 25)); }
|
||||
inline void wrccr(Register s, int simm13a) { v9_only(); emit_long( op(arith_op) |
|
||||
inline void wry( Register d) { v9_dep(); emit_int32( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(0, 29, 25)); }
|
||||
inline void wrccr(Register s) { v9_only(); emit_int32( op(arith_op) | rs1(s) | op3(wrreg_op3) | u_field(2, 29, 25)); }
|
||||
inline void wrccr(Register s, int simm13a) { v9_only(); emit_int32( op(arith_op) |
|
||||
rs1(s) |
|
||||
op3(wrreg_op3) |
|
||||
u_field(2, 29, 25) |
|
||||
immed(true) |
|
||||
simm(simm13a, 13)); }
|
||||
inline void wrasi(Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25)); }
|
||||
inline void wrasi(Register d) { v9_only(); emit_int32( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25)); }
|
||||
// wrasi(d, imm) stores (d xor imm) to asi
|
||||
inline void wrasi(Register d, int simm13a) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) |
|
||||
inline void wrasi(Register d, int simm13a) { v9_only(); emit_int32( op(arith_op) | rs1(d) | op3(wrreg_op3) |
|
||||
u_field(3, 29, 25) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void wrfprs( Register d) { v9_only(); emit_long( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); }
|
||||
inline void wrfprs( Register d) { v9_only(); emit_int32( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); }
|
||||
|
||||
|
||||
// VIS3 instructions
|
||||
|
||||
void movstosw( FloatRegister s, Register d ) { vis3_only(); emit_long( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstosw_opf) | fs2(s, FloatRegisterImpl::S)); }
|
||||
void movstouw( FloatRegister s, Register d ) { vis3_only(); emit_long( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstouw_opf) | fs2(s, FloatRegisterImpl::S)); }
|
||||
void movdtox( FloatRegister s, Register d ) { vis3_only(); emit_long( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mdtox_opf) | fs2(s, FloatRegisterImpl::D)); }
|
||||
void movstosw( FloatRegister s, Register d ) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstosw_opf) | fs2(s, FloatRegisterImpl::S)); }
|
||||
void movstouw( FloatRegister s, Register d ) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstouw_opf) | fs2(s, FloatRegisterImpl::S)); }
|
||||
void movdtox( FloatRegister s, Register d ) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mdtox_opf) | fs2(s, FloatRegisterImpl::D)); }
|
||||
|
||||
void movwtos( Register s, FloatRegister d ) { vis3_only(); emit_long( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); }
|
||||
void movxtod( Register s, FloatRegister d ) { vis3_only(); emit_long( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); }
|
||||
void movwtos( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); }
|
||||
void movxtod( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); }
|
||||
|
||||
// Creation
|
||||
Assembler(CodeBuffer* code) : AbstractAssembler(code) {
|
||||
|
@ -35,24 +35,24 @@ inline void Assembler::check_delay() {
|
||||
# endif
|
||||
}
|
||||
|
||||
inline void Assembler::emit_long(int x) {
|
||||
inline void Assembler::emit_int32(int x) {
|
||||
check_delay();
|
||||
AbstractAssembler::emit_long(x);
|
||||
AbstractAssembler::emit_int32(x);
|
||||
}
|
||||
|
||||
inline void Assembler::emit_data(int x, relocInfo::relocType rtype) {
|
||||
relocate(rtype);
|
||||
emit_long(x);
|
||||
emit_int32(x);
|
||||
}
|
||||
|
||||
inline void Assembler::emit_data(int x, RelocationHolder const& rspec) {
|
||||
relocate(rspec);
|
||||
emit_long(x);
|
||||
emit_int32(x);
|
||||
}
|
||||
|
||||
|
||||
inline void Assembler::add(Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::add(Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
inline void Assembler::add(Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::add(Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
|
||||
inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt ) { v9_only(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bpr_op2) | wdisp16(intptr_t(d), intptr_t(pc())) | predict(p) | rs1(s1), rt); has_delay_slot(); }
|
||||
inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, Label& L) { bpr( c, a, p, s1, target(L)); }
|
||||
@ -79,93 +79,93 @@ inline void Assembler::cbcond(Condition c, CC cc, Register s1, int simm5, Label&
|
||||
inline void Assembler::call( address d, relocInfo::relocType rt ) { cti(); emit_data( op(call_op) | wdisp(intptr_t(d), intptr_t(pc()), 30), rt); has_delay_slot(); assert(rt != relocInfo::virtual_call_type, "must use virtual_call_Relocation::spec"); }
|
||||
inline void Assembler::call( Label& L, relocInfo::relocType rt ) { call( target(L), rt); }
|
||||
|
||||
inline void Assembler::flush( Register s1, Register s2) { emit_long( op(arith_op) | op3(flush_op3) | rs1(s1) | rs2(s2)); }
|
||||
inline void Assembler::flush( Register s1, Register s2) { emit_int32( op(arith_op) | op3(flush_op3) | rs1(s1) | rs2(s2)); }
|
||||
inline void Assembler::flush( Register s1, int simm13a) { emit_data( op(arith_op) | op3(flush_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
inline void Assembler::jmpl( Register s1, Register s2, Register d ) { cti(); emit_long( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); }
|
||||
inline void Assembler::jmpl( Register s1, Register s2, Register d ) { cti(); emit_int32( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); }
|
||||
inline void Assembler::jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { cti(); emit_data( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); has_delay_slot(); }
|
||||
|
||||
inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { emit_long( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { emit_int32( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d, RelocationHolder const& rspec) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); }
|
||||
|
||||
inline void Assembler::ldfsr( Register s1, Register s2) { v9_dep(); emit_long( op(ldst_op) | op3(ldfsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldfsr( Register s1, Register s2) { v9_dep(); emit_int32( op(ldst_op) | op3(ldfsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldfsr( Register s1, int simm13a) { v9_dep(); emit_data( op(ldst_op) | op3(ldfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::ldxfsr( Register s1, Register s2) { v9_only(); emit_long( op(ldst_op) | rd(G1) | op3(ldfsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldxfsr( Register s1, Register s2) { v9_only(); emit_int32( op(ldst_op) | rd(G1) | op3(ldfsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldxfsr( Register s1, int simm13a) { v9_only(); emit_data( op(ldst_op) | rd(G1) | op3(ldfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
inline void Assembler::ldc( Register s1, Register s2, int crd) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(ldc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldc( Register s1, Register s2, int crd) { v8_only(); emit_int32( op(ldst_op) | fcn(crd) | op3(ldc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldc( Register s1, int simm13a, int crd) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(ldc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::lddc( Register s1, Register s2, int crd) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(lddc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::lddc( Register s1, Register s2, int crd) { v8_only(); emit_int32( op(ldst_op) | fcn(crd) | op3(lddc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::lddc( Register s1, int simm13a, int crd) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(lddc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::ldcsr( Register s1, Register s2, int crd) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(ldcsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldcsr( Register s1, Register s2, int crd) { v8_only(); emit_int32( op(ldst_op) | fcn(crd) | op3(ldcsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldcsr( Register s1, int simm13a, int crd) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(ldcsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
inline void Assembler::ldsb( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldsb_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldsb( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(ldsb_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldsb( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldsb_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
inline void Assembler::ldsh( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldsh_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldsh( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(ldsh_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldsh( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldsh_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::ldsw( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldsw_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldsw( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(ldsw_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldsw( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldsw_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::ldub( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldub_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldub( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(ldub_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldub( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldub_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::lduh( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(lduh_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::lduh( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(lduh_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::lduh( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(lduh_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::lduw( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(lduw_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::lduw( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(lduw_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::lduw( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(lduw_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
inline void Assembler::ldx( Register s1, Register s2, Register d) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(ldx_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldx( Register s1, Register s2, Register d) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(ldx_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldx( Register s1, int simm13a, Register d) { v9_only(); emit_data( op(ldst_op) | rd(d) | op3(ldx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::ldd( Register s1, Register s2, Register d) { v9_dep(); assert(d->is_even(), "not even"); emit_long( op(ldst_op) | rd(d) | op3(ldd_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldd( Register s1, Register s2, Register d) { v9_dep(); assert(d->is_even(), "not even"); emit_int32( op(ldst_op) | rd(d) | op3(ldd_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldd( Register s1, int simm13a, Register d) { v9_dep(); assert(d->is_even(), "not even"); emit_data( op(ldst_op) | rd(d) | op3(ldd_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
inline void Assembler::ldstub( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldstub_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldstub( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(ldstub_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldstub( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldstub_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
inline void Assembler::rett( Register s1, Register s2 ) { cti(); emit_long( op(arith_op) | op3(rett_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); }
|
||||
inline void Assembler::rett( Register s1, Register s2 ) { cti(); emit_int32( op(arith_op) | op3(rett_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); }
|
||||
inline void Assembler::rett( Register s1, int simm13a, relocInfo::relocType rt) { cti(); emit_data( op(arith_op) | op3(rett_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rt); has_delay_slot(); }
|
||||
|
||||
inline void Assembler::sethi( int imm22a, Register d, RelocationHolder const& rspec ) { emit_data( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(imm22a), rspec); }
|
||||
|
||||
// pp 222
|
||||
|
||||
inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2) { emit_long( op(ldst_op) | fd(d, w) | alt_op3(stf_op3, w) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2) { emit_int32( op(ldst_op) | fd(d, w) | alt_op3(stf_op3, w) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(stf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
inline void Assembler::stfsr( Register s1, Register s2) { v9_dep(); emit_long( op(ldst_op) | op3(stfsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stfsr( Register s1, Register s2) { v9_dep(); emit_int32( op(ldst_op) | op3(stfsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stfsr( Register s1, int simm13a) { v9_dep(); emit_data( op(ldst_op) | op3(stfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::stxfsr( Register s1, Register s2) { v9_only(); emit_long( op(ldst_op) | rd(G1) | op3(stfsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stxfsr( Register s1, Register s2) { v9_only(); emit_int32( op(ldst_op) | rd(G1) | op3(stfsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stxfsr( Register s1, int simm13a) { v9_only(); emit_data( op(ldst_op) | rd(G1) | op3(stfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
// p 226
|
||||
|
||||
inline void Assembler::stb( Register d, Register s1, Register s2) { emit_long( op(ldst_op) | rd(d) | op3(stb_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stb( Register d, Register s1, Register s2) { emit_int32( op(ldst_op) | rd(d) | op3(stb_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stb( Register d, Register s1, int simm13a) { emit_data( op(ldst_op) | rd(d) | op3(stb_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::sth( Register d, Register s1, Register s2) { emit_long( op(ldst_op) | rd(d) | op3(sth_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::sth( Register d, Register s1, Register s2) { emit_int32( op(ldst_op) | rd(d) | op3(sth_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::sth( Register d, Register s1, int simm13a) { emit_data( op(ldst_op) | rd(d) | op3(sth_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::stw( Register d, Register s1, Register s2) { emit_long( op(ldst_op) | rd(d) | op3(stw_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stw( Register d, Register s1, Register s2) { emit_int32( op(ldst_op) | rd(d) | op3(stw_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stw( Register d, Register s1, int simm13a) { emit_data( op(ldst_op) | rd(d) | op3(stw_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
|
||||
inline void Assembler::stx( Register d, Register s1, Register s2) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(stx_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stx( Register d, Register s1, Register s2) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(stx_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stx( Register d, Register s1, int simm13a) { v9_only(); emit_data( op(ldst_op) | rd(d) | op3(stx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::std( Register d, Register s1, Register s2) { v9_dep(); assert(d->is_even(), "not even"); emit_long( op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::std( Register d, Register s1, Register s2) { v9_dep(); assert(d->is_even(), "not even"); emit_int32( op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::std( Register d, Register s1, int simm13a) { v9_dep(); assert(d->is_even(), "not even"); emit_data( op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
// v8 p 99
|
||||
|
||||
inline void Assembler::stc( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stc( int crd, Register s1, Register s2) { v8_only(); emit_int32( op(ldst_op) | fcn(crd) | op3(stc_op3 ) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stc( int crd, Register s1, int simm13a) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(stc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::stdc( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stdc_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stdc( int crd, Register s1, Register s2) { v8_only(); emit_int32( op(ldst_op) | fcn(crd) | op3(stdc_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stdc( int crd, Register s1, int simm13a) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(stdc_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::stcsr( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stcsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stcsr( int crd, Register s1, Register s2) { v8_only(); emit_int32( op(ldst_op) | fcn(crd) | op3(stcsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stcsr( int crd, Register s1, int simm13a) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(stcsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void Assembler::stdcq( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stdcq( int crd, Register s1, Register s2) { v8_only(); emit_int32( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::stdcq( int crd, Register s1, int simm13a) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
// pp 231
|
||||
|
||||
inline void Assembler::swap( Register s1, Register s2, Register d) { v9_dep(); emit_long( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::swap( Register s1, Register s2, Register d) { v9_dep(); emit_int32( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::swap( Register s1, int simm13a, Register d) { v9_dep(); emit_data( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
#endif // CPU_SPARC_VM_ASSEMBLER_SPARC_INLINE_HPP
|
||||
|
@ -137,7 +137,7 @@ address CppInterpreterGenerator::generate_result_handler_for(BasicType type) {
|
||||
}
|
||||
__ ret(); // return from interpreter activation
|
||||
__ delayed()->restore(I5_savedSP, G0, SP); // remove interpreter frame
|
||||
NOT_PRODUCT(__ emit_long(0);) // marker for disassembly
|
||||
NOT_PRODUCT(__ emit_int32(0);) // marker for disassembly
|
||||
return entry;
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ address CppInterpreterGenerator::generate_tosca_to_stack_converter(BasicType typ
|
||||
}
|
||||
__ retl(); // return from interpreter activation
|
||||
__ delayed()->nop(); // schedule this better
|
||||
NOT_PRODUCT(__ emit_long(0);) // marker for disassembly
|
||||
NOT_PRODUCT(__ emit_int32(0);) // marker for disassembly
|
||||
return entry;
|
||||
}
|
||||
|
||||
@ -1473,7 +1473,7 @@ static address interpreter_frame_manager = NULL;
|
||||
__ brx(Assembler::equal, false, Assembler::pt, skip); \
|
||||
__ delayed()->nop(); \
|
||||
__ breakpoint_trap(); \
|
||||
__ emit_long(marker); \
|
||||
__ emit_int32(marker); \
|
||||
__ bind(skip); \
|
||||
}
|
||||
#else
|
||||
|
@ -1224,7 +1224,7 @@ void MacroAssembler::set_narrow_oop(jobject obj, Register d) {
|
||||
// Relocation with special format (see relocInfo_sparc.hpp).
|
||||
relocate(rspec, 1);
|
||||
// Assembler::sethi(0x3fffff, d);
|
||||
emit_long( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(0x3fffff) );
|
||||
emit_int32( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(0x3fffff) );
|
||||
// Don't add relocation for 'add'. Do patching during 'sethi' processing.
|
||||
add(d, 0x3ff, d);
|
||||
|
||||
@ -1240,7 +1240,7 @@ void MacroAssembler::set_narrow_klass(Klass* k, Register d) {
|
||||
// Relocation with special format (see relocInfo_sparc.hpp).
|
||||
relocate(rspec, 1);
|
||||
// Assembler::sethi(encoded_k, d);
|
||||
emit_long( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(encoded_k) );
|
||||
emit_int32( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(encoded_k) );
|
||||
// Don't add relocation for 'add'. Do patching during 'sethi' processing.
|
||||
add(d, low10(encoded_k), d);
|
||||
|
||||
|
@ -259,7 +259,7 @@ address TemplateInterpreterGenerator::generate_result_handler_for(BasicType type
|
||||
}
|
||||
__ ret(); // return from interpreter activation
|
||||
__ delayed()->restore(I5_savedSP, G0, SP); // remove interpreter frame
|
||||
NOT_PRODUCT(__ emit_long(0);) // marker for disassembly
|
||||
NOT_PRODUCT(__ emit_int32(0);) // marker for disassembly
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ int AbstractAssembler::code_fill_byte() {
|
||||
// make this go away someday
|
||||
void Assembler::emit_data(jint data, relocInfo::relocType rtype, int format) {
|
||||
if (rtype == relocInfo::none)
|
||||
emit_long(data);
|
||||
emit_int32(data);
|
||||
else emit_data(data, Relocation::spec_simple(rtype), format);
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ void Assembler::emit_data(jint data, RelocationHolder const& rspec, int format)
|
||||
else
|
||||
code_section()->relocate(inst_mark(), rspec, format);
|
||||
}
|
||||
emit_long(data);
|
||||
emit_int32(data);
|
||||
}
|
||||
|
||||
static int encode(Register r) {
|
||||
@ -243,7 +243,7 @@ void Assembler::emit_arith(int op1, int op2, Register dst, int32_t imm32) {
|
||||
} else {
|
||||
emit_int8(op1);
|
||||
emit_int8(op2 | encode(dst));
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,7 +254,7 @@ void Assembler::emit_arith_imm32(int op1, int op2, Register dst, int32_t imm32)
|
||||
assert((op1 & 0x02) == 0, "sign-extension bit should not be set");
|
||||
emit_int8(op1);
|
||||
emit_int8(op2 | encode(dst));
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
// immediate-to-memory forms
|
||||
@ -268,7 +268,7 @@ void Assembler::emit_arith_operand(int op1, Register rm, Address adr, int32_t im
|
||||
} else {
|
||||
emit_int8(op1);
|
||||
emit_operand(rm, adr, 4);
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
}
|
||||
|
||||
@ -976,7 +976,7 @@ void Assembler::addr_nop_7() {
|
||||
emit_int8(0x1F);
|
||||
emit_int8((unsigned char)0x80);
|
||||
// emit_rm(cbuf, 0x2, EAX_enc, EAX_enc);
|
||||
emit_long(0); // 32-bits offset (4 bytes)
|
||||
emit_int32(0); // 32-bits offset (4 bytes)
|
||||
}
|
||||
|
||||
void Assembler::addr_nop_8() {
|
||||
@ -987,7 +987,7 @@ void Assembler::addr_nop_8() {
|
||||
emit_int8((unsigned char)0x84);
|
||||
// emit_rm(cbuf, 0x2, EAX_enc, 0x4);
|
||||
emit_int8(0x00); // emit_rm(cbuf, 0x0, EAX_enc, EAX_enc);
|
||||
emit_long(0); // 32-bits offset (4 bytes)
|
||||
emit_int32(0); // 32-bits offset (4 bytes)
|
||||
}
|
||||
|
||||
void Assembler::addsd(XMMRegister dst, XMMRegister src) {
|
||||
@ -1076,7 +1076,7 @@ void Assembler::andl(Address dst, int32_t imm32) {
|
||||
prefix(dst);
|
||||
emit_int8((unsigned char)0x81);
|
||||
emit_operand(rsp, dst, 4);
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
void Assembler::andl(Register dst, int32_t imm32) {
|
||||
@ -1204,7 +1204,7 @@ void Assembler::cmpl(Address dst, int32_t imm32) {
|
||||
prefix(dst);
|
||||
emit_int8((unsigned char)0x81);
|
||||
emit_operand(rdi, dst, 4);
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
void Assembler::cmpl(Register dst, int32_t imm32) {
|
||||
@ -1408,7 +1408,7 @@ void Assembler::imull(Register dst, Register src, int value) {
|
||||
} else {
|
||||
emit_int8(0x69);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
emit_long(value);
|
||||
emit_int32(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1440,7 +1440,7 @@ void Assembler::jcc(Condition cc, Label& L, bool maybe_short) {
|
||||
"must be 32bit offset (call4)");
|
||||
emit_int8(0x0F);
|
||||
emit_int8((unsigned char)(0x80 | cc));
|
||||
emit_long(offs - long_size);
|
||||
emit_int32(offs - long_size);
|
||||
}
|
||||
} else {
|
||||
// Note: could eliminate cond. jumps to this jump if condition
|
||||
@ -1450,7 +1450,7 @@ void Assembler::jcc(Condition cc, Label& L, bool maybe_short) {
|
||||
L.add_patch_at(code(), locator());
|
||||
emit_int8(0x0F);
|
||||
emit_int8((unsigned char)(0x80 | cc));
|
||||
emit_long(0);
|
||||
emit_int32(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1498,7 +1498,7 @@ void Assembler::jmp(Label& L, bool maybe_short) {
|
||||
emit_int8((offs - short_size) & 0xFF);
|
||||
} else {
|
||||
emit_int8((unsigned char)0xE9);
|
||||
emit_long(offs - long_size);
|
||||
emit_int32(offs - long_size);
|
||||
}
|
||||
} else {
|
||||
// By default, forward jumps are always 32-bit displacements, since
|
||||
@ -1508,7 +1508,7 @@ void Assembler::jmp(Label& L, bool maybe_short) {
|
||||
InstructionMark im(this);
|
||||
L.add_patch_at(code(), locator());
|
||||
emit_int8((unsigned char)0xE9);
|
||||
emit_long(0);
|
||||
emit_int32(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1732,7 +1732,7 @@ void Assembler::vmovdqu(Address dst, XMMRegister src) {
|
||||
void Assembler::movl(Register dst, int32_t imm32) {
|
||||
int encode = prefix_and_encode(dst->encoding());
|
||||
emit_int8((unsigned char)(0xB8 | encode));
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
void Assembler::movl(Register dst, Register src) {
|
||||
@ -1753,7 +1753,7 @@ void Assembler::movl(Address dst, int32_t imm32) {
|
||||
prefix(dst);
|
||||
emit_int8((unsigned char)0xC7);
|
||||
emit_operand(rax, dst, 4);
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
void Assembler::movl(Address dst, Register src) {
|
||||
@ -2468,6 +2468,26 @@ void Assembler::ptest(XMMRegister dst, XMMRegister src) {
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::vptest(XMMRegister dst, Address src) {
|
||||
assert(VM_Version::supports_avx(), "");
|
||||
InstructionMark im(this);
|
||||
bool vector256 = true;
|
||||
assert(dst != xnoreg, "sanity");
|
||||
int dst_enc = dst->encoding();
|
||||
// swap src<->dst for encoding
|
||||
vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector256);
|
||||
emit_int8(0x17);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::vptest(XMMRegister dst, XMMRegister src) {
|
||||
assert(VM_Version::supports_avx(), "");
|
||||
bool vector256 = true;
|
||||
int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector256, VEX_OPCODE_0F_38);
|
||||
emit_int8(0x17);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::punpcklbw(XMMRegister dst, Address src) {
|
||||
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
|
||||
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
|
||||
@ -2499,7 +2519,7 @@ void Assembler::push(int32_t imm32) {
|
||||
// in 64bits we push 64bits onto the stack but only
|
||||
// take a 32bit immediate
|
||||
emit_int8(0x68);
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
void Assembler::push(Register src) {
|
||||
@ -2544,12 +2564,18 @@ void Assembler::rep_mov() {
|
||||
emit_int8((unsigned char)0xA5);
|
||||
}
|
||||
|
||||
// sets rcx bytes with rax, value at [edi]
|
||||
void Assembler::rep_stosb() {
|
||||
emit_int8((unsigned char)0xF3); // REP
|
||||
LP64_ONLY(prefix(REX_W));
|
||||
emit_int8((unsigned char)0xAA); // STOSB
|
||||
}
|
||||
|
||||
// sets rcx pointer sized words with rax, value at [edi]
|
||||
// generic
|
||||
void Assembler::rep_set() { // rep_set
|
||||
emit_int8((unsigned char)0xF3);
|
||||
// STOSQ
|
||||
LP64_ONLY(prefix(REX_W));
|
||||
void Assembler::rep_stos() {
|
||||
emit_int8((unsigned char)0xF3); // REP
|
||||
LP64_ONLY(prefix(REX_W)); // LP64:STOSQ, LP32:STOSD
|
||||
emit_int8((unsigned char)0xAB);
|
||||
}
|
||||
|
||||
@ -2785,7 +2811,7 @@ void Assembler::testl(Register dst, int32_t imm32) {
|
||||
emit_int8((unsigned char)0xF7);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
void Assembler::testl(Register dst, Register src) {
|
||||
@ -3650,6 +3676,15 @@ void Assembler::vextracti128h(Address dst, XMMRegister src) {
|
||||
emit_int8(0x01);
|
||||
}
|
||||
|
||||
// duplicate 4-bytes integer data from src into 8 locations in dest
|
||||
void Assembler::vpbroadcastd(XMMRegister dst, XMMRegister src) {
|
||||
assert(VM_Version::supports_avx2(), "");
|
||||
bool vector256 = true;
|
||||
int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, vector256, VEX_OPCODE_0F_38);
|
||||
emit_int8(0x58);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::vzeroupper() {
|
||||
assert(VM_Version::supports_avx(), "");
|
||||
(void)vex_prefix_and_encode(xmm0, xmm0, xmm0, VEX_SIMD_NONE);
|
||||
@ -4720,7 +4755,7 @@ void Assembler::andq(Address dst, int32_t imm32) {
|
||||
prefixq(dst);
|
||||
emit_int8((unsigned char)0x81);
|
||||
emit_operand(rsp, dst, 4);
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
void Assembler::andq(Register dst, int32_t imm32) {
|
||||
@ -4793,7 +4828,7 @@ void Assembler::cmpq(Address dst, int32_t imm32) {
|
||||
prefixq(dst);
|
||||
emit_int8((unsigned char)0x81);
|
||||
emit_operand(rdi, dst, 4);
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
void Assembler::cmpq(Register dst, int32_t imm32) {
|
||||
@ -4932,7 +4967,7 @@ void Assembler::imulq(Register dst, Register src, int value) {
|
||||
} else {
|
||||
emit_int8(0x69);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
emit_long(value);
|
||||
emit_int32(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5085,7 +5120,7 @@ void Assembler::movslq(Register dst, int32_t imm32) {
|
||||
InstructionMark im(this);
|
||||
int encode = prefixq_and_encode(dst->encoding());
|
||||
emit_int8((unsigned char)(0xC7 | encode));
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
void Assembler::movslq(Address dst, int32_t imm32) {
|
||||
@ -5094,7 +5129,7 @@ void Assembler::movslq(Address dst, int32_t imm32) {
|
||||
prefixq(dst);
|
||||
emit_int8((unsigned char)0xC7);
|
||||
emit_operand(rax, dst, 4);
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
void Assembler::movslq(Register dst, Address src) {
|
||||
@ -5172,7 +5207,7 @@ void Assembler::orq(Address dst, int32_t imm32) {
|
||||
prefixq(dst);
|
||||
emit_int8((unsigned char)0x81);
|
||||
emit_operand(rcx, dst, 4);
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
void Assembler::orq(Register dst, int32_t imm32) {
|
||||
@ -5407,7 +5442,7 @@ void Assembler::testq(Register dst, int32_t imm32) {
|
||||
emit_int8((unsigned char)0xF7);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
emit_long(imm32);
|
||||
emit_int32(imm32);
|
||||
}
|
||||
|
||||
void Assembler::testq(Register dst, Register src) {
|
||||
|
@ -832,7 +832,8 @@ private:
|
||||
|
||||
// These do register sized moves/scans
|
||||
void rep_mov();
|
||||
void rep_set();
|
||||
void rep_stos();
|
||||
void rep_stosb();
|
||||
void repne_scan();
|
||||
#ifdef _LP64
|
||||
void repne_scanl();
|
||||
@ -1443,9 +1444,12 @@ private:
|
||||
// Shift Right by bytes Logical DoubleQuadword Immediate
|
||||
void psrldq(XMMRegister dst, int shift);
|
||||
|
||||
// Logical Compare Double Quadword
|
||||
// Logical Compare 128bit
|
||||
void ptest(XMMRegister dst, XMMRegister src);
|
||||
void ptest(XMMRegister dst, Address src);
|
||||
// Logical Compare 256bit
|
||||
void vptest(XMMRegister dst, XMMRegister src);
|
||||
void vptest(XMMRegister dst, Address src);
|
||||
|
||||
// Interleave Low Bytes
|
||||
void punpcklbw(XMMRegister dst, XMMRegister src);
|
||||
@ -1753,6 +1757,9 @@ private:
|
||||
void vextractf128h(Address dst, XMMRegister src);
|
||||
void vextracti128h(Address dst, XMMRegister src);
|
||||
|
||||
// duplicate 4-bytes integer data from src into 8 locations in dest
|
||||
void vpbroadcastd(XMMRegister dst, XMMRegister src);
|
||||
|
||||
// AVX instruction which is used to clear upper 128 bits of YMM registers and
|
||||
// to avoid transaction penalty between AVX and SSE states. There is no
|
||||
// penalty if legacy SSE instructions are encoded using VEX prefix because
|
||||
|
@ -120,6 +120,9 @@ define_pd_global(intx, CMSYoungGenPerWorker, 64*M); // default max size of CMS
|
||||
product(bool, UseUnalignedLoadStores, false, \
|
||||
"Use SSE2 MOVDQU instruction for Arraycopy") \
|
||||
\
|
||||
product(bool, UseFastStosb, false, \
|
||||
"Use fast-string operation for zeroing: rep stosb") \
|
||||
\
|
||||
/* assembler */ \
|
||||
product(bool, Use486InstrsOnly, false, \
|
||||
"Use 80486 Compliant instruction subset") \
|
||||
|
@ -2540,7 +2540,7 @@ void MacroAssembler::jump_cc(Condition cc, AddressLiteral dst) {
|
||||
// 0000 1111 1000 tttn #32-bit disp
|
||||
emit_int8(0x0F);
|
||||
emit_int8((unsigned char)(0x80 | cc));
|
||||
emit_long(offs - long_size);
|
||||
emit_int32(offs - long_size);
|
||||
}
|
||||
} else {
|
||||
#ifdef ASSERT
|
||||
@ -5224,6 +5224,22 @@ void MacroAssembler::verified_entry(int framesize, bool stack_bang, bool fp_mode
|
||||
|
||||
}
|
||||
|
||||
void MacroAssembler::clear_mem(Register base, Register cnt, Register tmp) {
|
||||
// cnt - number of qwords (8-byte words).
|
||||
// base - start address, qword aligned.
|
||||
assert(base==rdi, "base register must be edi for rep stos");
|
||||
assert(tmp==rax, "tmp register must be eax for rep stos");
|
||||
assert(cnt==rcx, "cnt register must be ecx for rep stos");
|
||||
|
||||
xorptr(tmp, tmp);
|
||||
if (UseFastStosb) {
|
||||
shlptr(cnt,3); // convert to number of bytes
|
||||
rep_stosb();
|
||||
} else {
|
||||
NOT_LP64(shlptr(cnt,1);) // convert to number of dwords for 32-bit VM
|
||||
rep_stos();
|
||||
}
|
||||
}
|
||||
|
||||
// IndexOf for constant substrings with size >= 8 chars
|
||||
// which don't need to be loaded through stack.
|
||||
@ -5659,42 +5675,114 @@ void MacroAssembler::string_compare(Register str1, Register str2,
|
||||
testl(cnt2, cnt2);
|
||||
jcc(Assembler::zero, LENGTH_DIFF_LABEL);
|
||||
|
||||
// Load first characters
|
||||
// Compare first characters
|
||||
load_unsigned_short(result, Address(str1, 0));
|
||||
load_unsigned_short(cnt1, Address(str2, 0));
|
||||
|
||||
// Compare first characters
|
||||
subl(result, cnt1);
|
||||
jcc(Assembler::notZero, POP_LABEL);
|
||||
decrementl(cnt2);
|
||||
jcc(Assembler::zero, LENGTH_DIFF_LABEL);
|
||||
cmpl(cnt2, 1);
|
||||
jcc(Assembler::equal, LENGTH_DIFF_LABEL);
|
||||
|
||||
{
|
||||
// Check after comparing first character to see if strings are equivalent
|
||||
Label LSkip2;
|
||||
// Check if the strings start at same location
|
||||
cmpptr(str1, str2);
|
||||
jccb(Assembler::notEqual, LSkip2);
|
||||
|
||||
// Check if the length difference is zero (from stack)
|
||||
cmpl(Address(rsp, 0), 0x0);
|
||||
jcc(Assembler::equal, LENGTH_DIFF_LABEL);
|
||||
|
||||
// Strings might not be equivalent
|
||||
bind(LSkip2);
|
||||
}
|
||||
// Check if the strings start at the same location.
|
||||
cmpptr(str1, str2);
|
||||
jcc(Assembler::equal, LENGTH_DIFF_LABEL);
|
||||
|
||||
Address::ScaleFactor scale = Address::times_2;
|
||||
int stride = 8;
|
||||
|
||||
// Advance to next element
|
||||
addptr(str1, 16/stride);
|
||||
addptr(str2, 16/stride);
|
||||
if (UseAVX >= 2) {
|
||||
Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_WIDE_TAIL, COMPARE_SMALL_STR;
|
||||
Label COMPARE_WIDE_VECTORS_LOOP, COMPARE_16_CHARS, COMPARE_INDEX_CHAR;
|
||||
Label COMPARE_TAIL_LONG;
|
||||
int pcmpmask = 0x19;
|
||||
|
||||
if (UseSSE42Intrinsics) {
|
||||
// Setup to compare 16-chars (32-bytes) vectors,
|
||||
// start from first character again because it has aligned address.
|
||||
int stride2 = 16;
|
||||
int adr_stride = stride << scale;
|
||||
int adr_stride2 = stride2 << scale;
|
||||
|
||||
assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
|
||||
// rax and rdx are used by pcmpestri as elements counters
|
||||
movl(result, cnt2);
|
||||
andl(cnt2, ~(stride2-1)); // cnt2 holds the vector count
|
||||
jcc(Assembler::zero, COMPARE_TAIL_LONG);
|
||||
|
||||
// fast path : compare first 2 8-char vectors.
|
||||
bind(COMPARE_16_CHARS);
|
||||
movdqu(vec1, Address(str1, 0));
|
||||
pcmpestri(vec1, Address(str2, 0), pcmpmask);
|
||||
jccb(Assembler::below, COMPARE_INDEX_CHAR);
|
||||
|
||||
movdqu(vec1, Address(str1, adr_stride));
|
||||
pcmpestri(vec1, Address(str2, adr_stride), pcmpmask);
|
||||
jccb(Assembler::aboveEqual, COMPARE_WIDE_VECTORS);
|
||||
addl(cnt1, stride);
|
||||
|
||||
// Compare the characters at index in cnt1
|
||||
bind(COMPARE_INDEX_CHAR); //cnt1 has the offset of the mismatching character
|
||||
load_unsigned_short(result, Address(str1, cnt1, scale));
|
||||
load_unsigned_short(cnt2, Address(str2, cnt1, scale));
|
||||
subl(result, cnt2);
|
||||
jmp(POP_LABEL);
|
||||
|
||||
// Setup the registers to start vector comparison loop
|
||||
bind(COMPARE_WIDE_VECTORS);
|
||||
lea(str1, Address(str1, result, scale));
|
||||
lea(str2, Address(str2, result, scale));
|
||||
subl(result, stride2);
|
||||
subl(cnt2, stride2);
|
||||
jccb(Assembler::zero, COMPARE_WIDE_TAIL);
|
||||
negptr(result);
|
||||
|
||||
// In a loop, compare 16-chars (32-bytes) at once using (vpxor+vptest)
|
||||
bind(COMPARE_WIDE_VECTORS_LOOP);
|
||||
vmovdqu(vec1, Address(str1, result, scale));
|
||||
vpxor(vec1, Address(str2, result, scale));
|
||||
vptest(vec1, vec1);
|
||||
jccb(Assembler::notZero, VECTOR_NOT_EQUAL);
|
||||
addptr(result, stride2);
|
||||
subl(cnt2, stride2);
|
||||
jccb(Assembler::notZero, COMPARE_WIDE_VECTORS_LOOP);
|
||||
|
||||
// compare wide vectors tail
|
||||
bind(COMPARE_WIDE_TAIL);
|
||||
testptr(result, result);
|
||||
jccb(Assembler::zero, LENGTH_DIFF_LABEL);
|
||||
|
||||
movl(result, stride2);
|
||||
movl(cnt2, result);
|
||||
negptr(result);
|
||||
jmpb(COMPARE_WIDE_VECTORS_LOOP);
|
||||
|
||||
// Identifies the mismatching (higher or lower)16-bytes in the 32-byte vectors.
|
||||
bind(VECTOR_NOT_EQUAL);
|
||||
lea(str1, Address(str1, result, scale));
|
||||
lea(str2, Address(str2, result, scale));
|
||||
jmp(COMPARE_16_CHARS);
|
||||
|
||||
// Compare tail chars, length between 1 to 15 chars
|
||||
bind(COMPARE_TAIL_LONG);
|
||||
movl(cnt2, result);
|
||||
cmpl(cnt2, stride);
|
||||
jccb(Assembler::less, COMPARE_SMALL_STR);
|
||||
|
||||
movdqu(vec1, Address(str1, 0));
|
||||
pcmpestri(vec1, Address(str2, 0), pcmpmask);
|
||||
jcc(Assembler::below, COMPARE_INDEX_CHAR);
|
||||
subptr(cnt2, stride);
|
||||
jccb(Assembler::zero, LENGTH_DIFF_LABEL);
|
||||
lea(str1, Address(str1, result, scale));
|
||||
lea(str2, Address(str2, result, scale));
|
||||
negptr(cnt2);
|
||||
jmpb(WHILE_HEAD_LABEL);
|
||||
|
||||
bind(COMPARE_SMALL_STR);
|
||||
} else if (UseSSE42Intrinsics) {
|
||||
Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
|
||||
int pcmpmask = 0x19;
|
||||
// Setup to compare 16-byte vectors
|
||||
// Setup to compare 8-char (16-byte) vectors,
|
||||
// start from first character again because it has aligned address.
|
||||
movl(result, cnt2);
|
||||
andl(cnt2, ~(stride - 1)); // cnt2 holds the vector count
|
||||
jccb(Assembler::zero, COMPARE_TAIL);
|
||||
@ -5726,7 +5814,7 @@ void MacroAssembler::string_compare(Register str1, Register str2,
|
||||
jccb(Assembler::notZero, COMPARE_WIDE_VECTORS);
|
||||
|
||||
// compare wide vectors tail
|
||||
testl(result, result);
|
||||
testptr(result, result);
|
||||
jccb(Assembler::zero, LENGTH_DIFF_LABEL);
|
||||
|
||||
movl(cnt2, stride);
|
||||
@ -5738,21 +5826,20 @@ void MacroAssembler::string_compare(Register str1, Register str2,
|
||||
|
||||
// Mismatched characters in the vectors
|
||||
bind(VECTOR_NOT_EQUAL);
|
||||
addptr(result, cnt1);
|
||||
movptr(cnt2, result);
|
||||
load_unsigned_short(result, Address(str1, cnt2, scale));
|
||||
load_unsigned_short(cnt1, Address(str2, cnt2, scale));
|
||||
subl(result, cnt1);
|
||||
addptr(cnt1, result);
|
||||
load_unsigned_short(result, Address(str1, cnt1, scale));
|
||||
load_unsigned_short(cnt2, Address(str2, cnt1, scale));
|
||||
subl(result, cnt2);
|
||||
jmpb(POP_LABEL);
|
||||
|
||||
bind(COMPARE_TAIL); // limit is zero
|
||||
movl(cnt2, result);
|
||||
// Fallthru to tail compare
|
||||
}
|
||||
|
||||
// Shift str2 and str1 to the end of the arrays, negate min
|
||||
lea(str1, Address(str1, cnt2, scale, 0));
|
||||
lea(str2, Address(str2, cnt2, scale, 0));
|
||||
lea(str1, Address(str1, cnt2, scale));
|
||||
lea(str2, Address(str2, cnt2, scale));
|
||||
decrementl(cnt2); // first character was compared already
|
||||
negptr(cnt2);
|
||||
|
||||
// Compare the rest of the elements
|
||||
@ -5817,7 +5904,44 @@ void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Regist
|
||||
shll(limit, 1); // byte count != 0
|
||||
movl(result, limit); // copy
|
||||
|
||||
if (UseSSE42Intrinsics) {
|
||||
if (UseAVX >= 2) {
|
||||
// With AVX2, use 32-byte vector compare
|
||||
Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
|
||||
|
||||
// Compare 32-byte vectors
|
||||
andl(result, 0x0000001e); // tail count (in bytes)
|
||||
andl(limit, 0xffffffe0); // vector count (in bytes)
|
||||
jccb(Assembler::zero, COMPARE_TAIL);
|
||||
|
||||
lea(ary1, Address(ary1, limit, Address::times_1));
|
||||
lea(ary2, Address(ary2, limit, Address::times_1));
|
||||
negptr(limit);
|
||||
|
||||
bind(COMPARE_WIDE_VECTORS);
|
||||
vmovdqu(vec1, Address(ary1, limit, Address::times_1));
|
||||
vmovdqu(vec2, Address(ary2, limit, Address::times_1));
|
||||
vpxor(vec1, vec2);
|
||||
|
||||
vptest(vec1, vec1);
|
||||
jccb(Assembler::notZero, FALSE_LABEL);
|
||||
addptr(limit, 32);
|
||||
jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
|
||||
|
||||
testl(result, result);
|
||||
jccb(Assembler::zero, TRUE_LABEL);
|
||||
|
||||
vmovdqu(vec1, Address(ary1, result, Address::times_1, -32));
|
||||
vmovdqu(vec2, Address(ary2, result, Address::times_1, -32));
|
||||
vpxor(vec1, vec2);
|
||||
|
||||
vptest(vec1, vec1);
|
||||
jccb(Assembler::notZero, FALSE_LABEL);
|
||||
jmpb(TRUE_LABEL);
|
||||
|
||||
bind(COMPARE_TAIL); // limit is zero
|
||||
movl(limit, result);
|
||||
// Fallthru to tail compare
|
||||
} else if (UseSSE42Intrinsics) {
|
||||
// With SSE4.2, use double quad vector compare
|
||||
Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
|
||||
|
||||
@ -5995,29 +6119,53 @@ void MacroAssembler::generate_fill(BasicType t, bool aligned,
|
||||
{
|
||||
assert( UseSSE >= 2, "supported cpu only" );
|
||||
Label L_fill_32_bytes_loop, L_check_fill_8_bytes, L_fill_8_bytes_loop, L_fill_8_bytes;
|
||||
// Fill 32-byte chunks
|
||||
movdl(xtmp, value);
|
||||
pshufd(xtmp, xtmp, 0);
|
||||
if (UseAVX >= 2 && UseUnalignedLoadStores) {
|
||||
// Fill 64-byte chunks
|
||||
Label L_fill_64_bytes_loop, L_check_fill_32_bytes;
|
||||
vpbroadcastd(xtmp, xtmp);
|
||||
|
||||
subl(count, 8 << shift);
|
||||
jcc(Assembler::less, L_check_fill_8_bytes);
|
||||
align(16);
|
||||
subl(count, 16 << shift);
|
||||
jcc(Assembler::less, L_check_fill_32_bytes);
|
||||
align(16);
|
||||
|
||||
BIND(L_fill_32_bytes_loop);
|
||||
BIND(L_fill_64_bytes_loop);
|
||||
vmovdqu(Address(to, 0), xtmp);
|
||||
vmovdqu(Address(to, 32), xtmp);
|
||||
addptr(to, 64);
|
||||
subl(count, 16 << shift);
|
||||
jcc(Assembler::greaterEqual, L_fill_64_bytes_loop);
|
||||
|
||||
if (UseUnalignedLoadStores) {
|
||||
movdqu(Address(to, 0), xtmp);
|
||||
movdqu(Address(to, 16), xtmp);
|
||||
BIND(L_check_fill_32_bytes);
|
||||
addl(count, 8 << shift);
|
||||
jccb(Assembler::less, L_check_fill_8_bytes);
|
||||
vmovdqu(Address(to, 0), xtmp);
|
||||
addptr(to, 32);
|
||||
subl(count, 8 << shift);
|
||||
} else {
|
||||
movq(Address(to, 0), xtmp);
|
||||
movq(Address(to, 8), xtmp);
|
||||
movq(Address(to, 16), xtmp);
|
||||
movq(Address(to, 24), xtmp);
|
||||
}
|
||||
// Fill 32-byte chunks
|
||||
pshufd(xtmp, xtmp, 0);
|
||||
|
||||
addptr(to, 32);
|
||||
subl(count, 8 << shift);
|
||||
jcc(Assembler::greaterEqual, L_fill_32_bytes_loop);
|
||||
subl(count, 8 << shift);
|
||||
jcc(Assembler::less, L_check_fill_8_bytes);
|
||||
align(16);
|
||||
|
||||
BIND(L_fill_32_bytes_loop);
|
||||
|
||||
if (UseUnalignedLoadStores) {
|
||||
movdqu(Address(to, 0), xtmp);
|
||||
movdqu(Address(to, 16), xtmp);
|
||||
} else {
|
||||
movq(Address(to, 0), xtmp);
|
||||
movq(Address(to, 8), xtmp);
|
||||
movq(Address(to, 16), xtmp);
|
||||
movq(Address(to, 24), xtmp);
|
||||
}
|
||||
|
||||
addptr(to, 32);
|
||||
subl(count, 8 << shift);
|
||||
jcc(Assembler::greaterEqual, L_fill_32_bytes_loop);
|
||||
}
|
||||
BIND(L_check_fill_8_bytes);
|
||||
addl(count, 8 << shift);
|
||||
jccb(Assembler::zero, L_exit);
|
||||
|
@ -1011,6 +1011,10 @@ public:
|
||||
Assembler::vxorpd(dst, nds, src, vector256);
|
||||
}
|
||||
|
||||
// Simple version for AVX2 256bit vectors
|
||||
void vpxor(XMMRegister dst, XMMRegister src) { Assembler::vpxor(dst, dst, src, true); }
|
||||
void vpxor(XMMRegister dst, Address src) { Assembler::vpxor(dst, dst, src, true); }
|
||||
|
||||
// Move packed integer values from low 128 bit to hign 128 bit in 256 bit vector.
|
||||
void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) {
|
||||
if (UseAVX > 1) // vinserti128h is available only in AVX2
|
||||
@ -1096,6 +1100,9 @@ public:
|
||||
// C2 compiled method's prolog code.
|
||||
void verified_entry(int framesize, bool stack_bang, bool fp_mode_24b);
|
||||
|
||||
// clear memory of size 'cnt' qwords, starting at 'base'.
|
||||
void clear_mem(Register base, Register cnt, Register rtmp);
|
||||
|
||||
// IndexOf strings.
|
||||
// Small strings are loaded through stack if they cross page boundary.
|
||||
void string_indexof(Register str1, Register str2,
|
||||
|
@ -796,16 +796,22 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ align(OptoLoopAlignment);
|
||||
__ BIND(L_copy_64_bytes_loop);
|
||||
|
||||
if(UseUnalignedLoadStores) {
|
||||
__ movdqu(xmm0, Address(from, 0));
|
||||
__ movdqu(Address(from, to_from, Address::times_1, 0), xmm0);
|
||||
__ movdqu(xmm1, Address(from, 16));
|
||||
__ movdqu(Address(from, to_from, Address::times_1, 16), xmm1);
|
||||
__ movdqu(xmm2, Address(from, 32));
|
||||
__ movdqu(Address(from, to_from, Address::times_1, 32), xmm2);
|
||||
__ movdqu(xmm3, Address(from, 48));
|
||||
__ movdqu(Address(from, to_from, Address::times_1, 48), xmm3);
|
||||
|
||||
if (UseUnalignedLoadStores) {
|
||||
if (UseAVX >= 2) {
|
||||
__ vmovdqu(xmm0, Address(from, 0));
|
||||
__ vmovdqu(Address(from, to_from, Address::times_1, 0), xmm0);
|
||||
__ vmovdqu(xmm1, Address(from, 32));
|
||||
__ vmovdqu(Address(from, to_from, Address::times_1, 32), xmm1);
|
||||
} else {
|
||||
__ movdqu(xmm0, Address(from, 0));
|
||||
__ movdqu(Address(from, to_from, Address::times_1, 0), xmm0);
|
||||
__ movdqu(xmm1, Address(from, 16));
|
||||
__ movdqu(Address(from, to_from, Address::times_1, 16), xmm1);
|
||||
__ movdqu(xmm2, Address(from, 32));
|
||||
__ movdqu(Address(from, to_from, Address::times_1, 32), xmm2);
|
||||
__ movdqu(xmm3, Address(from, 48));
|
||||
__ movdqu(Address(from, to_from, Address::times_1, 48), xmm3);
|
||||
}
|
||||
} else {
|
||||
__ movq(xmm0, Address(from, 0));
|
||||
__ movq(Address(from, to_from, Address::times_1, 0), xmm0);
|
||||
|
@ -1286,23 +1286,54 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// end_to - destination array end address
|
||||
// qword_count - 64-bits element count, negative
|
||||
// to - scratch
|
||||
// L_copy_32_bytes - entry label
|
||||
// L_copy_bytes - entry label
|
||||
// L_copy_8_bytes - exit label
|
||||
//
|
||||
void copy_32_bytes_forward(Register end_from, Register end_to,
|
||||
void copy_bytes_forward(Register end_from, Register end_to,
|
||||
Register qword_count, Register to,
|
||||
Label& L_copy_32_bytes, Label& L_copy_8_bytes) {
|
||||
Label& L_copy_bytes, Label& L_copy_8_bytes) {
|
||||
DEBUG_ONLY(__ stop("enter at entry label, not here"));
|
||||
Label L_loop;
|
||||
__ align(OptoLoopAlignment);
|
||||
__ BIND(L_loop);
|
||||
if(UseUnalignedLoadStores) {
|
||||
__ movdqu(xmm0, Address(end_from, qword_count, Address::times_8, -24));
|
||||
__ movdqu(Address(end_to, qword_count, Address::times_8, -24), xmm0);
|
||||
__ movdqu(xmm1, Address(end_from, qword_count, Address::times_8, - 8));
|
||||
__ movdqu(Address(end_to, qword_count, Address::times_8, - 8), xmm1);
|
||||
|
||||
if (UseUnalignedLoadStores) {
|
||||
Label L_end;
|
||||
// Copy 64-bytes per iteration
|
||||
__ BIND(L_loop);
|
||||
if (UseAVX >= 2) {
|
||||
__ vmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56));
|
||||
__ vmovdqu(Address(end_to, qword_count, Address::times_8, -56), xmm0);
|
||||
__ vmovdqu(xmm1, Address(end_from, qword_count, Address::times_8, -24));
|
||||
__ vmovdqu(Address(end_to, qword_count, Address::times_8, -24), xmm1);
|
||||
} else {
|
||||
__ movdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56));
|
||||
__ movdqu(Address(end_to, qword_count, Address::times_8, -56), xmm0);
|
||||
__ movdqu(xmm1, Address(end_from, qword_count, Address::times_8, -40));
|
||||
__ movdqu(Address(end_to, qword_count, Address::times_8, -40), xmm1);
|
||||
__ movdqu(xmm2, Address(end_from, qword_count, Address::times_8, -24));
|
||||
__ movdqu(Address(end_to, qword_count, Address::times_8, -24), xmm2);
|
||||
__ movdqu(xmm3, Address(end_from, qword_count, Address::times_8, - 8));
|
||||
__ movdqu(Address(end_to, qword_count, Address::times_8, - 8), xmm3);
|
||||
}
|
||||
__ BIND(L_copy_bytes);
|
||||
__ addptr(qword_count, 8);
|
||||
__ jcc(Assembler::lessEqual, L_loop);
|
||||
__ subptr(qword_count, 4); // sub(8) and add(4)
|
||||
__ jccb(Assembler::greater, L_end);
|
||||
// Copy trailing 32 bytes
|
||||
if (UseAVX >= 2) {
|
||||
__ vmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -24));
|
||||
__ vmovdqu(Address(end_to, qword_count, Address::times_8, -24), xmm0);
|
||||
} else {
|
||||
__ movdqu(xmm0, Address(end_from, qword_count, Address::times_8, -24));
|
||||
__ movdqu(Address(end_to, qword_count, Address::times_8, -24), xmm0);
|
||||
__ movdqu(xmm1, Address(end_from, qword_count, Address::times_8, - 8));
|
||||
__ movdqu(Address(end_to, qword_count, Address::times_8, - 8), xmm1);
|
||||
}
|
||||
__ addptr(qword_count, 4);
|
||||
__ BIND(L_end);
|
||||
} else {
|
||||
// Copy 32-bytes per iteration
|
||||
__ BIND(L_loop);
|
||||
__ movq(to, Address(end_from, qword_count, Address::times_8, -24));
|
||||
__ movq(Address(end_to, qword_count, Address::times_8, -24), to);
|
||||
__ movq(to, Address(end_from, qword_count, Address::times_8, -16));
|
||||
@ -1311,15 +1342,15 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ movq(Address(end_to, qword_count, Address::times_8, - 8), to);
|
||||
__ movq(to, Address(end_from, qword_count, Address::times_8, - 0));
|
||||
__ movq(Address(end_to, qword_count, Address::times_8, - 0), to);
|
||||
|
||||
__ BIND(L_copy_bytes);
|
||||
__ addptr(qword_count, 4);
|
||||
__ jcc(Assembler::lessEqual, L_loop);
|
||||
}
|
||||
__ BIND(L_copy_32_bytes);
|
||||
__ addptr(qword_count, 4);
|
||||
__ jcc(Assembler::lessEqual, L_loop);
|
||||
__ subptr(qword_count, 4);
|
||||
__ jcc(Assembler::less, L_copy_8_bytes); // Copy trailing qwords
|
||||
}
|
||||
|
||||
|
||||
// Copy big chunks backward
|
||||
//
|
||||
// Inputs:
|
||||
@ -1327,23 +1358,55 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// dest - destination array address
|
||||
// qword_count - 64-bits element count
|
||||
// to - scratch
|
||||
// L_copy_32_bytes - entry label
|
||||
// L_copy_bytes - entry label
|
||||
// L_copy_8_bytes - exit label
|
||||
//
|
||||
void copy_32_bytes_backward(Register from, Register dest,
|
||||
void copy_bytes_backward(Register from, Register dest,
|
||||
Register qword_count, Register to,
|
||||
Label& L_copy_32_bytes, Label& L_copy_8_bytes) {
|
||||
Label& L_copy_bytes, Label& L_copy_8_bytes) {
|
||||
DEBUG_ONLY(__ stop("enter at entry label, not here"));
|
||||
Label L_loop;
|
||||
__ align(OptoLoopAlignment);
|
||||
__ BIND(L_loop);
|
||||
if(UseUnalignedLoadStores) {
|
||||
__ movdqu(xmm0, Address(from, qword_count, Address::times_8, 16));
|
||||
__ movdqu(Address(dest, qword_count, Address::times_8, 16), xmm0);
|
||||
__ movdqu(xmm1, Address(from, qword_count, Address::times_8, 0));
|
||||
__ movdqu(Address(dest, qword_count, Address::times_8, 0), xmm1);
|
||||
if (UseUnalignedLoadStores) {
|
||||
Label L_end;
|
||||
// Copy 64-bytes per iteration
|
||||
__ BIND(L_loop);
|
||||
if (UseAVX >= 2) {
|
||||
__ vmovdqu(xmm0, Address(from, qword_count, Address::times_8, 32));
|
||||
__ vmovdqu(Address(dest, qword_count, Address::times_8, 32), xmm0);
|
||||
__ vmovdqu(xmm1, Address(from, qword_count, Address::times_8, 0));
|
||||
__ vmovdqu(Address(dest, qword_count, Address::times_8, 0), xmm1);
|
||||
} else {
|
||||
__ movdqu(xmm0, Address(from, qword_count, Address::times_8, 48));
|
||||
__ movdqu(Address(dest, qword_count, Address::times_8, 48), xmm0);
|
||||
__ movdqu(xmm1, Address(from, qword_count, Address::times_8, 32));
|
||||
__ movdqu(Address(dest, qword_count, Address::times_8, 32), xmm1);
|
||||
__ movdqu(xmm2, Address(from, qword_count, Address::times_8, 16));
|
||||
__ movdqu(Address(dest, qword_count, Address::times_8, 16), xmm2);
|
||||
__ movdqu(xmm3, Address(from, qword_count, Address::times_8, 0));
|
||||
__ movdqu(Address(dest, qword_count, Address::times_8, 0), xmm3);
|
||||
}
|
||||
__ BIND(L_copy_bytes);
|
||||
__ subptr(qword_count, 8);
|
||||
__ jcc(Assembler::greaterEqual, L_loop);
|
||||
|
||||
__ addptr(qword_count, 4); // add(8) and sub(4)
|
||||
__ jccb(Assembler::less, L_end);
|
||||
// Copy trailing 32 bytes
|
||||
if (UseAVX >= 2) {
|
||||
__ vmovdqu(xmm0, Address(from, qword_count, Address::times_8, 0));
|
||||
__ vmovdqu(Address(dest, qword_count, Address::times_8, 0), xmm0);
|
||||
} else {
|
||||
__ movdqu(xmm0, Address(from, qword_count, Address::times_8, 16));
|
||||
__ movdqu(Address(dest, qword_count, Address::times_8, 16), xmm0);
|
||||
__ movdqu(xmm1, Address(from, qword_count, Address::times_8, 0));
|
||||
__ movdqu(Address(dest, qword_count, Address::times_8, 0), xmm1);
|
||||
}
|
||||
__ subptr(qword_count, 4);
|
||||
__ BIND(L_end);
|
||||
} else {
|
||||
// Copy 32-bytes per iteration
|
||||
__ BIND(L_loop);
|
||||
__ movq(to, Address(from, qword_count, Address::times_8, 24));
|
||||
__ movq(Address(dest, qword_count, Address::times_8, 24), to);
|
||||
__ movq(to, Address(from, qword_count, Address::times_8, 16));
|
||||
@ -1352,10 +1415,11 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ movq(Address(dest, qword_count, Address::times_8, 8), to);
|
||||
__ movq(to, Address(from, qword_count, Address::times_8, 0));
|
||||
__ movq(Address(dest, qword_count, Address::times_8, 0), to);
|
||||
|
||||
__ BIND(L_copy_bytes);
|
||||
__ subptr(qword_count, 4);
|
||||
__ jcc(Assembler::greaterEqual, L_loop);
|
||||
}
|
||||
__ BIND(L_copy_32_bytes);
|
||||
__ subptr(qword_count, 4);
|
||||
__ jcc(Assembler::greaterEqual, L_loop);
|
||||
__ addptr(qword_count, 4);
|
||||
__ jcc(Assembler::greater, L_copy_8_bytes); // Copy trailing qwords
|
||||
}
|
||||
@ -1385,7 +1449,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ pc();
|
||||
|
||||
Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes, L_copy_2_bytes;
|
||||
Label L_copy_bytes, L_copy_8_bytes, L_copy_4_bytes, L_copy_2_bytes;
|
||||
Label L_copy_byte, L_exit;
|
||||
const Register from = rdi; // source array address
|
||||
const Register to = rsi; // destination array address
|
||||
@ -1417,7 +1481,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ lea(end_from, Address(from, qword_count, Address::times_8, -8));
|
||||
__ lea(end_to, Address(to, qword_count, Address::times_8, -8));
|
||||
__ negptr(qword_count); // make the count negative
|
||||
__ jmp(L_copy_32_bytes);
|
||||
__ jmp(L_copy_bytes);
|
||||
|
||||
// Copy trailing qwords
|
||||
__ BIND(L_copy_8_bytes);
|
||||
@ -1460,8 +1524,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ ret(0);
|
||||
|
||||
// Copy in 32-bytes chunks
|
||||
copy_32_bytes_forward(end_from, end_to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes);
|
||||
// Copy in multi-bytes chunks
|
||||
copy_bytes_forward(end_from, end_to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
|
||||
__ jmp(L_copy_4_bytes);
|
||||
|
||||
return start;
|
||||
@ -1488,7 +1552,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ pc();
|
||||
|
||||
Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes, L_copy_2_bytes;
|
||||
Label L_copy_bytes, L_copy_8_bytes, L_copy_4_bytes, L_copy_2_bytes;
|
||||
const Register from = rdi; // source array address
|
||||
const Register to = rsi; // destination array address
|
||||
const Register count = rdx; // elements count
|
||||
@ -1531,10 +1595,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// Check for and copy trailing dword
|
||||
__ BIND(L_copy_4_bytes);
|
||||
__ testl(byte_count, 4);
|
||||
__ jcc(Assembler::zero, L_copy_32_bytes);
|
||||
__ jcc(Assembler::zero, L_copy_bytes);
|
||||
__ movl(rax, Address(from, qword_count, Address::times_8));
|
||||
__ movl(Address(to, qword_count, Address::times_8), rax);
|
||||
__ jmp(L_copy_32_bytes);
|
||||
__ jmp(L_copy_bytes);
|
||||
|
||||
// Copy trailing qwords
|
||||
__ BIND(L_copy_8_bytes);
|
||||
@ -1549,8 +1613,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ ret(0);
|
||||
|
||||
// Copy in 32-bytes chunks
|
||||
copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes);
|
||||
// Copy in multi-bytes chunks
|
||||
copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
|
||||
|
||||
restore_arg_regs();
|
||||
inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free
|
||||
@ -1585,7 +1649,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ pc();
|
||||
|
||||
Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes,L_copy_2_bytes,L_exit;
|
||||
Label L_copy_bytes, L_copy_8_bytes, L_copy_4_bytes,L_copy_2_bytes,L_exit;
|
||||
const Register from = rdi; // source array address
|
||||
const Register to = rsi; // destination array address
|
||||
const Register count = rdx; // elements count
|
||||
@ -1616,7 +1680,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ lea(end_from, Address(from, qword_count, Address::times_8, -8));
|
||||
__ lea(end_to, Address(to, qword_count, Address::times_8, -8));
|
||||
__ negptr(qword_count);
|
||||
__ jmp(L_copy_32_bytes);
|
||||
__ jmp(L_copy_bytes);
|
||||
|
||||
// Copy trailing qwords
|
||||
__ BIND(L_copy_8_bytes);
|
||||
@ -1652,8 +1716,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ ret(0);
|
||||
|
||||
// Copy in 32-bytes chunks
|
||||
copy_32_bytes_forward(end_from, end_to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes);
|
||||
// Copy in multi-bytes chunks
|
||||
copy_bytes_forward(end_from, end_to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
|
||||
__ jmp(L_copy_4_bytes);
|
||||
|
||||
return start;
|
||||
@ -1700,7 +1764,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ pc();
|
||||
|
||||
Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes;
|
||||
Label L_copy_bytes, L_copy_8_bytes, L_copy_4_bytes;
|
||||
const Register from = rdi; // source array address
|
||||
const Register to = rsi; // destination array address
|
||||
const Register count = rdx; // elements count
|
||||
@ -1735,10 +1799,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// Check for and copy trailing dword
|
||||
__ BIND(L_copy_4_bytes);
|
||||
__ testl(word_count, 2);
|
||||
__ jcc(Assembler::zero, L_copy_32_bytes);
|
||||
__ jcc(Assembler::zero, L_copy_bytes);
|
||||
__ movl(rax, Address(from, qword_count, Address::times_8));
|
||||
__ movl(Address(to, qword_count, Address::times_8), rax);
|
||||
__ jmp(L_copy_32_bytes);
|
||||
__ jmp(L_copy_bytes);
|
||||
|
||||
// Copy trailing qwords
|
||||
__ BIND(L_copy_8_bytes);
|
||||
@ -1753,8 +1817,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ ret(0);
|
||||
|
||||
// Copy in 32-bytes chunks
|
||||
copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes);
|
||||
// Copy in multi-bytes chunks
|
||||
copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
|
||||
|
||||
restore_arg_regs();
|
||||
inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free
|
||||
@ -1790,7 +1854,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ pc();
|
||||
|
||||
Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes, L_exit;
|
||||
Label L_copy_bytes, L_copy_8_bytes, L_copy_4_bytes, L_exit;
|
||||
const Register from = rdi; // source array address
|
||||
const Register to = rsi; // destination array address
|
||||
const Register count = rdx; // elements count
|
||||
@ -1826,7 +1890,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ lea(end_from, Address(from, qword_count, Address::times_8, -8));
|
||||
__ lea(end_to, Address(to, qword_count, Address::times_8, -8));
|
||||
__ negptr(qword_count);
|
||||
__ jmp(L_copy_32_bytes);
|
||||
__ jmp(L_copy_bytes);
|
||||
|
||||
// Copy trailing qwords
|
||||
__ BIND(L_copy_8_bytes);
|
||||
@ -1853,8 +1917,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ ret(0);
|
||||
|
||||
// Copy 32-bytes chunks
|
||||
copy_32_bytes_forward(end_from, end_to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes);
|
||||
// Copy in multi-bytes chunks
|
||||
copy_bytes_forward(end_from, end_to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
|
||||
__ jmp(L_copy_4_bytes);
|
||||
|
||||
return start;
|
||||
@ -1882,7 +1946,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ pc();
|
||||
|
||||
Label L_copy_32_bytes, L_copy_8_bytes, L_copy_2_bytes, L_exit;
|
||||
Label L_copy_bytes, L_copy_8_bytes, L_copy_2_bytes, L_exit;
|
||||
const Register from = rdi; // source array address
|
||||
const Register to = rsi; // destination array address
|
||||
const Register count = rdx; // elements count
|
||||
@ -1916,10 +1980,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
// Check for and copy trailing dword
|
||||
__ testl(dword_count, 1);
|
||||
__ jcc(Assembler::zero, L_copy_32_bytes);
|
||||
__ jcc(Assembler::zero, L_copy_bytes);
|
||||
__ movl(rax, Address(from, dword_count, Address::times_4, -4));
|
||||
__ movl(Address(to, dword_count, Address::times_4, -4), rax);
|
||||
__ jmp(L_copy_32_bytes);
|
||||
__ jmp(L_copy_bytes);
|
||||
|
||||
// Copy trailing qwords
|
||||
__ BIND(L_copy_8_bytes);
|
||||
@ -1937,8 +2001,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ ret(0);
|
||||
|
||||
// Copy in 32-bytes chunks
|
||||
copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes);
|
||||
// Copy in multi-bytes chunks
|
||||
copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
|
||||
|
||||
__ bind(L_exit);
|
||||
if (is_oop) {
|
||||
@ -1976,7 +2040,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ pc();
|
||||
|
||||
Label L_copy_32_bytes, L_copy_8_bytes, L_exit;
|
||||
Label L_copy_bytes, L_copy_8_bytes, L_exit;
|
||||
const Register from = rdi; // source array address
|
||||
const Register to = rsi; // destination array address
|
||||
const Register qword_count = rdx; // elements count
|
||||
@ -2008,7 +2072,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ lea(end_from, Address(from, qword_count, Address::times_8, -8));
|
||||
__ lea(end_to, Address(to, qword_count, Address::times_8, -8));
|
||||
__ negptr(qword_count);
|
||||
__ jmp(L_copy_32_bytes);
|
||||
__ jmp(L_copy_bytes);
|
||||
|
||||
// Copy trailing qwords
|
||||
__ BIND(L_copy_8_bytes);
|
||||
@ -2027,8 +2091,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ ret(0);
|
||||
}
|
||||
|
||||
// Copy 64-byte chunks
|
||||
copy_32_bytes_forward(end_from, end_to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes);
|
||||
// Copy in multi-bytes chunks
|
||||
copy_bytes_forward(end_from, end_to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
|
||||
|
||||
if (is_oop) {
|
||||
__ BIND(L_exit);
|
||||
@ -2065,7 +2129,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ pc();
|
||||
|
||||
Label L_copy_32_bytes, L_copy_8_bytes, L_exit;
|
||||
Label L_copy_bytes, L_copy_8_bytes, L_exit;
|
||||
const Register from = rdi; // source array address
|
||||
const Register to = rsi; // destination array address
|
||||
const Register qword_count = rdx; // elements count
|
||||
@ -2091,7 +2155,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
gen_write_ref_array_pre_barrier(to, saved_count, dest_uninitialized);
|
||||
}
|
||||
|
||||
__ jmp(L_copy_32_bytes);
|
||||
__ jmp(L_copy_bytes);
|
||||
|
||||
// Copy trailing qwords
|
||||
__ BIND(L_copy_8_bytes);
|
||||
@ -2110,8 +2174,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ ret(0);
|
||||
}
|
||||
|
||||
// Copy in 32-bytes chunks
|
||||
copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes);
|
||||
// Copy in multi-bytes chunks
|
||||
copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
|
||||
|
||||
if (is_oop) {
|
||||
__ BIND(L_exit);
|
||||
|
@ -429,7 +429,7 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
|
||||
char buf[256];
|
||||
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
cores_per_cpu(), threads_per_core(),
|
||||
cpu_family(), _model, _stepping,
|
||||
(supports_cmov() ? ", cmov" : ""),
|
||||
@ -446,6 +446,7 @@ void VM_Version::get_processor_features() {
|
||||
(supports_avx() ? ", avx" : ""),
|
||||
(supports_avx2() ? ", avx2" : ""),
|
||||
(supports_aes() ? ", aes" : ""),
|
||||
(supports_erms() ? ", erms" : ""),
|
||||
(supports_mmx_ext() ? ", mmxext" : ""),
|
||||
(supports_3dnow_prefetch() ? ", 3dnowpref" : ""),
|
||||
(supports_lzcnt() ? ", lzcnt": ""),
|
||||
@ -671,6 +672,16 @@ void VM_Version::get_processor_features() {
|
||||
FLAG_SET_DEFAULT(UsePopCountInstruction, false);
|
||||
}
|
||||
|
||||
// Use fast-string operations if available.
|
||||
if (supports_erms()) {
|
||||
if (FLAG_IS_DEFAULT(UseFastStosb)) {
|
||||
UseFastStosb = true;
|
||||
}
|
||||
} else if (UseFastStosb) {
|
||||
warning("fast-string operations are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseFastStosb, false);
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
if (FLAG_IS_DEFAULT(AlignVector)) {
|
||||
// Modern processors allow misaligned memory operations for vectors.
|
||||
|
@ -204,7 +204,8 @@ public:
|
||||
avx2 : 1,
|
||||
: 2,
|
||||
bmi2 : 1,
|
||||
: 23;
|
||||
erms : 1,
|
||||
: 22;
|
||||
} bits;
|
||||
};
|
||||
|
||||
@ -247,7 +248,8 @@ protected:
|
||||
CPU_TSCINV = (1 << 16),
|
||||
CPU_AVX = (1 << 17),
|
||||
CPU_AVX2 = (1 << 18),
|
||||
CPU_AES = (1 << 19)
|
||||
CPU_AES = (1 << 19),
|
||||
CPU_ERMS = (1 << 20) // enhanced 'rep movsb/stosb' instructions
|
||||
} cpuFeatureFlags;
|
||||
|
||||
enum {
|
||||
@ -425,6 +427,8 @@ protected:
|
||||
result |= CPU_TSCINV;
|
||||
if (_cpuid_info.std_cpuid1_ecx.bits.aes != 0)
|
||||
result |= CPU_AES;
|
||||
if (_cpuid_info.sef_cpuid7_ebx.bits.erms != 0)
|
||||
result |= CPU_ERMS;
|
||||
|
||||
// AMD features.
|
||||
if (is_amd()) {
|
||||
@ -489,7 +493,7 @@ public:
|
||||
return (_cpuid_info.std_max_function >= 0xB) &&
|
||||
// eax[4:0] | ebx[0:15] == 0 indicates invalid topology level.
|
||||
// Some cpus have max cpuid >= 0xB but do not support processor topology.
|
||||
((_cpuid_info.tpl_cpuidB0_eax & 0x1f | _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus) != 0);
|
||||
(((_cpuid_info.tpl_cpuidB0_eax & 0x1f) | _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus) != 0);
|
||||
}
|
||||
|
||||
static uint cores_per_cpu() {
|
||||
@ -550,6 +554,7 @@ public:
|
||||
static bool supports_avx2() { return (_cpuFeatures & CPU_AVX2) != 0; }
|
||||
static bool supports_tsc() { return (_cpuFeatures & CPU_TSC) != 0; }
|
||||
static bool supports_aes() { return (_cpuFeatures & CPU_AES) != 0; }
|
||||
static bool supports_erms() { return (_cpuFeatures & CPU_ERMS) != 0; }
|
||||
|
||||
// Intel features
|
||||
static bool is_intel_family_core() { return is_intel() &&
|
||||
|
@ -11572,15 +11572,28 @@ instruct MoveL2D_reg_reg_sse(regD dst, eRegL src, regD tmp) %{
|
||||
// =======================================================================
|
||||
// fast clearing of an array
|
||||
instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{
|
||||
predicate(!UseFastStosb);
|
||||
match(Set dummy (ClearArray cnt base));
|
||||
effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr);
|
||||
format %{ "SHL ECX,1\t# Convert doublewords to words\n\t"
|
||||
"XOR EAX,EAX\n\t"
|
||||
format %{ "XOR EAX,EAX\t# ClearArray:\n\t"
|
||||
"SHL ECX,1\t# Convert doublewords to words\n\t"
|
||||
"REP STOS\t# store EAX into [EDI++] while ECX--" %}
|
||||
opcode(0,0x4);
|
||||
ins_encode( Opcode(0xD1), RegOpc(ECX),
|
||||
OpcRegReg(0x33,EAX,EAX),
|
||||
Opcode(0xF3), Opcode(0xAB) );
|
||||
ins_encode %{
|
||||
__ clear_mem($base$$Register, $cnt$$Register, $zero$$Register);
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
instruct rep_fast_stosb(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{
|
||||
predicate(UseFastStosb);
|
||||
match(Set dummy (ClearArray cnt base));
|
||||
effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr);
|
||||
format %{ "XOR EAX,EAX\t# ClearArray:\n\t"
|
||||
"SHL ECX,3\t# Convert doublewords to bytes\n\t"
|
||||
"REP STOSB\t# store EAX into [EDI++] while ECX--" %}
|
||||
ins_encode %{
|
||||
__ clear_mem($base$$Register, $cnt$$Register, $zero$$Register);
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
|
@ -10374,16 +10374,33 @@ instruct MoveL2D_reg_reg(regD dst, rRegL src) %{
|
||||
instruct rep_stos(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy,
|
||||
rFlagsReg cr)
|
||||
%{
|
||||
predicate(!UseFastStosb);
|
||||
match(Set dummy (ClearArray cnt base));
|
||||
effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr);
|
||||
|
||||
format %{ "xorl rax, rax\t# ClearArray:\n\t"
|
||||
"rep stosq\t# Store rax to *rdi++ while rcx--" %}
|
||||
ins_encode(opc_reg_reg(0x33, RAX, RAX), // xorl %eax, %eax
|
||||
Opcode(0xF3), Opcode(0x48), Opcode(0xAB)); // rep REX_W stos
|
||||
format %{ "xorq rax, rax\t# ClearArray:\n\t"
|
||||
"rep stosq\t# Store rax to *rdi++ while rcx--" %}
|
||||
ins_encode %{
|
||||
__ clear_mem($base$$Register, $cnt$$Register, $zero$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct rep_fast_stosb(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy,
|
||||
rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseFastStosb);
|
||||
match(Set dummy (ClearArray cnt base));
|
||||
effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr);
|
||||
format %{ "xorq rax, rax\t# ClearArray:\n\t"
|
||||
"shlq rcx,3\t# Convert doublewords to bytes\n\t"
|
||||
"rep stosb\t# Store rax to *rdi++ while rcx--" %}
|
||||
ins_encode %{
|
||||
__ clear_mem($base$$Register, $cnt$$Register, $zero$$Register);
|
||||
%}
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
instruct string_compare(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
|
||||
rax_RegI result, regD tmp1, rFlagsReg cr)
|
||||
%{
|
||||
|
@ -298,12 +298,12 @@ void os::init_system_properties_values() {
|
||||
|
||||
// The next steps are taken in the product version:
|
||||
//
|
||||
// Obtain the JAVA_HOME value from the location of libjvm[_g].so.
|
||||
// Obtain the JAVA_HOME value from the location of libjvm.so.
|
||||
// This library should be located at:
|
||||
// <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm[_g].so.
|
||||
// <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm.so.
|
||||
//
|
||||
// If "/jre/lib/" appears at the right place in the path, then we
|
||||
// assume libjvm[_g].so is installed in a JDK and we use this path.
|
||||
// assume libjvm.so is installed in a JDK and we use this path.
|
||||
//
|
||||
// Otherwise exit with message: "Could not create the Java virtual machine."
|
||||
//
|
||||
@ -313,9 +313,9 @@ void os::init_system_properties_values() {
|
||||
// instead of exit check for $JAVA_HOME environment variable.
|
||||
//
|
||||
// If it is defined and we are able to locate $JAVA_HOME/jre/lib/<arch>,
|
||||
// then we append a fake suffix "hotspot/libjvm[_g].so" to this path so
|
||||
// it looks like libjvm[_g].so is installed there
|
||||
// <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm[_g].so.
|
||||
// then we append a fake suffix "hotspot/libjvm.so" to this path so
|
||||
// it looks like libjvm.so is installed there
|
||||
// <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm.so.
|
||||
//
|
||||
// Otherwise exit.
|
||||
//
|
||||
@ -1228,7 +1228,7 @@ const char* os::get_current_directory(char *buf, int buflen) {
|
||||
return getcwd(buf, buflen);
|
||||
}
|
||||
|
||||
// check if addr is inside libjvm[_g].so
|
||||
// check if addr is inside libjvm.so
|
||||
bool os::address_is_in_vm(address addr) {
|
||||
static address libjvm_base_addr;
|
||||
Dl_info dlinfo;
|
||||
@ -1689,7 +1689,7 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) {
|
||||
|
||||
static char saved_jvm_path[MAXPATHLEN] = {0};
|
||||
|
||||
// Find the full path to the current module, libjvm or libjvm_g
|
||||
// Find the full path to the current module, libjvm
|
||||
void os::jvm_path(char *buf, jint buflen) {
|
||||
// Error checking.
|
||||
if (buflen < MAXPATHLEN) {
|
||||
@ -1732,10 +1732,9 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
char* jrelib_p;
|
||||
int len;
|
||||
|
||||
// Check the current module name "libjvm" or "libjvm_g".
|
||||
// Check the current module name "libjvm"
|
||||
p = strrchr(buf, '/');
|
||||
assert(strstr(p, "/libjvm") == p, "invalid library name");
|
||||
p = strstr(p, "_g") ? "_g" : "";
|
||||
|
||||
rp = realpath(java_home_var, buf);
|
||||
if (rp == NULL)
|
||||
@ -1764,11 +1763,9 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
// to complete the path to JVM being overridden. Otherwise fallback
|
||||
// to the path to the current library.
|
||||
if (0 == access(buf, F_OK)) {
|
||||
// Use current module name "libjvm[_g]" instead of
|
||||
// "libjvm"debug_only("_g")"" since for fastdebug version
|
||||
// we should have "libjvm" but debug_only("_g") adds "_g"!
|
||||
// Use current module name "libjvm"
|
||||
len = strlen(buf);
|
||||
snprintf(buf + len, buflen-len, "/libjvm%s%s", p, JNI_LIB_SUFFIX);
|
||||
snprintf(buf + len, buflen-len, "/libjvm%s", JNI_LIB_SUFFIX);
|
||||
} else {
|
||||
// Fall back to path of current library
|
||||
rp = realpath(dli_fname, buf);
|
||||
|
@ -321,12 +321,12 @@ void os::init_system_properties_values() {
|
||||
|
||||
// The next steps are taken in the product version:
|
||||
//
|
||||
// Obtain the JAVA_HOME value from the location of libjvm[_g].so.
|
||||
// Obtain the JAVA_HOME value from the location of libjvm.so.
|
||||
// This library should be located at:
|
||||
// <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm[_g].so.
|
||||
// <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm.so.
|
||||
//
|
||||
// If "/jre/lib/" appears at the right place in the path, then we
|
||||
// assume libjvm[_g].so is installed in a JDK and we use this path.
|
||||
// assume libjvm.so is installed in a JDK and we use this path.
|
||||
//
|
||||
// Otherwise exit with message: "Could not create the Java virtual machine."
|
||||
//
|
||||
@ -336,9 +336,9 @@ void os::init_system_properties_values() {
|
||||
// instead of exit check for $JAVA_HOME environment variable.
|
||||
//
|
||||
// If it is defined and we are able to locate $JAVA_HOME/jre/lib/<arch>,
|
||||
// then we append a fake suffix "hotspot/libjvm[_g].so" to this path so
|
||||
// it looks like libjvm[_g].so is installed there
|
||||
// <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm[_g].so.
|
||||
// then we append a fake suffix "hotspot/libjvm.so" to this path so
|
||||
// it looks like libjvm.so is installed there
|
||||
// <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm.so.
|
||||
//
|
||||
// Otherwise exit.
|
||||
//
|
||||
@ -1679,7 +1679,7 @@ const char* os::get_current_directory(char *buf, int buflen) {
|
||||
return getcwd(buf, buflen);
|
||||
}
|
||||
|
||||
// check if addr is inside libjvm[_g].so
|
||||
// check if addr is inside libjvm.so
|
||||
bool os::address_is_in_vm(address addr) {
|
||||
static address libjvm_base_addr;
|
||||
Dl_info dlinfo;
|
||||
@ -2180,7 +2180,7 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) {
|
||||
|
||||
static char saved_jvm_path[MAXPATHLEN] = {0};
|
||||
|
||||
// Find the full path to the current module, libjvm.so or libjvm_g.so
|
||||
// Find the full path to the current module, libjvm.so
|
||||
void os::jvm_path(char *buf, jint buflen) {
|
||||
// Error checking.
|
||||
if (buflen < MAXPATHLEN) {
|
||||
@ -2223,10 +2223,9 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
char* jrelib_p;
|
||||
int len;
|
||||
|
||||
// Check the current module name "libjvm.so" or "libjvm_g.so".
|
||||
// Check the current module name "libjvm.so".
|
||||
p = strrchr(buf, '/');
|
||||
assert(strstr(p, "/libjvm") == p, "invalid library name");
|
||||
p = strstr(p, "_g") ? "_g" : "";
|
||||
|
||||
rp = realpath(java_home_var, buf);
|
||||
if (rp == NULL)
|
||||
@ -2242,11 +2241,9 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
}
|
||||
|
||||
if (0 == access(buf, F_OK)) {
|
||||
// Use current module name "libjvm[_g].so" instead of
|
||||
// "libjvm"debug_only("_g")".so" since for fastdebug version
|
||||
// we should have "libjvm.so" but debug_only("_g") adds "_g"!
|
||||
// Use current module name "libjvm.so"
|
||||
len = strlen(buf);
|
||||
snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
|
||||
snprintf(buf + len, buflen-len, "/hotspot/libjvm.so");
|
||||
} else {
|
||||
// Go back to path of .so
|
||||
rp = realpath(dli_fname, buf);
|
||||
|
@ -734,12 +734,12 @@ void os::init_system_properties_values() {
|
||||
|
||||
// The next steps are taken in the product version:
|
||||
//
|
||||
// Obtain the JAVA_HOME value from the location of libjvm[_g].so.
|
||||
// Obtain the JAVA_HOME value from the location of libjvm.so.
|
||||
// This library should be located at:
|
||||
// <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm[_g].so.
|
||||
// <JAVA_HOME>/jre/lib/<arch>/{client|server}/libjvm.so.
|
||||
//
|
||||
// If "/jre/lib/" appears at the right place in the path, then we
|
||||
// assume libjvm[_g].so is installed in a JDK and we use this path.
|
||||
// assume libjvm.so is installed in a JDK and we use this path.
|
||||
//
|
||||
// Otherwise exit with message: "Could not create the Java virtual machine."
|
||||
//
|
||||
@ -749,9 +749,9 @@ void os::init_system_properties_values() {
|
||||
// instead of exit check for $JAVA_HOME environment variable.
|
||||
//
|
||||
// If it is defined and we are able to locate $JAVA_HOME/jre/lib/<arch>,
|
||||
// then we append a fake suffix "hotspot/libjvm[_g].so" to this path so
|
||||
// it looks like libjvm[_g].so is installed there
|
||||
// <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm[_g].so.
|
||||
// then we append a fake suffix "hotspot/libjvm.so" to this path so
|
||||
// it looks like libjvm.so is installed there
|
||||
// <JAVA_HOME>/jre/lib/<arch>/hotspot/libjvm.so.
|
||||
//
|
||||
// Otherwise exit.
|
||||
//
|
||||
@ -1934,7 +1934,7 @@ const char* os::get_current_directory(char *buf, int buflen) {
|
||||
return getcwd(buf, buflen);
|
||||
}
|
||||
|
||||
// check if addr is inside libjvm[_g].so
|
||||
// check if addr is inside libjvm.so
|
||||
bool os::address_is_in_vm(address addr) {
|
||||
static address libjvm_base_addr;
|
||||
Dl_info dlinfo;
|
||||
@ -2474,7 +2474,7 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) {
|
||||
|
||||
static char saved_jvm_path[MAXPATHLEN] = { 0 };
|
||||
|
||||
// Find the full path to the current module, libjvm.so or libjvm_g.so
|
||||
// Find the full path to the current module, libjvm.so
|
||||
void os::jvm_path(char *buf, jint buflen) {
|
||||
// Error checking.
|
||||
if (buflen < MAXPATHLEN) {
|
||||
@ -2522,10 +2522,9 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
strcpy(cpu_arch, "amd64");
|
||||
}
|
||||
#endif
|
||||
// Check the current module name "libjvm.so" or "libjvm_g.so".
|
||||
// Check the current module name "libjvm.so".
|
||||
p = strrchr(buf, '/');
|
||||
assert(strstr(p, "/libjvm") == p, "invalid library name");
|
||||
p = strstr(p, "_g") ? "_g" : "";
|
||||
|
||||
realpath(java_home_var, buf);
|
||||
// determine if this is a legacy image or modules image
|
||||
@ -2538,11 +2537,9 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||
}
|
||||
|
||||
if (0 == access(buf, F_OK)) {
|
||||
// Use current module name "libjvm[_g].so" instead of
|
||||
// "libjvm"debug_only("_g")".so" since for fastdebug version
|
||||
// we should have "libjvm.so" but debug_only("_g") adds "_g"!
|
||||
// Use current module name "libjvm.so"
|
||||
len = strlen(buf);
|
||||
snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
|
||||
snprintf(buf + len, buflen-len, "/hotspot/libjvm.so");
|
||||
} else {
|
||||
// Go back to path of .so
|
||||
realpath((char *)dlinfo.dli_fname, buf);
|
||||
|
@ -182,7 +182,7 @@ void os::init_system_properties_values() {
|
||||
|
||||
if (!getenv("_ALT_JAVA_HOME_DIR", home_dir, MAX_PATH)) {
|
||||
os::jvm_path(home_dir, sizeof(home_dir));
|
||||
// Found the full path to jvm[_g].dll.
|
||||
// Found the full path to jvm.dll.
|
||||
// Now cut the path to <java_home>/jre if we can.
|
||||
*(strrchr(home_dir, '\\')) = '\0'; /* get rid of \jvm.dll */
|
||||
pslash = strrchr(home_dir, '\\');
|
||||
@ -1715,7 +1715,7 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) {
|
||||
|
||||
static char saved_jvm_path[MAX_PATH] = {0};
|
||||
|
||||
// Find the full path to the current module, jvm.dll or jvm_g.dll
|
||||
// Find the full path to the current module, jvm.dll
|
||||
void os::jvm_path(char *buf, jint buflen) {
|
||||
// Error checking.
|
||||
if (buflen < MAX_PATH) {
|
||||
|
@ -36,7 +36,7 @@ public class ProjectCreator {
|
||||
+ "into .dsp file, substituting for path given in "
|
||||
+ "-sourceBase. Example: HotSpotWorkSpace>");
|
||||
System.err.println(" -dllLoc <path to directory in which to put "
|
||||
+ "jvm.dll and jvm_g.dll; no trailing slash>");
|
||||
+ "jvm.dll; no trailing slash>");
|
||||
System.err.println(" If any of the above are specified, "
|
||||
+ "they must all be.");
|
||||
System.err.println(" Additional, optional arguments, which can be "
|
||||
|
@ -216,8 +216,6 @@ class AbstractAssembler : public ResourceObj {
|
||||
bool isByte(int x) const { return 0 <= x && x < 0x100; }
|
||||
bool isShiftCount(int x) const { return 0 <= x && x < 32; }
|
||||
|
||||
void emit_long(jint x) { emit_int32(x); } // deprecated
|
||||
|
||||
// Instruction boundaries (required when emitting relocatable values).
|
||||
class InstructionMark: public StackObj {
|
||||
private:
|
||||
|
@ -2259,7 +2259,7 @@ class LIR_OpVisitState: public StackObj {
|
||||
typedef enum { inputMode, firstMode = inputMode, tempMode, outputMode, numModes, invalidMode = -1 } OprMode;
|
||||
|
||||
enum {
|
||||
maxNumberOfOperands = 16,
|
||||
maxNumberOfOperands = 20,
|
||||
maxNumberOfInfos = 4
|
||||
};
|
||||
|
||||
|
@ -906,6 +906,7 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
|
||||
bool* is_synthetic_addr,
|
||||
u2* generic_signature_index_addr,
|
||||
AnnotationArray** field_annotations,
|
||||
AnnotationArray** field_type_annotations,
|
||||
ClassFileParser::FieldAnnotationCollector* parsed_annotations,
|
||||
TRAPS) {
|
||||
ClassFileStream* cfs = stream();
|
||||
@ -917,6 +918,10 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
|
||||
int runtime_visible_annotations_length = 0;
|
||||
u1* runtime_invisible_annotations = NULL;
|
||||
int runtime_invisible_annotations_length = 0;
|
||||
u1* runtime_visible_type_annotations = NULL;
|
||||
int runtime_visible_type_annotations_length = 0;
|
||||
u1* runtime_invisible_type_annotations = NULL;
|
||||
int runtime_invisible_type_annotations_length = 0;
|
||||
while (attributes_count--) {
|
||||
cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length
|
||||
u2 attribute_name_index = cfs->get_u2_fast();
|
||||
@ -971,6 +976,16 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
|
||||
runtime_invisible_annotations = cfs->get_u1_buffer();
|
||||
assert(runtime_invisible_annotations != NULL, "null invisible annotations");
|
||||
cfs->skip_u1(runtime_invisible_annotations_length, CHECK);
|
||||
} else if (attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) {
|
||||
runtime_visible_type_annotations_length = attribute_length;
|
||||
runtime_visible_type_annotations = cfs->get_u1_buffer();
|
||||
assert(runtime_visible_type_annotations != NULL, "null visible type annotations");
|
||||
cfs->skip_u1(runtime_visible_type_annotations_length, CHECK);
|
||||
} else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) {
|
||||
runtime_invisible_type_annotations_length = attribute_length;
|
||||
runtime_invisible_type_annotations = cfs->get_u1_buffer();
|
||||
assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations");
|
||||
cfs->skip_u1(runtime_invisible_type_annotations_length, CHECK);
|
||||
} else {
|
||||
cfs->skip_u1(attribute_length, CHECK); // Skip unknown attributes
|
||||
}
|
||||
@ -988,6 +1003,12 @@ void ClassFileParser::parse_field_attributes(ClassLoaderData* loader_data,
|
||||
runtime_invisible_annotations,
|
||||
runtime_invisible_annotations_length,
|
||||
CHECK);
|
||||
*field_type_annotations = assemble_annotations(loader_data,
|
||||
runtime_visible_type_annotations,
|
||||
runtime_visible_type_annotations_length,
|
||||
runtime_invisible_type_annotations,
|
||||
runtime_invisible_type_annotations_length,
|
||||
CHECK);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1084,6 +1105,7 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
|
||||
bool is_interface,
|
||||
FieldAllocationCount *fac,
|
||||
Array<AnnotationArray*>** fields_annotations,
|
||||
Array<AnnotationArray*>** fields_type_annotations,
|
||||
u2* java_fields_count_ptr, TRAPS) {
|
||||
ClassFileStream* cfs = stream();
|
||||
cfs->guarantee_more(2, CHECK_NULL); // length
|
||||
@ -1119,6 +1141,7 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
|
||||
THREAD, u2, total_fields * (FieldInfo::field_slots + 1));
|
||||
|
||||
AnnotationArray* field_annotations = NULL;
|
||||
AnnotationArray* field_type_annotations = NULL;
|
||||
// The generic signature slots start after all other fields' data.
|
||||
int generic_signature_slot = total_fields * FieldInfo::field_slots;
|
||||
int num_generic_signature = 0;
|
||||
@ -1160,7 +1183,7 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
|
||||
cp, attributes_count, is_static, signature_index,
|
||||
&constantvalue_index, &is_synthetic,
|
||||
&generic_signature_index, &field_annotations,
|
||||
&parsed_annotations,
|
||||
&field_type_annotations, &parsed_annotations,
|
||||
CHECK_NULL);
|
||||
if (field_annotations != NULL) {
|
||||
if (*fields_annotations == NULL) {
|
||||
@ -1170,6 +1193,14 @@ Array<u2>* ClassFileParser::parse_fields(ClassLoaderData* loader_data,
|
||||
}
|
||||
(*fields_annotations)->at_put(n, field_annotations);
|
||||
}
|
||||
if (field_type_annotations != NULL) {
|
||||
if (*fields_type_annotations == NULL) {
|
||||
*fields_type_annotations = MetadataFactory::new_array<AnnotationArray*>(
|
||||
loader_data, length, NULL,
|
||||
CHECK_NULL);
|
||||
}
|
||||
(*fields_type_annotations)->at_put(n, field_type_annotations);
|
||||
}
|
||||
if (is_synthetic) {
|
||||
access_flags.set_is_synthetic();
|
||||
}
|
||||
@ -1831,6 +1862,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
AnnotationArray** method_annotations,
|
||||
AnnotationArray** method_parameter_annotations,
|
||||
AnnotationArray** method_default_annotations,
|
||||
AnnotationArray** method_type_annotations,
|
||||
TRAPS) {
|
||||
ClassFileStream* cfs = stream();
|
||||
methodHandle nullHandle;
|
||||
@ -1903,6 +1935,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
u2** localvariable_table_start;
|
||||
u2* localvariable_type_table_length;
|
||||
u2** localvariable_type_table_start;
|
||||
u2 method_parameters_length = 0;
|
||||
u1* method_parameters_data = NULL;
|
||||
bool parsed_code_attribute = false;
|
||||
bool parsed_checked_exceptions_attribute = false;
|
||||
bool parsed_stackmap_attribute = false;
|
||||
@ -1918,6 +1952,10 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
int runtime_visible_parameter_annotations_length = 0;
|
||||
u1* runtime_invisible_parameter_annotations = NULL;
|
||||
int runtime_invisible_parameter_annotations_length = 0;
|
||||
u1* runtime_visible_type_annotations = NULL;
|
||||
int runtime_visible_type_annotations_length = 0;
|
||||
u1* runtime_invisible_type_annotations = NULL;
|
||||
int runtime_invisible_type_annotations_length = 0;
|
||||
u1* annotation_default = NULL;
|
||||
int annotation_default_length = 0;
|
||||
|
||||
@ -2108,6 +2146,14 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
parse_checked_exceptions(&checked_exceptions_length,
|
||||
method_attribute_length,
|
||||
cp, CHECK_(nullHandle));
|
||||
} else if (method_attribute_name == vmSymbols::tag_method_parameters()) {
|
||||
method_parameters_length = cfs->get_u1_fast();
|
||||
method_parameters_data = cfs->get_u1_buffer();
|
||||
cfs->skip_u2_fast(method_parameters_length);
|
||||
cfs->skip_u4_fast(method_parameters_length);
|
||||
// ignore this attribute if it cannot be reflected
|
||||
if (!SystemDictionary::Parameter_klass_loaded())
|
||||
method_parameters_length = 0;
|
||||
} else if (method_attribute_name == vmSymbols::tag_synthetic()) {
|
||||
if (method_attribute_length != 0) {
|
||||
classfile_parse_error(
|
||||
@ -2159,6 +2205,17 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
annotation_default = cfs->get_u1_buffer();
|
||||
assert(annotation_default != NULL, "null annotation default");
|
||||
cfs->skip_u1(annotation_default_length, CHECK_(nullHandle));
|
||||
} else if (method_attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) {
|
||||
runtime_visible_type_annotations_length = method_attribute_length;
|
||||
runtime_visible_type_annotations = cfs->get_u1_buffer();
|
||||
assert(runtime_visible_type_annotations != NULL, "null visible type annotations");
|
||||
// No need for the VM to parse Type annotations
|
||||
cfs->skip_u1(runtime_visible_type_annotations_length, CHECK_(nullHandle));
|
||||
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) {
|
||||
runtime_invisible_type_annotations_length = method_attribute_length;
|
||||
runtime_invisible_type_annotations = cfs->get_u1_buffer();
|
||||
assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations");
|
||||
cfs->skip_u1(runtime_invisible_type_annotations_length, CHECK_(nullHandle));
|
||||
} else {
|
||||
// Skip unknown attributes
|
||||
cfs->skip_u1(method_attribute_length, CHECK_(nullHandle));
|
||||
@ -2184,7 +2241,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
Method* m = Method::allocate(
|
||||
loader_data, code_length, access_flags, linenumber_table_length,
|
||||
total_lvt_length, exception_table_length, checked_exceptions_length,
|
||||
generic_signature_index, ConstMethod::NORMAL, CHECK_(nullHandle));
|
||||
method_parameters_length, generic_signature_index,
|
||||
ConstMethod::NORMAL, CHECK_(nullHandle));
|
||||
|
||||
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
|
||||
|
||||
@ -2232,6 +2290,18 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
exception_table_start, size);
|
||||
}
|
||||
|
||||
// Copy method parameters
|
||||
if (method_parameters_length > 0) {
|
||||
MethodParametersElement* elem = m->constMethod()->method_parameters_start();
|
||||
for(int i = 0; i < method_parameters_length; i++) {
|
||||
elem[i].name_cp_index =
|
||||
Bytes::get_Java_u2(method_parameters_data);
|
||||
method_parameters_data += 2;
|
||||
elem[i].flags = Bytes::get_Java_u4(method_parameters_data);
|
||||
method_parameters_data += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy checked exceptions
|
||||
if (checked_exceptions_length > 0) {
|
||||
int size = checked_exceptions_length * sizeof(CheckedExceptionElement) / sizeof(u2);
|
||||
@ -2333,6 +2403,12 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
NULL,
|
||||
0,
|
||||
CHECK_(nullHandle));
|
||||
*method_type_annotations = assemble_annotations(loader_data,
|
||||
runtime_visible_type_annotations,
|
||||
runtime_visible_type_annotations_length,
|
||||
runtime_invisible_type_annotations,
|
||||
runtime_invisible_type_annotations_length,
|
||||
CHECK_(nullHandle));
|
||||
|
||||
if (name == vmSymbols::finalize_method_name() &&
|
||||
signature == vmSymbols::void_method_signature()) {
|
||||
@ -2364,12 +2440,14 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
||||
Array<AnnotationArray*>** methods_annotations,
|
||||
Array<AnnotationArray*>** methods_parameter_annotations,
|
||||
Array<AnnotationArray*>** methods_default_annotations,
|
||||
Array<AnnotationArray*>** methods_type_annotations,
|
||||
bool* has_default_methods,
|
||||
TRAPS) {
|
||||
ClassFileStream* cfs = stream();
|
||||
AnnotationArray* method_annotations = NULL;
|
||||
AnnotationArray* method_parameter_annotations = NULL;
|
||||
AnnotationArray* method_default_annotations = NULL;
|
||||
AnnotationArray* method_type_annotations = NULL;
|
||||
cfs->guarantee_more(2, CHECK_NULL); // length
|
||||
u2 length = cfs->get_u2_fast();
|
||||
if (length == 0) {
|
||||
@ -2386,6 +2464,7 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
||||
&method_annotations,
|
||||
&method_parameter_annotations,
|
||||
&method_default_annotations,
|
||||
&method_type_annotations,
|
||||
CHECK_NULL);
|
||||
|
||||
if (method->is_final()) {
|
||||
@ -2411,7 +2490,13 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
||||
MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
|
||||
}
|
||||
(*methods_default_annotations)->at_put(index, method_default_annotations);
|
||||
if (*methods_type_annotations == NULL) {
|
||||
*methods_type_annotations =
|
||||
MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
|
||||
}
|
||||
(*methods_type_annotations)->at_put(index, method_type_annotations);
|
||||
}
|
||||
|
||||
if (_need_verify && length > 1) {
|
||||
// Check duplicated methods
|
||||
ResourceMark rm(THREAD);
|
||||
@ -2445,6 +2530,7 @@ Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
|
||||
Array<AnnotationArray*>* methods_annotations,
|
||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
||||
Array<AnnotationArray*>* methods_default_annotations,
|
||||
Array<AnnotationArray*>* methods_type_annotations,
|
||||
TRAPS) {
|
||||
int length = methods->length();
|
||||
// If JVMTI original method ordering or sharing is enabled we have to
|
||||
@ -2463,7 +2549,8 @@ Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
|
||||
// Note that the ordering is not alphabetical, see Symbol::fast_compare
|
||||
Method::sort_methods(methods, methods_annotations,
|
||||
methods_parameter_annotations,
|
||||
methods_default_annotations);
|
||||
methods_default_annotations,
|
||||
methods_type_annotations);
|
||||
|
||||
// If JVMTI original method ordering or sharing is enabled construct int
|
||||
// array remembering the original ordering
|
||||
@ -2728,6 +2815,10 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
|
||||
int runtime_visible_annotations_length = 0;
|
||||
u1* runtime_invisible_annotations = NULL;
|
||||
int runtime_invisible_annotations_length = 0;
|
||||
u1* runtime_visible_type_annotations = NULL;
|
||||
int runtime_visible_type_annotations_length = 0;
|
||||
u1* runtime_invisible_type_annotations = NULL;
|
||||
int runtime_invisible_type_annotations_length = 0;
|
||||
u1* inner_classes_attribute_start = NULL;
|
||||
u4 inner_classes_attribute_length = 0;
|
||||
u2 enclosing_method_class_index = 0;
|
||||
@ -2834,6 +2925,17 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
|
||||
classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK);
|
||||
parsed_bootstrap_methods_attribute = true;
|
||||
parse_classfile_bootstrap_methods_attribute(loader_data, cp, attribute_length, CHECK);
|
||||
} else if (tag == vmSymbols::tag_runtime_visible_type_annotations()) {
|
||||
runtime_visible_type_annotations_length = attribute_length;
|
||||
runtime_visible_type_annotations = cfs->get_u1_buffer();
|
||||
assert(runtime_visible_type_annotations != NULL, "null visible type annotations");
|
||||
// No need for the VM to parse Type annotations
|
||||
cfs->skip_u1(runtime_visible_type_annotations_length, CHECK);
|
||||
} else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_type_annotations()) {
|
||||
runtime_invisible_type_annotations_length = attribute_length;
|
||||
runtime_invisible_type_annotations = cfs->get_u1_buffer();
|
||||
assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations");
|
||||
cfs->skip_u1(runtime_invisible_type_annotations_length, CHECK);
|
||||
} else {
|
||||
// Unknown attribute
|
||||
cfs->skip_u1(attribute_length, CHECK);
|
||||
@ -2850,6 +2952,13 @@ void ClassFileParser::parse_classfile_attributes(ClassLoaderData* loader_data,
|
||||
runtime_invisible_annotations_length,
|
||||
CHECK);
|
||||
set_class_annotations(annotations);
|
||||
AnnotationArray* type_annotations = assemble_annotations(loader_data,
|
||||
runtime_visible_type_annotations,
|
||||
runtime_visible_type_annotations_length,
|
||||
runtime_invisible_type_annotations,
|
||||
runtime_invisible_type_annotations_length,
|
||||
CHECK);
|
||||
set_class_type_annotations(type_annotations);
|
||||
|
||||
if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
|
||||
u2 num_of_classes = parse_classfile_inner_classes_attribute(
|
||||
@ -2956,6 +3065,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
TempNewSymbol& parsed_name,
|
||||
bool verify,
|
||||
TRAPS) {
|
||||
|
||||
// When a retransformable agent is attached, JVMTI caches the
|
||||
// class bytes that existed before the first retransformation.
|
||||
// If RedefineClasses() was used before the retransformable
|
||||
@ -3190,7 +3300,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
// Fields (offsets are filled in later)
|
||||
FieldAllocationCount fac;
|
||||
Array<AnnotationArray*>* fields_annotations = NULL;
|
||||
Array<AnnotationArray*>* fields_type_annotations = NULL;
|
||||
Array<u2>* fields = parse_fields(loader_data, class_name, cp, access_flags.is_interface(), &fac, &fields_annotations,
|
||||
&fields_type_annotations,
|
||||
&java_fields_count,
|
||||
CHECK_(nullHandle));
|
||||
// Methods
|
||||
@ -3202,6 +3314,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
Array<AnnotationArray*>* methods_annotations = NULL;
|
||||
Array<AnnotationArray*>* methods_parameter_annotations = NULL;
|
||||
Array<AnnotationArray*>* methods_default_annotations = NULL;
|
||||
Array<AnnotationArray*>* methods_type_annotations = NULL;
|
||||
Array<Method*>* methods = parse_methods(loader_data,
|
||||
cp, access_flags.is_interface(),
|
||||
&promoted_flags,
|
||||
@ -3209,6 +3322,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
&methods_annotations,
|
||||
&methods_parameter_annotations,
|
||||
&methods_default_annotations,
|
||||
&methods_type_annotations,
|
||||
&has_default_methods,
|
||||
CHECK_(nullHandle));
|
||||
|
||||
@ -3270,6 +3384,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
methods_annotations,
|
||||
methods_parameter_annotations,
|
||||
methods_default_annotations,
|
||||
methods_type_annotations,
|
||||
CHECK_(nullHandle));
|
||||
|
||||
// promote flags from parse_methods() to the klass' flags
|
||||
@ -3687,11 +3802,13 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
if (is_anonymous()) // I am well known to myself
|
||||
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
|
||||
|
||||
// Allocate an annotation type if needed.
|
||||
if (fields_annotations != NULL ||
|
||||
methods_annotations != NULL ||
|
||||
methods_parameter_annotations != NULL ||
|
||||
methods_default_annotations != NULL) {
|
||||
// Allocate an annotation type if needed.
|
||||
methods_default_annotations != NULL ||
|
||||
fields_type_annotations != NULL ||
|
||||
methods_type_annotations != NULL) {
|
||||
Annotations* anno = Annotations::allocate(loader_data,
|
||||
fields_annotations, methods_annotations,
|
||||
methods_parameter_annotations,
|
||||
@ -3701,6 +3818,16 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
this_klass->set_annotations(NULL);
|
||||
}
|
||||
|
||||
if (fields_type_annotations != NULL ||
|
||||
methods_type_annotations != NULL) {
|
||||
assert(this_klass->annotations() != NULL, "annotations should have been allocated");
|
||||
Annotations* anno = Annotations::allocate(loader_data,
|
||||
fields_type_annotations,
|
||||
methods_type_annotations,
|
||||
NULL,
|
||||
NULL, CHECK_(nullHandle));
|
||||
this_klass->annotations()->set_type_annotations(anno);
|
||||
}
|
||||
|
||||
this_klass->set_minor_version(minor_version);
|
||||
this_klass->set_major_version(major_version);
|
||||
@ -3725,6 +3852,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
// Fill in field values obtained by parse_classfile_attributes
|
||||
if (parsed_annotations.has_any_annotations())
|
||||
parsed_annotations.apply_to(this_klass);
|
||||
|
||||
// Create annotations
|
||||
if (_annotations != NULL && this_klass->annotations() == NULL) {
|
||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
||||
@ -3732,6 +3860,19 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
}
|
||||
apply_parsed_class_attributes(this_klass);
|
||||
|
||||
// Create type annotations
|
||||
if (_type_annotations != NULL) {
|
||||
if (this_klass->annotations() == NULL) {
|
||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
||||
this_klass->set_annotations(anno);
|
||||
}
|
||||
if (this_klass->annotations()->type_annotations() == NULL) {
|
||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
||||
this_klass->annotations()->set_type_annotations(anno);
|
||||
}
|
||||
this_klass->annotations()->type_annotations()->set_class_annotations(_type_annotations);
|
||||
}
|
||||
|
||||
// Miranda methods
|
||||
if ((num_miranda_methods > 0) ||
|
||||
// if this class introduced new miranda methods or
|
||||
|
@ -64,6 +64,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
int _sde_length;
|
||||
Array<u2>* _inner_classes;
|
||||
AnnotationArray* _annotations;
|
||||
AnnotationArray* _type_annotations;
|
||||
|
||||
void set_class_synthetic_flag(bool x) { _synthetic_flag = x; }
|
||||
void set_class_sourcefile(Symbol* x) { _sourcefile = x; }
|
||||
@ -71,12 +72,14 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
void set_class_sde_buffer(char* x, int len) { _sde_buffer = x; _sde_length = len; }
|
||||
void set_class_inner_classes(Array<u2>* x) { _inner_classes = x; }
|
||||
void set_class_annotations(AnnotationArray* x) { _annotations = x; }
|
||||
void set_class_type_annotations(AnnotationArray* x) { _type_annotations = x; }
|
||||
void init_parsed_class_attributes() {
|
||||
_synthetic_flag = false;
|
||||
_sourcefile = NULL;
|
||||
_generic_signature = NULL;
|
||||
_sde_buffer = NULL;
|
||||
_sde_length = 0;
|
||||
_annotations = _type_annotations = NULL;
|
||||
// initialize the other flags too:
|
||||
_has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false;
|
||||
_max_bootstrap_specifier_index = -1;
|
||||
@ -163,6 +166,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
bool* is_synthetic_addr,
|
||||
u2* generic_signature_index_addr,
|
||||
AnnotationArray** field_annotations,
|
||||
AnnotationArray** field_type_annotations,
|
||||
FieldAnnotationCollector* parsed_annotations,
|
||||
TRAPS);
|
||||
Array<u2>* parse_fields(ClassLoaderData* loader_data,
|
||||
@ -170,6 +174,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
constantPoolHandle cp, bool is_interface,
|
||||
FieldAllocationCount *fac,
|
||||
Array<AnnotationArray*>** fields_annotations,
|
||||
Array<AnnotationArray*>** fields_type_annotations,
|
||||
u2* java_fields_count_ptr, TRAPS);
|
||||
|
||||
// Method parsing
|
||||
@ -180,6 +185,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
AnnotationArray** method_annotations,
|
||||
AnnotationArray** method_parameter_annotations,
|
||||
AnnotationArray** method_default_annotations,
|
||||
AnnotationArray** method_type_annotations,
|
||||
TRAPS);
|
||||
Array<Method*>* parse_methods(ClassLoaderData* loader_data,
|
||||
constantPoolHandle cp,
|
||||
@ -189,6 +195,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
Array<AnnotationArray*>** methods_annotations,
|
||||
Array<AnnotationArray*>** methods_parameter_annotations,
|
||||
Array<AnnotationArray*>** methods_default_annotations,
|
||||
Array<AnnotationArray*>** methods_type_annotations,
|
||||
bool* has_default_method,
|
||||
TRAPS);
|
||||
Array<int>* sort_methods(ClassLoaderData* loader_data,
|
||||
@ -196,6 +203,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
Array<AnnotationArray*>* methods_annotations,
|
||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
||||
Array<AnnotationArray*>* methods_default_annotations,
|
||||
Array<AnnotationArray*>* methods_type_annotations,
|
||||
TRAPS);
|
||||
u2* parse_exception_table(ClassLoaderData* loader_data,
|
||||
u4 code_length, u4 exception_table_length,
|
||||
|
@ -93,3 +93,10 @@ void ClassFileStream::skip_u2(int length, TRAPS) {
|
||||
}
|
||||
_current += length * 2;
|
||||
}
|
||||
|
||||
void ClassFileStream::skip_u4(int length, TRAPS) {
|
||||
if (_need_verify) {
|
||||
guarantee_more(length * 4, CHECK);
|
||||
}
|
||||
_current += length * 4;
|
||||
}
|
||||
|
@ -133,6 +133,11 @@ class ClassFileStream: public ResourceObj {
|
||||
_current += 2 * length;
|
||||
}
|
||||
|
||||
void skip_u4(int length, TRAPS);
|
||||
void skip_u4_fast(int length) {
|
||||
_current += 4 * length;
|
||||
}
|
||||
|
||||
// Tells whether eos is reached
|
||||
bool at_eos() const { return _current == _buffer_end; }
|
||||
};
|
||||
|
@ -330,10 +330,19 @@ Metaspace* ClassLoaderData::metaspace_non_null() {
|
||||
}
|
||||
if (this == the_null_class_loader_data()) {
|
||||
assert (class_loader() == NULL, "Must be");
|
||||
size_t word_size = Metaspace::first_chunk_word_size();
|
||||
set_metaspace(new Metaspace(_metaspace_lock, word_size));
|
||||
set_metaspace(new Metaspace(_metaspace_lock, Metaspace::BootMetaspaceType));
|
||||
} else if (is_anonymous()) {
|
||||
if (TraceClassLoaderData && Verbose && class_loader() != NULL) {
|
||||
tty->print_cr("is_anonymous: %s", class_loader()->klass()->internal_name());
|
||||
}
|
||||
set_metaspace(new Metaspace(_metaspace_lock, Metaspace::AnonymousMetaspaceType));
|
||||
} else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) {
|
||||
if (TraceClassLoaderData && Verbose && class_loader() != NULL) {
|
||||
tty->print_cr("is_reflection: %s", class_loader()->klass()->internal_name());
|
||||
}
|
||||
set_metaspace(new Metaspace(_metaspace_lock, Metaspace::ReflectionMetaspaceType));
|
||||
} else {
|
||||
set_metaspace(new Metaspace(_metaspace_lock)); // default size for now.
|
||||
set_metaspace(new Metaspace(_metaspace_lock, Metaspace::StandardMetaspaceType));
|
||||
}
|
||||
}
|
||||
return _metaspace;
|
||||
@ -672,8 +681,8 @@ void ClassLoaderData::initialize_shared_metaspaces() {
|
||||
"only supported for null loader data for now");
|
||||
assert (!_shared_metaspaces_initialized, "only initialize once");
|
||||
MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
|
||||
_ro_metaspace = new Metaspace(_metaspace_lock, SharedReadOnlySize/wordSize);
|
||||
_rw_metaspace = new Metaspace(_metaspace_lock, SharedReadWriteSize/wordSize);
|
||||
_ro_metaspace = new Metaspace(_metaspace_lock, Metaspace::ROMetaspaceType);
|
||||
_rw_metaspace = new Metaspace(_metaspace_lock, Metaspace::ReadWriteMetaspaceType);
|
||||
_shared_metaspaces_initialized = true;
|
||||
}
|
||||
|
||||
|
@ -1148,7 +1148,8 @@ static Method* new_method(
|
||||
int code_length = bytecodes->length();
|
||||
|
||||
Method* m = Method::allocate(cp->pool_holder()->class_loader_data(),
|
||||
code_length, flags, 0, 0, 0, 0, 0, mt, CHECK_NULL);
|
||||
code_length, flags, 0, 0, 0, 0, 0, 0,
|
||||
mt, CHECK_NULL);
|
||||
|
||||
m->set_constants(NULL); // This will get filled in later
|
||||
m->set_name_index(cp->utf8(name));
|
||||
|
@ -1813,10 +1813,12 @@ void java_lang_reflect_Method::compute_offsets() {
|
||||
annotations_offset = -1;
|
||||
parameter_annotations_offset = -1;
|
||||
annotation_default_offset = -1;
|
||||
type_annotations_offset = -1;
|
||||
compute_optional_offset(signature_offset, k, vmSymbols::signature_name(), vmSymbols::string_signature());
|
||||
compute_optional_offset(annotations_offset, k, vmSymbols::annotations_name(), vmSymbols::byte_array_signature());
|
||||
compute_optional_offset(parameter_annotations_offset, k, vmSymbols::parameter_annotations_name(), vmSymbols::byte_array_signature());
|
||||
compute_optional_offset(annotation_default_offset, k, vmSymbols::annotation_default_name(), vmSymbols::byte_array_signature());
|
||||
compute_optional_offset(type_annotations_offset, k, vmSymbols::type_annotations_name(), vmSymbols::byte_array_signature());
|
||||
}
|
||||
|
||||
Handle java_lang_reflect_Method::create(TRAPS) {
|
||||
@ -1962,6 +1964,22 @@ void java_lang_reflect_Method::set_annotation_default(oop method, oop value) {
|
||||
method->obj_field_put(annotation_default_offset, value);
|
||||
}
|
||||
|
||||
bool java_lang_reflect_Method::has_type_annotations_field() {
|
||||
return (type_annotations_offset >= 0);
|
||||
}
|
||||
|
||||
oop java_lang_reflect_Method::type_annotations(oop method) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
assert(has_type_annotations_field(), "type_annotations field must be present");
|
||||
return method->obj_field(type_annotations_offset);
|
||||
}
|
||||
|
||||
void java_lang_reflect_Method::set_type_annotations(oop method, oop value) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
assert(has_type_annotations_field(), "type_annotations field must be present");
|
||||
method->obj_field_put(type_annotations_offset, value);
|
||||
}
|
||||
|
||||
void java_lang_reflect_Constructor::compute_offsets() {
|
||||
Klass* k = SystemDictionary::reflect_Constructor_klass();
|
||||
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||
@ -1973,9 +1991,11 @@ void java_lang_reflect_Constructor::compute_offsets() {
|
||||
signature_offset = -1;
|
||||
annotations_offset = -1;
|
||||
parameter_annotations_offset = -1;
|
||||
type_annotations_offset = -1;
|
||||
compute_optional_offset(signature_offset, k, vmSymbols::signature_name(), vmSymbols::string_signature());
|
||||
compute_optional_offset(annotations_offset, k, vmSymbols::annotations_name(), vmSymbols::byte_array_signature());
|
||||
compute_optional_offset(parameter_annotations_offset, k, vmSymbols::parameter_annotations_name(), vmSymbols::byte_array_signature());
|
||||
compute_optional_offset(type_annotations_offset, k, vmSymbols::type_annotations_name(), vmSymbols::byte_array_signature());
|
||||
}
|
||||
|
||||
Handle java_lang_reflect_Constructor::create(TRAPS) {
|
||||
@ -2086,6 +2106,22 @@ void java_lang_reflect_Constructor::set_parameter_annotations(oop method, oop va
|
||||
method->obj_field_put(parameter_annotations_offset, value);
|
||||
}
|
||||
|
||||
bool java_lang_reflect_Constructor::has_type_annotations_field() {
|
||||
return (type_annotations_offset >= 0);
|
||||
}
|
||||
|
||||
oop java_lang_reflect_Constructor::type_annotations(oop constructor) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
assert(has_type_annotations_field(), "type_annotations field must be present");
|
||||
return constructor->obj_field(type_annotations_offset);
|
||||
}
|
||||
|
||||
void java_lang_reflect_Constructor::set_type_annotations(oop constructor, oop value) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
assert(has_type_annotations_field(), "type_annotations field must be present");
|
||||
constructor->obj_field_put(type_annotations_offset, value);
|
||||
}
|
||||
|
||||
void java_lang_reflect_Field::compute_offsets() {
|
||||
Klass* k = SystemDictionary::reflect_Field_klass();
|
||||
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||
@ -2096,8 +2132,10 @@ void java_lang_reflect_Field::compute_offsets() {
|
||||
// The generic signature and annotations fields are only present in 1.5
|
||||
signature_offset = -1;
|
||||
annotations_offset = -1;
|
||||
type_annotations_offset = -1;
|
||||
compute_optional_offset(signature_offset, k, vmSymbols::signature_name(), vmSymbols::string_signature());
|
||||
compute_optional_offset(annotations_offset, k, vmSymbols::annotations_name(), vmSymbols::byte_array_signature());
|
||||
compute_optional_offset(type_annotations_offset, k, vmSymbols::type_annotations_name(), vmSymbols::byte_array_signature());
|
||||
}
|
||||
|
||||
Handle java_lang_reflect_Field::create(TRAPS) {
|
||||
@ -2192,6 +2230,21 @@ void java_lang_reflect_Field::set_annotations(oop field, oop value) {
|
||||
field->obj_field_put(annotations_offset, value);
|
||||
}
|
||||
|
||||
bool java_lang_reflect_Field::has_type_annotations_field() {
|
||||
return (type_annotations_offset >= 0);
|
||||
}
|
||||
|
||||
oop java_lang_reflect_Field::type_annotations(oop field) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
assert(has_type_annotations_field(), "type_annotations field must be present");
|
||||
return field->obj_field(type_annotations_offset);
|
||||
}
|
||||
|
||||
void java_lang_reflect_Field::set_type_annotations(oop field, oop value) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
assert(has_type_annotations_field(), "type_annotations field must be present");
|
||||
field->obj_field_put(type_annotations_offset, value);
|
||||
}
|
||||
|
||||
void sun_reflect_ConstantPool::compute_offsets() {
|
||||
Klass* k = SystemDictionary::reflect_ConstantPool_klass();
|
||||
@ -2202,6 +2255,66 @@ void sun_reflect_ConstantPool::compute_offsets() {
|
||||
}
|
||||
}
|
||||
|
||||
void java_lang_reflect_Parameter::compute_offsets() {
|
||||
Klass* k = SystemDictionary::reflect_Parameter_klass();
|
||||
if(NULL != k) {
|
||||
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||
compute_offset(modifiers_offset, k, vmSymbols::modifiers_name(), vmSymbols::int_signature());
|
||||
compute_offset(index_offset, k, vmSymbols::index_name(), vmSymbols::int_signature());
|
||||
compute_offset(executable_offset, k, vmSymbols::executable_name(), vmSymbols::executable_signature());
|
||||
}
|
||||
}
|
||||
|
||||
Handle java_lang_reflect_Parameter::create(TRAPS) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
Symbol* name = vmSymbols::java_lang_reflect_Parameter();
|
||||
Klass* k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH);
|
||||
instanceKlassHandle klass (THREAD, k);
|
||||
// Ensure it is initialized
|
||||
klass->initialize(CHECK_NH);
|
||||
return klass->allocate_instance_handle(CHECK_NH);
|
||||
}
|
||||
|
||||
oop java_lang_reflect_Parameter::name(oop param) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
return param->obj_field(name_offset);
|
||||
}
|
||||
|
||||
void java_lang_reflect_Parameter::set_name(oop param, oop value) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
param->obj_field_put(name_offset, value);
|
||||
}
|
||||
|
||||
int java_lang_reflect_Parameter::modifiers(oop param) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
return param->int_field(modifiers_offset);
|
||||
}
|
||||
|
||||
void java_lang_reflect_Parameter::set_modifiers(oop param, int value) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
param->int_field_put(modifiers_offset, value);
|
||||
}
|
||||
|
||||
int java_lang_reflect_Parameter::index(oop param) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
return param->int_field(index_offset);
|
||||
}
|
||||
|
||||
void java_lang_reflect_Parameter::set_index(oop param, int value) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
param->int_field_put(index_offset, value);
|
||||
}
|
||||
|
||||
oop java_lang_reflect_Parameter::executable(oop param) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
return param->obj_field(executable_offset);
|
||||
}
|
||||
|
||||
void java_lang_reflect_Parameter::set_executable(oop param, oop value) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
param->obj_field_put(executable_offset, value);
|
||||
}
|
||||
|
||||
|
||||
Handle sun_reflect_ConstantPool::create(TRAPS) {
|
||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||
@ -2857,6 +2970,7 @@ int java_lang_reflect_Method::signature_offset;
|
||||
int java_lang_reflect_Method::annotations_offset;
|
||||
int java_lang_reflect_Method::parameter_annotations_offset;
|
||||
int java_lang_reflect_Method::annotation_default_offset;
|
||||
int java_lang_reflect_Method::type_annotations_offset;
|
||||
int java_lang_reflect_Constructor::clazz_offset;
|
||||
int java_lang_reflect_Constructor::parameterTypes_offset;
|
||||
int java_lang_reflect_Constructor::exceptionTypes_offset;
|
||||
@ -2865,6 +2979,7 @@ int java_lang_reflect_Constructor::modifiers_offset;
|
||||
int java_lang_reflect_Constructor::signature_offset;
|
||||
int java_lang_reflect_Constructor::annotations_offset;
|
||||
int java_lang_reflect_Constructor::parameter_annotations_offset;
|
||||
int java_lang_reflect_Constructor::type_annotations_offset;
|
||||
int java_lang_reflect_Field::clazz_offset;
|
||||
int java_lang_reflect_Field::name_offset;
|
||||
int java_lang_reflect_Field::type_offset;
|
||||
@ -2872,6 +2987,11 @@ int java_lang_reflect_Field::slot_offset;
|
||||
int java_lang_reflect_Field::modifiers_offset;
|
||||
int java_lang_reflect_Field::signature_offset;
|
||||
int java_lang_reflect_Field::annotations_offset;
|
||||
int java_lang_reflect_Field::type_annotations_offset;
|
||||
int java_lang_reflect_Parameter::name_offset;
|
||||
int java_lang_reflect_Parameter::modifiers_offset;
|
||||
int java_lang_reflect_Parameter::index_offset;
|
||||
int java_lang_reflect_Parameter::executable_offset;
|
||||
int java_lang_boxing_object::value_offset;
|
||||
int java_lang_boxing_object::long_value_offset;
|
||||
int java_lang_ref_Reference::referent_offset;
|
||||
@ -3056,6 +3176,8 @@ void JavaClasses::compute_offsets() {
|
||||
sun_reflect_ConstantPool::compute_offsets();
|
||||
sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
|
||||
}
|
||||
if (JDK_Version::is_jdk18x_version())
|
||||
java_lang_reflect_Parameter::compute_offsets();
|
||||
|
||||
// generated interpreter code wants to know about the offsets we just computed:
|
||||
AbstractAssembler::update_delayed_values();
|
||||
|
@ -554,6 +554,7 @@ class java_lang_reflect_Method : public java_lang_reflect_AccessibleObject {
|
||||
static int annotations_offset;
|
||||
static int parameter_annotations_offset;
|
||||
static int annotation_default_offset;
|
||||
static int type_annotations_offset;
|
||||
|
||||
static void compute_offsets();
|
||||
|
||||
@ -599,6 +600,10 @@ class java_lang_reflect_Method : public java_lang_reflect_AccessibleObject {
|
||||
static oop annotation_default(oop method);
|
||||
static void set_annotation_default(oop method, oop value);
|
||||
|
||||
static bool has_type_annotations_field();
|
||||
static oop type_annotations(oop method);
|
||||
static void set_type_annotations(oop method, oop value);
|
||||
|
||||
// Debugging
|
||||
friend class JavaClasses;
|
||||
};
|
||||
@ -618,6 +623,7 @@ class java_lang_reflect_Constructor : public java_lang_reflect_AccessibleObject
|
||||
static int signature_offset;
|
||||
static int annotations_offset;
|
||||
static int parameter_annotations_offset;
|
||||
static int type_annotations_offset;
|
||||
|
||||
static void compute_offsets();
|
||||
|
||||
@ -653,6 +659,10 @@ class java_lang_reflect_Constructor : public java_lang_reflect_AccessibleObject
|
||||
static oop parameter_annotations(oop method);
|
||||
static void set_parameter_annotations(oop method, oop value);
|
||||
|
||||
static bool has_type_annotations_field();
|
||||
static oop type_annotations(oop constructor);
|
||||
static void set_type_annotations(oop constructor, oop value);
|
||||
|
||||
// Debugging
|
||||
friend class JavaClasses;
|
||||
};
|
||||
@ -671,6 +681,7 @@ class java_lang_reflect_Field : public java_lang_reflect_AccessibleObject {
|
||||
static int modifiers_offset;
|
||||
static int signature_offset;
|
||||
static int annotations_offset;
|
||||
static int type_annotations_offset;
|
||||
|
||||
static void compute_offsets();
|
||||
|
||||
@ -710,10 +721,45 @@ class java_lang_reflect_Field : public java_lang_reflect_AccessibleObject {
|
||||
static oop annotation_default(oop method);
|
||||
static void set_annotation_default(oop method, oop value);
|
||||
|
||||
static bool has_type_annotations_field();
|
||||
static oop type_annotations(oop field);
|
||||
static void set_type_annotations(oop field, oop value);
|
||||
|
||||
// Debugging
|
||||
friend class JavaClasses;
|
||||
};
|
||||
|
||||
class java_lang_reflect_Parameter {
|
||||
private:
|
||||
// Note that to reduce dependencies on the JDK we compute these
|
||||
// offsets at run-time.
|
||||
static int name_offset;
|
||||
static int modifiers_offset;
|
||||
static int index_offset;
|
||||
static int executable_offset;
|
||||
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
// Allocation
|
||||
static Handle create(TRAPS);
|
||||
|
||||
// Accessors
|
||||
static oop name(oop field);
|
||||
static void set_name(oop field, oop value);
|
||||
|
||||
static int index(oop reflect);
|
||||
static void set_index(oop reflect, int value);
|
||||
|
||||
static int modifiers(oop reflect);
|
||||
static void set_modifiers(oop reflect, int value);
|
||||
|
||||
static oop executable(oop constructor);
|
||||
static void set_executable(oop constructor, oop value);
|
||||
|
||||
friend class JavaClasses;
|
||||
};
|
||||
|
||||
// Interface to sun.reflect.ConstantPool objects
|
||||
class sun_reflect_ConstantPool {
|
||||
private:
|
||||
|
@ -131,6 +131,7 @@ class SymbolPropertyTable;
|
||||
do_klass(Properties_klass, java_util_Properties, Pre ) \
|
||||
do_klass(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre ) \
|
||||
do_klass(reflect_Field_klass, java_lang_reflect_Field, Pre ) \
|
||||
do_klass(reflect_Parameter_klass, java_lang_reflect_Parameter, Opt ) \
|
||||
do_klass(reflect_Method_klass, java_lang_reflect_Method, Pre ) \
|
||||
do_klass(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre ) \
|
||||
\
|
||||
@ -459,6 +460,7 @@ public:
|
||||
// Tells whether ClassLoader.checkPackageAccess is present
|
||||
static bool has_checkPackageAccess() { return _has_checkPackageAccess; }
|
||||
|
||||
static bool Parameter_klass_loaded() { return WK_KLASS(reflect_Parameter_klass) != NULL; }
|
||||
static bool Class_klass_loaded() { return WK_KLASS(Class_klass) != NULL; }
|
||||
static bool Cloneable_klass_loaded() { return WK_KLASS(Cloneable_klass) != NULL; }
|
||||
static bool Object_klass_loaded() { return WK_KLASS(Object_klass) != NULL; }
|
||||
|
@ -86,6 +86,7 @@
|
||||
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") \
|
||||
@ -126,6 +127,7 @@
|
||||
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") \
|
||||
@ -136,6 +138,8 @@
|
||||
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") \
|
||||
\
|
||||
@ -233,12 +237,17 @@
|
||||
/* Support for annotations (JDK 1.5 and above) */ \
|
||||
\
|
||||
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") \
|
||||
/* Type Annotations (JDK 8 and above) */ \
|
||||
template(type_annotations_name, "typeAnnotations") \
|
||||
\
|
||||
\
|
||||
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
|
||||
template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \
|
||||
@ -470,6 +479,7 @@
|
||||
template(class_signature, "Ljava/lang/Class;") \
|
||||
template(string_signature, "Ljava/lang/String;") \
|
||||
template(reference_signature, "Ljava/lang/ref/Reference;") \
|
||||
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;") \
|
||||
|
@ -56,7 +56,7 @@ void ConcurrentMarkSweepPolicy::initialize_generations() {
|
||||
if (_generations == NULL)
|
||||
vm_exit_during_initialization("Unable to allocate gen spec");
|
||||
|
||||
if (ParNewGeneration::in_use()) {
|
||||
if (UseParNewGC) {
|
||||
if (UseAdaptiveSizePolicy) {
|
||||
_generations[0] = new GenerationSpec(Generation::ASParNew,
|
||||
_initial_gen0_size, _max_gen0_size);
|
||||
@ -96,7 +96,7 @@ void ConcurrentMarkSweepPolicy::initialize_size_policy(size_t init_eden_size,
|
||||
|
||||
void ConcurrentMarkSweepPolicy::initialize_gc_policy_counters() {
|
||||
// initialize the policy counters - 2 collectors, 3 generations
|
||||
if (ParNewGeneration::in_use()) {
|
||||
if (UseParNewGC) {
|
||||
_gc_policy_counters = new GCPolicyCounters("ParNew:CMS", 2, 3);
|
||||
}
|
||||
else {
|
||||
@ -119,7 +119,7 @@ void ASConcurrentMarkSweepPolicy::initialize_gc_policy_counters() {
|
||||
|
||||
assert(size_policy() != NULL, "A size policy is required");
|
||||
// initialize the policy counters - 2 collectors, 3 generations
|
||||
if (ParNewGeneration::in_use()) {
|
||||
if (UseParNewGC) {
|
||||
_gc_policy_counters = new CMSGCAdaptivePolicyCounters("ParNew:CMS", 2, 3,
|
||||
size_policy());
|
||||
}
|
||||
|
@ -214,7 +214,6 @@ HeapWord* CompactibleFreeListSpace::forward(oop q, size_t size,
|
||||
assert(q->forwardee() == NULL, "should be forwarded to NULL");
|
||||
}
|
||||
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::register_live_oop(q, adjusted_size));
|
||||
compact_top += adjusted_size;
|
||||
|
||||
// we need to update the offset table so that the beginnings of objects can be
|
||||
|
@ -827,10 +827,10 @@ void ConcurrentMarkSweepGeneration::printOccupancy(const char *s) {
|
||||
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
||||
if (PrintGCDetails) {
|
||||
if (Verbose) {
|
||||
gclog_or_tty->print(" [%d %s-%s: "SIZE_FORMAT"("SIZE_FORMAT")]",
|
||||
gclog_or_tty->print("[%d %s-%s: "SIZE_FORMAT"("SIZE_FORMAT")]",
|
||||
level(), short_name(), s, used(), capacity());
|
||||
} else {
|
||||
gclog_or_tty->print(" [%d %s-%s: "SIZE_FORMAT"K("SIZE_FORMAT"K)]",
|
||||
gclog_or_tty->print("[%d %s-%s: "SIZE_FORMAT"K("SIZE_FORMAT"K)]",
|
||||
level(), short_name(), s, used() / K, capacity() / K);
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ CollectionSetChooser::CollectionSetChooser() :
|
||||
_curr_index(0), _length(0), _first_par_unreserved_idx(0),
|
||||
_region_live_threshold_bytes(0), _remaining_reclaimable_bytes(0) {
|
||||
_region_live_threshold_bytes =
|
||||
HeapRegion::GrainBytes * (size_t) G1OldCSetRegionLiveThresholdPercent / 100;
|
||||
HeapRegion::GrainBytes * (size_t) G1MixedGCLiveThresholdPercent / 100;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -192,6 +192,7 @@ bool CMMarkStack::allocate(size_t capacity) {
|
||||
setEmpty();
|
||||
_capacity = (jint) capacity;
|
||||
_saved_index = -1;
|
||||
_should_expand = false;
|
||||
NOT_PRODUCT(_max_depth = 0);
|
||||
return true;
|
||||
}
|
||||
@ -747,8 +748,8 @@ void ConcurrentMark::reset() {
|
||||
assert(_heap_end != NULL, "heap bounds should look ok");
|
||||
assert(_heap_start < _heap_end, "heap bounds should look ok");
|
||||
|
||||
// reset all the marking data structures and any necessary flags
|
||||
clear_marking_state();
|
||||
// Reset all the marking data structures and any necessary flags
|
||||
reset_marking_state();
|
||||
|
||||
if (verbose_low()) {
|
||||
gclog_or_tty->print_cr("[global] resetting");
|
||||
@ -766,6 +767,23 @@ void ConcurrentMark::reset() {
|
||||
set_concurrent_marking_in_progress();
|
||||
}
|
||||
|
||||
|
||||
void ConcurrentMark::reset_marking_state(bool clear_overflow) {
|
||||
_markStack.set_should_expand();
|
||||
_markStack.setEmpty(); // Also clears the _markStack overflow flag
|
||||
if (clear_overflow) {
|
||||
clear_has_overflown();
|
||||
} else {
|
||||
assert(has_overflown(), "pre-condition");
|
||||
}
|
||||
_finger = _heap_start;
|
||||
|
||||
for (uint i = 0; i < _max_worker_id; ++i) {
|
||||
CMTaskQueue* queue = _task_queues->queue(i);
|
||||
queue->set_empty();
|
||||
}
|
||||
}
|
||||
|
||||
void ConcurrentMark::set_phase(uint active_tasks, bool concurrent) {
|
||||
assert(active_tasks <= _max_worker_id, "we should not have more");
|
||||
|
||||
@ -796,7 +814,7 @@ void ConcurrentMark::set_phase(uint active_tasks, bool concurrent) {
|
||||
void ConcurrentMark::set_non_marking_state() {
|
||||
// We set the global marking state to some default values when we're
|
||||
// not doing marking.
|
||||
clear_marking_state();
|
||||
reset_marking_state();
|
||||
_active_tasks = 0;
|
||||
clear_concurrent_marking_in_progress();
|
||||
}
|
||||
@ -963,7 +981,7 @@ void ConcurrentMark::enter_first_sync_barrier(uint worker_id) {
|
||||
// not clear the overflow flag since we rely on it being true when
|
||||
// we exit this method to abort the pause and restart concurent
|
||||
// marking.
|
||||
clear_marking_state(concurrent() /* clear_overflow */);
|
||||
reset_marking_state(concurrent() /* clear_overflow */);
|
||||
force_overflow()->update();
|
||||
|
||||
if (G1Log::fine()) {
|
||||
@ -1257,8 +1275,9 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
|
||||
if (has_overflown()) {
|
||||
// Oops. We overflowed. Restart concurrent marking.
|
||||
_restart_for_overflow = true;
|
||||
// Clear the flag. We do not need it any more.
|
||||
clear_has_overflown();
|
||||
// Clear the marking state because we will be restarting
|
||||
// marking due to overflowing the global mark stack.
|
||||
reset_marking_state();
|
||||
if (G1TraceMarkStackOverflow) {
|
||||
gclog_or_tty->print_cr("\nRemark led to restart for overflow.");
|
||||
}
|
||||
@ -1282,6 +1301,8 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
|
||||
/* option */ VerifyOption_G1UseNextMarking);
|
||||
}
|
||||
assert(!restart_for_overflow(), "sanity");
|
||||
// Completely reset the marking state since marking completed
|
||||
set_non_marking_state();
|
||||
}
|
||||
|
||||
// Expand the marking stack, if we have to and if we can.
|
||||
@ -1289,11 +1310,6 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
|
||||
_markStack.expand();
|
||||
}
|
||||
|
||||
// Reset the marking state if marking completed
|
||||
if (!restart_for_overflow()) {
|
||||
set_non_marking_state();
|
||||
}
|
||||
|
||||
#if VERIFY_OBJS_PROCESSED
|
||||
_scan_obj_cl.objs_processed = 0;
|
||||
ThreadLocalObjQueue::objs_enqueued = 0;
|
||||
@ -2963,22 +2979,6 @@ void ConcurrentMark::verify_no_cset_oops(bool verify_stacks,
|
||||
}
|
||||
#endif // PRODUCT
|
||||
|
||||
void ConcurrentMark::clear_marking_state(bool clear_overflow) {
|
||||
_markStack.set_should_expand();
|
||||
_markStack.setEmpty(); // Also clears the _markStack overflow flag
|
||||
if (clear_overflow) {
|
||||
clear_has_overflown();
|
||||
} else {
|
||||
assert(has_overflown(), "pre-condition");
|
||||
}
|
||||
_finger = _heap_start;
|
||||
|
||||
for (uint i = 0; i < _max_worker_id; ++i) {
|
||||
CMTaskQueue* queue = _task_queues->queue(i);
|
||||
queue->set_empty();
|
||||
}
|
||||
}
|
||||
|
||||
// Aggregate the counting data that was constructed concurrently
|
||||
// with marking.
|
||||
class AggregateCountDataHRClosure: public HeapRegionClosure {
|
||||
@ -3185,7 +3185,7 @@ void ConcurrentMark::abort() {
|
||||
// Clear the liveness counting data
|
||||
clear_all_count_data();
|
||||
// Empty mark stack
|
||||
clear_marking_state();
|
||||
reset_marking_state();
|
||||
for (uint i = 0; i < _max_worker_id; ++i) {
|
||||
_tasks[i]->clear_region_fields();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -478,15 +478,18 @@ protected:
|
||||
// It resets the global marking data structures, as well as the
|
||||
// task local ones; should be called during initial mark.
|
||||
void reset();
|
||||
// It resets all the marking data structures.
|
||||
void clear_marking_state(bool clear_overflow = true);
|
||||
|
||||
// Resets all the marking data structures. Called when we have to restart
|
||||
// marking or when marking completes (via set_non_marking_state below).
|
||||
void reset_marking_state(bool clear_overflow = true);
|
||||
|
||||
// We do this after we're done with marking so that the marking data
|
||||
// structures are initialised to a sensible and predictable state.
|
||||
void set_non_marking_state();
|
||||
|
||||
// It should be called to indicate which phase we're in (concurrent
|
||||
// mark or remark) and how many threads are currently active.
|
||||
void set_phase(uint active_tasks, bool concurrent);
|
||||
// We do this after we're done with marking so that the marking data
|
||||
// structures are initialised to a sensible and predictable state.
|
||||
void set_non_marking_state();
|
||||
|
||||
// prints all gathered CM-related statistics
|
||||
void print_stats();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -159,13 +159,11 @@ void ConcurrentMarkThread::run() {
|
||||
VM_CGC_Operation op(&final_cl, verbose_str, true /* needs_pll */);
|
||||
VMThread::execute(&op);
|
||||
}
|
||||
if (cm()->restart_for_overflow() &&
|
||||
G1TraceMarkStackOverflow) {
|
||||
gclog_or_tty->print_cr("Restarting conc marking because of MS overflow "
|
||||
"in remark (restart #%d).", iter);
|
||||
}
|
||||
|
||||
if (cm()->restart_for_overflow()) {
|
||||
if (G1TraceMarkStackOverflow) {
|
||||
gclog_or_tty->print_cr("Restarting conc marking because of MS overflow "
|
||||
"in remark (restart #%d).", iter);
|
||||
}
|
||||
if (G1Log::fine()) {
|
||||
gclog_or_tty->date_stamp(PrintGCDateStamps);
|
||||
gclog_or_tty->stamp(PrintGCTimeStamps);
|
||||
|
@ -3668,7 +3668,7 @@ void G1CollectedHeap::log_gc_header() {
|
||||
gclog_or_tty->stamp(PrintGCTimeStamps);
|
||||
|
||||
GCCauseString gc_cause_str = GCCauseString("GC pause", gc_cause())
|
||||
.append(g1_policy()->gcs_are_young() ? " (young)" : " (mixed)")
|
||||
.append(g1_policy()->gcs_are_young() ? "(young)" : "(mixed)")
|
||||
.append(g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : "");
|
||||
|
||||
gclog_or_tty->print("[%s", (const char*)gc_cause_str);
|
||||
|
@ -309,9 +309,9 @@ void G1CollectorPolicy::initialize_flags() {
|
||||
}
|
||||
|
||||
G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true) {
|
||||
assert(G1DefaultMinNewGenPercent <= G1DefaultMaxNewGenPercent, "Min larger than max");
|
||||
assert(G1DefaultMinNewGenPercent > 0 && G1DefaultMinNewGenPercent < 100, "Min out of bounds");
|
||||
assert(G1DefaultMaxNewGenPercent > 0 && G1DefaultMaxNewGenPercent < 100, "Max out of bounds");
|
||||
assert(G1NewSizePercent <= G1MaxNewSizePercent, "Min larger than max");
|
||||
assert(G1NewSizePercent > 0 && G1NewSizePercent < 100, "Min out of bounds");
|
||||
assert(G1MaxNewSizePercent > 0 && G1MaxNewSizePercent < 100, "Max out of bounds");
|
||||
|
||||
if (FLAG_IS_CMDLINE(NewRatio)) {
|
||||
if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) {
|
||||
@ -344,12 +344,12 @@ G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(
|
||||
}
|
||||
|
||||
uint G1YoungGenSizer::calculate_default_min_length(uint new_number_of_heap_regions) {
|
||||
uint default_value = (new_number_of_heap_regions * G1DefaultMinNewGenPercent) / 100;
|
||||
uint default_value = (new_number_of_heap_regions * G1NewSizePercent) / 100;
|
||||
return MAX2(1U, default_value);
|
||||
}
|
||||
|
||||
uint G1YoungGenSizer::calculate_default_max_length(uint new_number_of_heap_regions) {
|
||||
uint default_value = (new_number_of_heap_regions * G1DefaultMaxNewGenPercent) / 100;
|
||||
uint default_value = (new_number_of_heap_regions * G1MaxNewSizePercent) / 100;
|
||||
return MAX2(1U, default_value);
|
||||
}
|
||||
|
||||
|
@ -94,18 +94,18 @@ class TraceGen1TimeData : public CHeapObj<mtGC> {
|
||||
// will occur.
|
||||
//
|
||||
// If nothing related to the the young gen size is set on the command
|
||||
// line we should allow the young gen to be between
|
||||
// G1DefaultMinNewGenPercent and G1DefaultMaxNewGenPercent of the
|
||||
// heap size. This means that every time the heap size changes the
|
||||
// limits for the young gen size will be updated.
|
||||
// line we should allow the young gen to be between G1NewSizePercent
|
||||
// and G1MaxNewSizePercent of the heap size. This means that every time
|
||||
// the heap size changes, the limits for the young gen size will be
|
||||
// recalculated.
|
||||
//
|
||||
// If only -XX:NewSize is set we should use the specified value as the
|
||||
// minimum size for young gen. Still using G1DefaultMaxNewGenPercent
|
||||
// of the heap as maximum.
|
||||
// minimum size for young gen. Still using G1MaxNewSizePercent of the
|
||||
// heap as maximum.
|
||||
//
|
||||
// If only -XX:MaxNewSize is set we should use the specified value as the
|
||||
// maximum size for young gen. Still using G1DefaultMinNewGenPercent
|
||||
// of the heap as minimum.
|
||||
// maximum size for young gen. Still using G1NewSizePercent of the heap
|
||||
// as minimum.
|
||||
//
|
||||
// If -XX:NewSize and -XX:MaxNewSize are both specified we use these values.
|
||||
// No updates when the heap size changes. There is a special case when
|
||||
|
@ -282,10 +282,8 @@ class G1AdjustPointersClosure: public HeapRegionClosure {
|
||||
if (r->startsHumongous()) {
|
||||
// We must adjust the pointers on the single H object.
|
||||
oop obj = oop(r->bottom());
|
||||
debug_only(GenMarkSweep::track_interior_pointers(obj));
|
||||
// point all the oops to the new location
|
||||
obj->adjust_pointers();
|
||||
debug_only(GenMarkSweep::check_interior_pointers());
|
||||
}
|
||||
} else {
|
||||
// This really ought to be "as_CompactibleSpace"...
|
||||
|
@ -287,17 +287,18 @@
|
||||
"The number of times we'll force an overflow during " \
|
||||
"concurrent marking") \
|
||||
\
|
||||
experimental(uintx, G1DefaultMinNewGenPercent, 20, \
|
||||
"Percentage (0-100) of the heap size to use as minimum " \
|
||||
"young gen size.") \
|
||||
experimental(uintx, G1NewSizePercent, 20, \
|
||||
"Percentage (0-100) of the heap size to use as default " \
|
||||
"minimum young gen size.") \
|
||||
\
|
||||
experimental(uintx, G1DefaultMaxNewGenPercent, 80, \
|
||||
"Percentage (0-100) of the heap size to use as maximum " \
|
||||
"young gen size.") \
|
||||
experimental(uintx, G1MaxNewSizePercent, 80, \
|
||||
"Percentage (0-100) of the heap size to use as default " \
|
||||
" maximum young gen size.") \
|
||||
\
|
||||
experimental(uintx, G1OldCSetRegionLiveThresholdPercent, 90, \
|
||||
"Threshold for regions to be added to the collection set. " \
|
||||
"Regions with more live bytes than this will not be collected.") \
|
||||
experimental(uintx, G1MixedGCLiveThresholdPercent, 90, \
|
||||
"Threshold for regions to be considered for inclusion in the " \
|
||||
"collection set of mixed GCs. " \
|
||||
"Regions with live bytes exceeding this will not be collected.") \
|
||||
\
|
||||
product(uintx, G1HeapWastePercent, 5, \
|
||||
"Amount of space, expressed as a percentage of the heap size, " \
|
||||
|
@ -1623,7 +1623,3 @@ void ParNewGeneration::ref_processor_init()
|
||||
const char* ParNewGeneration::name() const {
|
||||
return "par new generation";
|
||||
}
|
||||
|
||||
bool ParNewGeneration::in_use() {
|
||||
return UseParNewGC && ParallelGCThreads > 0;
|
||||
}
|
||||
|
@ -361,8 +361,6 @@ class ParNewGeneration: public DefNewGeneration {
|
||||
delete _task_queues;
|
||||
}
|
||||
|
||||
static bool in_use();
|
||||
|
||||
virtual void ref_processor_init();
|
||||
virtual Generation::Name kind() { return Generation::ParNew; }
|
||||
virtual const char* name() const;
|
||||
|
@ -164,7 +164,6 @@ void PSMarkSweepDecorator::precompact() {
|
||||
start_array->allocate_block(compact_top);
|
||||
}
|
||||
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::register_live_oop(oop(q), size));
|
||||
compact_top += size;
|
||||
assert(compact_top <= dest->space()->end(),
|
||||
"Exceeding space in destination");
|
||||
@ -225,7 +224,6 @@ void PSMarkSweepDecorator::precompact() {
|
||||
start_array->allocate_block(compact_top);
|
||||
}
|
||||
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::register_live_oop(oop(q), sz));
|
||||
compact_top += sz;
|
||||
assert(compact_top <= dest->space()->end(),
|
||||
"Exceeding space in destination");
|
||||
@ -304,11 +302,8 @@ void PSMarkSweepDecorator::adjust_pointers() {
|
||||
HeapWord* end = _first_dead;
|
||||
|
||||
while (q < end) {
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q)));
|
||||
// point all the oops to the new location
|
||||
size_t size = oop(q)->adjust_pointers();
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers());
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size));
|
||||
q += size;
|
||||
}
|
||||
|
||||
@ -328,11 +323,8 @@ void PSMarkSweepDecorator::adjust_pointers() {
|
||||
Prefetch::write(q, interval);
|
||||
if (oop(q)->is_gc_marked()) {
|
||||
// q is alive
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q)));
|
||||
// point all the oops to the new location
|
||||
size_t size = oop(q)->adjust_pointers();
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers());
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size));
|
||||
debug_only(prev_q = q);
|
||||
q += size;
|
||||
} else {
|
||||
@ -366,7 +358,6 @@ void PSMarkSweepDecorator::compact(bool mangle_free_space ) {
|
||||
while (q < end) {
|
||||
size_t size = oop(q)->size();
|
||||
assert(!oop(q)->is_gc_marked(), "should be unmarked (special dense prefix handling)");
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size, q));
|
||||
debug_only(prev_q = q);
|
||||
q += size;
|
||||
}
|
||||
@ -401,7 +392,6 @@ void PSMarkSweepDecorator::compact(bool mangle_free_space ) {
|
||||
Prefetch::write(compaction_top, copy_interval);
|
||||
|
||||
// copy object and reinit its mark
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size, compaction_top));
|
||||
assert(q != compaction_top, "everything in this pass should be moving");
|
||||
Copy::aligned_conjoint_words(q, compaction_top, size);
|
||||
oop(compaction_top)->init_mark();
|
||||
|
@ -99,25 +99,6 @@ double PSParallelCompact::_dwl_adjustment;
|
||||
bool PSParallelCompact::_dwl_initialized = false;
|
||||
#endif // #ifdef ASSERT
|
||||
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
GrowableArray<void*>* PSParallelCompact::_root_refs_stack = NULL;
|
||||
GrowableArray<oop> * PSParallelCompact::_live_oops = NULL;
|
||||
GrowableArray<oop> * PSParallelCompact::_live_oops_moved_to = NULL;
|
||||
GrowableArray<size_t>* PSParallelCompact::_live_oops_size = NULL;
|
||||
size_t PSParallelCompact::_live_oops_index = 0;
|
||||
GrowableArray<void*>* PSParallelCompact::_other_refs_stack = NULL;
|
||||
GrowableArray<void*>* PSParallelCompact::_adjusted_pointers = NULL;
|
||||
bool PSParallelCompact::_pointer_tracking = false;
|
||||
bool PSParallelCompact::_root_tracking = true;
|
||||
|
||||
GrowableArray<HeapWord*>* PSParallelCompact::_cur_gc_live_oops = NULL;
|
||||
GrowableArray<HeapWord*>* PSParallelCompact::_cur_gc_live_oops_moved_to = NULL;
|
||||
GrowableArray<size_t> * PSParallelCompact::_cur_gc_live_oops_size = NULL;
|
||||
GrowableArray<HeapWord*>* PSParallelCompact::_last_gc_live_oops = NULL;
|
||||
GrowableArray<HeapWord*>* PSParallelCompact::_last_gc_live_oops_moved_to = NULL;
|
||||
GrowableArray<size_t> * PSParallelCompact::_last_gc_live_oops_size = NULL;
|
||||
#endif
|
||||
|
||||
void SplitInfo::record(size_t src_region_idx, size_t partial_obj_size,
|
||||
HeapWord* destination)
|
||||
{
|
||||
@ -2715,151 +2696,6 @@ void PSParallelCompact::verify_complete(SpaceId space_id) {
|
||||
}
|
||||
#endif // #ifdef ASSERT
|
||||
|
||||
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
|
||||
void PSParallelCompact::track_adjusted_pointer(void* p, bool isroot) {
|
||||
if (!ValidateMarkSweep)
|
||||
return;
|
||||
|
||||
if (!isroot) {
|
||||
if (_pointer_tracking) {
|
||||
guarantee(_adjusted_pointers->contains(p), "should have seen this pointer");
|
||||
_adjusted_pointers->remove(p);
|
||||
}
|
||||
} else {
|
||||
ptrdiff_t index = _root_refs_stack->find(p);
|
||||
if (index != -1) {
|
||||
int l = _root_refs_stack->length();
|
||||
if (l > 0 && l - 1 != index) {
|
||||
void* last = _root_refs_stack->pop();
|
||||
assert(last != p, "should be different");
|
||||
_root_refs_stack->at_put(index, last);
|
||||
} else {
|
||||
_root_refs_stack->remove(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PSParallelCompact::check_adjust_pointer(void* p) {
|
||||
_adjusted_pointers->push(p);
|
||||
}
|
||||
|
||||
|
||||
class AdjusterTracker: public OopClosure {
|
||||
public:
|
||||
AdjusterTracker() {};
|
||||
void do_oop(oop* o) { PSParallelCompact::check_adjust_pointer(o); }
|
||||
void do_oop(narrowOop* o) { PSParallelCompact::check_adjust_pointer(o); }
|
||||
};
|
||||
|
||||
|
||||
void PSParallelCompact::track_interior_pointers(oop obj) {
|
||||
if (ValidateMarkSweep) {
|
||||
_adjusted_pointers->clear();
|
||||
_pointer_tracking = true;
|
||||
|
||||
AdjusterTracker checker;
|
||||
obj->oop_iterate_no_header(&checker);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PSParallelCompact::check_interior_pointers() {
|
||||
if (ValidateMarkSweep) {
|
||||
_pointer_tracking = false;
|
||||
guarantee(_adjusted_pointers->length() == 0, "should have processed the same pointers");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PSParallelCompact::reset_live_oop_tracking() {
|
||||
if (ValidateMarkSweep) {
|
||||
guarantee((size_t)_live_oops->length() == _live_oops_index, "should be at end of live oops");
|
||||
_live_oops_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PSParallelCompact::register_live_oop(oop p, size_t size) {
|
||||
if (ValidateMarkSweep) {
|
||||
_live_oops->push(p);
|
||||
_live_oops_size->push(size);
|
||||
_live_oops_index++;
|
||||
}
|
||||
}
|
||||
|
||||
void PSParallelCompact::validate_live_oop(oop p, size_t size) {
|
||||
if (ValidateMarkSweep) {
|
||||
oop obj = _live_oops->at((int)_live_oops_index);
|
||||
guarantee(obj == p, "should be the same object");
|
||||
guarantee(_live_oops_size->at((int)_live_oops_index) == size, "should be the same size");
|
||||
_live_oops_index++;
|
||||
}
|
||||
}
|
||||
|
||||
void PSParallelCompact::live_oop_moved_to(HeapWord* q, size_t size,
|
||||
HeapWord* compaction_top) {
|
||||
assert(oop(q)->forwardee() == NULL || oop(q)->forwardee() == oop(compaction_top),
|
||||
"should be moved to forwarded location");
|
||||
if (ValidateMarkSweep) {
|
||||
PSParallelCompact::validate_live_oop(oop(q), size);
|
||||
_live_oops_moved_to->push(oop(compaction_top));
|
||||
}
|
||||
if (RecordMarkSweepCompaction) {
|
||||
_cur_gc_live_oops->push(q);
|
||||
_cur_gc_live_oops_moved_to->push(compaction_top);
|
||||
_cur_gc_live_oops_size->push(size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PSParallelCompact::compaction_complete() {
|
||||
if (RecordMarkSweepCompaction) {
|
||||
GrowableArray<HeapWord*>* _tmp_live_oops = _cur_gc_live_oops;
|
||||
GrowableArray<HeapWord*>* _tmp_live_oops_moved_to = _cur_gc_live_oops_moved_to;
|
||||
GrowableArray<size_t> * _tmp_live_oops_size = _cur_gc_live_oops_size;
|
||||
|
||||
_cur_gc_live_oops = _last_gc_live_oops;
|
||||
_cur_gc_live_oops_moved_to = _last_gc_live_oops_moved_to;
|
||||
_cur_gc_live_oops_size = _last_gc_live_oops_size;
|
||||
_last_gc_live_oops = _tmp_live_oops;
|
||||
_last_gc_live_oops_moved_to = _tmp_live_oops_moved_to;
|
||||
_last_gc_live_oops_size = _tmp_live_oops_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PSParallelCompact::print_new_location_of_heap_address(HeapWord* q) {
|
||||
if (!RecordMarkSweepCompaction) {
|
||||
tty->print_cr("Requires RecordMarkSweepCompaction to be enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_last_gc_live_oops == NULL) {
|
||||
tty->print_cr("No compaction information gathered yet");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _last_gc_live_oops->length(); i++) {
|
||||
HeapWord* old_oop = _last_gc_live_oops->at(i);
|
||||
size_t sz = _last_gc_live_oops_size->at(i);
|
||||
if (old_oop <= q && q < (old_oop + sz)) {
|
||||
HeapWord* new_oop = _last_gc_live_oops_moved_to->at(i);
|
||||
size_t offset = (q - old_oop);
|
||||
tty->print_cr("Address " PTR_FORMAT, q);
|
||||
tty->print_cr(" Was in oop " PTR_FORMAT ", size %d, at offset %d", old_oop, sz, offset);
|
||||
tty->print_cr(" Now in oop " PTR_FORMAT ", actual address " PTR_FORMAT, new_oop, new_oop + offset);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tty->print_cr("Address " PTR_FORMAT " not found in live oop information from last GC", q);
|
||||
}
|
||||
#endif //VALIDATE_MARK_SWEEP
|
||||
|
||||
// Update interior oops in the ranges of regions [beg_region, end_region).
|
||||
void
|
||||
PSParallelCompact::update_and_deadwood_in_dense_prefix(ParCompactionManager* cm,
|
||||
|
@ -1006,34 +1006,6 @@ class PSParallelCompact : AllStatic {
|
||||
// Reset time since last full gc
|
||||
static void reset_millis_since_last_gc();
|
||||
|
||||
protected:
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
static GrowableArray<void*>* _root_refs_stack;
|
||||
static GrowableArray<oop> * _live_oops;
|
||||
static GrowableArray<oop> * _live_oops_moved_to;
|
||||
static GrowableArray<size_t>* _live_oops_size;
|
||||
static size_t _live_oops_index;
|
||||
static size_t _live_oops_index_at_perm;
|
||||
static GrowableArray<void*>* _other_refs_stack;
|
||||
static GrowableArray<void*>* _adjusted_pointers;
|
||||
static bool _pointer_tracking;
|
||||
static bool _root_tracking;
|
||||
|
||||
// The following arrays are saved since the time of the last GC and
|
||||
// assist in tracking down problems where someone has done an errant
|
||||
// store into the heap, usually to an oop that wasn't properly
|
||||
// handleized across a GC. If we crash or otherwise fail before the
|
||||
// next GC, we can query these arrays to find out the object we had
|
||||
// intended to do the store to (assuming it is still alive) and the
|
||||
// offset within that object. Covered under RecordMarkSweepCompaction.
|
||||
static GrowableArray<HeapWord*> * _cur_gc_live_oops;
|
||||
static GrowableArray<HeapWord*> * _cur_gc_live_oops_moved_to;
|
||||
static GrowableArray<size_t>* _cur_gc_live_oops_size;
|
||||
static GrowableArray<HeapWord*> * _last_gc_live_oops;
|
||||
static GrowableArray<HeapWord*> * _last_gc_live_oops_moved_to;
|
||||
static GrowableArray<size_t>* _last_gc_live_oops_size;
|
||||
#endif
|
||||
|
||||
public:
|
||||
class MarkAndPushClosure: public OopClosure {
|
||||
private:
|
||||
@ -1191,25 +1163,6 @@ class PSParallelCompact : AllStatic {
|
||||
// Time since last full gc (in milliseconds).
|
||||
static jlong millis_since_last_gc();
|
||||
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
static void track_adjusted_pointer(void* p, bool isroot);
|
||||
static void check_adjust_pointer(void* p);
|
||||
static void track_interior_pointers(oop obj);
|
||||
static void check_interior_pointers();
|
||||
|
||||
static void reset_live_oop_tracking();
|
||||
static void register_live_oop(oop p, size_t size);
|
||||
static void validate_live_oop(oop p, size_t size);
|
||||
static void live_oop_moved_to(HeapWord* q, size_t size, HeapWord* compaction_top);
|
||||
static void compaction_complete();
|
||||
|
||||
// Querying operation of RecordMarkSweepCompaction results.
|
||||
// Finds and prints the current base oop and offset for a word
|
||||
// within an oop that was live during the last GC. Helpful for
|
||||
// tracking down heap stomps.
|
||||
static void print_new_location_of_heap_address(HeapWord* q);
|
||||
#endif // #ifdef VALIDATE_MARK_SWEEP
|
||||
|
||||
#ifndef PRODUCT
|
||||
// Debugging support.
|
||||
static const char* space_names[last_space_id];
|
||||
@ -1250,12 +1203,7 @@ template <class T>
|
||||
inline void PSParallelCompact::follow_root(ParCompactionManager* cm, T* p) {
|
||||
assert(!Universe::heap()->is_in_reserved(p),
|
||||
"roots shouldn't be things within the heap");
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
if (ValidateMarkSweep) {
|
||||
guarantee(!_root_refs_stack->contains(p), "should only be in here once");
|
||||
_root_refs_stack->push(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
T heap_oop = oopDesc::load_heap_oop(p);
|
||||
if (!oopDesc::is_null(heap_oop)) {
|
||||
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
|
||||
@ -1294,20 +1242,10 @@ inline void PSParallelCompact::adjust_pointer(T* p, bool isroot) {
|
||||
oopDesc::encode_store_heap_oop_not_null(p, new_obj);
|
||||
}
|
||||
}
|
||||
VALIDATE_MARK_SWEEP_ONLY(track_adjusted_pointer(p, isroot));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void PSParallelCompact::KeepAliveClosure::do_oop_work(T* p) {
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
if (ValidateMarkSweep) {
|
||||
if (!Universe::heap()->is_in_reserved(p)) {
|
||||
_root_refs_stack->push(p);
|
||||
} else {
|
||||
_other_refs_stack->push(p);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
mark_and_push(_compaction_manager, p);
|
||||
}
|
||||
|
||||
|
@ -808,8 +808,9 @@ void PSYoungGen::print_on(outputStream* st) const {
|
||||
st->print(" to "); to_space()->print_on(st);
|
||||
}
|
||||
|
||||
// Note that a space is not printed before the [NAME:
|
||||
void PSYoungGen::print_used_change(size_t prev_used) const {
|
||||
gclog_or_tty->print(" [%s:", name());
|
||||
gclog_or_tty->print("[%s:", name());
|
||||
gclog_or_tty->print(" " SIZE_FORMAT "K"
|
||||
"->" SIZE_FORMAT "K"
|
||||
"(" SIZE_FORMAT "K)",
|
||||
|
@ -42,26 +42,6 @@ size_t MarkSweep::_preserved_count_max = 0;
|
||||
PreservedMark* MarkSweep::_preserved_marks = NULL;
|
||||
ReferenceProcessor* MarkSweep::_ref_processor = NULL;
|
||||
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
GrowableArray<void*>* MarkSweep::_root_refs_stack = NULL;
|
||||
GrowableArray<oop> * MarkSweep::_live_oops = NULL;
|
||||
GrowableArray<oop> * MarkSweep::_live_oops_moved_to = NULL;
|
||||
GrowableArray<size_t>* MarkSweep::_live_oops_size = NULL;
|
||||
size_t MarkSweep::_live_oops_index = 0;
|
||||
size_t MarkSweep::_live_oops_index_at_perm = 0;
|
||||
GrowableArray<void*>* MarkSweep::_other_refs_stack = NULL;
|
||||
GrowableArray<void*>* MarkSweep::_adjusted_pointers = NULL;
|
||||
bool MarkSweep::_pointer_tracking = false;
|
||||
bool MarkSweep::_root_tracking = true;
|
||||
|
||||
GrowableArray<HeapWord*>* MarkSweep::_cur_gc_live_oops = NULL;
|
||||
GrowableArray<HeapWord*>* MarkSweep::_cur_gc_live_oops_moved_to = NULL;
|
||||
GrowableArray<size_t> * MarkSweep::_cur_gc_live_oops_size = NULL;
|
||||
GrowableArray<HeapWord*>* MarkSweep::_last_gc_live_oops = NULL;
|
||||
GrowableArray<HeapWord*>* MarkSweep::_last_gc_live_oops_moved_to = NULL;
|
||||
GrowableArray<size_t> * MarkSweep::_last_gc_live_oops_size = NULL;
|
||||
#endif
|
||||
|
||||
MarkSweep::FollowRootClosure MarkSweep::follow_root_closure;
|
||||
CodeBlobToOopClosure MarkSweep::follow_code_root_closure(&MarkSweep::follow_root_closure, /*do_marking=*/ true);
|
||||
|
||||
@ -185,142 +165,6 @@ void MarkSweep::restore_marks() {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
|
||||
void MarkSweep::track_adjusted_pointer(void* p, bool isroot) {
|
||||
if (!ValidateMarkSweep)
|
||||
return;
|
||||
|
||||
if (!isroot) {
|
||||
if (_pointer_tracking) {
|
||||
guarantee(_adjusted_pointers->contains(p), "should have seen this pointer");
|
||||
_adjusted_pointers->remove(p);
|
||||
}
|
||||
} else {
|
||||
ptrdiff_t index = _root_refs_stack->find(p);
|
||||
if (index != -1) {
|
||||
int l = _root_refs_stack->length();
|
||||
if (l > 0 && l - 1 != index) {
|
||||
void* last = _root_refs_stack->pop();
|
||||
assert(last != p, "should be different");
|
||||
_root_refs_stack->at_put(index, last);
|
||||
} else {
|
||||
_root_refs_stack->remove(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MarkSweep::check_adjust_pointer(void* p) {
|
||||
_adjusted_pointers->push(p);
|
||||
}
|
||||
|
||||
class AdjusterTracker: public OopClosure {
|
||||
public:
|
||||
AdjusterTracker() {}
|
||||
void do_oop(oop* o) { MarkSweep::check_adjust_pointer(o); }
|
||||
void do_oop(narrowOop* o) { MarkSweep::check_adjust_pointer(o); }
|
||||
};
|
||||
|
||||
void MarkSweep::track_interior_pointers(oop obj) {
|
||||
if (ValidateMarkSweep) {
|
||||
_adjusted_pointers->clear();
|
||||
_pointer_tracking = true;
|
||||
|
||||
AdjusterTracker checker;
|
||||
obj->oop_iterate_no_header(&checker);
|
||||
}
|
||||
}
|
||||
|
||||
void MarkSweep::check_interior_pointers() {
|
||||
if (ValidateMarkSweep) {
|
||||
_pointer_tracking = false;
|
||||
guarantee(_adjusted_pointers->length() == 0, "should have processed the same pointers");
|
||||
}
|
||||
}
|
||||
|
||||
void MarkSweep::reset_live_oop_tracking() {
|
||||
if (ValidateMarkSweep) {
|
||||
guarantee((size_t)_live_oops->length() == _live_oops_index, "should be at end of live oops");
|
||||
_live_oops_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MarkSweep::register_live_oop(oop p, size_t size) {
|
||||
if (ValidateMarkSweep) {
|
||||
_live_oops->push(p);
|
||||
_live_oops_size->push(size);
|
||||
_live_oops_index++;
|
||||
}
|
||||
}
|
||||
|
||||
void MarkSweep::validate_live_oop(oop p, size_t size) {
|
||||
if (ValidateMarkSweep) {
|
||||
oop obj = _live_oops->at((int)_live_oops_index);
|
||||
guarantee(obj == p, "should be the same object");
|
||||
guarantee(_live_oops_size->at((int)_live_oops_index) == size, "should be the same size");
|
||||
_live_oops_index++;
|
||||
}
|
||||
}
|
||||
|
||||
void MarkSweep::live_oop_moved_to(HeapWord* q, size_t size,
|
||||
HeapWord* compaction_top) {
|
||||
assert(oop(q)->forwardee() == NULL || oop(q)->forwardee() == oop(compaction_top),
|
||||
"should be moved to forwarded location");
|
||||
if (ValidateMarkSweep) {
|
||||
MarkSweep::validate_live_oop(oop(q), size);
|
||||
_live_oops_moved_to->push(oop(compaction_top));
|
||||
}
|
||||
if (RecordMarkSweepCompaction) {
|
||||
_cur_gc_live_oops->push(q);
|
||||
_cur_gc_live_oops_moved_to->push(compaction_top);
|
||||
_cur_gc_live_oops_size->push(size);
|
||||
}
|
||||
}
|
||||
|
||||
void MarkSweep::compaction_complete() {
|
||||
if (RecordMarkSweepCompaction) {
|
||||
GrowableArray<HeapWord*>* _tmp_live_oops = _cur_gc_live_oops;
|
||||
GrowableArray<HeapWord*>* _tmp_live_oops_moved_to = _cur_gc_live_oops_moved_to;
|
||||
GrowableArray<size_t> * _tmp_live_oops_size = _cur_gc_live_oops_size;
|
||||
|
||||
_cur_gc_live_oops = _last_gc_live_oops;
|
||||
_cur_gc_live_oops_moved_to = _last_gc_live_oops_moved_to;
|
||||
_cur_gc_live_oops_size = _last_gc_live_oops_size;
|
||||
_last_gc_live_oops = _tmp_live_oops;
|
||||
_last_gc_live_oops_moved_to = _tmp_live_oops_moved_to;
|
||||
_last_gc_live_oops_size = _tmp_live_oops_size;
|
||||
}
|
||||
}
|
||||
|
||||
void MarkSweep::print_new_location_of_heap_address(HeapWord* q) {
|
||||
if (!RecordMarkSweepCompaction) {
|
||||
tty->print_cr("Requires RecordMarkSweepCompaction to be enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_last_gc_live_oops == NULL) {
|
||||
tty->print_cr("No compaction information gathered yet");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _last_gc_live_oops->length(); i++) {
|
||||
HeapWord* old_oop = _last_gc_live_oops->at(i);
|
||||
size_t sz = _last_gc_live_oops_size->at(i);
|
||||
if (old_oop <= q && q < (old_oop + sz)) {
|
||||
HeapWord* new_oop = _last_gc_live_oops_moved_to->at(i);
|
||||
size_t offset = (q - old_oop);
|
||||
tty->print_cr("Address " PTR_FORMAT, q);
|
||||
tty->print_cr(" Was in oop " PTR_FORMAT ", size " SIZE_FORMAT ", at offset " SIZE_FORMAT, old_oop, sz, offset);
|
||||
tty->print_cr(" Now in oop " PTR_FORMAT ", actual address " PTR_FORMAT, new_oop, new_oop + offset);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tty->print_cr("Address " PTR_FORMAT " not found in live oop information from last GC", q);
|
||||
}
|
||||
#endif //VALIDATE_MARK_SWEEP
|
||||
|
||||
MarkSweep::IsAliveClosure MarkSweep::is_alive;
|
||||
|
||||
void MarkSweep::IsAliveClosure::do_object(oop p) { ShouldNotReachHere(); }
|
||||
|
@ -44,21 +44,6 @@ class DataLayout;
|
||||
//
|
||||
// Class unloading will only occur when a full gc is invoked.
|
||||
|
||||
// If VALIDATE_MARK_SWEEP is defined, the -XX:+ValidateMarkSweep flag will
|
||||
// be operational, and will provide slow but comprehensive self-checks within
|
||||
// the GC. This is not enabled by default in product or release builds,
|
||||
// since the extra call to track_adjusted_pointer() in _adjust_pointer()
|
||||
// would be too much overhead, and would disturb performance measurement.
|
||||
// However, debug builds are sometimes way too slow to run GC tests!
|
||||
#ifdef ASSERT
|
||||
#define VALIDATE_MARK_SWEEP 1
|
||||
#endif
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
#define VALIDATE_MARK_SWEEP_ONLY(code) code
|
||||
#else
|
||||
#define VALIDATE_MARK_SWEEP_ONLY(code)
|
||||
#endif
|
||||
|
||||
// declared at end
|
||||
class PreservedMark;
|
||||
|
||||
@ -147,33 +132,6 @@ class MarkSweep : AllStatic {
|
||||
// Reference processing (used in ...follow_contents)
|
||||
static ReferenceProcessor* _ref_processor;
|
||||
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
static GrowableArray<void*>* _root_refs_stack;
|
||||
static GrowableArray<oop> * _live_oops;
|
||||
static GrowableArray<oop> * _live_oops_moved_to;
|
||||
static GrowableArray<size_t>* _live_oops_size;
|
||||
static size_t _live_oops_index;
|
||||
static size_t _live_oops_index_at_perm;
|
||||
static GrowableArray<void*>* _other_refs_stack;
|
||||
static GrowableArray<void*>* _adjusted_pointers;
|
||||
static bool _pointer_tracking;
|
||||
static bool _root_tracking;
|
||||
|
||||
// The following arrays are saved since the time of the last GC and
|
||||
// assist in tracking down problems where someone has done an errant
|
||||
// store into the heap, usually to an oop that wasn't properly
|
||||
// handleized across a GC. If we crash or otherwise fail before the
|
||||
// next GC, we can query these arrays to find out the object we had
|
||||
// intended to do the store to (assuming it is still alive) and the
|
||||
// offset within that object. Covered under RecordMarkSweepCompaction.
|
||||
static GrowableArray<HeapWord*> * _cur_gc_live_oops;
|
||||
static GrowableArray<HeapWord*> * _cur_gc_live_oops_moved_to;
|
||||
static GrowableArray<size_t>* _cur_gc_live_oops_size;
|
||||
static GrowableArray<HeapWord*> * _last_gc_live_oops;
|
||||
static GrowableArray<HeapWord*> * _last_gc_live_oops_moved_to;
|
||||
static GrowableArray<size_t>* _last_gc_live_oops_size;
|
||||
#endif
|
||||
|
||||
// Non public closures
|
||||
static KeepAliveClosure keep_alive;
|
||||
|
||||
@ -227,24 +185,6 @@ class MarkSweep : AllStatic {
|
||||
static void adjust_pointer(oop* p) { adjust_pointer(p, false); }
|
||||
static void adjust_pointer(narrowOop* p) { adjust_pointer(p, false); }
|
||||
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
static void track_adjusted_pointer(void* p, bool isroot);
|
||||
static void check_adjust_pointer(void* p);
|
||||
static void track_interior_pointers(oop obj);
|
||||
static void check_interior_pointers();
|
||||
|
||||
static void reset_live_oop_tracking();
|
||||
static void register_live_oop(oop p, size_t size);
|
||||
static void validate_live_oop(oop p, size_t size);
|
||||
static void live_oop_moved_to(HeapWord* q, size_t size, HeapWord* compaction_top);
|
||||
static void compaction_complete();
|
||||
|
||||
// Querying operation of RecordMarkSweepCompaction results.
|
||||
// Finds and prints the current base oop and offset for a word
|
||||
// within an oop that was live during the last GC. Helpful for
|
||||
// tracking down heap stomps.
|
||||
static void print_new_location_of_heap_address(HeapWord* q);
|
||||
#endif
|
||||
};
|
||||
|
||||
class PreservedMark VALUE_OBJ_CLASS_SPEC {
|
||||
|
@ -46,12 +46,6 @@ inline void MarkSweep::mark_object(oop obj) {
|
||||
template <class T> inline void MarkSweep::follow_root(T* p) {
|
||||
assert(!Universe::heap()->is_in_reserved(p),
|
||||
"roots shouldn't be things within the heap");
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
if (ValidateMarkSweep) {
|
||||
guarantee(!_root_refs_stack->contains(p), "should only be in here once");
|
||||
_root_refs_stack->push(p);
|
||||
}
|
||||
#endif
|
||||
T heap_oop = oopDesc::load_heap_oop(p);
|
||||
if (!oopDesc::is_null(heap_oop)) {
|
||||
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
|
||||
@ -97,19 +91,9 @@ template <class T> inline void MarkSweep::adjust_pointer(T* p, bool isroot) {
|
||||
oopDesc::encode_store_heap_oop_not_null(p, new_obj);
|
||||
}
|
||||
}
|
||||
VALIDATE_MARK_SWEEP_ONLY(track_adjusted_pointer(p, isroot));
|
||||
}
|
||||
|
||||
template <class T> inline void MarkSweep::KeepAliveClosure::do_oop_work(T* p) {
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
if (ValidateMarkSweep) {
|
||||
if (!Universe::heap()->is_in_reserved(p)) {
|
||||
_root_refs_stack->push(p);
|
||||
} else {
|
||||
_other_refs_stack->push(p);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
mark_and_push(p);
|
||||
}
|
||||
|
||||
|
@ -99,9 +99,9 @@ class GCCauseString : StackObj {
|
||||
public:
|
||||
GCCauseString(const char* prefix, GCCause::Cause cause) {
|
||||
if (PrintGCCause) {
|
||||
_position = jio_snprintf(_buffer, _length, "%s (%s)", prefix, GCCause::to_string(cause));
|
||||
_position = jio_snprintf(_buffer, _length, "%s (%s) ", prefix, GCCause::to_string(cause));
|
||||
} else {
|
||||
_position = jio_snprintf(_buffer, _length, "%s", prefix);
|
||||
_position = jio_snprintf(_buffer, _length, "%s ", prefix);
|
||||
}
|
||||
assert(_position >= 0 && _position <= _length,
|
||||
err_msg("Need to increase the buffer size in GCCauseString? %d", _position));
|
||||
|
@ -417,7 +417,7 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
|
||||
|
||||
// exception handler lookup
|
||||
KlassHandle h_klass(THREAD, h_exception->klass());
|
||||
handler_bci = h_method->fast_exception_handler_bci_for(h_klass, current_bci, THREAD);
|
||||
handler_bci = Method::fast_exception_handler_bci_for(h_method, h_klass, current_bci, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
// We threw an exception while trying to find the exception handler.
|
||||
// Transfer the new exception to the exception handle which will
|
||||
|
@ -27,13 +27,8 @@
|
||||
#include "interpreter/interpreter.hpp"
|
||||
#include "interpreter/rewriter.hpp"
|
||||
#include "memory/gcLocker.hpp"
|
||||
#include "memory/metadataFactory.hpp"
|
||||
#include "memory/oopFactory.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/generateOopMap.hpp"
|
||||
#include "oops/objArrayOop.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "prims/methodComparator.hpp"
|
||||
#include "prims/methodHandles.hpp"
|
||||
|
||||
// Computes a CPC map (new_index -> original_index) for constant pool entries
|
||||
@ -402,13 +397,6 @@ void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) {
|
||||
}
|
||||
|
||||
|
||||
void Rewriter::rewrite(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS) {
|
||||
ResourceMark rm(THREAD);
|
||||
Rewriter rw(klass, cpool, methods, CHECK);
|
||||
// (That's all, folks.)
|
||||
}
|
||||
|
||||
|
||||
Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS)
|
||||
: _klass(klass),
|
||||
_pool(cpool),
|
||||
@ -453,46 +441,25 @@ Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Me
|
||||
restore_bytecodes();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Relocate jsr/rets in a method. This can't be done with the rewriter
|
||||
// stage because it can throw other exceptions, leaving the bytecodes
|
||||
// pointing at constant pool cache entries.
|
||||
// Link and check jvmti dependencies while we're iterating over the methods.
|
||||
// JSR292 code calls with a different set of methods, so two entry points.
|
||||
void Rewriter::relocate_and_link(instanceKlassHandle this_oop, TRAPS) {
|
||||
relocate_and_link(this_oop, this_oop->methods(), THREAD);
|
||||
}
|
||||
|
||||
void Rewriter::relocate_and_link(instanceKlassHandle this_oop,
|
||||
Array<Method*>* methods, TRAPS) {
|
||||
int len = methods->length();
|
||||
// Relocate after everything, but still do this under the is_rewritten flag,
|
||||
// so methods with jsrs in custom class lists in aren't attempted to be
|
||||
// rewritten in the RO section of the shared archive.
|
||||
// Relocated bytecodes don't have to be restored, only the cp cache entries
|
||||
for (int i = len-1; i >= 0; i--) {
|
||||
methodHandle m(THREAD, methods->at(i));
|
||||
methodHandle m(THREAD, _methods->at(i));
|
||||
|
||||
if (m->has_jsrs()) {
|
||||
m = rewrite_jsrs(m, CHECK);
|
||||
m = rewrite_jsrs(m, THREAD);
|
||||
// Restore bytecodes to their unrewritten state if there are exceptions
|
||||
// relocating bytecodes. If some are relocated, that is ok because that
|
||||
// doesn't affect constant pool to cpCache rewriting.
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
restore_bytecodes();
|
||||
return;
|
||||
}
|
||||
// Method might have gotten rewritten.
|
||||
methods->at_put(i, m());
|
||||
}
|
||||
|
||||
// Set up method entry points for compiler and interpreter .
|
||||
m->link_method(m, CHECK);
|
||||
|
||||
// This is for JVMTI and unrelated to relocator but the last thing we do
|
||||
#ifdef ASSERT
|
||||
if (StressMethodComparator) {
|
||||
static int nmc = 0;
|
||||
for (int j = i; j >= 0 && j >= i-4; j--) {
|
||||
if ((++nmc % 1000) == 0) tty->print_cr("Have run MethodComparator %d times...", nmc);
|
||||
bool z = MethodComparator::methods_EMCP(m(),
|
||||
methods->at(j));
|
||||
if (j == i && !z) {
|
||||
tty->print("MethodComparator FAIL: "); m->print(); m->print_codes();
|
||||
assert(z, "method must compare equal to itself");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //ASSERT
|
||||
}
|
||||
}
|
||||
|
@ -158,14 +158,6 @@ class Rewriter: public StackObj {
|
||||
public:
|
||||
// Driver routine:
|
||||
static void rewrite(instanceKlassHandle klass, TRAPS);
|
||||
static void rewrite(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS);
|
||||
|
||||
// Second pass, not gated by is_rewritten flag
|
||||
static void relocate_and_link(instanceKlassHandle klass, TRAPS);
|
||||
// JSR292 version to call with it's own methods.
|
||||
static void relocate_and_link(instanceKlassHandle klass,
|
||||
Array<Method*>* methods, TRAPS);
|
||||
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_INTERPRETER_REWRITER_HPP
|
||||
|
@ -67,7 +67,8 @@ void TreeChunk<Chunk_t, FreeList_t>::verify_tree_chunk_list() const {
|
||||
}
|
||||
|
||||
template <class Chunk_t, template <class> class FreeList_t>
|
||||
TreeList<Chunk_t, FreeList_t>::TreeList() {}
|
||||
TreeList<Chunk_t, FreeList_t>::TreeList() : _parent(NULL),
|
||||
_left(NULL), _right(NULL) {}
|
||||
|
||||
template <class Chunk_t, template <class> class FreeList_t>
|
||||
TreeList<Chunk_t, FreeList_t>*
|
||||
@ -82,7 +83,7 @@ TreeList<Chunk_t, FreeList_t>::as_TreeList(TreeChunk<Chunk_t,FreeList_t>* tc) {
|
||||
tl->link_head(tc);
|
||||
tl->link_tail(tc);
|
||||
tl->set_count(1);
|
||||
|
||||
assert(tl->parent() == NULL, "Should be clear");
|
||||
return tl;
|
||||
}
|
||||
|
||||
|
@ -777,6 +777,15 @@ MetaWord* CollectorPolicy::satisfy_failed_metadata_allocation(
|
||||
full_gc_count,
|
||||
GCCause::_metadata_GC_threshold);
|
||||
VMThread::execute(&op);
|
||||
|
||||
// If GC was locked out, try again. Check
|
||||
// before checking success because the prologue
|
||||
// could have succeeded and the GC still have
|
||||
// been locked out.
|
||||
if (op.gc_locked()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (op.prologue_succeeded()) {
|
||||
return op.result();
|
||||
}
|
||||
@ -818,7 +827,7 @@ void MarkSweepPolicy::initialize_generations() {
|
||||
if (_generations == NULL)
|
||||
vm_exit_during_initialization("Unable to allocate gen spec");
|
||||
|
||||
if (UseParNewGC && ParallelGCThreads > 0) {
|
||||
if (UseParNewGC) {
|
||||
_generations[0] = new GenerationSpec(Generation::ParNew, _initial_gen0_size, _max_gen0_size);
|
||||
} else {
|
||||
_generations[0] = new GenerationSpec(Generation::DefNew, _initial_gen0_size, _max_gen0_size);
|
||||
@ -831,10 +840,9 @@ void MarkSweepPolicy::initialize_generations() {
|
||||
|
||||
void MarkSweepPolicy::initialize_gc_policy_counters() {
|
||||
// initialize the policy counters - 2 collectors, 3 generations
|
||||
if (UseParNewGC && ParallelGCThreads > 0) {
|
||||
if (UseParNewGC) {
|
||||
_gc_policy_counters = new GCPolicyCounters("ParNew:MSC", 2, 3);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_gc_policy_counters = new GCPolicyCounters("Copy:MSC", 2, 3);
|
||||
}
|
||||
}
|
||||
|
@ -119,6 +119,7 @@ void FileMapInfo::populate_header(size_t alignment) {
|
||||
_header._magic = 0xf00baba2;
|
||||
_header._version = _current_version;
|
||||
_header._alignment = alignment;
|
||||
_header._obj_alignment = ObjectAlignmentInBytes;
|
||||
|
||||
// The following fields are for sanity checks for whether this archive
|
||||
// will function correctly with this JVM and the bootclasspath it's
|
||||
@ -211,7 +212,11 @@ void FileMapInfo::open_for_write() {
|
||||
|
||||
// Remove the existing file in case another process has it open.
|
||||
remove(_full_path);
|
||||
#ifdef _WINDOWS // if 0444 is used on Windows, then remove() will fail.
|
||||
int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0744);
|
||||
#else
|
||||
int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444);
|
||||
#endif
|
||||
if (fd < 0) {
|
||||
fail_stop("Unable to create shared archive file %s.", _full_path);
|
||||
}
|
||||
@ -370,9 +375,8 @@ ReservedSpace FileMapInfo::reserve_shared_memory() {
|
||||
return rs;
|
||||
}
|
||||
// the reserved virtual memory is for mapping class data sharing archive
|
||||
if (MemTracker::is_on()) {
|
||||
MemTracker::record_virtual_memory_type((address)rs.base(), mtClassShared);
|
||||
}
|
||||
MemTracker::record_virtual_memory_type((address)rs.base(), mtClassShared);
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
@ -394,6 +398,11 @@ char* FileMapInfo::map_region(int i) {
|
||||
fail_continue(err_msg("Unable to map %s shared space at required address.", shared_region_name[i]));
|
||||
return NULL;
|
||||
}
|
||||
#ifdef _WINDOWS
|
||||
// This call is Windows-only because the memory_type gets recorded for the other platforms
|
||||
// in method FileMapInfo::reserve_shared_memory(), which is not called on Windows.
|
||||
MemTracker::record_virtual_memory_type((address)base, mtClassShared);
|
||||
#endif
|
||||
return base;
|
||||
}
|
||||
|
||||
@ -465,6 +474,12 @@ bool FileMapInfo::validate() {
|
||||
" version or build of HotSpot.");
|
||||
return false;
|
||||
}
|
||||
if (_header._obj_alignment != ObjectAlignmentInBytes) {
|
||||
fail_continue("The shared archive file's ObjectAlignmentInBytes of %d"
|
||||
" does not equal the current ObjectAlignmentInBytes of %d.",
|
||||
_header._obj_alignment, ObjectAlignmentInBytes);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cannot verify interpreter yet, as it can only be created after the GC
|
||||
// heap has been initialized.
|
||||
|
@ -63,6 +63,7 @@ private:
|
||||
int _magic; // identify file type.
|
||||
int _version; // (from enum, above.)
|
||||
size_t _alignment; // how shared archive should be aligned
|
||||
int _obj_alignment; // value of ObjectAlignmentInBytes
|
||||
|
||||
struct space_info {
|
||||
int _file_offset; // sizeof(this) rounded to vm page size
|
||||
|
@ -100,21 +100,8 @@ void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp,
|
||||
|
||||
mark_sweep_phase3(level);
|
||||
|
||||
VALIDATE_MARK_SWEEP_ONLY(
|
||||
if (ValidateMarkSweep) {
|
||||
guarantee(_root_refs_stack->length() == 0, "should be empty by now");
|
||||
}
|
||||
)
|
||||
|
||||
mark_sweep_phase4();
|
||||
|
||||
VALIDATE_MARK_SWEEP_ONLY(
|
||||
if (ValidateMarkSweep) {
|
||||
guarantee(_live_oops->length() == _live_oops_moved_to->length(),
|
||||
"should be the same size");
|
||||
}
|
||||
)
|
||||
|
||||
restore_marks();
|
||||
|
||||
// Set saved marks for allocation profiler (and other things? -- dld)
|
||||
@ -187,31 +174,6 @@ void GenMarkSweep::allocate_stacks() {
|
||||
|
||||
_preserved_marks = (PreservedMark*)scratch;
|
||||
_preserved_count = 0;
|
||||
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
if (ValidateMarkSweep) {
|
||||
_root_refs_stack = new (ResourceObj::C_HEAP, mtGC) GrowableArray<void*>(100, true);
|
||||
_other_refs_stack = new (ResourceObj::C_HEAP, mtGC) GrowableArray<void*>(100, true);
|
||||
_adjusted_pointers = new (ResourceObj::C_HEAP, mtGC) GrowableArray<void*>(100, true);
|
||||
_live_oops = new (ResourceObj::C_HEAP, mtGC) GrowableArray<oop>(100, true);
|
||||
_live_oops_moved_to = new (ResourceObj::C_HEAP, mtGC) GrowableArray<oop>(100, true);
|
||||
_live_oops_size = new (ResourceObj::C_HEAP, mtGC) GrowableArray<size_t>(100, true);
|
||||
}
|
||||
if (RecordMarkSweepCompaction) {
|
||||
if (_cur_gc_live_oops == NULL) {
|
||||
_cur_gc_live_oops = new(ResourceObj::C_HEAP, mtGC) GrowableArray<HeapWord*>(100, true);
|
||||
_cur_gc_live_oops_moved_to = new(ResourceObj::C_HEAP, mtGC) GrowableArray<HeapWord*>(100, true);
|
||||
_cur_gc_live_oops_size = new(ResourceObj::C_HEAP, mtGC) GrowableArray<size_t>(100, true);
|
||||
_last_gc_live_oops = new(ResourceObj::C_HEAP, mtGC) GrowableArray<HeapWord*>(100, true);
|
||||
_last_gc_live_oops_moved_to = new(ResourceObj::C_HEAP, mtGC) GrowableArray<HeapWord*>(100, true);
|
||||
_last_gc_live_oops_size = new(ResourceObj::C_HEAP, mtGC) GrowableArray<size_t>(100, true);
|
||||
} else {
|
||||
_cur_gc_live_oops->clear();
|
||||
_cur_gc_live_oops_moved_to->clear();
|
||||
_cur_gc_live_oops_size->clear();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -225,19 +187,6 @@ void GenMarkSweep::deallocate_stacks() {
|
||||
_preserved_oop_stack.clear(true);
|
||||
_marking_stack.clear();
|
||||
_objarray_stack.clear(true);
|
||||
|
||||
#ifdef VALIDATE_MARK_SWEEP
|
||||
if (ValidateMarkSweep) {
|
||||
delete _root_refs_stack;
|
||||
delete _other_refs_stack;
|
||||
delete _adjusted_pointers;
|
||||
delete _live_oops;
|
||||
delete _live_oops_size;
|
||||
delete _live_oops_moved_to;
|
||||
_live_oops_index = 0;
|
||||
_live_oops_index_at_perm = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GenMarkSweep::mark_sweep_phase1(int level,
|
||||
@ -246,8 +195,6 @@ void GenMarkSweep::mark_sweep_phase1(int level,
|
||||
TraceTime tm("phase 1", PrintGC && Verbose, true, gclog_or_tty);
|
||||
trace(" 1");
|
||||
|
||||
VALIDATE_MARK_SWEEP_ONLY(reset_live_oop_tracking());
|
||||
|
||||
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
||||
|
||||
// Because follow_root_closure is created statically, cannot
|
||||
@ -315,8 +262,6 @@ void GenMarkSweep::mark_sweep_phase2() {
|
||||
TraceTime tm("phase 2", PrintGC && Verbose, true, gclog_or_tty);
|
||||
trace("2");
|
||||
|
||||
VALIDATE_MARK_SWEEP_ONLY(reset_live_oop_tracking());
|
||||
|
||||
gch->prepare_for_compaction();
|
||||
}
|
||||
|
||||
@ -337,8 +282,6 @@ void GenMarkSweep::mark_sweep_phase3(int level) {
|
||||
// Need new claim bits for the pointer adjustment tracing.
|
||||
ClassLoaderDataGraph::clear_claimed_marks();
|
||||
|
||||
VALIDATE_MARK_SWEEP_ONLY(reset_live_oop_tracking());
|
||||
|
||||
// Because the two closures below are created statically, cannot
|
||||
// use OopsInGenClosure constructor which takes a generation,
|
||||
// as the Universe has not been created when the static constructors
|
||||
@ -393,10 +336,6 @@ void GenMarkSweep::mark_sweep_phase4() {
|
||||
TraceTime tm("phase 4", PrintGC && Verbose, true, gclog_or_tty);
|
||||
trace("4");
|
||||
|
||||
VALIDATE_MARK_SWEEP_ONLY(reset_live_oop_tracking());
|
||||
|
||||
GenCompactClosure blk;
|
||||
gch->generation_iterate(&blk, true);
|
||||
|
||||
VALIDATE_MARK_SWEEP_ONLY(compaction_complete());
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ Metachunk* Metachunk::initialize(MetaWord* ptr, size_t word_size) {
|
||||
assert(chunk_end > chunk_bottom, "Chunk must be too small");
|
||||
chunk->set_end(chunk_end);
|
||||
chunk->set_next(NULL);
|
||||
chunk->set_prev(NULL);
|
||||
chunk->set_word_size(word_size);
|
||||
#ifdef ASSERT
|
||||
size_t data_word_size = pointer_delta(chunk_end, chunk_bottom, sizeof(MetaWord));
|
||||
@ -76,15 +77,15 @@ MetaWord* Metachunk::allocate(size_t word_size) {
|
||||
}
|
||||
|
||||
// _bottom points to the start of the chunk including the overhead.
|
||||
size_t Metachunk::used_word_size() {
|
||||
size_t Metachunk::used_word_size() const {
|
||||
return pointer_delta(_top, _bottom, sizeof(MetaWord));
|
||||
}
|
||||
|
||||
size_t Metachunk::free_word_size() {
|
||||
size_t Metachunk::free_word_size() const {
|
||||
return pointer_delta(_end, _top, sizeof(MetaWord));
|
||||
}
|
||||
|
||||
size_t Metachunk::capacity_word_size() {
|
||||
size_t Metachunk::capacity_word_size() const {
|
||||
return pointer_delta(_end, _bottom, sizeof(MetaWord));
|
||||
}
|
||||
|
||||
@ -93,6 +94,10 @@ void Metachunk::print_on(outputStream* st) const {
|
||||
" bottom " PTR_FORMAT " top " PTR_FORMAT
|
||||
" end " PTR_FORMAT " size " SIZE_FORMAT,
|
||||
bottom(), top(), end(), word_size());
|
||||
if (Verbose) {
|
||||
st->print_cr(" used " SIZE_FORMAT " free " SIZE_FORMAT,
|
||||
used_word_size(), free_word_size());
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
@ -67,9 +67,11 @@ class Metachunk VALUE_OBJ_CLASS_SPEC {
|
||||
void set_word_size(size_t v) { _word_size = v; }
|
||||
public:
|
||||
#ifdef ASSERT
|
||||
Metachunk() : _bottom(NULL), _end(NULL), _top(NULL), _is_free(false) {}
|
||||
Metachunk() : _bottom(NULL), _end(NULL), _top(NULL), _is_free(false),
|
||||
_next(NULL), _prev(NULL) {}
|
||||
#else
|
||||
Metachunk() : _bottom(NULL), _end(NULL), _top(NULL) {}
|
||||
Metachunk() : _bottom(NULL), _end(NULL), _top(NULL),
|
||||
_next(NULL), _prev(NULL) {}
|
||||
#endif
|
||||
|
||||
// Used to add a Metachunk to a list of Metachunks
|
||||
@ -102,15 +104,15 @@ class Metachunk VALUE_OBJ_CLASS_SPEC {
|
||||
}
|
||||
|
||||
// Reset top to bottom so chunk can be reused.
|
||||
void reset_empty() { _top = (_bottom + _overhead); }
|
||||
void reset_empty() { _top = (_bottom + _overhead); _next = NULL; _prev = NULL; }
|
||||
bool is_empty() { return _top == (_bottom + _overhead); }
|
||||
|
||||
// used (has been allocated)
|
||||
// free (available for future allocations)
|
||||
// capacity (total size of chunk)
|
||||
size_t used_word_size();
|
||||
size_t free_word_size();
|
||||
size_t capacity_word_size();
|
||||
size_t used_word_size() const;
|
||||
size_t free_word_size() const;
|
||||
size_t capacity_word_size()const;
|
||||
|
||||
// Debug support
|
||||
#ifdef ASSERT
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -87,11 +87,23 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||
|
||||
public:
|
||||
enum MetadataType {ClassType, NonClassType};
|
||||
enum MetaspaceType {
|
||||
StandardMetaspaceType,
|
||||
BootMetaspaceType,
|
||||
ROMetaspaceType,
|
||||
ReadWriteMetaspaceType,
|
||||
AnonymousMetaspaceType,
|
||||
ReflectionMetaspaceType
|
||||
};
|
||||
|
||||
private:
|
||||
void initialize(Mutex* lock, size_t initial_size = 0);
|
||||
void initialize(Mutex* lock, MetaspaceType type);
|
||||
|
||||
// Align up the word size to the allocation word size
|
||||
static size_t align_word_size_up(size_t);
|
||||
|
||||
static size_t _first_chunk_word_size;
|
||||
static size_t _first_class_chunk_word_size;
|
||||
|
||||
SpaceManager* _vsm;
|
||||
SpaceManager* vsm() const { return _vsm; }
|
||||
@ -110,8 +122,7 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||
|
||||
public:
|
||||
|
||||
Metaspace(Mutex* lock, size_t initial_size);
|
||||
Metaspace(Mutex* lock);
|
||||
Metaspace(Mutex* lock, MetaspaceType type);
|
||||
~Metaspace();
|
||||
|
||||
// Initialize globals for Metaspace
|
||||
@ -119,6 +130,7 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||
static void initialize_class_space(ReservedSpace rs);
|
||||
|
||||
static size_t first_chunk_word_size() { return _first_chunk_word_size; }
|
||||
static size_t first_class_chunk_word_size() { return _first_class_chunk_word_size; }
|
||||
|
||||
char* bottom() const;
|
||||
size_t used_words(MetadataType mdtype) const;
|
||||
|
@ -689,9 +689,15 @@ void MetaspaceShared::print_shared_spaces() {
|
||||
bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
|
||||
size_t image_alignment = mapinfo->alignment();
|
||||
|
||||
// Map in the shared memory and then map the regions on top of it
|
||||
#ifndef _WINDOWS
|
||||
// Map in the shared memory and then map the regions on top of it.
|
||||
// On Windows, don't map the memory here because it will cause the
|
||||
// mappings of the regions to fail.
|
||||
ReservedSpace shared_rs = mapinfo->reserve_shared_memory();
|
||||
if (!shared_rs.is_reserved()) return false;
|
||||
#endif
|
||||
|
||||
assert(!DumpSharedSpaces, "Should not be called with DumpSharedSpaces");
|
||||
|
||||
// Map each shared region
|
||||
if ((_ro_base = mapinfo->map_region(ro)) != NULL &&
|
||||
@ -708,8 +714,10 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
|
||||
if (_rw_base != NULL) mapinfo->unmap_region(rw);
|
||||
if (_md_base != NULL) mapinfo->unmap_region(md);
|
||||
if (_mc_base != NULL) mapinfo->unmap_region(mc);
|
||||
#ifndef _WINDOWS
|
||||
// Release the entire mapped region
|
||||
shared_rs.release();
|
||||
#endif
|
||||
// If -Xshare:on is specified, print out the error message and exit VM,
|
||||
// otherwise, set UseSharedSpaces to false and continue.
|
||||
if (RequireSharedSpaces) {
|
||||
|
@ -411,7 +411,6 @@ HeapWord* CompactibleSpace::forward(oop q, size_t size,
|
||||
assert(q->forwardee() == NULL, "should be forwarded to NULL");
|
||||
}
|
||||
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::register_live_oop(q, size));
|
||||
compact_top += size;
|
||||
|
||||
// we need to update the offset table so that the beginnings of objects can be
|
||||
@ -470,13 +469,10 @@ void Space::adjust_pointers() {
|
||||
if (oop(q)->is_gc_marked()) {
|
||||
// q is alive
|
||||
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q)));
|
||||
// point all the oops to the new location
|
||||
size_t size = oop(q)->adjust_pointers();
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers());
|
||||
|
||||
debug_only(prev_q = q);
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size));
|
||||
|
||||
q += size;
|
||||
} else {
|
||||
|
@ -655,16 +655,10 @@ protected:
|
||||
assert(block_is_obj(q), \
|
||||
"should be at block boundaries, and should be looking at objs"); \
|
||||
\
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q))); \
|
||||
\
|
||||
/* point all the oops to the new location */ \
|
||||
size_t size = oop(q)->adjust_pointers(); \
|
||||
size = adjust_obj_size(size); \
|
||||
\
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers()); \
|
||||
\
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size)); \
|
||||
\
|
||||
q += size; \
|
||||
} \
|
||||
\
|
||||
@ -685,12 +679,9 @@ protected:
|
||||
Prefetch::write(q, interval); \
|
||||
if (oop(q)->is_gc_marked()) { \
|
||||
/* q is alive */ \
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q))); \
|
||||
/* point all the oops to the new location */ \
|
||||
size_t size = oop(q)->adjust_pointers(); \
|
||||
size = adjust_obj_size(size); \
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers()); \
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size)); \
|
||||
debug_only(prev_q = q); \
|
||||
q += size; \
|
||||
} else { \
|
||||
@ -725,7 +716,6 @@ protected:
|
||||
size_t size = obj_size(q); \
|
||||
assert(!oop(q)->is_gc_marked(), \
|
||||
"should be unmarked (special dense prefix handling)"); \
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size, q)); \
|
||||
debug_only(prev_q = q); \
|
||||
q += size; \
|
||||
} \
|
||||
@ -759,8 +749,6 @@ protected:
|
||||
Prefetch::write(compaction_top, copy_interval); \
|
||||
\
|
||||
/* copy object and reinit its mark */ \
|
||||
VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size, \
|
||||
compaction_top)); \
|
||||
assert(q != compaction_top, "everything in this pass should be moving"); \
|
||||
Copy::aligned_conjoint_words(q, compaction_top, size); \
|
||||
oop(compaction_top)->init_mark(); \
|
||||
|
@ -62,7 +62,7 @@ TenuredGeneration::TenuredGeneration(ReservedSpace rs,
|
||||
_virtual_space.reserved_size(),
|
||||
_the_space, _gen_counters);
|
||||
#ifndef SERIALGC
|
||||
if (UseParNewGC && ParallelGCThreads > 0) {
|
||||
if (UseParNewGC) {
|
||||
typedef ParGCAllocBufferWithBOT* ParGCAllocBufferWithBOTPtr;
|
||||
_alloc_buffers = NEW_C_HEAP_ARRAY(ParGCAllocBufferWithBOTPtr,
|
||||
ParallelGCThreads, mtGC);
|
||||
|
@ -61,6 +61,9 @@ void Annotations::deallocate_contents(ClassLoaderData* loader_data) {
|
||||
free_contents(loader_data, methods_annotations());
|
||||
free_contents(loader_data, methods_parameter_annotations());
|
||||
free_contents(loader_data, methods_default_annotations());
|
||||
|
||||
// Recursively deallocate optional Annotations linked through this one
|
||||
MetadataFactory::free_metadata(loader_data, type_annotations());
|
||||
}
|
||||
|
||||
// Set the annotation at 'idnum' to 'anno'.
|
||||
|
@ -38,7 +38,8 @@ class outputStream;
|
||||
typedef Array<u1> AnnotationArray;
|
||||
|
||||
// Class to hold the various types of annotations. The only metadata that points
|
||||
// to this is InstanceKlass.
|
||||
// to this is InstanceKlass, or another Annotations instance if this is a
|
||||
// a type_annotation instance.
|
||||
|
||||
class Annotations: public MetaspaceObj {
|
||||
|
||||
@ -58,6 +59,8 @@ class Annotations: public MetaspaceObj {
|
||||
// such annotations.
|
||||
// Index is the idnum, which is initially the same as the methods array index.
|
||||
Array<AnnotationArray*>* _methods_default_annotations;
|
||||
// Type annotations for this class, or null if none.
|
||||
Annotations* _type_annotations;
|
||||
|
||||
// Constructor where some some values are known to not be null
|
||||
Annotations(Array<AnnotationArray*>* fa, Array<AnnotationArray*>* ma,
|
||||
@ -66,7 +69,8 @@ class Annotations: public MetaspaceObj {
|
||||
_fields_annotations(fa),
|
||||
_methods_annotations(ma),
|
||||
_methods_parameter_annotations(mpa),
|
||||
_methods_default_annotations(mda) {}
|
||||
_methods_default_annotations(mda),
|
||||
_type_annotations(NULL) {}
|
||||
|
||||
public:
|
||||
// Allocate instance of this class
|
||||
@ -81,22 +85,26 @@ class Annotations: public MetaspaceObj {
|
||||
static int size() { return sizeof(Annotations) / wordSize; }
|
||||
|
||||
// Constructor to initialize to null
|
||||
Annotations() : _class_annotations(NULL), _fields_annotations(NULL),
|
||||
Annotations() : _class_annotations(NULL),
|
||||
_fields_annotations(NULL),
|
||||
_methods_annotations(NULL),
|
||||
_methods_parameter_annotations(NULL),
|
||||
_methods_default_annotations(NULL) {}
|
||||
_methods_default_annotations(NULL),
|
||||
_type_annotations(NULL) {}
|
||||
|
||||
AnnotationArray* class_annotations() const { return _class_annotations; }
|
||||
Array<AnnotationArray*>* fields_annotations() const { return _fields_annotations; }
|
||||
Array<AnnotationArray*>* methods_annotations() const { return _methods_annotations; }
|
||||
Array<AnnotationArray*>* methods_parameter_annotations() const { return _methods_parameter_annotations; }
|
||||
Array<AnnotationArray*>* methods_default_annotations() const { return _methods_default_annotations; }
|
||||
Annotations* type_annotations() const { return _type_annotations; }
|
||||
|
||||
void set_class_annotations(AnnotationArray* md) { _class_annotations = md; }
|
||||
void set_fields_annotations(Array<AnnotationArray*>* md) { _fields_annotations = md; }
|
||||
void set_methods_annotations(Array<AnnotationArray*>* md) { _methods_annotations = md; }
|
||||
void set_methods_parameter_annotations(Array<AnnotationArray*>* md) { _methods_parameter_annotations = md; }
|
||||
void set_methods_default_annotations(Array<AnnotationArray*>* md) { _methods_default_annotations = md; }
|
||||
void set_type_annotations(Annotations* annos) { _type_annotations = annos; }
|
||||
|
||||
// Redefine classes support
|
||||
AnnotationArray* get_method_annotations_of(int idnum)
|
||||
@ -129,6 +137,7 @@ class Annotations: public MetaspaceObj {
|
||||
inline AnnotationArray* get_method_annotations_from(int idnum, Array<AnnotationArray*>* annos);
|
||||
void set_annotations(Array<AnnotationArray*>* md, Array<AnnotationArray*>** md_p) { *md_p = md; }
|
||||
|
||||
bool is_klass() const { return false; }
|
||||
private:
|
||||
void set_methods_annotations_of(instanceKlassHandle ik,
|
||||
int idnum, AnnotationArray* anno,
|
||||
|
@ -39,18 +39,21 @@ ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
int method_parameters_length,
|
||||
u2 generic_signature_index,
|
||||
MethodType method_type,
|
||||
TRAPS) {
|
||||
int size = ConstMethod::size(byte_code_size,
|
||||
compressed_line_number_size,
|
||||
localvariable_table_length,
|
||||
exception_table_length,
|
||||
checked_exceptions_length,
|
||||
generic_signature_index);
|
||||
compressed_line_number_size,
|
||||
localvariable_table_length,
|
||||
exception_table_length,
|
||||
checked_exceptions_length,
|
||||
method_parameters_length,
|
||||
generic_signature_index);
|
||||
return new (loader_data, size, true, THREAD) ConstMethod(
|
||||
byte_code_size, compressed_line_number_size, localvariable_table_length,
|
||||
exception_table_length, checked_exceptions_length, generic_signature_index,
|
||||
exception_table_length, checked_exceptions_length,
|
||||
method_parameters_length, generic_signature_index,
|
||||
method_type, size);
|
||||
}
|
||||
|
||||
@ -59,6 +62,7 @@ ConstMethod::ConstMethod(int byte_code_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
int method_parameters_length,
|
||||
u2 generic_signature_index,
|
||||
MethodType method_type,
|
||||
int size) {
|
||||
@ -74,7 +78,8 @@ ConstMethod::ConstMethod(int byte_code_size,
|
||||
checked_exceptions_length,
|
||||
compressed_line_number_size,
|
||||
localvariable_table_length,
|
||||
exception_table_length);
|
||||
exception_table_length,
|
||||
method_parameters_length);
|
||||
set_method_type(method_type);
|
||||
assert(this->size() == size, "wrong size for object");
|
||||
}
|
||||
@ -92,11 +97,12 @@ void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {
|
||||
// How big must this constMethodObject be?
|
||||
|
||||
int ConstMethod::size(int code_size,
|
||||
int compressed_line_number_size,
|
||||
int local_variable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
u2 generic_signature_index) {
|
||||
int compressed_line_number_size,
|
||||
int local_variable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
int method_parameters_length,
|
||||
u2 generic_signature_index) {
|
||||
int extra_bytes = code_size;
|
||||
if (compressed_line_number_size > 0) {
|
||||
extra_bytes += compressed_line_number_size;
|
||||
@ -117,6 +123,10 @@ int ConstMethod::size(int code_size,
|
||||
if (generic_signature_index != 0) {
|
||||
extra_bytes += sizeof(u2);
|
||||
}
|
||||
if (method_parameters_length > 0) {
|
||||
extra_bytes += sizeof(u2);
|
||||
extra_bytes += method_parameters_length * sizeof(MethodParametersElement);
|
||||
}
|
||||
int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
|
||||
return align_object_size(header_size() + extra_words);
|
||||
}
|
||||
@ -143,6 +153,18 @@ u2* ConstMethod::generic_signature_index_addr() const {
|
||||
u2* ConstMethod::checked_exceptions_length_addr() const {
|
||||
// Located immediately before the generic signature index.
|
||||
assert(has_checked_exceptions(), "called only if table is present");
|
||||
if(has_method_parameters()) {
|
||||
// If method parameters present, locate immediately before them.
|
||||
return (u2*)method_parameters_start() - 1;
|
||||
} else {
|
||||
// Else, the exception table is at the end of the constMethod.
|
||||
return has_generic_signature() ? (last_u2_element() - 1) :
|
||||
last_u2_element();
|
||||
}
|
||||
}
|
||||
|
||||
u2* ConstMethod::method_parameters_length_addr() const {
|
||||
assert(has_method_parameters(), "called only if table is present");
|
||||
return has_generic_signature() ? (last_u2_element() - 1) :
|
||||
last_u2_element();
|
||||
}
|
||||
@ -153,11 +175,15 @@ u2* ConstMethod::exception_table_length_addr() const {
|
||||
// If checked_exception present, locate immediately before them.
|
||||
return (u2*) checked_exceptions_start() - 1;
|
||||
} else {
|
||||
// Else, the exception table is at the end of the constMethod or
|
||||
// immediately before the generic signature index.
|
||||
if(has_method_parameters()) {
|
||||
// If method parameters present, locate immediately before them.
|
||||
return (u2*)method_parameters_start() - 1;
|
||||
} else {
|
||||
// Else, the exception table is at the end of the constMethod.
|
||||
return has_generic_signature() ? (last_u2_element() - 1) :
|
||||
last_u2_element();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u2* ConstMethod::localvariable_table_length_addr() const {
|
||||
@ -170,12 +196,16 @@ u2* ConstMethod::localvariable_table_length_addr() const {
|
||||
// If checked_exception present, locate immediately before them.
|
||||
return (u2*) checked_exceptions_start() - 1;
|
||||
} else {
|
||||
// Else, the linenumber table is at the end of the constMethod or
|
||||
// immediately before the generic signature index.
|
||||
if(has_method_parameters()) {
|
||||
// If method parameters present, locate immediately before them.
|
||||
return (u2*)method_parameters_start() - 1;
|
||||
} else {
|
||||
// Else, the exception table is at the end of the constMethod.
|
||||
return has_generic_signature() ? (last_u2_element() - 1) :
|
||||
last_u2_element();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the flags to indicate the presence of these optional fields.
|
||||
@ -183,29 +213,57 @@ void ConstMethod::set_inlined_tables_length(u2 generic_signature_index,
|
||||
int checked_exceptions_len,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_len,
|
||||
int exception_table_len) {
|
||||
// Must be done in the order below, otherwise length_addr accessors
|
||||
// will not work. Only set bit in header if length is positive.
|
||||
int exception_table_len,
|
||||
int method_parameters_len) {
|
||||
assert(_flags == 0, "Error");
|
||||
if (compressed_line_number_size > 0) {
|
||||
if (compressed_line_number_size > 0)
|
||||
_flags |= _has_linenumber_table;
|
||||
}
|
||||
if (generic_signature_index != 0) {
|
||||
if (generic_signature_index != 0)
|
||||
_flags |= _has_generic_signature;
|
||||
*(generic_signature_index_addr()) = generic_signature_index;
|
||||
}
|
||||
if (checked_exceptions_len > 0) {
|
||||
if (method_parameters_len > 0)
|
||||
_flags |= _has_method_parameters;
|
||||
if (checked_exceptions_len > 0)
|
||||
_flags |= _has_checked_exceptions;
|
||||
*(checked_exceptions_length_addr()) = checked_exceptions_len;
|
||||
}
|
||||
if (exception_table_len > 0) {
|
||||
if (exception_table_len > 0)
|
||||
_flags |= _has_exception_table;
|
||||
*(exception_table_length_addr()) = exception_table_len;
|
||||
}
|
||||
if (localvariable_table_len > 0) {
|
||||
if (localvariable_table_len > 0)
|
||||
_flags |= _has_localvariable_table;
|
||||
|
||||
// This code is extremely brittle and should possibly be revised.
|
||||
// The *_length_addr functions walk backwards through the
|
||||
// constMethod data, using each of the length indexes ahead of them,
|
||||
// as well as the flags variable. Therefore, the indexes must be
|
||||
// initialized in reverse order, or else they will compute the wrong
|
||||
// offsets. Moving the initialization of _flags into a separate
|
||||
// block solves *half* of the problem, but the following part will
|
||||
// still break if the order is not exactly right.
|
||||
//
|
||||
// Also, the servicability agent needs to be informed anytime
|
||||
// anything is added here. It might be advisable to have some sort
|
||||
// of indication of this inline.
|
||||
if (generic_signature_index != 0)
|
||||
*(generic_signature_index_addr()) = generic_signature_index;
|
||||
// New data should probably go here.
|
||||
if (method_parameters_len > 0)
|
||||
*(method_parameters_length_addr()) = method_parameters_len;
|
||||
if (checked_exceptions_len > 0)
|
||||
*(checked_exceptions_length_addr()) = checked_exceptions_len;
|
||||
if (exception_table_len > 0)
|
||||
*(exception_table_length_addr()) = exception_table_len;
|
||||
if (localvariable_table_len > 0)
|
||||
*(localvariable_table_length_addr()) = localvariable_table_len;
|
||||
}
|
||||
}
|
||||
|
||||
int ConstMethod::method_parameters_length() const {
|
||||
return has_method_parameters() ? *(method_parameters_length_addr()) : 0;
|
||||
}
|
||||
|
||||
MethodParametersElement* ConstMethod::method_parameters_start() const {
|
||||
u2* addr = method_parameters_length_addr();
|
||||
u2 length = *addr;
|
||||
assert(length > 0, "should only be called if table is present");
|
||||
addr -= length * sizeof(MethodParametersElement) / sizeof(u2);
|
||||
return (MethodParametersElement*) addr;
|
||||
}
|
||||
|
||||
|
||||
@ -298,6 +356,10 @@ void ConstMethod::verify_on(outputStream* st) {
|
||||
}
|
||||
guarantee(compressed_table_end <= m_end, "invalid method layout");
|
||||
// Verify checked exceptions, exception table and local variable tables
|
||||
if (has_method_parameters()) {
|
||||
u2* addr = method_parameters_length_addr();
|
||||
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
|
||||
}
|
||||
if (has_checked_exceptions()) {
|
||||
u2* addr = checked_exceptions_length_addr();
|
||||
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
|
||||
@ -318,6 +380,8 @@ void ConstMethod::verify_on(outputStream* st) {
|
||||
uncompressed_table_start = (u2*) exception_table_start();
|
||||
} else if (has_checked_exceptions()) {
|
||||
uncompressed_table_start = (u2*) checked_exceptions_start();
|
||||
} else if (has_method_parameters()) {
|
||||
uncompressed_table_start = (u2*) method_parameters_start();
|
||||
} else {
|
||||
uncompressed_table_start = (u2*) m_end;
|
||||
}
|
||||
|
@ -77,9 +77,18 @@
|
||||
// | (access flags bit tells whether table is present) |
|
||||
// | (indexed from end of ConstMethod*) |
|
||||
// |------------------------------------------------------|
|
||||
// | method parameters elements + length (length last) |
|
||||
// | (length is u2, elements are u2, u4 structures) |
|
||||
// | (see class MethodParametersElement) |
|
||||
// | (access flags bit tells whether table is present) |
|
||||
// | (indexed from end of ConstMethod*) |
|
||||
// |------------------------------------------------------|
|
||||
// | generic signature index (u2) |
|
||||
// | (indexed from start of constMethodOop) |
|
||||
// |------------------------------------------------------|
|
||||
//
|
||||
// IMPORTANT: If anything gets added here, there need to be changes to
|
||||
// ensure that ServicabilityAgent doesn't get broken as a result!
|
||||
|
||||
|
||||
// Utitily class decribing elements in checked exceptions table inlined in Method*.
|
||||
@ -109,6 +118,13 @@ class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
|
||||
u2 catch_type_index;
|
||||
};
|
||||
|
||||
// Utility class describing elements in method parameters
|
||||
class MethodParametersElement VALUE_OBJ_CLASS_SPEC {
|
||||
public:
|
||||
u2 name_cp_index;
|
||||
u4 flags;
|
||||
};
|
||||
|
||||
|
||||
class ConstMethod : public MetaspaceObj {
|
||||
friend class VMStructs;
|
||||
@ -123,7 +139,8 @@ private:
|
||||
_has_localvariable_table = 4,
|
||||
_has_exception_table = 8,
|
||||
_has_generic_signature = 16,
|
||||
_is_overpass = 32
|
||||
_has_method_parameters = 32,
|
||||
_is_overpass = 64
|
||||
};
|
||||
|
||||
// Bit vector of signature
|
||||
@ -160,6 +177,7 @@ private:
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
int method_parameters_length,
|
||||
u2 generic_signature_index,
|
||||
MethodType is_overpass,
|
||||
int size);
|
||||
@ -171,6 +189,7 @@ public:
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
int method_parameters_length,
|
||||
u2 generic_signature_index,
|
||||
MethodType mt,
|
||||
TRAPS);
|
||||
@ -182,7 +201,8 @@ public:
|
||||
int checked_exceptions_len,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_len,
|
||||
int exception_table_len);
|
||||
int exception_table_len,
|
||||
int method_parameters_length);
|
||||
|
||||
bool has_generic_signature() const
|
||||
{ return (_flags & _has_generic_signature) != 0; }
|
||||
@ -199,6 +219,9 @@ public:
|
||||
bool has_exception_handler() const
|
||||
{ return (_flags & _has_exception_table) != 0; }
|
||||
|
||||
bool has_method_parameters() const
|
||||
{ return (_flags & _has_method_parameters) != 0; }
|
||||
|
||||
MethodType method_type() const {
|
||||
return ((_flags & _is_overpass) == 0) ? NORMAL : OVERPASS;
|
||||
}
|
||||
@ -284,10 +307,11 @@ public:
|
||||
|
||||
// Size needed
|
||||
static int size(int code_size, int compressed_line_number_size,
|
||||
int local_variable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
u2 generic_signature_index);
|
||||
int local_variable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
int method_parameters_length,
|
||||
u2 generic_signature_index);
|
||||
|
||||
int size() const { return _constMethod_size;}
|
||||
void set_constMethod_size(int size) { _constMethod_size = size; }
|
||||
@ -308,6 +332,7 @@ public:
|
||||
u2* checked_exceptions_length_addr() const;
|
||||
u2* localvariable_table_length_addr() const;
|
||||
u2* exception_table_length_addr() const;
|
||||
u2* method_parameters_length_addr() const;
|
||||
|
||||
// checked exceptions
|
||||
int checked_exceptions_length() const;
|
||||
@ -321,6 +346,10 @@ public:
|
||||
int exception_table_length() const;
|
||||
ExceptionTableElement* exception_table_start() const;
|
||||
|
||||
// method parameters table
|
||||
int method_parameters_length() const;
|
||||
MethodParametersElement* method_parameters_start() const;
|
||||
|
||||
// byte codes
|
||||
void set_code(address code) {
|
||||
if (code_size() > 0) {
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "oops/symbol.hpp"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
||||
#include "prims/methodComparator.hpp"
|
||||
#include "runtime/fieldDescriptor.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/javaCalls.hpp"
|
||||
@ -160,6 +161,8 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end,
|
||||
|
||||
#endif // ndef DTRACE_ENABLED
|
||||
|
||||
volatile int InstanceKlass::_total_instanceKlass_count = 0;
|
||||
|
||||
Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
|
||||
int vtable_len,
|
||||
int itable_len,
|
||||
@ -203,6 +206,7 @@ Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
|
||||
access_flags, !host_klass.is_null());
|
||||
}
|
||||
|
||||
Atomic::inc(&_total_instanceKlass_count);
|
||||
return ik;
|
||||
}
|
||||
|
||||
@ -361,6 +365,9 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
|
||||
set_protection_domain(NULL);
|
||||
set_signers(NULL);
|
||||
set_init_lock(NULL);
|
||||
|
||||
// We should deallocate the Annotations instance
|
||||
MetadataFactory::free_metadata(loader_data, annotations());
|
||||
set_annotations(NULL);
|
||||
}
|
||||
|
||||
@ -599,7 +606,7 @@ bool InstanceKlass::link_class_impl(
|
||||
}
|
||||
|
||||
// relocate jsrs and link methods after they are all rewritten
|
||||
this_oop->relocate_and_link_methods(CHECK_false);
|
||||
this_oop->link_methods(CHECK_false);
|
||||
|
||||
// Initialize the vtable and interface table after
|
||||
// methods have been rewritten since rewrite may
|
||||
@ -647,10 +654,31 @@ void InstanceKlass::rewrite_class(TRAPS) {
|
||||
// Now relocate and link method entry points after class is rewritten.
|
||||
// This is outside is_rewritten flag. In case of an exception, it can be
|
||||
// executed more than once.
|
||||
void InstanceKlass::relocate_and_link_methods(TRAPS) {
|
||||
assert(is_loaded(), "must be loaded");
|
||||
instanceKlassHandle this_oop(THREAD, this);
|
||||
Rewriter::relocate_and_link(this_oop, CHECK);
|
||||
void InstanceKlass::link_methods(TRAPS) {
|
||||
int len = methods()->length();
|
||||
for (int i = len-1; i >= 0; i--) {
|
||||
methodHandle m(THREAD, methods()->at(i));
|
||||
|
||||
// Set up method entry points for compiler and interpreter .
|
||||
m->link_method(m, CHECK);
|
||||
|
||||
// This is for JVMTI and unrelated to relocator but the last thing we do
|
||||
#ifdef ASSERT
|
||||
if (StressMethodComparator) {
|
||||
ResourceMark rm(THREAD);
|
||||
static int nmc = 0;
|
||||
for (int j = i; j >= 0 && j >= i-4; j--) {
|
||||
if ((++nmc % 1000) == 0) tty->print_cr("Have run MethodComparator %d times...", nmc);
|
||||
bool z = MethodComparator::methods_EMCP(m(),
|
||||
methods()->at(j));
|
||||
if (j == i && !z) {
|
||||
tty->print("MethodComparator FAIL: "); m->print(); m->print_codes();
|
||||
assert(z, "method must compare equal to itself");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //ASSERT
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2306,6 +2334,9 @@ void InstanceKlass::release_C_heap_structures() {
|
||||
if (_array_name != NULL) _array_name->decrement_refcount();
|
||||
if (_source_file_name != NULL) _source_file_name->decrement_refcount();
|
||||
if (_source_debug_extension != NULL) FREE_C_HEAP_ARRAY(char, _source_debug_extension, mtClass);
|
||||
|
||||
assert(_total_instanceKlass_count >= 1, "Sanity check");
|
||||
Atomic::dec(&_total_instanceKlass_count);
|
||||
}
|
||||
|
||||
void InstanceKlass::set_source_file_name(Symbol* n) {
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "oops/fieldInfo.hpp"
|
||||
#include "oops/instanceOop.hpp"
|
||||
#include "oops/klassVtable.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/handles.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "utilities/accessFlags.hpp"
|
||||
@ -170,6 +171,11 @@ class InstanceKlass: public Klass {
|
||||
initialization_error // error happened during initialization
|
||||
};
|
||||
|
||||
static int number_of_instance_classes() { return _total_instanceKlass_count; }
|
||||
|
||||
private:
|
||||
static volatile int _total_instanceKlass_count;
|
||||
|
||||
protected:
|
||||
// Protection domain.
|
||||
oop _protection_domain;
|
||||
@ -454,7 +460,7 @@ class InstanceKlass: public Klass {
|
||||
bool link_class_or_fail(TRAPS); // returns false on failure
|
||||
void unlink_class();
|
||||
void rewrite_class(TRAPS);
|
||||
void relocate_and_link_methods(TRAPS);
|
||||
void link_methods(TRAPS);
|
||||
Method* class_initializer();
|
||||
|
||||
// set the class to initialized if no static initializer is present
|
||||
@ -657,6 +663,10 @@ class InstanceKlass: public Klass {
|
||||
if (annotations() == NULL) return NULL;
|
||||
return annotations()->fields_annotations();
|
||||
}
|
||||
Annotations* type_annotations() const {
|
||||
if (annotations() == NULL) return NULL;
|
||||
return annotations()->type_annotations();
|
||||
}
|
||||
|
||||
// allocation
|
||||
instanceOop allocate_instance(TRAPS);
|
||||
|
@ -64,6 +64,7 @@ Method* Method::allocate(ClassLoaderData* loader_data,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
int method_parameters_length,
|
||||
u2 generic_signature_index,
|
||||
ConstMethod::MethodType method_type,
|
||||
TRAPS) {
|
||||
@ -75,6 +76,7 @@ Method* Method::allocate(ClassLoaderData* loader_data,
|
||||
localvariable_table_length,
|
||||
exception_table_length,
|
||||
checked_exceptions_length,
|
||||
method_parameters_length,
|
||||
generic_signature_index,
|
||||
method_type,
|
||||
CHECK_NULL);
|
||||
@ -192,16 +194,16 @@ char* Method::name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol
|
||||
return buf;
|
||||
}
|
||||
|
||||
int Method::fast_exception_handler_bci_for(KlassHandle ex_klass, int throw_bci, TRAPS) {
|
||||
int Method::fast_exception_handler_bci_for(methodHandle mh, KlassHandle ex_klass, int throw_bci, TRAPS) {
|
||||
// exception table holds quadruple entries of the form (beg_bci, end_bci, handler_bci, klass_index)
|
||||
// access exception table
|
||||
ExceptionTable table(this);
|
||||
ExceptionTable table(mh());
|
||||
int length = table.length();
|
||||
// iterate through all entries sequentially
|
||||
constantPoolHandle pool(THREAD, constants());
|
||||
constantPoolHandle pool(THREAD, mh->constants());
|
||||
for (int i = 0; i < length; i ++) {
|
||||
//reacquire the table in case a GC happened
|
||||
ExceptionTable table(this);
|
||||
ExceptionTable table(mh());
|
||||
int beg_bci = table.start_pc(i);
|
||||
int end_bci = table.end_pc(i);
|
||||
assert(beg_bci <= end_bci, "inconsistent exception table");
|
||||
@ -1035,8 +1037,10 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid,
|
||||
|
||||
methodHandle m;
|
||||
{
|
||||
Method* m_oop = Method::allocate(loader_data, 0, accessFlags_from(flags_bits),
|
||||
0, 0, 0, 0, 0, ConstMethod::NORMAL, CHECK_(empty));
|
||||
Method* m_oop = Method::allocate(loader_data, 0,
|
||||
accessFlags_from(flags_bits),
|
||||
0, 0, 0, 0, 0, 0,
|
||||
ConstMethod::NORMAL, CHECK_(empty));
|
||||
m = methodHandle(THREAD, m_oop);
|
||||
}
|
||||
m->set_constants(cp());
|
||||
@ -1088,6 +1092,7 @@ methodHandle Method::clone_with_new_data(methodHandle m, u_char* new_code, int n
|
||||
int checked_exceptions_len = m->checked_exceptions_length();
|
||||
int localvariable_len = m->localvariable_table_length();
|
||||
int exception_table_len = m->exception_table_length();
|
||||
int method_parameters_len = m->method_parameters_length();
|
||||
|
||||
ClassLoaderData* loader_data = m->method_holder()->class_loader_data();
|
||||
Method* newm_oop = Method::allocate(loader_data,
|
||||
@ -1097,6 +1102,7 @@ methodHandle Method::clone_with_new_data(methodHandle m, u_char* new_code, int n
|
||||
localvariable_len,
|
||||
exception_table_len,
|
||||
checked_exceptions_len,
|
||||
method_parameters_len,
|
||||
generic_signature_index,
|
||||
m->method_type(),
|
||||
CHECK_(methodHandle()));
|
||||
@ -1331,13 +1337,15 @@ void Method::sort_methods(Array<Method*>* methods,
|
||||
Array<AnnotationArray*>* methods_annotations,
|
||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
||||
Array<AnnotationArray*>* methods_default_annotations,
|
||||
Array<AnnotationArray*>* methods_type_annotations,
|
||||
bool idempotent) {
|
||||
int length = methods->length();
|
||||
if (length > 1) {
|
||||
bool do_annotations = false;
|
||||
if (methods_annotations != NULL ||
|
||||
methods_parameter_annotations != NULL ||
|
||||
methods_default_annotations != NULL) {
|
||||
methods_default_annotations != NULL ||
|
||||
methods_type_annotations != NULL) {
|
||||
do_annotations = true;
|
||||
}
|
||||
if (do_annotations) {
|
||||
@ -1356,6 +1364,7 @@ void Method::sort_methods(Array<Method*>* methods,
|
||||
assert(methods_annotations == NULL || methods_annotations->length() == methods->length(), "");
|
||||
assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), "");
|
||||
assert(methods_default_annotations == NULL || methods_default_annotations->length() == methods->length(), "");
|
||||
assert(methods_type_annotations == NULL || methods_type_annotations->length() == methods->length(), "");
|
||||
if (do_annotations) {
|
||||
ResourceMark rm;
|
||||
// Allocate temporary storage
|
||||
@ -1363,6 +1372,7 @@ void Method::sort_methods(Array<Method*>* methods,
|
||||
reorder_based_on_method_index(methods, methods_annotations, temp_array);
|
||||
reorder_based_on_method_index(methods, methods_parameter_annotations, temp_array);
|
||||
reorder_based_on_method_index(methods, methods_default_annotations, temp_array);
|
||||
reorder_based_on_method_index(methods, methods_type_annotations, temp_array);
|
||||
}
|
||||
|
||||
// Reset method ordering
|
||||
|
@ -160,6 +160,7 @@ class Method : public Metadata {
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
int method_parameters_length,
|
||||
u2 generic_signature_index,
|
||||
ConstMethod::MethodType method_type,
|
||||
TRAPS);
|
||||
@ -225,6 +226,13 @@ class Method : public Metadata {
|
||||
}
|
||||
return ik->annotations()->get_method_default_annotations_of(method_idnum());
|
||||
}
|
||||
AnnotationArray* type_annotations() const {
|
||||
InstanceKlass* ik = method_holder();
|
||||
Annotations* type_annos = ik->type_annotations();
|
||||
if (type_annos == NULL)
|
||||
return NULL;
|
||||
return type_annos->get_method_annotations_of(method_idnum());
|
||||
}
|
||||
|
||||
#ifdef CC_INTERP
|
||||
void set_result_index(BasicType type);
|
||||
@ -343,7 +351,7 @@ class Method : public Metadata {
|
||||
// exception handler which caused the exception to be thrown, which
|
||||
// is needed for proper retries. See, for example,
|
||||
// InterpreterRuntime::exception_handler_for_exception.
|
||||
int fast_exception_handler_bci_for(KlassHandle ex_klass, int throw_bci, TRAPS);
|
||||
static int fast_exception_handler_bci_for(methodHandle mh, KlassHandle ex_klass, int throw_bci, TRAPS);
|
||||
|
||||
// method data access
|
||||
MethodData* method_data() const {
|
||||
@ -473,6 +481,12 @@ class Method : public Metadata {
|
||||
void print_codes_on(outputStream* st) const PRODUCT_RETURN;
|
||||
void print_codes_on(int from, int to, outputStream* st) const PRODUCT_RETURN;
|
||||
|
||||
// method parameters
|
||||
int method_parameters_length() const
|
||||
{ return constMethod()->method_parameters_length(); }
|
||||
MethodParametersElement* method_parameters_start() const
|
||||
{ return constMethod()->method_parameters_start(); }
|
||||
|
||||
// checked exceptions
|
||||
int checked_exceptions_length() const
|
||||
{ return constMethod()->checked_exceptions_length(); }
|
||||
@ -790,6 +804,7 @@ class Method : public Metadata {
|
||||
Array<AnnotationArray*>* methods_annotations,
|
||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
||||
Array<AnnotationArray*>* methods_default_annotations,
|
||||
Array<AnnotationArray*>* methods_type_annotations,
|
||||
bool idempotent = false);
|
||||
|
||||
// Deallocation function for redefine classes or if an error occurs
|
||||
|
@ -46,7 +46,8 @@ InlineTree::InlineTree(Compile* c,
|
||||
_method(callee),
|
||||
_site_invoke_ratio(site_invoke_ratio),
|
||||
_max_inline_level(max_inline_level),
|
||||
_count_inline_bcs(method()->code_size_for_inlining())
|
||||
_count_inline_bcs(method()->code_size_for_inlining()),
|
||||
_subtrees(c->comp_arena(), 2, 0, NULL)
|
||||
{
|
||||
NOT_PRODUCT(_count_inlines = 0;)
|
||||
if (_caller_jvms != NULL) {
|
||||
@ -209,16 +210,18 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal
|
||||
if ( callee_method->dont_inline()) return "don't inline by annotation";
|
||||
if ( callee_method->has_unloaded_classes_in_signature()) return "unloaded signature classes";
|
||||
|
||||
if (callee_method->force_inline() || callee_method->should_inline()) {
|
||||
if (callee_method->should_inline()) {
|
||||
// ignore heuristic controls on inlining
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Now perform checks which are heuristic
|
||||
|
||||
if (callee_method->has_compiled_code() &&
|
||||
callee_method->instructions_size() > InlineSmallCode) {
|
||||
if (!callee_method->force_inline()) {
|
||||
if (callee_method->has_compiled_code() &&
|
||||
callee_method->instructions_size() > InlineSmallCode) {
|
||||
return "already compiled into a big method";
|
||||
}
|
||||
}
|
||||
|
||||
// don't inline exception code unless the top method belongs to an
|
||||
@ -277,12 +280,15 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal
|
||||
//-----------------------------try_to_inline-----------------------------------
|
||||
// return NULL if ok, reason for not inlining otherwise
|
||||
// Relocated from "InliningClosure::try_to_inline"
|
||||
const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) {
|
||||
|
||||
const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay) {
|
||||
// Old algorithm had funny accumulating BC-size counters
|
||||
if (UseOldInlining && ClipInlining
|
||||
&& (int)count_inline_bcs() >= DesiredMethodLimit) {
|
||||
return "size > DesiredMethodLimit";
|
||||
if (!callee_method->force_inline() || !IncrementalInline) {
|
||||
return "size > DesiredMethodLimit";
|
||||
} else if (!C->inlining_incrementally()) {
|
||||
should_delay = true;
|
||||
}
|
||||
}
|
||||
|
||||
const char *msg = NULL;
|
||||
@ -303,8 +309,13 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
|
||||
if (callee_method->code_size() > MaxTrivialSize) {
|
||||
|
||||
// don't inline into giant methods
|
||||
if (C->unique() > (uint)NodeCountInliningCutoff) {
|
||||
return "NodeCountInliningCutoff";
|
||||
if (C->over_inlining_cutoff()) {
|
||||
if ((!callee_method->force_inline() && !caller_method->is_compiled_lambda_form())
|
||||
|| !IncrementalInline) {
|
||||
return "NodeCountInliningCutoff";
|
||||
} else {
|
||||
should_delay = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!UseInterpreter || CompileTheWorld) &&
|
||||
@ -323,7 +334,11 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
|
||||
return "not an accessor";
|
||||
}
|
||||
if (inline_level() > _max_inline_level) {
|
||||
return "inlining too deep";
|
||||
if (!callee_method->force_inline() || !IncrementalInline) {
|
||||
return "inlining too deep";
|
||||
} else if (!C->inlining_incrementally()) {
|
||||
should_delay = true;
|
||||
}
|
||||
}
|
||||
|
||||
// detect direct and indirect recursive inlining
|
||||
@ -348,7 +363,11 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
|
||||
|
||||
if (UseOldInlining && ClipInlining
|
||||
&& (int)count_inline_bcs() + size >= DesiredMethodLimit) {
|
||||
return "size > DesiredMethodLimit";
|
||||
if (!callee_method->force_inline() || !IncrementalInline) {
|
||||
return "size > DesiredMethodLimit";
|
||||
} else if (!C->inlining_incrementally()) {
|
||||
should_delay = true;
|
||||
}
|
||||
}
|
||||
|
||||
// ok, inline this method
|
||||
@ -413,8 +432,9 @@ void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const c
|
||||
}
|
||||
|
||||
//------------------------------ok_to_inline-----------------------------------
|
||||
WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, ciCallProfile& profile, WarmCallInfo* initial_wci) {
|
||||
WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, ciCallProfile& profile, WarmCallInfo* initial_wci, bool& should_delay) {
|
||||
assert(callee_method != NULL, "caller checks for optimized virtual!");
|
||||
assert(!should_delay, "should be initialized to false");
|
||||
#ifdef ASSERT
|
||||
// Make sure the incoming jvms has the same information content as me.
|
||||
// This means that we can eventually make this whole class AllStatic.
|
||||
@ -444,7 +464,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
|
||||
|
||||
// Check if inlining policy says no.
|
||||
WarmCallInfo wci = *(initial_wci);
|
||||
failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci);
|
||||
failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci, should_delay);
|
||||
if (failure_msg != NULL && C->log() != NULL) {
|
||||
C->log()->inline_fail(failure_msg);
|
||||
}
|
||||
|
@ -606,6 +606,16 @@
|
||||
\
|
||||
develop(bool, VerifyAliases, false, \
|
||||
"perform extra checks on the results of alias analysis") \
|
||||
\
|
||||
product(bool, IncrementalInline, true, \
|
||||
"do post parse inlining") \
|
||||
\
|
||||
develop(bool, AlwaysIncrementalInline, false, \
|
||||
"do all inlining incrementally") \
|
||||
\
|
||||
product(intx, LiveNodeCountInliningCutoff, 20000, \
|
||||
"max number of live nodes in a method") \
|
||||
|
||||
|
||||
C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG)
|
||||
|
||||
|
@ -262,8 +262,11 @@ CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
|
||||
|
||||
// Allow inlining decisions to be delayed
|
||||
class LateInlineCallGenerator : public DirectCallGenerator {
|
||||
protected:
|
||||
CallGenerator* _inline_cg;
|
||||
|
||||
virtual bool do_late_inline_check(JVMState* jvms) { return true; }
|
||||
|
||||
public:
|
||||
LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
|
||||
DirectCallGenerator(method, true), _inline_cg(inline_cg) {}
|
||||
@ -279,7 +282,9 @@ class LateInlineCallGenerator : public DirectCallGenerator {
|
||||
|
||||
// Record that this call site should be revisited once the main
|
||||
// parse is finished.
|
||||
Compile::current()->add_late_inline(this);
|
||||
if (!is_mh_late_inline()) {
|
||||
C->add_late_inline(this);
|
||||
}
|
||||
|
||||
// Emit the CallStaticJava and request separate projections so
|
||||
// that the late inlining logic can distinguish between fall
|
||||
@ -287,8 +292,15 @@ class LateInlineCallGenerator : public DirectCallGenerator {
|
||||
// as is done for allocations and macro expansion.
|
||||
return DirectCallGenerator::generate(jvms);
|
||||
}
|
||||
};
|
||||
|
||||
virtual void print_inlining_late(const char* msg) {
|
||||
CallNode* call = call_node();
|
||||
Compile* C = Compile::current();
|
||||
C->print_inlining_insert(this);
|
||||
C->print_inlining(method(), call->jvms()->depth()-1, call->jvms()->bci(), msg);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void LateInlineCallGenerator::do_late_inline() {
|
||||
// Can't inline it
|
||||
@ -296,6 +308,18 @@ void LateInlineCallGenerator::do_late_inline() {
|
||||
call_node()->in(0) == NULL || call_node()->in(0)->is_top())
|
||||
return;
|
||||
|
||||
for (int i1 = 0; i1 < method()->arg_size(); i1++) {
|
||||
if (call_node()->in(TypeFunc::Parms + i1)->is_top()) {
|
||||
assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (call_node()->in(TypeFunc::Memory)->is_top()) {
|
||||
assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing");
|
||||
return;
|
||||
}
|
||||
|
||||
CallStaticJavaNode* call = call_node();
|
||||
|
||||
// Make a clone of the JVMState that appropriate to use for driving a parse
|
||||
@ -324,6 +348,11 @@ void LateInlineCallGenerator::do_late_inline() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!do_late_inline_check(jvms)) {
|
||||
map->disconnect_inputs(NULL, C);
|
||||
return;
|
||||
}
|
||||
|
||||
C->print_inlining_insert(this);
|
||||
|
||||
CompileLog* log = C->log();
|
||||
@ -360,6 +389,10 @@ void LateInlineCallGenerator::do_late_inline() {
|
||||
result = (result_size == 1) ? kit.pop() : kit.pop_pair();
|
||||
}
|
||||
|
||||
C->set_has_loops(C->has_loops() || _inline_cg->method()->has_loops());
|
||||
C->env()->notice_inlined_method(_inline_cg->method());
|
||||
C->set_inlining_progress(true);
|
||||
|
||||
kit.replace_call(call, result);
|
||||
}
|
||||
|
||||
@ -368,6 +401,83 @@ CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* i
|
||||
return new LateInlineCallGenerator(method, inline_cg);
|
||||
}
|
||||
|
||||
class LateInlineMHCallGenerator : public LateInlineCallGenerator {
|
||||
ciMethod* _caller;
|
||||
int _attempt;
|
||||
bool _input_not_const;
|
||||
|
||||
virtual bool do_late_inline_check(JVMState* jvms);
|
||||
virtual bool already_attempted() const { return _attempt > 0; }
|
||||
|
||||
public:
|
||||
LateInlineMHCallGenerator(ciMethod* caller, ciMethod* callee, bool input_not_const) :
|
||||
LateInlineCallGenerator(callee, NULL), _caller(caller), _attempt(0), _input_not_const(input_not_const) {}
|
||||
|
||||
virtual bool is_mh_late_inline() const { return true; }
|
||||
|
||||
virtual JVMState* generate(JVMState* jvms) {
|
||||
JVMState* new_jvms = LateInlineCallGenerator::generate(jvms);
|
||||
if (_input_not_const) {
|
||||
// inlining won't be possible so no need to enqueue right now.
|
||||
call_node()->set_generator(this);
|
||||
} else {
|
||||
Compile::current()->add_late_inline(this);
|
||||
}
|
||||
return new_jvms;
|
||||
}
|
||||
|
||||
virtual void print_inlining_late(const char* msg) {
|
||||
if (!_input_not_const) return;
|
||||
LateInlineCallGenerator::print_inlining_late(msg);
|
||||
}
|
||||
};
|
||||
|
||||
bool LateInlineMHCallGenerator::do_late_inline_check(JVMState* jvms) {
|
||||
|
||||
CallGenerator* cg = for_method_handle_inline(jvms, _caller, method(), _input_not_const);
|
||||
|
||||
if (!_input_not_const) {
|
||||
_attempt++;
|
||||
}
|
||||
|
||||
if (cg != NULL) {
|
||||
assert(!cg->is_late_inline() && cg->is_inline(), "we're doing late inlining");
|
||||
_inline_cg = cg;
|
||||
Compile::current()->dec_number_of_mh_late_inlines();
|
||||
return true;
|
||||
}
|
||||
|
||||
call_node()->set_generator(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
CallGenerator* CallGenerator::for_mh_late_inline(ciMethod* caller, ciMethod* callee, bool input_not_const) {
|
||||
Compile::current()->inc_number_of_mh_late_inlines();
|
||||
CallGenerator* cg = new LateInlineMHCallGenerator(caller, callee, input_not_const);
|
||||
return cg;
|
||||
}
|
||||
|
||||
class LateInlineStringCallGenerator : public LateInlineCallGenerator {
|
||||
|
||||
public:
|
||||
LateInlineStringCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
|
||||
LateInlineCallGenerator(method, inline_cg) {}
|
||||
|
||||
virtual JVMState* generate(JVMState* jvms) {
|
||||
Compile *C = Compile::current();
|
||||
C->print_inlining_skip(this);
|
||||
|
||||
C->add_string_late_inline(this);
|
||||
|
||||
JVMState* new_jvms = DirectCallGenerator::generate(jvms);
|
||||
return new_jvms;
|
||||
}
|
||||
};
|
||||
|
||||
CallGenerator* CallGenerator::for_string_late_inline(ciMethod* method, CallGenerator* inline_cg) {
|
||||
return new LateInlineStringCallGenerator(method, inline_cg);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------WarmCallGenerator--------------------------------
|
||||
// Internal class which handles initial deferral of inlining decisions.
|
||||
@ -586,35 +696,53 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
|
||||
}
|
||||
|
||||
|
||||
CallGenerator* CallGenerator::for_method_handle_call(JVMState* jvms, ciMethod* caller, ciMethod* callee) {
|
||||
CallGenerator* CallGenerator::for_method_handle_call(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool delayed_forbidden) {
|
||||
assert(callee->is_method_handle_intrinsic() ||
|
||||
callee->is_compiled_lambda_form(), "for_method_handle_call mismatch");
|
||||
CallGenerator* cg = CallGenerator::for_method_handle_inline(jvms, caller, callee);
|
||||
if (cg != NULL)
|
||||
return cg;
|
||||
return CallGenerator::for_direct_call(callee);
|
||||
bool input_not_const;
|
||||
CallGenerator* cg = CallGenerator::for_method_handle_inline(jvms, caller, callee, input_not_const);
|
||||
Compile* C = Compile::current();
|
||||
if (cg != NULL) {
|
||||
if (!delayed_forbidden && AlwaysIncrementalInline) {
|
||||
return CallGenerator::for_late_inline(callee, cg);
|
||||
} else {
|
||||
return cg;
|
||||
}
|
||||
}
|
||||
int bci = jvms->bci();
|
||||
ciCallProfile profile = caller->call_profile_at_bci(bci);
|
||||
int call_site_count = caller->scale_count(profile.count());
|
||||
|
||||
if (IncrementalInline && call_site_count > 0 &&
|
||||
(input_not_const || !C->inlining_incrementally() || C->over_inlining_cutoff())) {
|
||||
return CallGenerator::for_mh_late_inline(caller, callee, input_not_const);
|
||||
} else {
|
||||
// Out-of-line call.
|
||||
return CallGenerator::for_direct_call(callee);
|
||||
}
|
||||
}
|
||||
|
||||
CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee) {
|
||||
CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool& input_not_const) {
|
||||
GraphKit kit(jvms);
|
||||
PhaseGVN& gvn = kit.gvn();
|
||||
Compile* C = kit.C;
|
||||
vmIntrinsics::ID iid = callee->intrinsic_id();
|
||||
input_not_const = true;
|
||||
switch (iid) {
|
||||
case vmIntrinsics::_invokeBasic:
|
||||
{
|
||||
// Get MethodHandle receiver:
|
||||
Node* receiver = kit.argument(0);
|
||||
if (receiver->Opcode() == Op_ConP) {
|
||||
input_not_const = false;
|
||||
const TypeOopPtr* oop_ptr = receiver->bottom_type()->is_oopptr();
|
||||
ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget();
|
||||
guarantee(!target->is_method_handle_intrinsic(), "should not happen"); // XXX remove
|
||||
const int vtable_index = Method::invalid_vtable_index;
|
||||
CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS);
|
||||
CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, true, true);
|
||||
assert(!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
|
||||
if (cg != NULL && cg->is_inline())
|
||||
return cg;
|
||||
} else {
|
||||
if (PrintInlining) C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), "receiver not constant");
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -627,6 +755,7 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod*
|
||||
// Get MemberName argument:
|
||||
Node* member_name = kit.argument(callee->arg_size() - 1);
|
||||
if (member_name->Opcode() == Op_ConP) {
|
||||
input_not_const = false;
|
||||
const TypeOopPtr* oop_ptr = member_name->bottom_type()->is_oopptr();
|
||||
ciMethod* target = oop_ptr->const_oop()->as_member_name()->get_vmtarget();
|
||||
|
||||
@ -659,9 +788,25 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod*
|
||||
}
|
||||
}
|
||||
}
|
||||
const int vtable_index = Method::invalid_vtable_index;
|
||||
const bool call_is_virtual = target->is_abstract(); // FIXME workaround
|
||||
CallGenerator* cg = C->call_generator(target, vtable_index, call_is_virtual, jvms, true, PROB_ALWAYS);
|
||||
|
||||
// Try to get the most accurate receiver type
|
||||
const bool is_virtual = (iid == vmIntrinsics::_linkToVirtual);
|
||||
const bool is_virtual_or_interface = (is_virtual || iid == vmIntrinsics::_linkToInterface);
|
||||
int vtable_index = Method::invalid_vtable_index;
|
||||
bool call_does_dispatch = false;
|
||||
|
||||
if (is_virtual_or_interface) {
|
||||
ciInstanceKlass* klass = target->holder();
|
||||
Node* receiver_node = kit.argument(0);
|
||||
const TypeOopPtr* receiver_type = gvn.type(receiver_node)->isa_oopptr();
|
||||
// call_does_dispatch and vtable_index are out-parameters. They might be changed.
|
||||
target = C->optimize_virtual_call(caller, jvms->bci(), klass, target, receiver_type,
|
||||
is_virtual,
|
||||
call_does_dispatch, vtable_index); // out-parameters
|
||||
}
|
||||
|
||||
CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, true, true);
|
||||
assert(!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
|
||||
if (cg != NULL && cg->is_inline())
|
||||
return cg;
|
||||
}
|
||||
|
@ -68,6 +68,12 @@ class CallGenerator : public ResourceObj {
|
||||
|
||||
// is_late_inline: supports conversion of call into an inline
|
||||
virtual bool is_late_inline() const { return false; }
|
||||
// same but for method handle calls
|
||||
virtual bool is_mh_late_inline() const { return false; }
|
||||
|
||||
// for method handle calls: have we tried inlinining the call already?
|
||||
virtual bool already_attempted() const { ShouldNotReachHere(); return false; }
|
||||
|
||||
// Replace the call with an inline version of the code
|
||||
virtual void do_late_inline() { ShouldNotReachHere(); }
|
||||
|
||||
@ -112,11 +118,13 @@ class CallGenerator : public ResourceObj {
|
||||
static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface
|
||||
static CallGenerator* for_dynamic_call(ciMethod* m); // invokedynamic
|
||||
|
||||
static CallGenerator* for_method_handle_call( JVMState* jvms, ciMethod* caller, ciMethod* callee);
|
||||
static CallGenerator* for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee);
|
||||
static CallGenerator* for_method_handle_call( JVMState* jvms, ciMethod* caller, ciMethod* callee, bool delayed_forbidden);
|
||||
static CallGenerator* for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool& input_not_const);
|
||||
|
||||
// How to generate a replace a direct call with an inline version
|
||||
static CallGenerator* for_late_inline(ciMethod* m, CallGenerator* inline_cg);
|
||||
static CallGenerator* for_mh_late_inline(ciMethod* caller, ciMethod* callee, bool input_not_const);
|
||||
static CallGenerator* for_string_late_inline(ciMethod* m, CallGenerator* inline_cg);
|
||||
|
||||
// How to make a call but defer the decision whether to inline or not.
|
||||
static CallGenerator* for_warm_call(WarmCallInfo* ci,
|
||||
@ -147,6 +155,8 @@ class CallGenerator : public ResourceObj {
|
||||
CallGenerator* cg);
|
||||
virtual Node* generate_predicate(JVMState* jvms) { return NULL; };
|
||||
|
||||
virtual void print_inlining_late(const char* msg) { ShouldNotReachHere(); }
|
||||
|
||||
static void print_inlining(Compile* C, ciMethod* callee, int inline_level, int bci, const char* msg) {
|
||||
if (PrintInlining)
|
||||
C->print_inlining(callee, inline_level, bci, msg);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "ci/bcEscapeAnalyzer.hpp"
|
||||
#include "compiler/oopMap.hpp"
|
||||
#include "opto/callGenerator.hpp"
|
||||
#include "opto/callnode.hpp"
|
||||
#include "opto/escape.hpp"
|
||||
#include "opto/locknode.hpp"
|
||||
@ -775,16 +776,38 @@ void CallNode::extract_projections(CallProjections* projs, bool separate_io_proj
|
||||
// and the exception object may not exist if an exception handler
|
||||
// swallows the exception but all the other must exist and be found.
|
||||
assert(projs->fallthrough_proj != NULL, "must be found");
|
||||
assert(projs->fallthrough_catchproj != NULL, "must be found");
|
||||
assert(projs->fallthrough_memproj != NULL, "must be found");
|
||||
assert(projs->fallthrough_ioproj != NULL, "must be found");
|
||||
assert(projs->catchall_catchproj != NULL, "must be found");
|
||||
assert(Compile::current()->inlining_incrementally() || projs->fallthrough_catchproj != NULL, "must be found");
|
||||
assert(Compile::current()->inlining_incrementally() || projs->fallthrough_memproj != NULL, "must be found");
|
||||
assert(Compile::current()->inlining_incrementally() || projs->fallthrough_ioproj != NULL, "must be found");
|
||||
assert(Compile::current()->inlining_incrementally() || projs->catchall_catchproj != NULL, "must be found");
|
||||
if (separate_io_proj) {
|
||||
assert(projs->catchall_memproj != NULL, "must be found");
|
||||
assert(projs->catchall_ioproj != NULL, "must be found");
|
||||
assert(Compile::current()->inlining_incrementally() || projs->catchall_memproj != NULL, "must be found");
|
||||
assert(Compile::current()->inlining_incrementally() || projs->catchall_ioproj != NULL, "must be found");
|
||||
}
|
||||
}
|
||||
|
||||
Node *CallNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
CallGenerator* cg = generator();
|
||||
if (can_reshape && cg != NULL && cg->is_mh_late_inline() && !cg->already_attempted()) {
|
||||
// Check whether this MH handle call becomes a candidate for inlining
|
||||
ciMethod* callee = cg->method();
|
||||
vmIntrinsics::ID iid = callee->intrinsic_id();
|
||||
if (iid == vmIntrinsics::_invokeBasic) {
|
||||
if (in(TypeFunc::Parms)->Opcode() == Op_ConP) {
|
||||
phase->C->prepend_late_inline(cg);
|
||||
set_generator(NULL);
|
||||
}
|
||||
} else {
|
||||
assert(callee->has_member_arg(), "wrong type of call?");
|
||||
if (in(TypeFunc::Parms + callee->arg_size() - 1)->Opcode() == Op_ConP) {
|
||||
phase->C->prepend_late_inline(cg);
|
||||
set_generator(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
return SafePointNode::Ideal(phase, can_reshape);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
uint CallJavaNode::size_of() const { return sizeof(*this); }
|
||||
|
@ -507,6 +507,7 @@ public:
|
||||
Node* exobj;
|
||||
};
|
||||
|
||||
class CallGenerator;
|
||||
|
||||
//------------------------------CallNode---------------------------------------
|
||||
// Call nodes now subsume the function of debug nodes at callsites, so they
|
||||
@ -517,26 +518,31 @@ public:
|
||||
const TypeFunc *_tf; // Function type
|
||||
address _entry_point; // Address of method being called
|
||||
float _cnt; // Estimate of number of times called
|
||||
CallGenerator* _generator; // corresponding CallGenerator for some late inline calls
|
||||
|
||||
CallNode(const TypeFunc* tf, address addr, const TypePtr* adr_type)
|
||||
: SafePointNode(tf->domain()->cnt(), NULL, adr_type),
|
||||
_tf(tf),
|
||||
_entry_point(addr),
|
||||
_cnt(COUNT_UNKNOWN)
|
||||
_cnt(COUNT_UNKNOWN),
|
||||
_generator(NULL)
|
||||
{
|
||||
init_class_id(Class_Call);
|
||||
}
|
||||
|
||||
const TypeFunc* tf() const { return _tf; }
|
||||
const address entry_point() const { return _entry_point; }
|
||||
const float cnt() const { return _cnt; }
|
||||
const TypeFunc* tf() const { return _tf; }
|
||||
const address entry_point() const { return _entry_point; }
|
||||
const float cnt() const { return _cnt; }
|
||||
CallGenerator* generator() const { return _generator; }
|
||||
|
||||
void set_tf(const TypeFunc* tf) { _tf = tf; }
|
||||
void set_entry_point(address p) { _entry_point = p; }
|
||||
void set_cnt(float c) { _cnt = c; }
|
||||
void set_tf(const TypeFunc* tf) { _tf = tf; }
|
||||
void set_entry_point(address p) { _entry_point = p; }
|
||||
void set_cnt(float c) { _cnt = c; }
|
||||
void set_generator(CallGenerator* cg) { _generator = cg; }
|
||||
|
||||
virtual const Type *bottom_type() const;
|
||||
virtual const Type *Value( PhaseTransform *phase ) const;
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
virtual Node *Identity( PhaseTransform *phase ) { return this; }
|
||||
virtual uint cmp( const Node &n ) const;
|
||||
virtual uint size_of() const = 0;
|
||||
|
@ -363,6 +363,49 @@ bool RegionNode::is_unreachable_region(PhaseGVN *phase) const {
|
||||
return true; // The Region node is unreachable - it is dead.
|
||||
}
|
||||
|
||||
bool RegionNode::try_clean_mem_phi(PhaseGVN *phase) {
|
||||
// Incremental inlining + PhaseStringOpts sometimes produce:
|
||||
//
|
||||
// cmpP with 1 top input
|
||||
// |
|
||||
// If
|
||||
// / \
|
||||
// IfFalse IfTrue /- Some Node
|
||||
// \ / / /
|
||||
// Region / /-MergeMem
|
||||
// \---Phi
|
||||
//
|
||||
//
|
||||
// It's expected by PhaseStringOpts that the Region goes away and is
|
||||
// replaced by If's control input but because there's still a Phi,
|
||||
// the Region stays in the graph. The top input from the cmpP is
|
||||
// propagated forward and a subgraph that is useful goes away. The
|
||||
// code below replaces the Phi with the MergeMem so that the Region
|
||||
// is simplified.
|
||||
|
||||
PhiNode* phi = has_unique_phi();
|
||||
if (phi && phi->type() == Type::MEMORY && req() == 3 && phi->is_diamond_phi(true)) {
|
||||
MergeMemNode* m = NULL;
|
||||
assert(phi->req() == 3, "same as region");
|
||||
for (uint i = 1; i < 3; ++i) {
|
||||
Node *mem = phi->in(i);
|
||||
if (mem && mem->is_MergeMem() && in(i)->outcnt() == 1) {
|
||||
// Nothing is control-dependent on path #i except the region itself.
|
||||
m = mem->as_MergeMem();
|
||||
uint j = 3 - i;
|
||||
Node* other = phi->in(j);
|
||||
if (other && other == m->base_memory()) {
|
||||
// m is a successor memory to other, and is not pinned inside the diamond, so push it out.
|
||||
// This will allow the diamond to collapse completely.
|
||||
phase->is_IterGVN()->replace_node(phi, m);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------Ideal------------------------------------------
|
||||
// Return a node which is more "ideal" than the current node. Must preserve
|
||||
// the CFG, but we can still strip out dead paths.
|
||||
@ -375,6 +418,10 @@ Node *RegionNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
bool has_phis = false;
|
||||
if (can_reshape) { // Need DU info to check for Phi users
|
||||
has_phis = (has_phi() != NULL); // Cache result
|
||||
if (has_phis && try_clean_mem_phi(phase)) {
|
||||
has_phis = false;
|
||||
}
|
||||
|
||||
if (!has_phis) { // No Phi users? Nothing merging?
|
||||
for (uint i = 1; i < req()-1; i++) {
|
||||
Node *if1 = in(i);
|
||||
@ -1005,7 +1052,9 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const {
|
||||
//------------------------------is_diamond_phi---------------------------------
|
||||
// Does this Phi represent a simple well-shaped diamond merge? Return the
|
||||
// index of the true path or 0 otherwise.
|
||||
int PhiNode::is_diamond_phi() const {
|
||||
// If check_control_only is true, do not inspect the If node at the
|
||||
// top, and return -1 (not an edge number) on success.
|
||||
int PhiNode::is_diamond_phi(bool check_control_only) const {
|
||||
// Check for a 2-path merge
|
||||
Node *region = in(0);
|
||||
if( !region ) return 0;
|
||||
@ -1018,6 +1067,7 @@ int PhiNode::is_diamond_phi() const {
|
||||
Node *iff = ifp1->in(0);
|
||||
if( !iff || !iff->is_If() ) return 0;
|
||||
if( iff != ifp2->in(0) ) return 0;
|
||||
if (check_control_only) return -1;
|
||||
// Check for a proper bool/cmp
|
||||
const Node *b = iff->in(1);
|
||||
if( !b->is_Bool() ) return 0;
|
||||
|
@ -95,6 +95,7 @@ public:
|
||||
virtual Node *Identity( PhaseTransform *phase );
|
||||
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||
virtual const RegMask &out_RegMask() const;
|
||||
bool try_clean_mem_phi(PhaseGVN *phase);
|
||||
};
|
||||
|
||||
//------------------------------JProjNode--------------------------------------
|
||||
@ -181,7 +182,7 @@ public:
|
||||
LoopSafety simple_data_loop_check(Node *in) const;
|
||||
// Is it unsafe data loop? It becomes a dead loop if this phi node removed.
|
||||
bool is_unsafe_data_reference(Node *in) const;
|
||||
int is_diamond_phi() const;
|
||||
int is_diamond_phi(bool check_control_only = false) const;
|
||||
virtual int Opcode() const;
|
||||
virtual bool pinned() const { return in(0) != 0; }
|
||||
virtual const TypePtr *adr_type() const { verify_adr_type(true); return _adr_type; }
|
||||
|
@ -136,7 +136,7 @@ int Compile::intrinsic_insertion_index(ciMethod* m, bool is_virtual) {
|
||||
|
||||
void Compile::register_intrinsic(CallGenerator* cg) {
|
||||
if (_intrinsics == NULL) {
|
||||
_intrinsics = new GrowableArray<CallGenerator*>(60);
|
||||
_intrinsics = new (comp_arena())GrowableArray<CallGenerator*>(comp_arena(), 60, 0, NULL);
|
||||
}
|
||||
// This code is stolen from ciObjectFactory::insert.
|
||||
// Really, GrowableArray should have methods for
|
||||
@ -365,6 +365,21 @@ void Compile::update_dead_node_list(Unique_Node_List &useful) {
|
||||
}
|
||||
}
|
||||
|
||||
void Compile::remove_useless_late_inlines(GrowableArray<CallGenerator*>* inlines, Unique_Node_List &useful) {
|
||||
int shift = 0;
|
||||
for (int i = 0; i < inlines->length(); i++) {
|
||||
CallGenerator* cg = inlines->at(i);
|
||||
CallNode* call = cg->call_node();
|
||||
if (shift > 0) {
|
||||
inlines->at_put(i-shift, cg);
|
||||
}
|
||||
if (!useful.member(call)) {
|
||||
shift++;
|
||||
}
|
||||
}
|
||||
inlines->trunc_to(inlines->length()-shift);
|
||||
}
|
||||
|
||||
// Disconnect all useless nodes by disconnecting those at the boundary.
|
||||
void Compile::remove_useless_nodes(Unique_Node_List &useful) {
|
||||
uint next = 0;
|
||||
@ -394,6 +409,9 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) {
|
||||
remove_macro_node(n);
|
||||
}
|
||||
}
|
||||
// clean up the late inline lists
|
||||
remove_useless_late_inlines(&_string_late_inlines, useful);
|
||||
remove_useless_late_inlines(&_late_inlines, useful);
|
||||
debug_only(verify_graph_edges(true/*check for no_dead_code*/);)
|
||||
}
|
||||
|
||||
@ -611,6 +629,12 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
_printer(IdealGraphPrinter::printer()),
|
||||
#endif
|
||||
_congraph(NULL),
|
||||
_late_inlines(comp_arena(), 2, 0, NULL),
|
||||
_string_late_inlines(comp_arena(), 2, 0, NULL),
|
||||
_late_inlines_pos(0),
|
||||
_number_of_mh_late_inlines(0),
|
||||
_inlining_progress(false),
|
||||
_inlining_incrementally(false),
|
||||
_print_inlining_list(NULL),
|
||||
_print_inlining(0) {
|
||||
C = this;
|
||||
@ -737,29 +761,13 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
rethrow_exceptions(kit.transfer_exceptions_into_jvms());
|
||||
}
|
||||
|
||||
if (!failing() && has_stringbuilder()) {
|
||||
{
|
||||
// remove useless nodes to make the usage analysis simpler
|
||||
ResourceMark rm;
|
||||
PhaseRemoveUseless pru(initial_gvn(), &for_igvn);
|
||||
}
|
||||
assert(IncrementalInline || (_late_inlines.length() == 0 && !has_mh_late_inlines()), "incremental inlining is off");
|
||||
|
||||
{
|
||||
ResourceMark rm;
|
||||
print_method("Before StringOpts", 3);
|
||||
PhaseStringOpts pso(initial_gvn(), &for_igvn);
|
||||
print_method("After StringOpts", 3);
|
||||
}
|
||||
|
||||
// now inline anything that we skipped the first time around
|
||||
while (_late_inlines.length() > 0) {
|
||||
CallGenerator* cg = _late_inlines.pop();
|
||||
cg->do_late_inline();
|
||||
if (failing()) return;
|
||||
}
|
||||
if (_late_inlines.length() == 0 && !has_mh_late_inlines() && !failing() && has_stringbuilder()) {
|
||||
inline_string_calls(true);
|
||||
}
|
||||
assert(_late_inlines.length() == 0, "should have been processed");
|
||||
dump_inlining();
|
||||
|
||||
if (failing()) return;
|
||||
|
||||
print_method("Before RemoveUseless", 3);
|
||||
|
||||
@ -906,6 +914,9 @@ Compile::Compile( ciEnv* ci_env,
|
||||
_dead_node_list(comp_arena()),
|
||||
_dead_node_count(0),
|
||||
_congraph(NULL),
|
||||
_number_of_mh_late_inlines(0),
|
||||
_inlining_progress(false),
|
||||
_inlining_incrementally(false),
|
||||
_print_inlining_list(NULL),
|
||||
_print_inlining(0) {
|
||||
C = this;
|
||||
@ -1760,6 +1771,124 @@ void Compile::cleanup_loop_predicates(PhaseIterGVN &igvn) {
|
||||
assert(predicate_count()==0, "should be clean!");
|
||||
}
|
||||
|
||||
// StringOpts and late inlining of string methods
|
||||
void Compile::inline_string_calls(bool parse_time) {
|
||||
{
|
||||
// remove useless nodes to make the usage analysis simpler
|
||||
ResourceMark rm;
|
||||
PhaseRemoveUseless pru(initial_gvn(), for_igvn());
|
||||
}
|
||||
|
||||
{
|
||||
ResourceMark rm;
|
||||
print_method("Before StringOpts", 3);
|
||||
PhaseStringOpts pso(initial_gvn(), for_igvn());
|
||||
print_method("After StringOpts", 3);
|
||||
}
|
||||
|
||||
// now inline anything that we skipped the first time around
|
||||
if (!parse_time) {
|
||||
_late_inlines_pos = _late_inlines.length();
|
||||
}
|
||||
|
||||
while (_string_late_inlines.length() > 0) {
|
||||
CallGenerator* cg = _string_late_inlines.pop();
|
||||
cg->do_late_inline();
|
||||
if (failing()) return;
|
||||
}
|
||||
_string_late_inlines.trunc_to(0);
|
||||
}
|
||||
|
||||
void Compile::inline_incrementally_one(PhaseIterGVN& igvn) {
|
||||
assert(IncrementalInline, "incremental inlining should be on");
|
||||
PhaseGVN* gvn = initial_gvn();
|
||||
|
||||
set_inlining_progress(false);
|
||||
for_igvn()->clear();
|
||||
gvn->replace_with(&igvn);
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (; i <_late_inlines.length() && !inlining_progress(); i++) {
|
||||
CallGenerator* cg = _late_inlines.at(i);
|
||||
_late_inlines_pos = i+1;
|
||||
cg->do_late_inline();
|
||||
if (failing()) return;
|
||||
}
|
||||
int j = 0;
|
||||
for (; i < _late_inlines.length(); i++, j++) {
|
||||
_late_inlines.at_put(j, _late_inlines.at(i));
|
||||
}
|
||||
_late_inlines.trunc_to(j);
|
||||
|
||||
{
|
||||
ResourceMark rm;
|
||||
PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn());
|
||||
}
|
||||
|
||||
igvn = PhaseIterGVN(gvn);
|
||||
}
|
||||
|
||||
// Perform incremental inlining until bound on number of live nodes is reached
|
||||
void Compile::inline_incrementally(PhaseIterGVN& igvn) {
|
||||
PhaseGVN* gvn = initial_gvn();
|
||||
|
||||
set_inlining_incrementally(true);
|
||||
set_inlining_progress(true);
|
||||
uint low_live_nodes = 0;
|
||||
|
||||
while(inlining_progress() && _late_inlines.length() > 0) {
|
||||
|
||||
if (live_nodes() > (uint)LiveNodeCountInliningCutoff) {
|
||||
if (low_live_nodes < (uint)LiveNodeCountInliningCutoff * 8 / 10) {
|
||||
// PhaseIdealLoop is expensive so we only try it once we are
|
||||
// out of loop and we only try it again if the previous helped
|
||||
// got the number of nodes down significantly
|
||||
PhaseIdealLoop ideal_loop( igvn, false, true );
|
||||
if (failing()) return;
|
||||
low_live_nodes = live_nodes();
|
||||
_major_progress = true;
|
||||
}
|
||||
|
||||
if (live_nodes() > (uint)LiveNodeCountInliningCutoff) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline_incrementally_one(igvn);
|
||||
|
||||
if (failing()) return;
|
||||
|
||||
igvn.optimize();
|
||||
|
||||
if (failing()) return;
|
||||
}
|
||||
|
||||
assert( igvn._worklist.size() == 0, "should be done with igvn" );
|
||||
|
||||
if (_string_late_inlines.length() > 0) {
|
||||
assert(has_stringbuilder(), "inconsistent");
|
||||
for_igvn()->clear();
|
||||
initial_gvn()->replace_with(&igvn);
|
||||
|
||||
inline_string_calls(false);
|
||||
|
||||
if (failing()) return;
|
||||
|
||||
{
|
||||
ResourceMark rm;
|
||||
PhaseRemoveUseless pru(initial_gvn(), for_igvn());
|
||||
}
|
||||
|
||||
igvn = PhaseIterGVN(gvn);
|
||||
|
||||
igvn.optimize();
|
||||
}
|
||||
|
||||
set_inlining_incrementally(false);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------Optimize---------------------------------------
|
||||
// Given a graph, optimize it.
|
||||
void Compile::Optimize() {
|
||||
@ -1792,6 +1921,12 @@ void Compile::Optimize() {
|
||||
|
||||
if (failing()) return;
|
||||
|
||||
inline_incrementally(igvn);
|
||||
|
||||
print_method("Incremental Inline", 2);
|
||||
|
||||
if (failing()) return;
|
||||
|
||||
// Perform escape analysis
|
||||
if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
|
||||
if (has_loops()) {
|
||||
@ -1914,6 +2049,7 @@ void Compile::Optimize() {
|
||||
|
||||
} // (End scope of igvn; run destructor if necessary for asserts.)
|
||||
|
||||
dump_inlining();
|
||||
// A method with only infinite loops has no edges entering loops from root
|
||||
{
|
||||
NOT_PRODUCT( TracePhase t2("graphReshape", &_t_graphReshaping, TimeCompiler); )
|
||||
@ -3362,6 +3498,28 @@ void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n
|
||||
|
||||
void Compile::dump_inlining() {
|
||||
if (PrintInlining) {
|
||||
// Print inlining message for candidates that we couldn't inline
|
||||
// for lack of space or non constant receiver
|
||||
for (int i = 0; i < _late_inlines.length(); i++) {
|
||||
CallGenerator* cg = _late_inlines.at(i);
|
||||
cg->print_inlining_late("live nodes > LiveNodeCountInliningCutoff");
|
||||
}
|
||||
Unique_Node_List useful;
|
||||
useful.push(root());
|
||||
for (uint next = 0; next < useful.size(); ++next) {
|
||||
Node* n = useful.at(next);
|
||||
if (n->is_Call() && n->as_Call()->generator() != NULL && n->as_Call()->generator()->call_node() == n) {
|
||||
CallNode* call = n->as_Call();
|
||||
CallGenerator* cg = call->generator();
|
||||
cg->print_inlining_late("receiver not constant");
|
||||
}
|
||||
uint max = n->len();
|
||||
for ( uint i = 0; i < max; ++i ) {
|
||||
Node *m = n->in(i);
|
||||
if ( m == NULL ) continue;
|
||||
useful.push(m);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < _print_inlining_list->length(); i++) {
|
||||
tty->print(_print_inlining_list->at(i).ss()->as_string());
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ class SafePointNode;
|
||||
class JVMState;
|
||||
class TypeData;
|
||||
class TypePtr;
|
||||
class TypeOopPtr;
|
||||
class TypeFunc;
|
||||
class Unique_Node_List;
|
||||
class nmethod;
|
||||
@ -280,6 +281,8 @@ class Compile : public Phase {
|
||||
int _orig_pc_slot_offset_in_bytes;
|
||||
|
||||
int _major_progress; // Count of something big happening
|
||||
bool _inlining_progress; // progress doing incremental inlining?
|
||||
bool _inlining_incrementally;// Are we doing incremental inlining (post parse)
|
||||
bool _has_loops; // True if the method _may_ have some loops
|
||||
bool _has_split_ifs; // True if the method _may_ have some split-if
|
||||
bool _has_unsafe_access; // True if the method _may_ produce faults in unsafe loads or stores.
|
||||
@ -367,8 +370,13 @@ class Compile : public Phase {
|
||||
Unique_Node_List* _for_igvn; // Initial work-list for next round of Iterative GVN
|
||||
WarmCallInfo* _warm_calls; // Sorted work-list for heat-based inlining.
|
||||
|
||||
GrowableArray<CallGenerator*> _late_inlines; // List of CallGenerators to be revisited after
|
||||
// main parsing has finished.
|
||||
GrowableArray<CallGenerator*> _late_inlines; // List of CallGenerators to be revisited after
|
||||
// main parsing has finished.
|
||||
GrowableArray<CallGenerator*> _string_late_inlines; // same but for string operations
|
||||
|
||||
int _late_inlines_pos; // Where in the queue should the next late inlining candidate go (emulate depth first inlining)
|
||||
uint _number_of_mh_late_inlines; // number of method handle late inlining still pending
|
||||
|
||||
|
||||
// Inlining may not happen in parse order which would make
|
||||
// PrintInlining output confusing. Keep track of PrintInlining
|
||||
@ -491,6 +499,10 @@ class Compile : public Phase {
|
||||
int fixed_slots() const { assert(_fixed_slots >= 0, ""); return _fixed_slots; }
|
||||
void set_fixed_slots(int n) { _fixed_slots = n; }
|
||||
int major_progress() const { return _major_progress; }
|
||||
void set_inlining_progress(bool z) { _inlining_progress = z; }
|
||||
int inlining_progress() const { return _inlining_progress; }
|
||||
void set_inlining_incrementally(bool z) { _inlining_incrementally = z; }
|
||||
int inlining_incrementally() const { return _inlining_incrementally; }
|
||||
void set_major_progress() { _major_progress++; }
|
||||
void clear_major_progress() { _major_progress = 0; }
|
||||
int num_loop_opts() const { return _num_loop_opts; }
|
||||
@ -729,9 +741,17 @@ class Compile : public Phase {
|
||||
|
||||
// Decide how to build a call.
|
||||
// The profile factor is a discount to apply to this site's interp. profile.
|
||||
CallGenerator* call_generator(ciMethod* call_method, int vtable_index, bool call_is_virtual, JVMState* jvms, bool allow_inline, float profile_factor, bool allow_intrinsics = true);
|
||||
CallGenerator* call_generator(ciMethod* call_method, int vtable_index, bool call_does_dispatch, JVMState* jvms, bool allow_inline, float profile_factor, bool allow_intrinsics = true, bool delayed_forbidden = false);
|
||||
bool should_delay_inlining(ciMethod* call_method, JVMState* jvms);
|
||||
|
||||
// Helper functions to identify inlining potential at call-site
|
||||
ciMethod* optimize_virtual_call(ciMethod* caller, int bci, ciInstanceKlass* klass,
|
||||
ciMethod* callee, const TypeOopPtr* receiver_type,
|
||||
bool is_virtual,
|
||||
bool &call_does_dispatch, int &vtable_index);
|
||||
ciMethod* optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* klass,
|
||||
ciMethod* callee, const TypeOopPtr* receiver_type);
|
||||
|
||||
// Report if there were too many traps at a current method and bci.
|
||||
// Report if a trap was recorded, and/or PerMethodTrapLimit was exceeded.
|
||||
// If there is no MDO at all, report no trap unless told to assume it.
|
||||
@ -765,10 +785,39 @@ class Compile : public Phase {
|
||||
WarmCallInfo* pop_warm_call();
|
||||
|
||||
// Record this CallGenerator for inlining at the end of parsing.
|
||||
void add_late_inline(CallGenerator* cg) { _late_inlines.push(cg); }
|
||||
void add_late_inline(CallGenerator* cg) {
|
||||
_late_inlines.insert_before(_late_inlines_pos, cg);
|
||||
_late_inlines_pos++;
|
||||
}
|
||||
|
||||
void prepend_late_inline(CallGenerator* cg) {
|
||||
_late_inlines.insert_before(0, cg);
|
||||
}
|
||||
|
||||
void add_string_late_inline(CallGenerator* cg) {
|
||||
_string_late_inlines.push(cg);
|
||||
}
|
||||
|
||||
void remove_useless_late_inlines(GrowableArray<CallGenerator*>* inlines, Unique_Node_List &useful);
|
||||
|
||||
void dump_inlining();
|
||||
|
||||
bool over_inlining_cutoff() const {
|
||||
if (!inlining_incrementally()) {
|
||||
return unique() > (uint)NodeCountInliningCutoff;
|
||||
} else {
|
||||
return live_nodes() > (uint)LiveNodeCountInliningCutoff;
|
||||
}
|
||||
}
|
||||
|
||||
void inc_number_of_mh_late_inlines() { _number_of_mh_late_inlines++; }
|
||||
void dec_number_of_mh_late_inlines() { assert(_number_of_mh_late_inlines > 0, "_number_of_mh_late_inlines < 0 !"); _number_of_mh_late_inlines--; }
|
||||
bool has_mh_late_inlines() const { return _number_of_mh_late_inlines > 0; }
|
||||
|
||||
void inline_incrementally_one(PhaseIterGVN& igvn);
|
||||
void inline_incrementally(PhaseIterGVN& igvn);
|
||||
void inline_string_calls(bool parse_time);
|
||||
|
||||
// Matching, CFG layout, allocation, code generation
|
||||
PhaseCFG* cfg() { return _cfg; }
|
||||
bool select_24_bit_instr() const { return _select_24_bit_instr; }
|
||||
|
@ -61,9 +61,9 @@ void trace_type_profile(Compile* C, ciMethod *method, int depth, int bci, ciMeth
|
||||
}
|
||||
}
|
||||
|
||||
CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool call_is_virtual,
|
||||
CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool call_does_dispatch,
|
||||
JVMState* jvms, bool allow_inline,
|
||||
float prof_factor, bool allow_intrinsics) {
|
||||
float prof_factor, bool allow_intrinsics, bool delayed_forbidden) {
|
||||
ciMethod* caller = jvms->method();
|
||||
int bci = jvms->bci();
|
||||
Bytecodes::Code bytecode = caller->java_code_at_bci(bci);
|
||||
@ -82,7 +82,7 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
|
||||
// See how many times this site has been invoked.
|
||||
int site_count = profile.count();
|
||||
int receiver_count = -1;
|
||||
if (call_is_virtual && UseTypeProfile && profile.has_receiver(0)) {
|
||||
if (call_does_dispatch && UseTypeProfile && profile.has_receiver(0)) {
|
||||
// Receivers in the profile structure are ordered by call counts
|
||||
// so that the most called (major) receiver is profile.receiver(0).
|
||||
receiver_count = profile.receiver_count(0);
|
||||
@ -94,7 +94,7 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
|
||||
int r2id = (rid != -1 && profile.has_receiver(1))? log->identify(profile.receiver(1)):-1;
|
||||
log->begin_elem("call method='%d' count='%d' prof_factor='%g'",
|
||||
log->identify(callee), site_count, prof_factor);
|
||||
if (call_is_virtual) log->print(" virtual='1'");
|
||||
if (call_does_dispatch) log->print(" virtual='1'");
|
||||
if (allow_inline) log->print(" inline='1'");
|
||||
if (receiver_count >= 0) {
|
||||
log->print(" receiver='%d' receiver_count='%d'", rid, receiver_count);
|
||||
@ -111,12 +111,12 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
|
||||
// We do this before the strict f.p. check below because the
|
||||
// intrinsics handle strict f.p. correctly.
|
||||
if (allow_inline && allow_intrinsics) {
|
||||
CallGenerator* cg = find_intrinsic(callee, call_is_virtual);
|
||||
CallGenerator* cg = find_intrinsic(callee, call_does_dispatch);
|
||||
if (cg != NULL) {
|
||||
if (cg->is_predicted()) {
|
||||
// Code without intrinsic but, hopefully, inlined.
|
||||
CallGenerator* inline_cg = this->call_generator(callee,
|
||||
vtable_index, call_is_virtual, jvms, allow_inline, prof_factor, false);
|
||||
vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor, false);
|
||||
if (inline_cg != NULL) {
|
||||
cg = CallGenerator::for_predicted_intrinsic(cg, inline_cg);
|
||||
}
|
||||
@ -130,7 +130,9 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
|
||||
// MethodHandle.invoke* are native methods which obviously don't
|
||||
// have bytecodes and so normal inlining fails.
|
||||
if (callee->is_method_handle_intrinsic()) {
|
||||
return CallGenerator::for_method_handle_call(jvms, caller, callee);
|
||||
CallGenerator* cg = CallGenerator::for_method_handle_call(jvms, caller, callee, delayed_forbidden);
|
||||
assert(cg == NULL || !delayed_forbidden || !cg->is_late_inline() || cg->is_mh_late_inline(), "unexpected CallGenerator");
|
||||
return cg;
|
||||
}
|
||||
|
||||
// Do not inline strict fp into non-strict code, or the reverse
|
||||
@ -147,7 +149,7 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
|
||||
float expected_uses = past_uses;
|
||||
|
||||
// Try inlining a bytecoded method:
|
||||
if (!call_is_virtual) {
|
||||
if (!call_does_dispatch) {
|
||||
InlineTree* ilt;
|
||||
if (UseOldInlining) {
|
||||
ilt = InlineTree::find_subtree_from_root(this->ilt(), jvms->caller(), jvms->method());
|
||||
@ -161,32 +163,39 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
|
||||
WarmCallInfo scratch_ci;
|
||||
if (!UseOldInlining)
|
||||
scratch_ci.init(jvms, callee, profile, prof_factor);
|
||||
WarmCallInfo* ci = ilt->ok_to_inline(callee, jvms, profile, &scratch_ci);
|
||||
bool should_delay = false;
|
||||
WarmCallInfo* ci = ilt->ok_to_inline(callee, jvms, profile, &scratch_ci, should_delay);
|
||||
assert(ci != &scratch_ci, "do not let this pointer escape");
|
||||
bool allow_inline = (ci != NULL && !ci->is_cold());
|
||||
bool require_inline = (allow_inline && ci->is_hot());
|
||||
|
||||
if (allow_inline) {
|
||||
CallGenerator* cg = CallGenerator::for_inline(callee, expected_uses);
|
||||
if (require_inline && cg != NULL && should_delay_inlining(callee, jvms)) {
|
||||
|
||||
if (require_inline && cg != NULL) {
|
||||
// Delay the inlining of this method to give us the
|
||||
// opportunity to perform some high level optimizations
|
||||
// first.
|
||||
return CallGenerator::for_late_inline(callee, cg);
|
||||
if (should_delay_inlining(callee, jvms)) {
|
||||
assert(!delayed_forbidden, "strange");
|
||||
return CallGenerator::for_string_late_inline(callee, cg);
|
||||
} else if ((should_delay || AlwaysIncrementalInline) && !delayed_forbidden) {
|
||||
return CallGenerator::for_late_inline(callee, cg);
|
||||
}
|
||||
}
|
||||
if (cg == NULL) {
|
||||
if (cg == NULL || should_delay) {
|
||||
// Fall through.
|
||||
} else if (require_inline || !InlineWarmCalls) {
|
||||
return cg;
|
||||
} else {
|
||||
CallGenerator* cold_cg = call_generator(callee, vtable_index, call_is_virtual, jvms, false, prof_factor);
|
||||
CallGenerator* cold_cg = call_generator(callee, vtable_index, call_does_dispatch, jvms, false, prof_factor);
|
||||
return CallGenerator::for_warm_call(ci, cold_cg, cg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try using the type profile.
|
||||
if (call_is_virtual && site_count > 0 && receiver_count > 0) {
|
||||
if (call_does_dispatch && site_count > 0 && receiver_count > 0) {
|
||||
// The major receiver's count >= TypeProfileMajorReceiverPercent of site_count.
|
||||
bool have_major_receiver = (100.*profile.receiver_prob(0) >= (float)TypeProfileMajorReceiverPercent);
|
||||
ciMethod* receiver_method = NULL;
|
||||
@ -200,7 +209,7 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
|
||||
if (receiver_method != NULL) {
|
||||
// The single majority receiver sufficiently outweighs the minority.
|
||||
CallGenerator* hit_cg = this->call_generator(receiver_method,
|
||||
vtable_index, !call_is_virtual, jvms, allow_inline, prof_factor);
|
||||
vtable_index, !call_does_dispatch, jvms, allow_inline, prof_factor);
|
||||
if (hit_cg != NULL) {
|
||||
// Look up second receiver.
|
||||
CallGenerator* next_hit_cg = NULL;
|
||||
@ -210,7 +219,7 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
|
||||
profile.receiver(1));
|
||||
if (next_receiver_method != NULL) {
|
||||
next_hit_cg = this->call_generator(next_receiver_method,
|
||||
vtable_index, !call_is_virtual, jvms,
|
||||
vtable_index, !call_does_dispatch, jvms,
|
||||
allow_inline, prof_factor);
|
||||
if (next_hit_cg != NULL && !next_hit_cg->is_inline() &&
|
||||
have_major_receiver && UseOnlyInlinedBimorphic) {
|
||||
@ -256,7 +265,7 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
|
||||
|
||||
// There was no special inlining tactic, or it bailed out.
|
||||
// Use a more generic tactic, like a simple call.
|
||||
if (call_is_virtual) {
|
||||
if (call_does_dispatch) {
|
||||
return CallGenerator::for_virtual_call(callee, vtable_index);
|
||||
} else {
|
||||
// Class Hierarchy Analysis or Type Profile reveals a unique target,
|
||||
@ -388,6 +397,7 @@ void Parse::do_call() {
|
||||
// orig_callee is the resolved callee which's signature includes the
|
||||
// appendix argument.
|
||||
const int nargs = orig_callee->arg_size();
|
||||
const bool is_signature_polymorphic = MethodHandles::is_signature_polymorphic(orig_callee->intrinsic_id());
|
||||
|
||||
// Push appendix argument (MethodType, CallSite, etc.), if one.
|
||||
if (iter().has_appendix()) {
|
||||
@ -404,25 +414,18 @@ void Parse::do_call() {
|
||||
// Then we may introduce a run-time check and inline on the path where it succeeds.
|
||||
// The other path may uncommon_trap, check for another receiver, or do a v-call.
|
||||
|
||||
// Choose call strategy.
|
||||
bool call_is_virtual = is_virtual_or_interface;
|
||||
int vtable_index = Method::invalid_vtable_index;
|
||||
ciMethod* callee = orig_callee;
|
||||
|
||||
// Try to get the most accurate receiver type
|
||||
ciMethod* callee = orig_callee;
|
||||
int vtable_index = Method::invalid_vtable_index;
|
||||
bool call_does_dispatch = false;
|
||||
|
||||
if (is_virtual_or_interface) {
|
||||
Node* receiver_node = stack(sp() - nargs);
|
||||
const TypeOopPtr* receiver_type = _gvn.type(receiver_node)->isa_oopptr();
|
||||
ciMethod* optimized_virtual_method = optimize_inlining(method(), bci(), klass, orig_callee, receiver_type);
|
||||
|
||||
// Have the call been sufficiently improved such that it is no longer a virtual?
|
||||
if (optimized_virtual_method != NULL) {
|
||||
callee = optimized_virtual_method;
|
||||
call_is_virtual = false;
|
||||
} else if (!UseInlineCaches && is_virtual && callee->is_loaded()) {
|
||||
// We can make a vtable call at this site
|
||||
vtable_index = callee->resolve_vtable_index(method()->holder(), klass);
|
||||
}
|
||||
// call_does_dispatch and vtable_index are out-parameters. They might be changed.
|
||||
callee = C->optimize_virtual_call(method(), bci(), klass, orig_callee, receiver_type,
|
||||
is_virtual,
|
||||
call_does_dispatch, vtable_index); // out-parameters
|
||||
}
|
||||
|
||||
// Note: It's OK to try to inline a virtual call.
|
||||
@ -438,7 +441,7 @@ void Parse::do_call() {
|
||||
// Decide call tactic.
|
||||
// This call checks with CHA, the interpreter profile, intrinsics table, etc.
|
||||
// It decides whether inlining is desirable or not.
|
||||
CallGenerator* cg = C->call_generator(callee, vtable_index, call_is_virtual, jvms, try_inline, prof_factor());
|
||||
CallGenerator* cg = C->call_generator(callee, vtable_index, call_does_dispatch, jvms, try_inline, prof_factor());
|
||||
|
||||
// NOTE: Don't use orig_callee and callee after this point! Use cg->method() instead.
|
||||
orig_callee = callee = NULL;
|
||||
@ -478,7 +481,7 @@ void Parse::do_call() {
|
||||
// the call site, perhaps because it did not match a pattern the
|
||||
// intrinsic was expecting to optimize. Should always be possible to
|
||||
// get a normal java call that may inline in that case
|
||||
cg = C->call_generator(cg->method(), vtable_index, call_is_virtual, jvms, try_inline, prof_factor(), /* allow_intrinsics= */ false);
|
||||
cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), /* allow_intrinsics= */ false);
|
||||
if ((new_jvms = cg->generate(jvms)) == NULL) {
|
||||
guarantee(failing(), "call failed to generate: calls should work");
|
||||
return;
|
||||
@ -513,55 +516,44 @@ void Parse::do_call() {
|
||||
round_double_result(cg->method());
|
||||
|
||||
ciType* rtype = cg->method()->return_type();
|
||||
if (Bytecodes::has_optional_appendix(iter().cur_bc_raw())) {
|
||||
ciType* ctype = declared_signature->return_type();
|
||||
|
||||
if (Bytecodes::has_optional_appendix(iter().cur_bc_raw()) || is_signature_polymorphic) {
|
||||
// Be careful here with return types.
|
||||
ciType* ctype = declared_signature->return_type();
|
||||
if (ctype != rtype) {
|
||||
BasicType rt = rtype->basic_type();
|
||||
BasicType ct = ctype->basic_type();
|
||||
Node* retnode = peek();
|
||||
if (ct == T_VOID) {
|
||||
// It's OK for a method to return a value that is discarded.
|
||||
// The discarding does not require any special action from the caller.
|
||||
// The Java code knows this, at VerifyType.isNullConversion.
|
||||
pop_node(rt); // whatever it was, pop it
|
||||
retnode = top();
|
||||
} else if (rt == T_INT || is_subword_type(rt)) {
|
||||
// FIXME: This logic should be factored out.
|
||||
if (ct == T_BOOLEAN) {
|
||||
retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0x1)) );
|
||||
} else if (ct == T_CHAR) {
|
||||
retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFFFF)) );
|
||||
} else if (ct == T_BYTE) {
|
||||
retnode = _gvn.transform( new (C) LShiftINode(retnode, intcon(24)) );
|
||||
retnode = _gvn.transform( new (C) RShiftINode(retnode, intcon(24)) );
|
||||
} else if (ct == T_SHORT) {
|
||||
retnode = _gvn.transform( new (C) LShiftINode(retnode, intcon(16)) );
|
||||
retnode = _gvn.transform( new (C) RShiftINode(retnode, intcon(16)) );
|
||||
} else {
|
||||
assert(ct == T_INT, err_msg_res("rt=%s, ct=%s", type2name(rt), type2name(ct)));
|
||||
}
|
||||
// Nothing. These cases are handled in lambda form bytecode.
|
||||
assert(ct == T_INT || is_subword_type(ct), err_msg_res("must match: rt=%s, ct=%s", type2name(rt), type2name(ct)));
|
||||
} else if (rt == T_OBJECT || rt == T_ARRAY) {
|
||||
assert(ct == T_OBJECT || ct == T_ARRAY, err_msg_res("rt=%s, ct=%s", type2name(rt), type2name(ct)));
|
||||
if (ctype->is_loaded()) {
|
||||
const TypeOopPtr* arg_type = TypeOopPtr::make_from_klass(rtype->as_klass());
|
||||
const Type* sig_type = TypeOopPtr::make_from_klass(ctype->as_klass());
|
||||
if (arg_type != NULL && !arg_type->higher_equal(sig_type)) {
|
||||
Node* retnode = pop();
|
||||
Node* cast_obj = _gvn.transform(new (C) CheckCastPPNode(control(), retnode, sig_type));
|
||||
pop();
|
||||
push(cast_obj);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(ct == rt, err_msg("unexpected mismatch rt=%d, ct=%d", rt, ct));
|
||||
assert(rt == ct, err_msg_res("unexpected mismatch: rt=%s, ct=%s", type2name(rt), type2name(ct)));
|
||||
// push a zero; it's better than getting an oop/int mismatch
|
||||
retnode = pop_node(rt);
|
||||
retnode = zerocon(ct);
|
||||
pop_node(rt);
|
||||
Node* retnode = zerocon(ct);
|
||||
push_node(ct, retnode);
|
||||
}
|
||||
// Now that the value is well-behaved, continue with the call-site type.
|
||||
rtype = ctype;
|
||||
}
|
||||
} else {
|
||||
assert(rtype == ctype, "mismatched return types"); // symbolic resolution enforces this
|
||||
}
|
||||
|
||||
// If the return type of the method is not loaded, assert that the
|
||||
@ -879,17 +871,39 @@ void Parse::count_compiled_calls(bool at_method_entry, bool is_inline) {
|
||||
#endif //PRODUCT
|
||||
|
||||
|
||||
ciMethod* Compile::optimize_virtual_call(ciMethod* caller, int bci, ciInstanceKlass* klass,
|
||||
ciMethod* callee, const TypeOopPtr* receiver_type,
|
||||
bool is_virtual,
|
||||
bool& call_does_dispatch, int& vtable_index) {
|
||||
// Set default values for out-parameters.
|
||||
call_does_dispatch = true;
|
||||
vtable_index = Method::invalid_vtable_index;
|
||||
|
||||
// Choose call strategy.
|
||||
ciMethod* optimized_virtual_method = optimize_inlining(caller, bci, klass, callee, receiver_type);
|
||||
|
||||
// Have the call been sufficiently improved such that it is no longer a virtual?
|
||||
if (optimized_virtual_method != NULL) {
|
||||
callee = optimized_virtual_method;
|
||||
call_does_dispatch = false;
|
||||
} else if (!UseInlineCaches && is_virtual && callee->is_loaded()) {
|
||||
// We can make a vtable call at this site
|
||||
vtable_index = callee->resolve_vtable_index(caller->holder(), klass);
|
||||
}
|
||||
return callee;
|
||||
}
|
||||
|
||||
// Identify possible target method and inlining style
|
||||
ciMethod* Parse::optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* klass,
|
||||
ciMethod *dest_method, const TypeOopPtr* receiver_type) {
|
||||
ciMethod* Compile::optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* klass,
|
||||
ciMethod* callee, const TypeOopPtr* receiver_type) {
|
||||
// only use for virtual or interface calls
|
||||
|
||||
// If it is obviously final, do not bother to call find_monomorphic_target,
|
||||
// because the class hierarchy checks are not needed, and may fail due to
|
||||
// incompletely loaded classes. Since we do our own class loading checks
|
||||
// in this module, we may confidently bind to any method.
|
||||
if (dest_method->can_be_statically_bound()) {
|
||||
return dest_method;
|
||||
if (callee->can_be_statically_bound()) {
|
||||
return callee;
|
||||
}
|
||||
|
||||
// Attempt to improve the receiver
|
||||
@ -898,8 +912,8 @@ ciMethod* Parse::optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* k
|
||||
if (receiver_type != NULL) {
|
||||
// Array methods are all inherited from Object, and are monomorphic.
|
||||
if (receiver_type->isa_aryptr() &&
|
||||
dest_method->holder() == env()->Object_klass()) {
|
||||
return dest_method;
|
||||
callee->holder() == env()->Object_klass()) {
|
||||
return callee;
|
||||
}
|
||||
|
||||
// All other interesting cases are instance klasses.
|
||||
@ -919,7 +933,7 @@ ciMethod* Parse::optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* k
|
||||
}
|
||||
|
||||
ciInstanceKlass* calling_klass = caller->holder();
|
||||
ciMethod* cha_monomorphic_target = dest_method->find_monomorphic_target(calling_klass, klass, actual_receiver);
|
||||
ciMethod* cha_monomorphic_target = callee->find_monomorphic_target(calling_klass, klass, actual_receiver);
|
||||
if (cha_monomorphic_target != NULL) {
|
||||
assert(!cha_monomorphic_target->is_abstract(), "");
|
||||
// Look at the method-receiver type. Does it add "too much information"?
|
||||
@ -937,10 +951,10 @@ ciMethod* Parse::optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* k
|
||||
cha_monomorphic_target->print();
|
||||
tty->cr();
|
||||
}
|
||||
if (C->log() != NULL) {
|
||||
C->log()->elem("missed_CHA_opportunity klass='%d' method='%d'",
|
||||
C->log()->identify(klass),
|
||||
C->log()->identify(cha_monomorphic_target));
|
||||
if (log() != NULL) {
|
||||
log()->elem("missed_CHA_opportunity klass='%d' method='%d'",
|
||||
log()->identify(klass),
|
||||
log()->identify(cha_monomorphic_target));
|
||||
}
|
||||
cha_monomorphic_target = NULL;
|
||||
}
|
||||
@ -952,7 +966,7 @@ ciMethod* Parse::optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* k
|
||||
// by dynamic class loading. Be sure to test the "static" receiver
|
||||
// dest_method here, as opposed to the actual receiver, which may
|
||||
// falsely lead us to believe that the receiver is final or private.
|
||||
C->dependencies()->assert_unique_concrete_method(actual_receiver, cha_monomorphic_target);
|
||||
dependencies()->assert_unique_concrete_method(actual_receiver, cha_monomorphic_target);
|
||||
return cha_monomorphic_target;
|
||||
}
|
||||
|
||||
@ -961,7 +975,7 @@ ciMethod* Parse::optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* k
|
||||
if (actual_receiver_is_exact) {
|
||||
// In case of evolution, there is a dependence on every inlined method, since each
|
||||
// such method can be changed when its class is redefined.
|
||||
ciMethod* exact_method = dest_method->resolve_invoke(calling_klass, actual_receiver);
|
||||
ciMethod* exact_method = callee->resolve_invoke(calling_klass, actual_receiver);
|
||||
if (exact_method != NULL) {
|
||||
#ifndef PRODUCT
|
||||
if (PrintOpto) {
|
||||
|
@ -1794,10 +1794,15 @@ void GraphKit::replace_call(CallNode* call, Node* result) {
|
||||
|
||||
if (ejvms == NULL) {
|
||||
// No exception edges to simply kill off those paths
|
||||
C->gvn_replace_by(callprojs.catchall_catchproj, C->top());
|
||||
C->gvn_replace_by(callprojs.catchall_memproj, C->top());
|
||||
C->gvn_replace_by(callprojs.catchall_ioproj, C->top());
|
||||
|
||||
if (callprojs.catchall_catchproj != NULL) {
|
||||
C->gvn_replace_by(callprojs.catchall_catchproj, C->top());
|
||||
}
|
||||
if (callprojs.catchall_memproj != NULL) {
|
||||
C->gvn_replace_by(callprojs.catchall_memproj, C->top());
|
||||
}
|
||||
if (callprojs.catchall_ioproj != NULL) {
|
||||
C->gvn_replace_by(callprojs.catchall_ioproj, C->top());
|
||||
}
|
||||
// Replace the old exception object with top
|
||||
if (callprojs.exobj != NULL) {
|
||||
C->gvn_replace_by(callprojs.exobj, C->top());
|
||||
@ -1809,10 +1814,15 @@ void GraphKit::replace_call(CallNode* call, Node* result) {
|
||||
SafePointNode* ex_map = ekit.combine_and_pop_all_exception_states();
|
||||
|
||||
Node* ex_oop = ekit.use_exception_state(ex_map);
|
||||
|
||||
C->gvn_replace_by(callprojs.catchall_catchproj, ekit.control());
|
||||
C->gvn_replace_by(callprojs.catchall_memproj, ekit.reset_memory());
|
||||
C->gvn_replace_by(callprojs.catchall_ioproj, ekit.i_o());
|
||||
if (callprojs.catchall_catchproj != NULL) {
|
||||
C->gvn_replace_by(callprojs.catchall_catchproj, ekit.control());
|
||||
}
|
||||
if (callprojs.catchall_memproj != NULL) {
|
||||
C->gvn_replace_by(callprojs.catchall_memproj, ekit.reset_memory());
|
||||
}
|
||||
if (callprojs.catchall_ioproj != NULL) {
|
||||
C->gvn_replace_by(callprojs.catchall_ioproj, ekit.i_o());
|
||||
}
|
||||
|
||||
// Replace the old exception object with the newly created one
|
||||
if (callprojs.exobj != NULL) {
|
||||
|
@ -2725,10 +2725,8 @@ Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest,
|
||||
zend = phase->transform( new(C) URShiftXNode(zend, shift) );
|
||||
}
|
||||
|
||||
Node* zsize = phase->transform( new(C) SubXNode(zend, zbase) );
|
||||
Node* zinit = phase->zerocon((unit == BytesPerLong) ? T_LONG : T_INT);
|
||||
|
||||
// Bulk clear double-words
|
||||
Node* zsize = phase->transform( new(C) SubXNode(zend, zbase) );
|
||||
Node* adr = phase->transform( new(C) AddPNode(dest, dest, start_offset) );
|
||||
mem = new (C) ClearArrayNode(ctl, mem, zsize, adr);
|
||||
return phase->transform(mem);
|
||||
|
@ -70,7 +70,7 @@ protected:
|
||||
InlineTree *build_inline_tree_for_callee(ciMethod* callee_method,
|
||||
JVMState* caller_jvms,
|
||||
int caller_bci);
|
||||
const char* try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result);
|
||||
const char* try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay);
|
||||
const char* should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const;
|
||||
const char* should_not_inline(ciMethod* callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const;
|
||||
void print_inlining(ciMethod *callee_method, int caller_bci, const char *failure_msg) const;
|
||||
@ -107,7 +107,7 @@ public:
|
||||
// and may be accessed by find_subtree_from_root.
|
||||
// The call_method is the dest_method for a special or static invocation.
|
||||
// The call_method is an optimized virtual method candidate otherwise.
|
||||
WarmCallInfo* ok_to_inline(ciMethod *call_method, JVMState* caller_jvms, ciCallProfile& profile, WarmCallInfo* wci);
|
||||
WarmCallInfo* ok_to_inline(ciMethod *call_method, JVMState* caller_jvms, ciCallProfile& profile, WarmCallInfo* wci, bool& should_delay);
|
||||
|
||||
// Information about inlined method
|
||||
JVMState* caller_jvms() const { return _caller_jvms; }
|
||||
@ -469,10 +469,6 @@ class Parse : public GraphKit {
|
||||
// Helper function to uncommon-trap or bailout for non-compilable call-sites
|
||||
bool can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass *klass);
|
||||
|
||||
// Helper function to identify inlining potential at call-site
|
||||
ciMethod* optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* klass,
|
||||
ciMethod *dest_method, const TypeOopPtr* receiver_type);
|
||||
|
||||
// Helper function to setup for type-profile based inlining
|
||||
bool prepare_type_profile_inline(ciInstanceKlass* prof_klass, ciMethod* prof_method);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user