This commit is contained in:
Phil Race 2018-05-16 09:45:40 -07:00
commit 7984fb2956
1140 changed files with 122023 additions and 3832 deletions
make
src/hotspot
cpu
os
os_cpu/solaris_x86
share

@ -509,6 +509,15 @@ jdk.localedata_COPY += _dict _th
# Exclude BreakIterator classes that are just used in compile process to generate
# data files and shouldn't go in the product
jdk.localedata_EXCLUDE_FILES += sun/text/resources/ext/BreakIteratorRules_th.java
################################################################################
# There is an issue in sjavac that triggers a warning in jdk.jfr that isn't
# triggered without sjavac.
ifeq ($(ENABLE_SJAVAC), yes)
jdk.jfr_SETUP := GENERATE_JDKBYTECODE_NOWARNINGS
endif
jdk.jfr_COPY := .xsd .xml .dtd
jdk.jfr_ADD_JAVAC_FLAGS := -XDstringConcat=inline -Xlint:-exports
################################################################################
# If this is an imported module that has prebuilt classes, only compile

@ -26,7 +26,7 @@
# All valid JVM features, regardless of platform
VALID_JVM_FEATURES="compiler1 compiler2 zero minimal dtrace jvmti jvmci \
graal vm-structs jni-check services management cmsgc g1gc parallelgc serialgc nmt cds \
static-build link-time-opt aot"
static-build link-time-opt aot jfr"
# All valid JVM variants
VALID_JVM_VARIANTS="server client minimal core zero custom"
@ -309,6 +309,11 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES],
AC_MSG_ERROR([Specified JVM feature 'cmsgc' requires feature 'serialgc'])
fi
# Enable JFR by default, except on linux-sparcv9 and on minimal.
if test "x$OPENJDK_TARGET_OS" != xlinux || test "x$OPENJDK_TARGET_CPU" != xsparcv9; then
NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES jfr"
fi
# Turn on additional features based on other parts of configure
if test "x$INCLUDE_DTRACE" = "xtrue"; then
JVM_FEATURES="$JVM_FEATURES dtrace"
@ -396,7 +401,7 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES],
NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES cds"
fi
# Enable default features depending on variant.
# Enable features depending on variant.
JVM_FEATURES_server="compiler1 compiler2 $NON_MINIMAL_FEATURES $JVM_FEATURES $JVM_FEATURES_jvmci $JVM_FEATURES_aot $JVM_FEATURES_graal"
JVM_FEATURES_client="compiler1 $NON_MINIMAL_FEATURES $JVM_FEATURES $JVM_FEATURES_jvmci"
JVM_FEATURES_core="$NON_MINIMAL_FEATURES $JVM_FEATURES"

@ -130,7 +130,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
if test "x$OPENJDK_TARGET_OS" = xsolaris; then
BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lsocket -lsched -ldoor -ldemangle -lnsl \
-lrt"
-lrt -lkstat"
BASIC_JVM_LIBS="$BASIC_JVM_LIBS $LIBCXX_JVM"
fi

@ -59,7 +59,9 @@ BOOT_MODULES += \
java.security.sasl \
java.xml \
jdk.internal.vm.ci \
jdk.jfr \
jdk.management \
jdk.management.jfr \
jdk.management.agent \
jdk.net \
jdk.sctp \
@ -152,6 +154,7 @@ DOCS_MODULES += \
jdk.jdeps \
jdk.jdi \
jdk.jdwp.agent \
jdk.jfr \
jdk.jlink \
jdk.jsobject \
jdk.jshell \
@ -159,6 +162,7 @@ DOCS_MODULES += \
jdk.localedata \
jdk.management \
jdk.management.agent \
jdk.management.jfr \
jdk.naming.dns \
jdk.naming.rmi \
jdk.net \

@ -391,6 +391,13 @@ endef
# STRIPFLAGS Optionally change the flags given to the strip command
# PRECOMPILED_HEADER Header file to use as precompiled header
# PRECOMPILED_HEADER_EXCLUDE List of source files that should not use PCH
#
# After being called, some variables are exported from this macro, all prefixed
# with parameter 1 followed by a '_':
# TARGET The library or executable created by the macro
# TARGET_DEPS All prerequisites for the target calculated by the macro
# ALL_OBJS All object files
# IMPORT_LIBRARY The import library created for a shared library on Windows
SetupNativeCompilation = $(NamedParamsMacroTemplate)
define SetupNativeCompilationBody
@ -874,7 +881,9 @@ define SetupNativeCompilationBody
endif
endif
$$($1_TARGET): $$($1_ALL_OBJS) $$($1_RES) $$($1_VARDEPS_FILE) $$(STATIC_MAPFILE_DEP)
$1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_RES) $$($1_VARDEPS_FILE) $$(STATIC_MAPFILE_DEP)
$$($1_TARGET): $$($1_TARGET_DEPS)
$$(call LogInfo, Building static library $$($1_BASENAME))
$$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \
$$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_ALL_OBJS) \
@ -964,8 +973,10 @@ define SetupNativeCompilationBody
endif
endif
$$($1_TARGET): $$($1_ALL_OBJS) $$($1_RES) $$($1_MANIFEST) \
$1_TARGET_DEPS := $$($1_ALL_OBJS) $$($1_RES) $$($1_MANIFEST) \
$$($1_REAL_MAPFILE) $$($1_VARDEPS_FILE)
$$($1_TARGET): $$($1_TARGET_DEPS)
ifneq ($$($1_OBJ_FILE_LIST), )
ifeq ($$($1_LINK_OBJS_RELATIVE), true)
$$(eval $$(call ListPathsSafely, $1_ALL_OBJS_RELATIVE, $$($1_OBJ_FILE_LIST)))

@ -79,76 +79,44 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
endif
################################################################################
#
# How to install jvm.cfg.
#
ifeq ($(call check-jvm-variant, zero), true)
JVMCFG_ARCH := zero
else
JVMCFG_ARCH := $(OPENJDK_TARGET_CPU_LEGACY)
# In jvm.cfg, the first listed KNOWN variant is the default. On most build
# configurations, that is the server variant.
ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), windows-x86)
DEFAULT_CFG_VARIANT ?= client
endif
DEFAULT_CFG_VARIANT ?= server
# Any variant other than server, client or minimal is represented as server in
# the cfg file.
VALID_CFG_VARIANTS := server client minimal
CFG_VARIANTS := $(filter $(VALID_CFG_VARIANTS), $(JVM_VARIANTS)) \
$(if $(filter-out $(VALID_CFG_VARIANTS), $(JVM_VARIANTS)), server)
# Change the order to put the default variant first if present.
ORDERED_CFG_VARIANTS := \
$(if $(filter $(DEFAULT_CFG_VARIANT), $(CFG_VARIANTS)), $(DEFAULT_CFG_VARIANT)) \
$(filter-out $(DEFAULT_CFG_VARIANT), $(CFG_VARIANTS))
ifeq ($(OPENJDK_TARGET_OS), macosx)
JVMCFG_SRC := $(TOPDIR)/src/java.base/macosx/conf/$(JVMCFG_ARCH)/jvm.cfg
else
JVMCFG_SRC := $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/conf/$(JVMCFG_ARCH)/jvm.cfg
# Allow override by ALT_JVMCFG_SRC if it exists
JVMCFG_SRC := $(if $(wildcard $(ALT_JVMCFG_SRC)),$(ALT_JVMCFG_SRC),$(JVMCFG_SRC))
endif
JVMCFG := $(LIB_DST_DIR)/jvm.cfg
ifeq ($(OPENJDK_TARGET_CPU_BITS), 64)
COPY_JVM_CFG_FILE := true
else
# On 32-bit machines we have three potential VMs: client, server and minimal.
# Historically we usually have both client and server and so that is what the
# committed jvm.cfg expects (including platform specific ergonomics switches
# to decide whether to use client or server by default). So when we have anything
# other than client and server we need to define a new jvm.cfg file.
# The main problem is deciding whether to use aliases for the VMs that are not
# present and the current position is that we add aliases for client and server, but
# not for minimal.
CLIENT_AND_SERVER := $(call check-jvm-variant, client)+$(call check-jvm-variant, server)
ifeq ($(CLIENT_AND_SERVER), true+true)
COPY_JVM_CFG_FILE := true
else
# For zero, the default jvm.cfg file is sufficient
ifeq ($(call check-jvm-variant, zero), true)
COPY_JVM_CFG_FILE := true
endif
endif
endif
define print-cfg-line
$(call LogInfo, Adding -$1 $2 to jvm.cfg)
$(PRINTF) -- "-$1 $2\n" >> $@ $(NEWLINE)
endef
ifeq ($(COPY_JVM_CFG_FILE), true)
$(JVMCFG): $(JVMCFG_SRC)
$(call install-file)
else
$(JVMCFG):
$(MKDIR) -p $(@D)
$(RM) $(@)
# Now check for other permutations
ifeq ($(call check-jvm-variant, server), true)
$(PRINTF) -- "-server KNOWN\n">>$(@)
$(PRINTF) -- "-client ALIASED_TO -server\n">>$(@)
ifeq ($(call check-jvm-variant, minimal), true)
$(PRINTF) -- "-minimal KNOWN\n">>$(@)
endif
else
ifeq ($(call check-jvm-variant, client), true)
$(PRINTF) -- "-client KNOWN\n">>$(@)
$(PRINTF) -- "-server ALIASED_TO -client\n">>$(@)
ifeq ($(call check-jvm-variant, minimal), true)
$(PRINTF) -- "-minimal KNOWN\n">>$(@)
endif
else
ifeq ($(call check-jvm-variant, minimal), true)
$(PRINTF) -- "-minimal KNOWN\n">>$(@)
$(PRINTF) -- "-server ALIASED_TO -minimal\n">>$(@)
$(PRINTF) -- "-client ALIASED_TO -minimal\n">>$(@)
endif
endif
endif
endif
$(JVMCFG): $(call DependOnVariable, ORDERED_CFG_VARIANTS)
$(call MakeTargetDir)
$(RM) $@
$(foreach v, $(ORDERED_CFG_VARIANTS), \
$(call print-cfg-line,$v,KNOWN) \
)
# If either of server or client aren't present, add IGNORE lines for
# them.
$(foreach v, server client, \
$(if $(filter $v, $(ORDERED_CFG_VARIANTS)), , \
$(call print-cfg-line,$v,IGNORE) \
) \
)
TARGETS += $(JVMCFG)

