Merge
This commit is contained in:
commit
79324abda0
1
.hgtags
1
.hgtags
@ -313,3 +313,4 @@ ff3fc75f3214ad7e03595be1b0d0f38d887b6f0e jdk9-b66
|
||||
5b500c93ce4822d47061cd518ff3f72d9d8cb5b5 jdk9-b68
|
||||
d69c968463f0ae5d0b45de3fc14fe65171b23948 jdk9-b69
|
||||
43d0179ee9de3bfffae3417f09e07eb6d8efc963 jdk9-b70
|
||||
f66c185284727f6e6ffd27e9c45ed2dd9da0a691 jdk9-b71
|
||||
|
@ -313,3 +313,4 @@ f546760134eb861fcfecd4ce611b0040b0d25a6a jdk9-b67
|
||||
70e4272790b6199e9ca89df2758ff9cb58ec4125 jdk9-b68
|
||||
1bcfd6b8726582cff5a42dbfc75903e36f9dd4fe jdk9-b69
|
||||
eed77fcd77711fcdba05f18fc22f37d86efb243c jdk9-b70
|
||||
c706ef5ea5da00078dc5e4334660315f7d99c15b jdk9-b71
|
||||
|
@ -4364,7 +4364,7 @@ VS_SDK_PLATFORM_NAME_2013=
|
||||
#CUSTOM_AUTOCONF_INCLUDE
|
||||
|
||||
# Do not change or remove the following line, it is needed for consistency checks:
|
||||
DATE_WHEN_GENERATED=1434614912
|
||||
DATE_WHEN_GENERATED=1435822080
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
@ -42961,7 +42961,7 @@ $as_echo "$as_me: WARNING: X11 is not used, so --with-x is ignored" >&2;}
|
||||
if test "x$x_libraries" = xNONE; then
|
||||
if test -f "$SYSROOT/usr/X11R6/lib/libX11.so"; then
|
||||
x_libraries="$SYSROOT/usr/X11R6/lib"
|
||||
elif test "$SYSROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
|
||||
elif test -f "$SYSROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
|
||||
x_libraries="$SYSROOT/usr/lib64"
|
||||
elif test -f "$SYSROOT/usr/lib/libX11.so"; then
|
||||
x_libraries="$SYSROOT/usr/lib"
|
||||
|
@ -113,7 +113,7 @@ AC_DEFUN_ONCE([LIB_SETUP_X11],
|
||||
if test "x$x_libraries" = xNONE; then
|
||||
if test -f "$SYSROOT/usr/X11R6/lib/libX11.so"; then
|
||||
x_libraries="$SYSROOT/usr/X11R6/lib"
|
||||
elif test "$SYSROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
|
||||
elif test -f "$SYSROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
|
||||
x_libraries="$SYSROOT/usr/lib64"
|
||||
elif test -f "$SYSROOT/usr/lib/libX11.so"; then
|
||||
x_libraries="$SYSROOT/usr/lib"
|
||||
|
@ -1188,28 +1188,11 @@ if [ "$SKIP_DEFAULT" != "true" ]; then
|
||||
OTHER_JDK="$OTHER/install/jdk"
|
||||
OTHER_JRE="$OTHER/install/jre"
|
||||
echo "Selecting install images for compare"
|
||||
elif [ -d "$THIS/deploy/jdk" -o -d "$THIS/deploy/images/jdk" ] \
|
||||
&& [ -d "$OTHER/deploy/jdk" -o -d "$OTHER/deploy/images/jdk" ]; then
|
||||
if [ -d "$THIS/deploy/images/jdk" ]; then
|
||||
THIS_JDK="$THIS/deploy/images/jdk"
|
||||
THIS_JRE="$THIS/deploy/images/jre"
|
||||
else
|
||||
THIS_JDK="$THIS/deploy/jdk"
|
||||
THIS_JRE="$THIS/deploy/jre"
|
||||
fi
|
||||
if [ -d "$OTHER/deploy/images/jdk" ]; then
|
||||
OTHER_JDK="$OTHER/deploy/images/jdk"
|
||||
OTHER_JRE="$OTHER/deploy/images/jre"
|
||||
else
|
||||
OTHER_JDK="$OTHER/deploy/jdk"
|
||||
OTHER_JRE="$OTHER/deploy/jre"
|
||||
fi
|
||||
echo "Selecting deploy images for compare"
|
||||
elif [ -d "$THIS/deploy/images/jdk" ] && [ -d "$OTHER/deploy/jdk" ]; then
|
||||
THIS_JDK="$THIS/deploy/jdk"
|
||||
THIS_JRE="$THIS/deploy/jre"
|
||||
OTHER_JDK="$OTHER/deploy/jdk"
|
||||
OTHER_JRE="$OTHER/deploy/jre"
|
||||
elif [ -d "$THIS/images/jdk" ] && [ -d "$OTHER/deploy/images/jdk" ]; then
|
||||
THIS_JDK="$THIS/images/jdk"
|
||||
THIS_JRE="$THIS/images/jre"
|
||||
OTHER_JDK="$OTHER/deploy/images/jdk"
|
||||
OTHER_JRE="$OTHER/deploy/images/jre"
|
||||
echo "Selecting deploy images for compare"
|
||||
elif [ -d "$THIS/images/jdk" ] && [ -d "$OTHER/images/jdk" ]; then
|
||||
THIS_JDK="$THIS/images/jdk"
|
||||
@ -1221,30 +1204,28 @@ if [ "$SKIP_DEFAULT" != "true" ]; then
|
||||
echo "No common images found."
|
||||
exit 1
|
||||
fi
|
||||
echo " $THIS_JDK"
|
||||
echo " $OTHER_JDK"
|
||||
|
||||
if [ -d "$THIS/deploy/jdk-bundle" -o -d "$THIS/deploy/images/jdk-bundle" ] \
|
||||
&& [ -d "$OTHER/deploy/jdk-bundle" -o -d "$OTHER/deploy/images/jdk-bundle" ]; then
|
||||
if [ -d "$THIS/images/jdk-bundle" -o -d "$THIS/deploy/images/jdk-bundle" ] \
|
||||
&& [ -d "$OTHER/images/jdk-bundle" -o -d "$OTHER/deploy/images/jdk-bundle" ]; then
|
||||
if [ -d "$THIS/deploy/images/jdk-bundle" ]; then
|
||||
THIS_JDK_BUNDLE="$THIS/deploy/images/jdk-bundle"
|
||||
THIS_JRE_BUNDLE="$THIS/deploy/images/jre-bundle"
|
||||
else
|
||||
THIS_JDK_BUNDLE="$THIS/deploy/jdk-bundle"
|
||||
THIS_JRE_BUNDLE="$THIS/deploy/jre-bundle"
|
||||
THIS_JDK_BUNDLE="$THIS/images/jdk-bundle"
|
||||
THIS_JRE_BUNDLE="$THIS/images/jre-bundle"
|
||||
fi
|
||||
if [ -d "$OTHER/deploy/images/jdk-bundle" ]; then
|
||||
OTHER_JDK_BUNDLE="$OTHER/deploy/images/jdk-bundle"
|
||||
OTHER_JRE_BUNDLE="$OTHER/deploy/images/jre-bundle"
|
||||
else
|
||||
OTHER_JDK_BUNDLE="$OTHER/deploy/jdk-bundle"
|
||||
OTHER_JRE_BUNDLE="$OTHER/deploy/jre-bundle"
|
||||
OTHER_JDK_BUNDLE="$OTHER/images/jdk-bundle"
|
||||
OTHER_JRE_BUNDLE="$OTHER/images/jre-bundle"
|
||||
fi
|
||||
echo "Also comparing deploy macosx bundles"
|
||||
elif [ -d "$THIS/images/jdk-bundle" ] && [ -d "$OTHER/images/jdk-bundle" ]; then
|
||||
THIS_JDK_BUNDLE="$THIS/images/jdk-bundle"
|
||||
THIS_JRE_BUNDLE="$THIS/images/jre-bundle"
|
||||
OTHER_JDK_BUNDLE="$OTHER/images/jdk-bundle"
|
||||
OTHER_JRE_BUNDLE="$OTHER/images/jre-bundle"
|
||||
echo "Also comparing macosx bundles"
|
||||
echo " $THIS_JDK_BUNDLE"
|
||||
echo " $OTHER_JDK_BUNDLE"
|
||||
fi
|
||||
|
||||
if [ -d "$THIS/deploy/bundles" -o -d "$THIS/deploy/images/bundles" ] \
|
||||
@ -1262,19 +1243,21 @@ if [ "$SKIP_DEFAULT" != "true" ]; then
|
||||
echo "Also comparing deploy javadoc bundles"
|
||||
fi
|
||||
|
||||
if [ -d "$THIS/deploy/JavaAppletPlugin.plugin" -o -d "$THIS/deploy/images/JavaAppletPlugin.plugin" ] \
|
||||
&& [ -d "$OTHER/deploy/JavaAppletPlugin.plugin" -o -d "$OTHER/deploy/images/JavaAppletPlugin.plugin" ]; then
|
||||
if [ -d "$THIS/deploy/images/bundles" ]; then
|
||||
if [ -d "$THIS/images/JavaAppletPlugin.plugin" ] \
|
||||
&& [ -d "$OTHER/images/JavaAppletPlugin.plugin" -o -d "$OTHER/deploy/images/JavaAppletPlugin.plugin" ]; then
|
||||
if [ -d "$THIS/images/JavaAppletPlugin.plugin" ]; then
|
||||
THIS_DEPLOY_APPLET_PLUGIN_DIR="$THIS/images/JavaAppletPlugin.plugin"
|
||||
else
|
||||
THIS_DEPLOY_APPLET_PLUGIN_DIR="$THIS/deploy/images/JavaAppletPlugin.plugin"
|
||||
else
|
||||
THIS_DEPLOY_APPLET_PLUGIN_DIR="$THIS/deploy/JavaAppletPlugin.plugin"
|
||||
fi
|
||||
if [ -d "$OTHER/deploy/images/bundles" ]; then
|
||||
OTHER_DEPLOY_APPLET_PLUGIN_DIR="$OTHER/deploy/images/JavaAppletPlugin.plugin"
|
||||
if [ -d "$OTHER/images/JavaAppletPlugin.plugin" ]; then
|
||||
OTHER_DEPLOY_APPLET_PLUGIN_DIR="$OTHER/images/JavaAppletPlugin.plugin"
|
||||
else
|
||||
OTHER_DEPLOY_APPLET_PLUGIN_DIR="$OTHER/deploy/JavaAppletPlugin.plugin"
|
||||
OTHER_DEPLOY_APPLET_PLUGIN_DIR="$OTHER/deploy/images/JavaAppletPlugin.plugin"
|
||||
fi
|
||||
echo "Also comparing deploy applet image"
|
||||
echo " $THIS_DEPLOY_APPLET_PLUGIN_DIR"
|
||||
echo " $OTHER_DEPLOY_APPLET_PLUGIN_DIR"
|
||||
fi
|
||||
|
||||
if [ -d "$OTHER/images" ]; then
|
||||
|
@ -313,3 +313,4 @@ afc1e295c4bf83f9a5dd539c29914edd4a754a3f jdk9-b65
|
||||
8efad64f40eb8cd4df376c0a5275892eeb396bbd jdk9-b68
|
||||
de8acedcb5b5870f1dc54cba575aaa5d33897ea2 jdk9-b69
|
||||
e7cf01990ed366bd493080663259281e91ce223b jdk9-b70
|
||||
cd39ed501fb0504554a7f58ac6cf3dd2b64afec0 jdk9-b71
|
||||
|
@ -65,7 +65,7 @@ import org.omg.CORBA.ValueMember;
|
||||
import sun.corba.Bridge;
|
||||
|
||||
/**
|
||||
* A ObjectStreamClass describes a class that can be serialized to a stream
|
||||
* An ObjectStreamClass describes a class that can be serialized to a stream
|
||||
* or a class that was serialized to a stream. It contains the name
|
||||
* and the serialVersionUID of the class.
|
||||
* <br>
|
||||
@ -788,9 +788,9 @@ public class ObjectStreamClass implements java.io.Serializable {
|
||||
/* Compare the base class names of streamName and localName.
|
||||
*
|
||||
* @return Return true iff the base class name compare.
|
||||
* @parameter streamName Fully qualified class name.
|
||||
* @parameter localName Fully qualified class name.
|
||||
* @parameter pkgSeparator class names use either '.' or '/'.
|
||||
* @param streamName Fully qualified class name.
|
||||
* @param localName Fully qualified class name.
|
||||
* @param pkgSeparator class names use either '.' or '/'.
|
||||
*
|
||||
* Only compare base class name to allow package renaming.
|
||||
*/
|
||||
|
@ -656,9 +656,9 @@ public class ObjectStreamClass_1_3_1 implements java.io.Serializable {
|
||||
/* Compare the base class names of streamName and localName.
|
||||
*
|
||||
* @return Return true iff the base class name compare.
|
||||
* @parameter streamName Fully qualified class name.
|
||||
* @parameter localName Fully qualified class name.
|
||||
* @parameter pkgSeparator class names use either '.' or '/'.
|
||||
* @param streamName Fully qualified class name.
|
||||
* @param localName Fully qualified class name.
|
||||
* @param pkgSeparator class names use either '.' or '/'.
|
||||
*
|
||||
* Only compare base class name to allow package renaming.
|
||||
*/
|
||||
|
@ -27,10 +27,10 @@ package org.omg.CORBA;
|
||||
|
||||
|
||||
/**
|
||||
* This Helper class is used to facilitate the marshalling of <tt>Bounds</tt>.
|
||||
* This Helper class is used to facilitate the marshalling of {@code Bounds}.
|
||||
* For more information on Helper files, see
|
||||
* <a href="doc-files/generatedfiles.html#helper">
|
||||
* "Generated Files: Helper Files"</a>.<P>
|
||||
* "Generated Files: Helper Files"</a>.
|
||||
*/
|
||||
|
||||
abstract public class BoundsHelper
|
||||
|
@ -28,10 +28,10 @@ package org.omg.CORBA.ORBPackage;
|
||||
|
||||
/**
|
||||
* This Helper class is used to facilitate the marshalling of
|
||||
* <tt>ORBPackage/InvalidName</tt>.
|
||||
* {@code ORBPackage/InvalidName}.
|
||||
* For more information on Helper files, see
|
||||
* <a href="doc-files/generatedfiles.html#helper">
|
||||
* "Generated Files: Helper Files"</a>.<P>
|
||||
* "Generated Files: Helper Files"</a>.
|
||||
*/
|
||||
|
||||
abstract public class InvalidNameHelper
|
||||
|
@ -28,10 +28,10 @@ package org.omg.CORBA.TypeCodePackage;
|
||||
|
||||
/**
|
||||
* This Helper class is used to facilitate the marshalling of
|
||||
* <tt>TypeCodePackage/BadKind</tt>.
|
||||
* {@code TypeCodePackage/BadKind}.
|
||||
* For more information on Helper files, see
|
||||
* <a href="doc-files/generatedfiles.html#helper">
|
||||
* "Generated Files: Helper Files"</a>.<P>
|
||||
* "Generated Files: Helper Files"</a>.
|
||||
*/
|
||||
|
||||
abstract public class BadKindHelper
|
||||
|
@ -28,10 +28,10 @@ package org.omg.CORBA.TypeCodePackage;
|
||||
|
||||
/**
|
||||
* This Helper class is used to facilitate the marshalling of
|
||||
* <tt>TypeCodePackage/Bounds</tt>.
|
||||
* {@code TypeCodePackage/Bounds}.
|
||||
* For more information on Helper files, see
|
||||
* <a href="doc-files/generatedfiles.html#helper">
|
||||
* "Generated Files: Helper Files"</a>.<P>
|
||||
* "Generated Files: Helper Files"</a>.
|
||||
*/
|
||||
|
||||
abstract public class BoundsHelper
|
||||
|
@ -473,3 +473,4 @@ d47dfabd16d48eb96a451edd1b61194a39ee0eb5 jdk9-b67
|
||||
11af3990d56c97b40318bc1f20608e86f051a3f7 jdk9-b68
|
||||
ff0929a59ced0e144201aa05819ae2e47d6f2c61 jdk9-b69
|
||||
8672e9264db30c21504063932dbc374eabc287a1 jdk9-b70
|
||||
07c6b035d68b0c41b1dcd442157b50b41a2551e9 jdk9-b71
|
||||
|
@ -58,6 +58,7 @@ sun.jvm.hotspot.debugger.cdbg.basic.x86 \
|
||||
sun.jvm.hotspot.debugger.dummy \
|
||||
sun.jvm.hotspot.debugger.linux \
|
||||
sun.jvm.hotspot.debugger.linux.amd64 \
|
||||
sun.jvm.hotspot.debugger.linux.aarch64 \
|
||||
sun.jvm.hotspot.debugger.linux.ppc64 \
|
||||
sun.jvm.hotspot.debugger.linux.x86 \
|
||||
sun.jvm.hotspot.debugger.posix \
|
||||
@ -65,6 +66,7 @@ sun.jvm.hotspot.debugger.posix.elf \
|
||||
sun.jvm.hotspot.debugger.ppc64 \
|
||||
sun.jvm.hotspot.debugger.proc \
|
||||
sun.jvm.hotspot.debugger.proc.amd64 \
|
||||
sun.jvm.hotspot.debugger.proc.aarch64 \
|
||||
sun.jvm.hotspot.debugger.proc.ppc64 \
|
||||
sun.jvm.hotspot.debugger.proc.sparc \
|
||||
sun.jvm.hotspot.debugger.proc.x86 \
|
||||
@ -91,11 +93,13 @@ sun.jvm.hotspot.oops \
|
||||
sun.jvm.hotspot.prims \
|
||||
sun.jvm.hotspot.runtime \
|
||||
sun.jvm.hotspot.runtime.amd64 \
|
||||
sun.jvm.hotspot.runtime.aarch64 \
|
||||
sun.jvm.hotspot.runtime.bsd \
|
||||
sun.jvm.hotspot.runtime.bsd_amd64 \
|
||||
sun.jvm.hotspot.runtime.bsd_x86 \
|
||||
sun.jvm.hotspot.runtime.linux \
|
||||
sun.jvm.hotspot.runtime.linux_amd64 \
|
||||
sun.jvm.hotspot.runtime.linux_aarch64 \
|
||||
sun.jvm.hotspot.runtime.linux_ppc64 \
|
||||
sun.jvm.hotspot.runtime.linux_sparc \
|
||||
sun.jvm.hotspot.runtime.linux_x86 \
|
||||
@ -149,16 +153,19 @@ sun/jvm/hotspot/debugger/dummy/*.java \
|
||||
sun/jvm/hotspot/debugger/linux/*.java \
|
||||
sun/jvm/hotspot/debugger/linux/ppc64/*.java \
|
||||
sun/jvm/hotspot/debugger/linux/x86/*.java \
|
||||
sun/jvm/hotspot/debugger/linux/aarch64/*.java \
|
||||
sun/jvm/hotspot/debugger/posix/*.java \
|
||||
sun/jvm/hotspot/debugger/posix/elf/*.java \
|
||||
sun/jvm/hotspot/debugger/ppc64/*.java \
|
||||
sun/jvm/hotspot/debugger/proc/*.java \
|
||||
sun/jvm/hotspot/debugger/proc/amd64/*.java \
|
||||
sun/jvm/hotspot/debugger/proc/aarch64/*.java \
|
||||
sun/jvm/hotspot/debugger/proc/ppc64/*.java \
|
||||
sun/jvm/hotspot/debugger/proc/sparc/*.java \
|
||||
sun/jvm/hotspot/debugger/proc/x86/*.java \
|
||||
sun/jvm/hotspot/debugger/remote/*.java \
|
||||
sun/jvm/hotspot/debugger/remote/amd64/*.java \
|
||||
sun/jvm/hotspot/debugger/remote/aarch64/*.java \
|
||||
sun/jvm/hotspot/debugger/remote/ppc64/*.java \
|
||||
sun/jvm/hotspot/debugger/remote/sparc/*.java \
|
||||
sun/jvm/hotspot/debugger/remote/x86/*.java \
|
||||
@ -178,11 +185,13 @@ sun/jvm/hotspot/opto/*.java \
|
||||
sun/jvm/hotspot/prims/*.java \
|
||||
sun/jvm/hotspot/runtime/*.java \
|
||||
sun/jvm/hotspot/runtime/amd64/*.java \
|
||||
sun/jvm/hotspot/runtime/aarch64/*.java \
|
||||
sun/jvm/hotspot/runtime/bsd/*.java \
|
||||
sun/jvm/hotspot/runtime/bsd_amd64/*.java \
|
||||
sun/jvm/hotspot/runtime/bsd_x86/*.java \
|
||||
sun/jvm/hotspot/runtime/linux/*.java \
|
||||
sun/jvm/hotspot/runtime/linux_amd64/*.java \
|
||||
sun/jvm/hotspot/runtime/linux_aarch64/*.java \
|
||||
sun/jvm/hotspot/runtime/linux_ppc64/*.java \
|
||||
sun/jvm/hotspot/runtime/linux_sparc/*.java \
|
||||
sun/jvm/hotspot/runtime/linux_x86/*.java \
|
||||
|
@ -53,6 +53,10 @@
|
||||
#include "sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext.h"
|
||||
#endif
|
||||
|
||||
#ifdef aarch64
|
||||
#include "sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext.h"
|
||||
#endif
|
||||
|
||||
static jfieldID p_ps_prochandle_ID = 0;
|
||||
static jfieldID threadList_ID = 0;
|
||||
static jfieldID loadObjectList_ID = 0;
|
||||
@ -368,7 +372,7 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo
|
||||
#define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG
|
||||
#endif
|
||||
#ifdef aarch64
|
||||
#define NPRGREG 32
|
||||
#define NPRGREG sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_NPRGREG
|
||||
#endif
|
||||
#if defined(sparc) || defined(sparcv9)
|
||||
#define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
|
||||
@ -473,6 +477,13 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo
|
||||
|
||||
#define REG_INDEX(reg) sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext_##reg
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 31; i++)
|
||||
regs[i] = gregs.regs[i];
|
||||
regs[REG_INDEX(SP)] = gregs.sp;
|
||||
regs[REG_INDEX(PC)] = gregs.pc;
|
||||
}
|
||||
#endif /* aarch64 */
|
||||
|
||||
#ifdef ppc64
|
||||
|
@ -53,14 +53,15 @@ $(ARCH)/LinuxDebuggerLocal.o: LinuxDebuggerLocal.c
|
||||
$(JAVAH) -jni -classpath ../../../build/classes -d $(ARCH) \
|
||||
sun.jvm.hotspot.debugger.x86.X86ThreadContext \
|
||||
sun.jvm.hotspot.debugger.sparc.SPARCThreadContext \
|
||||
sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext
|
||||
sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext \
|
||||
sun.jvm.hotspot.debugger.aarch64.AARCH64ThreadContext
|
||||
$(GCC) $(CFLAGS) $< -o $@
|
||||
|
||||
$(ARCH)/sadis.o: ../../share/native/sadis.c
|
||||
$(JAVAH) -jni -classpath ../../../build/classes -d $(ARCH) \
|
||||
sun.jvm.hotspot.asm.Disassembler
|
||||
$(GCC) $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
$(ARCH)/%.o: %.c
|
||||
$(GCC) $(CFLAGS) $< -o $@
|
||||
|
||||
|
@ -72,6 +72,7 @@ combination of ptrace and /proc calls.
|
||||
#define user_regs_struct pt_regs
|
||||
#endif
|
||||
#if defined(aarch64)
|
||||
#include <asm/ptrace.h>
|
||||
#define user_regs_struct user_pt_regs
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2015, 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
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
// Linux does not have the proc service library, though it does provide the
|
||||
// thread_db library which can be used to manipulate threads without having
|
||||
// to know the details of LinuxThreads or NPTL
|
||||
// to know the details of NPTL
|
||||
|
||||
// copied from Solaris "proc_service.h"
|
||||
typedef enum {
|
||||
|
@ -983,19 +983,15 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
|
||||
curFrame.getFP(),
|
||||
anno));
|
||||
} else {
|
||||
if (VM.getVM().getCPU().equals("x86") || VM.getVM().getCPU().equals("amd64")) {
|
||||
// For C2, which has null frame pointers on x86/amd64
|
||||
CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC());
|
||||
Address sp = curFrame.getSP();
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(cb.getFrameSize() > 0, "CodeBlob must have non-zero frame size");
|
||||
}
|
||||
annoPanel.addAnnotation(new Annotation(sp,
|
||||
sp.addOffsetTo(cb.getFrameSize()),
|
||||
anno));
|
||||
} else {
|
||||
Assert.that(VM.getVM().getCPU().equals("ia64"), "only ia64 should reach here");
|
||||
// For C2, which has null frame pointers on x86/amd64/aarch64
|
||||
CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC());
|
||||
Address sp = curFrame.getSP();
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(cb.getFrameSize() > 0, "CodeBlob must have non-zero frame size");
|
||||
}
|
||||
annoPanel.addAnnotation(new Annotation(sp,
|
||||
sp.addOffsetTo(cb.getFrameSize()),
|
||||
anno));
|
||||
}
|
||||
|
||||
// Add interpreter frame annotations
|
||||
|
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.debugger.aarch64;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
||||
|
||||
/** Specifies the thread context on aarch64 platforms; only a sub-portion
|
||||
* of the context is guaranteed to be present on all operating
|
||||
* systems. */
|
||||
|
||||
public abstract class AARCH64ThreadContext implements ThreadContext {
|
||||
// Taken from /usr/include/asm/sigcontext.h on Linux/AARCH64.
|
||||
|
||||
// NOTE: the indices for the various registers must be maintained as
|
||||
// listed across various operating systems. However, only a small
|
||||
// subset of the registers' values are guaranteed to be present (and
|
||||
// must be present for the SA's stack walking to work)
|
||||
|
||||
// One instance of the Native annotation is enough to trigger header generation
|
||||
// for this file.
|
||||
@Native
|
||||
public static final int R0 = 0;
|
||||
public static final int R1 = 1;
|
||||
public static final int R2 = 2;
|
||||
public static final int R3 = 3;
|
||||
public static final int R4 = 4;
|
||||
public static final int R5 = 5;
|
||||
public static final int R6 = 6;
|
||||
public static final int R7 = 7;
|
||||
public static final int R8 = 8;
|
||||
public static final int R9 = 9;
|
||||
public static final int R10 = 10;
|
||||
public static final int R11 = 11;
|
||||
public static final int R12 = 12;
|
||||
public static final int R13 = 13;
|
||||
public static final int R14 = 14;
|
||||
public static final int R15 = 15;
|
||||
public static final int R16 = 16;
|
||||
public static final int R17 = 17;
|
||||
public static final int R18 = 18;
|
||||
public static final int R19 = 19;
|
||||
public static final int R20 = 20;
|
||||
public static final int R21 = 21;
|
||||
public static final int R22 = 22;
|
||||
public static final int R23 = 23;
|
||||
public static final int R24 = 24;
|
||||
public static final int R25 = 25;
|
||||
public static final int R26 = 26;
|
||||
public static final int R27 = 27;
|
||||
public static final int R28 = 28;
|
||||
public static final int FP = 29;
|
||||
public static final int LR = 30;
|
||||
public static final int SP = 31;
|
||||
public static final int PC = 32;
|
||||
|
||||
public static final int NPRGREG = 33;
|
||||
|
||||
private long[] data;
|
||||
|
||||
public AARCH64ThreadContext() {
|
||||
data = new long[NPRGREG];
|
||||
}
|
||||
|
||||
public int getNumRegisters() {
|
||||
return NPRGREG;
|
||||
}
|
||||
|
||||
public String getRegisterName(int index) {
|
||||
switch (index) {
|
||||
case LR: return "lr";
|
||||
case SP: return "sp";
|
||||
case PC: return "pc";
|
||||
default:
|
||||
return "r" + index;
|
||||
}
|
||||
}
|
||||
|
||||
public void setRegister(int index, long value) {
|
||||
data[index] = value;
|
||||
}
|
||||
|
||||
public long getRegister(int index) {
|
||||
return data[index];
|
||||
}
|
||||
|
||||
public CFrame getTopFrame(Debugger dbg) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** This can't be implemented in this class since we would have to
|
||||
* tie the implementation to, for example, the debugging system */
|
||||
public abstract void setRegisterAsAddress(int index, Address value);
|
||||
|
||||
/** This can't be implemented in this class since we would have to
|
||||
* tie the implementation to, for example, the debugging system */
|
||||
public abstract Address getRegisterAsAddress(int index);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -31,12 +32,14 @@ import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
||||
import sun.jvm.hotspot.debugger.x86.*;
|
||||
import sun.jvm.hotspot.debugger.amd64.*;
|
||||
import sun.jvm.hotspot.debugger.aarch64.*;
|
||||
import sun.jvm.hotspot.debugger.sparc.*;
|
||||
import sun.jvm.hotspot.debugger.ppc64.*;
|
||||
import sun.jvm.hotspot.debugger.linux.x86.*;
|
||||
import sun.jvm.hotspot.debugger.linux.amd64.*;
|
||||
import sun.jvm.hotspot.debugger.linux.sparc.*;
|
||||
import sun.jvm.hotspot.debugger.linux.ppc64.*;
|
||||
import sun.jvm.hotspot.debugger.linux.aarch64.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
class LinuxCDebugger implements CDebugger {
|
||||
@ -106,6 +109,13 @@ class LinuxCDebugger implements CDebugger {
|
||||
Address pc = context.getRegisterAsAddress(PPC64ThreadContext.PC);
|
||||
if (pc == null) return null;
|
||||
return new LinuxPPC64CFrame(dbg, sp, pc, LinuxDebuggerLocal.getAddressSize());
|
||||
} else if (cpu.equals("aarch64")) {
|
||||
AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext();
|
||||
Address fp = context.getRegisterAsAddress(AARCH64ThreadContext.FP);
|
||||
if (fp == null) return null;
|
||||
Address pc = context.getRegisterAsAddress(AARCH64ThreadContext.PC);
|
||||
if (pc == null) return null;
|
||||
return new LinuxAARCH64CFrame(dbg, fp, pc);
|
||||
} else {
|
||||
// Runtime exception thrown by LinuxThreadContextFactory if unknown cpu
|
||||
ThreadContext context = (ThreadContext) thread.getContext();
|
||||
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.debugger.linux.aarch64;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.aarch64.*;
|
||||
import sun.jvm.hotspot.debugger.linux.*;
|
||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
||||
import sun.jvm.hotspot.debugger.cdbg.basic.*;
|
||||
|
||||
final public class LinuxAARCH64CFrame extends BasicCFrame {
|
||||
public LinuxAARCH64CFrame(LinuxDebugger dbg, Address fp, Address pc) {
|
||||
super(dbg.getCDebugger());
|
||||
this.fp = fp;
|
||||
this.pc = pc;
|
||||
this.dbg = dbg;
|
||||
}
|
||||
|
||||
// override base class impl to avoid ELF parsing
|
||||
public ClosestSymbol closestSymbolToPC() {
|
||||
// try native lookup in debugger.
|
||||
return dbg.lookup(dbg.getAddressValue(pc()));
|
||||
}
|
||||
|
||||
public Address pc() {
|
||||
return pc;
|
||||
}
|
||||
|
||||
public Address localVariableBase() {
|
||||
return fp;
|
||||
}
|
||||
|
||||
public CFrame sender(ThreadProxy thread) {
|
||||
AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext();
|
||||
Address rsp = context.getRegisterAsAddress(AARCH64ThreadContext.SP);
|
||||
|
||||
if ((fp == null) || fp.lessThan(rsp)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check alignment of fp
|
||||
if (dbg.getAddressValue(fp) % (2 * ADDRESS_SIZE) != 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Address nextFP = fp.getAddressAt(0 * ADDRESS_SIZE);
|
||||
if (nextFP == null || nextFP.lessThanOrEqual(fp)) {
|
||||
return null;
|
||||
}
|
||||
Address nextPC = fp.getAddressAt(1 * ADDRESS_SIZE);
|
||||
if (nextPC == null) {
|
||||
return null;
|
||||
}
|
||||
return new LinuxAARCH64CFrame(dbg, nextFP, nextPC);
|
||||
}
|
||||
|
||||
// package/class internals only
|
||||
private static final int ADDRESS_SIZE = 8;
|
||||
private Address pc;
|
||||
private Address sp;
|
||||
private Address fp;
|
||||
private LinuxDebugger dbg;
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.debugger.linux.aarch64;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.aarch64.*;
|
||||
import sun.jvm.hotspot.debugger.linux.*;
|
||||
|
||||
public class LinuxAARCH64ThreadContext extends AARCH64ThreadContext {
|
||||
private LinuxDebugger debugger;
|
||||
|
||||
public LinuxAARCH64ThreadContext(LinuxDebugger debugger) {
|
||||
super();
|
||||
this.debugger = debugger;
|
||||
}
|
||||
|
||||
public void setRegisterAsAddress(int index, Address value) {
|
||||
setRegister(index, debugger.getAddressValue(value));
|
||||
}
|
||||
|
||||
public Address getRegisterAsAddress(int index) {
|
||||
return debugger.newAddress(getRegister(index));
|
||||
}
|
||||
}
|
@ -31,11 +31,13 @@ import java.lang.reflect.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
||||
import sun.jvm.hotspot.debugger.proc.amd64.*;
|
||||
import sun.jvm.hotspot.debugger.proc.aarch64.*;
|
||||
import sun.jvm.hotspot.debugger.proc.sparc.*;
|
||||
import sun.jvm.hotspot.debugger.proc.ppc64.*;
|
||||
import sun.jvm.hotspot.debugger.proc.x86.*;
|
||||
import sun.jvm.hotspot.debugger.ppc64.*;
|
||||
import sun.jvm.hotspot.debugger.amd64.*;
|
||||
import sun.jvm.hotspot.debugger.aarch64.*;
|
||||
import sun.jvm.hotspot.debugger.sparc.*;
|
||||
import sun.jvm.hotspot.debugger.x86.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
@ -88,6 +90,10 @@ public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger {
|
||||
threadFactory = new ProcAMD64ThreadFactory(this);
|
||||
pcRegIndex = AMD64ThreadContext.RIP;
|
||||
fpRegIndex = AMD64ThreadContext.RBP;
|
||||
} else if (cpu.equals("aarch64")) {
|
||||
threadFactory = new ProcAARCH64ThreadFactory(this);
|
||||
pcRegIndex = AARCH64ThreadContext.PC;
|
||||
fpRegIndex = AARCH64ThreadContext.FP;
|
||||
} else if (cpu.equals("ppc64")) {
|
||||
threadFactory = new ProcPPC64ThreadFactory(this);
|
||||
pcRegIndex = PPC64ThreadContext.PC;
|
||||
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.debugger.proc.aarch64;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.aarch64.*;
|
||||
import sun.jvm.hotspot.debugger.proc.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class ProcAARCH64Thread implements ThreadProxy {
|
||||
private ProcDebugger debugger;
|
||||
private int id;
|
||||
|
||||
public ProcAARCH64Thread(ProcDebugger debugger, Address addr) {
|
||||
this.debugger = debugger;
|
||||
|
||||
// FIXME: the size here should be configurable. However, making it
|
||||
// so would produce a dependency on the "types" package from the
|
||||
// debugger package, which is not desired.
|
||||
this.id = (int) addr.getCIntegerAt(0, 4, true);
|
||||
}
|
||||
|
||||
public ProcAARCH64Thread(ProcDebugger debugger, long id) {
|
||||
this.debugger = debugger;
|
||||
this.id = (int) id;
|
||||
}
|
||||
|
||||
public ThreadContext getContext() throws IllegalThreadStateException {
|
||||
ProcAARCH64ThreadContext context = new ProcAARCH64ThreadContext(debugger);
|
||||
long[] regs = debugger.getThreadIntegerRegisterSet(id);
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(regs.length == AARCH64ThreadContext.NPRGREG, "size mismatch");
|
||||
}
|
||||
for (int i = 0; i < regs.length; i++) {
|
||||
context.setRegister(i, regs[i]);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
public boolean canSetContext() throws DebuggerException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setContext(ThreadContext context)
|
||||
throws IllegalThreadStateException, DebuggerException {
|
||||
throw new DebuggerException("Unimplemented");
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "t@" + id;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if ((obj == null) || !(obj instanceof ProcAARCH64Thread)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (((ProcAARCH64Thread) obj).id == id);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return id;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.debugger.proc.aarch64;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.aarch64.*;
|
||||
import sun.jvm.hotspot.debugger.proc.*;
|
||||
|
||||
public class ProcAARCH64ThreadContext extends AARCH64ThreadContext {
|
||||
private ProcDebugger debugger;
|
||||
|
||||
public ProcAARCH64ThreadContext(ProcDebugger debugger) {
|
||||
super();
|
||||
this.debugger = debugger;
|
||||
}
|
||||
|
||||
public void setRegisterAsAddress(int index, Address value) {
|
||||
setRegister(index, debugger.getAddressValue(value));
|
||||
}
|
||||
|
||||
public Address getRegisterAsAddress(int index) {
|
||||
return debugger.newAddress(getRegister(index));
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.debugger.proc.aarch64;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.proc.*;
|
||||
|
||||
public class ProcAARCH64ThreadFactory implements ProcThreadFactory {
|
||||
private ProcDebugger debugger;
|
||||
|
||||
public ProcAARCH64ThreadFactory(ProcDebugger debugger) {
|
||||
this.debugger = debugger;
|
||||
}
|
||||
|
||||
public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
|
||||
return new ProcAARCH64Thread(debugger, threadIdentifierAddr);
|
||||
}
|
||||
|
||||
public ThreadProxy createThreadWrapper(long id) {
|
||||
return new ProcAARCH64Thread(debugger, id);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.debugger.remote.aarch64;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.aarch64.*;
|
||||
import sun.jvm.hotspot.debugger.remote.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class RemoteAARCH64Thread extends RemoteThread {
|
||||
public RemoteAARCH64Thread(RemoteDebuggerClient debugger, Address addr) {
|
||||
super(debugger, addr);
|
||||
}
|
||||
|
||||
public RemoteAARCH64Thread(RemoteDebuggerClient debugger, long id) {
|
||||
super(debugger, id);
|
||||
}
|
||||
|
||||
public ThreadContext getContext() throws IllegalThreadStateException {
|
||||
RemoteAARCH64ThreadContext context = new RemoteAARCH64ThreadContext(debugger);
|
||||
long[] regs = (addr != null)? debugger.getThreadIntegerRegisterSet(addr) :
|
||||
debugger.getThreadIntegerRegisterSet(id);
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(regs.length == AARCH64ThreadContext.NPRGREG, "size of register set must match");
|
||||
}
|
||||
for (int i = 0; i < regs.length; i++) {
|
||||
context.setRegister(i, regs[i]);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.debugger.remote.aarch64;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.aarch64.*;
|
||||
import sun.jvm.hotspot.debugger.remote.*;
|
||||
|
||||
public class RemoteAARCH64ThreadContext extends AARCH64ThreadContext {
|
||||
private RemoteDebuggerClient debugger;
|
||||
|
||||
public RemoteAARCH64ThreadContext(RemoteDebuggerClient debugger) {
|
||||
super();
|
||||
this.debugger = debugger;
|
||||
}
|
||||
|
||||
public void setRegisterAsAddress(int index, Address value) {
|
||||
setRegister(index, debugger.getAddressValue(value));
|
||||
}
|
||||
|
||||
public Address getRegisterAsAddress(int index) {
|
||||
return debugger.newAddress(getRegister(index));
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.debugger.remote.aarch64;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.remote.*;
|
||||
|
||||
public class RemoteAARCH64ThreadFactory implements RemoteThreadFactory {
|
||||
private RemoteDebuggerClient debugger;
|
||||
|
||||
public RemoteAARCH64ThreadFactory(RemoteDebuggerClient debugger) {
|
||||
this.debugger = debugger;
|
||||
}
|
||||
|
||||
public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
|
||||
return new RemoteAARCH64Thread(debugger, threadIdentifierAddr);
|
||||
}
|
||||
|
||||
public ThreadProxy createThreadWrapper(long id) {
|
||||
return new RemoteAARCH64Thread(debugger, id);
|
||||
}
|
||||
}
|
@ -49,7 +49,6 @@ import sun.jvm.hotspot.types.*;
|
||||
public abstract class Generation extends VMObject {
|
||||
private static long reservedFieldOffset;
|
||||
private static long virtualSpaceFieldOffset;
|
||||
private static CIntegerField levelField;
|
||||
protected static final int K = 1024;
|
||||
// Fields for class StatRecord
|
||||
private static Field statRecordField;
|
||||
@ -75,7 +74,6 @@ public abstract class Generation extends VMObject {
|
||||
|
||||
reservedFieldOffset = type.getField("_reserved").getOffset();
|
||||
virtualSpaceFieldOffset = type.getField("_virtual_space").getOffset();
|
||||
levelField = type.getCIntegerField("_level");
|
||||
// StatRecord
|
||||
statRecordField = type.getField("_stat_record");
|
||||
type = db.lookupType("Generation::StatRecord");
|
||||
@ -130,14 +128,6 @@ public abstract class Generation extends VMObject {
|
||||
}
|
||||
}
|
||||
|
||||
public GenerationSpec spec() {
|
||||
return ((GenCollectedHeap) VM.getVM().getUniverse().heap()).spec(level());
|
||||
}
|
||||
|
||||
public int level() {
|
||||
return (int) levelField.getValue(addr);
|
||||
}
|
||||
|
||||
public int invocations() {
|
||||
return getStatRecord().getInvocations();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2015, 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
|
||||
@ -357,12 +357,6 @@ public abstract class Frame implements Cloneable {
|
||||
// FIXME: avoiding implementing this for now if possible
|
||||
// public void interpreter_frame_set_monitor_end(BasicObjectLock* value);
|
||||
// public void interpreter_frame_verify_monitor(BasicObjectLock* value) const;
|
||||
//
|
||||
// Tells whether the current interpreter_frame frame pointer
|
||||
// corresponds to the old compiled/deoptimized fp
|
||||
// The receiver used to be a top level frame
|
||||
// public boolean interpreter_frame_equals_unpacked_fp(intptr_t* fp);
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// Method and constant pool cache:
|
||||
//
|
||||
|
@ -35,6 +35,7 @@ import sun.jvm.hotspot.runtime.win32_amd64.Win32AMD64JavaThreadPDAccess;
|
||||
import sun.jvm.hotspot.runtime.win32_x86.Win32X86JavaThreadPDAccess;
|
||||
import sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess;
|
||||
import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess;
|
||||
import sun.jvm.hotspot.runtime.linux_aarch64.LinuxAARCH64JavaThreadPDAccess;
|
||||
import sun.jvm.hotspot.runtime.linux_ppc64.LinuxPPC64JavaThreadPDAccess;
|
||||
import sun.jvm.hotspot.runtime.linux_sparc.LinuxSPARCJavaThreadPDAccess;
|
||||
import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess;
|
||||
@ -91,6 +92,8 @@ public class Threads {
|
||||
access = new LinuxSPARCJavaThreadPDAccess();
|
||||
} else if (cpu.equals("ppc64")) {
|
||||
access = new LinuxPPC64JavaThreadPDAccess();
|
||||
} else if (cpu.equals("aarch64")) {
|
||||
access = new LinuxAARCH64JavaThreadPDAccess();
|
||||
} else {
|
||||
try {
|
||||
access = (JavaThreadPDAccess)
|
||||
|
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.runtime.aarch64;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.aarch64.*;
|
||||
import sun.jvm.hotspot.code.*;
|
||||
import sun.jvm.hotspot.interpreter.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.runtime.aarch64.*;
|
||||
|
||||
/** <P> Should be able to be used on all aarch64 platforms we support
|
||||
(Linux/aarch64) to implement JavaThread's "currentFrameGuess()"
|
||||
functionality. Input is an AARCH64ThreadContext; output is SP, FP,
|
||||
and PC for an AARCH64Frame. Instantiation of the AARCH64Frame is
|
||||
left to the caller, since we may need to subclass AARCH64Frame to
|
||||
support signal handler frames on Unix platforms. </P>
|
||||
|
||||
<P> Algorithm is to walk up the stack within a given range (say,
|
||||
512K at most) looking for a plausible PC and SP for a Java frame,
|
||||
also considering those coming in from the context. If we find a PC
|
||||
that belongs to the VM (i.e., in generated code like the
|
||||
interpreter or CodeCache) then we try to find an associated FP.
|
||||
We repeat this until we either find a complete frame or run out of
|
||||
stack to look at. </P> */
|
||||
|
||||
public class AARCH64CurrentFrameGuess {
|
||||
private AARCH64ThreadContext context;
|
||||
private JavaThread thread;
|
||||
private Address spFound;
|
||||
private Address fpFound;
|
||||
private Address pcFound;
|
||||
|
||||
private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.aarch64.AARCH64Frame.DEBUG")
|
||||
!= null;
|
||||
|
||||
public AARCH64CurrentFrameGuess(AARCH64ThreadContext context,
|
||||
JavaThread thread) {
|
||||
this.context = context;
|
||||
this.thread = thread;
|
||||
}
|
||||
|
||||
/** Returns false if not able to find a frame within a reasonable range. */
|
||||
public boolean run(long regionInBytesToSearch) {
|
||||
Address sp = context.getRegisterAsAddress(AARCH64ThreadContext.SP);
|
||||
Address pc = context.getRegisterAsAddress(AARCH64ThreadContext.PC);
|
||||
Address fp = context.getRegisterAsAddress(AARCH64ThreadContext.FP);
|
||||
if (sp == null) {
|
||||
// Bail out if no last java frame either
|
||||
if (thread.getLastJavaSP() != null) {
|
||||
setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Address end = sp.addOffsetTo(regionInBytesToSearch);
|
||||
VM vm = VM.getVM();
|
||||
|
||||
setValues(null, null, null); // Assume we're not going to find anything
|
||||
|
||||
if (vm.isJavaPCDbg(pc)) {
|
||||
if (vm.isClientCompiler()) {
|
||||
// If the topmost frame is a Java frame, we are (pretty much)
|
||||
// guaranteed to have a viable FP. We should be more robust
|
||||
// than this (we have the potential for losing entire threads'
|
||||
// stack traces) but need to see how much work we really have
|
||||
// to do here. Searching the stack for an (SP, FP) pair is
|
||||
// hard since it's easy to misinterpret inter-frame stack
|
||||
// pointers as base-of-frame pointers; we also don't know the
|
||||
// sizes of C1 frames (not registered in the nmethod) so can't
|
||||
// derive them from SP.
|
||||
|
||||
setValues(sp, fp, pc);
|
||||
return true;
|
||||
} else {
|
||||
if (vm.getInterpreter().contains(pc)) {
|
||||
if (DEBUG) {
|
||||
System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " +
|
||||
sp + ", fp = " + fp + ", pc = " + pc);
|
||||
}
|
||||
setValues(sp, fp, pc);
|
||||
return true;
|
||||
}
|
||||
|
||||
// For the server compiler, FP is not guaranteed to be valid
|
||||
// for compiled code. In addition, an earlier attempt at a
|
||||
// non-searching algorithm (see below) failed because the
|
||||
// stack pointer from the thread context was pointing
|
||||
// (considerably) beyond the ostensible end of the stack, into
|
||||
// garbage; walking from the topmost frame back caused a crash.
|
||||
//
|
||||
// This algorithm takes the current PC as a given and tries to
|
||||
// find the correct corresponding SP by walking up the stack
|
||||
// and repeatedly performing stackwalks (very inefficient).
|
||||
//
|
||||
// FIXME: there is something wrong with stackwalking across
|
||||
// adapter frames...this is likely to be the root cause of the
|
||||
// failure with the simpler algorithm below.
|
||||
|
||||
for (long offset = 0;
|
||||
offset < regionInBytesToSearch;
|
||||
offset += vm.getAddressSize()) {
|
||||
try {
|
||||
Address curSP = sp.addOffsetTo(offset);
|
||||
Frame frame = new AARCH64Frame(curSP, null, pc);
|
||||
RegisterMap map = thread.newRegisterMap(false);
|
||||
while (frame != null) {
|
||||
if (frame.isEntryFrame() && frame.entryFrameIsFirst()) {
|
||||
// We were able to traverse all the way to the
|
||||
// bottommost Java frame.
|
||||
// This sp looks good. Keep it.
|
||||
if (DEBUG) {
|
||||
System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc);
|
||||
}
|
||||
setValues(curSP, null, pc);
|
||||
return true;
|
||||
}
|
||||
frame = frame.sender(map);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (DEBUG) {
|
||||
System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset);
|
||||
}
|
||||
// Bad SP. Try another.
|
||||
}
|
||||
}
|
||||
|
||||
// Were not able to find a plausible SP to go with this PC.
|
||||
// Bail out.
|
||||
return false;
|
||||
|
||||
/*
|
||||
// Original algorithm which does not work because SP was
|
||||
// pointing beyond where it should have:
|
||||
|
||||
// For the server compiler, FP is not guaranteed to be valid
|
||||
// for compiled code. We see whether the PC is in the
|
||||
// interpreter and take care of that, otherwise we run code
|
||||
// (unfortunately) duplicated from AARCH64Frame.senderForCompiledFrame.
|
||||
|
||||
CodeCache cc = vm.getCodeCache();
|
||||
if (cc.contains(pc)) {
|
||||
CodeBlob cb = cc.findBlob(pc);
|
||||
|
||||
// See if we can derive a frame pointer from SP and PC
|
||||
// NOTE: This is the code duplicated from AARCH64Frame
|
||||
Address saved_fp = null;
|
||||
int llink_offset = cb.getLinkOffset();
|
||||
if (llink_offset >= 0) {
|
||||
// Restore base-pointer, since next frame might be an interpreter frame.
|
||||
Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset);
|
||||
saved_fp = fp_addr.getAddressAt(0);
|
||||
}
|
||||
|
||||
setValues(sp, saved_fp, pc);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
// If the current program counter was not known to us as a Java
|
||||
// PC, we currently assume that we are in the run-time system
|
||||
// and attempt to look to thread-local storage for saved SP and
|
||||
// FP. Note that if these are null (because we were, in fact,
|
||||
// in Java code, i.e., vtable stubs or similar, and the SA
|
||||
// didn't have enough insight into the target VM to understand
|
||||
// that) then we are going to lose the entire stack trace for
|
||||
// the thread, which is sub-optimal. FIXME.
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " +
|
||||
thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP());
|
||||
}
|
||||
if (thread.getLastJavaSP() == null) {
|
||||
return false; // No known Java frames on stack
|
||||
}
|
||||
|
||||
// The runtime has a nasty habit of not saving fp in the frame
|
||||
// anchor, leaving us to grovel about in the stack to find a
|
||||
// plausible address. Fortunately, this only happens in
|
||||
// compiled code; there we always have a valid PC, and we always
|
||||
// push LR and FP onto the stack as a pair, with FP at the lower
|
||||
// address.
|
||||
pc = thread.getLastJavaPC();
|
||||
fp = thread.getLastJavaFP();
|
||||
sp = thread.getLastJavaSP();
|
||||
|
||||
if (fp == null) {
|
||||
CodeCache cc = vm.getCodeCache();
|
||||
if (cc.contains(pc)) {
|
||||
CodeBlob cb = cc.findBlob(pc);
|
||||
if (DEBUG) {
|
||||
System.out.println("FP is null. Found blob frame size " + cb.getFrameSize());
|
||||
}
|
||||
// See if we can derive a frame pointer from SP and PC
|
||||
long link_offset = cb.getFrameSize() - 2 * VM.getVM().getAddressSize();
|
||||
if (link_offset >= 0) {
|
||||
fp = sp.addOffsetTo(link_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setValues(sp, fp, null);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public Address getSP() { return spFound; }
|
||||
public Address getFP() { return fpFound; }
|
||||
/** May be null if getting values from thread-local storage; take
|
||||
care to call the correct AARCH64Frame constructor to recover this if
|
||||
necessary */
|
||||
public Address getPC() { return pcFound; }
|
||||
|
||||
private void setValues(Address sp, Address fp, Address pc) {
|
||||
spFound = sp;
|
||||
fpFound = fp;
|
||||
pcFound = pc;
|
||||
}
|
||||
}
|
@ -0,0 +1,555 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.runtime.aarch64;
|
||||
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.code.*;
|
||||
import sun.jvm.hotspot.compiler.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
/** Specialization of and implementation of abstract methods of the
|
||||
Frame class for the aarch64 family of CPUs. */
|
||||
|
||||
public class AARCH64Frame extends Frame {
|
||||
private static final boolean DEBUG;
|
||||
static {
|
||||
DEBUG = System.getProperty("sun.jvm.hotspot.runtime.aarch64.AARCH64Frame.DEBUG") != null;
|
||||
}
|
||||
|
||||
// All frames
|
||||
private static final int LINK_OFFSET = 0;
|
||||
private static final int RETURN_ADDR_OFFSET = 1;
|
||||
private static final int SENDER_SP_OFFSET = 2;
|
||||
|
||||
// Interpreter frames
|
||||
private static final int INTERPRETER_FRAME_MIRROR_OFFSET = 2; // for native calls only
|
||||
private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1;
|
||||
private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1;
|
||||
private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET - 1;
|
||||
private static int INTERPRETER_FRAME_MDX_OFFSET; // Non-core builds only
|
||||
private static int INTERPRETER_FRAME_CACHE_OFFSET;
|
||||
private static int INTERPRETER_FRAME_LOCALS_OFFSET;
|
||||
private static int INTERPRETER_FRAME_BCX_OFFSET;
|
||||
private static int INTERPRETER_FRAME_INITIAL_SP_OFFSET;
|
||||
private static int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET;
|
||||
private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET;
|
||||
|
||||
// Entry frames
|
||||
private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET = -8;
|
||||
|
||||
// Native frames
|
||||
private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2;
|
||||
|
||||
private static VMReg fp = new VMReg(29);
|
||||
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
initialize(VM.getVM().getTypeDataBase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static synchronized void initialize(TypeDataBase db) {
|
||||
INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1;
|
||||
INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1;
|
||||
INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1;
|
||||
INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
|
||||
INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1;
|
||||
INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
|
||||
INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
|
||||
}
|
||||
|
||||
|
||||
// an additional field beyond sp and pc:
|
||||
Address raw_fp; // frame pointer
|
||||
private Address raw_unextendedSP;
|
||||
|
||||
private AARCH64Frame() {
|
||||
}
|
||||
|
||||
private void adjustForDeopt() {
|
||||
if ( pc != null) {
|
||||
// Look for a deopt pc and if it is deopted convert to original pc
|
||||
CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
|
||||
if (cb != null && cb.isJavaMethod()) {
|
||||
NMethod nm = (NMethod) cb;
|
||||
if (pc.equals(nm.deoptHandlerBegin())) {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
|
||||
}
|
||||
// adjust pc if frame is deoptimized.
|
||||
pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
|
||||
deoptimized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AARCH64Frame(Address raw_sp, Address raw_fp, Address pc) {
|
||||
this.raw_sp = raw_sp;
|
||||
this.raw_unextendedSP = raw_sp;
|
||||
this.raw_fp = raw_fp;
|
||||
this.pc = pc;
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("AARCH64Frame(sp, fp, pc): " + this);
|
||||
dumpStack();
|
||||
}
|
||||
}
|
||||
|
||||
public AARCH64Frame(Address raw_sp, Address raw_fp) {
|
||||
this.raw_sp = raw_sp;
|
||||
this.raw_unextendedSP = raw_sp;
|
||||
this.raw_fp = raw_fp;
|
||||
this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("AARCH64Frame(sp, fp): " + this);
|
||||
dumpStack();
|
||||
}
|
||||
}
|
||||
|
||||
public AARCH64Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) {
|
||||
this.raw_sp = raw_sp;
|
||||
this.raw_unextendedSP = raw_unextendedSp;
|
||||
this.raw_fp = raw_fp;
|
||||
this.pc = pc;
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("AARCH64Frame(sp, unextendedSP, fp, pc): " + this);
|
||||
dumpStack();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
AARCH64Frame frame = new AARCH64Frame();
|
||||
frame.raw_sp = raw_sp;
|
||||
frame.raw_unextendedSP = raw_unextendedSP;
|
||||
frame.raw_fp = raw_fp;
|
||||
frame.pc = pc;
|
||||
frame.deoptimized = deoptimized;
|
||||
return frame;
|
||||
}
|
||||
|
||||
public boolean equals(Object arg) {
|
||||
if (arg == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(arg instanceof AARCH64Frame)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AARCH64Frame other = (AARCH64Frame) arg;
|
||||
|
||||
return (AddressOps.equal(getSP(), other.getSP()) &&
|
||||
AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) &&
|
||||
AddressOps.equal(getFP(), other.getFP()) &&
|
||||
AddressOps.equal(getPC(), other.getPC()));
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
if (raw_sp == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return raw_sp.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "sp: " + (getSP() == null? "null" : getSP().toString()) +
|
||||
", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) +
|
||||
", fp: " + (getFP() == null? "null" : getFP().toString()) +
|
||||
", pc: " + (pc == null? "null" : pc.toString());
|
||||
}
|
||||
|
||||
// accessors for the instance variables
|
||||
public Address getFP() { return raw_fp; }
|
||||
public Address getSP() { return raw_sp; }
|
||||
public Address getID() { return raw_sp; }
|
||||
|
||||
// FIXME: not implemented yet
|
||||
public boolean isSignalHandlerFrameDbg() { return false; }
|
||||
public int getSignalNumberDbg() { return 0; }
|
||||
public String getSignalNameDbg() { return null; }
|
||||
|
||||
public boolean isInterpretedFrameValid() {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(isInterpretedFrame(), "Not an interpreted frame");
|
||||
}
|
||||
|
||||
// These are reasonable sanity checks
|
||||
if (getFP() == null || getFP().andWithMask(0x3) != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getSP() == null || getSP().andWithMask(0x3) != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// These are hacks to keep us out of trouble.
|
||||
// The problem with these is that they mask other problems
|
||||
if (getFP().lessThanOrEqual(getSP())) {
|
||||
// this attempts to deal with unsigned comparison above
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) {
|
||||
// stack frames shouldn't be large.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: not applicable in current system
|
||||
// void patch_pc(Thread* thread, address pc);
|
||||
|
||||
public Frame sender(RegisterMap regMap, CodeBlob cb) {
|
||||
AARCH64RegisterMap map = (AARCH64RegisterMap) regMap;
|
||||
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(map != null, "map must be set");
|
||||
}
|
||||
|
||||
// Default is we done have to follow them. The sender_for_xxx will
|
||||
// update it accordingly
|
||||
map.setIncludeArgumentOops(false);
|
||||
|
||||
if (isEntryFrame()) return senderForEntryFrame(map);
|
||||
if (isInterpretedFrame()) return senderForInterpreterFrame(map);
|
||||
|
||||
if(cb == null) {
|
||||
cb = VM.getVM().getCodeCache().findBlob(getPC());
|
||||
} else {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
|
||||
}
|
||||
}
|
||||
|
||||
if (cb != null) {
|
||||
return senderForCompiledFrame(map, cb);
|
||||
}
|
||||
|
||||
// Must be native-compiled frame, i.e. the marshaling code for native
|
||||
// methods that exists in the core system.
|
||||
return new AARCH64Frame(getSenderSP(), getLink(), getSenderPC());
|
||||
}
|
||||
|
||||
private Frame senderForEntryFrame(AARCH64RegisterMap map) {
|
||||
if (DEBUG) {
|
||||
System.out.println("senderForEntryFrame");
|
||||
}
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(map != null, "map must be set");
|
||||
}
|
||||
// Java frame called from C; skip all C frames and return top C
|
||||
// frame of that chunk as the sender
|
||||
AARCH64JavaCallWrapper jcw = (AARCH64JavaCallWrapper) getEntryFrameCallWrapper();
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
|
||||
Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
|
||||
}
|
||||
AARCH64Frame fr;
|
||||
if (jcw.getLastJavaPC() != null) {
|
||||
fr = new AARCH64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC());
|
||||
} else {
|
||||
fr = new AARCH64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP());
|
||||
}
|
||||
map.clear();
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
private void adjustUnextendedSP() {
|
||||
// If we are returning to a compiled MethodHandle call site, the
|
||||
// saved_fp will in fact be a saved value of the unextended SP. The
|
||||
// simplest way to tell whether we are returning to such a call site
|
||||
// is as follows:
|
||||
|
||||
CodeBlob cb = cb();
|
||||
NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull();
|
||||
if (senderNm != null) {
|
||||
// If the sender PC is a deoptimization point, get the original
|
||||
// PC. For MethodHandle call site the unextended_sp is stored in
|
||||
// saved_fp.
|
||||
if (senderNm.isDeoptMhEntry(getPC())) {
|
||||
// DEBUG_ONLY(verifyDeoptMhOriginalPc(senderNm, getFP()));
|
||||
raw_unextendedSP = getFP();
|
||||
}
|
||||
else if (senderNm.isDeoptEntry(getPC())) {
|
||||
// DEBUG_ONLY(verifyDeoptOriginalPc(senderNm, raw_unextendedSp));
|
||||
}
|
||||
else if (senderNm.isMethodHandleReturn(getPC())) {
|
||||
raw_unextendedSP = getFP();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Frame senderForInterpreterFrame(AARCH64RegisterMap map) {
|
||||
if (DEBUG) {
|
||||
System.out.println("senderForInterpreterFrame");
|
||||
}
|
||||
Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
|
||||
Address sp = addressOfStackSlot(SENDER_SP_OFFSET);
|
||||
// We do not need to update the callee-save register mapping because above
|
||||
// us is either another interpreter frame or a converter-frame, but never
|
||||
// directly a compiled frame.
|
||||
// 11/24/04 SFG. With the removal of adapter frames this is no longer true.
|
||||
// However c2 no longer uses callee save register for java calls so there
|
||||
// are no callee register to find.
|
||||
|
||||
if (map.getUpdateMap())
|
||||
updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET));
|
||||
|
||||
return new AARCH64Frame(sp, unextendedSP, getLink(), getSenderPC());
|
||||
}
|
||||
|
||||
private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
|
||||
map.setLocation(fp, savedFPAddr);
|
||||
}
|
||||
|
||||
private Frame senderForCompiledFrame(AARCH64RegisterMap map, CodeBlob cb) {
|
||||
if (DEBUG) {
|
||||
System.out.println("senderForCompiledFrame");
|
||||
}
|
||||
|
||||
//
|
||||
// NOTE: some of this code is (unfortunately) duplicated AARCH64CurrentFrameGuess
|
||||
//
|
||||
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(map != null, "map must be set");
|
||||
}
|
||||
|
||||
// frame owned by optimizing compiler
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size");
|
||||
}
|
||||
Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize());
|
||||
|
||||
// The return_address is always the word on the stack
|
||||
Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize());
|
||||
|
||||
// This is the saved value of FP which may or may not really be an FP.
|
||||
// It is only an FP if the sender is an interpreter frame.
|
||||
Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize());
|
||||
|
||||
if (map.getUpdateMap()) {
|
||||
// Tell GC to use argument oopmaps for some runtime stubs that need it.
|
||||
// For C1, the runtime stub might not have oop maps, so set this flag
|
||||
// outside of update_register_map.
|
||||
map.setIncludeArgumentOops(cb.callerMustGCArguments());
|
||||
|
||||
if (cb.getOopMaps() != null) {
|
||||
ImmutableOopMapSet.updateRegisterMap(this, cb, map, true);
|
||||
}
|
||||
|
||||
// Since the prolog does the save and restore of FP there is no oopmap
|
||||
// for it so we must fill in its location as if there was an oopmap entry
|
||||
// since if our caller was compiled code there could be live jvm state in it.
|
||||
updateMapWithSavedLink(map, savedFPAddr);
|
||||
}
|
||||
|
||||
return new AARCH64Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC);
|
||||
}
|
||||
|
||||
protected boolean hasSenderPD() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public long frameSize() {
|
||||
return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize());
|
||||
}
|
||||
|
||||
public Address getLink() {
|
||||
try {
|
||||
if (DEBUG) {
|
||||
System.out.println("Reading link at " + addressOfStackSlot(LINK_OFFSET)
|
||||
+ " = " + addressOfStackSlot(LINK_OFFSET).getAddressAt(0));
|
||||
}
|
||||
return addressOfStackSlot(LINK_OFFSET).getAddressAt(0);
|
||||
} catch (Exception e) {
|
||||
if (DEBUG)
|
||||
System.out.println("Returning null");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: not implementable yet
|
||||
//inline void frame::set_link(intptr_t* addr) { *(intptr_t **)addr_at(link_offset) = addr; }
|
||||
|
||||
public Address getUnextendedSP() { return raw_unextendedSP; }
|
||||
|
||||
// Return address:
|
||||
public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); }
|
||||
public Address getSenderPC() { return getSenderPCAddr().getAddressAt(0); }
|
||||
|
||||
// return address of param, zero origin index.
|
||||
public Address getNativeParamAddr(int idx) {
|
||||
return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx);
|
||||
}
|
||||
|
||||
public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); }
|
||||
|
||||
public Address addressOfInterpreterFrameLocals() {
|
||||
return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
|
||||
}
|
||||
|
||||
private Address addressOfInterpreterFrameBCX() {
|
||||
return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET);
|
||||
}
|
||||
|
||||
public int getInterpreterFrameBCI() {
|
||||
// FIXME: this is not atomic with respect to GC and is unsuitable
|
||||
// for use in a non-debugging, or reflective, system. Need to
|
||||
// figure out how to express this.
|
||||
Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
|
||||
Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0);
|
||||
Method method = (Method)Metadata.instantiateWrapperFor(methodHandle);
|
||||
return bcpToBci(bcp, method);
|
||||
}
|
||||
|
||||
public Address addressOfInterpreterFrameMDX() {
|
||||
return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
//inline int frame::interpreter_frame_monitor_size() {
|
||||
// return BasicObjectLock::size();
|
||||
//}
|
||||
|
||||
// expression stack
|
||||
// (the max_stack arguments are used by the GC; see class FrameClosure)
|
||||
|
||||
public Address addressOfInterpreterFrameExpressionStack() {
|
||||
Address monitorEnd = interpreterFrameMonitorEnd().address();
|
||||
return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize());
|
||||
}
|
||||
|
||||
public int getInterpreterFrameExpressionStackDirection() { return -1; }
|
||||
|
||||
// top of expression stack
|
||||
public Address addressOfInterpreterFrameTOS() {
|
||||
return getSP();
|
||||
}
|
||||
|
||||
/** Expression stack from top down */
|
||||
public Address addressOfInterpreterFrameTOSAt(int slot) {
|
||||
return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
|
||||
}
|
||||
|
||||
public Address getInterpreterFrameSenderSP() {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(isInterpretedFrame(), "interpreted frame expected");
|
||||
}
|
||||
return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
|
||||
}
|
||||
|
||||
// Monitors
|
||||
public BasicObjectLock interpreterFrameMonitorBegin() {
|
||||
return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET));
|
||||
}
|
||||
|
||||
public BasicObjectLock interpreterFrameMonitorEnd() {
|
||||
Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0);
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
// make sure the pointer points inside the frame
|
||||
Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer");
|
||||
Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer");
|
||||
}
|
||||
return new BasicObjectLock(result);
|
||||
}
|
||||
|
||||
public int interpreterFrameMonitorSize() {
|
||||
return BasicObjectLock.size();
|
||||
}
|
||||
|
||||
// Method
|
||||
public Address addressOfInterpreterFrameMethod() {
|
||||
return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET);
|
||||
}
|
||||
|
||||
// Constant pool cache
|
||||
public Address addressOfInterpreterFrameCPCache() {
|
||||
return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET);
|
||||
}
|
||||
|
||||
// Entry frames
|
||||
public JavaCallWrapper getEntryFrameCallWrapper() {
|
||||
return new AARCH64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0));
|
||||
}
|
||||
|
||||
protected Address addressOfSavedOopResult() {
|
||||
// offset is 2 for compiler2 and 3 for compiler1
|
||||
return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) *
|
||||
VM.getVM().getAddressSize());
|
||||
}
|
||||
|
||||
protected Address addressOfSavedReceiver() {
|
||||
return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
|
||||
}
|
||||
|
||||
private void dumpStack() {
|
||||
for (Address addr = getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
|
||||
AddressOps.lt(addr, getSP());
|
||||
addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
|
||||
System.out.println(addr + ": " + addr.getAddressAt(0));
|
||||
}
|
||||
System.out.println("-----------------------");
|
||||
for (Address addr = getSP();
|
||||
AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize()));
|
||||
addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
|
||||
System.out.println(addr + ": " + addr.getAddressAt(0));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.runtime.aarch64;
|
||||
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
|
||||
public class AARCH64JavaCallWrapper extends JavaCallWrapper {
|
||||
private static AddressField lastJavaFPField;
|
||||
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
initialize(VM.getVM().getTypeDataBase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static synchronized void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("JavaFrameAnchor");
|
||||
|
||||
lastJavaFPField = type.getAddressField("_last_Java_fp");
|
||||
}
|
||||
|
||||
public AARCH64JavaCallWrapper(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public Address getLastJavaFP() {
|
||||
return lastJavaFPField.getValue(addr.addOffsetTo(anchorField.getOffset()));
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.runtime.aarch64;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
|
||||
public class AARCH64RegisterMap extends RegisterMap {
|
||||
|
||||
/** This is the only public constructor */
|
||||
public AARCH64RegisterMap(JavaThread thread, boolean updateMap) {
|
||||
super(thread, updateMap);
|
||||
}
|
||||
|
||||
protected AARCH64RegisterMap(RegisterMap map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
AARCH64RegisterMap retval = new AARCH64RegisterMap(this);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// no PD state to clear or copy:
|
||||
protected void clearPD() {}
|
||||
protected void initializePD() {}
|
||||
protected void initializeFromPD(RegisterMap map) {}
|
||||
protected Address getLocationPD(VMReg reg) { return null; }
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.runtime.linux_aarch64;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.debugger.aarch64.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.runtime.aarch64.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class LinuxAARCH64JavaThreadPDAccess implements JavaThreadPDAccess {
|
||||
private static AddressField lastJavaFPField;
|
||||
private static AddressField osThreadField;
|
||||
|
||||
// Field from OSThread
|
||||
private static CIntegerField osThreadThreadIDField;
|
||||
|
||||
// This is currently unneeded but is being kept in case we change
|
||||
// the currentFrameGuess algorithm
|
||||
private static final long GUESS_SCAN_RANGE = 128 * 1024;
|
||||
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
initialize(VM.getVM().getTypeDataBase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static synchronized void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("JavaThread");
|
||||
osThreadField = type.getAddressField("_osthread");
|
||||
|
||||
Type anchorType = db.lookupType("JavaFrameAnchor");
|
||||
lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
|
||||
|
||||
Type osThreadType = db.lookupType("OSThread");
|
||||
osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id");
|
||||
}
|
||||
|
||||
public Address getLastJavaFP(Address addr) {
|
||||
return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
|
||||
}
|
||||
|
||||
public Address getLastJavaPC(Address addr) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Address getBaseOfStackPointer(Address addr) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Frame getLastFramePD(JavaThread thread, Address addr) {
|
||||
Address fp = thread.getLastJavaFP();
|
||||
if (fp == null) {
|
||||
return null; // no information
|
||||
}
|
||||
return new AARCH64Frame(thread.getLastJavaSP(), fp);
|
||||
}
|
||||
|
||||
public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
|
||||
return new AARCH64RegisterMap(thread, updateMap);
|
||||
}
|
||||
|
||||
public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
|
||||
ThreadProxy t = getThreadProxy(addr);
|
||||
AARCH64ThreadContext context = (AARCH64ThreadContext) t.getContext();
|
||||
AARCH64CurrentFrameGuess guesser = new AARCH64CurrentFrameGuess(context, thread);
|
||||
if (!guesser.run(GUESS_SCAN_RANGE)) {
|
||||
return null;
|
||||
}
|
||||
if (guesser.getPC() == null) {
|
||||
return new AARCH64Frame(guesser.getSP(), guesser.getFP());
|
||||
} else {
|
||||
return new AARCH64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
|
||||
}
|
||||
}
|
||||
|
||||
public void printThreadIDOn(Address addr, PrintStream tty) {
|
||||
tty.print(getThreadProxy(addr));
|
||||
}
|
||||
|
||||
public void printInfoOn(Address threadAddr, PrintStream tty) {
|
||||
tty.print("Thread id: ");
|
||||
printThreadIDOn(threadAddr, tty);
|
||||
// tty.println("\nPostJavaState: " + getPostJavaState(threadAddr));
|
||||
}
|
||||
|
||||
public Address getLastSP(Address addr) {
|
||||
ThreadProxy t = getThreadProxy(addr);
|
||||
AARCH64ThreadContext context = (AARCH64ThreadContext) t.getContext();
|
||||
return context.getRegisterAsAddress(AARCH64ThreadContext.SP);
|
||||
}
|
||||
|
||||
public ThreadProxy getThreadProxy(Address addr) {
|
||||
// Addr is the address of the JavaThread.
|
||||
// Fetch the OSThread (for now and for simplicity, not making a
|
||||
// separate "OSThread" class in this package)
|
||||
Address osThreadAddr = osThreadField.getValue(addr);
|
||||
// Get the address of the _thread_id from the OSThread
|
||||
Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
|
||||
|
||||
JVMDebugger debugger = VM.getVM().getDebugger();
|
||||
return debugger.getThreadForIdentifierAddress(threadIdAddr);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2015, 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
|
||||
@ -25,7 +25,10 @@
|
||||
package sun.jvm.hotspot.utilities;
|
||||
|
||||
public interface AltPlatformInfo {
|
||||
// Additional cpu types can be tested via this interface
|
||||
|
||||
// Additional cpu types can be tested via this interface
|
||||
public boolean knownCPU(String cpu);
|
||||
}
|
||||
|
||||
// Mangle a cpu name if necessary
|
||||
public String getCPU(String cpu);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2015, 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
|
||||
@ -52,27 +52,54 @@ public class PlatformInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns "sparc" for SPARC based platforms and "x86" for x86 based
|
||||
platforms. Otherwise returns the value of os.arch. If the value
|
||||
is not recognized as supported, an exception is thrown instead. */
|
||||
public static boolean knownCPU(String cpu) {
|
||||
final String[] KNOWN =
|
||||
new String[] {"i386", "x86", "x86_64", "amd64", "sparc", "sparcv9", "ppc64", "aarch64"};
|
||||
|
||||
for(String s : KNOWN) {
|
||||
if(s.equals(cpu))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Returns "sparc" for SPARC based platforms "x86" for x86 based
|
||||
platforms and x86_64 for 64bit x86 based platform. Otherwise
|
||||
returns the value of os.arch. If the value is not recognized as supported,
|
||||
an exception is thrown instead. */
|
||||
|
||||
public static String getCPU() throws UnsupportedPlatformException {
|
||||
String cpu = System.getProperty("os.arch");
|
||||
if (cpu.equals("i386") || cpu.equals("x86")) {
|
||||
return "x86";
|
||||
} else if (cpu.equals("sparc") || cpu.equals("sparcv9")) {
|
||||
return "sparc";
|
||||
} else if (cpu.equals("ia64") || cpu.equals("amd64") || cpu.equals("x86_64") || cpu.equals("ppc64") || cpu.equals("aarch64")) {
|
||||
return cpu;
|
||||
} else {
|
||||
try {
|
||||
Class pic = Class.forName("sun.jvm.hotspot.utilities.PlatformInfoClosed");
|
||||
AltPlatformInfo api = (AltPlatformInfo)pic.newInstance();
|
||||
if (api.knownCPU(cpu)) {
|
||||
return cpu;
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
throw new UnsupportedPlatformException("CPU type " + cpu + " not yet supported");
|
||||
|
||||
// Let any additional CPU mangling fire first
|
||||
try {
|
||||
Class pic = Class.forName("sun.jvm.hotspot.utilities.PlatformInfoClosed");
|
||||
AltPlatformInfo api = (AltPlatformInfo) pic.newInstance();
|
||||
if (api.knownCPU(cpu)) {
|
||||
return api.getCPU(cpu);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignored
|
||||
}
|
||||
|
||||
// Check that CPU is supported
|
||||
if (!knownCPU(cpu)) {
|
||||
throw new UnsupportedPlatformException("CPU type " + cpu + " not yet supported");
|
||||
}
|
||||
|
||||
// Tweeks
|
||||
if (cpu.equals("i386"))
|
||||
return "x86";
|
||||
|
||||
if (cpu.equals("sparcv9"))
|
||||
return "sparc";
|
||||
|
||||
if (cpu.equals("x86_64"))
|
||||
return "amd64";
|
||||
|
||||
return cpu;
|
||||
|
||||
}
|
||||
|
||||
// this main is invoked from Makefile to make platform specific agent Makefile(s).
|
||||
|
@ -84,11 +84,11 @@ public class PointerLocation {
|
||||
}
|
||||
|
||||
public boolean isInNewGen() {
|
||||
return ((gen != null) && (gen.level() == 0));
|
||||
return ((gen != null) && (gen == ((GenCollectedHeap)heap).getGen(0)));
|
||||
}
|
||||
|
||||
public boolean isInOldGen() {
|
||||
return ((gen != null) && (gen.level() == 1));
|
||||
return ((gen != null) && (gen == ((GenCollectedHeap)heap).getGen(1)));
|
||||
}
|
||||
|
||||
public boolean inOtherGen() {
|
||||
@ -207,8 +207,6 @@ public class PointerLocation {
|
||||
tty.print("In new generation ");
|
||||
} else if (isInOldGen()) {
|
||||
tty.print("In old generation ");
|
||||
} else if (gen != null) {
|
||||
tty.print("In Generation " + getGeneration().level());
|
||||
} else {
|
||||
tty.print("In unknown section of Java heap");
|
||||
}
|
||||
|
@ -263,14 +263,19 @@ endif
|
||||
$(DtraceOutDir):
|
||||
mkdir $(DtraceOutDir)
|
||||
|
||||
# When building using a devkit, dtrace cannot find the correct preprocessor so
|
||||
# we run it explicitly before runing dtrace.
|
||||
$(DtraceOutDir)/hotspot.h: $(DTRACE_COMMON_SRCDIR)/hotspot.d | $(DtraceOutDir)
|
||||
$(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hotspot.d
|
||||
$(QUIETLY) $(CC) -E $(DTRACE_OPTS) -I. -x c $(DTRACE_COMMON_SRCDIR)/hotspot.d > $(DtraceOutDir)/hotspot.d
|
||||
$(QUIETLY) $(DTRACE_PROG) -h -o $@ -s $(DtraceOutDir)/hotspot.d
|
||||
|
||||
$(DtraceOutDir)/hotspot_jni.h: $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d | $(DtraceOutDir)
|
||||
$(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d
|
||||
$(QUIETLY) $(CC) -E $(DTRACE_OPTS) -I. -x c $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d > $(DtraceOutDir)/hotspot_jni.d
|
||||
$(QUIETLY) $(DTRACE_PROG) -h -o $@ -s $(DtraceOutDir)/hotspot_jni.d
|
||||
|
||||
$(DtraceOutDir)/hs_private.h: $(DTRACE_COMMON_SRCDIR)/hs_private.d | $(DtraceOutDir)
|
||||
$(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -h -o $@ -s $(DTRACE_COMMON_SRCDIR)/hs_private.d
|
||||
$(QUIETLY) $(CC) -E $(DTRACE_OPTS) -I. -x c $(DTRACE_COMMON_SRCDIR)/hs_private.d > $(DtraceOutDir)/hs_private.d
|
||||
$(QUIETLY) $(DTRACE_PROG) -h -o $@ -s $(DtraceOutDir)/hs_private.d
|
||||
|
||||
dtrace_gen_headers: $(DtraceOutDir)/hotspot.h $(DtraceOutDir)/hotspot_jni.h $(DtraceOutDir)/hs_private.h
|
||||
|
||||
|
@ -56,13 +56,14 @@ all_debug_universal:
|
||||
universalize: $(UNIVERSAL_LIPO_LIST) $(UNIVERSAL_COPY_LIST)
|
||||
$(RM) -r $(EXPORT_PATH)/lib/{i386,amd64}
|
||||
|
||||
LIPO ?= lipo
|
||||
|
||||
# Package built libraries in a universal binary
|
||||
$(UNIVERSAL_LIPO_LIST):
|
||||
BUILT_LIPO_FILES="`find $(EXPORT_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_LIB_DIR)/,,$@) 2>/dev/null`" || test $$? = "1"; \
|
||||
if [ -n "$${BUILT_LIPO_FILES}" ]; then \
|
||||
$(MKDIR) -p $(shell dirname $@); \
|
||||
lipo -create -output $@ $${BUILT_LIPO_FILES}; \
|
||||
$(LIPO) -create -output $@ $${BUILT_LIPO_FILES}; \
|
||||
fi
|
||||
|
||||
|
||||
|
@ -44,6 +44,7 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/code/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/compiler/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/amd64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/aarch64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/amd64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/x86/*.java \
|
||||
@ -55,6 +56,7 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/amd64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ia64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ppc64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/aarch64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/x86/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/sparc/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/posix/*.java \
|
||||
@ -63,6 +65,7 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/ppc64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/amd64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/ppc64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/aarch64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/sparc/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/x86/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/*.java \
|
||||
@ -70,6 +73,7 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/amd64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/ppc64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/sparc/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/x86/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/aarch64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/sparc/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/win32/coff/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/*.java \
|
||||
@ -92,11 +96,13 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/opto/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/prims/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/amd64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/aarch64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd_amd64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/bsd_x86/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_amd64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_aarch64/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_x86/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_sparc/*.java \
|
||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_ppc64/*.java \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -526,16 +526,6 @@ frame frame::sender(RegisterMap* map) const {
|
||||
return frame(sender_sp(), link(), sender_pc());
|
||||
}
|
||||
|
||||
bool frame::interpreter_frame_equals_unpacked_fp(intptr_t* fp) {
|
||||
assert(is_interpreted_frame(), "must be interpreter frame");
|
||||
Method* method = interpreter_frame_method();
|
||||
// When unpacking an optimized frame the frame pointer is
|
||||
// adjusted with:
|
||||
int diff = (method->max_locals() - method->size_of_parameters()) *
|
||||
Interpreter::stackElementWords;
|
||||
return _fp == (fp - diff);
|
||||
}
|
||||
|
||||
bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
|
||||
// QQQ
|
||||
#ifdef CC_INTERP
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc. 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
|
||||
@ -84,7 +84,7 @@ define_pd_global(intx, InlineSmallCode, 1000);
|
||||
|
||||
#ifdef BUILTIN_SIM
|
||||
#define UseBuiltinSim true
|
||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
|
||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
||||
\
|
||||
product(bool, NotifySimulator, UseBuiltinSim, \
|
||||
"tell the AArch64 sim where we are in method code") \
|
||||
@ -112,7 +112,7 @@ define_pd_global(intx, InlineSmallCode, 1000);
|
||||
#define NotifySimulator false
|
||||
#define UseSimulatorCache false
|
||||
#define DisableBCCheck true
|
||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
|
||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
||||
\
|
||||
product(bool, NearCpool, true, \
|
||||
"constant pool is close to instructions") \
|
||||
|
@ -2934,41 +2934,40 @@ void MacroAssembler::cmpptr(Register src1, Address src2) {
|
||||
cmp(src1, rscratch1);
|
||||
}
|
||||
|
||||
void MacroAssembler::store_check(Register obj) {
|
||||
// Does a store check for the oop in register obj. The content of
|
||||
// register obj is destroyed afterwards.
|
||||
store_check_part_1(obj);
|
||||
store_check_part_2(obj);
|
||||
}
|
||||
|
||||
void MacroAssembler::store_check(Register obj, Address dst) {
|
||||
store_check(obj);
|
||||
}
|
||||
|
||||
void MacroAssembler::store_check(Register obj) {
|
||||
// Does a store check for the oop in register obj. The content of
|
||||
// register obj is destroyed afterwards.
|
||||
|
||||
// split the store check operation so that other instructions can be scheduled inbetween
|
||||
void MacroAssembler::store_check_part_1(Register obj) {
|
||||
BarrierSet* bs = Universe::heap()->barrier_set();
|
||||
assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
|
||||
lsr(obj, obj, CardTableModRefBS::card_shift);
|
||||
}
|
||||
|
||||
void MacroAssembler::store_check_part_2(Register obj) {
|
||||
BarrierSet* bs = Universe::heap()->barrier_set();
|
||||
assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
|
||||
CardTableModRefBS* ct = (CardTableModRefBS*)bs;
|
||||
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
|
||||
|
||||
// The calculation for byte_map_base is as follows:
|
||||
// byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift);
|
||||
// So this essentially converts an address to a displacement and
|
||||
// it will never need to be relocated.
|
||||
lsr(obj, obj, CardTableModRefBS::card_shift);
|
||||
|
||||
// FIXME: It's not likely that disp will fit into an offset so we
|
||||
// don't bother to check, but it could save an instruction.
|
||||
intptr_t disp = (intptr_t) ct->byte_map_base;
|
||||
mov(rscratch1, disp);
|
||||
strb(zr, Address(obj, rscratch1));
|
||||
assert(CardTableModRefBS::dirty_card_val() == 0, "must be");
|
||||
|
||||
{
|
||||
ExternalAddress cardtable((address) ct->byte_map_base);
|
||||
unsigned long offset;
|
||||
adrp(rscratch1, cardtable, offset);
|
||||
assert(offset == 0, "byte_map_base is misaligned");
|
||||
}
|
||||
|
||||
if (UseCondCardMark) {
|
||||
Label L_already_dirty;
|
||||
ldrb(rscratch2, Address(obj, rscratch1));
|
||||
cbz(rscratch2, L_already_dirty);
|
||||
strb(zr, Address(obj, rscratch1));
|
||||
bind(L_already_dirty);
|
||||
} else {
|
||||
strb(zr, Address(obj, rscratch1));
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::load_klass(Register dst, Register src) {
|
||||
|
@ -719,10 +719,6 @@ public:
|
||||
|
||||
#endif // INCLUDE_ALL_GCS
|
||||
|
||||
// split store_check(Register obj) to enhance instruction interleaving
|
||||
void store_check_part_1(Register obj);
|
||||
void store_check_part_2(Register obj);
|
||||
|
||||
// oop manipulations
|
||||
void load_klass(Register dst, Register src);
|
||||
void store_klass(Register dst, Register src);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2015, Red Hat Inc. 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
|
||||
@ -2120,6 +2120,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
save_native_result(masm, ret_type, stack_slots);
|
||||
}
|
||||
|
||||
__ mov(c_rarg2, rthread);
|
||||
__ lea(c_rarg1, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size));
|
||||
__ mov(c_rarg0, obj_reg);
|
||||
|
||||
@ -2128,7 +2129,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
__ ldr(r19, Address(rthread, in_bytes(Thread::pending_exception_offset())));
|
||||
__ str(zr, Address(rthread, in_bytes(Thread::pending_exception_offset())));
|
||||
|
||||
rt_call(masm, CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), 2, 0, 1);
|
||||
rt_call(masm, CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), 3, 0, 1);
|
||||
|
||||
#ifdef ASSERT
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -190,6 +190,11 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
}
|
||||
|
||||
if (UseGHASHIntrinsics) {
|
||||
warning("GHASH intrinsics are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
|
||||
}
|
||||
|
||||
if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
|
||||
UseCRC32Intrinsics = true;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ define_pd_global(size_t, CMSYoungGenPerWorker, 16*M); // Default max size of CM
|
||||
define_pd_global(uintx, TypeProfileLevel, 111);
|
||||
|
||||
// Platform dependent flag handling: flags only defined on this platform.
|
||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
|
||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
||||
\
|
||||
/* Load poll address from thread. This is used to implement per-thread */ \
|
||||
/* safepoints on platforms != IA64. */ \
|
||||
|
@ -2475,7 +2475,8 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||
|
||||
// Slow case of monitor enter.
|
||||
// Inline a special case of call_VM that disallows any pending_exception.
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), r_oop, r_box);
|
||||
// Arguments are (oop obj, BasicLock* lock, JavaThread* thread).
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), r_oop, r_box, R16_thread);
|
||||
|
||||
__ asm_assert_mem8_is_zero(thread_(pending_exception),
|
||||
"no pending exception allowed on exit from SharedRuntime::complete_monitor_unlocking_C", 0);
|
||||
|
@ -176,6 +176,11 @@ void VM_Version::initialize() {
|
||||
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
|
||||
}
|
||||
|
||||
if (UseGHASHIntrinsics) {
|
||||
warning("GHASH intrinsics are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
|
||||
}
|
||||
|
||||
if (UseSHA) {
|
||||
warning("SHA instructions are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
@ -505,7 +510,8 @@ void VM_Version::determine_section_size() {
|
||||
|
||||
void VM_Version::determine_features() {
|
||||
#if defined(ABI_ELFv2)
|
||||
const int code_size = (num_features+1+2*7)*BytesPerInstWord; // TODO(asmundak): calculation is incorrect.
|
||||
// 1 InstWord per call for the blr instruction.
|
||||
const int code_size = (num_features+1+2*1)*BytesPerInstWord;
|
||||
#else
|
||||
// 7 InstWords for each call (function descriptor + blr instruction).
|
||||
const int code_size = (num_features+1+2*7)*BytesPerInstWord;
|
||||
@ -540,7 +546,8 @@ void VM_Version::determine_features() {
|
||||
a->popcntw(R7, R5); // code[6] -> popcntw
|
||||
a->fcfids(F3, F4); // code[7] -> fcfids
|
||||
a->vand(VR0, VR0, VR0); // code[8] -> vand
|
||||
a->lqarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[9] -> lqarx_m
|
||||
// arg0 of lqarx must be an even register, (arg1 + arg2) must be a multiple of 16
|
||||
a->lqarx_unchecked(R6, R3_ARG1, R4_ARG2, 1); // code[9] -> lqarx_m
|
||||
a->vcipher(VR0, VR1, VR2); // code[10] -> vcipher
|
||||
a->vpmsumb(VR0, VR1, VR2); // code[11] -> vpmsumb
|
||||
a->tcheck(0); // code[12] -> tcheck
|
||||
@ -572,7 +579,8 @@ void VM_Version::determine_features() {
|
||||
|
||||
// Execute code. Illegal instructions will be replaced by 0 in the signal handler.
|
||||
VM_Version::_is_determine_features_test_running = true;
|
||||
(*test)((address)mid_of_test_area, (uint64_t)0);
|
||||
// We must align the first argument to 16 bytes because of the lqarx check.
|
||||
(*test)((address)align_size_up((intptr_t)mid_of_test_area, 16), (uint64_t)0);
|
||||
VM_Version::_is_determine_features_test_running = false;
|
||||
|
||||
// determine which instructions are legal.
|
||||
@ -614,12 +622,12 @@ void VM_Version::config_dscr() {
|
||||
MacroAssembler* a = new MacroAssembler(&cb);
|
||||
|
||||
// Emit code.
|
||||
uint64_t (*get_dscr)() = (uint64_t(*)())(void *)a->emit_fd();
|
||||
uint64_t (*get_dscr)() = (uint64_t(*)())(void *)a->function_entry();
|
||||
uint32_t *code = (uint32_t *)a->pc();
|
||||
a->mfdscr(R3);
|
||||
a->blr();
|
||||
|
||||
void (*set_dscr)(long) = (void(*)(long))(void *)a->emit_fd();
|
||||
void (*set_dscr)(long) = (void(*)(long))(void *)a->function_entry();
|
||||
a->mtdscr(R3);
|
||||
a->blr();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, 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
|
||||
@ -129,6 +129,7 @@ class Assembler : public AbstractAssembler {
|
||||
flog3_op3 = 0x36,
|
||||
edge_op3 = 0x36,
|
||||
fsrc_op3 = 0x36,
|
||||
xmulx_op3 = 0x36,
|
||||
impdep2_op3 = 0x37,
|
||||
stpartialf_op3 = 0x37,
|
||||
jmpl_op3 = 0x38,
|
||||
@ -220,6 +221,8 @@ class Assembler : public AbstractAssembler {
|
||||
mdtox_opf = 0x110,
|
||||
mstouw_opf = 0x111,
|
||||
mstosw_opf = 0x113,
|
||||
xmulx_opf = 0x115,
|
||||
xmulxhi_opf = 0x116,
|
||||
mxtod_opf = 0x118,
|
||||
mwtos_opf = 0x119,
|
||||
|
||||
@ -1212,6 +1215,9 @@ public:
|
||||
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)); }
|
||||
|
||||
void xmulx(Register s1, Register s2, Register d) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(xmulx_op3) | rs1(s1) | opf(xmulx_opf) | rs2(s2)); }
|
||||
void xmulxhi(Register s1, Register s2, Register d) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(xmulx_op3) | rs1(s1) | opf(xmulxhi_opf) | rs2(s2)); }
|
||||
|
||||
// Crypto SHA instructions
|
||||
|
||||
void sha1() { sha1_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha1_opf)); }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, 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
|
||||
@ -599,12 +599,6 @@ bool frame::is_valid_stack_pointer(intptr_t* valid_sp, intptr_t* sp) {
|
||||
return next_younger_sp_or_null(valid_sp, sp) != NULL;
|
||||
}
|
||||
|
||||
|
||||
bool frame::interpreter_frame_equals_unpacked_fp(intptr_t* fp) {
|
||||
assert(is_interpreted_frame(), "must be interpreter frame");
|
||||
return this->fp() == fp;
|
||||
}
|
||||
|
||||
bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
|
||||
#ifdef CC_INTERP
|
||||
// Is there anything to do?
|
||||
|
@ -81,7 +81,7 @@ define_pd_global(size_t, CMSYoungGenPerWorker, 16*M); // default max size of CM
|
||||
|
||||
define_pd_global(uintx, TypeProfileLevel, 111);
|
||||
|
||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
|
||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
||||
\
|
||||
product(intx, UseVIS, 99, \
|
||||
"Highest supported VIS instructions set on Sparc") \
|
||||
|
@ -4786,6 +4786,130 @@ class StubGenerator: public StubCodeGenerator {
|
||||
return start;
|
||||
}
|
||||
|
||||
/* Single and multi-block ghash operations */
|
||||
address generate_ghash_processBlocks() {
|
||||
__ align(CodeEntryAlignment);
|
||||
Label L_ghash_loop, L_aligned, L_main;
|
||||
StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
|
||||
address start = __ pc();
|
||||
|
||||
Register state = I0;
|
||||
Register subkeyH = I1;
|
||||
Register data = I2;
|
||||
Register len = I3;
|
||||
|
||||
__ save_frame(0);
|
||||
|
||||
__ ldx(state, 0, O0);
|
||||
__ ldx(state, 8, O1);
|
||||
|
||||
// Loop label for multiblock operations
|
||||
__ BIND(L_ghash_loop);
|
||||
|
||||
// Check if 'data' is unaligned
|
||||
__ andcc(data, 7, G1);
|
||||
__ br(Assembler::zero, false, Assembler::pt, L_aligned);
|
||||
__ delayed()->nop();
|
||||
|
||||
Register left_shift = L1;
|
||||
Register right_shift = L2;
|
||||
Register data_ptr = L3;
|
||||
|
||||
// Get left and right shift values in bits
|
||||
__ sll(G1, LogBitsPerByte, left_shift);
|
||||
__ mov(64, right_shift);
|
||||
__ sub(right_shift, left_shift, right_shift);
|
||||
|
||||
// Align to read 'data'
|
||||
__ sub(data, G1, data_ptr);
|
||||
|
||||
// Load first 8 bytes of 'data'
|
||||
__ ldx(data_ptr, 0, O4);
|
||||
__ sllx(O4, left_shift, O4);
|
||||
__ ldx(data_ptr, 8, O5);
|
||||
__ srlx(O5, right_shift, G4);
|
||||
__ bset(G4, O4);
|
||||
|
||||
// Load second 8 bytes of 'data'
|
||||
__ sllx(O5, left_shift, O5);
|
||||
__ ldx(data_ptr, 16, G4);
|
||||
__ srlx(G4, right_shift, G4);
|
||||
__ ba(L_main);
|
||||
__ delayed()->bset(G4, O5);
|
||||
|
||||
// If 'data' is aligned, load normally
|
||||
__ BIND(L_aligned);
|
||||
__ ldx(data, 0, O4);
|
||||
__ ldx(data, 8, O5);
|
||||
|
||||
__ BIND(L_main);
|
||||
__ ldx(subkeyH, 0, O2);
|
||||
__ ldx(subkeyH, 8, O3);
|
||||
|
||||
__ xor3(O0, O4, O0);
|
||||
__ xor3(O1, O5, O1);
|
||||
|
||||
__ xmulxhi(O0, O3, G3);
|
||||
__ xmulx(O0, O2, O5);
|
||||
__ xmulxhi(O1, O2, G4);
|
||||
__ xmulxhi(O1, O3, G5);
|
||||
__ xmulx(O0, O3, G1);
|
||||
__ xmulx(O1, O3, G2);
|
||||
__ xmulx(O1, O2, O3);
|
||||
__ xmulxhi(O0, O2, O4);
|
||||
|
||||
__ mov(0xE1, O0);
|
||||
__ sllx(O0, 56, O0);
|
||||
|
||||
__ xor3(O5, G3, O5);
|
||||
__ xor3(O5, G4, O5);
|
||||
__ xor3(G5, G1, G1);
|
||||
__ xor3(G1, O3, G1);
|
||||
__ srlx(G2, 63, O1);
|
||||
__ srlx(G1, 63, G3);
|
||||
__ sllx(G2, 63, O3);
|
||||
__ sllx(G2, 58, O2);
|
||||
__ xor3(O3, O2, O2);
|
||||
|
||||
__ sllx(G1, 1, G1);
|
||||
__ or3(G1, O1, G1);
|
||||
|
||||
__ xor3(G1, O2, G1);
|
||||
|
||||
__ sllx(G2, 1, G2);
|
||||
|
||||
__ xmulxhi(G1, O0, O1);
|
||||
__ xmulx(G1, O0, O2);
|
||||
__ xmulxhi(G2, O0, O3);
|
||||
__ xmulx(G2, O0, G1);
|
||||
|
||||
__ xor3(O4, O1, O4);
|
||||
__ xor3(O5, O2, O5);
|
||||
__ xor3(O5, O3, O5);
|
||||
|
||||
__ sllx(O4, 1, O2);
|
||||
__ srlx(O5, 63, O3);
|
||||
|
||||
__ or3(O2, O3, O0);
|
||||
|
||||
__ sllx(O5, 1, O1);
|
||||
__ srlx(G1, 63, O2);
|
||||
__ or3(O1, O2, O1);
|
||||
__ xor3(O1, G3, O1);
|
||||
|
||||
__ deccc(len);
|
||||
__ br(Assembler::notZero, true, Assembler::pt, L_ghash_loop);
|
||||
__ delayed()->add(data, 16, data);
|
||||
|
||||
__ stx(O0, I0, 0);
|
||||
__ stx(O1, I0, 8);
|
||||
|
||||
__ ret();
|
||||
__ delayed()->restore();
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
void generate_initial() {
|
||||
// Generates all stubs and initializes the entry points
|
||||
|
||||
@ -4859,6 +4983,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt();
|
||||
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel();
|
||||
}
|
||||
// generate GHASH intrinsics code
|
||||
if (UseGHASHIntrinsics) {
|
||||
StubRoutines::_ghash_processBlocks = generate_ghash_processBlocks();
|
||||
}
|
||||
|
||||
// generate SHA1/SHA256/SHA512 intrinsics code
|
||||
if (UseSHA1Intrinsics) {
|
||||
|
@ -300,6 +300,17 @@ void VM_Version::initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
// GHASH/GCM intrinsics
|
||||
if (has_vis3() && (UseVIS > 2)) {
|
||||
if (FLAG_IS_DEFAULT(UseGHASHIntrinsics)) {
|
||||
UseGHASHIntrinsics = true;
|
||||
}
|
||||
} else if (UseGHASHIntrinsics) {
|
||||
if (!FLAG_IS_DEFAULT(UseGHASHIntrinsics))
|
||||
warning("GHASH intrinsics require VIS3 insructions support. Intriniscs will be disabled");
|
||||
FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
|
||||
}
|
||||
|
||||
// SHA1, SHA256, and SHA512 instructions were added to SPARC T-series at different times
|
||||
if (has_sha1() || has_sha256() || has_sha512()) {
|
||||
if (UseVIS > 0) { // SHA intrinsics use VIS1 instructions
|
||||
|
@ -1347,7 +1347,7 @@ void Assembler::andl(Register dst, Register src) {
|
||||
|
||||
void Assembler::andnl(Register dst, Register src1, Register src2) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
int encode = vex_prefix_0F38_and_encode(dst, src1, src2, false);
|
||||
int encode = vex_prefix_0F38_and_encode_legacy(dst, src1, src2, false);
|
||||
emit_int8((unsigned char)0xF2);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
@ -1355,7 +1355,7 @@ void Assembler::andnl(Register dst, Register src1, Register src2) {
|
||||
void Assembler::andnl(Register dst, Register src1, Address src2) {
|
||||
InstructionMark im(this);
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
vex_prefix_0F38(dst, src1, src2, false);
|
||||
vex_prefix_0F38_legacy(dst, src1, src2, false);
|
||||
emit_int8((unsigned char)0xF2);
|
||||
emit_operand(dst, src2);
|
||||
}
|
||||
@ -1382,7 +1382,7 @@ void Assembler::bswapl(Register reg) { // bswap
|
||||
|
||||
void Assembler::blsil(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
int encode = vex_prefix_0F38_and_encode(rbx, dst, src, false);
|
||||
int encode = vex_prefix_0F38_and_encode_legacy(rbx, dst, src, false);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
@ -1390,14 +1390,14 @@ void Assembler::blsil(Register dst, Register src) {
|
||||
void Assembler::blsil(Register dst, Address src) {
|
||||
InstructionMark im(this);
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
vex_prefix_0F38(rbx, dst, src, false);
|
||||
vex_prefix_0F38_legacy(rbx, dst, src, false);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
emit_operand(rbx, src);
|
||||
}
|
||||
|
||||
void Assembler::blsmskl(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
int encode = vex_prefix_0F38_and_encode(rdx, dst, src, false);
|
||||
int encode = vex_prefix_0F38_and_encode_legacy(rdx, dst, src, false);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
@ -1412,7 +1412,7 @@ void Assembler::blsmskl(Register dst, Address src) {
|
||||
|
||||
void Assembler::blsrl(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
int encode = vex_prefix_0F38_and_encode(rcx, dst, src, false);
|
||||
int encode = vex_prefix_0F38_and_encode_legacy(rcx, dst, src, false);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
@ -1420,7 +1420,7 @@ void Assembler::blsrl(Register dst, Register src) {
|
||||
void Assembler::blsrl(Register dst, Address src) {
|
||||
InstructionMark im(this);
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
vex_prefix_0F38(rcx, dst, src, false);
|
||||
vex_prefix_0F38_legacy(rcx, dst, src, false);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
emit_operand(rcx, src);
|
||||
}
|
||||
@ -3095,8 +3095,16 @@ void Assembler::pshuflw(XMMRegister dst, Address src, int mode) {
|
||||
void Assembler::psrldq(XMMRegister dst, int shift) {
|
||||
// Shift 128 bit value in xmm register by number of bytes.
|
||||
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
|
||||
int encode = simd_prefix_and_encode(xmm3, dst, dst, VEX_SIMD_66, true, VEX_OPCODE_0F,
|
||||
false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
|
||||
int encode = simd_prefix_and_encode(xmm3, dst, dst, VEX_SIMD_66, true, VEX_OPCODE_0F, false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
|
||||
emit_int8(0x73);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
emit_int8(shift);
|
||||
}
|
||||
|
||||
void Assembler::pslldq(XMMRegister dst, int shift) {
|
||||
// Shift left 128 bit value in xmm register by number of bytes.
|
||||
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
|
||||
int encode = simd_prefix_and_encode(xmm7, dst, dst, VEX_SIMD_66, true, VEX_OPCODE_0F, false, AVX_128bit, (VM_Version::supports_avx512bw() == false));
|
||||
emit_int8(0x73);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
emit_int8(shift);
|
||||
@ -3106,15 +3114,16 @@ void Assembler::ptest(XMMRegister dst, Address src) {
|
||||
assert(VM_Version::supports_sse4_1(), "");
|
||||
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
|
||||
InstructionMark im(this);
|
||||
simd_prefix(dst, src, VEX_SIMD_66, false, VEX_OPCODE_0F_38);
|
||||
simd_prefix(dst, xnoreg, src, VEX_SIMD_66, false,
|
||||
VEX_OPCODE_0F_38, false, AVX_128bit, true);
|
||||
emit_int8(0x17);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::ptest(XMMRegister dst, XMMRegister src) {
|
||||
assert(VM_Version::supports_sse4_1(), "");
|
||||
int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
|
||||
false, VEX_OPCODE_0F_38);
|
||||
int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, false,
|
||||
VEX_OPCODE_0F_38, false, AVX_128bit, true);
|
||||
emit_int8(0x17);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
@ -3126,7 +3135,7 @@ void Assembler::vptest(XMMRegister dst, Address src) {
|
||||
assert(dst != xnoreg, "sanity");
|
||||
int dst_enc = dst->encoding();
|
||||
// swap src<->dst for encoding
|
||||
vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len);
|
||||
vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len, true, false);
|
||||
emit_int8(0x17);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
@ -3135,7 +3144,7 @@ void Assembler::vptest(XMMRegister dst, XMMRegister src) {
|
||||
assert(VM_Version::supports_avx(), "");
|
||||
int vector_len = AVX_256bit;
|
||||
int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
|
||||
vector_len, VEX_OPCODE_0F_38);
|
||||
vector_len, VEX_OPCODE_0F_38, true, false);
|
||||
emit_int8(0x17);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
@ -3146,12 +3155,12 @@ void Assembler::punpcklbw(XMMRegister dst, Address src) {
|
||||
if (VM_Version::supports_evex()) {
|
||||
tuple_type = EVEX_FVM;
|
||||
}
|
||||
emit_simd_arith(0x60, dst, src, VEX_SIMD_66);
|
||||
emit_simd_arith(0x60, dst, src, VEX_SIMD_66, false, (VM_Version::supports_avx512vlbw() == false));
|
||||
}
|
||||
|
||||
void Assembler::punpcklbw(XMMRegister dst, XMMRegister src) {
|
||||
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
|
||||
emit_simd_arith(0x60, dst, src, VEX_SIMD_66);
|
||||
emit_simd_arith(0x60, dst, src, VEX_SIMD_66, false, (VM_Version::supports_avx512vlbw() == false));
|
||||
}
|
||||
|
||||
void Assembler::punpckldq(XMMRegister dst, Address src) {
|
||||
@ -4979,7 +4988,51 @@ void Assembler::vpbroadcastd(XMMRegister dst, XMMRegister src) {
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
// duplicate 4-bytes integer data from src into 8 locations in dest
|
||||
// duplicate 1-byte integer data from src into 16||32|64 locations in dest : requires AVX512BW and AVX512VL
|
||||
void Assembler::evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
|
||||
vector_len, VEX_OPCODE_0F_38, false);
|
||||
emit_int8(0x78);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evpbroadcastb(XMMRegister dst, Address src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
tuple_type = EVEX_T1S;
|
||||
input_size_in_bits = EVEX_8bit;
|
||||
InstructionMark im(this);
|
||||
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, vector_len);
|
||||
emit_int8(0x78);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
// duplicate 2-byte integer data from src into 8|16||32 locations in dest : requires AVX512BW and AVX512VL
|
||||
void Assembler::evpbroadcastw(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
|
||||
vector_len, VEX_OPCODE_0F_38, false);
|
||||
emit_int8(0x79);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evpbroadcastw(XMMRegister dst, Address src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
tuple_type = EVEX_T1S;
|
||||
input_size_in_bits = EVEX_16bit;
|
||||
InstructionMark im(this);
|
||||
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, vector_len);
|
||||
emit_int8(0x79);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
// duplicate 4-byte integer data from src into 4|8|16 locations in dest : requires AVX512VL
|
||||
void Assembler::evpbroadcastd(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
|
||||
@ -4988,6 +5041,121 @@ void Assembler::evpbroadcastd(XMMRegister dst, XMMRegister src, int vector_len)
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evpbroadcastd(XMMRegister dst, Address src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
tuple_type = EVEX_T1S;
|
||||
input_size_in_bits = EVEX_32bit;
|
||||
InstructionMark im(this);
|
||||
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, vector_len);
|
||||
emit_int8(0x58);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
// duplicate 8-byte integer data from src into 4|8|16 locations in dest : requires AVX512VL
|
||||
void Assembler::evpbroadcastq(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
|
||||
VEX_OPCODE_0F_38, true, vector_len, false, false);
|
||||
emit_int8(0x59);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evpbroadcastq(XMMRegister dst, Address src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
tuple_type = EVEX_T1S;
|
||||
input_size_in_bits = EVEX_64bit;
|
||||
InstructionMark im(this);
|
||||
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, true, vector_len);
|
||||
emit_int8(0x59);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
// duplicate single precision fp from src into 4|8|16 locations in dest : requires AVX512VL
|
||||
void Assembler::evpbroadcastss(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
|
||||
VEX_OPCODE_0F_38, false, vector_len, false, false);
|
||||
emit_int8(0x18);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evpbroadcastss(XMMRegister dst, Address src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
tuple_type = EVEX_T1S;
|
||||
input_size_in_bits = EVEX_32bit;
|
||||
InstructionMark im(this);
|
||||
assert(dst != xnoreg, "sanity");
|
||||
int dst_enc = dst->encoding();
|
||||
// swap src<->dst for encoding
|
||||
vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector_len);
|
||||
emit_int8(0x18);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
// duplicate double precision fp from src into 2|4|8 locations in dest : requires AVX512VL
|
||||
void Assembler::evpbroadcastsd(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
|
||||
VEX_OPCODE_0F_38, true, vector_len, false, false);
|
||||
emit_int8(0x19);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evpbroadcastsd(XMMRegister dst, Address src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
tuple_type = EVEX_T1S;
|
||||
input_size_in_bits = EVEX_64bit;
|
||||
InstructionMark im(this);
|
||||
assert(dst != xnoreg, "sanity");
|
||||
int dst_enc = dst->encoding();
|
||||
// swap src<->dst for encoding
|
||||
vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, true, vector_len);
|
||||
emit_int8(0x19);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
// duplicate 1-byte integer data from src into 16||32|64 locations in dest : requires AVX512BW and AVX512VL
|
||||
void Assembler::evpbroadcastb(XMMRegister dst, Register src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
|
||||
VEX_OPCODE_0F_38, false, vector_len, false, false);
|
||||
emit_int8(0x7A);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
// duplicate 2-byte integer data from src into 8|16||32 locations in dest : requires AVX512BW and AVX512VL
|
||||
void Assembler::evpbroadcastw(XMMRegister dst, Register src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
|
||||
VEX_OPCODE_0F_38, false, vector_len, false, false);
|
||||
emit_int8(0x7B);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
// duplicate 4-byte integer data from src into 4|8|16 locations in dest : requires AVX512VL
|
||||
void Assembler::evpbroadcastd(XMMRegister dst, Register src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
|
||||
VEX_OPCODE_0F_38, false, vector_len, false, false);
|
||||
emit_int8(0x7C);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
// duplicate 8-byte integer data from src into 4|8|16 locations in dest : requires AVX512VL
|
||||
void Assembler::evpbroadcastq(XMMRegister dst, Register src, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "");
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66,
|
||||
VEX_OPCODE_0F_38, true, vector_len, false, false);
|
||||
emit_int8(0x7C);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
// Carry-Less Multiplication Quadword
|
||||
void Assembler::pclmulqdq(XMMRegister dst, XMMRegister src, int mask) {
|
||||
assert(VM_Version::supports_clmul(), "");
|
||||
@ -5598,7 +5766,7 @@ void Assembler::evex_prefix(bool vex_r, bool vex_b, bool vex_x, bool vex_w, bool
|
||||
|
||||
void Assembler::vex_prefix(Address adr, int nds_enc, int xreg_enc, VexSimdPrefix pre,
|
||||
VexOpcode opc, bool vex_w, int vector_len, bool legacy_mode, bool no_mask_reg) {
|
||||
bool vex_r = (xreg_enc >= 8);
|
||||
bool vex_r = ((xreg_enc & 8) == 8) ? 1 : 0;
|
||||
bool vex_b = adr.base_needs_rex();
|
||||
bool vex_x = adr.index_needs_rex();
|
||||
avx_vector_len = vector_len;
|
||||
@ -5626,8 +5794,8 @@ void Assembler::vex_prefix(Address adr, int nds_enc, int xreg_enc, VexSimdPrefix
|
||||
|
||||
int Assembler::vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc,
|
||||
bool vex_w, int vector_len, bool legacy_mode, bool no_mask_reg ) {
|
||||
bool vex_r = (dst_enc >= 8);
|
||||
bool vex_b = (src_enc >= 8);
|
||||
bool vex_r = ((dst_enc & 8) == 8) ? 1 : 0;
|
||||
bool vex_b = ((src_enc & 8) == 8) ? 1 : 0;
|
||||
bool vex_x = false;
|
||||
avx_vector_len = vector_len;
|
||||
|
||||
@ -6272,19 +6440,15 @@ void Assembler::andq(Register dst, Register src) {
|
||||
|
||||
void Assembler::andnq(Register dst, Register src1, Register src2) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
int encode = vex_prefix_0F38_and_encode_q(dst, src1, src2);
|
||||
int encode = vex_prefix_0F38_and_encode_q_legacy(dst, src1, src2);
|
||||
emit_int8((unsigned char)0xF2);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::andnq(Register dst, Register src1, Address src2) {
|
||||
if (VM_Version::supports_evex()) {
|
||||
tuple_type = EVEX_T1S;
|
||||
input_size_in_bits = EVEX_64bit;
|
||||
}
|
||||
InstructionMark im(this);
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
vex_prefix_0F38_q(dst, src1, src2);
|
||||
vex_prefix_0F38_q_legacy(dst, src1, src2);
|
||||
emit_int8((unsigned char)0xF2);
|
||||
emit_operand(dst, src2);
|
||||
}
|
||||
@ -6311,7 +6475,7 @@ void Assembler::bswapq(Register reg) {
|
||||
|
||||
void Assembler::blsiq(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
int encode = vex_prefix_0F38_and_encode_q(rbx, dst, src);
|
||||
int encode = vex_prefix_0F38_and_encode_q_legacy(rbx, dst, src);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
@ -6319,14 +6483,14 @@ void Assembler::blsiq(Register dst, Register src) {
|
||||
void Assembler::blsiq(Register dst, Address src) {
|
||||
InstructionMark im(this);
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
vex_prefix_0F38_q(rbx, dst, src);
|
||||
vex_prefix_0F38_q_legacy(rbx, dst, src);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
emit_operand(rbx, src);
|
||||
}
|
||||
|
||||
void Assembler::blsmskq(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
int encode = vex_prefix_0F38_and_encode_q(rdx, dst, src);
|
||||
int encode = vex_prefix_0F38_and_encode_q_legacy(rdx, dst, src);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
@ -6334,14 +6498,14 @@ void Assembler::blsmskq(Register dst, Register src) {
|
||||
void Assembler::blsmskq(Register dst, Address src) {
|
||||
InstructionMark im(this);
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
vex_prefix_0F38_q(rdx, dst, src);
|
||||
vex_prefix_0F38_q_legacy(rdx, dst, src);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
emit_operand(rdx, src);
|
||||
}
|
||||
|
||||
void Assembler::blsrq(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
int encode = vex_prefix_0F38_and_encode_q(rcx, dst, src);
|
||||
int encode = vex_prefix_0F38_and_encode_q_legacy(rcx, dst, src);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
@ -6349,7 +6513,7 @@ void Assembler::blsrq(Register dst, Register src) {
|
||||
void Assembler::blsrq(Register dst, Address src) {
|
||||
InstructionMark im(this);
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
vex_prefix_0F38_q(rcx, dst, src);
|
||||
vex_prefix_0F38_q_legacy(rcx, dst, src);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
emit_operand(rcx, src);
|
||||
}
|
||||
|
@ -661,6 +661,14 @@ private:
|
||||
vector_len, no_mask_reg);
|
||||
}
|
||||
|
||||
void vex_prefix_0F38_legacy(Register dst, Register nds, Address src, bool no_mask_reg = false) {
|
||||
bool vex_w = false;
|
||||
int vector_len = AVX_128bit;
|
||||
vex_prefix(src, nds->encoding(), dst->encoding(),
|
||||
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w,
|
||||
vector_len, true, no_mask_reg);
|
||||
}
|
||||
|
||||
void vex_prefix_0F38_q(Register dst, Register nds, Address src, bool no_mask_reg = false) {
|
||||
bool vex_w = true;
|
||||
int vector_len = AVX_128bit;
|
||||
@ -668,6 +676,15 @@ private:
|
||||
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w,
|
||||
vector_len, no_mask_reg);
|
||||
}
|
||||
|
||||
void vex_prefix_0F38_q_legacy(Register dst, Register nds, Address src, bool no_mask_reg = false) {
|
||||
bool vex_w = true;
|
||||
int vector_len = AVX_128bit;
|
||||
vex_prefix(src, nds->encoding(), dst->encoding(),
|
||||
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w,
|
||||
vector_len, true, no_mask_reg);
|
||||
}
|
||||
|
||||
int vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc,
|
||||
VexSimdPrefix pre, VexOpcode opc,
|
||||
bool vex_w, int vector_len,
|
||||
@ -680,6 +697,15 @@ private:
|
||||
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector_len,
|
||||
false, no_mask_reg);
|
||||
}
|
||||
|
||||
int vex_prefix_0F38_and_encode_legacy(Register dst, Register nds, Register src, bool no_mask_reg = false) {
|
||||
bool vex_w = false;
|
||||
int vector_len = AVX_128bit;
|
||||
return vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(),
|
||||
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector_len,
|
||||
true, no_mask_reg);
|
||||
}
|
||||
|
||||
int vex_prefix_0F38_and_encode_q(Register dst, Register nds, Register src, bool no_mask_reg = false) {
|
||||
bool vex_w = true;
|
||||
int vector_len = AVX_128bit;
|
||||
@ -687,6 +713,15 @@ private:
|
||||
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector_len,
|
||||
false, no_mask_reg);
|
||||
}
|
||||
|
||||
int vex_prefix_0F38_and_encode_q_legacy(Register dst, Register nds, Register src, bool no_mask_reg = false) {
|
||||
bool vex_w = true;
|
||||
int vector_len = AVX_128bit;
|
||||
return vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(),
|
||||
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector_len,
|
||||
true, no_mask_reg);
|
||||
}
|
||||
|
||||
int vex_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src,
|
||||
VexSimdPrefix pre, int vector_len = AVX_128bit,
|
||||
VexOpcode opc = VEX_OPCODE_0F, bool legacy_mode = false,
|
||||
@ -1666,6 +1701,8 @@ private:
|
||||
|
||||
// Shift Right by bytes Logical DoubleQuadword Immediate
|
||||
void psrldq(XMMRegister dst, int shift);
|
||||
// Shift Left by bytes Logical DoubleQuadword Immediate
|
||||
void pslldq(XMMRegister dst, int shift);
|
||||
|
||||
// Logical Compare 128bit
|
||||
void ptest(XMMRegister dst, XMMRegister src);
|
||||
@ -2024,8 +2061,25 @@ private:
|
||||
// duplicate 4-bytes integer data from src into 8 locations in dest
|
||||
void vpbroadcastd(XMMRegister dst, XMMRegister src);
|
||||
|
||||
// duplicate 4-bytes integer data from src into vector_len locations in dest
|
||||
// duplicate n-bytes integer data from src into vector_len locations in dest
|
||||
void evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len);
|
||||
void evpbroadcastb(XMMRegister dst, Address src, int vector_len);
|
||||
void evpbroadcastw(XMMRegister dst, XMMRegister src, int vector_len);
|
||||
void evpbroadcastw(XMMRegister dst, Address src, int vector_len);
|
||||
void evpbroadcastd(XMMRegister dst, XMMRegister src, int vector_len);
|
||||
void evpbroadcastd(XMMRegister dst, Address src, int vector_len);
|
||||
void evpbroadcastq(XMMRegister dst, XMMRegister src, int vector_len);
|
||||
void evpbroadcastq(XMMRegister dst, Address src, int vector_len);
|
||||
|
||||
void evpbroadcastss(XMMRegister dst, XMMRegister src, int vector_len);
|
||||
void evpbroadcastss(XMMRegister dst, Address src, int vector_len);
|
||||
void evpbroadcastsd(XMMRegister dst, XMMRegister src, int vector_len);
|
||||
void evpbroadcastsd(XMMRegister dst, Address src, int vector_len);
|
||||
|
||||
void evpbroadcastb(XMMRegister dst, Register src, int vector_len);
|
||||
void evpbroadcastw(XMMRegister dst, Register src, int vector_len);
|
||||
void evpbroadcastd(XMMRegister dst, Register src, int vector_len);
|
||||
void evpbroadcastq(XMMRegister dst, Register src, int vector_len);
|
||||
|
||||
// Carry-Less Multiplication Quadword
|
||||
void pclmulqdq(XMMRegister dst, XMMRegister src, int mask);
|
||||
|
@ -58,4 +58,6 @@ void Compile::pd_compiler2_init() {
|
||||
OptoReg::invalidate(i);
|
||||
}
|
||||
}
|
||||
|
||||
SuperWordLoopUnrollAnalysis = true;
|
||||
}
|
||||
|
@ -524,17 +524,6 @@ frame frame::sender(RegisterMap* map) const {
|
||||
return frame(sender_sp(), link(), sender_pc());
|
||||
}
|
||||
|
||||
|
||||
bool frame::interpreter_frame_equals_unpacked_fp(intptr_t* fp) {
|
||||
assert(is_interpreted_frame(), "must be interpreter frame");
|
||||
Method* method = interpreter_frame_method();
|
||||
// When unpacking an optimized frame the frame pointer is
|
||||
// adjusted with:
|
||||
int diff = (method->max_locals() - method->size_of_parameters()) *
|
||||
Interpreter::stackElementWords;
|
||||
return _fp == (fp - diff);
|
||||
}
|
||||
|
||||
bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
|
||||
// QQQ
|
||||
#ifdef CC_INTERP
|
||||
|
@ -84,7 +84,7 @@ define_pd_global(uintx, TypeProfileLevel, 111);
|
||||
|
||||
define_pd_global(bool, PreserveFramePointer, false);
|
||||
|
||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
|
||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
||||
\
|
||||
develop(bool, IEEEPrecision, true, \
|
||||
"Enables IEEE precision (for INTEL only)") \
|
||||
|
@ -4260,31 +4260,24 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr,
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void MacroAssembler::store_check(Register obj) {
|
||||
// Does a store check for the oop in register obj. The content of
|
||||
// register obj is destroyed afterwards.
|
||||
store_check_part_1(obj);
|
||||
store_check_part_2(obj);
|
||||
}
|
||||
|
||||
void MacroAssembler::store_check(Register obj, Address dst) {
|
||||
store_check(obj);
|
||||
}
|
||||
|
||||
void MacroAssembler::store_check(Register obj) {
|
||||
// Does a store check for the oop in register obj. The content of
|
||||
// register obj is destroyed afterwards.
|
||||
|
||||
// split the store check operation so that other instructions can be scheduled inbetween
|
||||
void MacroAssembler::store_check_part_1(Register obj) {
|
||||
BarrierSet* bs = Universe::heap()->barrier_set();
|
||||
assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
|
||||
shrptr(obj, CardTableModRefBS::card_shift);
|
||||
}
|
||||
|
||||
void MacroAssembler::store_check_part_2(Register obj) {
|
||||
BarrierSet* bs = Universe::heap()->barrier_set();
|
||||
assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind");
|
||||
CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
|
||||
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
|
||||
|
||||
shrptr(obj, CardTableModRefBS::card_shift);
|
||||
|
||||
Address card_addr;
|
||||
|
||||
// The calculation for byte_map_base is as follows:
|
||||
// byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift);
|
||||
// So this essentially converts an address to a displacement and it will
|
||||
@ -4292,8 +4285,7 @@ void MacroAssembler::store_check_part_2(Register obj) {
|
||||
// large for a 32bit displacement.
|
||||
intptr_t disp = (intptr_t) ct->byte_map_base;
|
||||
if (is_simm32(disp)) {
|
||||
Address cardtable(noreg, obj, Address::times_1, disp);
|
||||
movb(cardtable, 0);
|
||||
card_addr = Address(noreg, obj, Address::times_1, disp);
|
||||
} else {
|
||||
// By doing it as an ExternalAddress 'disp' could be converted to a rip-relative
|
||||
// displacement and done in a single instruction given favorable mapping and a
|
||||
@ -4301,7 +4293,21 @@ void MacroAssembler::store_check_part_2(Register obj) {
|
||||
// entry and that entry is not properly handled by the relocation code.
|
||||
AddressLiteral cardtable((address)ct->byte_map_base, relocInfo::none);
|
||||
Address index(noreg, obj, Address::times_1);
|
||||
movb(as_Address(ArrayAddress(cardtable, index)), 0);
|
||||
card_addr = as_Address(ArrayAddress(cardtable, index));
|
||||
}
|
||||
|
||||
int dirty = CardTableModRefBS::dirty_card_val();
|
||||
if (UseCondCardMark) {
|
||||
Label L_already_dirty;
|
||||
if (UseConcMarkSweepGC) {
|
||||
membar(Assembler::StoreLoad);
|
||||
}
|
||||
cmpb(card_addr, dirty);
|
||||
jcc(Assembler::equal, L_already_dirty);
|
||||
movb(card_addr, dirty);
|
||||
bind(L_already_dirty);
|
||||
} else {
|
||||
movb(card_addr, dirty);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,10 +315,6 @@ class MacroAssembler: public Assembler {
|
||||
|
||||
#endif // INCLUDE_ALL_GCS
|
||||
|
||||
// split store_check(Register obj) to enhance instruction interleaving
|
||||
void store_check_part_1(Register obj);
|
||||
void store_check_part_2(Register obj);
|
||||
|
||||
// C 'boolean' to Java boolean: x == 0 ? 0 : 1
|
||||
void c2bool(Register x);
|
||||
|
||||
|
@ -365,22 +365,22 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
|
||||
map->set_callee_saved(STACK_OFFSET(xmm14H_off), xmm14->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm15H_off), xmm15->as_VMReg()->next());
|
||||
if (UseAVX > 2) {
|
||||
map->set_callee_saved(STACK_OFFSET(xmm16H_off), xmm16->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm17H_off), xmm17->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm18H_off), xmm18->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm19H_off), xmm19->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm20H_off), xmm20->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm21H_off), xmm21->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm22H_off), xmm22->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm23H_off), xmm23->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm24H_off), xmm24->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm25H_off), xmm25->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm26H_off), xmm26->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm27H_off), xmm27->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm28H_off), xmm28->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm29H_off), xmm29->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm30H_off), xmm30->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm31H_off), xmm31->as_VMReg());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm16H_off), xmm16->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm17H_off), xmm17->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm18H_off), xmm18->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm19H_off), xmm19->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm20H_off), xmm20->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm21H_off), xmm21->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm22H_off), xmm22->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm23H_off), xmm23->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm24H_off), xmm24->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm25H_off), xmm25->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm26H_off), xmm26->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm27H_off), xmm27->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm28H_off), xmm28->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm29H_off), xmm29->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm30H_off), xmm30->as_VMReg()->next());
|
||||
map->set_callee_saved(STACK_OFFSET(xmm31H_off), xmm31->as_VMReg()->next());
|
||||
}
|
||||
}
|
||||
|
||||
@ -466,7 +466,7 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve
|
||||
__ vinsertf64x4h(xmm29, Address(rsp, 928));
|
||||
__ vinsertf64x4h(xmm30, Address(rsp, 960));
|
||||
__ vinsertf64x4h(xmm31, Address(rsp, 992));
|
||||
__ subptr(rsp, 1024);
|
||||
__ addptr(rsp, 1024);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -2727,6 +2727,167 @@ class StubGenerator: public StubCodeGenerator {
|
||||
return start;
|
||||
}
|
||||
|
||||
// byte swap x86 long
|
||||
address generate_ghash_long_swap_mask() {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", "ghash_long_swap_mask");
|
||||
address start = __ pc();
|
||||
__ emit_data(0x0b0a0908, relocInfo::none, 0);
|
||||
__ emit_data(0x0f0e0d0c, relocInfo::none, 0);
|
||||
__ emit_data(0x03020100, relocInfo::none, 0);
|
||||
__ emit_data(0x07060504, relocInfo::none, 0);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
// byte swap x86 byte array
|
||||
address generate_ghash_byte_swap_mask() {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", "ghash_byte_swap_mask");
|
||||
address start = __ pc();
|
||||
__ emit_data(0x0c0d0e0f, relocInfo::none, 0);
|
||||
__ emit_data(0x08090a0b, relocInfo::none, 0);
|
||||
__ emit_data(0x04050607, relocInfo::none, 0);
|
||||
__ emit_data(0x00010203, relocInfo::none, 0);
|
||||
return start;
|
||||
}
|
||||
|
||||
/* Single and multi-block ghash operations */
|
||||
address generate_ghash_processBlocks() {
|
||||
assert(UseGHASHIntrinsics, "need GHASH intrinsics and CLMUL support");
|
||||
__ align(CodeEntryAlignment);
|
||||
Label L_ghash_loop, L_exit;
|
||||
StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
|
||||
address start = __ pc();
|
||||
|
||||
const Register state = rdi;
|
||||
const Register subkeyH = rsi;
|
||||
const Register data = rdx;
|
||||
const Register blocks = rcx;
|
||||
|
||||
const Address state_param(rbp, 8+0);
|
||||
const Address subkeyH_param(rbp, 8+4);
|
||||
const Address data_param(rbp, 8+8);
|
||||
const Address blocks_param(rbp, 8+12);
|
||||
|
||||
const XMMRegister xmm_temp0 = xmm0;
|
||||
const XMMRegister xmm_temp1 = xmm1;
|
||||
const XMMRegister xmm_temp2 = xmm2;
|
||||
const XMMRegister xmm_temp3 = xmm3;
|
||||
const XMMRegister xmm_temp4 = xmm4;
|
||||
const XMMRegister xmm_temp5 = xmm5;
|
||||
const XMMRegister xmm_temp6 = xmm6;
|
||||
const XMMRegister xmm_temp7 = xmm7;
|
||||
|
||||
__ enter();
|
||||
|
||||
__ movptr(state, state_param);
|
||||
__ movptr(subkeyH, subkeyH_param);
|
||||
__ movptr(data, data_param);
|
||||
__ movptr(blocks, blocks_param);
|
||||
|
||||
__ movdqu(xmm_temp0, Address(state, 0));
|
||||
__ pshufb(xmm_temp0, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr()));
|
||||
|
||||
__ movdqu(xmm_temp1, Address(subkeyH, 0));
|
||||
__ pshufb(xmm_temp1, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr()));
|
||||
|
||||
__ BIND(L_ghash_loop);
|
||||
__ movdqu(xmm_temp2, Address(data, 0));
|
||||
__ pshufb(xmm_temp2, ExternalAddress(StubRoutines::x86::ghash_byte_swap_mask_addr()));
|
||||
|
||||
__ pxor(xmm_temp0, xmm_temp2);
|
||||
|
||||
//
|
||||
// Multiply with the hash key
|
||||
//
|
||||
__ movdqu(xmm_temp3, xmm_temp0);
|
||||
__ pclmulqdq(xmm_temp3, xmm_temp1, 0); // xmm3 holds a0*b0
|
||||
__ movdqu(xmm_temp4, xmm_temp0);
|
||||
__ pclmulqdq(xmm_temp4, xmm_temp1, 16); // xmm4 holds a0*b1
|
||||
|
||||
__ movdqu(xmm_temp5, xmm_temp0);
|
||||
__ pclmulqdq(xmm_temp5, xmm_temp1, 1); // xmm5 holds a1*b0
|
||||
__ movdqu(xmm_temp6, xmm_temp0);
|
||||
__ pclmulqdq(xmm_temp6, xmm_temp1, 17); // xmm6 holds a1*b1
|
||||
|
||||
__ pxor(xmm_temp4, xmm_temp5); // xmm4 holds a0*b1 + a1*b0
|
||||
|
||||
__ movdqu(xmm_temp5, xmm_temp4); // move the contents of xmm4 to xmm5
|
||||
__ psrldq(xmm_temp4, 8); // shift by xmm4 64 bits to the right
|
||||
__ pslldq(xmm_temp5, 8); // shift by xmm5 64 bits to the left
|
||||
__ pxor(xmm_temp3, xmm_temp5);
|
||||
__ pxor(xmm_temp6, xmm_temp4); // Register pair <xmm6:xmm3> holds the result
|
||||
// of the carry-less multiplication of
|
||||
// xmm0 by xmm1.
|
||||
|
||||
// We shift the result of the multiplication by one bit position
|
||||
// to the left to cope for the fact that the bits are reversed.
|
||||
__ movdqu(xmm_temp7, xmm_temp3);
|
||||
__ movdqu(xmm_temp4, xmm_temp6);
|
||||
__ pslld (xmm_temp3, 1);
|
||||
__ pslld(xmm_temp6, 1);
|
||||
__ psrld(xmm_temp7, 31);
|
||||
__ psrld(xmm_temp4, 31);
|
||||
__ movdqu(xmm_temp5, xmm_temp7);
|
||||
__ pslldq(xmm_temp4, 4);
|
||||
__ pslldq(xmm_temp7, 4);
|
||||
__ psrldq(xmm_temp5, 12);
|
||||
__ por(xmm_temp3, xmm_temp7);
|
||||
__ por(xmm_temp6, xmm_temp4);
|
||||
__ por(xmm_temp6, xmm_temp5);
|
||||
|
||||
//
|
||||
// First phase of the reduction
|
||||
//
|
||||
// Move xmm3 into xmm4, xmm5, xmm7 in order to perform the shifts
|
||||
// independently.
|
||||
__ movdqu(xmm_temp7, xmm_temp3);
|
||||
__ movdqu(xmm_temp4, xmm_temp3);
|
||||
__ movdqu(xmm_temp5, xmm_temp3);
|
||||
__ pslld(xmm_temp7, 31); // packed right shift shifting << 31
|
||||
__ pslld(xmm_temp4, 30); // packed right shift shifting << 30
|
||||
__ pslld(xmm_temp5, 25); // packed right shift shifting << 25
|
||||
__ pxor(xmm_temp7, xmm_temp4); // xor the shifted versions
|
||||
__ pxor(xmm_temp7, xmm_temp5);
|
||||
__ movdqu(xmm_temp4, xmm_temp7);
|
||||
__ pslldq(xmm_temp7, 12);
|
||||
__ psrldq(xmm_temp4, 4);
|
||||
__ pxor(xmm_temp3, xmm_temp7); // first phase of the reduction complete
|
||||
|
||||
//
|
||||
// Second phase of the reduction
|
||||
//
|
||||
// Make 3 copies of xmm3 in xmm2, xmm5, xmm7 for doing these
|
||||
// shift operations.
|
||||
__ movdqu(xmm_temp2, xmm_temp3);
|
||||
__ movdqu(xmm_temp7, xmm_temp3);
|
||||
__ movdqu(xmm_temp5, xmm_temp3);
|
||||
__ psrld(xmm_temp2, 1); // packed left shifting >> 1
|
||||
__ psrld(xmm_temp7, 2); // packed left shifting >> 2
|
||||
__ psrld(xmm_temp5, 7); // packed left shifting >> 7
|
||||
__ pxor(xmm_temp2, xmm_temp7); // xor the shifted versions
|
||||
__ pxor(xmm_temp2, xmm_temp5);
|
||||
__ pxor(xmm_temp2, xmm_temp4);
|
||||
__ pxor(xmm_temp3, xmm_temp2);
|
||||
__ pxor(xmm_temp6, xmm_temp3); // the result is in xmm6
|
||||
|
||||
__ decrement(blocks);
|
||||
__ jcc(Assembler::zero, L_exit);
|
||||
__ movdqu(xmm_temp0, xmm_temp6);
|
||||
__ addptr(data, 16);
|
||||
__ jmp(L_ghash_loop);
|
||||
|
||||
__ BIND(L_exit);
|
||||
// Byte swap 16-byte result
|
||||
__ pshufb(xmm_temp6, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr()));
|
||||
__ movdqu(Address(state, 0), xmm_temp6); // store the result
|
||||
|
||||
__ leave();
|
||||
__ ret(0);
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments:
|
||||
*
|
||||
@ -3026,6 +3187,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt();
|
||||
}
|
||||
|
||||
// Generate GHASH intrinsics code
|
||||
if (UseGHASHIntrinsics) {
|
||||
StubRoutines::x86::_ghash_long_swap_mask_addr = generate_ghash_long_swap_mask();
|
||||
StubRoutines::x86::_ghash_byte_swap_mask_addr = generate_ghash_byte_swap_mask();
|
||||
StubRoutines::_ghash_processBlocks = generate_ghash_processBlocks();
|
||||
}
|
||||
|
||||
// Safefetch stubs.
|
||||
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
|
||||
&StubRoutines::_safefetch32_fault_pc,
|
||||
|
@ -382,7 +382,12 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
// restore regs belonging to calling function
|
||||
#ifdef _WIN64
|
||||
for (int i = 15; i >= 6; i--) {
|
||||
int xmm_ub = 15;
|
||||
if (UseAVX > 2) {
|
||||
xmm_ub = 31;
|
||||
}
|
||||
// emit the restores for xmm regs
|
||||
for (int i = 6; i <= xmm_ub; i++) {
|
||||
__ movdqu(as_XMMRegister(i), xmm_save(i));
|
||||
}
|
||||
#endif
|
||||
@ -3681,6 +3686,175 @@ class StubGenerator: public StubCodeGenerator {
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
// byte swap x86 long
|
||||
address generate_ghash_long_swap_mask() {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", "ghash_long_swap_mask");
|
||||
address start = __ pc();
|
||||
__ emit_data64(0x0f0e0d0c0b0a0908, relocInfo::none );
|
||||
__ emit_data64(0x0706050403020100, relocInfo::none );
|
||||
return start;
|
||||
}
|
||||
|
||||
// byte swap x86 byte array
|
||||
address generate_ghash_byte_swap_mask() {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", "ghash_byte_swap_mask");
|
||||
address start = __ pc();
|
||||
__ emit_data64(0x08090a0b0c0d0e0f, relocInfo::none );
|
||||
__ emit_data64(0x0001020304050607, relocInfo::none );
|
||||
return start;
|
||||
}
|
||||
|
||||
/* Single and multi-block ghash operations */
|
||||
address generate_ghash_processBlocks() {
|
||||
__ align(CodeEntryAlignment);
|
||||
Label L_ghash_loop, L_exit;
|
||||
StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
|
||||
address start = __ pc();
|
||||
|
||||
const Register state = c_rarg0;
|
||||
const Register subkeyH = c_rarg1;
|
||||
const Register data = c_rarg2;
|
||||
const Register blocks = c_rarg3;
|
||||
|
||||
#ifdef _WIN64
|
||||
const int XMM_REG_LAST = 10;
|
||||
#endif
|
||||
|
||||
const XMMRegister xmm_temp0 = xmm0;
|
||||
const XMMRegister xmm_temp1 = xmm1;
|
||||
const XMMRegister xmm_temp2 = xmm2;
|
||||
const XMMRegister xmm_temp3 = xmm3;
|
||||
const XMMRegister xmm_temp4 = xmm4;
|
||||
const XMMRegister xmm_temp5 = xmm5;
|
||||
const XMMRegister xmm_temp6 = xmm6;
|
||||
const XMMRegister xmm_temp7 = xmm7;
|
||||
const XMMRegister xmm_temp8 = xmm8;
|
||||
const XMMRegister xmm_temp9 = xmm9;
|
||||
const XMMRegister xmm_temp10 = xmm10;
|
||||
|
||||
__ enter();
|
||||
|
||||
#ifdef _WIN64
|
||||
// save the xmm registers which must be preserved 6-10
|
||||
__ subptr(rsp, -rsp_after_call_off * wordSize);
|
||||
for (int i = 6; i <= XMM_REG_LAST; i++) {
|
||||
__ movdqu(xmm_save(i), as_XMMRegister(i));
|
||||
}
|
||||
#endif
|
||||
|
||||
__ movdqu(xmm_temp10, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr()));
|
||||
|
||||
__ movdqu(xmm_temp0, Address(state, 0));
|
||||
__ pshufb(xmm_temp0, xmm_temp10);
|
||||
|
||||
|
||||
__ BIND(L_ghash_loop);
|
||||
__ movdqu(xmm_temp2, Address(data, 0));
|
||||
__ pshufb(xmm_temp2, ExternalAddress(StubRoutines::x86::ghash_byte_swap_mask_addr()));
|
||||
|
||||
__ movdqu(xmm_temp1, Address(subkeyH, 0));
|
||||
__ pshufb(xmm_temp1, xmm_temp10);
|
||||
|
||||
__ pxor(xmm_temp0, xmm_temp2);
|
||||
|
||||
//
|
||||
// Multiply with the hash key
|
||||
//
|
||||
__ movdqu(xmm_temp3, xmm_temp0);
|
||||
__ pclmulqdq(xmm_temp3, xmm_temp1, 0); // xmm3 holds a0*b0
|
||||
__ movdqu(xmm_temp4, xmm_temp0);
|
||||
__ pclmulqdq(xmm_temp4, xmm_temp1, 16); // xmm4 holds a0*b1
|
||||
|
||||
__ movdqu(xmm_temp5, xmm_temp0);
|
||||
__ pclmulqdq(xmm_temp5, xmm_temp1, 1); // xmm5 holds a1*b0
|
||||
__ movdqu(xmm_temp6, xmm_temp0);
|
||||
__ pclmulqdq(xmm_temp6, xmm_temp1, 17); // xmm6 holds a1*b1
|
||||
|
||||
__ pxor(xmm_temp4, xmm_temp5); // xmm4 holds a0*b1 + a1*b0
|
||||
|
||||
__ movdqu(xmm_temp5, xmm_temp4); // move the contents of xmm4 to xmm5
|
||||
__ psrldq(xmm_temp4, 8); // shift by xmm4 64 bits to the right
|
||||
__ pslldq(xmm_temp5, 8); // shift by xmm5 64 bits to the left
|
||||
__ pxor(xmm_temp3, xmm_temp5);
|
||||
__ pxor(xmm_temp6, xmm_temp4); // Register pair <xmm6:xmm3> holds the result
|
||||
// of the carry-less multiplication of
|
||||
// xmm0 by xmm1.
|
||||
|
||||
// We shift the result of the multiplication by one bit position
|
||||
// to the left to cope for the fact that the bits are reversed.
|
||||
__ movdqu(xmm_temp7, xmm_temp3);
|
||||
__ movdqu(xmm_temp8, xmm_temp6);
|
||||
__ pslld(xmm_temp3, 1);
|
||||
__ pslld(xmm_temp6, 1);
|
||||
__ psrld(xmm_temp7, 31);
|
||||
__ psrld(xmm_temp8, 31);
|
||||
__ movdqu(xmm_temp9, xmm_temp7);
|
||||
__ pslldq(xmm_temp8, 4);
|
||||
__ pslldq(xmm_temp7, 4);
|
||||
__ psrldq(xmm_temp9, 12);
|
||||
__ por(xmm_temp3, xmm_temp7);
|
||||
__ por(xmm_temp6, xmm_temp8);
|
||||
__ por(xmm_temp6, xmm_temp9);
|
||||
|
||||
//
|
||||
// First phase of the reduction
|
||||
//
|
||||
// Move xmm3 into xmm7, xmm8, xmm9 in order to perform the shifts
|
||||
// independently.
|
||||
__ movdqu(xmm_temp7, xmm_temp3);
|
||||
__ movdqu(xmm_temp8, xmm_temp3);
|
||||
__ movdqu(xmm_temp9, xmm_temp3);
|
||||
__ pslld(xmm_temp7, 31); // packed right shift shifting << 31
|
||||
__ pslld(xmm_temp8, 30); // packed right shift shifting << 30
|
||||
__ pslld(xmm_temp9, 25); // packed right shift shifting << 25
|
||||
__ pxor(xmm_temp7, xmm_temp8); // xor the shifted versions
|
||||
__ pxor(xmm_temp7, xmm_temp9);
|
||||
__ movdqu(xmm_temp8, xmm_temp7);
|
||||
__ pslldq(xmm_temp7, 12);
|
||||
__ psrldq(xmm_temp8, 4);
|
||||
__ pxor(xmm_temp3, xmm_temp7); // first phase of the reduction complete
|
||||
|
||||
//
|
||||
// Second phase of the reduction
|
||||
//
|
||||
// Make 3 copies of xmm3 in xmm2, xmm4, xmm5 for doing these
|
||||
// shift operations.
|
||||
__ movdqu(xmm_temp2, xmm_temp3);
|
||||
__ movdqu(xmm_temp4, xmm_temp3);
|
||||
__ movdqu(xmm_temp5, xmm_temp3);
|
||||
__ psrld(xmm_temp2, 1); // packed left shifting >> 1
|
||||
__ psrld(xmm_temp4, 2); // packed left shifting >> 2
|
||||
__ psrld(xmm_temp5, 7); // packed left shifting >> 7
|
||||
__ pxor(xmm_temp2, xmm_temp4); // xor the shifted versions
|
||||
__ pxor(xmm_temp2, xmm_temp5);
|
||||
__ pxor(xmm_temp2, xmm_temp8);
|
||||
__ pxor(xmm_temp3, xmm_temp2);
|
||||
__ pxor(xmm_temp6, xmm_temp3); // the result is in xmm6
|
||||
|
||||
__ decrement(blocks);
|
||||
__ jcc(Assembler::zero, L_exit);
|
||||
__ movdqu(xmm_temp0, xmm_temp6);
|
||||
__ addptr(data, 16);
|
||||
__ jmp(L_ghash_loop);
|
||||
|
||||
__ BIND(L_exit);
|
||||
__ pshufb(xmm_temp6, xmm_temp10); // Byte swap 16-byte result
|
||||
__ movdqu(Address(state, 0), xmm_temp6); // store the result
|
||||
|
||||
#ifdef _WIN64
|
||||
// restore xmm regs belonging to calling function
|
||||
for (int i = 6; i <= XMM_REG_LAST; i++) {
|
||||
__ movdqu(as_XMMRegister(i), xmm_save(i));
|
||||
}
|
||||
#endif
|
||||
__ leave();
|
||||
__ ret(0);
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments:
|
||||
*
|
||||
@ -4120,6 +4294,13 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel();
|
||||
}
|
||||
|
||||
// Generate GHASH intrinsics code
|
||||
if (UseGHASHIntrinsics) {
|
||||
StubRoutines::x86::_ghash_long_swap_mask_addr = generate_ghash_long_swap_mask();
|
||||
StubRoutines::x86::_ghash_byte_swap_mask_addr = generate_ghash_byte_swap_mask();
|
||||
StubRoutines::_ghash_processBlocks = generate_ghash_processBlocks();
|
||||
}
|
||||
|
||||
// Safefetch stubs.
|
||||
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
|
||||
&StubRoutines::_safefetch32_fault_pc,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2015, 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
|
||||
@ -33,6 +33,8 @@
|
||||
|
||||
address StubRoutines::x86::_verify_mxcsr_entry = NULL;
|
||||
address StubRoutines::x86::_key_shuffle_mask_addr = NULL;
|
||||
address StubRoutines::x86::_ghash_long_swap_mask_addr = NULL;
|
||||
address StubRoutines::x86::_ghash_byte_swap_mask_addr = NULL;
|
||||
|
||||
uint64_t StubRoutines::x86::_crc_by128_masks[] =
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2015, 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
|
||||
@ -36,10 +36,15 @@
|
||||
// masks and table for CRC32
|
||||
static uint64_t _crc_by128_masks[];
|
||||
static juint _crc_table[];
|
||||
// swap mask for ghash
|
||||
static address _ghash_long_swap_mask_addr;
|
||||
static address _ghash_byte_swap_mask_addr;
|
||||
|
||||
public:
|
||||
static address verify_mxcsr_entry() { return _verify_mxcsr_entry; }
|
||||
static address key_shuffle_mask_addr() { return _key_shuffle_mask_addr; }
|
||||
static address crc_by128_masks_addr() { return (address)_crc_by128_masks; }
|
||||
static address ghash_long_swap_mask_addr() { return _ghash_long_swap_mask_addr; }
|
||||
static address ghash_byte_swap_mask_addr() { return _ghash_byte_swap_mask_addr; }
|
||||
|
||||
#endif // CPU_X86_VM_STUBROUTINES_X86_32_HPP
|
||||
|
@ -33,7 +33,7 @@ static bool returns_to_call_stub(address return_pc) { return return_pc == _
|
||||
|
||||
enum platform_dependent_constants {
|
||||
code_size1 = 19000, // simply increase if too small (assembler will crash if too small)
|
||||
code_size2 = 23000 // simply increase if too small (assembler will crash if too small)
|
||||
code_size2 = 24000 // simply increase if too small (assembler will crash if too small)
|
||||
};
|
||||
|
||||
class x86 {
|
||||
|
@ -677,6 +677,17 @@ void VM_Version::get_processor_features() {
|
||||
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
|
||||
}
|
||||
|
||||
// GHASH/GCM intrinsics
|
||||
if (UseCLMUL && (UseSSE > 2)) {
|
||||
if (FLAG_IS_DEFAULT(UseGHASHIntrinsics)) {
|
||||
UseGHASHIntrinsics = true;
|
||||
}
|
||||
} else if (UseGHASHIntrinsics) {
|
||||
if (!FLAG_IS_DEFAULT(UseGHASHIntrinsics))
|
||||
warning("GHASH intrinsic requires CLMUL and SSE2 instructions on this CPU");
|
||||
FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
|
||||
}
|
||||
|
||||
if (UseSHA) {
|
||||
warning("SHA instructions are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
|
@ -702,6 +702,7 @@ public:
|
||||
static bool supports_avx512cd() { return (_cpuFeatures & CPU_AVX512CD) != 0; }
|
||||
static bool supports_avx512bw() { return (_cpuFeatures & CPU_AVX512BW) != 0; }
|
||||
static bool supports_avx512vl() { return (_cpuFeatures & CPU_AVX512VL) != 0; }
|
||||
static bool supports_avx512vlbw() { return (supports_avx512bw() && supports_avx512vl()); }
|
||||
// Intel features
|
||||
static bool is_intel_family_core() { return is_intel() &&
|
||||
extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -63,7 +63,8 @@ define_pd_global(uintx, TypeProfileLevel, 0);
|
||||
|
||||
define_pd_global(bool, PreserveFramePointer, false);
|
||||
|
||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
|
||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
||||
\
|
||||
product(bool, UseFastEmptyMethods, true, \
|
||||
"Use fast method entry code for empty methods") \
|
||||
\
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2013 SAP AG. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -38,8 +38,8 @@ class AIXDecoder: public AbstractDecoder {
|
||||
|
||||
virtual bool demangle(const char* symbol, char* buf, int buflen) { return false; } // demangled by getFuncName
|
||||
|
||||
virtual bool decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) {
|
||||
return (::getFuncName((codeptr_t)addr, buf, buflen, offset, 0, 0, 0) == 0);
|
||||
virtual bool decode(address addr, char* buf, int buflen, int* offset, const char* modulepath, bool demangle) {
|
||||
return (::getFuncName((codeptr_t)addr, buf, buflen, offset, 0, 0, 0, demangle) == 0);
|
||||
}
|
||||
virtual bool decode(address addr, char *buf, int buflen, int* offset, const void *base) {
|
||||
ShouldNotReachHere();
|
||||
|
@ -29,7 +29,7 @@
|
||||
//
|
||||
// Defines Aix specific flags. They are not available on other platforms.
|
||||
//
|
||||
#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
|
||||
#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
|
||||
\
|
||||
/* Use 64K pages for virtual memory (shmat). */ \
|
||||
product(bool, Use64KPages, true, \
|
||||
|
@ -1439,7 +1439,8 @@ static address resolve_function_descriptor_to_code_pointer(address p) {
|
||||
}
|
||||
|
||||
bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
int buflen, int *offset) {
|
||||
int buflen, int *offset,
|
||||
bool demangle) {
|
||||
if (offset) {
|
||||
*offset = -1;
|
||||
}
|
||||
@ -1454,7 +1455,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
}
|
||||
|
||||
// Go through Decoder::decode to call getFuncName which reads the name from the traceback table.
|
||||
return Decoder::decode(addr, buf, buflen, offset);
|
||||
return Decoder::decode(addr, buf, buflen, offset, demangle);
|
||||
}
|
||||
|
||||
static int getModuleName(codeptr_t pc, // [in] program counter
|
||||
@ -1653,7 +1654,7 @@ void os::print_memory_info(outputStream* st) {
|
||||
}
|
||||
}
|
||||
|
||||
void os::pd_print_cpu_info(outputStream* st) {
|
||||
void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
|
||||
// cpu
|
||||
st->print("CPU:");
|
||||
st->print("total %d", os::processor_count());
|
||||
@ -3761,10 +3762,6 @@ ExtendedPC os::get_thread_pc(Thread* thread) {
|
||||
return fetcher.result();
|
||||
}
|
||||
|
||||
// Not neede on Aix.
|
||||
// int os::Aix::safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime) {
|
||||
// }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// debug support
|
||||
|
||||
|
@ -114,7 +114,8 @@ extern "C" int getFuncName(
|
||||
int* p_displacement, // [out] optional: displacement (-1 if not available)
|
||||
const struct tbtable** p_tb, // [out] optional: ptr to traceback table to get further
|
||||
// information (NULL if not available)
|
||||
char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages
|
||||
char* p_errmsg, size_t errmsglen,// [out] optional: user provided buffer for error messages
|
||||
bool demangle // [in] whether to demangle the name
|
||||
) {
|
||||
struct tbtable* tb = 0;
|
||||
unsigned int searchcount = 0;
|
||||
@ -216,15 +217,17 @@ extern "C" int getFuncName(
|
||||
p_name[0] = '\0';
|
||||
|
||||
// If it is a C++ name, try and demangle it using the Demangle interface (see demangle.h).
|
||||
char* rest;
|
||||
Name* const name = Demangle(buf, rest);
|
||||
if (name) {
|
||||
const char* const demangled_name = name->Text();
|
||||
if (demangled_name) {
|
||||
strncpy(p_name, demangled_name, namelen-1);
|
||||
p_name[namelen-1] = '\0';
|
||||
if (demangle) {
|
||||
char* rest;
|
||||
Name* const name = Demangle(buf, rest);
|
||||
if (name) {
|
||||
const char* const demangled_name = name->Text();
|
||||
if (demangled_name) {
|
||||
strncpy(p_name, demangled_name, namelen-1);
|
||||
p_name[namelen-1] = '\0';
|
||||
}
|
||||
delete name;
|
||||
}
|
||||
delete name;
|
||||
}
|
||||
|
||||
// Fallback: if demangling did not work, just provide the unmangled name.
|
||||
@ -325,7 +328,7 @@ int dladdr(void* addr, Dl_info* info) {
|
||||
int displacement = 0;
|
||||
|
||||
if (getFuncName((codeptr_t) p, funcname, sizeof(funcname), &displacement,
|
||||
NULL, NULL, 0) == 0) {
|
||||
NULL, NULL, 0, true /* demangle */) == 0) {
|
||||
if (funcname[0] != '\0') {
|
||||
const char* const interned = dladdr_fixed_strings.intern(funcname);
|
||||
info->dli_sname = interned;
|
||||
|
@ -87,7 +87,8 @@ int getFuncName(
|
||||
char* p_name, size_t namelen, // [out] optional: user provided buffer for the function name
|
||||
int* p_displacement, // [out] optional: displacement
|
||||
const struct tbtable** p_tb, // [out] optional: ptr to traceback table to get further information
|
||||
char* p_errmsg, size_t errmsglen // [out] optional: user provided buffer for error messages
|
||||
char* p_errmsg, size_t errmsglen,// [out] optional: user provided buffer for error messages
|
||||
bool demangle = true // [in] whether to demangle the name
|
||||
);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2015, 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
|
||||
@ -42,7 +42,7 @@ class MachODecoder : public AbstractDecoder {
|
||||
virtual bool decode(address pc, char* buf, int buflen, int* offset,
|
||||
const void* base);
|
||||
virtual bool decode(address pc, char* buf, int buflen, int* offset,
|
||||
const char* module_path = NULL) {
|
||||
const char* module_path, bool demangle) {
|
||||
ShouldNotReachHere();
|
||||
return false;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2015, 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
|
||||
@ -28,19 +28,20 @@
|
||||
//
|
||||
// Defines Bsd specific flags. They are not available on other platforms.
|
||||
//
|
||||
#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
|
||||
product(bool, UseOprofile, false, \
|
||||
"enable support for Oprofile profiler") \
|
||||
\
|
||||
product(bool, UseBsdPosixThreadCPUClocks, true, \
|
||||
"enable fast Bsd Posix clocks where available") \
|
||||
/* NB: The default value of UseBsdPosixThreadCPUClocks may be \
|
||||
overridden in Arguments::parse_each_vm_init_arg. */ \
|
||||
\
|
||||
product(bool, UseHugeTLBFS, false, \
|
||||
"Use MAP_HUGETLB for large pages") \
|
||||
\
|
||||
product(bool, UseSHM, false, \
|
||||
#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
|
||||
\
|
||||
product(bool, UseOprofile, false, \
|
||||
"enable support for Oprofile profiler") \
|
||||
\
|
||||
/* NB: The default value of UseBsdPosixThreadCPUClocks may be */ \
|
||||
/* overridden in Arguments::parse_each_vm_init_arg. */ \
|
||||
product(bool, UseBsdPosixThreadCPUClocks, true, \
|
||||
"enable fast Bsd Posix clocks where available") \
|
||||
\
|
||||
product(bool, UseHugeTLBFS, false, \
|
||||
"Use MAP_HUGETLB for large pages") \
|
||||
\
|
||||
product(bool, UseSHM, false, \
|
||||
"Use SYSV shared memory for large pages")
|
||||
|
||||
//
|
||||
|
@ -637,11 +637,6 @@ void os::Bsd::hotspot_sigmask(Thread* thread) {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// create new thread
|
||||
|
||||
// check if it's safe to start a new thread
|
||||
static bool _thread_safety_check(Thread* thread) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
// library handle for calling objc_registerThreadWithCollector()
|
||||
// without static linking to the libobjc library
|
||||
@ -681,15 +676,6 @@ static void *java_start(Thread *thread) {
|
||||
OSThread* osthread = thread->osthread();
|
||||
Monitor* sync = osthread->startThread_lock();
|
||||
|
||||
// non floating stack BsdThreads needs extra check, see above
|
||||
if (!_thread_safety_check(thread)) {
|
||||
// notify parent thread
|
||||
MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
|
||||
osthread->set_state(ZOMBIE);
|
||||
sync->notify_all();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
osthread->set_thread_id(os::Bsd::gettid());
|
||||
|
||||
#ifdef __APPLE__
|
||||
@ -1339,7 +1325,8 @@ bool os::address_is_in_vm(address addr) {
|
||||
#define MACH_MAXSYMLEN 256
|
||||
|
||||
bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
int buflen, int *offset) {
|
||||
int buflen, int *offset,
|
||||
bool demangle) {
|
||||
// buf is not optional, but offset is optional
|
||||
assert(buf != NULL, "sanity check");
|
||||
|
||||
@ -1349,7 +1336,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
if (dladdr((void*)addr, &dlinfo) != 0) {
|
||||
// see if we have a matching symbol
|
||||
if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
|
||||
if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
|
||||
if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
|
||||
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
|
||||
}
|
||||
if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
|
||||
@ -1358,15 +1345,16 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
// no matching symbol so try for just file info
|
||||
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
|
||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||
buf, buflen, offset, dlinfo.dli_fname)) {
|
||||
buf, buflen, offset, dlinfo.dli_fname, demangle)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle non-dynamic manually:
|
||||
if (dlinfo.dli_fbase != NULL &&
|
||||
Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset, dlinfo.dli_fbase)) {
|
||||
if (!Decoder::demangle(localbuf, buf, buflen)) {
|
||||
Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset,
|
||||
dlinfo.dli_fbase)) {
|
||||
if (!(demangle && Decoder::demangle(localbuf, buf, buflen))) {
|
||||
jio_snprintf(buf, buflen, "%s", localbuf);
|
||||
}
|
||||
return true;
|
||||
@ -1706,7 +1694,7 @@ void os::print_os_info(outputStream* st) {
|
||||
os::Posix::print_load_average(st);
|
||||
}
|
||||
|
||||
void os::pd_print_cpu_info(outputStream* st) {
|
||||
void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
|
||||
// Nothing to do for now.
|
||||
}
|
||||
|
||||
@ -2276,8 +2264,6 @@ bool os::remove_stack_guard_pages(char* addr, size_t size) {
|
||||
return os::uncommit_memory(addr, size);
|
||||
}
|
||||
|
||||
static address _highest_vm_reserved_address = NULL;
|
||||
|
||||
// If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory
|
||||
// at 'requested_addr'. If there are existing memory mappings at the same
|
||||
// location, however, they will be overwritten. If 'fixed' is false,
|
||||
@ -2300,23 +2286,9 @@ static char* anon_mmap(char* requested_addr, size_t bytes, bool fixed) {
|
||||
addr = (char*)::mmap(requested_addr, bytes, PROT_NONE,
|
||||
flags, -1, 0);
|
||||
|
||||
if (addr != MAP_FAILED) {
|
||||
// anon_mmap() should only get called during VM initialization,
|
||||
// don't need lock (actually we can skip locking even it can be called
|
||||
// from multiple threads, because _highest_vm_reserved_address is just a
|
||||
// hint about the upper limit of non-stack memory regions.)
|
||||
if ((address)addr + bytes > _highest_vm_reserved_address) {
|
||||
_highest_vm_reserved_address = (address)addr + bytes;
|
||||
}
|
||||
}
|
||||
|
||||
return addr == MAP_FAILED ? NULL : addr;
|
||||
}
|
||||
|
||||
// Don't update _highest_vm_reserved_address, because there might be memory
|
||||
// regions above addr + size. If so, releasing a memory region only creates
|
||||
// a hole in the address space, it doesn't help prevent heap-stack collision.
|
||||
//
|
||||
static int anon_munmap(char * addr, size_t size) {
|
||||
return ::munmap(addr, size) == 0;
|
||||
}
|
||||
@ -2490,15 +2462,7 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
|
||||
assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
|
||||
|
||||
// Repeatedly allocate blocks until the block is allocated at the
|
||||
// right spot. Give up after max_tries. Note that reserve_memory() will
|
||||
// automatically update _highest_vm_reserved_address if the call is
|
||||
// successful. The variable tracks the highest memory address every reserved
|
||||
// by JVM. It is used to detect heap-stack collision if running with
|
||||
// fixed-stack BsdThreads. Because here we may attempt to reserve more
|
||||
// space than needed, it could confuse the collision detecting code. To
|
||||
// solve the problem, save current _highest_vm_reserved_address and
|
||||
// calculate the correct value before return.
|
||||
address old_highest = _highest_vm_reserved_address;
|
||||
// right spot.
|
||||
|
||||
// Bsd mmap allows caller to pass an address as hint; give it a try first,
|
||||
// if kernel honors the hint then we can return immediately.
|
||||
@ -2552,10 +2516,8 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
|
||||
}
|
||||
|
||||
if (i < max_tries) {
|
||||
_highest_vm_reserved_address = MAX2(old_highest, (address)requested_addr + bytes);
|
||||
return requested_addr;
|
||||
} else {
|
||||
_highest_vm_reserved_address = old_highest;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -3715,12 +3677,6 @@ ExtendedPC os::get_thread_pc(Thread* thread) {
|
||||
return fetcher.result();
|
||||
}
|
||||
|
||||
int os::Bsd::safe_cond_timedwait(pthread_cond_t *_cond,
|
||||
pthread_mutex_t *_mutex,
|
||||
const struct timespec *_abstime) {
|
||||
return pthread_cond_timedwait(_cond, _mutex, _abstime);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// debug support
|
||||
|
||||
@ -4286,7 +4242,7 @@ int os::PlatformEvent::park(jlong millis) {
|
||||
// In that case, we should propagate the notify to another waiter.
|
||||
|
||||
while (_Event < 0) {
|
||||
status = os::Bsd::safe_cond_timedwait(_cond, _mutex, &abst);
|
||||
status = pthread_cond_timedwait(_cond, _mutex, &abst);
|
||||
if (status != 0 && WorkAroundNPTLTimedWaitHang) {
|
||||
pthread_cond_destroy(_cond);
|
||||
pthread_cond_init(_cond, NULL);
|
||||
@ -4492,7 +4448,7 @@ void Parker::park(bool isAbsolute, jlong time) {
|
||||
if (time == 0) {
|
||||
status = pthread_cond_wait(_cond, _mutex);
|
||||
} else {
|
||||
status = os::Bsd::safe_cond_timedwait(_cond, _mutex, &absTime);
|
||||
status = pthread_cond_timedwait(_cond, _mutex, &absTime);
|
||||
if (status != 0 && WorkAroundNPTLTimedWaitHang) {
|
||||
pthread_cond_destroy(_cond);
|
||||
pthread_cond_init(_cond, NULL);
|
||||
|
@ -30,9 +30,6 @@
|
||||
// Information about the protection of the page at address '0' on this os.
|
||||
static bool zero_page_read_protected() { return true; }
|
||||
|
||||
// pthread_getattr_np comes with BsdThreads-0.9-7 on RedHat 7.1
|
||||
typedef int (*pthread_getattr_func_type)(pthread_t, pthread_attr_t *);
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Mac OS X doesn't support clock_gettime. Stub out the type, it is
|
||||
// unused
|
||||
@ -145,9 +142,6 @@ class Bsd {
|
||||
|
||||
// none present
|
||||
|
||||
// BsdThreads work-around for 6292965
|
||||
static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime);
|
||||
|
||||
private:
|
||||
typedef int (*sched_getcpu_func_t)(void);
|
||||
typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2015, 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
|
||||
@ -28,14 +28,15 @@
|
||||
//
|
||||
// Defines Linux specific flags. They are not available on other platforms.
|
||||
//
|
||||
#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
|
||||
#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
|
||||
\
|
||||
product(bool, UseOprofile, false, \
|
||||
"enable support for Oprofile profiler") \
|
||||
\
|
||||
/* NB: The default value of UseLinuxPosixThreadCPUClocks may be */ \
|
||||
/* overridden in Arguments::parse_each_vm_init_arg. */ \
|
||||
product(bool, UseLinuxPosixThreadCPUClocks, true, \
|
||||
"enable fast Linux Posix clocks where available") \
|
||||
/* NB: The default value of UseLinuxPosixThreadCPUClocks may be \
|
||||
overridden in Arguments::parse_each_vm_init_arg. */ \
|
||||
\
|
||||
product(bool, UseHugeTLBFS, false, \
|
||||
"Use MAP_HUGETLB for large pages") \
|
||||
|
@ -135,8 +135,6 @@ Mutex* os::Linux::_createThread_lock = NULL;
|
||||
pthread_t os::Linux::_main_thread;
|
||||
int os::Linux::_page_size = -1;
|
||||
const int os::Linux::_vm_default_page_size = (8 * K);
|
||||
bool os::Linux::_is_floating_stack = false;
|
||||
bool os::Linux::_is_NPTL = false;
|
||||
bool os::Linux::_supports_fast_thread_cpu_time = false;
|
||||
const char * os::Linux::_glibc_version = NULL;
|
||||
const char * os::Linux::_libpthread_version = NULL;
|
||||
@ -150,8 +148,6 @@ static int clock_tics_per_sec = 100;
|
||||
static sigset_t check_signal_done;
|
||||
static bool check_signals = true;
|
||||
|
||||
static pid_t _initial_pid = 0;
|
||||
|
||||
// Signal number used to suspend/resume a thread
|
||||
|
||||
// do not use any signal number less than SIGSEGV, see 4355769
|
||||
@ -223,18 +219,10 @@ static char cpu_arch[] = HOTSPOT_LIB_ARCH;
|
||||
//
|
||||
// Returns the kernel thread id of the currently running thread. Kernel
|
||||
// thread id is used to access /proc.
|
||||
//
|
||||
// (Note that getpid() on LinuxThreads returns kernel thread id too; but
|
||||
// on NPTL, it returns the same pid for all threads, as required by POSIX.)
|
||||
//
|
||||
pid_t os::Linux::gettid() {
|
||||
int rslt = syscall(SYS_gettid);
|
||||
if (rslt == -1) {
|
||||
// old kernel, no NPTL support
|
||||
return getpid();
|
||||
} else {
|
||||
return (pid_t)rslt;
|
||||
}
|
||||
assert(rslt != -1, "must be."); // old linuxthreads implementation?
|
||||
return (pid_t)rslt;
|
||||
}
|
||||
|
||||
// Most versions of linux have a bug where the number of processors are
|
||||
@ -508,68 +496,48 @@ void os::Linux::hotspot_sigmask(Thread* thread) {
|
||||
// detecting pthread library
|
||||
|
||||
void os::Linux::libpthread_init() {
|
||||
// Save glibc and pthread version strings. Note that _CS_GNU_LIBC_VERSION
|
||||
// and _CS_GNU_LIBPTHREAD_VERSION are supported in glibc >= 2.3.2. Use a
|
||||
// generic name for earlier versions.
|
||||
// Define macros here so we can build HotSpot on old systems.
|
||||
#ifndef _CS_GNU_LIBC_VERSION
|
||||
#define _CS_GNU_LIBC_VERSION 2
|
||||
#endif
|
||||
#ifndef _CS_GNU_LIBPTHREAD_VERSION
|
||||
#define _CS_GNU_LIBPTHREAD_VERSION 3
|
||||
// Save glibc and pthread version strings.
|
||||
#if !defined(_CS_GNU_LIBC_VERSION) || \
|
||||
!defined(_CS_GNU_LIBPTHREAD_VERSION)
|
||||
#error "glibc too old (< 2.3.2)"
|
||||
#endif
|
||||
|
||||
size_t n = confstr(_CS_GNU_LIBC_VERSION, NULL, 0);
|
||||
if (n > 0) {
|
||||
char *str = (char *)malloc(n, mtInternal);
|
||||
confstr(_CS_GNU_LIBC_VERSION, str, n);
|
||||
os::Linux::set_glibc_version(str);
|
||||
} else {
|
||||
// _CS_GNU_LIBC_VERSION is not supported, try gnu_get_libc_version()
|
||||
static char _gnu_libc_version[32];
|
||||
jio_snprintf(_gnu_libc_version, sizeof(_gnu_libc_version),
|
||||
"glibc %s %s", gnu_get_libc_version(), gnu_get_libc_release());
|
||||
os::Linux::set_glibc_version(_gnu_libc_version);
|
||||
}
|
||||
assert(n > 0, "cannot retrieve glibc version");
|
||||
char *str = (char *)malloc(n, mtInternal);
|
||||
confstr(_CS_GNU_LIBC_VERSION, str, n);
|
||||
os::Linux::set_glibc_version(str);
|
||||
|
||||
n = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, 0);
|
||||
if (n > 0) {
|
||||
char *str = (char *)malloc(n, mtInternal);
|
||||
confstr(_CS_GNU_LIBPTHREAD_VERSION, str, n);
|
||||
// Vanilla RH-9 (glibc 2.3.2) has a bug that confstr() always tells
|
||||
// us "NPTL-0.29" even we are running with LinuxThreads. Check if this
|
||||
// is the case. LinuxThreads has a hard limit on max number of threads.
|
||||
// So sysconf(_SC_THREAD_THREADS_MAX) will return a positive value.
|
||||
// On the other hand, NPTL does not have such a limit, sysconf()
|
||||
// will return -1 and errno is not changed. Check if it is really NPTL.
|
||||
if (strcmp(os::Linux::glibc_version(), "glibc 2.3.2") == 0 &&
|
||||
strstr(str, "NPTL") &&
|
||||
sysconf(_SC_THREAD_THREADS_MAX) > 0) {
|
||||
free(str);
|
||||
os::Linux::set_libpthread_version("linuxthreads");
|
||||
} else {
|
||||
os::Linux::set_libpthread_version(str);
|
||||
}
|
||||
} else {
|
||||
// glibc before 2.3.2 only has LinuxThreads.
|
||||
os::Linux::set_libpthread_version("linuxthreads");
|
||||
}
|
||||
|
||||
if (strstr(libpthread_version(), "NPTL")) {
|
||||
os::Linux::set_is_NPTL();
|
||||
} else {
|
||||
os::Linux::set_is_LinuxThreads();
|
||||
}
|
||||
|
||||
// LinuxThreads have two flavors: floating-stack mode, which allows variable
|
||||
// stack size; and fixed-stack mode. NPTL is always floating-stack.
|
||||
if (os::Linux::is_NPTL() || os::Linux::supports_variable_stack_size()) {
|
||||
os::Linux::set_is_floating_stack();
|
||||
}
|
||||
assert(n > 0, "cannot retrieve pthread version");
|
||||
str = (char *)malloc(n, mtInternal);
|
||||
confstr(_CS_GNU_LIBPTHREAD_VERSION, str, n);
|
||||
os::Linux::set_libpthread_version(str);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// thread stack
|
||||
// thread stack expansion
|
||||
|
||||
// os::Linux::manually_expand_stack() takes care of expanding the thread
|
||||
// stack. Note that this is normally not needed: pthread stacks allocate
|
||||
// thread stack using mmap() without MAP_NORESERVE, so the stack is already
|
||||
// committed. Therefore it is not necessary to expand the stack manually.
|
||||
//
|
||||
// Manually expanding the stack was historically needed on LinuxThreads
|
||||
// thread stacks, which were allocated with mmap(MAP_GROWSDOWN). Nowadays
|
||||
// it is kept to deal with very rare corner cases:
|
||||
//
|
||||
// For one, user may run the VM on an own implementation of threads
|
||||
// whose stacks are - like the old LinuxThreads - implemented using
|
||||
// mmap(MAP_GROWSDOWN).
|
||||
//
|
||||
// Also, this coding may be needed if the VM is running on the primordial
|
||||
// thread. Normally we avoid running on the primordial thread; however,
|
||||
// user may still invoke the VM on the primordial thread.
|
||||
//
|
||||
// The following historical comment describes the details about running
|
||||
// on a thread stack allocated with mmap(MAP_GROWSDOWN):
|
||||
|
||||
|
||||
// Force Linux kernel to expand current thread stack. If "bottom" is close
|
||||
// to the stack guard, caller should block all signals.
|
||||
@ -593,10 +561,7 @@ void os::Linux::libpthread_init() {
|
||||
// stack overflow detection.
|
||||
//
|
||||
// Newer version of LinuxThreads (since glibc-2.2, or, RH-7.x) and NPTL do
|
||||
// not use this flag. However, the stack of initial thread is not created
|
||||
// by pthread, it is still MAP_GROWSDOWN. Also it's possible (though
|
||||
// unlikely) that user code can create a thread with MAP_GROWSDOWN stack
|
||||
// and then attach the thread to JVM.
|
||||
// not use MAP_GROWSDOWN.
|
||||
//
|
||||
// To get around the problem and allow stack banging on Linux, we need to
|
||||
// manually expand thread stack after receiving the SIGSEGV.
|
||||
@ -671,45 +636,6 @@ bool os::Linux::manually_expand_stack(JavaThread * t, address addr) {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// create new thread
|
||||
|
||||
static address highest_vm_reserved_address();
|
||||
|
||||
// check if it's safe to start a new thread
|
||||
static bool _thread_safety_check(Thread* thread) {
|
||||
if (os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack()) {
|
||||
// Fixed stack LinuxThreads (SuSE Linux/x86, and some versions of Redhat)
|
||||
// Heap is mmap'ed at lower end of memory space. Thread stacks are
|
||||
// allocated (MAP_FIXED) from high address space. Every thread stack
|
||||
// occupies a fixed size slot (usually 2Mbytes, but user can change
|
||||
// it to other values if they rebuild LinuxThreads).
|
||||
//
|
||||
// Problem with MAP_FIXED is that mmap() can still succeed even part of
|
||||
// the memory region has already been mmap'ed. That means if we have too
|
||||
// many threads and/or very large heap, eventually thread stack will
|
||||
// collide with heap.
|
||||
//
|
||||
// Here we try to prevent heap/stack collision by comparing current
|
||||
// stack bottom with the highest address that has been mmap'ed by JVM
|
||||
// plus a safety margin for memory maps created by native code.
|
||||
//
|
||||
// This feature can be disabled by setting ThreadSafetyMargin to 0
|
||||
//
|
||||
if (ThreadSafetyMargin > 0) {
|
||||
address stack_bottom = os::current_stack_base() - os::current_stack_size();
|
||||
|
||||
// not safe if our stack extends below the safety margin
|
||||
return stack_bottom - ThreadSafetyMargin >= highest_vm_reserved_address();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Floating stack LinuxThreads or NPTL:
|
||||
// Unlike fixed stack LinuxThreads, thread stacks are not MAP_FIXED. When
|
||||
// there's not enough space left, pthread_create() will fail. If we come
|
||||
// here, that means enough space has been reserved for stack.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Thread start routine for all newly created threads
|
||||
static void *java_start(Thread *thread) {
|
||||
// Try to randomize the cache line index of hot stack frames.
|
||||
@ -726,15 +652,6 @@ static void *java_start(Thread *thread) {
|
||||
OSThread* osthread = thread->osthread();
|
||||
Monitor* sync = osthread->startThread_lock();
|
||||
|
||||
// non floating stack LinuxThreads needs extra check, see above
|
||||
if (!_thread_safety_check(thread)) {
|
||||
// notify parent thread
|
||||
MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
|
||||
osthread->set_state(ZOMBIE);
|
||||
sync->notify_all();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// thread_id is kernel thread id (similar to Solaris LWP id)
|
||||
osthread->set_thread_id(os::Linux::gettid());
|
||||
|
||||
@ -833,12 +750,6 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
|
||||
ThreadState state;
|
||||
|
||||
{
|
||||
// Serialize thread creation if we are running with fixed stack LinuxThreads
|
||||
bool lock = os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack();
|
||||
if (lock) {
|
||||
os::Linux::createThread_lock()->lock_without_safepoint_check();
|
||||
}
|
||||
|
||||
pthread_t tid;
|
||||
int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);
|
||||
|
||||
@ -851,7 +762,6 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
|
||||
// Need to clean up stuff we've allocated so far
|
||||
thread->set_osthread(NULL);
|
||||
delete osthread;
|
||||
if (lock) os::Linux::createThread_lock()->unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -866,10 +776,6 @@ bool os::create_thread(Thread* thread, ThreadType thr_type,
|
||||
sync_with_child->wait(Mutex::_no_safepoint_check_flag);
|
||||
}
|
||||
}
|
||||
|
||||
if (lock) {
|
||||
os::Linux::createThread_lock()->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Aborted due to thread limit being reached
|
||||
@ -1497,7 +1403,6 @@ void os::abort(bool dump_core, void* siginfo, void* context) {
|
||||
|
||||
// Die immediately, no exit hook, no abort hook, no cleanup.
|
||||
void os::die() {
|
||||
// _exit() on LinuxThreads only kills current thread
|
||||
::abort();
|
||||
}
|
||||
|
||||
@ -1520,24 +1425,7 @@ size_t os::lasterror(char *buf, size_t len) {
|
||||
|
||||
intx os::current_thread_id() { return (intx)pthread_self(); }
|
||||
int os::current_process_id() {
|
||||
|
||||
// Under the old linux thread library, linux gives each thread
|
||||
// its own process id. Because of this each thread will return
|
||||
// a different pid if this method were to return the result
|
||||
// of getpid(2). Linux provides no api that returns the pid
|
||||
// of the launcher thread for the vm. This implementation
|
||||
// returns a unique pid, the pid of the launcher thread
|
||||
// that starts the vm 'process'.
|
||||
|
||||
// Under the NPTL, getpid() returns the same pid as the
|
||||
// launcher thread rather than a unique pid per thread.
|
||||
// Use gettid() if you want the old pre NPTL behaviour.
|
||||
|
||||
// if you are looking for the result of a call to getpid() that
|
||||
// returns a unique pid for the calling thread, then look at the
|
||||
// OSThread::thread_id() method in osThread_linux.hpp file
|
||||
|
||||
return (int)(_initial_pid ? _initial_pid : getpid());
|
||||
return ::getpid();
|
||||
}
|
||||
|
||||
// DLL functions
|
||||
@ -1623,7 +1511,8 @@ bool os::address_is_in_vm(address addr) {
|
||||
}
|
||||
|
||||
bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
int buflen, int *offset) {
|
||||
int buflen, int *offset,
|
||||
bool demangle) {
|
||||
// buf is not optional, but offset is optional
|
||||
assert(buf != NULL, "sanity check");
|
||||
|
||||
@ -1632,7 +1521,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
if (dladdr((void*)addr, &dlinfo) != 0) {
|
||||
// see if we have a matching symbol
|
||||
if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
|
||||
if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
|
||||
if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
|
||||
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
|
||||
}
|
||||
if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
|
||||
@ -1641,7 +1530,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
// no matching symbol so try for just file info
|
||||
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
|
||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||
buf, buflen, offset, dlinfo.dli_fname)) {
|
||||
buf, buflen, offset, dlinfo.dli_fname, demangle)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -2183,9 +2072,6 @@ void os::Linux::print_libversion_info(outputStream* st) {
|
||||
st->print("libc:");
|
||||
st->print("%s ", os::Linux::glibc_version());
|
||||
st->print("%s ", os::Linux::libpthread_version());
|
||||
if (os::Linux::is_LinuxThreads()) {
|
||||
st->print("(%s stack)", os::Linux::is_floating_stack() ? "floating" : "fixed");
|
||||
}
|
||||
st->cr();
|
||||
}
|
||||
|
||||
@ -2215,12 +2101,52 @@ void os::print_memory_info(outputStream* st) {
|
||||
st->cr();
|
||||
}
|
||||
|
||||
void os::pd_print_cpu_info(outputStream* st) {
|
||||
st->print("\n/proc/cpuinfo:\n");
|
||||
if (!_print_ascii_file("/proc/cpuinfo", st)) {
|
||||
st->print(" <Not Available>");
|
||||
// Print the first "model name" line and the first "flags" line
|
||||
// that we find and nothing more. We assume "model name" comes
|
||||
// before "flags" so if we find a second "model name", then the
|
||||
// "flags" field is considered missing.
|
||||
static bool print_model_name_and_flags(outputStream* st, char* buf, size_t buflen) {
|
||||
#if defined(IA32) || defined(AMD64)
|
||||
// Other platforms have less repetitive cpuinfo files
|
||||
FILE *fp = fopen("/proc/cpuinfo", "r");
|
||||
if (fp) {
|
||||
while (!feof(fp)) {
|
||||
if (fgets(buf, buflen, fp)) {
|
||||
// Assume model name comes before flags
|
||||
bool model_name_printed = false;
|
||||
if (strstr(buf, "model name") != NULL) {
|
||||
if (!model_name_printed) {
|
||||
st->print_raw("\nCPU Model and flags from /proc/cpuinfo:\n");
|
||||
st->print_raw(buf);
|
||||
model_name_printed = true;
|
||||
} else {
|
||||
// model name printed but not flags? Odd, just return
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// print the flags line too
|
||||
if (strstr(buf, "flags") != NULL) {
|
||||
st->print_raw(buf);
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
#endif // x86 platforms
|
||||
return false;
|
||||
}
|
||||
|
||||
void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
|
||||
// Only print the model name if the platform provides this as a summary
|
||||
if (!print_model_name_and_flags(st, buf, buflen)) {
|
||||
st->print("\n/proc/cpuinfo:\n");
|
||||
if (!_print_ascii_file("/proc/cpuinfo", st)) {
|
||||
st->print_cr(" <Not Available>");
|
||||
}
|
||||
}
|
||||
st->cr();
|
||||
}
|
||||
|
||||
void os::print_siginfo(outputStream* st, void* siginfo) {
|
||||
@ -3044,8 +2970,6 @@ bool os::remove_stack_guard_pages(char* addr, size_t size) {
|
||||
return os::uncommit_memory(addr, size);
|
||||
}
|
||||
|
||||
static address _highest_vm_reserved_address = NULL;
|
||||
|
||||
// If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory
|
||||
// at 'requested_addr'. If there are existing memory mappings at the same
|
||||
// location, however, they will be overwritten. If 'fixed' is false,
|
||||
@ -3068,23 +2992,9 @@ static char* anon_mmap(char* requested_addr, size_t bytes, bool fixed) {
|
||||
addr = (char*)::mmap(requested_addr, bytes, PROT_NONE,
|
||||
flags, -1, 0);
|
||||
|
||||
if (addr != MAP_FAILED) {
|
||||
// anon_mmap() should only get called during VM initialization,
|
||||
// don't need lock (actually we can skip locking even it can be called
|
||||
// from multiple threads, because _highest_vm_reserved_address is just a
|
||||
// hint about the upper limit of non-stack memory regions.)
|
||||
if ((address)addr + bytes > _highest_vm_reserved_address) {
|
||||
_highest_vm_reserved_address = (address)addr + bytes;
|
||||
}
|
||||
}
|
||||
|
||||
return addr == MAP_FAILED ? NULL : addr;
|
||||
}
|
||||
|
||||
// Don't update _highest_vm_reserved_address, because there might be memory
|
||||
// regions above addr + size. If so, releasing a memory region only creates
|
||||
// a hole in the address space, it doesn't help prevent heap-stack collision.
|
||||
//
|
||||
static int anon_munmap(char * addr, size_t size) {
|
||||
return ::munmap(addr, size) == 0;
|
||||
}
|
||||
@ -3098,10 +3008,6 @@ bool os::pd_release_memory(char* addr, size_t size) {
|
||||
return anon_munmap(addr, size);
|
||||
}
|
||||
|
||||
static address highest_vm_reserved_address() {
|
||||
return _highest_vm_reserved_address;
|
||||
}
|
||||
|
||||
static bool linux_mprotect(char* addr, size_t size, int prot) {
|
||||
// Linux wants the mprotect address argument to be page aligned.
|
||||
char* bottom = (char*)align_size_down((intptr_t)addr, os::Linux::page_size());
|
||||
@ -3718,15 +3624,7 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
|
||||
assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
|
||||
|
||||
// Repeatedly allocate blocks until the block is allocated at the
|
||||
// right spot. Give up after max_tries. Note that reserve_memory() will
|
||||
// automatically update _highest_vm_reserved_address if the call is
|
||||
// successful. The variable tracks the highest memory address every reserved
|
||||
// by JVM. It is used to detect heap-stack collision if running with
|
||||
// fixed-stack LinuxThreads. Because here we may attempt to reserve more
|
||||
// space than needed, it could confuse the collision detecting code. To
|
||||
// solve the problem, save current _highest_vm_reserved_address and
|
||||
// calculate the correct value before return.
|
||||
address old_highest = _highest_vm_reserved_address;
|
||||
// right spot.
|
||||
|
||||
// Linux mmap allows caller to pass an address as hint; give it a try first,
|
||||
// if kernel honors the hint then we can return immediately.
|
||||
@ -3780,10 +3678,8 @@ char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
|
||||
}
|
||||
|
||||
if (i < max_tries) {
|
||||
_highest_vm_reserved_address = MAX2(old_highest, (address)requested_addr + bytes);
|
||||
return requested_addr;
|
||||
} else {
|
||||
_highest_vm_reserved_address = old_highest;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -4627,16 +4523,6 @@ void os::init(void) {
|
||||
char dummy; // used to get a guess on initial stack address
|
||||
// first_hrtime = gethrtime();
|
||||
|
||||
// With LinuxThreads the JavaMain thread pid (primordial thread)
|
||||
// is different than the pid of the java launcher thread.
|
||||
// So, on Linux, the launcher thread pid is passed to the VM
|
||||
// via the sun.java.launcher.pid property.
|
||||
// Use this property instead of getpid() if it was correctly passed.
|
||||
// See bug 6351349.
|
||||
pid_t java_launcher_pid = (pid_t) Arguments::sun_java_launcher_pid();
|
||||
|
||||
_initial_pid = (java_launcher_pid > 0) ? java_launcher_pid : getpid();
|
||||
|
||||
clock_tics_per_sec = sysconf(_SC_CLK_TCK);
|
||||
|
||||
init_random(1234567);
|
||||
@ -4769,9 +4655,8 @@ jint os::init_2(void) {
|
||||
|
||||
Linux::libpthread_init();
|
||||
if (PrintMiscellaneous && (Verbose || WizardMode)) {
|
||||
tty->print_cr("[HotSpot is running with %s, %s(%s)]\n",
|
||||
Linux::glibc_version(), Linux::libpthread_version(),
|
||||
Linux::is_floating_stack() ? "floating stack" : "fixed stack");
|
||||
tty->print_cr("[HotSpot is running with %s, %s]\n",
|
||||
Linux::glibc_version(), Linux::libpthread_version());
|
||||
}
|
||||
|
||||
if (UseNUMA) {
|
||||
@ -4946,22 +4831,6 @@ ExtendedPC os::get_thread_pc(Thread* thread) {
|
||||
return fetcher.result();
|
||||
}
|
||||
|
||||
int os::Linux::safe_cond_timedwait(pthread_cond_t *_cond,
|
||||
pthread_mutex_t *_mutex,
|
||||
const struct timespec *_abstime) {
|
||||
if (is_NPTL()) {
|
||||
return pthread_cond_timedwait(_cond, _mutex, _abstime);
|
||||
} else {
|
||||
// 6292965: LinuxThreads pthread_cond_timedwait() resets FPU control
|
||||
// word back to default 64bit precision if condvar is signaled. Java
|
||||
// wants 53bit precision. Save and restore current value.
|
||||
int fpu = get_fpu_control_word();
|
||||
int status = pthread_cond_timedwait(_cond, _mutex, _abstime);
|
||||
set_fpu_control_word(fpu);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// debug support
|
||||
|
||||
@ -5585,7 +5454,7 @@ int os::PlatformEvent::park(jlong millis) {
|
||||
// In that case, we should propagate the notify to another waiter.
|
||||
|
||||
while (_Event < 0) {
|
||||
status = os::Linux::safe_cond_timedwait(_cond, _mutex, &abst);
|
||||
status = pthread_cond_timedwait(_cond, _mutex, &abst);
|
||||
if (status != 0 && WorkAroundNPTLTimedWaitHang) {
|
||||
pthread_cond_destroy(_cond);
|
||||
pthread_cond_init(_cond, os::Linux::condAttr());
|
||||
@ -5813,7 +5682,7 @@ void Parker::park(bool isAbsolute, jlong time) {
|
||||
status = pthread_cond_wait(&_cond[_cur_index], _mutex);
|
||||
} else {
|
||||
_cur_index = isAbsolute ? ABS_INDEX : REL_INDEX;
|
||||
status = os::Linux::safe_cond_timedwait(&_cond[_cur_index], _mutex, &absTime);
|
||||
status = pthread_cond_timedwait(&_cond[_cur_index], _mutex, &absTime);
|
||||
if (status != 0 && WorkAroundNPTLTimedWaitHang) {
|
||||
pthread_cond_destroy(&_cond[_cur_index]);
|
||||
pthread_cond_init(&_cond[_cur_index], isAbsolute ? NULL : os::Linux::condAttr());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2015, 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
|
||||
@ -27,9 +27,6 @@
|
||||
|
||||
// Linux_OS defines the interface to Linux operating systems
|
||||
|
||||
// pthread_getattr_np comes with LinuxThreads-0.9-7 on RedHat 7.1
|
||||
typedef int (*pthread_getattr_func_type)(pthread_t, pthread_attr_t *);
|
||||
|
||||
// Information about the protection of the page at address '0' on this os.
|
||||
static bool zero_page_read_protected() { return true; }
|
||||
|
||||
@ -63,8 +60,6 @@ class Linux {
|
||||
static const char *_glibc_version;
|
||||
static const char *_libpthread_version;
|
||||
|
||||
static bool _is_floating_stack;
|
||||
static bool _is_NPTL;
|
||||
static bool _supports_fast_thread_cpu_time;
|
||||
|
||||
static GrowableArray<int>* _cpu_to_node;
|
||||
@ -90,10 +85,6 @@ class Linux {
|
||||
|
||||
static bool supports_variable_stack_size();
|
||||
|
||||
static void set_is_NPTL() { _is_NPTL = true; }
|
||||
static void set_is_LinuxThreads() { _is_NPTL = false; }
|
||||
static void set_is_floating_stack() { _is_floating_stack = true; }
|
||||
|
||||
static void rebuild_cpu_to_node_map();
|
||||
static GrowableArray<int>* cpu_to_node() { return _cpu_to_node; }
|
||||
|
||||
@ -178,14 +169,6 @@ class Linux {
|
||||
static const char *glibc_version() { return _glibc_version; }
|
||||
static const char *libpthread_version() { return _libpthread_version; }
|
||||
|
||||
// NPTL or LinuxThreads?
|
||||
static bool is_LinuxThreads() { return !_is_NPTL; }
|
||||
static bool is_NPTL() { return _is_NPTL; }
|
||||
|
||||
// NPTL is always floating stack. LinuxThreads could be using floating
|
||||
// stack or fixed stack.
|
||||
static bool is_floating_stack() { return _is_floating_stack; }
|
||||
|
||||
static void libpthread_init();
|
||||
static bool libnuma_init();
|
||||
static void* libnuma_dlsym(void* handle, const char* name);
|
||||
@ -234,9 +217,6 @@ class Linux {
|
||||
|
||||
// none present
|
||||
|
||||
// LinuxThreads work-around for 6292965
|
||||
static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime);
|
||||
|
||||
private:
|
||||
typedef int (*sched_getcpu_func_t)(void);
|
||||
typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2015, 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
|
||||
@ -28,7 +28,7 @@
|
||||
//
|
||||
// Defines Solaris specific flags. They are not available on other platforms.
|
||||
//
|
||||
#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
|
||||
#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
|
||||
\
|
||||
product(bool, UseExtendedFileIO, true, \
|
||||
"Enable workaround for limitations of stdio FILE structure")
|
||||
|
@ -1627,7 +1627,8 @@ typedef int (*dladdr1_func_type)(void *, Dl_info *, void **, int);
|
||||
static dladdr1_func_type dladdr1_func = NULL;
|
||||
|
||||
bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
int buflen, int * offset) {
|
||||
int buflen, int * offset,
|
||||
bool demangle) {
|
||||
// buf is not optional, but offset is optional
|
||||
assert(buf != NULL, "sanity check");
|
||||
|
||||
@ -1655,7 +1656,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
if (dlinfo.dli_saddr != NULL &&
|
||||
(char *)dlinfo.dli_saddr + info->st_size > (char *)addr) {
|
||||
if (dlinfo.dli_sname != NULL) {
|
||||
if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
|
||||
if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
|
||||
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
|
||||
}
|
||||
if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
|
||||
@ -1665,7 +1666,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
// no matching symbol so try for just file info
|
||||
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
|
||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||
buf, buflen, offset, dlinfo.dli_fname)) {
|
||||
buf, buflen, offset, dlinfo.dli_fname, demangle)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1679,7 +1680,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
if (dladdr((void *)addr, &dlinfo) != 0) {
|
||||
// see if we have a matching symbol
|
||||
if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) {
|
||||
if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) {
|
||||
if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
|
||||
jio_snprintf(buf, buflen, dlinfo.dli_sname);
|
||||
}
|
||||
if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr;
|
||||
@ -1688,7 +1689,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
// no matching symbol so try for just file info
|
||||
if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) {
|
||||
if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase),
|
||||
buf, buflen, offset, dlinfo.dli_fname)) {
|
||||
buf, buflen, offset, dlinfo.dli_fname, demangle)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1996,7 +1997,7 @@ static bool check_addr0(outputStream* st) {
|
||||
return status;
|
||||
}
|
||||
|
||||
void os::pd_print_cpu_info(outputStream* st) {
|
||||
void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
|
||||
// Nothing to do for now.
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2015, 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
|
||||
@ -162,7 +162,7 @@ void WindowsDecoder::initialize() {
|
||||
// current function and comparing the result
|
||||
address addr = (address)Decoder::demangle;
|
||||
char buf[MAX_PATH];
|
||||
if (decode(addr, buf, sizeof(buf), NULL)) {
|
||||
if (decode(addr, buf, sizeof(buf), NULL, NULL, true /* demangle */)) {
|
||||
_can_decode_in_vm = !strcmp(buf, "Decoder::demangle");
|
||||
}
|
||||
}
|
||||
@ -187,7 +187,7 @@ bool WindowsDecoder::can_decode_C_frame_in_vm() const {
|
||||
}
|
||||
|
||||
|
||||
bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath) {
|
||||
bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath, bool demangle_name) {
|
||||
if (_pfnSymGetSymFromAddr64 != NULL) {
|
||||
PIMAGEHLP_SYMBOL64 pSymbol;
|
||||
char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)];
|
||||
@ -197,7 +197,7 @@ bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, co
|
||||
DWORD64 displacement;
|
||||
if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) {
|
||||
if (buf != NULL) {
|
||||
if (demangle(pSymbol->Name, buf, buflen)) {
|
||||
if (!(demangle_name && demangle(pSymbol->Name, buf, buflen))) {
|
||||
jio_snprintf(buf, buflen, "%s", pSymbol->Name);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2015, 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
|
||||
@ -60,7 +60,7 @@ public:
|
||||
|
||||
bool can_decode_C_frame_in_vm() const;
|
||||
bool demangle(const char* symbol, char *buf, int buflen);
|
||||
bool decode(address addr, char *buf, int buflen, int* offset, const char* modulepath = NULL);
|
||||
bool decode(address addr, char *buf, int buflen, int* offset, const char* modulepath, bool demangle);
|
||||
bool decode(address addr, char *buf, int buflen, int* offset, const void* base) {
|
||||
ShouldNotReachHere();
|
||||
return false;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2015, 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
|
||||
@ -28,8 +28,7 @@
|
||||
//
|
||||
// Defines Windows specific flags. They are not available on other platforms.
|
||||
//
|
||||
#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, \
|
||||
diagnostic, notproduct) \
|
||||
#define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
|
||||
\
|
||||
product(bool, UseUTCFileTimestamp, true, \
|
||||
"Adjust the timestamp returned from stat() to be UTC")
|
||||
|
@ -1369,11 +1369,12 @@ bool os::dll_address_to_library_name(address addr, char* buf,
|
||||
}
|
||||
|
||||
bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
int buflen, int *offset) {
|
||||
int buflen, int *offset,
|
||||
bool demangle) {
|
||||
// buf is not optional, but offset is optional
|
||||
assert(buf != NULL, "sanity check");
|
||||
|
||||
if (Decoder::decode(addr, buf, buflen, offset)) {
|
||||
if (Decoder::decode(addr, buf, buflen, offset, demangle)) {
|
||||
return true;
|
||||
}
|
||||
if (offset != NULL) *offset = -1;
|
||||
@ -1732,7 +1733,7 @@ void os::win32::print_windows_version(outputStream* st) {
|
||||
st->cr();
|
||||
}
|
||||
|
||||
void os::pd_print_cpu_info(outputStream* st) {
|
||||
void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
|
||||
// Nothing to do for now.
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file hat
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2015, 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
|
||||
@ -619,54 +619,15 @@ bool os::is_allocatable(size_t bytes) {
|
||||
|
||||
#ifdef AMD64
|
||||
size_t os::Linux::min_stack_allowed = 64 * K;
|
||||
|
||||
// amd64: pthread on amd64 is always in floating stack mode
|
||||
bool os::Linux::supports_variable_stack_size() { return true; }
|
||||
#else
|
||||
size_t os::Linux::min_stack_allowed = (48 DEBUG_ONLY(+4))*K;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;})
|
||||
#endif
|
||||
|
||||
// Test if pthread library can support variable thread stack size. LinuxThreads
|
||||
// in fixed stack mode allocates 2M fixed slot for each thread. LinuxThreads
|
||||
// in floating stack mode and NPTL support variable stack size.
|
||||
bool os::Linux::supports_variable_stack_size() {
|
||||
if (os::Linux::is_NPTL()) {
|
||||
// NPTL, yes
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// Note: We can't control default stack size when creating a thread.
|
||||
// If we use non-default stack size (pthread_attr_setstacksize), both
|
||||
// floating stack and non-floating stack LinuxThreads will return the
|
||||
// same value. This makes it impossible to implement this function by
|
||||
// detecting thread stack size directly.
|
||||
//
|
||||
// An alternative approach is to check %gs. Fixed-stack LinuxThreads
|
||||
// do not use %gs, so its value is 0. Floating-stack LinuxThreads use
|
||||
// %gs (either as LDT selector or GDT selector, depending on kernel)
|
||||
// to access thread specific data.
|
||||
//
|
||||
// Note that %gs is a reserved glibc register since early 2001, so
|
||||
// applications are not allowed to change its value (Ulrich Drepper from
|
||||
// Redhat confirmed that all known offenders have been modified to use
|
||||
// either %fs or TSD). In the worst case scenario, when VM is embedded in
|
||||
// a native application that plays with %gs, we might see non-zero %gs
|
||||
// even LinuxThreads is running in fixed stack mode. As the result, we'll
|
||||
// return true and skip _thread_safety_check(), so we may not be able to
|
||||
// detect stack-heap collisions. But otherwise it's harmless.
|
||||
//
|
||||
#ifdef __GNUC__
|
||||
return (GET_GS() != 0);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif // AMD64
|
||||
|
||||
// Test if pthread library can support variable thread stack size.
|
||||
bool os::Linux::supports_variable_stack_size() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// return default stack size for thr_type
|
||||
size_t os::Linux::default_stack_size(os::ThreadType thr_type) {
|
||||
// default stack size (compiler thread needs larger stack)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2015, 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
|
||||
@ -40,8 +40,7 @@
|
||||
// actual memory pages are committed on demand.
|
||||
//
|
||||
// If an application creates and destroys a lot of threads, usually the
|
||||
// stack space freed by a thread will soon get reused by new thread
|
||||
// (this is especially true in NPTL or LinuxThreads in fixed-stack mode).
|
||||
// stack space freed by a thread will soon get reused by new thread.
|
||||
// No memory page in _sp_map is wasted.
|
||||
//
|
||||
// However, it's still possible that we might end up populating &
|
||||
|
@ -363,9 +363,6 @@ class CompilerInterfaceVC10 extends CompilerInterface {
|
||||
|
||||
// Set /On option
|
||||
addAttr(rv, "Optimization", opt);
|
||||
// Set /FR option.
|
||||
addAttr(rv, "BrowseInformation", "true");
|
||||
addAttr(rv, "BrowseInformationFile", "$(IntDir)");
|
||||
// Set /MD option.
|
||||
addAttr(rv, "RuntimeLibrary", "MultiThreadedDLL");
|
||||
// Set /Oy- option
|
||||
|
@ -1619,6 +1619,9 @@ void LIRGenerator::CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc*
|
||||
LIR_Opr dirty = LIR_OprFact::intConst(CardTableModRefBS::dirty_card_val());
|
||||
if (UseCondCardMark) {
|
||||
LIR_Opr cur_value = new_register(T_INT);
|
||||
if (UseConcMarkSweepGC) {
|
||||
__ membar_storeload();
|
||||
}
|
||||
__ move(card_addr, cur_value);
|
||||
|
||||
LabelObj* L_already_dirty = new LabelObj();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2015, 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
|
||||
@ -25,4 +25,4 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "c1/c1_globals.hpp"
|
||||
|
||||
C1_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG)
|
||||
C1_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG, IGNORE_RANGE, IGNORE_CONSTRAINT)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2015, 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
|
||||
@ -60,7 +60,7 @@
|
||||
//
|
||||
// Defines all global flags used by the client compiler.
|
||||
//
|
||||
#define C1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \
|
||||
#define C1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, range, constraint) \
|
||||
\
|
||||
/* Printing */ \
|
||||
notproduct(bool, PrintC1Statistics, false, \
|
||||
@ -148,6 +148,7 @@
|
||||
\
|
||||
product(intx, ValueMapInitialSize, 11, \
|
||||
"Initial size of a value map") \
|
||||
range(1, NOT_LP64(1*K) LP64_ONLY(32*K)) \
|
||||
\
|
||||
product(intx, ValueMapMaxLoopSize, 8, \
|
||||
"maximum size of a loop optimized by global value numbering") \
|
||||
@ -191,6 +192,7 @@
|
||||
\
|
||||
develop(intx, NestedInliningSizeRatio, 90, \
|
||||
"Percentage of prev. allowed inline size in recursive inlining") \
|
||||
range(0, 100) \
|
||||
\
|
||||
notproduct(bool, PrintIRWithLIR, false, \
|
||||
"Print IR instructions with generated LIR") \
|
||||
@ -338,10 +340,15 @@
|
||||
diagnostic(bool, C1PatchInvokeDynamic, true, \
|
||||
"Patch invokedynamic appendix not known at compile time") \
|
||||
\
|
||||
|
||||
|
||||
// Read default values for c1 globals
|
||||
|
||||
C1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)
|
||||
C1_FLAGS(DECLARE_DEVELOPER_FLAG, \
|
||||
DECLARE_PD_DEVELOPER_FLAG, \
|
||||
DECLARE_PRODUCT_FLAG, \
|
||||
DECLARE_PD_PRODUCT_FLAG, \
|
||||
DECLARE_DIAGNOSTIC_FLAG, \
|
||||
DECLARE_NOTPRODUCT_FLAG, \
|
||||
IGNORE_RANGE, \
|
||||
IGNORE_CONSTRAINT)
|
||||
|
||||
#endif // SHARE_VM_C1_C1_GLOBALS_HPP
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user