Merge
This commit is contained in:
commit
7984fb2956
make
CompileJavaModules.gmkjprt.properties
autoconf
common
copy
hotspot
gensrc
lib
src/classes/build/tools/projectcreator
launcher
lib
nashorn
nb_native/nbproject
src/hotspot
cpu
aarch64
arm
sparc
x86
os
bsd
linux
solaris
windows
os_cpu/solaris_x86
share
c1
ci
classfile
classFileParser.cppclassLoaderData.cppclassLoaderData.hppklassFactory.cppmoduleEntry.cppmoduleEntry.hpppackageEntry.cpppackageEntry.hppsystemDictionary.cppvmSymbols.cppvmSymbols.hpp
code
compiler
gc
g1
g1CollectedHeap.hppg1EvacStats.cppg1FullGCAdjustTask.cppg1FullGCCompactTask.cppg1FullGCCompactTask.hppg1FullGCPrepareTask.cppg1FullGCPrepareTask.hppg1FullGCTask.cppg1GCPhaseTimes.cppg1HeapRegionEventSender.cppg1HeapRegionEventSender.hppg1ParScanThreadState.inline.hppg1RemSet.cppheapRegionTracer.cpp
shared
jfr
@ -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))
|
||||
|
||||
|
94
make/hotspot/gensrc/GensrcJfr.gmk
Normal file
94
make/hotspot/gensrc/GensrcJfr.gmk
Normal file
@ -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,
|
||||
|
90
src/hotspot/cpu/aarch64/vm_version_ext_aarch64.cpp
Normal file
90
src/hotspot/cpu/aarch64/vm_version_ext_aarch64.cpp
Normal file
@ -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;
|
||||
}
|
54
src/hotspot/cpu/aarch64/vm_version_ext_aarch64.hpp
Normal file
54
src/hotspot/cpu/aarch64/vm_version_ext_aarch64.hpp
Normal file
@ -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
|
94
src/hotspot/cpu/arm/vm_version_ext_arm.cpp
Normal file
94
src/hotspot/cpu/arm/vm_version_ext_arm.cpp
Normal file
@ -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;
|
||||
}
|
54
src/hotspot/cpu/arm/vm_version_ext_arm.hpp
Normal file
54
src/hotspot/cpu/arm/vm_version_ext_arm.hpp
Normal file
@ -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
|
185
src/hotspot/cpu/sparc/vm_version_ext_sparc.cpp
Normal file
185
src/hotspot/cpu/sparc/vm_version_ext_sparc.cpp
Normal file
@ -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;
|
||||
}
|
64
src/hotspot/cpu/sparc/vm_version_ext_sparc.hpp
Normal file
64
src/hotspot/cpu/sparc/vm_version_ext_sparc.hpp
Normal file
@ -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,
|
||||
|
210
src/hotspot/cpu/x86/rdtsc_x86.cpp
Normal file
210
src/hotspot/cpu/x86/rdtsc_x86.cpp
Normal file
@ -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;
|
||||
}
|
50
src/hotspot/cpu/x86/rdtsc_x86.hpp
Normal file
50
src/hotspot/cpu/x86/rdtsc_x86.hpp
Normal file
@ -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,
|
||||
|
967
src/hotspot/cpu/x86/vm_version_ext_x86.cpp
Normal file
967
src/hotspot/cpu/x86/vm_version_ext_x86.cpp
Normal file
@ -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",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
};
|
99
src/hotspot/cpu/x86/vm_version_ext_x86.hpp
Normal file
99
src/hotspot/cpu/x86/vm_version_ext_x86.hpp
Normal file
@ -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
|
405
src/hotspot/os/bsd/os_perf_bsd.cpp
Normal file
405
src/hotspot/os/bsd/os_perf_bsd.cpp
Normal file
@ -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(¤t_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;
|
||||
}
|
1060
src/hotspot/os/linux/os_perf_linux.cpp
Normal file
1060
src/hotspot/os/linux/os_perf_linux.cpp
Normal file
File diff suppressed because it is too large
Load Diff
756
src/hotspot/os/solaris/os_perf_solaris.cpp
Normal file
756
src/hotspot/os/solaris/os_perf_solaris.cpp
Normal file
@ -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;
|
||||
}
|
1332
src/hotspot/os/windows/os_perf_windows.cpp
Normal file
1332
src/hotspot/os/windows/os_perf_windows.cpp
Normal file
File diff suppressed because it is too large
Load Diff
165
src/hotspot/os/windows/pdh_interface.cpp
Normal file
165
src/hotspot/os/windows/pdh_interface.cpp
Normal file
@ -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;
|
||||
}
|
64
src/hotspot/os/windows/pdh_interface.hpp
Normal file
64
src/hotspot/os/windows/pdh_interface.hpp
Normal file
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
49
src/hotspot/share/gc/g1/g1HeapRegionEventSender.cpp
Normal file
49
src/hotspot/share/gc/g1/g1HeapRegionEventSender.cpp
Normal file
@ -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.");
|
||||
}
|
||||
}
|
||||
|
159
src/hotspot/share/gc/shared/gcConfiguration.cpp
Normal file
159
src/hotspot/share/gc/shared/gcConfiguration.cpp
Normal file
@ -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;
|
||||
}
|
80
src/hotspot/share/gc/shared/gcConfiguration.hpp
Normal file
80
src/hotspot/share/gc/shared/gcConfiguration.hpp
Normal file
@ -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) {
|
||||
|
633
src/hotspot/share/jfr/dcmd/jfrDcmds.cpp
Normal file
633
src/hotspot/share/jfr/dcmd/jfrDcmds.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
171
src/hotspot/share/jfr/dcmd/jfrDcmds.hpp
Normal file
171
src/hotspot/share/jfr/dcmd/jfrDcmds.hpp
Normal file
@ -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
|
1556
src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp
Normal file
1556
src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp
Normal file
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
|
279
src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp
Normal file
279
src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
|
41
src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.hpp
Normal file
41
src/hotspot/share/jfr/instrumentation/jfrJvmtiAgent.hpp
Normal file
@ -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
|
98
src/hotspot/share/jfr/jfr.cpp
Normal file
98
src/hotspot/share/jfr/jfr.cpp
Normal file
@ -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();
|
||||
}
|
58
src/hotspot/share/jfr/jfr.hpp
Normal file
58
src/hotspot/share/jfr/jfr.hpp
Normal file
@ -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
Loading…
x
Reference in New Issue
Block a user