@ -1,4 +1,5 @@
# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
#
# Copyright (c) 2014, 2018, 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
@ -21,14 +22,25 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# List of JVMs that can be used as an option to java, javac, etc.
# Order is important -- first in this list is the default JVM.
# NOTE that both this file and its format are UNSUPPORTED and
# WILL GO AWAY in a future release.
#
# You may also select a JVM in an arbitrary location with the
# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
# and may not be available in a future release.
#
-server KNOWN
-client IGNORE
include CopyCommon.gmk
################################################################################
$(eval $(call SetupCopyFiles, COPY_JFR_METADATA, \
SRC := $(TOPDIR)/src/hotspot/share/jfr/metadata, \
DEST := $(JDK_OUTPUTDIR)/modules/jdk.jfr/jdk/jfr/internal/types, \
FILES := metadata.xml \
))
TARGETS += $(COPY_JFR_METADATA)
JFR_CONF_DIR := $(TOPDIR)/src/jdk.jfr/share/conf/jfr
$(eval $(call SetupCopyFiles, COPY_JFR_CONF, \
DEST := $(LIB_DST_DIR)/jfr, \
FILES := $(wildcard $(JFR_CONF_DIR)/*.jfc), \
FLATTEN := true, \
))
TARGETS += $(COPY_JFR_CONF)
################################################################################

@ -38,6 +38,7 @@ include HotspotCommon.gmk
include gensrc/GensrcAdlc.gmk
include gensrc/GensrcDtrace.gmk
include gensrc/GensrcJvmti.gmk
include gensrc/GensrcJfr.gmk
$(eval $(call IncludeCustomExtension, hotspot/gensrc/GenerateSources.gmk))

@ -0,0 +1,94 @@
#
# Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# 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.
#
$(eval $(call IncludeCustomExtension, hotspot/gensrc/GensrcJfr.gmk))
################################################################################
# Build tools needed for the Jfr source code generation
JFR_TOOLS_SRCDIR := $(TOPDIR)/src/hotspot/share/jfr/metadata
JFR_TOOLS_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/tools/jfr
$(eval $(call SetupJavaCompiler, GENERATE_JFRBYTECODE, \
JAVAC := $(JAVAC), \
FLAGS := $(DISABLE_WARNINGS), \
SERVER_DIR := $(SJAVAC_SERVER_DIR), \
SERVER_JVM := $(SJAVAC_SERVER_JAVA), \
DISABLE_SJAVAC := true, \
))
$(eval $(call SetupJavaCompilation, BUILD_JFR_TOOLS, \
SETUP := GENERATE_JFRBYTECODE, \
SRC := $(JFR_TOOLS_SRCDIR), \
INCLUDE_FILES := GenerateJfrFiles.java, \
BIN := $(JFR_TOOLS_OUTPUTDIR), \
))
TOOL_JFR_GEN := $(JAVA_SMALL) -cp $(JFR_TOOLS_OUTPUTDIR) GenerateJfrFiles
################################################################################
# Setup make rules for Jfr file file generation.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name. This name is
# also used as the name of the output file.
#
# Remaining parameters are named arguments. These include:
# XML_FILE -- The input source file to use
# XSD_FILE -- The input schema for validation
# OUTPUT_DIR -- The directory to put the generated file in
SetupJfrGeneration = $(NamedParamsMacroTemplate)
define SetupJfrGenerationBody
$$($1_OUTPUT_DIR)/$1: $$($1_XML_FILE) $$($1_XSD_FILE) $$(BUILD_JFR_TOOLS)
$$(call LogInfo, Generating $$(@F))
$$(call MakeDir, $$(@D))
$$(call ExecuteWithLog, $$@, $$(TOOL_JFR_GEN) $$($1_XML_FILE) $$($1_XSD_FILE) $$($1_OUTPUT_DIR))
test -f $$@
TARGETS += $$($1_OUTPUT_DIR)/$1
endef
################################################################################
# Create files in gensrc/jfrfiles
JFR_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jfrfiles
JFR_SRCDIR := $(TOPDIR)/src/hotspot/share/jfr/metadata
METADATA_XML ?= $(JFR_SRCDIR)/metadata.xml
METADATA_XSD ?= $(JFR_SRCDIR)/metadata.xsd
# Changing these will trigger a rebuild of generated jfr files.
JFR_DEPS += \
$(METADATA_XML) \
$(METADATA_XSD) \
#
# our generator will generate all files in one go, so only need to setup one target rule
$(eval $(call SetupJfrGeneration, jfrEventClasses.hpp, \
XML_FILE := $(METADATA_XML), \
XSD_FILE := $(METADATA_XSD), \
OUTPUT_DIR := $(JFR_OUTPUTDIR), \
))

@ -1,5 +1,5 @@
#
# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2013, 2018, 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
@ -50,7 +50,7 @@ TOOL_JVMTI_GEN := $(JAVA_SMALL) -cp $(JVMTI_TOOLS_OUTPUTDIR) jvmtiGen
TOOL_JVMTI_ENV_FILL := $(JAVA_SMALL) -cp $(JVMTI_TOOLS_OUTPUTDIR) jvmtiEnvFill
################################################################################
# Setup make rules for an xml transform for jvmti/trace file generation.
# Setup make rules for an xml transform for jvmti file generation.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name. This name is
@ -126,48 +126,3 @@ ifeq ($(JVM_VARIANT), $(firstword $(JVM_VARIANTS)))
TARGETS += $(COPY_JVMTI_H)
endif
################################################################################
# Create trace files in gensrc/tracefiles
TRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/tracefiles
TRACE_SRCDIR := $(TOPDIR)/src/hotspot/share/trace
# Append list of XSL files to search (might have been set by custom extensions)
TRACE_XSL_FILES += $(wildcard $(TRACE_SRCDIR)/*.xsl)
TRACE_XML ?= $(TRACE_SRCDIR)/trace.xml
# Changing these will trigger a rebuild of generated trace files.
TRACE_DEPS += \
$(TRACE_XML) \
$(TRACE_SRCDIR)/tracetypes.xml \
$(TRACE_SRCDIR)/tracerelationdecls.xml \
$(TRACE_SRCDIR)/traceevents.xml \
$(TRACE_SRCDIR)/trace.dtd \
$(TRACE_SRCDIR)/xinclude.mod \
#
# Setup rule for generating a trace file
#
# $1 is generated source file name in $(TRACE_OUTPUTDIR)
define SetupTraceGeneration
$$(eval $$(call SetupXslTransform, $1, \
XML_FILE := $$(TRACE_XML), \
XSL_FILE := $$(firstword $$(filter %/$$(basename $1).xsl, $$(TRACE_XSL_FILES))), \
OUTPUT_DIR := $$(TRACE_OUTPUTDIR), \
DEPS := $$(TRACE_DEPS), \
))
endef
# Append files to generated (might have been set by custom extensions)
TRACE_GENSRC_FILES += \
traceEventClasses.hpp \
traceEventIds.hpp \
traceTypes.hpp \
#
# Call SetupTraceGeneration for all trace gensrc files
$(foreach tracefile, $(TRACE_GENSRC_FILES), \
$(eval $(call SetupTraceGeneration, $(tracefile))) \
)

@ -177,6 +177,13 @@ $(eval $(call SetupNativeCompilation, BUILD_LIBJVM, \
PRECOMPILED_HEADER_EXCLUDE := $(JVM_PRECOMPILED_HEADER_EXCLUDE), \
))
# Always recompile vm_version.cpp if libjvm needs to be relinked. This ensures
# that the internal vm version is updated as it relies on __DATE__ and __TIME__
# macros.
VM_VERSION_OBJ := $(JVM_OUTPUTDIR)/objs/vm_version$(OBJ_SUFFIX)
$(VM_VERSION_OBJ): $(filter-out $(VM_VERSION_OBJ) $(JVM_MAPFILE), \
$(BUILD_LIBJVM_TARGET_DEPS))
ifeq ($(OPENJDK_TARGET_OS), windows)
# It doesn't matter which jvm.lib file gets exported, but we need
# to pick just one.

@ -154,6 +154,12 @@ ifneq ($(call check-jvm-feature, serialgc), true)
# If serial is disabled, we cannot use serial as OldGC in parallel
JVM_EXCLUDE_FILES += psMarkSweep.cpp psMarkSweepDecorator.cpp
endif
ifneq ($(call check-jvm-feature, jfr), true)
JVM_CFLAGS_FEATURES += -DINCLUDE_JFR=0
JVM_EXCLUDE_PATTERNS += jfr
endif
################################################################################
ifeq ($(call check-jvm-feature, link-time-opt), true)

@ -223,7 +223,7 @@ class BuildConfig {
sysDefines.add("_WINDOWS");
sysDefines.add("HOTSPOT_BUILD_USER=\\\""+System.getProperty("user.name")+"\\\"");
sysDefines.add("HOTSPOT_BUILD_TARGET=\\\""+get("Build")+"\\\"");
sysDefines.add("INCLUDE_TRACE=1");
sysDefines.add("INCLUDE_JFR=1");
sysDefines.add("_JNI_IMPLEMENTATION_");
if (vars.get("PlatformName").equals("Win32")) {
sysDefines.add("HOTSPOT_LIB_ARCH=\\\"i386\\\"");

@ -1,5 +1,5 @@
#
# Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2006, 2018, 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
@ -273,6 +273,7 @@ my.make.rule.test.targets.svc= \
${my.test.target.set:TESTNAME=jdk_instrument}, \
${my.test.target.set:TESTNAME=jdk_jmx}, \
${my.test.target.set:TESTNAME=jdk_jdi}, \
${my.test.target.set:TESTNAME=jdk_jfr}, \
${my.test.target.set:TESTNAME=svc_tools}, \
${my.make.rule.test.targets.svc.extra}

@ -39,6 +39,7 @@ $(eval $(call SetupBuildLauncher, pack200, \
# On Mac, we have always exported all symbols, probably due to oversight
# and/or misunderstanding. To emulate this, don't hide any symbols
# by default.
# On AIX/xlc we need at least xlc 13.1 for the symbol hiding
# Also provide an override for non-conformant libraries.
ifeq ($(TOOLCHAIN_TYPE), gcc)
CXXFLAGS_JDKEXE += -fvisibility=hidden
@ -50,7 +51,9 @@ else ifeq ($(TOOLCHAIN_TYPE), clang)
else ifeq ($(TOOLCHAIN_TYPE), solstudio)
CXXFLAGS_JDKEXE += -xldscope=hidden
else ifeq ($(TOOLCHAIN_TYPE), xlc)
CXXFLAGS_JDKEXE += -qvisibility=hidden
ifneq ($(CC_VERSION_NUMBER), 12.1)
CXXFLAGS_JDKEXE += -qvisibility=hidden
endif
endif
UNPACKEXE_SRC := $(TOPDIR)/src/jdk.pack/share/native/common-unpack \

@ -45,6 +45,7 @@ endif
# On Mac, we have always exported all symbols, probably due to oversight
# and/or misunderstanding. To emulate this, don't hide any symbols
# by default.
# On AIX/xlc we need at least xlc 13.1 for the symbol hiding
# Also provide an override for non-conformant libraries.
ifeq ($(TOOLCHAIN_TYPE), gcc)
LAUNCHER_CFLAGS += -fvisibility=hidden
@ -56,7 +57,9 @@ else ifeq ($(TOOLCHAIN_TYPE), clang)
else ifeq ($(TOOLCHAIN_TYPE), solstudio)
LAUNCHER_CFLAGS += -xldscope=hidden
else ifeq ($(TOOLCHAIN_TYPE), xlc)
LAUNCHER_CFLAGS += -qvisibility=hidden
ifneq ($(CC_VERSION_NUMBER), 12.1)
CXXFLAGS_JDKEXE += -qvisibility=hidden
endif
endif
LAUNCHER_SRC := $(TOPDIR)/src/java.base/share/native/launcher

@ -41,6 +41,7 @@ WIN_JAVA_LIB := $(SUPPORT_OUTPUTDIR)/native/java.base/libjava/java.lib
# On Mac, we have always exported all symbols, probably due to oversight
# and/or misunderstanding. To emulate this, don't hide any symbols
# by default.
# On AIX/xlc we need at least xlc 13.1 for the symbol hiding
# Also provide an override for non-conformant libraries.
ifeq ($(TOOLCHAIN_TYPE), gcc)
CFLAGS_JDKLIB += -fvisibility=hidden
@ -58,9 +59,11 @@ else ifeq ($(TOOLCHAIN_TYPE), solstudio)
CXXFLAGS_JDKLIB += -xldscope=hidden
EXPORT_ALL_SYMBOLS := -xldscope=global
else ifeq ($(TOOLCHAIN_TYPE), xlc)
CFLAGS_JDKLIB += -qvisibility=hidden
CXXFLAGS_JDKLIB += -qvisibility=hidden
EXPORT_ALL_SYMBOLS := -qvisibility=default
ifneq ($(CC_VERSION_NUMBER), 12.1)
CFLAGS_JDKLIB += -qvisibility=hidden
CXXFLAGS_JDKLIB += -qvisibility=hidden
EXPORT_ALL_SYMBOLS := -qvisibility=default
endif
endif
################################################################################

@ -1,5 +1,5 @@
#
# Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2010, 2018, 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
@ -98,8 +98,8 @@ dist.javadoc.dir=${dist.dir}/javadoc
dist.nashornapi.javadoc.dir=${dist.javadoc.dir}/nashornapi
dist.dynalinkapi.javadoc.dir=${dist.javadoc.dir}/dynalinkapi
# configuration for java flight recorder
run.test.jvmargs.jfr=-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=${build.dir},stackdepth=128
# configuration for flight recorder
run.test.jvmargs.jfr=XX:StartFlightRecording=disk=true,dumponexit=true,dumponexitpath=${build.dir},stackdepth=128
# test library location
test.lib=test/nashorn/lib
@ -354,7 +354,7 @@ run.test.xms=2G
# uncomment this jfr.args to enable light recordings. the stack needs to be cranked up to 1024 frames,
# or everything will as of the now drown in lambda forms and be cut off.
#
#jfr.args=-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath="test_suite.jfr",stackdepth=1024 \
#jfr.args=-XX:StartFlightRecording=disk=true,dumponexit=true,dumponexitpath="test_suite.jfr",stackdepth=1024
jfr.args=

@ -2891,7 +2891,6 @@
<in>stringUtils.hpp</in>
<in>ticks.cpp</in>
<in>ticks.hpp</in>
<in>ticks.inline.hpp</in>
<in>utf8.cpp</in>
<in>utf8.hpp</in>
<in>vmError.cpp</in>
@ -6887,7 +6886,7 @@
<pElem>../../hotspot/src/share/vm/ci</pElem>
<pElem>../../hotspot/src/share/vm/oops</pElem>
<pElem>../../hotspot/src/share/vm/trace</pElem>
<pElem>../../build/macosx-x86_64-normal-server-release/hotspot/variant-server/gensrc/tracefiles</pElem>
<pElem>../../build/macosx-x86_64-normal-server-release/hotspot/variant-server/gensrc/jfrfiles</pElem>
<pElem>../../hotspot/src/share/vm/gc/parallel</pElem>
<pElem>../../hotspot/src/share/vm/gc/shared</pElem>
<pElem>../../hotspot/src/share/vm/classfile</pElem>
@ -15408,11 +15407,6 @@
tool="3"
flavor2="0">
</item>
<item path="../../src/hotspot/share/utilities/ticks.inline.hpp"
ex="false"
tool="3"
flavor2="0">
</item>
<item path="../../src/hotspot/share/utilities/utf8.cpp"
ex="false"
tool="1"
@ -29190,11 +29184,6 @@
tool="3"
flavor2="0">
</item>
<item path="../../src/hotspot/share/utilities/ticks.inline.hpp"
ex="false"
tool="3"
flavor2="0">
</item>
<item path="../../src/hotspot/share/utilities/utf8.cpp"
ex="false"
tool="1"

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2018, 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.
*
@ -28,6 +28,7 @@
#include "runtime/frame.inline.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/globalDefinitions.hpp"
// Implementation of the platform-specific part of StubRoutines - for
// a description of how to extend it, see the stubRoutines.hpp file.
@ -52,8 +53,7 @@ bool StubRoutines::aarch64::_completed = false;
/**
* crc_table[] from jdk/src/share/native/java/util/zip/zlib-1.2.5/crc32.h
*/
juint StubRoutines::aarch64::_crc_table[]
__attribute__ ((aligned(4096))) =
juint StubRoutines::aarch64::_crc_table[] ATTRIBUTE_ALIGNED(4096) =
{
// Table 0
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,

@ -0,0 +1,90 @@
/*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/os.inline.hpp"
#include "vm_version_ext_aarch64.hpp"
// VM_Version_Ext statics
int VM_Version_Ext::_no_of_threads = 0;
int VM_Version_Ext::_no_of_cores = 0;
int VM_Version_Ext::_no_of_sockets = 0;
bool VM_Version_Ext::_initialized = false;
char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0};
char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0};
void VM_Version_Ext::initialize_cpu_information(void) {
// do nothing if cpu info has been initialized
if (_initialized) {
return;
}
int core_id = -1;
int chip_id = -1;
int len = 0;
char* src_string = NULL;
_no_of_cores = os::processor_count();
_no_of_threads = _no_of_cores;
_no_of_sockets = _no_of_cores;
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "AArch64");
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _features_string);
_initialized = true;
}
int VM_Version_Ext::number_of_threads(void) {
initialize_cpu_information();
return _no_of_threads;
}
int VM_Version_Ext::number_of_cores(void) {
initialize_cpu_information();
return _no_of_cores;
}
int VM_Version_Ext::number_of_sockets(void) {
initialize_cpu_information();
return _no_of_sockets;
}
const char* VM_Version_Ext::cpu_name(void) {
initialize_cpu_information();
char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing);
if (NULL == tmp) {
return NULL;
}
strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE);
return tmp;
}
const char* VM_Version_Ext::cpu_description(void) {
initialize_cpu_information();
char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing);
if (NULL == tmp) {
return NULL;
}
strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE);
return tmp;
}

@ -0,0 +1,54 @@
/*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef CPU_AARCH64_VM_VM_VERSION_EXT_AARCH64_HPP
#define CPU_AARCH64_VM_VM_VERSION_EXT_AARCH64_HPP
#include "utilities/macros.hpp"
#include "vm_version_aarch64.hpp"
class VM_Version_Ext : public VM_Version {
private:
static const size_t CPU_TYPE_DESC_BUF_SIZE = 256;
static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096;
static int _no_of_threads;
static int _no_of_cores;
static int _no_of_sockets;
static bool _initialized;
static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE];
static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE];
public:
static int number_of_threads(void);
static int number_of_cores(void);
static int number_of_sockets(void);
static const char* cpu_name(void);
static const char* cpu_description(void);
static void initialize_cpu_information(void);
};
#endif // CPU_AARCH64_VM_VM_VERSION_EXT_AARCH64_HPP

@ -0,0 +1,94 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "runtime/os.inline.hpp"
#include "vm_version_ext_arm.hpp"
// VM_Version_Ext statics
int VM_Version_Ext::_no_of_threads = 0;
int VM_Version_Ext::_no_of_cores = 0;
int VM_Version_Ext::_no_of_sockets = 0;
bool VM_Version_Ext::_initialized = false;
char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0};
char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0};
void VM_Version_Ext::initialize_cpu_information(void) {
// do nothing if cpu info has been initialized
if (_initialized) {
return;
}
int core_id = -1;
int chip_id = -1;
int len = 0;
char* src_string = NULL;
_no_of_cores = os::processor_count();
_no_of_threads = _no_of_cores;
_no_of_sockets = _no_of_cores;
#ifdef AARCH64
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "AArch64");
#else
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "ARM%d", _arm_arch);
#endif
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _features_string);
_initialized = true;
}
int VM_Version_Ext::number_of_threads(void) {
initialize_cpu_information();
return _no_of_threads;
}
int VM_Version_Ext::number_of_cores(void) {
initialize_cpu_information();
return _no_of_cores;
}
int VM_Version_Ext::number_of_sockets(void) {
initialize_cpu_information();
return _no_of_sockets;
}
const char* VM_Version_Ext::cpu_name(void) {
initialize_cpu_information();
char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing);
if (NULL == tmp) {
return NULL;
}
strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE);
return tmp;
}
const char* VM_Version_Ext::cpu_description(void) {
initialize_cpu_information();
char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing);
if (NULL == tmp) {
return NULL;
}
strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE);
return tmp;
}

@ -0,0 +1,54 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef CPU_ARM_VM_VM_VERSION_EXT_ARM_HPP
#define CPU_ARM_VM_VM_VERSION_EXT_ARM_HPP
#include "utilities/macros.hpp"
#include "vm_version_arm.hpp"
class VM_Version_Ext : public VM_Version {
private:
static const size_t CPU_TYPE_DESC_BUF_SIZE = 256;
static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096;
static int _no_of_threads;
static int _no_of_cores;
static int _no_of_sockets;
static bool _initialized;
static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE];
static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE];
public:
static int number_of_threads(void);
static int number_of_cores(void);
static int number_of_sockets(void);
static const char* cpu_name(void);
static const char* cpu_description(void);
static void initialize_cpu_information(void);
};
#endif // CPU_ARM_VM_VM_VERSION_EXT_ARM_HPP

@ -0,0 +1,185 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "jvm.h"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "vm_version_ext_sparc.hpp"
// VM_Version_Ext statics
int VM_Version_Ext::_no_of_threads = 0;
int VM_Version_Ext::_no_of_cores = 0;
int VM_Version_Ext::_no_of_sockets = 0;
kid_t VM_Version_Ext::_kcid = -1;
char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0};
char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0};
// get cpu information. It takes into account if the kstat chain id
// has been changed and update the info if necessary.
bool VM_Version_Ext::initialize_cpu_information(void) {
int core_id = -1;
int chip_id = -1;
int len = 0;
char* src_string = NULL;
kstat_ctl_t* kc = kstat_open();
if (!kc) {
return false;
}
// check if kstat chain has been updated
kid_t kcid = kstat_chain_update(kc);
if (kcid == -1) {
kstat_close(kc);
return false;
}
bool updated = ((kcid > 0) && (kcid != _kcid)) ||
((kcid == 0) && (_kcid == -1));
if (!updated) {
kstat_close(kc);
return true;
}
// update the cached _kcid
_kcid = kcid;
// find the number of online processors
// for modern processsors, it is also known as the
// hardware threads.
_no_of_threads = sysconf(_SC_NPROCESSORS_ONLN);
if (_no_of_threads <= 0 ) {
kstat_close(kc);
return false;
}
_no_of_cores = 0;
_no_of_sockets = 0;
// loop through the kstat chain
kstat_t* ksp = NULL;
for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
// only interested in "cpu_info"
if (strcmp(ksp->ks_module, (char*)CPU_INFO) == 0) {
if (kstat_read(kc, ksp, NULL) == -1) {
kstat_close(kc);
return false;
}
if (ksp->ks_data != NULL) {
kstat_named_t* knm = (kstat_named_t *)ksp->ks_data;
// loop through the number of fields in each record
for (int i = 0; i < ksp->ks_ndata; i++) {
// set cpu type if it hasn't been already set
if ((strcmp((const char*)&(knm[i].name), CPU_TYPE) == 0) &&
(_cpu_name[0] == '\0')) {
if (knm[i].data_type == KSTAT_DATA_STRING) {
src_string = (char*)KSTAT_NAMED_STR_PTR(&knm[i]);
} else {
src_string = (char*)&(knm[i].value.c[0]);
}
len = strlen(src_string);
if (len < CPU_TYPE_DESC_BUF_SIZE) {
jio_snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE,
"%s", src_string);
}
}
// set cpu description if it hasn't been already set
if ((strcmp((const char*)&(knm[i].name), CPU_DESCRIPTION) == 0) &&
(_cpu_desc[0] == '\0')) {
if (knm[i].data_type == KSTAT_DATA_STRING) {
src_string = (char*)KSTAT_NAMED_STR_PTR(&knm[i]);
} else {
src_string = (char*)&(knm[i].value.c[0]);
}
len = strlen(src_string);
if (len < CPU_DETAILED_DESC_BUF_SIZE) {
jio_snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE,
"%s", src_string);
}
}
// count the number of sockets based on the chip id
if (strcmp((const char*)&(knm[i].name), CHIP_ID) == 0) {
if (chip_id != knm[i].value.l) {
chip_id = knm[i].value.l;
_no_of_sockets++;
}
}
// count the number of cores based on the core id
if (strcmp((const char*)&(knm[i].name), CORE_ID) == 0) {
if (core_id != knm[i].value.l) {
core_id = knm[i].value.l;
_no_of_cores++;
}
}
}
}
}
}
kstat_close(kc);
return true;
}
int VM_Version_Ext::number_of_threads(void) {
initialize_cpu_information();
return _no_of_threads;
}
int VM_Version_Ext::number_of_cores(void) {
initialize_cpu_information();
return _no_of_cores;
}
int VM_Version_Ext::number_of_sockets(void) {
initialize_cpu_information();
return _no_of_sockets;
}
const char* VM_Version_Ext::cpu_name(void) {
if (!initialize_cpu_information()) {
return NULL;
}
char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing);
if (NULL == tmp) {
return NULL;
}
strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE);
return tmp;
}
const char* VM_Version_Ext::cpu_description(void) {
if (!initialize_cpu_information()) {
return NULL;
}
char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing);
if (NULL == tmp) {
return NULL;
}
strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE);
return tmp;
}

@ -0,0 +1,64 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef CPU_SPARC_VM_VM_VERSION_EXT_SPARC_HPP
#define CPU_SPARC_VM_VM_VERSION_EXT_SPARC_HPP
#include "utilities/macros.hpp"
#include "vm_version_sparc.hpp"
#include <kstat.h>
#include <sys/processor.h>
#define CPU_INFO "cpu_info"
#define CPU_TYPE "fpu_type"
#define CPU_DESCRIPTION "implementation"
#define CHIP_ID "chip_id"
#define CORE_ID "core_id"
class VM_Version_Ext : public VM_Version {
private:
static const size_t CPU_TYPE_DESC_BUF_SIZE = 256;
static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096;
static int _no_of_threads;
static int _no_of_cores;
static int _no_of_sockets;
static kid_t _kcid;
static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE];
static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE];
static bool initialize_cpu_information(void);
public:
static int number_of_threads(void);
static int number_of_cores(void);
static int number_of_sockets(void);
static const char* cpu_name(void);
static const char* cpu_description(void);
};
#endif // CPU_SPARC_VM_VM_VERSION_EXT_SPARC_HPP

@ -27,14 +27,9 @@
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "runtime/stubRoutines.hpp"
#include "macroAssembler_x86.hpp"
#ifdef _MSC_VER
#define ALIGNED_(x) __declspec(align(x))
#else
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
#include "runtime/stubRoutines.hpp"
#include "utilities/globalDefinitions.hpp"
/******************************************************************************/
// ALGORITHM DESCRIPTION - COS()
@ -181,7 +176,7 @@
#ifdef _LP64
// The 64 bit code is at most SSE2 compliant
ALIGNED_(8) juint _ONE[] =
ATTRIBUTE_ALIGNED(8) juint _ONE[] =
{
0x00000000UL, 0x3ff00000UL
};
@ -636,7 +631,7 @@ void MacroAssembler::fast_cos(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xm
#else
// The 32 bit code is at most SSE2 compliant
ALIGNED_(16) juint _static_const_table_cos[] =
ATTRIBUTE_ALIGNED(16) juint _static_const_table_cos[] =
{
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
0x00000000UL, 0x00000000UL, 0x3ff00000UL, 0x176d6d31UL, 0xbf73b92eUL,

@ -27,14 +27,9 @@
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "runtime/stubRoutines.hpp"
#include "macroAssembler_x86.hpp"
#ifdef _MSC_VER
#define ALIGNED_(x) __declspec(align(x))
#else
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
#include "runtime/stubRoutines.hpp"
#include "utilities/globalDefinitions.hpp"
/******************************************************************************/
// ALGORITHM DESCRIPTION - EXP()
@ -72,7 +67,7 @@
#ifdef _LP64
// The 64 bit code is at most SSE2 compliant
ALIGNED_(16) juint _cv[] =
ATTRIBUTE_ALIGNED(16) juint _cv[] =
{
0x652b82feUL, 0x40571547UL, 0x652b82feUL, 0x40571547UL, 0xfefa0000UL,
0x3f862e42UL, 0xfefa0000UL, 0x3f862e42UL, 0xbc9e3b3aUL, 0x3d1cf79aUL,
@ -81,22 +76,22 @@ ALIGNED_(16) juint _cv[] =
0xc090cf0fUL, 0x3f811115UL, 0x55548ba1UL, 0x3fc55555UL
};
ALIGNED_(16) juint _shifter[] =
ATTRIBUTE_ALIGNED(16) juint _shifter[] =
{
0x00000000UL, 0x43380000UL, 0x00000000UL, 0x43380000UL
};
ALIGNED_(16) juint _mmask[] =
ATTRIBUTE_ALIGNED(16) juint _mmask[] =
{
0xffffffc0UL, 0x00000000UL, 0xffffffc0UL, 0x00000000UL
};
ALIGNED_(16) juint _bias[] =
ATTRIBUTE_ALIGNED(16) juint _bias[] =
{
0x0000ffc0UL, 0x00000000UL, 0x0000ffc0UL, 0x00000000UL
};
ALIGNED_(16) juint _Tbl_addr[] =
ATTRIBUTE_ALIGNED(16) juint _Tbl_addr[] =
{
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x0e03754dUL,
0x3cad7bbfUL, 0x3e778060UL, 0x00002c9aUL, 0x3567f613UL, 0x3c8cd252UL,
@ -152,37 +147,37 @@ ALIGNED_(16) juint _Tbl_addr[] =
0x000fa7c1UL
};
ALIGNED_(16) juint _ALLONES[] =
ATTRIBUTE_ALIGNED(16) juint _ALLONES[] =
{
0xffffffffUL, 0xffffffffUL, 0xffffffffUL, 0xffffffffUL
};
ALIGNED_(16) juint _ebias[] =
ATTRIBUTE_ALIGNED(16) juint _ebias[] =
{
0x00000000UL, 0x3ff00000UL, 0x00000000UL, 0x3ff00000UL
};
ALIGNED_(4) juint _XMAX[] =
ATTRIBUTE_ALIGNED(4) juint _XMAX[] =
{
0xffffffffUL, 0x7fefffffUL
};
ALIGNED_(4) juint _XMIN[] =
ATTRIBUTE_ALIGNED(4) juint _XMIN[] =
{
0x00000000UL, 0x00100000UL
};
ALIGNED_(4) juint _INF[] =
ATTRIBUTE_ALIGNED(4) juint _INF[] =
{
0x00000000UL, 0x7ff00000UL
};
ALIGNED_(4) juint _ZERO[] =
ATTRIBUTE_ALIGNED(4) juint _ZERO[] =
{
0x00000000UL, 0x00000000UL
};
ALIGNED_(4) juint _ONE_val[] =
ATTRIBUTE_ALIGNED(4) juint _ONE_val[] =
{
0x00000000UL, 0x3ff00000UL
};
@ -411,7 +406,7 @@ void MacroAssembler::fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xm
}
#else
// The 32 bit code is at most SSE2 compliant
ALIGNED_(16) juint _static_const_table[] =
ATTRIBUTE_ALIGNED(16) juint _static_const_table[] =
{
0x00000000UL, 0xfff00000UL, 0x00000000UL, 0xfff00000UL, 0xffffffc0UL,
0x00000000UL, 0xffffffc0UL, 0x00000000UL, 0x0000ffc0UL, 0x00000000UL,

@ -28,12 +28,7 @@
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "macroAssembler_x86.hpp"
#ifdef _MSC_VER
#define ALIGNED_(x) __declspec(align(x))
#else
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
#include "utilities/globalDefinitions.hpp"
/******************************************************************************/
// ALGORITHM DESCRIPTION - LOG()
@ -62,7 +57,7 @@
#ifdef _LP64
// The 64 bit code is at most SSE2 compliant
ALIGNED_(16) juint _L_tbl[] =
ATTRIBUTE_ALIGNED(16) juint _L_tbl[] =
{
0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
@ -170,12 +165,12 @@ ALIGNED_(16) juint _L_tbl[] =
0x80000000UL
};
ALIGNED_(16) juint _log2[] =
ATTRIBUTE_ALIGNED(16) juint _log2[] =
{
0xfefa3800UL, 0x3fa62e42UL, 0x93c76730UL, 0x3ceef357UL
};
ALIGNED_(16) juint _coeff[] =
ATTRIBUTE_ALIGNED(16) juint _coeff[] =
{
0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL, 0x3d6fb175UL,
0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL, 0x9999999aUL, 0x3fc99999UL,
@ -367,7 +362,7 @@ void MacroAssembler::fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xm
}
#else
// The 32 bit code is at most SSE2 compliant
ALIGNED_(16) juint _static_const_table_log[] =
ATTRIBUTE_ALIGNED(16) juint _static_const_table_log[] =
{
0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,

@ -27,14 +27,9 @@
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "runtime/stubRoutines.hpp"
#include "macroAssembler_x86.hpp"
#ifdef _MSC_VER
#define ALIGNED_(x) __declspec(align(x))
#else
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
#include "runtime/stubRoutines.hpp"
#include "utilities/globalDefinitions.hpp"
/******************************************************************************/
// ALGORITHM DESCRIPTION - LOG10()
@ -63,17 +58,17 @@
#ifdef _LP64
// The 64 bit code is at most SSE2 compliant
ALIGNED_(16) juint _HIGHSIGMASK_log10[] =
ATTRIBUTE_ALIGNED(16) juint _HIGHSIGMASK_log10[] =
{
0xf8000000UL, 0xffffffffUL, 0x00000000UL, 0xffffe000UL
};
ALIGNED_(16) juint _LOG10_E[] =
ATTRIBUTE_ALIGNED(16) juint _LOG10_E[] =
{
0x00000000UL, 0x3fdbc000UL, 0xbf2e4108UL, 0x3f5a7a6cUL
};
ALIGNED_(16) juint _L_tbl_log10[] =
ATTRIBUTE_ALIGNED(16) juint _L_tbl_log10[] =
{
0x509f7800UL, 0x3fd34413UL, 0x1f12b358UL, 0x3d1fef31UL, 0x80333400UL,
0x3fd32418UL, 0xc671d9d0UL, 0xbcf542bfUL, 0x51195000UL, 0x3fd30442UL,
@ -181,12 +176,12 @@ ALIGNED_(16) juint _L_tbl_log10[] =
0x00000000UL
};
ALIGNED_(16) juint _log2_log10[] =
ATTRIBUTE_ALIGNED(16) juint _log2_log10[] =
{
0x509f7800UL, 0x3f934413UL, 0x1f12b358UL, 0x3cdfef31UL
};
ALIGNED_(16) juint _coeff_log10[] =
ATTRIBUTE_ALIGNED(16) juint _coeff_log10[] =
{
0xc1a5f12eUL, 0x40358874UL, 0x64d4ef0dUL, 0xc0089309UL, 0x385593b1UL,
0xc025c917UL, 0xdc963467UL, 0x3ffc6a02UL, 0x7f9d3aa1UL, 0x4016ab9fUL,
@ -387,7 +382,7 @@ void MacroAssembler::fast_log10(XMMRegister xmm0, XMMRegister xmm1, XMMRegister
}
#else
// The 32 bit code is at most SSE2 compliant
ALIGNED_(16) juint _static_const_table_log10[] =
ATTRIBUTE_ALIGNED(16) juint _static_const_table_log10[] =
{
0x509f7800UL, 0x3fd34413UL, 0x1f12b358UL, 0x3d1fef31UL, 0x80333400UL,
0x3fd32418UL, 0xc671d9d0UL, 0xbcf542bfUL, 0x51195000UL, 0x3fd30442UL,

@ -27,14 +27,9 @@
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "runtime/stubRoutines.hpp"
#include "macroAssembler_x86.hpp"
#ifdef _MSC_VER
#define ALIGNED_(x) __declspec(align(x))
#else
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
#include "runtime/stubRoutines.hpp"
#include "utilities/globalDefinitions.hpp"
/******************************************************************************/
// ALGORITHM DESCRIPTION - POW()
@ -90,22 +85,22 @@
#ifdef _LP64
// The 64 bit code is at most SSE2 compliant
ALIGNED_(16) juint _HIGHSIGMASK[] =
ATTRIBUTE_ALIGNED(16) juint _HIGHSIGMASK[] =
{
0x00000000UL, 0xfffff800UL, 0x00000000UL, 0xfffff800UL
};
ALIGNED_(16) juint _LOG2_E[] =
ATTRIBUTE_ALIGNED(16) juint _LOG2_E[] =
{
0x00000000UL, 0x3ff72000UL, 0x161bb241UL, 0xbf5dabe1UL
};
ALIGNED_(16) juint _HIGHMASK_Y[] =
ATTRIBUTE_ALIGNED(16) juint _HIGHMASK_Y[] =
{
0x00000000UL, 0xfffffff8UL, 0x00000000UL, 0xffffffffUL
};
ALIGNED_(16) juint _T_exp[] =
ATTRIBUTE_ALIGNED(16) juint _T_exp[] =
{
0x00000000UL, 0x3ff00000UL, 0x00000000UL, 0x3b700000UL, 0xfa5abcbfUL,
0x3ff00b1aUL, 0xa7609f71UL, 0xbc84f6b2UL, 0xa9fb3335UL, 0x3ff0163dUL,
@ -314,29 +309,29 @@ ALIGNED_(16) juint _T_exp[] =
0x6b2a23d9UL, 0x3fffe9d9UL, 0x7442fde3UL, 0x3c74a603UL
};
ALIGNED_(16) juint _e_coeff[] =
ATTRIBUTE_ALIGNED(16) juint _e_coeff[] =
{
0xe78a6731UL, 0x3f55d87fUL, 0xd704a0c0UL, 0x3fac6b08UL, 0x6fba4e77UL,
0x3f83b2abUL, 0xff82c58fUL, 0x3fcebfbdUL, 0xfefa39efUL, 0x3fe62e42UL,
0x00000000UL, 0x00000000UL
};
ALIGNED_(16) juint _coeff_h[] =
ATTRIBUTE_ALIGNED(16) juint _coeff_h[] =
{
0x00000000UL, 0xbfd61a00UL, 0x00000000UL, 0xbf5dabe1UL
};
ALIGNED_(16) juint _HIGHMASK_LOG_X[] =
ATTRIBUTE_ALIGNED(16) juint _HIGHMASK_LOG_X[] =
{
0xf8000000UL, 0xffffffffUL, 0x00000000UL, 0xfffff800UL
};
ALIGNED_(8) juint _HALFMASK[] =
ATTRIBUTE_ALIGNED(8) juint _HALFMASK[] =
{
0xf8000000UL, 0xffffffffUL, 0xf8000000UL, 0xffffffffUL
};
ALIGNED_(16) juint _coeff_pow[] =
ATTRIBUTE_ALIGNED(16) juint _coeff_pow[] =
{
0x6dc96112UL, 0xbf836578UL, 0xee241472UL, 0xbf9b0301UL, 0x9f95985aUL,
0xbfb528dbUL, 0xb3841d2aUL, 0xbfd619b6UL, 0x518775e3UL, 0x3f9004f2UL,
@ -345,7 +340,7 @@ ALIGNED_(16) juint _coeff_pow[] =
0x486ececbUL, 0x3fc4635eUL, 0x412055ccUL, 0xbdd61bb2UL
};
ALIGNED_(16) juint _L_tbl_pow[] =
ATTRIBUTE_ALIGNED(16) juint _L_tbl_pow[] =
{
0x00000000UL, 0x3ff00000UL, 0x00000000UL, 0x00000000UL, 0x20000000UL,
0x3feff00aUL, 0x96621f95UL, 0x3e5b1856UL, 0xe0000000UL, 0x3fefe019UL,
@ -760,12 +755,12 @@ ALIGNED_(16) juint _L_tbl_pow[] =
0x00000000UL, 0x80000000UL
};
ALIGNED_(8) juint _log2_pow[] =
ATTRIBUTE_ALIGNED(8) juint _log2_pow[] =
{
0xfefa39efUL, 0x3fe62e42UL, 0xfefa39efUL, 0xbfe62e42UL
};
ALIGNED_(8) juint _DOUBLE2[] =
ATTRIBUTE_ALIGNED(8) juint _DOUBLE2[] =
{
0x00000000UL, 0x40000000UL
};
@ -1862,7 +1857,7 @@ void MacroAssembler::fast_pow(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xm
}
#else
// The 32 bit code is at most SSE2 compliant
ALIGNED_(16) juint _static_const_table_pow[] =
ATTRIBUTE_ALIGNED(16) juint _static_const_table_pow[] =
{
0x00000000UL, 0xbfd61a00UL, 0x00000000UL, 0xbf5dabe1UL, 0xf8000000UL,
0xffffffffUL, 0x00000000UL, 0xfffff800UL, 0x00000000UL, 0x3ff00000UL,

@ -27,15 +27,10 @@
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "macroAssembler_x86.hpp"
#include "runtime/stubRoutines.hpp"
#include "stubRoutines_x86.hpp"
#include "macroAssembler_x86.hpp"
#ifdef _MSC_VER
#define ALIGNED_(x) __declspec(align(x))
#else
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
#include "utilities/globalDefinitions.hpp"
/******************************************************************************/
// ALGORITHM DESCRIPTION - SIN()
@ -183,22 +178,22 @@
#ifdef _LP64
// The 64 bit code is at most SSE2 compliant
ALIGNED_(16) juint StubRoutines::x86::_ONEHALF[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_ONEHALF[] =
{
0x00000000UL, 0x3fe00000UL, 0x00000000UL, 0x3fe00000UL
};
ALIGNED_(16) juint StubRoutines::x86::_P_2[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_P_2[] =
{
0x1a600000UL, 0x3d90b461UL, 0x1a600000UL, 0x3d90b461UL
};
ALIGNED_(16) juint StubRoutines::x86::_SC_4[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_SC_4[] =
{
0xa556c734UL, 0x3ec71de3UL, 0x1a01a01aUL, 0x3efa01a0UL
};
ALIGNED_(16) juint StubRoutines::x86::_Ctable[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_Ctable[] =
{
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
0x00000000UL, 0x00000000UL, 0x3ff00000UL, 0x176d6d31UL, 0xbf73b92eUL,
@ -305,22 +300,22 @@ ALIGNED_(16) juint StubRoutines::x86::_Ctable[] =
0x00000000UL, 0x3ff00000UL
};
ALIGNED_(16) juint StubRoutines::x86::_SC_2[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_SC_2[] =
{
0x11111111UL, 0x3f811111UL, 0x55555555UL, 0x3fa55555UL
};
ALIGNED_(16) juint StubRoutines::x86::_SC_3[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_SC_3[] =
{
0x1a01a01aUL, 0xbf2a01a0UL, 0x16c16c17UL, 0xbf56c16cUL
};
ALIGNED_(16) juint StubRoutines::x86::_SC_1[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_SC_1[] =
{
0x55555555UL, 0xbfc55555UL, 0x00000000UL, 0xbfe00000UL
};
ALIGNED_(16) juint StubRoutines::x86::_PI_INV_TABLE[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_PI_INV_TABLE[] =
{
0x00000000UL, 0x00000000UL, 0xa2f9836eUL, 0x4e441529UL, 0xfc2757d1UL,
0xf534ddc0UL, 0xdb629599UL, 0x3c439041UL, 0xfe5163abUL, 0xdebbc561UL,
@ -333,52 +328,52 @@ ALIGNED_(16) juint StubRoutines::x86::_PI_INV_TABLE[] =
0xf0cfbc21UL
};
ALIGNED_(8) juint StubRoutines::x86::_PI_4[] =
ATTRIBUTE_ALIGNED(8) juint StubRoutines::x86::_PI_4[] =
{
0x40000000UL, 0x3fe921fbUL, 0x18469899UL, 0x3e64442dUL
};
ALIGNED_(8) juint StubRoutines::x86::_PI32INV[] =
ATTRIBUTE_ALIGNED(8) juint StubRoutines::x86::_PI32INV[] =
{
0x6dc9c883UL, 0x40245f30UL
};
ALIGNED_(8) juint _SHIFTER[] =
ATTRIBUTE_ALIGNED(8) juint _SHIFTER[] =
{
0x00000000UL, 0x43380000UL
};
ALIGNED_(8) juint StubRoutines::x86::_SIGN_MASK[] =
ATTRIBUTE_ALIGNED(8) juint StubRoutines::x86::_SIGN_MASK[] =
{
0x00000000UL, 0x80000000UL
};
ALIGNED_(8) juint StubRoutines::x86::_P_3[] =
ATTRIBUTE_ALIGNED(8) juint StubRoutines::x86::_P_3[] =
{
0x2e037073UL, 0x3b63198aUL
};
ALIGNED_(8) juint _ALL_ONES[] =
ATTRIBUTE_ALIGNED(8) juint _ALL_ONES[] =
{
0xffffffffUL, 0x3fefffffUL
};
ALIGNED_(8) juint _TWO_POW_55[] =
ATTRIBUTE_ALIGNED(8) juint _TWO_POW_55[] =
{
0x00000000UL, 0x43600000UL
};
ALIGNED_(8) juint _TWO_POW_M55[] =
ATTRIBUTE_ALIGNED(8) juint _TWO_POW_M55[] =
{
0x00000000UL, 0x3c800000UL
};
ALIGNED_(8) juint StubRoutines::x86::_P_1[] =
ATTRIBUTE_ALIGNED(8) juint StubRoutines::x86::_P_1[] =
{
0x54400000UL, 0x3fb921fbUL
};
ALIGNED_(8) juint StubRoutines::x86::_NEG_ZERO[] =
ATTRIBUTE_ALIGNED(8) juint StubRoutines::x86::_NEG_ZERO[] =
{
0x00000000UL, 0x80000000UL
};
@ -853,54 +848,54 @@ void MacroAssembler::fast_sin(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xm
}
#else
// The 32 bit code is at most SSE2 compliant
ALIGNED_(8) juint _zero_none[] =
ATTRIBUTE_ALIGNED(8) juint _zero_none[] =
{
0x00000000UL, 0x00000000UL, 0x00000000UL, 0xbff00000UL
};
ALIGNED_(4) juint __4onpi_d[] =
ATTRIBUTE_ALIGNED(4) juint __4onpi_d[] =
{
0x6dc9c883UL, 0x3ff45f30UL
};
ALIGNED_(4) juint _TWO_32H[] =
ATTRIBUTE_ALIGNED(4) juint _TWO_32H[] =
{
0x00000000UL, 0x41f80000UL
};
ALIGNED_(4) juint _pi04_3d[] =
ATTRIBUTE_ALIGNED(4) juint _pi04_3d[] =
{
0x54442d00UL, 0x3fe921fbUL, 0x98cc5180UL, 0x3ce84698UL, 0xcbb5bf6cUL,
0xb9dfc8f8UL
};
ALIGNED_(4) juint _pi04_5d[] =
ATTRIBUTE_ALIGNED(4) juint _pi04_5d[] =
{
0x54400000UL, 0x3fe921fbUL, 0x1a600000UL, 0x3dc0b461UL, 0x2e000000UL,
0x3b93198aUL, 0x25200000UL, 0x396b839aUL, 0x533e63a0UL, 0x37027044UL
};
ALIGNED_(4) juint _SCALE[] =
ATTRIBUTE_ALIGNED(4) juint _SCALE[] =
{
0x00000000UL, 0x32600000UL
};
ALIGNED_(4) juint _zeros[] =
ATTRIBUTE_ALIGNED(4) juint _zeros[] =
{
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x80000000UL
};
ALIGNED_(4) juint _pi04_2d[] =
ATTRIBUTE_ALIGNED(4) juint _pi04_2d[] =
{
0x54400000UL, 0x3fe921fbUL, 0x1a626331UL, 0x3dc0b461UL
};
ALIGNED_(4) juint _TWO_12H[] =
ATTRIBUTE_ALIGNED(4) juint _TWO_12H[] =
{
0x00000000UL, 0x40b80000UL
};
ALIGNED_(2) jushort __4onpi_31l[] =
ATTRIBUTE_ALIGNED(2) jushort __4onpi_31l[] =
{
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x836e, 0xa2f9,
0x40d8, 0x0000, 0x0000, 0x0000, 0x2a50, 0x9c88, 0x40b7, 0x0000, 0x0000, 0x0000,
@ -1629,29 +1624,29 @@ void MacroAssembler::libm_reduce_pi04l(Register eax, Register ecx, Register edx,
ret(0);
}
ALIGNED_(16) juint StubRoutines::x86::_L_2il0floatpacket_0[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_L_2il0floatpacket_0[] =
{
0xffffffffUL, 0x7fffffffUL, 0x00000000UL, 0x00000000UL
};
ALIGNED_(16) juint StubRoutines::x86::_Pi4Inv[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_Pi4Inv[] =
{
0x6dc9c883UL, 0x3ff45f30UL
};
ALIGNED_(16) juint StubRoutines::x86::_Pi4x3[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_Pi4x3[] =
{
0x54443000UL, 0xbfe921fbUL, 0x3b39a000UL, 0x3d373dcbUL, 0xe0e68948UL,
0xba845c06UL
};
ALIGNED_(16) juint StubRoutines::x86::_Pi4x4[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_Pi4x4[] =
{
0x54400000UL, 0xbfe921fbUL, 0x1a600000UL, 0xbdc0b461UL, 0x2e000000UL,
0xbb93198aUL, 0x252049c1UL, 0xb96b839aUL
};
ALIGNED_(16) jushort _SP[] =
ATTRIBUTE_ALIGNED(16) jushort _SP[] =
{
0xaaab, 0xaaaa, 0xaaaa, 0xaaaa, 0xbffc, 0x0000, 0x8887, 0x8888, 0x8888, 0x8888,
0x3ff8, 0x0000, 0xc527, 0x0d00, 0x00d0, 0xd00d, 0xbff2, 0x0000, 0x45f6, 0xb616,
@ -1660,7 +1655,7 @@ ALIGNED_(16) jushort _SP[] =
0xbfd6, 0x0000, 0x8610, 0x307f, 0x62a1, 0xc921, 0x3fce, 0x0000
};
ALIGNED_(16) jushort _CP[] =
ATTRIBUTE_ALIGNED(16) jushort _CP[] =
{
0x0000, 0x0000, 0x0000, 0x8000, 0xbffe, 0x0000, 0xaaa5, 0xaaaa, 0xaaaa, 0xaaaa,
0x3ffa, 0x0000, 0x9c2f, 0x0b60, 0x60b6, 0xb60b, 0xbff5, 0x0000, 0xf024, 0x0cac,
@ -1669,7 +1664,7 @@ ALIGNED_(16) jushort _CP[] =
0xbfda, 0x0000, 0x3ac6, 0x0ba0, 0x07ce, 0xd585, 0x3fd2, 0x0000
};
ALIGNED_(16) juint StubRoutines::x86::_ones[] =
ATTRIBUTE_ALIGNED(16) juint StubRoutines::x86::_ones[] =
{
0x00000000UL, 0x3ff00000UL, 0x00000000UL, 0xbff00000UL
};
@ -2197,7 +2192,7 @@ void MacroAssembler::libm_sincos_huge(XMMRegister xmm0, XMMRegister xmm1, Regist
jmp(B1_15);
}
ALIGNED_(16) juint _static_const_table_sin[] =
ATTRIBUTE_ALIGNED(16) juint _static_const_table_sin[] =
{
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
0x00000000UL, 0x00000000UL, 0x3ff00000UL, 0x176d6d31UL, 0xbf73b92eUL,

@ -27,14 +27,9 @@
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "runtime/stubRoutines.hpp"
#include "macroAssembler_x86.hpp"
#ifdef _MSC_VER
#define ALIGNED_(x) __declspec(align(x))
#else
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
#include "runtime/stubRoutines.hpp"
#include "utilities/globalDefinitions.hpp"
/******************************************************************************/
// ALGORITHM DESCRIPTION - TAN()
@ -107,42 +102,42 @@
#ifdef _LP64
// The 64 bit code is at most SSE2 compliant
ALIGNED_(16) juint _ONEHALF_tan[] =
ATTRIBUTE_ALIGNED(16) juint _ONEHALF_tan[] =
{
0x00000000UL, 0x3fe00000UL, 0x00000000UL, 0x3fe00000UL
};
ALIGNED_(16) juint _MUL16[] =
ATTRIBUTE_ALIGNED(16) juint _MUL16[] =
{
0x00000000UL, 0x40300000UL, 0x00000000UL, 0x3ff00000UL
};
ALIGNED_(16) juint _sign_mask_tan[] =
ATTRIBUTE_ALIGNED(16) juint _sign_mask_tan[] =
{
0x00000000UL, 0x80000000UL, 0x00000000UL, 0x80000000UL
};
ALIGNED_(16) juint _PI32INV_tan[] =
ATTRIBUTE_ALIGNED(16) juint _PI32INV_tan[] =
{
0x6dc9c883UL, 0x3fe45f30UL, 0x6dc9c883UL, 0x40245f30UL
};
ALIGNED_(16) juint _P_1_tan[] =
ATTRIBUTE_ALIGNED(16) juint _P_1_tan[] =
{
0x54444000UL, 0x3fb921fbUL, 0x54440000UL, 0x3fb921fbUL
};
ALIGNED_(16) juint _P_2_tan[] =
ATTRIBUTE_ALIGNED(16) juint _P_2_tan[] =
{
0x67674000UL, 0xbd32e7b9UL, 0x4c4c0000UL, 0x3d468c23UL
};
ALIGNED_(16) juint _P_3_tan[] =
ATTRIBUTE_ALIGNED(16) juint _P_3_tan[] =
{
0x3707344aUL, 0x3aa8a2e0UL, 0x03707345UL, 0x3ae98a2eUL
};
ALIGNED_(16) juint _Ctable_tan[] =
ATTRIBUTE_ALIGNED(16) juint _Ctable_tan[] =
{
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x882c10faUL,
0x3f9664f4UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
@ -428,37 +423,37 @@ ALIGNED_(16) juint _Ctable_tan[] =
0x00000000UL, 0x00000000UL, 0x00000000UL
};
ALIGNED_(16) juint _MASK_35_tan[] =
ATTRIBUTE_ALIGNED(16) juint _MASK_35_tan[] =
{
0xfffc0000UL, 0xffffffffUL, 0x00000000UL, 0x00000000UL
};
ALIGNED_(16) juint _Q_11_tan[] =
ATTRIBUTE_ALIGNED(16) juint _Q_11_tan[] =
{
0xb8fe4d77UL, 0x3f82609aUL
};
ALIGNED_(16) juint _Q_9_tan[] =
ATTRIBUTE_ALIGNED(16) juint _Q_9_tan[] =
{
0xbf847a43UL, 0x3f9664a0UL
};
ALIGNED_(16) juint _Q_7_tan[] =
ATTRIBUTE_ALIGNED(16) juint _Q_7_tan[] =
{
0x52c4c8abUL, 0x3faba1baUL
};
ALIGNED_(16) juint _Q_5_tan[] =
ATTRIBUTE_ALIGNED(16) juint _Q_5_tan[] =
{
0x11092746UL, 0x3fc11111UL
};
ALIGNED_(16) juint _Q_3_tan[] =
ATTRIBUTE_ALIGNED(16) juint _Q_3_tan[] =
{
0x55555612UL, 0x3fd55555UL
};
ALIGNED_(16) juint _PI_INV_TABLE_tan[] =
ATTRIBUTE_ALIGNED(16) juint _PI_INV_TABLE_tan[] =
{
0x00000000UL, 0x00000000UL, 0xa2f9836eUL, 0x4e441529UL, 0xfc2757d1UL,
0xf534ddc0UL, 0xdb629599UL, 0x3c439041UL, 0xfe5163abUL, 0xdebbc561UL,
@ -471,32 +466,32 @@ ALIGNED_(16) juint _PI_INV_TABLE_tan[] =
0xf0cfbc21UL
};
ALIGNED_(8) juint _PI_4_tan[] =
ATTRIBUTE_ALIGNED(8) juint _PI_4_tan[] =
{
0x00000000UL, 0x3fe921fbUL, 0x4611a626UL, 0x3e85110bUL
};
ALIGNED_(8) juint _QQ_2_tan[] =
ATTRIBUTE_ALIGNED(8) juint _QQ_2_tan[] =
{
0x676733afUL, 0x3d32e7b9UL
};
ALIGNED_(8) juint _ONE_tan[] =
ATTRIBUTE_ALIGNED(8) juint _ONE_tan[] =
{
0x00000000UL, 0x3ff00000UL
};
ALIGNED_(8) juint _TWO_POW_55_tan[] =
ATTRIBUTE_ALIGNED(8) juint _TWO_POW_55_tan[] =
{
0x00000000UL, 0x43600000UL
};
ALIGNED_(4) juint _TWO_POW_M55_tan[] =
ATTRIBUTE_ALIGNED(4) juint _TWO_POW_M55_tan[] =
{
0x00000000UL, 0x3c800000UL
};
ALIGNED_(4) juint _NEG_ZERO_tan[] =
ATTRIBUTE_ALIGNED(4) juint _NEG_ZERO_tan[] =
{
0x00000000UL, 0x80000000UL
};
@ -1064,21 +1059,21 @@ void MacroAssembler::fast_tan(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xm
}
#else
// The 32 bit code is at most SSE2 compliant
ALIGNED_(16) jushort _TP[] =
ATTRIBUTE_ALIGNED(16) jushort _TP[] =
{
0x4cd6, 0xaf6c, 0xc710, 0xc662, 0xbffd, 0x0000, 0x4b06, 0xb0ac, 0xd3b2, 0xcc2c,
0x3ff9, 0x0000, 0x00e3, 0xc850, 0xaa28, 0x9533, 0xbff3, 0x0000, 0x2ff0, 0x466d,
0x1a3b, 0xb266, 0x3fe5, 0x0000
};
ALIGNED_(16) jushort _TQ[] =
ATTRIBUTE_ALIGNED(16) jushort _TQ[] =
{
0x399c, 0x8391, 0x154c, 0x94ca, 0xbfff, 0x0000, 0xb6a3, 0xc36a, 0x44e2, 0x8a2c,
0x3ffe, 0x0000, 0xb70f, 0xd068, 0xa6ce, 0xe9dd, 0xbff9, 0x0000, 0x820f, 0x51ce,
0x7d76, 0x9bff, 0x3ff3, 0x0000
};
ALIGNED_(16) jushort _GP[] =
ATTRIBUTE_ALIGNED(16) jushort _GP[] =
{
0xaaab, 0xaaaa, 0xaaaa, 0xaaaa, 0xbffd, 0x0000, 0xb62f, 0x0b60, 0x60b6, 0xb60b,
0xbff9, 0x0000, 0xdfa7, 0x08aa, 0x55e0, 0x8ab3, 0xbff6, 0x0000, 0x85a0, 0xa819,
@ -1670,7 +1665,7 @@ void MacroAssembler::libm_tancot_huge(XMMRegister xmm0, XMMRegister xmm1, Regist
jmp(B1_15);
}
ALIGNED_(16) juint _static_const_table_tan[] =
ATTRIBUTE_ALIGNED(16) juint _static_const_table_tan[] =
{
0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x882c10faUL,
0x3f9664f4UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL,

@ -0,0 +1,210 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "rdtsc_x86.hpp"
#include "runtime/thread.inline.hpp"
#include "vm_version_ext_x86.hpp"
// The following header contains the implementations of rdtsc()
#include OS_CPU_HEADER_INLINE(os)
static jlong _epoch = 0;
static bool rdtsc_elapsed_counter_enabled = false;
static jlong tsc_frequency = 0;
static jlong set_epoch() {
assert(0 == _epoch, "invariant");
_epoch = os::rdtsc();
return _epoch;
}
// Base loop to estimate ticks frequency for tsc counter from user mode.
// Volatiles and sleep() are used to prevent compiler from applying optimizations.
static void do_time_measurements(volatile jlong& time_base,
volatile jlong& time_fast,
volatile jlong& time_base_elapsed,
volatile jlong& time_fast_elapsed) {
static const unsigned int FT_SLEEP_MILLISECS = 1;
const unsigned int loopcount = 3;
volatile jlong start = 0;
volatile jlong fstart = 0;
volatile jlong end = 0;
volatile jlong fend = 0;
// Figure out the difference between rdtsc and os provided timer.
// base algorithm adopted from JRockit.
for (unsigned int times = 0; times < loopcount; times++) {
start = os::elapsed_counter();
OrderAccess::fence();
fstart = os::rdtsc();
// use sleep to prevent compiler from optimizing
os::sleep(Thread::current(), FT_SLEEP_MILLISECS, true);
end = os::elapsed_counter();
OrderAccess::fence();
fend = os::rdtsc();
time_base += end - start;
time_fast += fend - fstart;
// basis for calculating the os tick start
// to fast time tick start offset
time_base_elapsed += end;
time_fast_elapsed += (fend - _epoch);
}
time_base /= loopcount;
time_fast /= loopcount;
time_base_elapsed /= loopcount;
time_fast_elapsed /= loopcount;
}
static jlong initialize_frequency() {
assert(0 == tsc_frequency, "invariant");
assert(0 == _epoch, "invariant");
const jlong initial_counter = set_epoch();
if (initial_counter == 0) {
return 0;
}
// os time frequency
static double os_freq = (double)os::elapsed_frequency();
assert(os_freq > 0, "os_elapsed frequency corruption!");
double tsc_freq = .0;
double os_to_tsc_conv_factor = 1.0;
// if platform supports invariant tsc,
// apply higher resolution and granularity for conversion calculations
if (VM_Version_Ext::supports_tscinv_ext()) {
// for invariant tsc platforms, take the maximum qualified cpu frequency
tsc_freq = (double)VM_Version_Ext::maximum_qualified_cpu_frequency();
os_to_tsc_conv_factor = tsc_freq / os_freq;
} else {
// use measurements to estimate
// a conversion factor and the tsc frequency
volatile jlong time_base = 0;
volatile jlong time_fast = 0;
volatile jlong time_base_elapsed = 0;
volatile jlong time_fast_elapsed = 0;
// do measurements to get base data
// on os timer and fast ticks tsc time relation.
do_time_measurements(time_base, time_fast, time_base_elapsed, time_fast_elapsed);
// if invalid measurements, cannot proceed
if (time_fast == 0 || time_base == 0) {
return 0;
}
os_to_tsc_conv_factor = (double)time_fast / (double)time_base;
if (os_to_tsc_conv_factor > 1) {
// estimate on tsc counter frequency
tsc_freq = os_to_tsc_conv_factor * os_freq;
}
}
if ((tsc_freq < 0) || (tsc_freq > 0 && tsc_freq <= os_freq) || (os_to_tsc_conv_factor <= 1)) {
// safer to run with normal os time
tsc_freq = .0;
}
// frequency of the tsc_counter
return (jlong)tsc_freq;
}
static bool initialize_elapsed_counter() {
tsc_frequency = initialize_frequency();
return tsc_frequency != 0 && _epoch != 0;
}
static bool ergonomics() {
const bool invtsc_support = Rdtsc::is_supported();
if (FLAG_IS_DEFAULT(UseFastUnorderedTimeStamps) && invtsc_support) {
FLAG_SET_ERGO(bool, UseFastUnorderedTimeStamps, true);
}
bool ft_enabled = UseFastUnorderedTimeStamps && invtsc_support;
if (!ft_enabled) {
if (UseFastUnorderedTimeStamps && VM_Version::supports_tsc()) {
warning("\nThe hardware does not support invariant tsc (INVTSC) register and/or cannot guarantee tsc synchronization between sockets at startup.\n"\
"Values returned via rdtsc() are not guaranteed to be accurate, esp. when comparing values from cross sockets reads. Enabling UseFastUnorderedTimeStamps on non-invariant tsc hardware should be considered experimental.\n");
ft_enabled = true;
}
}
if (!ft_enabled) {
// Warn if unable to support command-line flag
if (UseFastUnorderedTimeStamps && !VM_Version::supports_tsc()) {
warning("Ignoring UseFastUnorderedTimeStamps, hardware does not support normal tsc");
}
}
return ft_enabled;
}
bool Rdtsc::is_supported() {
return VM_Version_Ext::supports_tscinv_ext();
}
bool Rdtsc::is_elapsed_counter_enabled() {
return rdtsc_elapsed_counter_enabled;
}
jlong Rdtsc::frequency() {
return tsc_frequency;
}
jlong Rdtsc::elapsed_counter() {
return os::rdtsc() - _epoch;
}
jlong Rdtsc::epoch() {
return _epoch;
}
jlong Rdtsc::raw() {
return os::rdtsc();
}
bool Rdtsc::initialize() {
static bool initialized = false;
if (!initialized) {
assert(!rdtsc_elapsed_counter_enabled, "invariant");
VM_Version_Ext::initialize();
assert(0 == tsc_frequency, "invariant");
assert(0 == _epoch, "invariant");
bool result = initialize_elapsed_counter(); // init hw
if (result) {
result = ergonomics(); // check logical state
}
rdtsc_elapsed_counter_enabled = result;
initialized = true;
}
return rdtsc_elapsed_counter_enabled;
}

@ -0,0 +1,50 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef CPU_X86_VM_RDTSC_X86_HPP
#define CPU_X86_VM_RDTSC_X86_HPP
#include "memory/allocation.hpp"
#include "utilities/macros.hpp"
// Interface to the x86 rdtsc() time counter, if available.
// Not guaranteed to be synchronized across hardware threads and
// therefore software threads, and can be updated asynchronously
// by software. elapsed_counter() can jump backwards
// as well as jump forward when threads query different cores/sockets.
// Very much not recommended for general use.
// INVTSC is a minimal requirement for auto-enablement.
class Rdtsc : AllStatic {
public:
static jlong elapsed_counter(); // provides quick time stamps
static jlong frequency(); // tsc register
static bool is_supported(); // InvariantTSC
static jlong raw(); // direct rdtsc() access
static bool is_elapsed_counter_enabled(); // turn off with -XX:-UseFastUnorderedTimeStamps
static jlong epoch();
static bool initialize();
};
#endif // CPU_X86_VM_RDTSC_X86_HPP

@ -27,14 +27,9 @@
#include "runtime/frame.inline.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/globalDefinitions.hpp"
#include "crc32c.h"
#ifdef _MSC_VER
#define ALIGNED_(x) __declspec(align(x))
#else
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
// Implementation of the platform-specific part of StubRoutines - for
// a description of how to extend it, see the stubRoutines.hpp file.
@ -275,7 +270,7 @@ void StubRoutines::x86::generate_CRC32C_table(bool is_pclmulqdq_table_supported)
}
}
ALIGNED_(64) juint StubRoutines::x86::_k256[] =
ATTRIBUTE_ALIGNED(64) juint StubRoutines::x86::_k256[] =
{
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
@ -298,10 +293,10 @@ ALIGNED_(64) juint StubRoutines::x86::_k256[] =
#ifdef _LP64
// used in MacroAssembler::sha256_AVX2
// dynamically built from _k256
ALIGNED_(64) juint StubRoutines::x86::_k256_W[2*sizeof(StubRoutines::x86::_k256)];
ATTRIBUTE_ALIGNED(64) juint StubRoutines::x86::_k256_W[2*sizeof(StubRoutines::x86::_k256)];
// used in MacroAssembler::sha512_AVX2
ALIGNED_(64) julong StubRoutines::x86::_k512_W[] =
ATTRIBUTE_ALIGNED(64) julong StubRoutines::x86::_k512_W[] =
{
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,

@ -0,0 +1,967 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "jvm.h"
#include "utilities/macros.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/java.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "vm_version_ext_x86.hpp"
typedef enum {
CPU_FAMILY_8086_8088 = 0,
CPU_FAMILY_INTEL_286 = 2,
CPU_FAMILY_INTEL_386 = 3,
CPU_FAMILY_INTEL_486 = 4,
CPU_FAMILY_PENTIUM = 5,
CPU_FAMILY_PENTIUMPRO = 6, // Same family several models
CPU_FAMILY_PENTIUM_4 = 0xF
} FamilyFlag;
typedef enum {
RDTSCP_FLAG = 0x08000000, // bit 27
INTEL64_FLAG = 0x20000000 // bit 29
} _featureExtendedEdxFlag;
#define CPUID_STANDARD_FN 0x0
#define CPUID_STANDARD_FN_1 0x1
#define CPUID_STANDARD_FN_4 0x4
#define CPUID_STANDARD_FN_B 0xb
#define CPUID_EXTENDED_FN 0x80000000
#define CPUID_EXTENDED_FN_1 0x80000001
#define CPUID_EXTENDED_FN_2 0x80000002
#define CPUID_EXTENDED_FN_3 0x80000003
#define CPUID_EXTENDED_FN_4 0x80000004
#define CPUID_EXTENDED_FN_7 0x80000007
#define CPUID_EXTENDED_FN_8 0x80000008
typedef enum {
FPU_FLAG = 0x00000001,
VME_FLAG = 0x00000002,
DE_FLAG = 0x00000004,
PSE_FLAG = 0x00000008,
TSC_FLAG = 0x00000010,
MSR_FLAG = 0x00000020,
PAE_FLAG = 0x00000040,
MCE_FLAG = 0x00000080,
CX8_FLAG = 0x00000100,
APIC_FLAG = 0x00000200,
SEP_FLAG = 0x00000800,
MTRR_FLAG = 0x00001000,
PGE_FLAG = 0x00002000,
MCA_FLAG = 0x00004000,
CMOV_FLAG = 0x00008000,
PAT_FLAG = 0x00010000,
PSE36_FLAG = 0x00020000,
PSNUM_FLAG = 0x00040000,
CLFLUSH_FLAG = 0x00080000,
DTS_FLAG = 0x00200000,
ACPI_FLAG = 0x00400000,
MMX_FLAG = 0x00800000,
FXSR_FLAG = 0x01000000,
SSE_FLAG = 0x02000000,
SSE2_FLAG = 0x04000000,
SS_FLAG = 0x08000000,
HTT_FLAG = 0x10000000,
TM_FLAG = 0x20000000
} FeatureEdxFlag;
static BufferBlob* cpuid_brand_string_stub_blob;
static const int cpuid_brand_string_stub_size = 550;
extern "C" {
typedef void (*getCPUIDBrandString_stub_t)(void*);
}
static getCPUIDBrandString_stub_t getCPUIDBrandString_stub = NULL;
class VM_Version_Ext_StubGenerator: public StubCodeGenerator {
public:
VM_Version_Ext_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
address generate_getCPUIDBrandString(void) {
// Flags to test CPU type.
const uint32_t HS_EFL_AC = 0x40000;
const uint32_t HS_EFL_ID = 0x200000;
// Values for when we don't have a CPUID instruction.
const int CPU_FAMILY_SHIFT = 8;
const uint32_t CPU_FAMILY_386 = (3 << CPU_FAMILY_SHIFT);
const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT);
Label detect_486, cpu486, detect_586, done, ext_cpuid;
StubCodeMark mark(this, "VM_Version_Ext", "getCPUIDNameInfo_stub");
# define __ _masm->
address start = __ pc();
//
// void getCPUIDBrandString(VM_Version::CpuidInfo* cpuid_info);
//
// LP64: rcx and rdx are first and second argument registers on windows
__ push(rbp);
#ifdef _LP64
__ mov(rbp, c_rarg0); // cpuid_info address
#else
__ movptr(rbp, Address(rsp, 8)); // cpuid_info address
#endif
__ push(rbx);
__ push(rsi);
__ pushf(); // preserve rbx, and flags
__ pop(rax);
__ push(rax);
__ mov(rcx, rax);
//
// if we are unable to change the AC flag, we have a 386
//
__ xorl(rax, HS_EFL_AC);
__ push(rax);
__ popf();
__ pushf();
__ pop(rax);
__ cmpptr(rax, rcx);
__ jccb(Assembler::notEqual, detect_486);
__ movl(rax, CPU_FAMILY_386);
__ jmp(done);
//
// If we are unable to change the ID flag, we have a 486 which does
// not support the "cpuid" instruction.
//
__ bind(detect_486);
__ mov(rax, rcx);
__ xorl(rax, HS_EFL_ID);
__ push(rax);
__ popf();
__ pushf();
__ pop(rax);
__ cmpptr(rcx, rax);
__ jccb(Assembler::notEqual, detect_586);
__ bind(cpu486);
__ movl(rax, CPU_FAMILY_486);
__ jmp(done);
//
// At this point, we have a chip which supports the "cpuid" instruction
//
__ bind(detect_586);
__ xorl(rax, rax);
__ cpuid();
__ orl(rax, rax);
__ jcc(Assembler::equal, cpu486); // if cpuid doesn't support an input
// value of at least 1, we give up and
// assume a 486
//
// Extended cpuid(0x80000000) for processor brand string detection
//
__ bind(ext_cpuid);
__ movl(rax, CPUID_EXTENDED_FN);
__ cpuid();
__ cmpl(rax, CPUID_EXTENDED_FN_4);
__ jcc(Assembler::below, done);
//
// Extended cpuid(0x80000002) // first 16 bytes in brand string
//
__ movl(rax, CPUID_EXTENDED_FN_2);
__ cpuid();
__ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_0_offset())));
__ movl(Address(rsi, 0), rax);
__ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_1_offset())));
__ movl(Address(rsi, 0), rbx);
__ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_2_offset())));
__ movl(Address(rsi, 0), rcx);
__ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_3_offset())));
__ movl(Address(rsi,0), rdx);
//
// Extended cpuid(0x80000003) // next 16 bytes in brand string
//
__ movl(rax, CPUID_EXTENDED_FN_3);
__ cpuid();
__ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_4_offset())));
__ movl(Address(rsi, 0), rax);
__ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_5_offset())));
__ movl(Address(rsi, 0), rbx);
__ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_6_offset())));
__ movl(Address(rsi, 0), rcx);
__ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_7_offset())));
__ movl(Address(rsi,0), rdx);
//
// Extended cpuid(0x80000004) // last 16 bytes in brand string
//
__ movl(rax, CPUID_EXTENDED_FN_4);
__ cpuid();
__ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_8_offset())));
__ movl(Address(rsi, 0), rax);
__ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_9_offset())));
__ movl(Address(rsi, 0), rbx);
__ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_10_offset())));
__ movl(Address(rsi, 0), rcx);
__ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_11_offset())));
__ movl(Address(rsi,0), rdx);
//
// return
//
__ bind(done);
__ popf();
__ pop(rsi);
__ pop(rbx);
__ pop(rbp);
__ ret(0);
# undef __
return start;
};
};
// VM_Version_Ext statics
const size_t VM_Version_Ext::VENDOR_LENGTH = 13;
const size_t VM_Version_Ext::CPU_EBS_MAX_LENGTH = (3 * 4 * 4 + 1);
const size_t VM_Version_Ext::CPU_TYPE_DESC_BUF_SIZE = 256;
const size_t VM_Version_Ext::CPU_DETAILED_DESC_BUF_SIZE = 4096;
char* VM_Version_Ext::_cpu_brand_string = NULL;
jlong VM_Version_Ext::_max_qualified_cpu_frequency = 0;
int VM_Version_Ext::_no_of_threads = 0;
int VM_Version_Ext::_no_of_cores = 0;
int VM_Version_Ext::_no_of_packages = 0;
void VM_Version_Ext::initialize(void) {
ResourceMark rm;
cpuid_brand_string_stub_blob = BufferBlob::create("getCPUIDBrandString_stub", cpuid_brand_string_stub_size);
if (cpuid_brand_string_stub_blob == NULL) {
vm_exit_during_initialization("Unable to allocate getCPUIDBrandString_stub");
}
CodeBuffer c(cpuid_brand_string_stub_blob);
VM_Version_Ext_StubGenerator g(&c);
getCPUIDBrandString_stub = CAST_TO_FN_PTR(getCPUIDBrandString_stub_t,
g.generate_getCPUIDBrandString());
}
const char* VM_Version_Ext::cpu_model_description(void) {
uint32_t cpu_family = extended_cpu_family();
uint32_t cpu_model = extended_cpu_model();
const char* model = NULL;
if (cpu_family == CPU_FAMILY_PENTIUMPRO) {
for (uint32_t i = 0; i <= cpu_model; i++) {
model = _model_id_pentium_pro[i];
if (model == NULL) {
break;
}
}
}
return model;
}
const char* VM_Version_Ext::cpu_brand_string(void) {
if (_cpu_brand_string == NULL) {
_cpu_brand_string = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_EBS_MAX_LENGTH, mtInternal);
if (NULL == _cpu_brand_string) {
return NULL;
}
int ret_val = cpu_extended_brand_string(_cpu_brand_string, CPU_EBS_MAX_LENGTH);
if (ret_val != OS_OK) {
FREE_C_HEAP_ARRAY(char, _cpu_brand_string);
_cpu_brand_string = NULL;
}
}
return _cpu_brand_string;
}
const char* VM_Version_Ext::cpu_brand(void) {
const char* brand = NULL;
if ((_cpuid_info.std_cpuid1_ebx.value & 0xFF) > 0) {
int brand_num = _cpuid_info.std_cpuid1_ebx.value & 0xFF;
brand = _brand_id[0];
for (int i = 0; brand != NULL && i <= brand_num; i += 1) {
brand = _brand_id[i];
}
}
return brand;
}
bool VM_Version_Ext::cpu_is_em64t(void) {
return ((_cpuid_info.ext_cpuid1_edx.value & INTEL64_FLAG) == INTEL64_FLAG);
}
bool VM_Version_Ext::is_netburst(void) {
return (is_intel() && (extended_cpu_family() == CPU_FAMILY_PENTIUM_4));
}
bool VM_Version_Ext::supports_tscinv_ext(void) {
if (!supports_tscinv_bit()) {
return false;
}
if (is_intel()) {
return true;
}
if (is_amd()) {
return !is_amd_Barcelona();
}
return false;
}
void VM_Version_Ext::resolve_cpu_information_details(void) {
// in future we want to base this information on proper cpu
// and cache topology enumeration such as:
// Intel 64 Architecture Processor Topology Enumeration
// which supports system cpu and cache topology enumeration
// either using 2xAPICIDs or initial APICIDs
// currently only rough cpu information estimates
// which will not necessarily reflect the exact configuration of the system
// this is the number of logical hardware threads
// visible to the operating system
_no_of_threads = os::processor_count();
// find out number of threads per cpu package
int threads_per_package = threads_per_core() * cores_per_cpu();
// use amount of threads visible to the process in order to guess number of sockets
_no_of_packages = _no_of_threads / threads_per_package;
// process might only see a subset of the total number of threads
// from a single processor package. Virtualization/resource management for example.
// If so then just write a hard 1 as num of pkgs.
if (0 == _no_of_packages) {
_no_of_packages = 1;
}
// estimate the number of cores
_no_of_cores = cores_per_cpu() * _no_of_packages;
}
int VM_Version_Ext::number_of_threads(void) {
if (_no_of_threads == 0) {
resolve_cpu_information_details();
}
return _no_of_threads;
}
int VM_Version_Ext::number_of_cores(void) {
if (_no_of_cores == 0) {
resolve_cpu_information_details();
}
return _no_of_cores;
}
int VM_Version_Ext::number_of_sockets(void) {
if (_no_of_packages == 0) {
resolve_cpu_information_details();
}
return _no_of_packages;
}
const char* VM_Version_Ext::cpu_family_description(void) {
int cpu_family_id = extended_cpu_family();
if (is_amd()) {
return _family_id_amd[cpu_family_id];
}
if (is_intel()) {
if (cpu_family_id == CPU_FAMILY_PENTIUMPRO) {
return cpu_model_description();
}
return _family_id_intel[cpu_family_id];
}
return "Unknown x86";
}
int VM_Version_Ext::cpu_type_description(char* const buf, size_t buf_len) {
assert(buf != NULL, "buffer is NULL!");
assert(buf_len >= CPU_TYPE_DESC_BUF_SIZE, "buffer len should at least be == CPU_TYPE_DESC_BUF_SIZE!");
const char* cpu_type = NULL;
const char* x64 = NULL;
if (is_intel()) {
cpu_type = "Intel";
x64 = cpu_is_em64t() ? " Intel64" : "";
} else if (is_amd()) {
cpu_type = "AMD";
x64 = cpu_is_em64t() ? " AMD64" : "";
} else {
cpu_type = "Unknown x86";
x64 = cpu_is_em64t() ? " x86_64" : "";
}
jio_snprintf(buf, buf_len, "%s %s%s SSE SSE2%s%s%s%s%s%s%s%s",
cpu_type,
cpu_family_description(),
supports_ht() ? " (HT)" : "",
supports_sse3() ? " SSE3" : "",
supports_ssse3() ? " SSSE3" : "",
supports_sse4_1() ? " SSE4.1" : "",
supports_sse4_2() ? " SSE4.2" : "",
supports_sse4a() ? " SSE4A" : "",
is_netburst() ? " Netburst" : "",
is_intel_family_core() ? " Core" : "",
x64);
return OS_OK;
}
int VM_Version_Ext::cpu_extended_brand_string(char* const buf, size_t buf_len) {
assert(buf != NULL, "buffer is NULL!");
assert(buf_len >= CPU_EBS_MAX_LENGTH, "buffer len should at least be == CPU_EBS_MAX_LENGTH!");
assert(getCPUIDBrandString_stub != NULL, "not initialized");
// invoke newly generated asm code to fetch CPU Brand String
getCPUIDBrandString_stub(&_cpuid_info);
// fetch results into buffer
*((uint32_t*) &buf[0]) = _cpuid_info.proc_name_0;
*((uint32_t*) &buf[4]) = _cpuid_info.proc_name_1;
*((uint32_t*) &buf[8]) = _cpuid_info.proc_name_2;
*((uint32_t*) &buf[12]) = _cpuid_info.proc_name_3;
*((uint32_t*) &buf[16]) = _cpuid_info.proc_name_4;
*((uint32_t*) &buf[20]) = _cpuid_info.proc_name_5;
*((uint32_t*) &buf[24]) = _cpuid_info.proc_name_6;
*((uint32_t*) &buf[28]) = _cpuid_info.proc_name_7;
*((uint32_t*) &buf[32]) = _cpuid_info.proc_name_8;
*((uint32_t*) &buf[36]) = _cpuid_info.proc_name_9;
*((uint32_t*) &buf[40]) = _cpuid_info.proc_name_10;
*((uint32_t*) &buf[44]) = _cpuid_info.proc_name_11;
return OS_OK;
}
size_t VM_Version_Ext::cpu_write_support_string(char* const buf, size_t buf_len) {
assert(buf != NULL, "buffer is NULL!");
assert(buf_len > 0, "buffer len not enough!");
unsigned int flag = 0;
unsigned int fi = 0;
size_t written = 0;
const char* prefix = "";
#define WRITE_TO_BUF(string) \
{ \
int res = jio_snprintf(&buf[written], buf_len - written, "%s%s", prefix, string); \
if (res < 0 || (size_t) res >= buf_len - 1) { \
buf[buf_len-1] = '\0'; \
return buf_len - 1; \
} \
written += res; \
if (prefix[0] == '\0') { \
prefix = ", "; \
} \
}
for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) {
if (flag == HTT_FLAG && (((_cpuid_info.std_cpuid1_ebx.value >> 16) & 0xff) <= 1)) {
continue; /* no hyperthreading */
} else if (flag == SEP_FLAG && (cpu_family() == CPU_FAMILY_PENTIUMPRO && ((_cpuid_info.std_cpuid1_eax.value & 0xff) < 0x33))) {
continue; /* no fast system call */
}
if ((_cpuid_info.std_cpuid1_edx.value & flag) && strlen(_feature_edx_id[fi]) > 0) {
WRITE_TO_BUF(_feature_edx_id[fi]);
}
}
for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) {
if ((_cpuid_info.std_cpuid1_ecx.value & flag) && strlen(_feature_ecx_id[fi]) > 0) {
WRITE_TO_BUF(_feature_ecx_id[fi]);
}
}
for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) {
if ((_cpuid_info.ext_cpuid1_ecx.value & flag) && strlen(_feature_extended_ecx_id[fi]) > 0) {
WRITE_TO_BUF(_feature_extended_ecx_id[fi]);
}
}
for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) {
if ((_cpuid_info.ext_cpuid1_edx.value & flag) && strlen(_feature_extended_edx_id[fi]) > 0) {
WRITE_TO_BUF(_feature_extended_edx_id[fi]);
}
}
if (supports_tscinv_bit()) {
WRITE_TO_BUF("Invariant TSC");
}
return written;
}
/**
* Write a detailed description of the cpu to a given buffer, including
* feature set.
*/
int VM_Version_Ext::cpu_detailed_description(char* const buf, size_t buf_len) {
assert(buf != NULL, "buffer is NULL!");
assert(buf_len >= CPU_DETAILED_DESC_BUF_SIZE, "buffer len should at least be == CPU_DETAILED_DESC_BUF_SIZE!");
static const char* unknown = "<unknown>";
char vendor_id[VENDOR_LENGTH];
const char* family = NULL;
const char* model = NULL;
const char* brand = NULL;
int outputLen = 0;
family = cpu_family_description();
if (family == NULL) {
family = unknown;
}
model = cpu_model_description();
if (model == NULL) {
model = unknown;
}
brand = cpu_brand_string();
if (brand == NULL) {
brand = cpu_brand();
if (brand == NULL) {
brand = unknown;
}
}
*((uint32_t*) &vendor_id[0]) = _cpuid_info.std_vendor_name_0;
*((uint32_t*) &vendor_id[4]) = _cpuid_info.std_vendor_name_2;
*((uint32_t*) &vendor_id[8]) = _cpuid_info.std_vendor_name_1;
vendor_id[VENDOR_LENGTH-1] = '\0';
outputLen = jio_snprintf(buf, buf_len, "Brand: %s, Vendor: %s\n"
"Family: %s (0x%x), Model: %s (0x%x), Stepping: 0x%x\n"
"Ext. family: 0x%x, Ext. model: 0x%x, Type: 0x%x, Signature: 0x%8.8x\n"
"Features: ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n"
"Ext. features: eax: 0x%8.8x, ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n"
"Supports: ",
brand,
vendor_id,
family,
extended_cpu_family(),
model,
extended_cpu_model(),
cpu_stepping(),
_cpuid_info.std_cpuid1_eax.bits.ext_family,
_cpuid_info.std_cpuid1_eax.bits.ext_model,
_cpuid_info.std_cpuid1_eax.bits.proc_type,
_cpuid_info.std_cpuid1_eax.value,
_cpuid_info.std_cpuid1_ebx.value,
_cpuid_info.std_cpuid1_ecx.value,
_cpuid_info.std_cpuid1_edx.value,
_cpuid_info.ext_cpuid1_eax,
_cpuid_info.ext_cpuid1_ebx,
_cpuid_info.ext_cpuid1_ecx,
_cpuid_info.ext_cpuid1_edx);
if (outputLen < 0 || (size_t) outputLen >= buf_len - 1) {
buf[buf_len-1] = '\0';
return OS_ERR;
}
cpu_write_support_string(&buf[outputLen], buf_len - outputLen);
return OS_OK;
}
const char* VM_Version_Ext::cpu_name(void) {
char cpu_type_desc[CPU_TYPE_DESC_BUF_SIZE];
size_t cpu_desc_len = sizeof(cpu_type_desc);
cpu_type_description(cpu_type_desc, cpu_desc_len);
char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, cpu_desc_len, mtTracing);
if (NULL == tmp) {
return NULL;
}
strncpy(tmp, cpu_type_desc, cpu_desc_len);
return tmp;
}
const char* VM_Version_Ext::cpu_description(void) {
char cpu_detailed_desc_buffer[CPU_DETAILED_DESC_BUF_SIZE];
size_t cpu_detailed_desc_len = sizeof(cpu_detailed_desc_buffer);
cpu_detailed_description(cpu_detailed_desc_buffer, cpu_detailed_desc_len);
char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, cpu_detailed_desc_len, mtTracing);
if (NULL == tmp) {
return NULL;
}
strncpy(tmp, cpu_detailed_desc_buffer, cpu_detailed_desc_len);
return tmp;
}
/**
* See Intel Application note 485 (chapter 10) for details
* on frequency extraction from cpu brand string.
* http://www.intel.com/content/dam/www/public/us/en/documents/application-notes/processor-identification-cpuid-instruction-note.pdf
*
*/
jlong VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) {
// get brand string
const char* const brand_string = cpu_brand_string();
if (brand_string == NULL) {
return 0;
}
const u8 MEGA = 1000000;
u8 multiplier = 0;
jlong frequency = 0;
// the frequency information in the cpu brand string
// is given in either of two formats "x.xxyHz" or "xxxxyHz",
// where y=M,G,T and x is digits
const char* Hz_location = strchr(brand_string, 'H');
if (Hz_location != NULL) {
if (*(Hz_location + 1) == 'z') {
// switch on y in "yHz"
switch(*(Hz_location - 1)) {
case 'M' :
// Set multiplier to frequency is in Hz
multiplier = MEGA;
break;
case 'G' :
multiplier = MEGA * 1000;
break;
case 'T' :
multiplier = MEGA * 1000 * 1000;
break;
}
}
}
if (multiplier > 0) {
// compute frequency (in Hz) from brand string
if (*(Hz_location - 4) == '.') { // if format is "x.xx"
frequency = (jlong)(*(Hz_location - 5) - '0') * (multiplier);
frequency += (jlong)(*(Hz_location - 3) - '0') * (multiplier / 10);
frequency += (jlong)(*(Hz_location - 2) - '0') * (multiplier / 100);
} else { // format is "xxxx"
frequency = (jlong)(*(Hz_location - 5) - '0') * 1000;
frequency += (jlong)(*(Hz_location - 4) - '0') * 100;
frequency += (jlong)(*(Hz_location - 3) - '0') * 10;
frequency += (jlong)(*(Hz_location - 2) - '0');
frequency *= multiplier;
}
}
return frequency;
}
jlong VM_Version_Ext::maximum_qualified_cpu_frequency(void) {
if (_max_qualified_cpu_frequency == 0) {
_max_qualified_cpu_frequency = max_qualified_cpu_freq_from_brand_string();
}
return _max_qualified_cpu_frequency;
}
const char* const VM_Version_Ext::_family_id_intel[] = {
"8086/8088",
"",
"286",
"386",
"486",
"Pentium",
"Pentium Pro", //or Pentium-M/Woodcrest depeding on model
"",
"",
"",
"",
"",
"",
"",
"",
"Pentium 4"
};
const char* const VM_Version_Ext::_family_id_amd[] = {
"",
"",
"",
"",
"5x86",
"K5/K6",
"Athlon/AthlonXP",
"",
"",
"",
"",
"",
"",
"",
"",
"Opteron/Athlon64",
"Opteron QC/Phenom" // Barcelona et.al.
};
// Partially from Intel 64 and IA-32 Architecture Software Developer's Manual,
// September 2013, Vol 3C Table 35-1
const char* const VM_Version_Ext::_model_id_pentium_pro[] = {
"",
"Pentium Pro",
"",
"Pentium II model 3",
"",
"Pentium II model 5/Xeon/Celeron",
"Celeron",
"Pentium III/Pentium III Xeon",
"Pentium III/Pentium III Xeon",
"Pentium M model 9", // Yonah
"Pentium III, model A",
"Pentium III, model B",
"",
"Pentium M model D", // Dothan
"",
"Core 2", // 0xf Woodcrest/Conroe/Merom/Kentsfield/Clovertown
"",
"",
"",
"",
"",
"",
"Celeron", // 0x16 Celeron 65nm
"Core 2", // 0x17 Penryn / Harpertown
"",
"",
"Core i7", // 0x1A CPU_MODEL_NEHALEM_EP
"Atom", // 0x1B Z5xx series Silverthorn
"",
"Core 2", // 0x1D Dunnington (6-core)
"Nehalem", // 0x1E CPU_MODEL_NEHALEM
"",
"",
"",
"",
"",
"",
"Westmere", // 0x25 CPU_MODEL_WESTMERE
"",
"",
"", // 0x28
"",
"Sandy Bridge", // 0x2a "2nd Generation Intel Core i7, i5, i3"
"",
"Westmere-EP", // 0x2c CPU_MODEL_WESTMERE_EP
"Sandy Bridge-EP", // 0x2d CPU_MODEL_SANDYBRIDGE_EP
"Nehalem-EX", // 0x2e CPU_MODEL_NEHALEM_EX
"Westmere-EX", // 0x2f CPU_MODEL_WESTMERE_EX
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"Ivy Bridge", // 0x3a
"",
"Haswell", // 0x3c "4th Generation Intel Core Processor"
"", // 0x3d "Next Generation Intel Core Processor"
"Ivy Bridge-EP", // 0x3e "Next Generation Intel Xeon Processor E7 Family"
"", // 0x3f "Future Generation Intel Xeon Processor"
"",
"",
"",
"",
"",
"Haswell", // 0x45 "4th Generation Intel Core Processor"
"Haswell", // 0x46 "4th Generation Intel Core Processor"
NULL
};
/* Brand ID is for back compability
* Newer CPUs uses the extended brand string */
const char* const VM_Version_Ext::_brand_id[] = {
"",
"Celeron processor",
"Pentium III processor",
"Intel Pentium III Xeon processor",
"",
"",
"",
"",
"Intel Pentium 4 processor",
NULL
};
const char* const VM_Version_Ext::_feature_edx_id[] = {
"On-Chip FPU",
"Virtual Mode Extensions",
"Debugging Extensions",
"Page Size Extensions",
"Time Stamp Counter",
"Model Specific Registers",
"Physical Address Extension",
"Machine Check Exceptions",
"CMPXCHG8B Instruction",
"On-Chip APIC",
"",
"Fast System Call",
"Memory Type Range Registers",
"Page Global Enable",
"Machine Check Architecture",
"Conditional Mov Instruction",
"Page Attribute Table",
"36-bit Page Size Extension",
"Processor Serial Number",
"CLFLUSH Instruction",
"",
"Debug Trace Store feature",
"ACPI registers in MSR space",
"Intel Architecture MMX Technology",
"Fast Float Point Save and Restore",
"Streaming SIMD extensions",
"Streaming SIMD extensions 2",
"Self-Snoop",
"Hyper Threading",
"Thermal Monitor",
"",
"Pending Break Enable"
};
const char* const VM_Version_Ext::_feature_extended_edx_id[] = {
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"SYSCALL/SYSRET",
"",
"",
"",
"",
"",
"",
"",
"",
"Execute Disable Bit",
"",
"",
"",
"",
"",
"",
"RDTSCP",
"",
"Intel 64 Architecture",
"",
""
};
const char* const VM_Version_Ext::_feature_ecx_id[] = {
"Streaming SIMD Extensions 3",
"PCLMULQDQ",
"64-bit DS Area",
"MONITOR/MWAIT instructions",
"CPL Qualified Debug Store",
"Virtual Machine Extensions",
"Safer Mode Extensions",
"Enhanced Intel SpeedStep technology",
"Thermal Monitor 2",
"Supplemental Streaming SIMD Extensions 3",
"L1 Context ID",
"",
"Fused Multiply-Add",
"CMPXCHG16B",
"xTPR Update Control",
"Perfmon and Debug Capability",
"",
"Process-context identifiers",
"Direct Cache Access",
"Streaming SIMD extensions 4.1",
"Streaming SIMD extensions 4.2",
"x2APIC",
"MOVBE",
"Popcount instruction",
"TSC-Deadline",
"AESNI",
"XSAVE",
"OSXSAVE",
"AVX",
"F16C",
"RDRAND",
""
};
const char* const VM_Version_Ext::_feature_extended_ecx_id[] = {
"LAHF/SAHF instruction support",
"Core multi-processor leagacy mode",
"",
"",
"",
"Advanced Bit Manipulations: LZCNT",
"SSE4A: MOVNTSS, MOVNTSD, EXTRQ, INSERTQ",
"Misaligned SSE mode",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
""
};

@ -0,0 +1,99 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef CPU_X86_VM_VM_VERSION_EXT_X86_HPP
#define CPU_X86_VM_VM_VERSION_EXT_X86_HPP
#include "utilities/macros.hpp"
#include "vm_version_x86.hpp"
class VM_Version_Ext : public VM_Version {
private:
static const size_t VENDOR_LENGTH;
static const size_t CPU_EBS_MAX_LENGTH;
static const size_t CPU_TYPE_DESC_BUF_SIZE;
static const size_t CPU_DETAILED_DESC_BUF_SIZE;
static const char* const _family_id_intel[];
static const char* const _family_id_amd[];
static const char* const _brand_id[];
static const char* const _model_id_pentium_pro[];
static const char* const _feature_edx_id[];
static const char* const _feature_extended_edx_id[];
static const char* const _feature_ecx_id[];
static const char* const _feature_extended_ecx_id[];
static int _no_of_threads;
static int _no_of_cores;
static int _no_of_packages;
static char* _cpu_brand_string;
static jlong _max_qualified_cpu_frequency;
static const char* cpu_family_description(void);
static const char* cpu_model_description(void);
static const char* cpu_brand(void);
static const char* cpu_brand_string(void);
static int cpu_type_description(char* const buf, size_t buf_len);
static int cpu_detailed_description(char* const buf, size_t buf_len);
static int cpu_extended_brand_string(char* const buf, size_t buf_len);
static bool cpu_is_em64t(void);
static bool is_netburst(void);
static size_t cpu_write_support_string(char* const buf, size_t buf_len);
static void resolve_cpu_information_details(void);
static jlong max_qualified_cpu_freq_from_brand_string(void);
public:
// Offsets for cpuid asm stub brand string
static ByteSize proc_name_0_offset() { return byte_offset_of(CpuidInfo, proc_name_0); }
static ByteSize proc_name_1_offset() { return byte_offset_of(CpuidInfo, proc_name_1); }
static ByteSize proc_name_2_offset() { return byte_offset_of(CpuidInfo, proc_name_2); }
static ByteSize proc_name_3_offset() { return byte_offset_of(CpuidInfo, proc_name_3); }
static ByteSize proc_name_4_offset() { return byte_offset_of(CpuidInfo, proc_name_4); }
static ByteSize proc_name_5_offset() { return byte_offset_of(CpuidInfo, proc_name_5); }
static ByteSize proc_name_6_offset() { return byte_offset_of(CpuidInfo, proc_name_6); }
static ByteSize proc_name_7_offset() { return byte_offset_of(CpuidInfo, proc_name_7); }
static ByteSize proc_name_8_offset() { return byte_offset_of(CpuidInfo, proc_name_8); }
static ByteSize proc_name_9_offset() { return byte_offset_of(CpuidInfo, proc_name_9); }
static ByteSize proc_name_10_offset() { return byte_offset_of(CpuidInfo, proc_name_10); }
static ByteSize proc_name_11_offset() { return byte_offset_of(CpuidInfo, proc_name_11); }
static int number_of_threads(void);
static int number_of_cores(void);
static int number_of_sockets(void);
static jlong maximum_qualified_cpu_frequency(void);
static bool supports_tscinv_ext(void);
static const char* cpu_name(void);
static const char* cpu_description(void);
static void initialize();
};
#endif // CPU_X86_VM_VM_VERSION_EXT_X86_HPP

@ -0,0 +1,405 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/os.hpp"
#include "runtime/os_perf.hpp"
#include "vm_version_ext_x86.hpp"
#ifdef __APPLE__
#import <libproc.h>
#include <sys/time.h>
#include <sys/sysctl.h>
#include <mach/mach.h>
#include <mach/task_info.h>
#endif
static const double NANOS_PER_SEC = 1000000000.0;
class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
friend class CPUPerformanceInterface;
private:
long _total_cpu_nanos;
long _total_csr_nanos;
long _jvm_user_nanos;
long _jvm_system_nanos;
long _jvm_context_switches;
long _used_ticks;
long _total_ticks;
int _active_processor_count;
bool now_in_nanos(long* resultp) {
timeval current_time;
if (gettimeofday(&current_time, NULL) != 0) {
// Error getting current time
return false;
}
*resultp = current_time.tv_sec * NANOS_PER_SEC + 1000L * current_time.tv_usec;
return true;
}
double normalize(double value) {
return MIN2<double>(MAX2<double>(value, 0.0), 1.0);
}
int cpu_load(int which_logical_cpu, double* cpu_load);
int context_switch_rate(double* rate);
int cpu_load_total_process(double* cpu_load);
int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);
CPUPerformance(const CPUPerformance& rhs); // no impl
CPUPerformance& operator=(const CPUPerformance& rhs); // no impl
public:
CPUPerformance();
bool initialize();
~CPUPerformance();
};
CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
_total_cpu_nanos= 0;
_total_csr_nanos= 0;
_jvm_context_switches = 0;
_jvm_user_nanos = 0;
_jvm_system_nanos = 0;
_used_ticks = 0;
_total_ticks = 0;
_active_processor_count = 0;
}
bool CPUPerformanceInterface::CPUPerformance::initialize() {
return true;
}
CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
}
int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
return FUNCTIONALITY_NOT_IMPLEMENTED;
}
int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
#ifdef __APPLE__
host_name_port_t host = mach_host_self();
host_flavor_t flavor = HOST_CPU_LOAD_INFO;
mach_msg_type_number_t host_info_count = HOST_CPU_LOAD_INFO_COUNT;
host_cpu_load_info_data_t cpu_load_info;
kern_return_t kr = host_statistics(host, flavor, (host_info_t)&cpu_load_info, &host_info_count);
if (kr != KERN_SUCCESS) {
return OS_ERR;
}
long used_ticks = cpu_load_info.cpu_ticks[CPU_STATE_USER] + cpu_load_info.cpu_ticks[CPU_STATE_NICE] + cpu_load_info.cpu_ticks[CPU_STATE_SYSTEM];
long total_ticks = used_ticks + cpu_load_info.cpu_ticks[CPU_STATE_IDLE];
if (_used_ticks == 0 || _total_ticks == 0) {
// First call, just set the values
_used_ticks = used_ticks;
_total_ticks = total_ticks;
return OS_ERR;
}
long used_delta = used_ticks - _used_ticks;
long total_delta = total_ticks - _total_ticks;
_used_ticks = used_ticks;
_total_ticks = total_ticks;
if (total_delta == 0) {
// Avoid division by zero
return OS_ERR;
}
*cpu_load = (double)used_delta / total_delta;
return OS_OK;
#else
return FUNCTIONALITY_NOT_IMPLEMENTED;
#endif
}
int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) {
#ifdef __APPLE__
int result = cpu_load_total_process(psystemTotalLoad);
mach_port_t task = mach_task_self();
mach_msg_type_number_t task_info_count = TASK_INFO_MAX;
task_info_data_t task_info_data;
kern_return_t kr = task_info(task, TASK_ABSOLUTETIME_INFO, (task_info_t)task_info_data, &task_info_count);
if (kr != KERN_SUCCESS) {
return OS_ERR;
}
task_absolutetime_info_t absolutetime_info = (task_absolutetime_info_t)task_info_data;
int active_processor_count = os::active_processor_count();
long jvm_user_nanos = absolutetime_info->total_user;
long jvm_system_nanos = absolutetime_info->total_system;
long total_cpu_nanos;
if(!now_in_nanos(&total_cpu_nanos)) {
return OS_ERR;
}
if (_total_cpu_nanos == 0 || active_processor_count != _active_processor_count) {
// First call or change in active processor count
result = OS_ERR;
}
long delta_nanos = active_processor_count * (total_cpu_nanos - _total_cpu_nanos);
if (delta_nanos == 0) {
// Avoid division by zero
return OS_ERR;
}
*pjvmUserLoad = normalize((double)(jvm_user_nanos - _jvm_user_nanos)/delta_nanos);
*pjvmKernelLoad = normalize((double)(jvm_system_nanos - _jvm_system_nanos)/delta_nanos);
_active_processor_count = active_processor_count;
_total_cpu_nanos = total_cpu_nanos;
_jvm_user_nanos = jvm_user_nanos;
_jvm_system_nanos = jvm_system_nanos;
return result;
#else
return FUNCTIONALITY_NOT_IMPLEMENTED;
#endif
}
int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {
#ifdef __APPLE__
mach_port_t task = mach_task_self();
mach_msg_type_number_t task_info_count = TASK_INFO_MAX;
task_info_data_t task_info_data;
kern_return_t kr = task_info(task, TASK_EVENTS_INFO, (task_info_t)task_info_data, &task_info_count);
if (kr != KERN_SUCCESS) {
return OS_ERR;
}
int result = OS_OK;
if (_total_csr_nanos == 0 || _jvm_context_switches == 0) {
// First call just set initial values.
result = OS_ERR;
}
long jvm_context_switches = ((task_events_info_t)task_info_data)->csw;
long total_csr_nanos;
if(!now_in_nanos(&total_csr_nanos)) {
return OS_ERR;
}
double delta_in_sec = (double)(total_csr_nanos - _total_csr_nanos) / NANOS_PER_SEC;
if (delta_in_sec == 0.0) {
// Avoid division by zero
return OS_ERR;
}
*rate = (jvm_context_switches - _jvm_context_switches) / delta_in_sec;
_jvm_context_switches = jvm_context_switches;
_total_csr_nanos = total_csr_nanos;
return result;
#else
return FUNCTIONALITY_NOT_IMPLEMENTED;
#endif
}
CPUPerformanceInterface::CPUPerformanceInterface() {
_impl = NULL;
}
bool CPUPerformanceInterface::initialize() {
_impl = new CPUPerformanceInterface::CPUPerformance();
return _impl != NULL && _impl->initialize();
}
CPUPerformanceInterface::~CPUPerformanceInterface() {
if (_impl != NULL) {
delete _impl;
}
}
int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {
return _impl->cpu_load(which_logical_cpu, cpu_load);
}
int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {
return _impl->cpu_load_total_process(cpu_load);
}
int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) const {
return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);
}
int CPUPerformanceInterface::context_switch_rate(double* rate) const {
return _impl->context_switch_rate(rate);
}
class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {
friend class SystemProcessInterface;
private:
SystemProcesses();
bool initialize();
SystemProcesses(const SystemProcesses& rhs); // no impl
SystemProcesses& operator=(const SystemProcesses& rhs); // no impl
~SystemProcesses();
//information about system processes
int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;
};
SystemProcessInterface::SystemProcesses::SystemProcesses() {
}
bool SystemProcessInterface::SystemProcesses::initialize() {
return true;
}
SystemProcessInterface::SystemProcesses::~SystemProcesses() {
}
int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const {
assert(system_processes != NULL, "system_processes pointer is NULL!");
assert(no_of_sys_processes != NULL, "system_processes counter pointer is NULL!");
#ifdef __APPLE__
pid_t* pids = NULL;
int pid_count = 0;
ResourceMark rm;
int try_count = 0;
while (pids == NULL) {
// Find out buffer size
size_t pids_bytes = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
if (pids_bytes <= 0) {
return OS_ERR;
}
pid_count = pids_bytes / sizeof(pid_t);
pids = NEW_RESOURCE_ARRAY(pid_t, pid_count);
memset(pids, 0, pids_bytes);
pids_bytes = proc_listpids(PROC_ALL_PIDS, 0, pids, pids_bytes);
if (pids_bytes <= 0) {
// couldn't fit buffer, retry.
FREE_RESOURCE_ARRAY(pid_t, pids, pid_count);
pids = NULL;
try_count++;
if (try_count > 3) {
return OS_ERR;
}
} else {
pid_count = pids_bytes / sizeof(pid_t);
}
}
int process_count = 0;
SystemProcess* next = NULL;
for (int i = 0; i < pid_count; i++) {
pid_t pid = pids[i];
if (pid != 0) {
char buffer[PROC_PIDPATHINFO_MAXSIZE];
memset(buffer, 0 , sizeof(buffer));
if (proc_pidpath(pid, buffer, sizeof(buffer)) != -1) {
int length = strlen(buffer);
if (length > 0) {
SystemProcess* current = new SystemProcess();
char * path = NEW_C_HEAP_ARRAY(char, length + 1, mtInternal);
strcpy(path, buffer);
current->set_path(path);
current->set_pid((int)pid);
current->set_next(next);
next = current;
process_count++;
}
}
}
}
*no_of_sys_processes = process_count;
*system_processes = next;
return OS_OK;
#endif
return FUNCTIONALITY_NOT_IMPLEMENTED;
}
int SystemProcessInterface::system_processes(SystemProcess** system_procs, int* no_of_sys_processes) const {
return _impl->system_processes(system_procs, no_of_sys_processes);
}
SystemProcessInterface::SystemProcessInterface() {
_impl = NULL;
}
bool SystemProcessInterface::initialize() {
_impl = new SystemProcessInterface::SystemProcesses();
return _impl != NULL && _impl->initialize();
}
SystemProcessInterface::~SystemProcessInterface() {
if (_impl != NULL) {
delete _impl;
}
}
CPUInformationInterface::CPUInformationInterface() {
_cpu_info = NULL;
}
bool CPUInformationInterface::initialize() {
_cpu_info = new CPUInformation();
if (NULL == _cpu_info) {
return false;
}
_cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads());
_cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores());
_cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets());
_cpu_info->set_cpu_name(VM_Version_Ext::cpu_name());
_cpu_info->set_cpu_description(VM_Version_Ext::cpu_description());
return true;
}
CPUInformationInterface::~CPUInformationInterface() {
if (_cpu_info != NULL) {
if (_cpu_info->cpu_name() != NULL) {
const char* cpu_name = _cpu_info->cpu_name();
FREE_C_HEAP_ARRAY(char, cpu_name);
_cpu_info->set_cpu_name(NULL);
}
if (_cpu_info->cpu_description() != NULL) {
const char* cpu_desc = _cpu_info->cpu_description();
FREE_C_HEAP_ARRAY(char, cpu_desc);
_cpu_info->set_cpu_description(NULL);
}
delete _cpu_info;
}
}
int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {
if (NULL == _cpu_info) {
return OS_ERR;
}
cpu_info = *_cpu_info; // shallow copy assignment
return OS_OK;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,756 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "jvm.h"
#include "memory/allocation.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/os_perf.hpp"
#include "os_solaris.inline.hpp"
#include "utilities/macros.hpp"
#include CPU_HEADER(vm_version_ext)
#include <sys/types.h>
#include <procfs.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <fcntl.h>
#include <kstat.h>
#include <unistd.h>
#include <string.h>
#include <sys/sysinfo.h>
#include <sys/lwp.h>
#include <pthread.h>
#include <time.h>
#include <utmpx.h>
#include <dlfcn.h>
#include <sys/loadavg.h>
#include <limits.h>
static const double NANOS_PER_SEC = 1000000000.0;
struct CPUPerfTicks {
kstat_t* kstat;
uint64_t last_idle;
uint64_t last_total;
double last_ratio;
};
struct CPUPerfCounters {
int nProcs;
CPUPerfTicks* jvmTicks;
kstat_ctl_t* kstat_ctrl;
};
static int get_info(const char* path, void* info, size_t s, off_t o) {
assert(path != NULL, "path is NULL!");
assert(info != NULL, "info is NULL!");
int fd = -1;
if ((fd = open(path, O_RDONLY)) < 0) {
return OS_ERR;
}
if (pread(fd, info, s, o) != s) {
close(fd);
return OS_ERR;
}
close(fd);
return OS_OK;
}
static int get_psinfo2(void* info, size_t s, off_t o) {
return get_info("/proc/self/psinfo", info, s, o);
}
static int get_psinfo(psinfo_t* info) {
return get_psinfo2(info, sizeof(*info), 0);
}
static int get_psinfo(char* file, psinfo_t* info) {
assert(file != NULL, "file is NULL!");
assert(info != NULL, "info is NULL!");
return get_info(file, info, sizeof(*info), 0);
}
static int get_usage(prusage_t* usage) {
assert(usage != NULL, "usage is NULL!");
return get_info("/proc/self/usage", usage, sizeof(*usage), 0);
}
static int read_cpustat(kstat_ctl_t* kstat_ctrl, CPUPerfTicks* load, cpu_stat_t* cpu_stat) {
assert(kstat_ctrl != NULL, "kstat_ctrl pointer is NULL!");
assert(load != NULL, "load pointer is NULL!");
assert(cpu_stat != NULL, "cpu_stat pointer is NULL!");
if (load->kstat == NULL) {
// no handle.
return OS_ERR;
}
if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == OS_ERR) {
// disable handle for this CPU
load->kstat = NULL;
return OS_ERR;
}
return OS_OK;
}
static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters) {
assert(counters != NULL, "counters pointer is NULL!");
cpu_stat_t cpu_stat = {0};
if (which_logical_cpu >= counters->nProcs) {
return .0;
}
CPUPerfTicks load = counters->jvmTicks[which_logical_cpu];
if (read_cpustat(counters->kstat_ctrl, &load, &cpu_stat) != OS_OK) {
return .0;
}
uint_t* usage = cpu_stat.cpu_sysinfo.cpu;
if (usage == NULL) {
return .0;
}
uint64_t c_idle = usage[CPU_IDLE];
uint64_t c_total = 0;
for (int i = 0; i < CPU_STATES; i++) {
c_total += usage[i];
}
// Calculate diff against previous snapshot
uint64_t d_idle = c_idle - load.last_idle;
uint64_t d_total = c_total - load.last_total;
/** update if weve moved */
if (d_total > 0) {
// Save current values for next time around
load.last_idle = c_idle;
load.last_total = c_total;
load.last_ratio = (double) (d_total - d_idle) / d_total;
}
return load.last_ratio;
}
static int get_boot_time(uint64_t* time) {
assert(time != NULL, "time pointer is NULL!");
setutxent();
for(;;) {
struct utmpx* u;
if ((u = getutxent()) == NULL) {
break;
}
if (u->ut_type == BOOT_TIME) {
*time = u->ut_xtime;
endutxent();
return OS_OK;
}
}
endutxent();
return OS_ERR;
}
static int get_noof_context_switches(CPUPerfCounters* counters, uint64_t* switches) {
assert(switches != NULL, "switches pointer is NULL!");
assert(counters != NULL, "counter pointer is NULL!");
*switches = 0;
uint64_t s = 0;
// Collect data from all CPUs
for (int i = 0; i < counters->nProcs; i++) {
cpu_stat_t cpu_stat = {0};
CPUPerfTicks load = counters->jvmTicks[i];
if (read_cpustat(counters->kstat_ctrl, &load, &cpu_stat) == OS_OK) {
s += cpu_stat.cpu_sysinfo.pswitch;
} else {
//fail fast...
return OS_ERR;
}
}
*switches = s;
return OS_OK;
}
static int perf_context_switch_rate(CPUPerfCounters* counters, double* rate) {
assert(counters != NULL, "counters is NULL!");
assert(rate != NULL, "rate pointer is NULL!");
static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER;
static uint64_t lastTime = 0;
static uint64_t lastSwitches = 0;
static double lastRate = 0.0;
uint64_t lt = 0;
int res = 0;
if (lastTime == 0) {
uint64_t tmp;
if (get_boot_time(&tmp) < 0) {
return OS_ERR;
}
lt = tmp * 1000;
}
res = OS_OK;
pthread_mutex_lock(&contextSwitchLock);
{
uint64_t sw = 0;
clock_t t, d;
if (lastTime == 0) {
lastTime = lt;
}
t = clock();
d = t - lastTime;
if (d == 0) {
*rate = lastRate;
} else if (get_noof_context_switches(counters, &sw)== OS_OK) {
*rate = ((double)(sw - lastSwitches) / d) * 1000;
lastRate = *rate;
lastSwitches = sw;
lastTime = t;
} else {
*rate = 0.0;
res = OS_ERR;
}
if (*rate < 0.0) {
*rate = 0.0;
lastRate = 0.0;
}
}
pthread_mutex_unlock(&contextSwitchLock);
return res;
}
class CPUPerformanceInterface::CPUPerformance : public CHeapObj<mtInternal> {
friend class CPUPerformanceInterface;
private:
CPUPerfCounters _counters;
int cpu_load(int which_logical_cpu, double* cpu_load);
int context_switch_rate(double* rate);
int cpu_load_total_process(double* cpu_load);
int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad);
CPUPerformance();
~CPUPerformance();
bool initialize();
};
CPUPerformanceInterface::CPUPerformance::CPUPerformance() {
_counters.nProcs = 0;
_counters.jvmTicks = NULL;
_counters.kstat_ctrl = NULL;
}
bool CPUPerformanceInterface::CPUPerformance::initialize() {
// initialize kstat control structure,
_counters.kstat_ctrl = kstat_open();
assert(_counters.kstat_ctrl != NULL, "error initializing kstat control structure!");
if (NULL == _counters.kstat_ctrl) {
return false;
}
// Get number of CPU(s)
if ((_counters.nProcs = sysconf(_SC_NPROCESSORS_ONLN)) == OS_ERR) {
// ignore error?
_counters.nProcs = 1;
}
assert(_counters.nProcs > 0, "no CPUs detected in sysconf call!");
if (_counters.nProcs == 0) {
return false;
}
// Data structure(s) for saving CPU load (one per CPU)
size_t tick_array_size = _counters.nProcs * sizeof(CPUPerfTicks);
_counters.jvmTicks = (CPUPerfTicks*)NEW_C_HEAP_ARRAY(char, tick_array_size, mtInternal);
if (NULL == _counters.jvmTicks) {
return false;
}
memset(_counters.jvmTicks, 0, tick_array_size);
// Get kstat cpu_stat counters for every CPU
// loop over kstat to find our cpu_stat(s)
int i = 0;
for (kstat_t* kstat = _counters.kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) {
if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) {
if (kstat_read(_counters.kstat_ctrl, kstat, NULL) == OS_ERR) {
continue;
}
if (i == _counters.nProcs) {
// more cpu_stats than reported CPUs
break;
}
_counters.jvmTicks[i++].kstat = kstat;
}
}
return true;
}
CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
if (_counters.jvmTicks != NULL) {
FREE_C_HEAP_ARRAY(char, _counters.jvmTicks);
}
if (_counters.kstat_ctrl != NULL) {
kstat_close(_counters.kstat_ctrl);
}
}
int CPUPerformanceInterface::CPUPerformance::cpu_load(int which_logical_cpu, double* cpu_load) {
assert(cpu_load != NULL, "cpu_load pointer is NULL!");
double t = .0;
if (-1 == which_logical_cpu) {
for (int i = 0; i < _counters.nProcs; i++) {
t += get_cpu_load(i, &_counters);
}
// Cap total systemload to 1.0
t = MIN2<double>((t / _counters.nProcs), 1.0);
} else {
t = MIN2<double>(get_cpu_load(which_logical_cpu, &_counters), 1.0);
}
*cpu_load = t;
return OS_OK;
}
int CPUPerformanceInterface::CPUPerformance::cpu_load_total_process(double* cpu_load) {
assert(cpu_load != NULL, "cpu_load pointer is NULL!");
psinfo_t info;
// Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s
// process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000.
if (get_psinfo2(&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) != 0) {
*cpu_load = 0.0;
return OS_ERR;
}
*cpu_load = (double) info.pr_pctcpu / 0x8000;
return OS_OK;
}
int CPUPerformanceInterface::CPUPerformance::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) {
assert(pjvmUserLoad != NULL, "pjvmUserLoad not inited");
assert(pjvmKernelLoad != NULL, "pjvmKernelLoad not inited");
assert(psystemTotalLoad != NULL, "psystemTotalLoad not inited");
static uint64_t lastTime;
static uint64_t lastUser, lastKernel;
static double lastUserRes, lastKernelRes;
pstatus_t pss;
psinfo_t info;
*pjvmKernelLoad = *pjvmUserLoad = *psystemTotalLoad = 0;
if (get_info("/proc/self/status", &pss.pr_utime, sizeof(timestruc_t)*2, offsetof(pstatus_t, pr_utime)) != 0) {
return OS_ERR;
}
if (get_psinfo(&info) != 0) {
return OS_ERR;
}
// get the total time in user, kernel and total time
// check ratios for 'lately' and multiply the 'recent load'.
uint64_t time = (info.pr_time.tv_sec * NANOS_PER_SEC) + info.pr_time.tv_nsec;
uint64_t user = (pss.pr_utime.tv_sec * NANOS_PER_SEC) + pss.pr_utime.tv_nsec;
uint64_t kernel = (pss.pr_stime.tv_sec * NANOS_PER_SEC) + pss.pr_stime.tv_nsec;
uint64_t diff = time - lastTime;
double load = (double) info.pr_pctcpu / 0x8000;
if (diff > 0) {
lastUserRes = (load * (user - lastUser)) / diff;
lastKernelRes = (load * (kernel - lastKernel)) / diff;
// BUG9182835 - patch for clamping these values to sane ones.
lastUserRes = MIN2<double>(1, lastUserRes);
lastUserRes = MAX2<double>(0, lastUserRes);
lastKernelRes = MIN2<double>(1, lastKernelRes);
lastKernelRes = MAX2<double>(0, lastKernelRes);
}
double t = .0;
cpu_load(-1, &t);
// clamp at user+system and 1.0
if (lastUserRes + lastKernelRes > t) {
t = MIN2<double>(lastUserRes + lastKernelRes, 1.0);
}
*pjvmUserLoad = lastUserRes;
*pjvmKernelLoad = lastKernelRes;
*psystemTotalLoad = t;
lastTime = time;
lastUser = user;
lastKernel = kernel;
return OS_OK;
}
int CPUPerformanceInterface::CPUPerformance::context_switch_rate(double* rate) {
return perf_context_switch_rate(&_counters, rate);
}
CPUPerformanceInterface::CPUPerformanceInterface() {
_impl = NULL;
}
bool CPUPerformanceInterface::initialize() {
_impl = new CPUPerformanceInterface::CPUPerformance();
return _impl != NULL && _impl->initialize();
}
CPUPerformanceInterface::~CPUPerformanceInterface(void) {
if (_impl != NULL) {
delete _impl;
}
}
int CPUPerformanceInterface::cpu_load(int which_logical_cpu, double* cpu_load) const {
return _impl->cpu_load(which_logical_cpu, cpu_load);
}
int CPUPerformanceInterface::cpu_load_total_process(double* cpu_load) const {
return _impl->cpu_load_total_process(cpu_load);
}
int CPUPerformanceInterface::cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad) const {
return _impl->cpu_loads_process(pjvmUserLoad, pjvmKernelLoad, psystemTotalLoad);
}
int CPUPerformanceInterface::context_switch_rate(double* rate) const {
return _impl->context_switch_rate(rate);
}
class SystemProcessInterface::SystemProcesses : public CHeapObj<mtInternal> {
friend class SystemProcessInterface;
private:
class ProcessIterator : public CHeapObj<mtInternal> {
friend class SystemProcessInterface::SystemProcesses;
private:
DIR* _dir;
struct dirent* _entry;
bool _valid;
ProcessIterator();
~ProcessIterator();
bool initialize();
bool is_valid() const { return _valid; }
bool is_valid_entry(struct dirent* const entry) const;
bool is_dir(const char* const name) const;
char* allocate_string(const char* const str) const;
int current(SystemProcess* const process_info);
int next_process();
};
ProcessIterator* _iterator;
SystemProcesses();
bool initialize();
~SystemProcesses();
//information about system processes
int system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const;
};
bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_dir(const char* name) const {
struct stat64 mystat;
int ret_val = 0;
ret_val = ::stat64(name, &mystat);
if (ret_val < 0) {
return false;
}
ret_val = S_ISDIR(mystat.st_mode);
return ret_val > 0;
}
// if it has a numeric name, is a directory and has a 'psinfo' file in it
bool SystemProcessInterface::SystemProcesses::ProcessIterator::is_valid_entry(struct dirent* entry) const {
// ignore the "." and ".." directories
if ((strcmp(entry->d_name, ".") == 0) ||
(strcmp(entry->d_name, "..") == 0)) {
return false;
}
char buffer[PATH_MAX] = {0};
uint64_t size = 0;
bool result = false;
FILE *fp = NULL;
if (atoi(entry->d_name) != 0) {
jio_snprintf(buffer, PATH_MAX, "/proc/%s", entry->d_name);
if (is_dir(buffer)) {
memset(buffer, 0, PATH_MAX);
jio_snprintf(buffer, PATH_MAX, "/proc/%s/psinfo", entry->d_name);
if ((fp = fopen(buffer, "r")) != NULL) {
int nread = 0;
psinfo_t psinfo_data;
if ((nread = fread(&psinfo_data, 1, sizeof(psinfo_t), fp)) != -1) {
// only considering system process owned by root
if (psinfo_data.pr_uid == 0) {
result = true;
}
}
}
}
}
if (fp != NULL) {
fclose(fp);
}
return result;
}
char* SystemProcessInterface::SystemProcesses::ProcessIterator::allocate_string(const char* str) const {
if (str != NULL) {
size_t len = strlen(str);
char* tmp = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
strncpy(tmp, str, len);
tmp[len] = '\0';
return tmp;
}
return NULL;
}
int SystemProcessInterface::SystemProcesses::ProcessIterator::current(SystemProcess* process_info) {
if (!is_valid()) {
return OS_ERR;
}
char psinfo_path[PATH_MAX] = {0};
jio_snprintf(psinfo_path, PATH_MAX, "/proc/%s/psinfo", _entry->d_name);
FILE *fp = NULL;
if ((fp = fopen(psinfo_path, "r")) == NULL) {
return OS_ERR;
}
int nread = 0;
psinfo_t psinfo_data;
if ((nread = fread(&psinfo_data, 1, sizeof(psinfo_t), fp)) == -1) {
fclose(fp);
return OS_ERR;
}
char *exe_path = NULL;
if ((psinfo_data.pr_fname != NULL) &&
(psinfo_data.pr_psargs != NULL)) {
char *path_substring = strstr(psinfo_data.pr_psargs, psinfo_data.pr_fname);
if (path_substring != NULL) {
int len = path_substring - psinfo_data.pr_psargs;
exe_path = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
if (exe_path != NULL) {
jio_snprintf(exe_path, len, "%s", psinfo_data.pr_psargs);
exe_path[len] = '\0';
}
}
}
process_info->set_pid(atoi(_entry->d_name));
process_info->set_name(allocate_string(psinfo_data.pr_fname));
process_info->set_path(allocate_string(exe_path));
process_info->set_command_line(allocate_string(psinfo_data.pr_psargs));
if (exe_path != NULL) {
FREE_C_HEAP_ARRAY(char, exe_path);
}
if (fp != NULL) {
fclose(fp);
}
return OS_OK;
}
int SystemProcessInterface::SystemProcesses::ProcessIterator::next_process() {
struct dirent* entry;
if (!is_valid()) {
return OS_ERR;
}
do {
if ((entry = os::readdir(_dir, _entry)) == NULL) {
// error
_valid = false;
return OS_ERR;
}
} while(!is_valid_entry(_entry));
_valid = true;
return OS_OK;
}
SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() {
_dir = NULL;
_entry = NULL;
_valid = false;
}
bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() {
_dir = opendir("/proc");
_entry = (struct dirent*)NEW_C_HEAP_ARRAY(char, sizeof(struct dirent) + _PC_NAME_MAX + 1, mtInternal);
if (NULL == _entry) {
return false;
}
_valid = true;
next_process();
return true;
}
SystemProcessInterface::SystemProcesses::ProcessIterator::~ProcessIterator() {
if (_entry != NULL) {
FREE_C_HEAP_ARRAY(char, _entry);
}
if (_dir != NULL) {
closedir(_dir);
}
}
SystemProcessInterface::SystemProcesses::SystemProcesses() {
_iterator = NULL;
}
bool SystemProcessInterface::SystemProcesses::initialize() {
_iterator = new SystemProcessInterface::SystemProcesses::ProcessIterator();
return _iterator != NULL && _iterator->initialize();
}
SystemProcessInterface::SystemProcesses::~SystemProcesses() {
if (_iterator != NULL) {
delete _iterator;
}
}
int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** system_processes, int* no_of_sys_processes) const {
assert(system_processes != NULL, "system_processes pointer is NULL!");
assert(no_of_sys_processes != NULL, "system_processes counter pointer is NULL!");
assert(_iterator != NULL, "iterator is NULL!");
// initialize pointers
*no_of_sys_processes = 0;
*system_processes = NULL;
while (_iterator->is_valid()) {
SystemProcess* tmp = new SystemProcess();
_iterator->current(tmp);
//if already existing head
if (*system_processes != NULL) {
//move "first to second"
tmp->set_next(*system_processes);
}
// new head
*system_processes = tmp;
// increment
(*no_of_sys_processes)++;
// step forward
_iterator->next_process();
}
return OS_OK;
}
int SystemProcessInterface::system_processes(SystemProcess** system_procs, int* no_of_sys_processes) const {
return _impl->system_processes(system_procs, no_of_sys_processes);
}
SystemProcessInterface::SystemProcessInterface() {
_impl = NULL;
}
bool SystemProcessInterface::initialize() {
_impl = new SystemProcessInterface::SystemProcesses();
return _impl != NULL && _impl->initialize();
}
SystemProcessInterface::~SystemProcessInterface() {
if (_impl != NULL) {
delete _impl;
}
}
CPUInformationInterface::CPUInformationInterface() {
_cpu_info = NULL;
}
bool CPUInformationInterface::initialize() {
_cpu_info = new CPUInformation();
if (_cpu_info == NULL) {
return false;
}
_cpu_info->set_number_of_hardware_threads(VM_Version_Ext::number_of_threads());
_cpu_info->set_number_of_cores(VM_Version_Ext::number_of_cores());
_cpu_info->set_number_of_sockets(VM_Version_Ext::number_of_sockets());
_cpu_info->set_cpu_name(VM_Version_Ext::cpu_name());
_cpu_info->set_cpu_description(VM_Version_Ext::cpu_description());
return true;
}
CPUInformationInterface::~CPUInformationInterface() {
if (_cpu_info != NULL) {
if (_cpu_info->cpu_name() != NULL) {
const char* cpu_name = _cpu_info->cpu_name();
FREE_C_HEAP_ARRAY(char, cpu_name);
_cpu_info->set_cpu_name(NULL);
}
if (_cpu_info->cpu_description() != NULL) {
const char* cpu_desc = _cpu_info->cpu_description();
FREE_C_HEAP_ARRAY(char, cpu_desc);
_cpu_info->set_cpu_description(NULL);
}
delete _cpu_info;
}
}
int CPUInformationInterface::cpu_information(CPUInformation& cpu_info) {
if (_cpu_info == NULL) {
return OS_ERR;
}
cpu_info = *_cpu_info; // shallow copy assignment
return OS_OK;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,165 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "pdh_interface.hpp"
#include "runtime/os.hpp"
#include "utilities/macros.hpp"
// PDH API
typedef PDH_STATUS (WINAPI *PdhAddCounter_Fn)(HQUERY, LPCSTR, DWORD, HCOUNTER*);
typedef PDH_STATUS (WINAPI *PdhOpenQuery_Fn)(LPCWSTR, DWORD, HQUERY*);
typedef DWORD (WINAPI *PdhCloseQuery_Fn)(HQUERY);
typedef PDH_STATUS (WINAPI *PdhCollectQueryData_Fn)(HQUERY);
typedef DWORD (WINAPI *PdhGetFormattedCounterValue_Fn)(HCOUNTER, DWORD, LPDWORD, PPDH_FMT_COUNTERVALUE);
typedef PDH_STATUS (WINAPI *PdhEnumObjectItems_Fn)(LPCTSTR, LPCTSTR, LPCTSTR, LPTSTR, LPDWORD, LPTSTR, LPDWORD, DWORD, DWORD);
typedef PDH_STATUS (WINAPI *PdhRemoveCounter_Fn)(HCOUNTER);
typedef PDH_STATUS (WINAPI *PdhLookupPerfNameByIndex_Fn)(LPCSTR, DWORD, LPSTR, LPDWORD);
typedef PDH_STATUS (WINAPI *PdhMakeCounterPath_Fn)(PDH_COUNTER_PATH_ELEMENTS*, LPTSTR, LPDWORD, DWORD);
PdhAddCounter_Fn PdhDll::_PdhAddCounter = NULL;
PdhOpenQuery_Fn PdhDll::_PdhOpenQuery = NULL;
PdhCloseQuery_Fn PdhDll::_PdhCloseQuery = NULL;
PdhCollectQueryData_Fn PdhDll::_PdhCollectQueryData = NULL;
PdhGetFormattedCounterValue_Fn PdhDll::_PdhGetFormattedCounterValue = NULL;
PdhEnumObjectItems_Fn PdhDll::_PdhEnumObjectItems = NULL;
PdhRemoveCounter_Fn PdhDll::_PdhRemoveCounter = NULL;
PdhLookupPerfNameByIndex_Fn PdhDll::_PdhLookupPerfNameByIndex = NULL;
PdhMakeCounterPath_Fn PdhDll::_PdhMakeCounterPath = NULL;
LONG PdhDll::_critical_section = 0;
LONG PdhDll::_initialized = 0;
LONG PdhDll::_pdh_reference_count = 0;
HMODULE PdhDll::_hModule = NULL;
void PdhDll::initialize(void) {
_hModule = os::win32::load_Windows_dll("pdh.dll", NULL, 0);
if (NULL == _hModule) {
return;
}
// The 'A' at the end means the ANSI (not the UNICODE) vesions of the methods
_PdhAddCounter = (PdhAddCounter_Fn)::GetProcAddress(_hModule, "PdhAddCounterA");
_PdhOpenQuery = (PdhOpenQuery_Fn)::GetProcAddress(_hModule, "PdhOpenQueryA");
_PdhCloseQuery = (PdhCloseQuery_Fn)::GetProcAddress(_hModule, "PdhCloseQuery");
_PdhCollectQueryData = (PdhCollectQueryData_Fn)::GetProcAddress(_hModule, "PdhCollectQueryData");
_PdhGetFormattedCounterValue = (PdhGetFormattedCounterValue_Fn)::GetProcAddress(_hModule, "PdhGetFormattedCounterValue");
_PdhEnumObjectItems = (PdhEnumObjectItems_Fn)::GetProcAddress(_hModule, "PdhEnumObjectItemsA");
_PdhRemoveCounter = (PdhRemoveCounter_Fn)::GetProcAddress(_hModule, "PdhRemoveCounter");
_PdhLookupPerfNameByIndex = (PdhLookupPerfNameByIndex_Fn)::GetProcAddress(_hModule, "PdhLookupPerfNameByIndexA");
_PdhMakeCounterPath = (PdhMakeCounterPath_Fn)::GetProcAddress(_hModule, "PdhMakeCounterPathA");
InterlockedExchange(&_initialized, 1);
}
bool PdhDll::PdhDetach(void) {
LONG prev_ref_count = InterlockedExchangeAdd(&_pdh_reference_count, -1);
BOOL ret = false;
if (1 == prev_ref_count) {
if (_initialized && _hModule != NULL) {
ret = FreeLibrary(_hModule);
if (ret) {
_hModule = NULL;
_PdhAddCounter = NULL;
_PdhOpenQuery = NULL;
_PdhCloseQuery = NULL;
_PdhCollectQueryData = NULL;
_PdhGetFormattedCounterValue = NULL;
_PdhEnumObjectItems = NULL;
_PdhRemoveCounter = NULL;
_PdhLookupPerfNameByIndex = NULL;
_PdhMakeCounterPath = NULL;
InterlockedExchange(&_initialized, 0);
}
}
}
return ret != 0;
}
bool PdhDll::PdhAttach(void) {
InterlockedExchangeAdd(&_pdh_reference_count, 1);
if (1 == _initialized) {
return true;
}
while (InterlockedCompareExchange(&_critical_section, 1, 0) == 1);
if (0 == _initialized) {
initialize();
}
while (InterlockedCompareExchange(&_critical_section, 0, 1) == 0);
return (_PdhAddCounter != NULL && _PdhOpenQuery != NULL
&& _PdhCloseQuery != NULL && PdhCollectQueryData != NULL
&& _PdhGetFormattedCounterValue != NULL && _PdhEnumObjectItems != NULL
&& _PdhRemoveCounter != NULL && PdhLookupPerfNameByIndex != NULL
&& _PdhMakeCounterPath != NULL);
}
PDH_STATUS PdhDll::PdhAddCounter(HQUERY hQuery, LPCSTR szFullCounterPath, DWORD dwUserData, HCOUNTER* phCounter) {
assert(_initialized && _PdhAddCounter != NULL, "PdhAvailable() not yet called");
return _PdhAddCounter(hQuery, szFullCounterPath, dwUserData, phCounter);
}
PDH_STATUS PdhDll::PdhOpenQuery(LPCWSTR szDataSource, DWORD dwUserData, HQUERY* phQuery) {
assert(_initialized && _PdhOpenQuery != NULL, "PdhAvailable() not yet called");
return _PdhOpenQuery(szDataSource, dwUserData, phQuery);
}
DWORD PdhDll::PdhCloseQuery(HQUERY hQuery) {
assert(_initialized && _PdhCloseQuery != NULL, "PdhAvailable() not yet called");
return _PdhCloseQuery(hQuery);
}
PDH_STATUS PdhDll::PdhCollectQueryData(HQUERY hQuery) {
assert(_initialized && _PdhCollectQueryData != NULL, "PdhAvailable() not yet called");
return _PdhCollectQueryData(hQuery);
}
DWORD PdhDll::PdhGetFormattedCounterValue(HCOUNTER hCounter, DWORD dwFormat, LPDWORD lpdwType, PPDH_FMT_COUNTERVALUE pValue) {
assert(_initialized && _PdhGetFormattedCounterValue != NULL, "PdhAvailable() not yet called");
return _PdhGetFormattedCounterValue(hCounter, dwFormat, lpdwType, pValue);
}
PDH_STATUS PdhDll::PdhEnumObjectItems(LPCTSTR szDataSource, LPCTSTR szMachineName, LPCTSTR szObjectName,
LPTSTR mszCounterList, LPDWORD pcchCounterListLength, LPTSTR mszInstanceList,
LPDWORD pcchInstanceListLength, DWORD dwDetailLevel, DWORD dwFlags) {
assert(_initialized && _PdhEnumObjectItems != NULL, "PdhAvailable() not yet called");
return _PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, mszCounterList, pcchCounterListLength,
mszInstanceList, pcchInstanceListLength, dwDetailLevel, dwFlags);
}
PDH_STATUS PdhDll::PdhRemoveCounter(HCOUNTER hCounter) {
assert(_initialized && _PdhRemoveCounter != NULL, "PdhAvailable() not yet called");
return _PdhRemoveCounter(hCounter);
}
PDH_STATUS PdhDll::PdhLookupPerfNameByIndex(LPCSTR szMachineName, DWORD dwNameIndex, LPSTR szNameBuffer, LPDWORD pcchNameBufferSize) {
assert(_initialized && _PdhLookupPerfNameByIndex != NULL, "PdhAvailable() not yet called");
return _PdhLookupPerfNameByIndex(szMachineName, dwNameIndex, szNameBuffer, pcchNameBufferSize);
}
PDH_STATUS PdhDll::PdhMakeCounterPath(PDH_COUNTER_PATH_ELEMENTS* pCounterPathElements, LPTSTR szFullPathBuffer, LPDWORD pcchBufferSize, DWORD dwFlags) {
assert(_initialized && _PdhMakeCounterPath != NULL, "PdhAvailable() not yet called");
return _PdhMakeCounterPath(pCounterPathElements, szFullPathBuffer, pcchBufferSize, dwFlags);
}
bool PdhDll::PdhStatusFail(PDH_STATUS pdhStat) {
return pdhStat != ERROR_SUCCESS && pdhStat != PDH_MORE_DATA;
}

@ -0,0 +1,64 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef OS_WINDOWS_VM_PDH_INTERFACE_HPP
#define OS_WINDOWS_VM_PDH_INTERFACE_HPP
#include "memory/allocation.hpp"
#include <pdh.h>
#include <pdhmsg.h>
class PdhDll: public AllStatic {
private:
static LONG _pdh_reference_count;
static LONG _critical_section;
static LONG _initialized;
static HMODULE _hModule;
static void initialize();
static PDH_STATUS (WINAPI *_PdhAddCounter)(HQUERY, LPCSTR, DWORD, HCOUNTER*);
static PDH_STATUS (WINAPI *_PdhOpenQuery)(LPCWSTR, DWORD, HQUERY*);
static DWORD (WINAPI *_PdhCloseQuery)(HQUERY);
static PDH_STATUS (WINAPI *_PdhCollectQueryData)(HQUERY);
static DWORD (WINAPI *_PdhGetFormattedCounterValue)(HCOUNTER, DWORD, LPDWORD, PPDH_FMT_COUNTERVALUE);
static PDH_STATUS (WINAPI *_PdhEnumObjectItems)(LPCTSTR, LPCTSTR, LPCTSTR, LPTSTR, LPDWORD, LPTSTR, LPDWORD, DWORD, DWORD);
static PDH_STATUS (WINAPI *_PdhRemoveCounter)(HCOUNTER);
static PDH_STATUS (WINAPI *_PdhLookupPerfNameByIndex)(LPCSTR, DWORD, LPSTR, LPDWORD);
static PDH_STATUS (WINAPI *_PdhMakeCounterPath)(PPDH_COUNTER_PATH_ELEMENTS, LPTSTR, LPDWORD, DWORD);
public:
static PDH_STATUS PdhAddCounter(HQUERY, LPCSTR, DWORD, HCOUNTER*);
static PDH_STATUS PdhOpenQuery(LPCWSTR, DWORD, HQUERY*);
static DWORD PdhCloseQuery(HQUERY);
static PDH_STATUS PdhCollectQueryData(HQUERY);
static DWORD PdhGetFormattedCounterValue(HCOUNTER, DWORD, LPDWORD, PPDH_FMT_COUNTERVALUE);
static PDH_STATUS PdhEnumObjectItems(LPCTSTR, LPCTSTR, LPCTSTR, LPTSTR, LPDWORD, LPTSTR, LPDWORD, DWORD, DWORD);
static PDH_STATUS PdhRemoveCounter(HCOUNTER);
static PDH_STATUS PdhLookupPerfNameByIndex(LPCSTR, DWORD, LPSTR, LPDWORD);
static PDH_STATUS PdhMakeCounterPath(PPDH_COUNTER_PATH_ELEMENTS, LPTSTR, LPDWORD, DWORD);
static bool PdhStatusFail(PDH_STATUS pdhStat);
static bool PdhAttach();
static bool PdhDetach();
};
#endif // OS_WINDOWS_VM_PDH_INTERFACE_HPP

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018, 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,6 +27,8 @@
#include "runtime/os.hpp"
extern "C" jlong _raw_rdtsc(); // In .il file
inline jlong os::rdtsc() { return _raw_rdtsc(); }
#endif // OS_CPU_SOLARIS_X86_VM_OS_SOLARIS_X86_INLINE_HPP

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2018, 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,7 @@
#include "c1/c1_ValueType.hpp"
#include "compiler/compileBroker.hpp"
#include "interpreter/linkResolver.hpp"
#include "jfr/support/jfrIntrinsics.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
@ -41,6 +42,7 @@
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/macros.hpp"
Compiler::Compiler() : AbstractCompiler(compiler_c1) {
@ -222,10 +224,10 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) {
case vmIntrinsics::_compareAndSetObject:
case vmIntrinsics::_getCharStringU:
case vmIntrinsics::_putCharStringU:
#ifdef TRACE_HAVE_INTRINSICS
#ifdef JFR_HAVE_INTRINSICS
case vmIntrinsics::_counterTime:
case vmIntrinsics::_getBufferWriter:
#if defined(_LP64) || !defined(TRACE_ID_CLASS_SHIFT)
case vmIntrinsics::_getEventWriter:
#if defined(_LP64) || !defined(TRACE_ID_SHIFT)
case vmIntrinsics::_getClassId:
#endif
#endif

@ -35,6 +35,7 @@
#include "ci/ciUtilities.inline.hpp"
#include "compiler/compileBroker.hpp"
#include "interpreter/bytecode.hpp"
#include "jfr/jfrEvents.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/sharedRuntime.hpp"
@ -4300,6 +4301,30 @@ void GraphBuilder::append_char_access(ciMethod* callee, bool is_store) {
}
}
static void post_inlining_event(EventCompilerInlining* event,
int compile_id,
const char* msg,
bool success,
int bci,
ciMethod* caller,
ciMethod* callee) {
assert(caller != NULL, "invariant");
assert(callee != NULL, "invariant");
assert(event != NULL, "invariant");
assert(event->should_commit(), "invariant");
JfrStructCalleeMethod callee_struct;
callee_struct.set_type(callee->holder()->name()->as_utf8());
callee_struct.set_name(callee->name()->as_utf8());
callee_struct.set_descriptor(callee->signature()->as_symbol()->as_utf8());
event->set_compileId(compile_id);
event->set_message(msg);
event->set_succeeded(success);
event->set_bci(bci);
event->set_caller(caller->get_Method());
event->set_callee(callee_struct);
event->commit();
}
void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool success) {
CompileLog* log = compilation()->log();
if (log != NULL) {
@ -4315,18 +4340,10 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes
log->inline_fail("reason unknown");
}
}
#if INCLUDE_TRACE
EventCompilerInlining event;
if (event.should_commit()) {
event.set_compileId(compilation()->env()->task()->compile_id());
event.set_message(msg);
event.set_succeeded(success);
event.set_bci(bci());
event.set_caller(method()->get_Method());
event.set_callee(callee->to_trace_struct());
event.commit();
post_inlining_event(&event, compilation()->env()->task()->compile_id(), msg, success, bci(), method(), callee);
}
#endif // INCLUDE_TRACE
CompileTask::print_inlining_ul(callee, scope()->level(), bci(), msg);

@ -42,9 +42,6 @@
#include "runtime/vm_version.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/macros.hpp"
#ifdef TRACE_HAVE_INTRINSICS
#include "trace/traceMacros.hpp"
#endif
#ifdef ASSERT
#define __ gen()->lir(__FILE__, __LINE__)->
@ -2916,7 +2913,7 @@ void LIRGenerator::do_IfOp(IfOp* x) {
__ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg, as_BasicType(x->x()->type()));
}
#ifdef TRACE_HAVE_INTRINSICS
#ifdef JFR_HAVE_INTRINSICS
void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) {
CodeEmitInfo* info = state_for(x);
CodeEmitInfo* info2 = new CodeEmitInfo(info); // Clone for the second null check
@ -2928,7 +2925,7 @@ void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) {
LIR_Opr klass = new_register(T_METADATA);
__ move(new LIR_Address(arg.result(), java_lang_Class::klass_offset_in_bytes(), T_ADDRESS), klass, info);
LIR_Opr id = new_register(T_LONG);
ByteSize offset = TRACE_KLASS_TRACE_ID_OFFSET;
ByteSize offset = KLASS_TRACE_ID_OFFSET;
LIR_Address* trace_id_addr = new LIR_Address(klass, in_bytes(offset), T_LONG);
__ move(trace_id_addr, id);
@ -2938,18 +2935,18 @@ void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) {
#ifdef TRACE_ID_META_BITS
__ logical_and(id, LIR_OprFact::longConst(~TRACE_ID_META_BITS), id);
#endif
#ifdef TRACE_ID_CLASS_SHIFT
__ unsigned_shift_right(id, TRACE_ID_CLASS_SHIFT, id);
#ifdef TRACE_ID_SHIFT
__ unsigned_shift_right(id, TRACE_ID_SHIFT, id);
#endif
__ move(id, rlock_result(x));
}
void LIRGenerator::do_getBufferWriter(Intrinsic* x) {
void LIRGenerator::do_getEventWriter(Intrinsic* x) {
LabelObj* L_end = new LabelObj();
LIR_Address* jobj_addr = new LIR_Address(getThreadPointer(),
in_bytes(TRACE_THREAD_DATA_WRITER_OFFSET),
in_bytes(THREAD_LOCAL_WRITER_OFFSET_JFR),
T_OBJECT);
LIR_Opr result = rlock_result(x);
__ move_wide(jobj_addr, result);
@ -2987,15 +2984,15 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) {
break;
}
#ifdef TRACE_HAVE_INTRINSICS
#ifdef JFR_HAVE_INTRINSICS
case vmIntrinsics::_getClassId:
do_ClassIDIntrinsic(x);
break;
case vmIntrinsics::_getBufferWriter:
do_getBufferWriter(x);
case vmIntrinsics::_getEventWriter:
do_getEventWriter(x);
break;
case vmIntrinsics::_counterTime:
do_RuntimeCall(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), x);
do_RuntimeCall(CAST_FROM_FN_PTR(address, JFR_TIME_FUNCTION), x);
break;
#endif

@ -30,6 +30,7 @@
#include "c1/c1_LIR.hpp"
#include "ci/ciMethodData.hpp"
#include "gc/shared/barrierSet.hpp"
#include "jfr/support/jfrIntrinsics.hpp"
#include "utilities/macros.hpp"
#include "utilities/sizes.hpp"
@ -459,9 +460,9 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
SwitchRangeArray* create_lookup_ranges(LookupSwitch* x);
void do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux);
#ifdef TRACE_HAVE_INTRINSICS
#ifdef JFR_HAVE_INTRINSICS
void do_ClassIDIntrinsic(Intrinsic* x);
void do_getBufferWriter(Intrinsic* x);
void do_getEventWriter(Intrinsic* x);
#endif
void do_RuntimeCall(address routine, Intrinsic* x);

@ -43,6 +43,7 @@
#include "gc/shared/collectedHeap.hpp"
#include "interpreter/bytecode.hpp"
#include "interpreter/interpreter.hpp"
#include "jfr/support/jfrIntrinsics.hpp"
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
@ -320,8 +321,8 @@ const char* Runtime1::name_for_address(address entry) {
FUNCTION_CASE(entry, SharedRuntime::dtrace_method_exit);
FUNCTION_CASE(entry, is_instance_of);
FUNCTION_CASE(entry, trace_block_entry);
#ifdef TRACE_HAVE_INTRINSICS
FUNCTION_CASE(entry, TRACE_TIME_METHOD);
#ifdef JFR_HAVE_INTRINSICS
FUNCTION_CASE(entry, JFR_TIME_FUNCTION);
#endif
FUNCTION_CASE(entry, StubRoutines::updateBytesCRC32());
FUNCTION_CASE(entry, StubRoutines::updateBytesCRC32C());

@ -42,6 +42,7 @@
#include "compiler/disassembler.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "interpreter/linkResolver.hpp"
#include "jfr/jfrEvents.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
@ -60,7 +61,6 @@
#include "runtime/safepointVerifiers.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/thread.inline.hpp"
#include "trace/tracing.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/macros.hpp"
#ifdef COMPILER1
@ -1144,7 +1144,6 @@ void ciEnv::record_failure(const char* reason) {
}
void ciEnv::report_failure(const char* reason) {
// Create and fire JFR event
EventCompilationFailure event;
if (event.should_commit()) {
event.set_compileId(compile_id());

@ -48,7 +48,6 @@
#include "runtime/deoptimization.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/xmlstream.hpp"
#include "trace/tracing.hpp"
#ifdef COMPILER2
#include "ci/bcEscapeAnalyzer.hpp"
#include "ci/ciTypeFlow.hpp"
@ -1495,13 +1494,3 @@ bool ciMethod::is_consistent_info(ciMethod* declared_method, ciMethod* resolved_
}
// ------------------------------------------------------------------
#if INCLUDE_TRACE
TraceStructCalleeMethod ciMethod::to_trace_struct() const {
TraceStructCalleeMethod result;
result.set_type(holder()->name()->as_utf8());
result.set_name(name()->as_utf8());
result.set_descriptor(signature()->as_symbol()->as_utf8());
return result;
}
#endif

@ -32,7 +32,6 @@
#include "compiler/methodLiveness.hpp"
#include "prims/methodHandles.hpp"
#include "utilities/bitMap.hpp"
#include "trace/tracing.hpp"
class ciMethodBlocks;
class MethodLiveness;
@ -362,10 +361,6 @@ class ciMethod : public ciMetadata {
void print_short_name(outputStream* st = tty);
static bool is_consistent_info(ciMethod* declared_method, ciMethod* resolved_method);
#if INCLUDE_TRACE
TraceStructCalleeMethod to_trace_struct() const;
#endif
};
#endif // SHARE_VM_CI_CIMETHOD_HPP

@ -67,7 +67,6 @@
#include "runtime/timer.hpp"
#include "services/classLoadingService.hpp"
#include "services/threadService.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/align.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/copy.hpp"
@ -80,6 +79,9 @@
#if INCLUDE_CDS
#include "classfile/systemDictionaryShared.hpp"
#endif
#if INCLUDE_JFR
#include "jfr/support/jfrTraceIdExtension.hpp"
#endif
// We generally try to create the oops directly when parsing, rather than
// allocating temporary data structures and copying the bytes twice. A
@ -5639,7 +5641,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa
}
}
TRACE_INIT_ID(ik);
JFR_ONLY(INIT_ID(ik);)
// If we reach here, all is well.
// Now remove the InstanceKlass* from the _klass_to_deallocate field

@ -76,8 +76,10 @@
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#if INCLUDE_TRACE
#include "trace/tracing.hpp"
#include "utilities/ticks.hpp"
#if INCLUDE_JFR
#include "jfr/jfr.hpp"
#include "jfr/jfrEvents.hpp"
#endif
volatile size_t ClassLoaderDataGraph::_num_array_classes = 0;
@ -161,7 +163,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous) :
NOT_PRODUCT(_dependency_count = 0); // number of class loader dependencies
TRACE_INIT_ID(this);
JFR_ONLY(INIT_ID(this);)
}
ClassLoaderData::ChunkedHandleList::~ChunkedHandleList() {
@ -1276,6 +1278,28 @@ bool ClassLoaderDataGraph::contains_loader_data(ClassLoaderData* loader_data) {
}
#endif // PRODUCT
#if INCLUDE_JFR
static Ticks class_unload_time;
static void post_class_unload_event(Klass* const k) {
assert(k != NULL, "invariant");
EventClassUnload event(UNTIMED);
event.set_endtime(class_unload_time);
event.set_unloadedClass(k);
event.set_definingClassLoader(k->class_loader_data());
event.commit();
}
static void post_class_unload_events() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
if (Jfr::is_enabled()) {
if (EventClassUnload::is_enabled()) {
class_unload_time = Ticks::now();
ClassLoaderDataGraph::classes_unloading_do(&post_class_unload_event);
}
Jfr::on_unloading_classes();
}
}
#endif // INCLUDE_JFR
// Move class loader data from main list to the unloaded list for unloading
// and deallocation later.
@ -1353,8 +1377,7 @@ bool ClassLoaderDataGraph::do_unloading(bool clean_previous_versions) {
}
data = data->next();
}
post_class_unload_events();
JFR_ONLY(post_class_unload_events();)
}
log_debug(class, loader, data)("do_unloading: loaders processed %u, loaders removed %u", loaders_processed, loaders_removed);
@ -1393,20 +1416,6 @@ int ClassLoaderDataGraph::resize_if_needed() {
return resized;
}
void ClassLoaderDataGraph::post_class_unload_events() {
#if INCLUDE_TRACE
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
if (Tracing::enabled()) {
if (Tracing::is_event_enabled(TraceClassUnloadEvent)) {
assert(_unloading != NULL, "need class loader data unload list!");
_class_unload_time = Ticks::now();
classes_unloading_do(&class_unload_event);
}
Tracing::on_unloading_classes();
}
#endif
}
ClassLoaderDataGraphKlassIteratorAtomic::ClassLoaderDataGraphKlassIteratorAtomic()
: _next_klass(NULL) {
ClassLoaderData* cld = ClassLoaderDataGraph::_head;
@ -1490,20 +1499,3 @@ void ClassLoaderDataGraph::print_on(outputStream * const out) {
}
}
#endif // PRODUCT
#if INCLUDE_TRACE
Ticks ClassLoaderDataGraph::_class_unload_time;
void ClassLoaderDataGraph::class_unload_event(Klass* const k) {
assert(k != NULL, "invariant");
// post class unload event
EventClassUnload event(UNTIMED);
event.set_endtime(_class_unload_time);
event.set_unloadedClass(k);
event.set_definingClassLoader(k->class_loader_data());
event.commit();
}
#endif // INCLUDE_TRACE

@ -31,13 +31,13 @@
#include "oops/oopHandle.hpp"
#include "oops/weakHandle.hpp"
#include "runtime/mutex.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_TRACE
#include "utilities/ticks.hpp"
#if INCLUDE_JFR
#include "jfr/support/jfrTraceIdExtension.hpp"
#endif
//
// A class loader represents a linkset. Conceptually, a linkset identifies
// the complete transitive closure of resolved links that a dynamic linker can
@ -85,7 +85,6 @@ class ClassLoaderDataGraph : public AllStatic {
static ClassLoaderData* add_to_graph(Handle class_loader, bool anonymous);
static ClassLoaderData* add(Handle class_loader, bool anonymous);
static void post_class_unload_events();
public:
static ClassLoaderData* find_or_create(Handle class_loader);
static void purge();
@ -167,12 +166,6 @@ class ClassLoaderDataGraph : public AllStatic {
#ifndef PRODUCT
static bool contains_loader_data(ClassLoaderData* loader_data);
#endif
#if INCLUDE_TRACE
private:
static Ticks _class_unload_time;
static void class_unload_event(Klass* const k);
#endif
};
// ClassLoaderData class
@ -268,7 +261,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
// JFR support
Klass* _class_loader_klass;
Symbol* _class_loader_name;
TRACE_DEFINE_TRACE_ID_FIELD;
JFR_ONLY(DEFINE_TRACE_ID_FIELD;)
void set_next(ClassLoaderData* next) { _next = next; }
ClassLoaderData* next() const { return _next; }
@ -410,7 +403,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
Klass* class_loader_klass() const { return _class_loader_klass; }
Symbol* class_loader_name() const { return _class_loader_name; }
TRACE_DEFINE_TRACE_ID_METHODS;
JFR_ONLY(DEFINE_TRACE_ID_METHODS;)
};
// An iterator that distributes Klasses to parallel worker threads.

@ -35,7 +35,11 @@
#include "prims/jvmtiEnvBase.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
#include "runtime/handles.inline.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_JFR
#include "jfr/support/jfrKlassExtension.hpp"
#endif
// called during initial loading of a shared class
InstanceKlass* KlassFactory::check_shared_class_file_load_hook(
@ -228,7 +232,7 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream,
result->store_fingerprint(stream->compute_fingerprint());
}
TRACE_KLASS_CREATION(result, parser, THREAD);
JFR_ONLY(ON_KLASS_CREATION(result, parser, THREAD);)
#if INCLUDE_CDS
if (DumpSharedSpaces) {

@ -33,7 +33,6 @@
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/safepoint.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/events.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.inline.hpp"
@ -215,7 +214,7 @@ void ModuleEntry::purge_reads() {
}
}
void ModuleEntry::module_reads_do(ModuleClosure* const f) {
void ModuleEntry::module_reads_do(ModuleClosure* f) {
assert_locked_or_safepoint(Module_lock);
assert(f != NULL, "invariant");
@ -279,7 +278,7 @@ ModuleEntry* ModuleEntry::new_unnamed_module_entry(Handle module_handle, ClassLo
entry->set_loader_data(cld);
entry->_is_open = true;
TRACE_INIT_ID(entry);
JFR_ONLY(INIT_ID(entry);)
return entry;
}
@ -367,7 +366,7 @@ ModuleEntry* ModuleEntryTable::new_entry(unsigned int hash, Handle module_handle
}
}
TRACE_INIT_ID(entry);
JFR_ONLY(INIT_ID(entry);)
return entry;
}

@ -32,10 +32,13 @@
#include "oops/symbol.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/mutexLocker.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#if INCLUDE_JFR
#include "jfr/support/jfrTraceIdExtension.hpp"
#endif
#define UNNAMED_MODULE "Unnamed Module"
#define JAVAPKG "java"
@ -69,7 +72,7 @@ private:
bool _must_walk_reads; // walk module's reads list at GC safepoints to purge out dead modules
bool _is_open; // whether the packages in the module are all unqualifiedly exported
bool _is_patched; // whether the module is patched via --patch-module
TRACE_DEFINE_TRACE_ID_FIELD;
JFR_ONLY(DEFINE_TRACE_ID_FIELD;)
enum {MODULE_READS_SIZE = 101}; // Initial size of list of modules that the module can read.
public:
@ -164,8 +167,6 @@ public:
// iteration support for readability
void module_reads_do(ModuleClosure* const f);
TRACE_DEFINE_TRACE_ID_METHODS;
// Purge dead weak references out of reads list when any given class loader is unloaded.
void purge_reads();
void delete_reads();
@ -178,12 +179,14 @@ public:
void print(outputStream* st = tty);
void verify();
JFR_ONLY(DEFINE_TRACE_ID_METHODS;)
};
// Iterator interface
class ModuleClosure: public StackObj {
public:
virtual void do_module(ModuleEntry* const module) = 0;
virtual void do_module(ModuleEntry* module) = 0;
};

@ -29,7 +29,6 @@
#include "memory/resourceArea.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/events.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.inline.hpp"
@ -200,7 +199,7 @@ PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, Modu
assert(Module_lock->owned_by_self(), "should have the Module_lock");
PackageEntry* entry = (PackageEntry*)Hashtable<Symbol*, mtModule>::allocate_new_entry(hash, name);
TRACE_INIT_ID(entry);
JFR_ONLY(INIT_ID(entry);)
// Initialize fields specific to a PackageEntry
entry->init();
@ -283,7 +282,7 @@ void PackageEntryTable::verify_javabase_packages(GrowableArray<Symbol*> *pkg_lis
}
// iteration of qualified exports
void PackageEntry::package_exports_do(ModuleClosure* const f) {
void PackageEntry::package_exports_do(ModuleClosure* f) {
assert_locked_or_safepoint(Module_lock);
assert(f != NULL, "invariant");

@ -29,7 +29,12 @@
#include "oops/symbol.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#if INCLUDE_JFR
#include "jfr/support/jfrTraceIdExtension.hpp"
#endif
// A PackageEntry basically represents a Java package. It contains:
// - Symbol* containing the package's name.
@ -104,7 +109,7 @@ private:
// Contains list of modules this package is qualifiedly exported to. Access
// to this list is protected by the Module_lock.
GrowableArray<ModuleEntry*>* _qualified_exports;
TRACE_DEFINE_TRACE_ID_FIELD;
JFR_ONLY(DEFINE_TRACE_ID_FIELD;)
// Initial size of a package entry's list of qualified exports.
enum {QUAL_EXP_SIZE = 43};
@ -197,9 +202,9 @@ public:
}
// iteration of qualified exports
void package_exports_do(ModuleClosure* const f);
void package_exports_do(ModuleClosure* f);
TRACE_DEFINE_TRACE_ID_METHODS;
JFR_ONLY(DEFINE_TRACE_ID_METHODS;)
// Purge dead weak references out of exported list when any given class loader is unloaded.
void purge_qualified_exports();

@ -47,6 +47,7 @@
#include "gc/shared/oopStorage.inline.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "interpreter/interpreter.hpp"
#include "jfr/jfrEvents.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/filemap.hpp"
@ -81,7 +82,6 @@
#include "services/classLoadingService.hpp"
#include "services/diagnosticCommand.hpp"
#include "services/threadService.hpp"
#include "trace/tracing.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_CDS
#include "classfile/systemDictionaryShared.hpp"
@ -623,32 +623,16 @@ InstanceKlass* SystemDictionary::handle_parallel_super_load(
return NULL;
}
static void post_class_load_event(EventClassLoad* event,
const InstanceKlass* k,
const ClassLoaderData* init_cld) {
#if INCLUDE_TRACE
static void post_class_load_event(EventClassLoad* event, const InstanceKlass* k, const ClassLoaderData* init_cld) {
assert(event != NULL, "invariant");
assert(k != NULL, "invariant");
if (event->should_commit()) {
event->set_loadedClass(k);
event->set_definingClassLoader(k->class_loader_data());
event->set_initiatingClassLoader(init_cld);
event->commit();
}
#endif // INCLUDE_TRACE
assert(event->should_commit(), "invariant");
event->set_loadedClass(k);
event->set_definingClassLoader(k->class_loader_data());
event->set_initiatingClassLoader(init_cld);
event->commit();
}
static void class_define_event(InstanceKlass* k,
const ClassLoaderData* def_cld) {
#if INCLUDE_TRACE
EventClassDefine event;
if (event.should_commit()) {
event.set_definedClass(k);
event.set_definingClassLoader(def_cld);
event.commit();
}
#endif // INCLUDE_TRACE
}
// Be careful when modifying this code: once you have run
// placeholders()->find_and_add(PlaceholderTable::LOAD_INSTANCE),
@ -881,9 +865,9 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
if (HAS_PENDING_EXCEPTION || k == NULL) {
return NULL;
}
post_class_load_event(&class_load_start_event, k, loader_data);
if (class_load_start_event.should_commit()) {
post_class_load_event(&class_load_start_event, k, loader_data);
}
#ifdef ASSERT
{
ClassLoaderData* loader_data = k->class_loader_data();
@ -1045,8 +1029,9 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
assert(THREAD->is_Java_thread(), "thread->is_Java_thread()");
JvmtiExport::post_class_load((JavaThread *) THREAD, k);
}
post_class_load_event(&class_load_start_event, k, loader_data);
if (class_load_start_event.should_commit()) {
post_class_load_event(&class_load_start_event, k, loader_data);
}
}
assert(host_klass != NULL || NULL == cp_patches,
"cp_patches only found with host_klass");
@ -1558,6 +1543,15 @@ InstanceKlass* SystemDictionary::load_instance_class(Symbol* class_name, Handle
}
}
static void post_class_define_event(InstanceKlass* k, const ClassLoaderData* def_cld) {
EventClassDefine event;
if (event.should_commit()) {
event.set_definedClass(k);
event.set_definingClassLoader(def_cld);
event.commit();
}
}
void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) {
HandleMark hm(THREAD);
@ -1626,7 +1620,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, TRAPS) {
JvmtiExport::post_class_load((JavaThread *) THREAD, k);
}
class_define_event(k, loader_data);
post_class_define_event(k, loader_data);
}
// Support parallel classloading

@ -350,7 +350,7 @@ vmIntrinsics::ID vmIntrinsics::for_raw_conversion(BasicType src, BasicType dest)
bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) {
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
switch(id) {
#ifdef TRACE_HAVE_INTRINSICS
#ifdef JFR_HAVE_INTRINSICS
case vmIntrinsics::_counterTime:
#endif
case vmIntrinsics::_currentTimeMillis:
@ -388,7 +388,7 @@ bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) {
bool vmIntrinsics::can_trap(vmIntrinsics::ID id) {
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
switch(id) {
#ifdef TRACE_HAVE_INTRINSICS
#ifdef JFR_HAVE_INTRINSICS
case vmIntrinsics::_counterTime:
case vmIntrinsics::_getClassId:
#endif
@ -424,7 +424,7 @@ bool vmIntrinsics::can_trap(vmIntrinsics::ID id) {
bool vmIntrinsics::should_be_pinned(vmIntrinsics::ID id) {
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
switch(id) {
#ifdef TRACE_HAVE_INTRINSICS
#ifdef JFR_HAVE_INTRINSICS
case vmIntrinsics::_counterTime:
#endif
case vmIntrinsics::_currentTimeMillis:

@ -26,10 +26,12 @@
#define SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
#include "classfile/moduleEntry.hpp"
#include "oops/symbol.hpp"
#include "memory/iterator.hpp"
#include "trace/traceMacros.hpp"
#include "jfr/support/jfrIntrinsics.hpp"
#include "jvmci/vmSymbols_jvmci.hpp"
#include "memory/iterator.hpp"
#include "oops/symbol.hpp"
#include "utilities/macros.hpp"
// The class vmSymbols is a name space for fast lookup of
// symbols commonly used in the VM.
@ -640,8 +642,8 @@
/* forEachRemaining support */ \
template(java_util_stream_StreamsRangeIntSpliterator, "java/util/stream/Streams$RangeIntSpliterator") \
\
/* trace signatures */ \
TRACE_TEMPLATES(template) \
/* jfr signatures */ \
JFR_TEMPLATES(template) \
\
/* cds */ \
template(jdk_internal_loader_ClassLoaders, "jdk/internal/loader/ClassLoaders") \
@ -827,7 +829,7 @@
do_intrinsic(_nanoTime, java_lang_System, nanoTime_name, void_long_signature, F_S) \
do_name( nanoTime_name, "nanoTime") \
\
TRACE_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias) \
JFR_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias) \
\
do_intrinsic(_arraycopy, java_lang_System, arraycopy_name, arraycopy_signature, F_S) \
do_name( arraycopy_name, "arraycopy") \

@ -33,6 +33,7 @@
#include "code/nmethod.hpp"
#include "code/pcDesc.hpp"
#include "compiler/compileBroker.hpp"
#include "jfr/jfrEvents.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
@ -53,7 +54,6 @@
#include "runtime/sweeper.hpp"
#include "runtime/vmThread.hpp"
#include "services/memoryService.hpp"
#include "trace/tracing.hpp"
#include "utilities/align.hpp"
#include "utilities/vmError.hpp"
#include "utilities/xmlstream.hpp"

@ -35,6 +35,7 @@
#include "compiler/compilerOracle.hpp"
#include "compiler/directivesParser.hpp"
#include "interpreter/linkResolver.hpp"
#include "jfr/jfrEvents.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
@ -57,11 +58,11 @@
#include "runtime/sweeper.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/vframe.inline.hpp"
#include "trace/tracing.hpp"
#include "utilities/debug.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/events.hpp"
#include "utilities/formatBuffer.hpp"
#include "utilities/macros.hpp"
#ifdef COMPILER1
#include "c1/c1_Compiler.hpp"
#endif
@ -1945,8 +1946,7 @@ static void codecache_print(outputStream* out, bool detailed) {
}
}
void CompileBroker::post_compile(CompilerThread* thread, CompileTask* task, EventCompilation& event, bool success, ciEnv* ci_env) {
void CompileBroker::post_compile(CompilerThread* thread, CompileTask* task, bool success, ciEnv* ci_env) {
if (success) {
task->mark_success();
if (ci_env != NULL) {
@ -1959,19 +1959,21 @@ void CompileBroker::post_compile(CompilerThread* thread, CompileTask* task, Even
}
}
}
// simulate crash during compilation
assert(task->compile_id() != CICrashAt, "just as planned");
if (event.should_commit()) {
event.set_method(task->method());
event.set_compileId(task->compile_id());
event.set_compileLevel(task->comp_level());
event.set_succeded(task->is_success());
event.set_isOsr(task->osr_bci() != CompileBroker::standard_entry_bci);
event.set_codeSize((task->code() == NULL) ? 0 : task->code()->total_size());
event.set_inlinedBytes(task->num_inlined_bytecodes());
event.commit();
}
}
static void post_compilation_event(EventCompilation* event, CompileTask* task) {
assert(event != NULL, "invariant");
assert(event->should_commit(), "invariant");
event->set_method(task->method());
event->set_compileId(task->compile_id());
event->set_compileLevel(task->comp_level());
event->set_succeded(task->is_success());
event->set_isOsr(task->osr_bci() != CompileBroker::standard_entry_bci);
event->set_codeSize((task->code() == NULL) ? 0 : task->code()->total_size());
event->set_inlinedBytes(task->num_inlined_bytecodes());
event->commit();
}
int DirectivesStack::_depth = 0;
@ -2066,7 +2068,10 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
compilable = ciEnv::MethodCompilable_not_at_tier;
}
}
post_compile(thread, task, event, task->code() != NULL, NULL);
post_compile(thread, task, task->code() != NULL, NULL);
if (event.should_commit()) {
post_compilation_event(&event, task);
}
} else
#endif // INCLUDE_JVMCI
@ -2123,7 +2128,10 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
ci_env.report_failure(failure_reason);
}
post_compile(thread, task, event, !ci_env.failing(), &ci_env);
post_compile(thread, task, !ci_env.failing(), &ci_env);
if (event.should_commit()) {
post_compilation_event(&event, task);
}
}
// Remove the JNI handle block after the ciEnv destructor has run in
// the previous block.

@ -30,7 +30,6 @@
#include "compiler/compileTask.hpp"
#include "compiler/compilerDirectives.hpp"
#include "runtime/perfData.hpp"
#include "trace/tracing.hpp"
#include "utilities/stack.hpp"
#if INCLUDE_JVMCI
#include "jvmci/jvmciCompiler.hpp"
@ -252,7 +251,7 @@ class CompileBroker: AllStatic {
#endif
static void invoke_compiler_on_method(CompileTask* task);
static void post_compile(CompilerThread* thread, CompileTask* task, EventCompilation& event, bool success, ciEnv* ci_env);
static void post_compile(CompilerThread* thread, CompileTask* task, bool success, ciEnv* ci_env);
static void set_last_compile(CompilerThread *thread, const methodHandle& method, bool is_osr, int comp_level);
static void push_jni_handle_block();
static void pop_jni_handle_block();

@ -86,7 +86,6 @@ class STWGCTimer;
class G1NewTracer;
class EvacuationFailedInfo;
class nmethod;
class Ticks;
class WorkGang;
class G1Allocator;
class G1ArchiveAllocator;

@ -23,12 +23,11 @@
*/
#include "precompiled.hpp"
#include "memory/allocation.inline.hpp"
#include "gc/g1/g1_globals.hpp"
#include "gc/g1/g1EvacStats.hpp"
#include "gc/shared/gcId.hpp"
#include "logging/log.hpp"
#include "trace/tracing.hpp"
#include "memory/allocation.inline.hpp"
void G1EvacStats::log_plab_allocation() {
PLABStats::log_plab_allocation();

@ -34,7 +34,6 @@
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "logging/log.hpp"
#include "utilities/ticks.inline.hpp"
class G1AdjustLiveClosure : public StackObj {
G1AdjustClosure* _adjust_closure;

@ -32,7 +32,7 @@
#include "gc/shared/gcTraceTime.inline.hpp"
#include "logging/log.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/ticks.inline.hpp"
#include "utilities/ticks.hpp"
class G1ResetHumongousClosure : public HeapRegionClosure {
G1CMBitMap* _bitmap;

@ -31,7 +31,6 @@
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/heapRegionManager.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "utilities/ticks.hpp"
class G1CollectedHeap;
class G1CMBitMap;

@ -36,7 +36,7 @@
#include "gc/shared/referenceProcessor.hpp"
#include "logging/log.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/ticks.inline.hpp"
#include "utilities/ticks.hpp"
bool G1FullGCPrepareTask::G1CalculatePointersClosure::do_heap_region(HeapRegion* hr) {
if (hr->is_humongous()) {

@ -32,7 +32,6 @@
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/heapRegionManager.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "utilities/ticks.hpp"
class G1CMBitMap;

@ -25,7 +25,7 @@
#include "precompiled.hpp"
#include "gc/g1/g1FullGCTask.hpp"
#include "logging/log.hpp"
#include "utilities/ticks.inline.hpp"
#include "utilities/ticks.hpp"
void G1FullGCTask::log_task(const char* name, uint worker_id, const Ticks& start, const Ticks& stop) {
Tickspan duration = stop - start;

@ -488,7 +488,7 @@ G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times,
G1GCParPhaseTimesTracker::~G1GCParPhaseTimesTracker() {
if (_phase_times != NULL) {
_phase_times->record_time_secs(_phase, _worker_id, TicksToTimeHelper::seconds(Ticks::now() - _start_time));
_phase_times->record_time_secs(_phase, _worker_id, (Ticks::now() - _start_time).seconds());
}
}
@ -506,7 +506,7 @@ G1EvacPhaseTimesTracker::~G1EvacPhaseTimesTracker() {
if (_phase_times != NULL) {
// Exclude trim time by increasing the start time.
_start_time += _trim_time;
_phase_times->record_or_add_objcopy_time_secs(_worker_id, TicksToTimeHelper::seconds(_trim_time));
_phase_times->record_or_add_objcopy_time_secs(_worker_id, _trim_time.seconds());
}
}

@ -0,0 +1,49 @@
/*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/heapRegion.hpp"
#include "g1HeapRegionEventSender.hpp"
#include "jfr/jfrEvents.hpp"
class DumpEventInfoClosure : public HeapRegionClosure {
public:
bool do_heap_region(HeapRegion* r) {
EventG1HeapRegionInformation evt;
evt.set_index(r->hrm_index());
evt.set_type(r->get_trace_type());
evt.set_start((uintptr_t)r->bottom());
evt.set_used(r->used());
evt.commit();
return false;
}
};
void G1HeapRegionEventSender::send_events() {
DumpEventInfoClosure c;
G1CollectedHeap::heap()->heap_region_iterate(&c);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2018, 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
@ -21,24 +21,15 @@
* questions.
*
*/
#ifndef SHARE_VM_TRACE_NOTRACEBACKEND_HPP
#define SHARE_VM_TRACE_NOTRACEBACKEND_HPP
#include "jni.h"
#include "trace/traceTime.hpp"
#ifndef SHARE_VM_GC_G1_G1HEAPREGIONEVENTSENDER_HPP
#define SHARE_VM_GC_G1_G1HEAPREGIONEVENTSENDER_HPP
class NoTraceBackend {
#include "memory/allocation.hpp"
class G1HeapRegionEventSender : public AllStatic {
public:
static TracingTime time() {
return 0;
}
static void send_events();
};
class TraceThreadData {
public:
TraceThreadData() {}
};
typedef NoTraceBackend Tracing;
#endif // SHARE_VM_TRACE_NOTRACEBACKEND_HPP
#endif // SHARE_VM_GC_G1_G1HEAPREGIONEVENTSENDER_HPP

@ -29,7 +29,6 @@
#include "gc/g1/g1RemSet.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/ticks.inline.hpp"
template <class T> void G1ParScanThreadState::do_oop_evac(T* p) {
// Reference should not be NULL here as such are never pushed to the task queue.

@ -44,11 +44,12 @@
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/os.hpp"
#include "utilities/align.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/intHisto.hpp"
#include "utilities/stack.inline.hpp"
#include "utilities/ticks.inline.hpp"
#include "utilities/ticks.hpp"
// Collects information about the overall remembered set scan progress during an evacuation.
class G1RemSetScanState : public CHeapObj<mtGC> {
@ -428,15 +429,15 @@ void G1RemSet::scan_rem_set(G1ParScanThreadState* pss, uint worker_i) {
G1GCPhaseTimes* p = _g1p->phase_times();
p->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, TicksToTimeHelper::seconds(cl.rem_set_root_scan_time()));
p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, TicksToTimeHelper::seconds(cl.rem_set_trim_partially_time()));
p->record_time_secs(G1GCPhaseTimes::ScanRS, worker_i, cl.rem_set_root_scan_time().seconds());
p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, cl.rem_set_trim_partially_time().seconds());
p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_scanned(), G1GCPhaseTimes::ScanRSScannedCards);
p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_claimed(), G1GCPhaseTimes::ScanRSClaimedCards);
p->record_thread_work_item(G1GCPhaseTimes::ScanRS, worker_i, cl.cards_skipped(), G1GCPhaseTimes::ScanRSSkippedCards);
p->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, TicksToTimeHelper::seconds(cl.strong_code_root_scan_time()));
p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, TicksToTimeHelper::seconds(cl.strong_code_root_trim_partially_time()));
p->record_time_secs(G1GCPhaseTimes::CodeRoots, worker_i, cl.strong_code_root_scan_time().seconds());
p->add_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, cl.strong_code_root_trim_partially_time().seconds());
}
// Closure used for updating rem sets. Only called during an evacuation pause.
@ -935,7 +936,7 @@ public:
"TARS " PTR_FORMAT,
region_idx,
_cm->liveness(region_idx) * HeapWordSize,
TicksToTimeHelper::seconds(time) * 1000.0,
time.seconds() * 1000.0,
marked_bytes,
p2i(hr->bottom()),
p2i(top_at_mark_start),

@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "gc/g1/heapRegionTracer.hpp"
#include "trace/tracing.hpp"
#include "jfr/jfrEvents.hpp"
void HeapRegionTracer::send_region_type_change(uint index,
G1HeapRegionTraceType::Type from,

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2018, 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,7 @@
#include "precompiled.hpp"
#include "gc/shared/ageTableTracer.hpp"
#include "gc/shared/gcId.hpp"
#include "trace/tracing.hpp"
#include "jfr/jfrEvents.hpp"
void AgeTableTracer::send_tenuring_distribution_event(uint age, size_t size) {
EventTenuringDistribution e;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2018, 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
@ -24,13 +24,16 @@
#include "precompiled.hpp"
#include "gc/shared/allocTracer.hpp"
#include "jfr/jfrEvents.hpp"
#include "runtime/handles.hpp"
#include "trace/tracing.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_JFR
#include "jfr/support/jfrAllocationTracer.hpp"
#endif
void AllocTracer::send_allocation_outside_tlab(Klass* klass, HeapWord* obj, size_t alloc_size, Thread* thread) {
TRACE_ALLOCATION(obj, alloc_size, thread);
JFR_ONLY(JfrAllocationTracer tracer(obj, alloc_size, thread);)
EventObjectAllocationOutsideTLAB event;
if (event.should_commit()) {
event.set_objectClass(klass);
@ -40,7 +43,7 @@ void AllocTracer::send_allocation_outside_tlab(Klass* klass, HeapWord* obj, size
}
void AllocTracer::send_allocation_in_new_tlab(Klass* klass, HeapWord* obj, size_t tlab_size, size_t alloc_size, Thread* thread) {
TRACE_ALLOCATION(obj, tlab_size, thread);
JFR_ONLY(JfrAllocationTracer tracer(obj, alloc_size, thread);)
EventObjectAllocationInNewTLAB event;
if (event.should_commit()) {
event.set_objectClass(klass);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, 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,8 +25,8 @@
#ifndef SHARE_VM_GC_SHARED_COPYFAILEDINFO_HPP
#define SHARE_VM_GC_SHARED_COPYFAILEDINFO_HPP
#include "jfr/support/jfrThreadId.hpp"
#include "runtime/thread.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/globalDefinitions.hpp"
class CopyFailedInfo : public CHeapObj<mtGC> {
@ -72,9 +72,9 @@ class PromotionFailedInfo : public CopyFailedInfo {
void register_copy_failure(size_t size) {
CopyFailedInfo::register_copy_failure(size);
if (_thread_trace_id == 0) {
_thread_trace_id = THREAD_TRACE_ID(Thread::current());
_thread_trace_id = JFR_THREAD_ID(Thread::current());
} else {
assert(THREAD_TRACE_ID(Thread::current()) == _thread_trace_id,
assert(JFR_THREAD_ID(Thread::current()) == _thread_trace_id,
"The PromotionFailedInfo should be thread local.");
}
}

@ -0,0 +1,159 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/gcConfiguration.hpp"
#include "memory/universe.hpp"
#include "runtime/arguments.hpp"
#include "runtime/globals.hpp"
#include "utilities/debug.hpp"
GCName GCConfiguration::young_collector() const {
if (UseG1GC) {
return G1New;
}
if (UseParallelGC) {
return ParallelScavenge;
}
if (UseConcMarkSweepGC) {
return ParNew;
}
return DefNew;
}
GCName GCConfiguration::old_collector() const {
if (UseG1GC) {
return G1Old;
}
if (UseConcMarkSweepGC) {
return ConcurrentMarkSweep;
}
if (UseParallelOldGC) {
return ParallelOld;
}
return SerialOld;
}
uint GCConfiguration::num_parallel_gc_threads() const {
return ParallelGCThreads;
}
uint GCConfiguration::num_concurrent_gc_threads() const {
return ConcGCThreads;
}
bool GCConfiguration::uses_dynamic_gc_threads() const {
return UseDynamicNumberOfGCThreads;
}
bool GCConfiguration::is_explicit_gc_concurrent() const {
return ExplicitGCInvokesConcurrent;
}
bool GCConfiguration::is_explicit_gc_disabled() const {
return DisableExplicitGC;
}
bool GCConfiguration::has_pause_target_default_value() const {
return FLAG_IS_DEFAULT(MaxGCPauseMillis);
}
uintx GCConfiguration::pause_target() const {
return MaxGCPauseMillis;
}
uintx GCConfiguration::gc_time_ratio() const {
return GCTimeRatio;
}
bool GCTLABConfiguration::uses_tlabs() const {
return UseTLAB;
}
size_t GCTLABConfiguration::min_tlab_size() const {
return MinTLABSize;
}
uint GCTLABConfiguration::tlab_refill_waste_limit() const {
return TLABRefillWasteFraction;
}
intx GCSurvivorConfiguration::max_tenuring_threshold() const {
return MaxTenuringThreshold;
}
intx GCSurvivorConfiguration::initial_tenuring_threshold() const {
return InitialTenuringThreshold;
}
size_t GCHeapConfiguration::max_size() const {
return MaxHeapSize;
}
size_t GCHeapConfiguration::min_size() const {
return Arguments::min_heap_size();
}
size_t GCHeapConfiguration::initial_size() const {
return InitialHeapSize;
}
bool GCHeapConfiguration::uses_compressed_oops() const {
return UseCompressedOops;
}
Universe::NARROW_OOP_MODE GCHeapConfiguration::narrow_oop_mode() const {
return Universe::narrow_oop_mode();
}
uint GCHeapConfiguration::object_alignment_in_bytes() const {
return ObjectAlignmentInBytes;
}
int GCHeapConfiguration::heap_address_size_in_bits() const {
return BitsPerHeapOop;
}
bool GCYoungGenerationConfiguration::has_max_size_default_value() const {
return FLAG_IS_DEFAULT(MaxNewSize);
}
uintx GCYoungGenerationConfiguration::max_size() const {
return MaxNewSize;
}
uintx GCYoungGenerationConfiguration::min_size() const {
return NewSize;
}
intx GCYoungGenerationConfiguration::new_ratio() const {
return NewRatio;
}

@ -0,0 +1,80 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef SHARE_VM_GC_SHARED_GCCONFIGURATION_HPP
#define SHARE_VM_GC_SHARED_GCCONFIGURATION_HPP
#include "gc/shared/gcName.hpp"
#include "memory/universe.hpp"
#include "utilities/globalDefinitions.hpp"
class GCConfiguration {
public:
GCName young_collector() const;
GCName old_collector() const;
uint num_parallel_gc_threads() const;
uint num_concurrent_gc_threads() const;
bool uses_dynamic_gc_threads() const;
bool is_explicit_gc_concurrent() const;
bool is_explicit_gc_disabled() const;
uintx gc_time_ratio() const;
bool has_pause_target_default_value() const;
uintx pause_target() const;
};
class GCTLABConfiguration {
public:
bool uses_tlabs() const;
size_t min_tlab_size() const;
uint tlab_refill_waste_limit() const;
};
class GCSurvivorConfiguration {
public:
intx initial_tenuring_threshold() const;
intx max_tenuring_threshold() const;
};
class GCHeapConfiguration {
public:
size_t max_size() const;
size_t min_size() const;
size_t initial_size() const;
bool uses_compressed_oops() const;
Universe::NARROW_OOP_MODE narrow_oop_mode() const;
uint object_alignment_in_bytes() const;
int heap_address_size_in_bits() const;
};
class GCYoungGenerationConfiguration {
public:
bool has_max_size_default_value() const;
uintx max_size() const;
uintx min_size() const;
intx new_ratio() const;
};
#endif // SHARE_VM_GC_SHARED_GCCONFIGURATION_HPP

@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "gc/shared/gcTimer.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/ticks.inline.hpp"
// the "time" parameter for most functions
// has a default value set by Ticks::now()
@ -376,7 +375,7 @@ public:
GCTimer gc_timer;
gc_timer.register_gc_start(1);
assert(gc_timer.gc_start() == 1, "Incorrect");
assert(gc_timer.gc_start() == Ticks(1), "Incorrect");
}
static void gc_end() {
@ -384,7 +383,7 @@ public:
gc_timer.register_gc_start(1);
gc_timer.register_gc_end(2);
assert(gc_timer.gc_end() == 2, "Incorrect");
assert(gc_timer.gc_end() == Ticks(2), "Incorrect");
}
};

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, 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
@ -35,7 +35,7 @@
#include "runtime/os.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include "utilities/ticks.inline.hpp"
#include "utilities/ticks.hpp"
#if INCLUDE_G1GC
#include "gc/g1/evacuationInfo.hpp"
#endif

@ -28,10 +28,8 @@
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTrace.hpp"
#include "gc/shared/gcWhen.hpp"
#include "jfr/jfrEvents.hpp"
#include "runtime/os.hpp"
#include "trace/traceBackend.hpp"
#include "trace/tracing.hpp"
#include "tracefiles/traceEventClasses.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_G1GC
#include "gc/g1/evacuationInfo.hpp"
@ -160,8 +158,8 @@ void OldGCTracer::send_old_gc_event() const {
}
}
static TraceStructCopyFailed to_trace_struct(const CopyFailedInfo& cf_info) {
TraceStructCopyFailed failed_info;
static JfrStructCopyFailed to_struct(const CopyFailedInfo& cf_info) {
JfrStructCopyFailed failed_info;
failed_info.set_objectCount(cf_info.failed_count());
failed_info.set_firstSize(cf_info.first_size());
failed_info.set_smallestSize(cf_info.smallest_size());
@ -173,7 +171,7 @@ void YoungGCTracer::send_promotion_failed_event(const PromotionFailedInfo& pf_in
EventPromotionFailed e;
if (e.should_commit()) {
e.set_gcId(GCId::current());
e.set_promotionFailed(to_trace_struct(pf_info));
e.set_promotionFailed(to_struct(pf_info));
e.set_thread(pf_info.thread_trace_id());
e.commit();
}
@ -231,14 +229,14 @@ void G1NewTracer::send_evacuation_failed_event(const EvacuationFailedInfo& ef_in
EventEvacuationFailed e;
if (e.should_commit()) {
e.set_gcId(GCId::current());
e.set_evacuationFailed(to_trace_struct(ef_info));
e.set_evacuationFailed(to_struct(ef_info));
e.commit();
}
}
static TraceStructG1EvacuationStatistics
static JfrStructG1EvacuationStatistics
create_g1_evacstats(unsigned gcid, const G1EvacSummary& summary) {
TraceStructG1EvacuationStatistics s;
JfrStructG1EvacuationStatistics s;
s.set_gcId(gcid);
s.set_allocated(summary.allocated() * HeapWordSize);
s.set_wasted(summary.wasted() * HeapWordSize);
@ -313,8 +311,8 @@ void G1NewTracer::send_adaptive_ihop_statistics(size_t threshold,
#endif // INCLUDE_G1GC
static TraceStructVirtualSpace to_trace_struct(const VirtualSpaceSummary& summary) {
TraceStructVirtualSpace space;
static JfrStructVirtualSpace to_struct(const VirtualSpaceSummary& summary) {
JfrStructVirtualSpace space;
space.set_start((TraceAddress)summary.start());
space.set_committedEnd((TraceAddress)summary.committed_end());
space.set_committedSize(summary.committed_size());
@ -323,8 +321,8 @@ static TraceStructVirtualSpace to_trace_struct(const VirtualSpaceSummary& summar
return space;
}
static TraceStructObjectSpace to_trace_struct(const SpaceSummary& summary) {
TraceStructObjectSpace space;
static JfrStructObjectSpace to_struct(const SpaceSummary& summary) {
JfrStructObjectSpace space;
space.set_start((TraceAddress)summary.start());
space.set_end((TraceAddress)summary.end());
space.set_used(summary.used());
@ -344,7 +342,7 @@ class GCHeapSummaryEventSender : public GCHeapSummaryVisitor {
if (e.should_commit()) {
e.set_gcId(GCId::current());
e.set_when((u1)_when);
e.set_heapSpace(to_trace_struct(heap_space));
e.set_heapSpace(to_struct(heap_space));
e.set_heapUsed(heap_summary->used());
e.commit();
}
@ -380,12 +378,12 @@ class GCHeapSummaryEventSender : public GCHeapSummaryVisitor {
e.set_gcId(GCId::current());
e.set_when((u1)_when);
e.set_oldSpace(to_trace_struct(ps_heap_summary->old()));
e.set_oldObjectSpace(to_trace_struct(ps_heap_summary->old_space()));
e.set_youngSpace(to_trace_struct(ps_heap_summary->young()));
e.set_edenSpace(to_trace_struct(ps_heap_summary->eden()));
e.set_fromSpace(to_trace_struct(ps_heap_summary->from()));
e.set_toSpace(to_trace_struct(ps_heap_summary->to()));
e.set_oldSpace(to_struct(ps_heap_summary->old()));
e.set_oldObjectSpace(to_struct(ps_heap_summary->old_space()));
e.set_youngSpace(to_struct(ps_heap_summary->young()));
e.set_edenSpace(to_struct(ps_heap_summary->eden()));
e.set_fromSpace(to_struct(ps_heap_summary->from()));
e.set_toSpace(to_struct(ps_heap_summary->to()));
e.commit();
}
}
@ -396,8 +394,8 @@ void GCTracer::send_gc_heap_summary_event(GCWhen::Type when, const GCHeapSummary
heap_summary.accept(&visitor);
}
static TraceStructMetaspaceSizes to_trace_struct(const MetaspaceSizes& sizes) {
TraceStructMetaspaceSizes meta_sizes;
static JfrStructMetaspaceSizes to_struct(const MetaspaceSizes& sizes) {
JfrStructMetaspaceSizes meta_sizes;
meta_sizes.set_committed(sizes.committed());
meta_sizes.set_used(sizes.used());
@ -412,9 +410,9 @@ void GCTracer::send_meta_space_summary_event(GCWhen::Type when, const MetaspaceS
e.set_gcId(GCId::current());
e.set_when((u1) when);
e.set_gcThreshold(meta_space_summary.capacity_until_GC());
e.set_metaspace(to_trace_struct(meta_space_summary.meta_space()));
e.set_dataSpace(to_trace_struct(meta_space_summary.data_space()));
e.set_classSpace(to_trace_struct(meta_space_summary.class_space()));
e.set_metaspace(to_struct(meta_space_summary.meta_space()));
e.set_dataSpace(to_struct(meta_space_summary.data_space()));
e.set_classSpace(to_struct(meta_space_summary.class_space()));
e.commit();
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2018, 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
@ -26,34 +26,50 @@
#include "precompiled.hpp"
#include "gc/shared/gcId.hpp"
#include "gc/shared/objectCountEventSender.hpp"
#include "jfr/jfrEvents.hpp"
#include "memory/heapInspection.hpp"
#include "trace/tracing.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include "utilities/ticks.hpp"
#if INCLUDE_SERVICES
void ObjectCountEventSender::send(const KlassInfoEntry* entry, const Ticks& timestamp) {
#if INCLUDE_TRACE
assert(Tracing::is_event_enabled(EventObjectCountAfterGC::eventId),
"Only call this method if the event is enabled");
EventObjectCountAfterGC event(UNTIMED);
event.set_gcId(GCId::current());
event.set_objectClass(entry->klass());
event.set_count(entry->count());
event.set_totalSize(entry->words() * BytesPerWord);
event.set_endtime(timestamp);
event.commit();
#endif // INCLUDE_TRACE
}
bool ObjectCountEventSender::should_send_event() {
#if INCLUDE_TRACE
return Tracing::is_event_enabled(EventObjectCountAfterGC::eventId);
#if INCLUDE_JFR
return _should_send_requestable_event || EventObjectCountAfterGC::is_enabled();
#else
return false;
#endif // INCLUDE_TRACE
#endif // INCLUDE_JFR
}
bool ObjectCountEventSender::_should_send_requestable_event = false;
void ObjectCountEventSender::enable_requestable_event() {
_should_send_requestable_event = true;
}
void ObjectCountEventSender::disable_requestable_event() {
_should_send_requestable_event = false;
}
template <typename T>
void ObjectCountEventSender::send_event_if_enabled(Klass* klass, jlong count, julong size, const Ticks& timestamp) {
T event(UNTIMED);
if (event.should_commit()) {
event.set_gcId(GCId::current());
event.set_objectClass(klass);
event.set_count(count);
event.set_totalSize(size);
event.set_endtime(timestamp);
event.commit();
}
}
void ObjectCountEventSender::send(const KlassInfoEntry* entry, const Ticks& timestamp) {
Klass* klass = entry->klass();
jlong count = entry->count();
julong total_size = entry->words() * BytesPerWord;
send_event_if_enabled<EventObjectCount>(klass, count, total_size, timestamp);
send_event_if_enabled<EventObjectCountAfterGC>(klass, count, total_size, timestamp);
}
#endif // INCLUDE_SERVICES

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2018, 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,15 +27,25 @@
#include "gc/shared/gcTrace.hpp"
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include "utilities/ticks.hpp"
#if INCLUDE_SERVICES
class KlassInfoEntry;
class Ticks;
class Klass;
class ObjectCountEventSender : public AllStatic {
static bool _should_send_requestable_event;
template <typename T>
static void send_event_if_enabled(Klass* klass, jlong count, julong size, const Ticks& timestamp);
public:
static void enable_requestable_event();
static void disable_requestable_event();
static void send(const KlassInfoEntry* entry, const Ticks& timestamp);
static bool should_send_event();
};

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, 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
@ -26,13 +26,15 @@
#include "gc/shared/weakProcessor.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/jniHandles.hpp"
#include "trace/tracing.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_JFR
#include "jfr/jfr.hpp"
#endif
void WeakProcessor::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive) {
JNIHandles::weak_oops_do(is_alive, keep_alive);
JvmtiExport::weak_oops_do(is_alive, keep_alive);
TRACE_WEAK_OOPS_DO(is_alive, keep_alive);
JFR_ONLY(Jfr::weak_oops_do(is_alive, keep_alive);)
}
void WeakProcessor::oops_do(OopClosure* closure) {

@ -0,0 +1,633 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/vmSymbols.hpp"
#include "jfr/jfr.hpp"
#include "jfr/dcmd/jfrDcmds.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#include "services/diagnosticArgument.hpp"
#include "services/diagnosticFramework.hpp"
#include "utilities/globalDefinitions.hpp"
#ifdef _WINDOWS
#define JFR_FILENAME_EXAMPLE "C:\\Users\\user\\My Recording.jfr"
#endif
#ifdef __APPLE__
#define JFR_FILENAME_EXAMPLE "/Users/user/My Recording.jfr"
#endif
#ifndef JFR_FILENAME_EXAMPLE
#define JFR_FILENAME_EXAMPLE "/home/user/My Recording.jfr"
#endif
// JNIHandle management
// ------------------------------------------------------------------
// push_jni_handle_block
//
// Push on a new block of JNI handles.
static void push_jni_handle_block(Thread* const thread) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));
// Allocate a new block for JNI handles.
// Inlined code from jni_PushLocalFrame()
JNIHandleBlock* prev_handles = thread->active_handles();
JNIHandleBlock* entry_handles = JNIHandleBlock::allocate_block(thread);
assert(entry_handles != NULL && prev_handles != NULL, "should not be NULL");
entry_handles->set_pop_frame_link(prev_handles); // make sure prev handles get gc'd.
thread->set_active_handles(entry_handles);
}
// ------------------------------------------------------------------
// pop_jni_handle_block
//
// Pop off the current block of JNI handles.
static void pop_jni_handle_block(Thread* const thread) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));
// Release our JNI handle block
JNIHandleBlock* entry_handles = thread->active_handles();
JNIHandleBlock* prev_handles = entry_handles->pop_frame_link();
// restore
thread->set_active_handles(prev_handles);
entry_handles->set_pop_frame_link(NULL);
JNIHandleBlock::release_block(entry_handles, thread); // may block
}
class JNIHandleBlockManager : public StackObj {
private:
Thread* const _thread;
public:
JNIHandleBlockManager(Thread* thread) : _thread(thread) {
push_jni_handle_block(_thread);
}
~JNIHandleBlockManager() {
pop_jni_handle_block(_thread);
}
};
static bool is_module_available(outputStream* output, TRAPS) {
return JfrJavaSupport::is_jdk_jfr_module_available(output, THREAD);
}
static bool is_disabled(outputStream* output) {
if (Jfr::is_disabled()) {
if (output != NULL) {
output->print_cr("Flight Recorder is disabled.\n");
}
return true;
}
return false;
}
static bool is_recorder_instance_created(outputStream* output) {
if (!JfrRecorder::is_created()) {
if (output != NULL) {
output->print_cr("No available recordings.\n");
output->print_cr("Use JFR.start to start a recording.\n");
}
return false;
}
return true;
}
static bool invalid_state(outputStream* out, TRAPS) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
return is_disabled(out) || !is_module_available(out, THREAD);
}
static void print_pending_exception(outputStream* output, oop throwable) {
assert(throwable != NULL, "invariant");
oop msg = java_lang_Throwable::message(throwable);
if (msg != NULL) {
char* text = java_lang_String::as_utf8_string(msg);
output->print_raw_cr(text);
}
}
static void print_message(outputStream* output, const char* message) {
if (message != NULL) {
output->print_raw(message);
}
}
static void handle_dcmd_result(outputStream* output,
const oop result,
const DCmdSource source,
TRAPS) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
assert(output != NULL, "invariant");
if (HAS_PENDING_EXCEPTION) {
print_pending_exception(output, PENDING_EXCEPTION);
// Don't clear excption on startup, JVM should fail initialization.
if (DCmd_Source_Internal != source) {
CLEAR_PENDING_EXCEPTION;
}
return;
}
assert(!HAS_PENDING_EXCEPTION, "invariant");
if (result != NULL) {
const char* result_chars = java_lang_String::as_utf8_string(result);
print_message(output, result_chars);
}
}
static oop construct_dcmd_instance(JfrJavaArguments* args, TRAPS) {
assert(args != NULL, "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
assert(args->klass() != NULL, "invariant");
args->set_name("<init>", CHECK_NULL);
args->set_signature("()V", CHECK_NULL);
JfrJavaSupport::new_object(args, CHECK_NULL);
return (oop)args->result()->get_jobject();
}
JfrDumpFlightRecordingDCmd::JfrDumpFlightRecordingDCmd(outputStream* output,
bool heap) : DCmdWithParser(output, heap),
_name("name", "Recording name, e.g. \\\"My Recording\\\"", "STRING", true, NULL),
_filename("filename", "Copy recording data to file, i.e \\\"" JFR_FILENAME_EXAMPLE "\\\"", "STRING", true),
_path_to_gc_roots("path-to-gc-roots", "Collect path to GC roots", "BOOLEAN", false, "false") {
_dcmdparser.add_dcmd_option(&_name);
_dcmdparser.add_dcmd_option(&_filename);
_dcmdparser.add_dcmd_option(&_path_to_gc_roots);
};
int JfrDumpFlightRecordingDCmd::num_arguments() {
ResourceMark rm;
JfrDumpFlightRecordingDCmd* dcmd = new JfrDumpFlightRecordingDCmd(NULL, false);
if (dcmd != NULL) {
DCmdMark mark(dcmd);
return dcmd->_dcmdparser.num_arguments();
}
return 0;
}
void JfrDumpFlightRecordingDCmd::execute(DCmdSource source, TRAPS) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
if (invalid_state(output(), THREAD) || !is_recorder_instance_created(output())) {
return;
}
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
JNIHandleBlockManager jni_handle_management(THREAD);
JavaValue result(T_OBJECT);
JfrJavaArguments constructor_args(&result);
constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdDump", CHECK);
const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK);
Handle h_dcmd_instance(THREAD, dcmd);
assert(h_dcmd_instance.not_null(), "invariant");
jstring name = NULL;
if (_name.is_set() && _name.value() != NULL) {
name = JfrJavaSupport::new_string(_name.value(), CHECK);
}
jstring filepath = NULL;
if (_filename.is_set() && _filename.value() != NULL) {
filepath = JfrJavaSupport::new_string(_filename.value(), CHECK);
}
jobject path_to_gc_roots = NULL;
if (_path_to_gc_roots.is_set()) {
path_to_gc_roots = JfrJavaSupport::new_java_lang_Boolean(_path_to_gc_roots.value(), CHECK);
}
static const char klass[] = "jdk/jfr/internal/dcmd/DCmdDump";
static const char method[] = "execute";
static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;";
JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
execute_args.set_receiver(h_dcmd_instance);
// arguments
execute_args.push_jobject(name);
execute_args.push_jobject(filepath);
execute_args.push_jobject(path_to_gc_roots);
JfrJavaSupport::call_virtual(&execute_args, THREAD);
handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD);
}
JfrCheckFlightRecordingDCmd::JfrCheckFlightRecordingDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap),
_name("name","Recording text, e.g. \\\"My Recording\\\" or omit to see all recordings","STRING",false, NULL),
_verbose("verbose","Print event settings for the recording(s)","BOOLEAN",
false, "false") {
_dcmdparser.add_dcmd_option(&_name);
_dcmdparser.add_dcmd_option(&_verbose);
};
int JfrCheckFlightRecordingDCmd::num_arguments() {
ResourceMark rm;
JfrCheckFlightRecordingDCmd* dcmd = new JfrCheckFlightRecordingDCmd(NULL, false);
if (dcmd != NULL) {
DCmdMark mark(dcmd);
return dcmd->_dcmdparser.num_arguments();
}
return 0;
}
void JfrCheckFlightRecordingDCmd::execute(DCmdSource source, TRAPS) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
if (invalid_state(output(), THREAD) || !is_recorder_instance_created(output())) {
return;
}
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
JNIHandleBlockManager jni_handle_management(THREAD);
JavaValue result(T_OBJECT);
JfrJavaArguments constructor_args(&result);
constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdCheck", CHECK);
const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK);
Handle h_dcmd_instance(THREAD, dcmd);
assert(h_dcmd_instance.not_null(), "invariant");
jstring name = NULL;
if (_name.is_set() && _name.value() != NULL) {
name = JfrJavaSupport::new_string(_name.value(), CHECK);
}
jobject verbose = NULL;
if (_verbose.is_set()) {
verbose = JfrJavaSupport::new_java_lang_Boolean(_verbose.value(), CHECK);
}
static const char klass[] = "jdk/jfr/internal/dcmd/DCmdCheck";
static const char method[] = "execute";
static const char signature[] = "(Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;";
JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
execute_args.set_receiver(h_dcmd_instance);
// arguments
execute_args.push_jobject(name);
execute_args.push_jobject(verbose);
JfrJavaSupport::call_virtual(&execute_args, THREAD);
handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD);
}
JfrStartFlightRecordingDCmd::JfrStartFlightRecordingDCmd(outputStream* output,
bool heap) : DCmdWithParser(output, heap),
_name("name", "Name that can be used to identify recording, e.g. \\\"My Recording\\\"", "STRING", false, NULL),
_settings("settings", "Settings file(s), e.g. profile or default. See JRE_HOME/lib/jfr", "STRING SET", false),
_delay("delay", "Delay recording start with (s)econds, (m)inutes), (h)ours), or (d)ays, e.g. 5h.", "NANOTIME", false, "0"),
_duration("duration", "Duration of recording in (s)econds, (m)inutes, (h)ours, or (d)ays, e.g. 300s.", "NANOTIME", false, "0"),
_filename("filename", "Resulting recording filename, e.g. \\\"" JFR_FILENAME_EXAMPLE "\\\"", "STRING", false),
_disk("disk", "Recording should be persisted to disk", "BOOLEAN", false),
_maxage("maxage", "Maximum time to keep recorded data (on disk) in (s)econds, (m)inutes, (h)ours, or (d)ays, e.g. 60m, or 0 for no limit", "NANOTIME", false, "0"),
_maxsize("maxsize", "Maximum amount of bytes to keep (on disk) in (k)B, (M)B or (G)B, e.g. 500M, or 0 for no limit", "MEMORY SIZE", false, "0"),
_dump_on_exit("dumponexit", "Dump running recording when JVM shuts down", "BOOLEAN", false),
_path_to_gc_roots("path-to-gc-roots", "Collect path to GC roots", "BOOLEAN", false, "false") {
_dcmdparser.add_dcmd_option(&_name);
_dcmdparser.add_dcmd_option(&_settings);
_dcmdparser.add_dcmd_option(&_delay);
_dcmdparser.add_dcmd_option(&_duration);
_dcmdparser.add_dcmd_option(&_disk);
_dcmdparser.add_dcmd_option(&_filename);
_dcmdparser.add_dcmd_option(&_maxage);
_dcmdparser.add_dcmd_option(&_maxsize);
_dcmdparser.add_dcmd_option(&_dump_on_exit);
_dcmdparser.add_dcmd_option(&_path_to_gc_roots);
};
int JfrStartFlightRecordingDCmd::num_arguments() {
ResourceMark rm;
JfrStartFlightRecordingDCmd* dcmd = new JfrStartFlightRecordingDCmd(NULL, false);
if (dcmd != NULL) {
DCmdMark mark(dcmd);
return dcmd->_dcmdparser.num_arguments();
}
return 0;
}
void JfrStartFlightRecordingDCmd::execute(DCmdSource source, TRAPS) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
if (invalid_state(output(), THREAD)) {
return;
}
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
JNIHandleBlockManager jni_handle_management(THREAD);
JavaValue result(T_OBJECT);
JfrJavaArguments constructor_args(&result);
constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdStart", THREAD);
const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK);
Handle h_dcmd_instance(THREAD, dcmd);
assert(h_dcmd_instance.not_null(), "invariant");
jstring name = NULL;
if (_name.is_set() && _name.value() != NULL) {
name = JfrJavaSupport::new_string(_name.value(), CHECK);
}
jstring filename = NULL;
if (_filename.is_set() && _filename.value() != NULL) {
filename = JfrJavaSupport::new_string(_filename.value(), CHECK);
}
jobject maxage = NULL;
if (_maxage.is_set()) {
maxage = JfrJavaSupport::new_java_lang_Long(_maxage.value()._nanotime, CHECK);
}
jobject maxsize = NULL;
if (_maxsize.is_set()) {
maxsize = JfrJavaSupport::new_java_lang_Long(_maxsize.value()._size, CHECK);
}
jobject duration = NULL;
if (_duration.is_set()) {
duration = JfrJavaSupport::new_java_lang_Long(_duration.value()._nanotime, CHECK);
}
jobject delay = NULL;
if (_delay.is_set()) {
delay = JfrJavaSupport::new_java_lang_Long(_delay.value()._nanotime, CHECK);
}
jobject disk = NULL;
if (_disk.is_set()) {
disk = JfrJavaSupport::new_java_lang_Boolean(_disk.value(), CHECK);
}
jobject dump_on_exit = NULL;
if (_dump_on_exit.is_set()) {
dump_on_exit = JfrJavaSupport::new_java_lang_Boolean(_dump_on_exit.value(), CHECK);
}
jobject path_to_gc_roots = NULL;
if (_path_to_gc_roots.is_set()) {
path_to_gc_roots = JfrJavaSupport::new_java_lang_Boolean(_path_to_gc_roots.value(), CHECK);
}
jobjectArray settings = NULL;
if (_settings.is_set()) {
const int length = _settings.value()->array()->length();
settings = JfrJavaSupport::new_string_array(length, CHECK);
assert(settings != NULL, "invariant");
for (int i = 0; i < length; ++i) {
jobject element = JfrJavaSupport::new_string(_settings.value()->array()->at(i), CHECK);
assert(element != NULL, "invariant");
JfrJavaSupport::set_array_element(settings, element, i, CHECK);
}
}
static const char klass[] = "jdk/jfr/internal/dcmd/DCmdStart";
static const char method[] = "execute";
static const char signature[] = "(Ljava/lang/String;[Ljava/lang/String;Ljava/lang/Long;"
"Ljava/lang/Long;Ljava/lang/Boolean;Ljava/lang/String;"
"Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/lang/String;";
JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
execute_args.set_receiver(h_dcmd_instance);
// arguments
execute_args.push_jobject(name);
execute_args.push_jobject(settings);
execute_args.push_jobject(delay);
execute_args.push_jobject(duration);
execute_args.push_jobject(disk);
execute_args.push_jobject(filename);
execute_args.push_jobject(maxage);
execute_args.push_jobject(maxsize);
execute_args.push_jobject(dump_on_exit);
execute_args.push_jobject(path_to_gc_roots);
JfrJavaSupport::call_virtual(&execute_args, THREAD);
handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD);
}
JfrStopFlightRecordingDCmd::JfrStopFlightRecordingDCmd(outputStream* output,
bool heap) : DCmdWithParser(output, heap),
_name("name", "Recording text,.e.g \\\"My Recording\\\"", "STRING", false, NULL),
_filename("filename", "Copy recording data to file, e.g. \\\"" JFR_FILENAME_EXAMPLE "\\\"", "STRING", false, NULL) {
_dcmdparser.add_dcmd_option(&_name);
_dcmdparser.add_dcmd_option(&_filename);
};
int JfrStopFlightRecordingDCmd::num_arguments() {
ResourceMark rm;
JfrStopFlightRecordingDCmd* dcmd = new JfrStopFlightRecordingDCmd(NULL, false);
if (dcmd != NULL) {
DCmdMark mark(dcmd);
return dcmd->_dcmdparser.num_arguments();
}
return 0;
}
void JfrStopFlightRecordingDCmd::execute(DCmdSource source, TRAPS) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
if (invalid_state(output(), THREAD) || !is_recorder_instance_created(output())) {
return;
}
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
JNIHandleBlockManager jni_handle_management(THREAD);
JavaValue result(T_OBJECT);
JfrJavaArguments constructor_args(&result);
constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdStop", CHECK);
const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK);
Handle h_dcmd_instance(THREAD, dcmd);
assert(h_dcmd_instance.not_null(), "invariant");
jstring name = NULL;
if (_name.is_set() && _name.value() != NULL) {
name = JfrJavaSupport::new_string(_name.value(), CHECK);
}
jstring filepath = NULL;
if (_filename.is_set() && _filename.value() != NULL) {
filepath = JfrJavaSupport::new_string(_filename.value(), CHECK);
}
static const char klass[] = "jdk/jfr/internal/dcmd/DCmdStop";
static const char method[] = "execute";
static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;";
JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
execute_args.set_receiver(h_dcmd_instance);
// arguments
execute_args.push_jobject(name);
execute_args.push_jobject(filepath);
JfrJavaSupport::call_virtual(&execute_args, THREAD);
handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD);
}
JfrConfigureFlightRecorderDCmd::JfrConfigureFlightRecorderDCmd(outputStream* output,
bool heap) : DCmdWithParser(output, heap),
_repository_path("repositorypath", "Path to repository,.e.g \\\"My Repository\\\"", "STRING", false, NULL),
_dump_path("dumppath", "Path to dump,.e.g \\\"My Dump path\\\"", "STRING", false, NULL),
_stack_depth("stackdepth", "Stack Depth", "JLONG", false, "64"),
_global_buffer_count("globalbuffercount", "Number of global buffers,", "JLONG", false, "32"),
_global_buffer_size("globalbuffersize", "Size of a global buffers,", "JLONG", false, "524288"),
_thread_buffer_size("thread_buffer_size", "Size of a thread buffer", "JLONG", false, "8192"),
_memory_size("memorysize", "Overall memory size, ", "JLONG", false, "16777216"),
_max_chunk_size("maxchunksize", "Size of an individual disk chunk", "JLONG", false, "12582912"),
_sample_threads("samplethreads", "Activate Thread sampling", "BOOLEAN", false, "true") {
_dcmdparser.add_dcmd_option(&_repository_path);
_dcmdparser.add_dcmd_option(&_dump_path);
_dcmdparser.add_dcmd_option(&_stack_depth);
_dcmdparser.add_dcmd_option(&_global_buffer_count);
_dcmdparser.add_dcmd_option(&_global_buffer_size);
_dcmdparser.add_dcmd_option(&_thread_buffer_size);
_dcmdparser.add_dcmd_option(&_memory_size);
_dcmdparser.add_dcmd_option(&_max_chunk_size);
_dcmdparser.add_dcmd_option(&_sample_threads);
};
int JfrConfigureFlightRecorderDCmd::num_arguments() {
ResourceMark rm;
JfrConfigureFlightRecorderDCmd* dcmd = new JfrConfigureFlightRecorderDCmd(NULL, false);
if (dcmd != NULL) {
DCmdMark mark(dcmd);
return dcmd->_dcmdparser.num_arguments();
}
return 0;
}
void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
if (invalid_state(output(), THREAD)) {
return;
}
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
JNIHandleBlockManager jni_handle_management(THREAD);
JavaValue result(T_OBJECT);
JfrJavaArguments constructor_args(&result);
constructor_args.set_klass("jdk/jfr/internal/dcmd/DCmdConfigure", CHECK);
const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK);
Handle h_dcmd_instance(THREAD, dcmd);
assert(h_dcmd_instance.not_null(), "invariant");
jstring repository_path = NULL;
if (_repository_path.is_set() && _repository_path.value() != NULL) {
repository_path = JfrJavaSupport::new_string(_repository_path.value(), CHECK);
}
jstring dump_path = NULL;
if (_dump_path.is_set() && _dump_path.value() != NULL) {
dump_path = JfrJavaSupport::new_string(_dump_path.value(), CHECK);
}
jobject stack_depth = NULL;
if (_stack_depth.is_set()) {
stack_depth = JfrJavaSupport::new_java_lang_Integer((jint)_stack_depth.value(), CHECK);
}
jobject global_buffer_count = NULL;
if (_global_buffer_count.is_set()) {
global_buffer_count = JfrJavaSupport::new_java_lang_Long(_global_buffer_count.value(), CHECK);
}
jobject global_buffer_size = NULL;
if (_global_buffer_size.is_set()) {
global_buffer_size = JfrJavaSupport::new_java_lang_Long(_global_buffer_size.value(), CHECK);
}
jobject thread_buffer_size = NULL;
if (_thread_buffer_size.is_set()) {
thread_buffer_size = JfrJavaSupport::new_java_lang_Long(_thread_buffer_size.value(), CHECK);
}
jobject max_chunk_size = NULL;
if (_max_chunk_size.is_set()) {
max_chunk_size = JfrJavaSupport::new_java_lang_Long(_max_chunk_size.value(), CHECK);
}
jobject memory_size = NULL;
if (_memory_size.is_set()) {
memory_size = JfrJavaSupport::new_java_lang_Long(_memory_size.value(), CHECK);
}
jobject sample_threads = NULL;
if (_sample_threads.is_set()) {
sample_threads = JfrJavaSupport::new_java_lang_Boolean(_sample_threads.value(), CHECK);
}
static const char klass[] = "jdk/jfr/internal/dcmd/DCmdConfigure";
static const char method[] = "execute";
static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Integer;"
"Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;"
"Ljava/lang/Long;Ljava/lang/Boolean;)Ljava/lang/String;";
JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
execute_args.set_receiver(h_dcmd_instance);
// params
execute_args.push_jobject(repository_path);
execute_args.push_jobject(dump_path);
execute_args.push_jobject(stack_depth);
execute_args.push_jobject(global_buffer_count);
execute_args.push_jobject(global_buffer_size);
execute_args.push_jobject(thread_buffer_size);
execute_args.push_jobject(memory_size);
execute_args.push_jobject(max_chunk_size);
execute_args.push_jobject(sample_threads);
JfrJavaSupport::call_virtual(&execute_args, THREAD);
handle_dcmd_result(output(), (oop)result.get_jobject(), source, THREAD);
}
bool register_jfr_dcmds() {
uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI | DCmd_Source_MBean;
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrCheckFlightRecordingDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrDumpFlightRecordingDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrStartFlightRecordingDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrStopFlightRecordingDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JfrConfigureFlightRecorderDCmd>(full_export, true, false));
return true;
}

@ -0,0 +1,171 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef SHARE_VM_JFR_JFRDCMDS_HPP
#define SHARE_VM_JFR_JFRDCMDS_HPP
#include "services/diagnosticCommand.hpp"
class JfrDumpFlightRecordingDCmd : public DCmdWithParser {
protected:
DCmdArgument<char*> _name;
DCmdArgument<char*> _filename;
DCmdArgument<bool> _path_to_gc_roots;
public:
JfrDumpFlightRecordingDCmd(outputStream* output, bool heap);
static const char* name() {
return "JFR.dump";
}
static const char* description() {
return "Copies contents of a JFR recording to file. Either the name or the recording id must be specified.";
}
static const char* impact() {
return "Low";
}
static const JavaPermission permission() {
JavaPermission p = {"java.lang.management.ManagementPermission", "monitor", NULL};
return p;
}
static int num_arguments();
virtual void execute(DCmdSource source, TRAPS);
};
class JfrCheckFlightRecordingDCmd : public DCmdWithParser {
protected:
DCmdArgument<char*> _name;
DCmdArgument<bool> _verbose;
public:
JfrCheckFlightRecordingDCmd(outputStream* output, bool heap);
static const char* name() {
return "JFR.check";
}
static const char* description() {
return "Checks running JFR recording(s)";
}
static const char* impact() {
return "Low";
}
static const JavaPermission permission() {
JavaPermission p = {"java.lang.management.ManagementPermission", "monitor", NULL};
return p;
}
static int num_arguments();
virtual void execute(DCmdSource source, TRAPS);
};
class JfrStartFlightRecordingDCmd : public DCmdWithParser {
protected:
DCmdArgument<char*> _name;
DCmdArgument<StringArrayArgument*> _settings;
DCmdArgument<NanoTimeArgument> _delay;
DCmdArgument<NanoTimeArgument> _duration;
DCmdArgument<bool> _disk;
DCmdArgument<char*> _filename;
DCmdArgument<NanoTimeArgument> _maxage;
DCmdArgument<MemorySizeArgument> _maxsize;
DCmdArgument<bool> _dump_on_exit;
DCmdArgument<bool> _path_to_gc_roots;
public:
JfrStartFlightRecordingDCmd(outputStream* output, bool heap);
static const char* name() {
return "JFR.start";
}
static const char* description() {
return "Starts a new JFR recording";
}
static const char* impact() {
return "Medium: Depending on the settings for a recording, the impact can range from low to high.";
}
static const JavaPermission permission() {
JavaPermission p = {"java.lang.management.ManagementPermission", "monitor", NULL};
return p;
}
static int num_arguments();
virtual void execute(DCmdSource source, TRAPS);
};
class JfrStopFlightRecordingDCmd : public DCmdWithParser {
protected:
DCmdArgument<char*> _name;
DCmdArgument<char*> _filename;
public:
JfrStopFlightRecordingDCmd(outputStream* output, bool heap);
static const char* name() {
return "JFR.stop";
}
static const char* description() {
return "Stops a JFR recording";
}
static const char* impact() {
return "Low";
}
static const JavaPermission permission() {
JavaPermission p = {"java.lang.management.ManagementPermission", "monitor", NULL};
return p;
}
static int num_arguments();
virtual void execute(DCmdSource source, TRAPS);
};
class JfrRuntimeOptions;
class JfrConfigureFlightRecorderDCmd : public DCmdWithParser {
friend class JfrOptionSet;
protected:
DCmdArgument<char*> _repository_path;
DCmdArgument<char*> _dump_path;
DCmdArgument<jlong> _stack_depth;
DCmdArgument<jlong> _global_buffer_count;
DCmdArgument<jlong> _global_buffer_size;
DCmdArgument<jlong> _thread_buffer_size;
DCmdArgument<jlong> _memory_size;
DCmdArgument<jlong> _max_chunk_size;
DCmdArgument<bool> _sample_threads;
public:
JfrConfigureFlightRecorderDCmd(outputStream* output, bool heap);
static const char* name() {
return "JFR.configure";
}
static const char* description() {
return "Configure JFR";
}
static const char* impact() {
return "Low";
}
static const JavaPermission permission() {
JavaPermission p = {"java.lang.management.ManagementPermission", "monitor", NULL};
return p;
}
static int num_arguments();
virtual void execute(DCmdSource source, TRAPS);
};
bool register_jfr_dcmds();
#endif // SHARE_VM_JFR_JFRDCMDS_HPP

File diff suppressed because it is too large Load Diff

@ -0,0 +1,45 @@
/*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef SHARE_VM_JFR_INSTRUMENTATION_JFREVENTCLASSTRANSFORMER_HPP
#define SHARE_VM_JFR_INSTRUMENTATION_JFREVENTCLASSTRANSFORMER_HPP
#include "memory/allocation.hpp"
#include "utilities/exceptions.hpp"
class ClassFileParser;
class InstanceKlass;
//
// Intercepts the initial class load of jdk.jfr.Event and subclasses.
// Will replace the sent in InstanceKlass* with a class file schema extended InstanceKlass*.
//
class JfrEventClassTransformer : AllStatic {
public:
static void on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS);
static void set_force_instrumentation(bool force_instrumentation);
static bool is_force_instrumentation();
};
#endif // SHARE_VM_JFR_INSTRUMENTATION_JFREVENTCLASSTRANSFORMER_HPP

@ -0,0 +1,279 @@
/*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "jvm.h"
#include "jfr/instrumentation/jfrJvmtiAgent.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/jni/jfrUpcalls.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp"
#include "jfr/support/jfrEventClass.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/exceptions.hpp"
static const size_t ERROR_MSG_BUFFER_SIZE = 256;
static JfrJvmtiAgent* agent = NULL;
static jvmtiEnv* jfr_jvmti_env = NULL;
static void check_jvmti_error(jvmtiEnv* jvmti, jvmtiError errnum, const char* str) {
if (errnum != JVMTI_ERROR_NONE) {
char* errnum_str = NULL;
jvmti->GetErrorName(errnum, &errnum_str);
log_error(jfr, system)("ERROR: JfrJvmtiAgent: " INT32_FORMAT " (%s): %s\n",
errnum,
NULL == errnum_str ? "Unknown" : errnum_str,
NULL == str ? "" : str);
}
}
static jvmtiError set_event_notification_mode(jvmtiEventMode mode,
jvmtiEvent event,
jthread event_thread,
...) {
if (jfr_jvmti_env == NULL) {
return JVMTI_ERROR_NONE;
}
const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventNotificationMode(mode, event, event_thread);
check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventNotificationMode");
return jvmti_ret_code;
}
static jvmtiError update_class_file_load_hook_event(jvmtiEventMode mode) {
return set_event_notification_mode(mode, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
}
static JavaThread* current_java_thread() {
Thread* this_thread = Thread::current();
assert(this_thread != NULL && this_thread->is_Java_thread(), "invariant");
return static_cast<JavaThread*>(this_thread);
}
// jvmti event callbacks require C linkage
extern "C" void JNICALL jfr_on_class_file_load_hook(jvmtiEnv *jvmti_env,
JNIEnv* jni_env,
jclass class_being_redefined,
jobject loader,
const char* name,
jobject protection_domain,
jint class_data_len,
const unsigned char* class_data,
jint* new_class_data_len,
unsigned char** new_class_data) {
if (class_being_redefined == NULL) {
return;
}
JavaThread* jt = JavaThread::thread_from_jni_environment(jni_env);
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));;
ThreadInVMfromNative tvmfn(jt);
JfrUpcalls::on_retransform(JfrTraceId::get(class_being_redefined),
class_being_redefined,
class_data_len,
class_data,
new_class_data_len,
new_class_data,
jt);
}
// caller needs ResourceMark
static jclass* create_classes_array(jint classes_count, TRAPS) {
assert(classes_count > 0, "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
ThreadInVMfromNative tvmfn((JavaThread*)THREAD);
jclass* const classes = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, jclass, classes_count);
if (NULL == classes) {
char error_buffer[ERROR_MSG_BUFFER_SIZE];
jio_snprintf(error_buffer, ERROR_MSG_BUFFER_SIZE,
"Thread local allocation (native) of " SIZE_FORMAT " bytes failed "
"in retransform classes", sizeof(jclass) * classes_count);
log_error(jfr, system)("%s", error_buffer);
JfrJavaSupport::throw_out_of_memory_error(error_buffer, CHECK_NULL);
}
return classes;
}
static void log_and_throw(TRAPS) {
if (!HAS_PENDING_EXCEPTION) {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
ThreadInVMfromNative tvmfn((JavaThread*)THREAD);
log_error(jfr, system)("JfrJvmtiAgent::retransformClasses failed");
JfrJavaSupport::throw_class_format_error("JfrJvmtiAgent::retransformClasses failed", THREAD);
}
}
static void check_exception_and_log(JNIEnv* env, TRAPS) {
assert(env != NULL, "invariant");
if (env->ExceptionOccurred()) {
// array index out of bound
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
ThreadInVMfromNative tvmfn((JavaThread*)THREAD);
log_error(jfr, system)("GetObjectArrayElement threw an exception");
return;
}
}
void JfrJvmtiAgent::retransform_classes(JNIEnv* env, jobjectArray classes_array, TRAPS) {
assert(env != NULL, "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(THREAD));
if (classes_array == NULL) {
return;
}
const jint classes_count = env->GetArrayLength(classes_array);
if (classes_count <= 0) {
return;
}
ResourceMark rm(THREAD);
jclass* const classes = create_classes_array(classes_count, CHECK);
assert(classes != NULL, "invariant");
for (jint i = 0; i < classes_count; i++) {
jclass clz = (jclass)env->GetObjectArrayElement(classes_array, i);
check_exception_and_log(env, THREAD);
// inspecting the oop/klass requires a thread transition
{
ThreadInVMfromNative transition((JavaThread*)THREAD);
if (JdkJfrEvent::is_a(clz)) {
// should have been tagged already
assert(JdkJfrEvent::is_subklass(clz), "invariant");
} else {
// outside the event hierarchy
JdkJfrEvent::tag_as_host(clz);
}
}
classes[i] = clz;
}
if (jfr_jvmti_env->RetransformClasses(classes_count, classes) != JVMTI_ERROR_NONE) {
log_and_throw(THREAD);
}
}
static jvmtiError register_callbacks(JavaThread* jt) {
assert(jfr_jvmti_env != NULL, "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
jvmtiEventCallbacks callbacks;
/* Set callbacks */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.ClassFileLoadHook = jfr_on_class_file_load_hook;
const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventCallbacks");
return jvmti_ret_code;
}
static jvmtiError register_capabilities(JavaThread* jt) {
assert(jfr_jvmti_env != NULL, "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
jvmtiCapabilities capabilities;
/* Add JVMTI capabilities */
(void)memset(&capabilities, 0, sizeof(capabilities));
capabilities.can_retransform_classes = 1;
capabilities.can_retransform_any_class = 1;
const jvmtiError jvmti_ret_code = jfr_jvmti_env->AddCapabilities(&capabilities);
check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "Add Capabilities");
return jvmti_ret_code;
}
static jint create_jvmti_env(JavaThread* jt) {
assert(jfr_jvmti_env == NULL, "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(jt));
extern struct JavaVM_ main_vm;
JavaVM* vm = &main_vm;
return vm->GetEnv((void **)&jfr_jvmti_env, JVMTI_VERSION);
}
static jvmtiError unregister_callbacks(JavaThread* jt) {
if (jfr_jvmti_env == NULL) {
return JVMTI_ERROR_NONE;
}
jvmtiEventCallbacks callbacks;
/* Set empty callbacks */
memset(&callbacks, 0, sizeof(callbacks));
const jvmtiError jvmti_ret_code = jfr_jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
check_jvmti_error(jfr_jvmti_env, jvmti_ret_code, "SetEventCallbacks");
return jvmti_ret_code;
}
JfrJvmtiAgent::JfrJvmtiAgent() {}
JfrJvmtiAgent::~JfrJvmtiAgent() {
JavaThread* jt = current_java_thread();
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
ThreadToNativeFromVM transition(jt);
update_class_file_load_hook_event(JVMTI_DISABLE);
unregister_callbacks(jt);
if (jfr_jvmti_env != NULL) {
jfr_jvmti_env->DisposeEnvironment();
jfr_jvmti_env = NULL;
}
agent = NULL;
}
static bool initialize() {
JavaThread* const jt = current_java_thread();
assert(jt != NULL, "invariant");
assert(jt->thread_state() == _thread_in_vm, "invariant");
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt));
ThreadToNativeFromVM transition(jt);
if (create_jvmti_env(jt) != JNI_OK) {
assert(jfr_jvmti_env == NULL, "invariant");
return false;
}
assert(jfr_jvmti_env != NULL, "invariant");
if (register_capabilities(jt) != JVMTI_ERROR_NONE) {
return false;
}
if (register_callbacks(jt) != JVMTI_ERROR_NONE) {
return false;
}
if (update_class_file_load_hook_event(JVMTI_ENABLE) != JVMTI_ERROR_NONE) {
return false;
}
return true;
}
bool JfrJvmtiAgent::create() {
assert(jfr_jvmti_env == NULL, "invariant");
agent = new JfrJvmtiAgent();
if (agent == NULL) {
return false;
}
if (!initialize()) {
delete agent;
agent = NULL;
return false;
}
return true;
}
void JfrJvmtiAgent::destroy() {
if (agent != NULL) {
delete agent;
agent = NULL;
}
}

@ -0,0 +1,41 @@
/*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef SHARE_VM_JFR_INSTRUMENTATION_JFRJVMTIAGENT_HPP
#define SHARE_VM_JFR_INSTRUMENTATION_JFRJVMTIAGENT_HPP
#include "jfr/utilities/jfrAllocation.hpp"
class JfrJvmtiAgent : public JfrCHeapObj {
friend class JfrRecorder;
private:
JfrJvmtiAgent();
~JfrJvmtiAgent();
static bool create();
static void destroy();
public:
static void retransform_classes(JNIEnv* env, jobjectArray classes, TRAPS);
};
#endif // SHARE_VM_JFR_INSTRUMENTATION_JFRJVMTIAGENT_HPP

@ -0,0 +1,98 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "jfr/jfr.hpp"
#include "jfr/leakprofiler/leakProfiler.hpp"
#include "jfr/periodic/sampling/jfrThreadSampler.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
#include "jfr/recorder/repository/jfrEmergencyDump.hpp"
#include "jfr/support/jfrThreadLocal.hpp"
#include "runtime/java.hpp"
bool Jfr::is_enabled() {
return JfrRecorder::is_enabled();
}
bool Jfr::is_disabled() {
return JfrRecorder::is_disabled();
}
bool Jfr::is_recording() {
return JfrRecorder::is_recording();
}
void Jfr::on_vm_init() {
if (!JfrRecorder::on_vm_init()) {
vm_exit_during_initialization("Failure when starting JFR on_vm_init");
}
}
void Jfr::on_vm_start() {
if (!JfrRecorder::on_vm_start()) {
vm_exit_during_initialization("Failure when starting JFR on_vm_start");
}
}
void Jfr::on_unloading_classes() {
if (JfrRecorder::is_created()) {
JfrCheckpointManager::write_type_set_for_unloaded_classes();
}
}
void Jfr::on_thread_exit(JavaThread* thread) {
if (JfrRecorder::is_recording()) {
JfrThreadLocal::on_exit(thread);
}
}
void Jfr::on_thread_destruct(Thread* thread) {
if (JfrRecorder::is_created()) {
JfrThreadLocal::on_destruct(thread);
}
}
void Jfr::on_vm_shutdown(bool exception_handler) {
if (JfrRecorder::is_recording()) {
JfrEmergencyDump::on_vm_shutdown(exception_handler);
}
}
void Jfr::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
LeakProfiler::oops_do(is_alive, f);
}
bool Jfr::on_start_flight_recording_option(const JavaVMOption** option, char* tail) {
return JfrOptionSet::parse_start_flight_recording_option(option, tail);
}
bool Jfr::on_flight_recorder_option(const JavaVMOption** option, char* tail) {
return JfrOptionSet::parse_flight_recorder_option(option, tail);
}
Thread* Jfr::sampler_thread() {
return JfrThreadSampling::sampler_thread();
}

@ -0,0 +1,58 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#ifndef SHARE_VM_JFR_JFR_HPP
#define SHARE_VM_JFR_JFR_HPP
#include "jni.h"
#include "memory/allocation.hpp"
class BoolObjectClosure;
class JavaThread;
class OopClosure;
class Thread;
extern "C" void JNICALL jfr_register_natives(JNIEnv*, jclass);
//
// The VM interface to Flight Recorder.
//
class Jfr : AllStatic {
public:
static bool is_enabled();
static bool is_disabled();
static bool is_recording();
static void on_vm_init();
static void on_vm_start();
static void on_unloading_classes();
static void on_thread_exit(JavaThread* thread);
static void on_thread_destruct(Thread* thread);
static void on_vm_shutdown(bool exception_handler = false);
static bool on_start_flight_recording_option(const JavaVMOption** option, char* tail);
static bool on_flight_recorder_option(const JavaVMOption** option, char* tail);
static void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
static Thread* sampler_thread();
};
#endif // SHARE_VM_JFR_JFR_HPP

Some files were not shown because too many files have changed in this diff Show More