mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
Merge
This commit is contained in:
commit
d14a64b0ed
137 changed files with 3865 additions and 2119 deletions
116
hotspot/make/lib/CompileGtest.gmk
Normal file
116
hotspot/make/lib/CompileGtest.gmk
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016, 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
GTEST_TEST_SRC := $(HOTSPOT_TOPDIR)/test/native
|
||||||
|
GTEST_FRAMEWORK_SRC := $(SRC_ROOT)/test/fmw/gtest
|
||||||
|
|
||||||
|
# On Windows, there are no internal debug symbols so must set copying to true
|
||||||
|
# to get any at all.
|
||||||
|
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||||
|
GTEST_COPY_DEBUG_SYMBOLS := true
|
||||||
|
else
|
||||||
|
GTEST_COPY_DEBUG_SYMBOLS := false
|
||||||
|
endif
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
GTEST_TEST_SRC_FILES := $(shell $(FIND) $(HOTSPOT_TOPDIR)/test/native -name \
|
||||||
|
"test*.cpp" -type f)
|
||||||
|
|
||||||
|
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||||
|
GTEST_JVM_MAPFILE := $(JVM_MAPFILE)
|
||||||
|
else
|
||||||
|
GTEST_JVM_MAPFILE := $(JVM_OUTPUTDIR)/gtest/mapfile
|
||||||
|
|
||||||
|
$(JVM_OUTPUTDIR)/gtest/symbols: $(JVM_OUTPUTDIR)/symbols
|
||||||
|
$(call MakeDir, $(@D))
|
||||||
|
( $(CAT) $< ; echo "runUnitTests" ) > $@
|
||||||
|
|
||||||
|
$(GTEST_JVM_MAPFILE): $(JVM_OUTPUTDIR)/gtest/symbols
|
||||||
|
$(call create-mapfile)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Disabling switch warning for clang because of test source.
|
||||||
|
|
||||||
|
$(eval $(call SetupNativeCompilation, BUILD_GTEST_LIBJVM, \
|
||||||
|
TOOLCHAIN := $(JVM_TOOLCHAIN), \
|
||||||
|
LIBRARY := jvm, \
|
||||||
|
OUTPUT_DIR := $(JVM_OUTPUTDIR)/gtest, \
|
||||||
|
EXTRA_FILES := $(GTEST_TEST_SRC_FILES) \
|
||||||
|
$(GTEST_FRAMEWORK_SRC)/src/gtest-all.cc \
|
||||||
|
$(GTEST_TEST_SRC)/gtestMain.cpp, \
|
||||||
|
OBJECT_DIR := $(JVM_OUTPUTDIR)/gtest/objs, \
|
||||||
|
EXTRA_OBJECT_FILES := $(filter-out %/operator_new$(OBJ_SUFFIX), \
|
||||||
|
$(BUILD_LIBJVM_ALL_OBJS)), \
|
||||||
|
CFLAGS := $(JVM_CFLAGS) -I$(GTEST_FRAMEWORK_SRC) \
|
||||||
|
-I$(GTEST_FRAMEWORK_SRC)/include \
|
||||||
|
-I$(GTEST_TEST_SRC), \
|
||||||
|
CFLAGS_windows := /EHsc, \
|
||||||
|
CFLAGS_solaris := -DGTEST_HAS_EXCEPTIONS=0 -library=stlport4, \
|
||||||
|
CFLAGS_macosx := -DGTEST_OS_MAC=1, \
|
||||||
|
CFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
|
||||||
|
CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
|
||||||
|
DISABLED_WARNINGS_gcc := undef, \
|
||||||
|
DISABLED_WARNINGS_clang := undef switch format-nonliteral \
|
||||||
|
tautological-undefined-compare, \
|
||||||
|
DISABLED_WARNINGS_solstudio := identexpected, \
|
||||||
|
LDFLAGS := $(JVM_LDFLAGS), \
|
||||||
|
LDFLAGS_solaris := -library=stlport4 $(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||||
|
LIBS := $(JVM_LIBS), \
|
||||||
|
OPTIMIZATION := $(JVM_OPTIMIZATION), \
|
||||||
|
MAPFILE := $(GTEST_JVM_MAPFILE), \
|
||||||
|
USE_MAPFILE_FOR_SYMBOLS := true, \
|
||||||
|
COPY_DEBUG_SYMBOLS := $(GTEST_COPY_DEBUG_SYMBOLS), \
|
||||||
|
ZIP_EXTERNAL_DEBUG_SYMBOLS := false, \
|
||||||
|
))
|
||||||
|
|
||||||
|
TARGETS += $(BUILD_GTEST_LIBJVM)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
$(eval $(call SetupNativeCompilation, BUILD_GTEST_LAUNCHER, \
|
||||||
|
TOOLCHAIN := $(JVM_TOOLCHAIN), \
|
||||||
|
PROGRAM := gtestLauncher, \
|
||||||
|
OUTPUT_DIR := $(JVM_OUTPUTDIR)/gtest, \
|
||||||
|
EXTRA_FILES := $(GTEST_TEST_SRC)/gtestLauncher.cpp, \
|
||||||
|
OBJECT_DIR := $(JVM_OUTPUTDIR)/gtest/launcher-objs, \
|
||||||
|
CFLAGS := $(JVM_CFLAGS) -I$(GTEST_FRAMEWORK_SRC) \
|
||||||
|
-I$(GTEST_FRAMEWORK_SRC)/include, \
|
||||||
|
CFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
|
||||||
|
CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
|
||||||
|
LDFLAGS := $(LDFLAGS_TESTEXE), \
|
||||||
|
LDFLAGS_unix := -L$(JVM_OUTPUTDIR)/gtest $(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||||
|
LDFLAGS_solaris := -library=stlport4, \
|
||||||
|
LIBS_unix := -ljvm, \
|
||||||
|
LIBS_windows := $(JVM_OUTPUTDIR)/gtest/objs/jvm.lib, \
|
||||||
|
COPY_DEBUG_SYMBOLS := $(GTEST_COPY_DEBUG_SYMBOLS), \
|
||||||
|
ZIP_EXTERNAL_DEBUG_SYMBOLS := false, \
|
||||||
|
))
|
||||||
|
|
||||||
|
$(BUILD_GTEST_LAUNCHER): $(BUILD_GTEST_LIBJVM)
|
||||||
|
|
||||||
|
TARGETS += $(BUILD_GTEST_LAUNCHER)
|
||||||
|
|
||||||
|
################################################################################
|
|
@ -37,6 +37,10 @@ include lib/CompileDtracePreJvm.gmk
|
||||||
include lib/CompileJvm.gmk
|
include lib/CompileJvm.gmk
|
||||||
include lib/CompileDtracePostJvm.gmk
|
include lib/CompileDtracePostJvm.gmk
|
||||||
|
|
||||||
|
ifeq ($(BUILD_GTEST), true)
|
||||||
|
include lib/CompileGtest.gmk
|
||||||
|
endif
|
||||||
|
|
||||||
all: $(TARGETS)
|
all: $(TARGETS)
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
|
@ -153,20 +153,33 @@ $(JVM_OUTPUTDIR)/symbols: $(SYMBOLS_SRC)
|
||||||
################################################################################
|
################################################################################
|
||||||
# Finally convert the symbol list into a platform-specific mapfile
|
# Finally convert the symbol list into a platform-specific mapfile
|
||||||
|
|
||||||
$(JVM_MAPFILE): $(JVM_OUTPUTDIR)/symbols
|
ifeq ($(OPENJDK_TARGET_OS), macosx)
|
||||||
$(call LogInfo, Creating mapfile)
|
# On macosx, we need to add a leading underscore
|
||||||
$(RM) $@
|
define create-mapfile-work
|
||||||
ifeq ($(OPENJDK_TARGET_OS), macosx)
|
|
||||||
# On macosx, we need to add a leading underscore
|
|
||||||
$(AWK) '{ if ($$0 ~ ".") { print " _" $$0 } }' < $^ > $@.tmp
|
$(AWK) '{ if ($$0 ~ ".") { print " _" $$0 } }' < $^ > $@.tmp
|
||||||
else ifeq ($(OPENJDK_TARGET_OS), windows)
|
endef
|
||||||
# On windows, add an 'EXPORTS' header
|
else ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||||
|
# On windows, add an 'EXPORTS' header
|
||||||
|
define create-mapfile-work
|
||||||
$(ECHO) "EXPORTS" > $@.tmp
|
$(ECHO) "EXPORTS" > $@.tmp
|
||||||
$(AWK) '{ if ($$0 ~ ".") { print " " $$0 } }' < $^ >> $@.tmp
|
$(AWK) '{ if ($$0 ~ ".") { print " " $$0 } }' < $^ >> $@.tmp
|
||||||
else
|
endef
|
||||||
# Assume standard linker script
|
else
|
||||||
|
# Assume standard linker script
|
||||||
|
define create-mapfile-work
|
||||||
$(PRINTF) "SUNWprivate_1.1 { \n global: \n" > $@.tmp
|
$(PRINTF) "SUNWprivate_1.1 { \n global: \n" > $@.tmp
|
||||||
$(AWK) '{ if ($$0 ~ ".") { print " " $$0 ";" } }' < $^ >> $@.tmp
|
$(AWK) '{ if ($$0 ~ ".") { print " " $$0 ";" } }' < $^ >> $@.tmp
|
||||||
$(PRINTF) " local: \n *; \n }; \n" >> $@.tmp
|
$(PRINTF) " local: \n *; \n }; \n" >> $@.tmp
|
||||||
endif
|
endef
|
||||||
|
endif
|
||||||
|
|
||||||
|
define create-mapfile
|
||||||
|
$(call LogInfo, Creating mapfile)
|
||||||
|
$(call MakeDir, $(@D))
|
||||||
|
$(call create-mapfile-work)
|
||||||
|
$(RM) $@
|
||||||
$(MV) $@.tmp $@
|
$(MV) $@.tmp $@
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(JVM_MAPFILE): $(JVM_OUTPUTDIR)/symbols
|
||||||
|
$(call create-mapfile)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,6 +22,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
package build.tools.projectcreator;
|
||||||
|
|
||||||
class ArgIterator {
|
class ArgIterator {
|
||||||
String[] args;
|
String[] args;
|
||||||
int i;
|
int i;
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,6 +22,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
package build.tools.projectcreator;
|
||||||
|
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
@ -37,7 +39,7 @@ class BuildConfig {
|
||||||
if (ci == null) {
|
if (ci == null) {
|
||||||
String comp = (String)getField(null, "CompilerVersion");
|
String comp = (String)getField(null, "CompilerVersion");
|
||||||
try {
|
try {
|
||||||
ci = (CompilerInterface)Class.forName("CompilerInterface" + comp).newInstance();
|
ci = (CompilerInterface)Class.forName("build.tools.projectcreator.CompilerInterface" + comp).newInstance();
|
||||||
} catch (Exception cnfe) {
|
} catch (Exception cnfe) {
|
||||||
System.err.println("Cannot find support for compiler " + comp);
|
System.err.println("Cannot find support for compiler " + comp);
|
||||||
throw new RuntimeException(cnfe.toString());
|
throw new RuntimeException(cnfe.toString());
|
||||||
|
@ -66,6 +68,8 @@ class BuildConfig {
|
||||||
String buildSpace = getFieldString(null, "BuildSpace");
|
String buildSpace = getFieldString(null, "BuildSpace");
|
||||||
String outDir = buildBase;
|
String outDir = buildBase;
|
||||||
String jdkTargetRoot = getFieldString(null, "JdkTargetRoot");
|
String jdkTargetRoot = getFieldString(null, "JdkTargetRoot");
|
||||||
|
String makeBinary = getFieldString(null, "MakeBinary");
|
||||||
|
String makeOutput = expandFormat(getFieldString(null, "MakeOutput"));
|
||||||
|
|
||||||
put("Id", flavourBuild);
|
put("Id", flavourBuild);
|
||||||
put("OutputDir", outDir);
|
put("OutputDir", outDir);
|
||||||
|
@ -74,6 +78,8 @@ class BuildConfig {
|
||||||
put("BuildSpace", buildSpace);
|
put("BuildSpace", buildSpace);
|
||||||
put("OutputDll", outDir + Util.sep + outDll);
|
put("OutputDll", outDir + Util.sep + outDll);
|
||||||
put("JdkTargetRoot", jdkTargetRoot);
|
put("JdkTargetRoot", jdkTargetRoot);
|
||||||
|
put("MakeBinary", makeBinary);
|
||||||
|
put("MakeOutput", makeOutput);
|
||||||
|
|
||||||
context = new String [] {flavourBuild, flavour, build, null};
|
context = new String [] {flavourBuild, flavour, build, null};
|
||||||
}
|
}
|
||||||
|
@ -148,9 +154,11 @@ class BuildConfig {
|
||||||
String relativeAltSrcInclude =
|
String relativeAltSrcInclude =
|
||||||
getFieldString(null, "RelativeAltSrcInclude");
|
getFieldString(null, "RelativeAltSrcInclude");
|
||||||
Vector<String> v = getFieldVector(null, "AltRelativeInclude");
|
Vector<String> v = getFieldVector(null, "AltRelativeInclude");
|
||||||
for (String pathPart : v) {
|
if (v != null) {
|
||||||
if (path.contains(relativeAltSrcInclude + Util.sep + pathPart)) {
|
for (String pathPart : v) {
|
||||||
return true;
|
if (path.contains(relativeAltSrcInclude + Util.sep + pathPart)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -360,8 +368,7 @@ class BuildConfig {
|
||||||
|
|
||||||
static boolean appliesToTieredBuild(String cfg) {
|
static boolean appliesToTieredBuild(String cfg) {
|
||||||
return (cfg != null &&
|
return (cfg != null &&
|
||||||
(cfg.startsWith("compiler1") ||
|
cfg.startsWith("server"));
|
||||||
cfg.startsWith("compiler2")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filters out the IgnoreFile and IgnorePaths since they are
|
// Filters out the IgnoreFile and IgnorePaths since they are
|
||||||
|
@ -372,7 +379,7 @@ class BuildConfig {
|
||||||
|
|
||||||
static String getTieredBuildCfg(String cfg) {
|
static String getTieredBuildCfg(String cfg) {
|
||||||
assert appliesToTieredBuild(cfg) : "illegal configuration " + cfg;
|
assert appliesToTieredBuild(cfg) : "illegal configuration " + cfg;
|
||||||
return "tiered" + cfg.substring(9);
|
return "server";
|
||||||
}
|
}
|
||||||
|
|
||||||
static Object getField(String cfg, String field) {
|
static Object getField(String cfg, String field) {
|
||||||
|
@ -524,7 +531,7 @@ class C1DebugConfig extends GenericDebugNonKernelConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
C1DebugConfig() {
|
C1DebugConfig() {
|
||||||
initNames("compiler1", "debug", "jvm.dll");
|
initNames("client", "debug", "jvm.dll");
|
||||||
init(getIncludes(), getDefines());
|
init(getIncludes(), getDefines());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -535,7 +542,7 @@ class C1FastDebugConfig extends GenericDebugNonKernelConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
C1FastDebugConfig() {
|
C1FastDebugConfig() {
|
||||||
initNames("compiler1", "fastdebug", "jvm.dll");
|
initNames("client", "fastdebug", "jvm.dll");
|
||||||
init(getIncludes(), getDefines());
|
init(getIncludes(), getDefines());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -546,7 +553,7 @@ class TieredDebugConfig extends GenericDebugNonKernelConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
TieredDebugConfig() {
|
TieredDebugConfig() {
|
||||||
initNames("tiered", "debug", "jvm.dll");
|
initNames("server", "debug", "jvm.dll");
|
||||||
init(getIncludes(), getDefines());
|
init(getIncludes(), getDefines());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -557,7 +564,7 @@ class TieredFastDebugConfig extends GenericDebugNonKernelConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
TieredFastDebugConfig() {
|
TieredFastDebugConfig() {
|
||||||
initNames("tiered", "fastdebug", "jvm.dll");
|
initNames("server", "fastdebug", "jvm.dll");
|
||||||
init(getIncludes(), getDefines());
|
init(getIncludes(), getDefines());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -576,14 +583,14 @@ abstract class ProductConfig extends BuildConfig {
|
||||||
|
|
||||||
class C1ProductConfig extends ProductConfig {
|
class C1ProductConfig extends ProductConfig {
|
||||||
C1ProductConfig() {
|
C1ProductConfig() {
|
||||||
initNames("compiler1", "product", "jvm.dll");
|
initNames("client", "product", "jvm.dll");
|
||||||
init(getIncludes(), getDefines());
|
init(getIncludes(), getDefines());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TieredProductConfig extends ProductConfig {
|
class TieredProductConfig extends ProductConfig {
|
||||||
TieredProductConfig() {
|
TieredProductConfig() {
|
||||||
initNames("tiered", "product", "jvm.dll");
|
initNames("server", "product", "jvm.dll");
|
||||||
init(getIncludes(), getDefines());
|
init(getIncludes(), getDefines());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1,29 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 2016, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package build.tools.projectcreator;
|
||||||
|
|
||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.SimpleFileVisitor;
|
import java.nio.file.SimpleFileVisitor;
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,6 +22,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
package build.tools.projectcreator;
|
||||||
|
|
||||||
import static java.nio.file.FileVisitResult.CONTINUE;
|
import static java.nio.file.FileVisitResult.CONTINUE;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,6 +22,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
package build.tools.projectcreator;
|
||||||
|
|
||||||
public class ProjectCreator {
|
public class ProjectCreator {
|
||||||
|
|
||||||
public static void usage() {
|
public static void usage() {
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,6 +22,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
package build.tools.projectcreator;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,6 +22,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
package build.tools.projectcreator;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
@ -317,6 +319,18 @@ public abstract class WinGammaPlatform {
|
||||||
HsArgHandler.STRING
|
HsArgHandler.STRING
|
||||||
),
|
),
|
||||||
|
|
||||||
|
new HsArgRule("-makeBinary",
|
||||||
|
"MakeBinary",
|
||||||
|
null,
|
||||||
|
HsArgHandler.STRING
|
||||||
|
),
|
||||||
|
|
||||||
|
new HsArgRule("-makeOutput",
|
||||||
|
"MakeOutput",
|
||||||
|
null,
|
||||||
|
HsArgHandler.STRING
|
||||||
|
),
|
||||||
|
|
||||||
new HsArgRule("-platformName",
|
new HsArgRule("-platformName",
|
||||||
"PlatformName",
|
"PlatformName",
|
||||||
null,
|
null,
|
||||||
|
@ -554,10 +568,6 @@ public abstract class WinGammaPlatform {
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BuildConfig.getField(null, "UseToGeneratePch") == null) {
|
|
||||||
throw new RuntimeException("ERROR: need to specify one file to compute PCH, with -useToGeneratePch flag");
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildConfig.putField(null, "PlatformObject", this);
|
BuildConfig.putField(null, "PlatformObject", this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,6 +22,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
package build.tools.projectcreator;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -71,6 +73,7 @@ public class WinGammaPlatformVC10 extends WinGammaPlatform {
|
||||||
|
|
||||||
startTag("PropertyGroup", "Label", "Globals");
|
startTag("PropertyGroup", "Label", "Globals");
|
||||||
tagData("ProjectGuid", "{8822CB5C-1C41-41C2-8493-9F6E1994338B}");
|
tagData("ProjectGuid", "{8822CB5C-1C41-41C2-8493-9F6E1994338B}");
|
||||||
|
tagData("Keyword", "MakeFileProj");
|
||||||
tag("SccProjectName");
|
tag("SccProjectName");
|
||||||
tag("SccLocalPath");
|
tag("SccLocalPath");
|
||||||
endTag();
|
endTag();
|
||||||
|
@ -79,9 +82,8 @@ public class WinGammaPlatformVC10 extends WinGammaPlatform {
|
||||||
|
|
||||||
for (BuildConfig cfg : allConfigs) {
|
for (BuildConfig cfg : allConfigs) {
|
||||||
startTag(cfg, "PropertyGroup", "Label", "Configuration");
|
startTag(cfg, "PropertyGroup", "Label", "Configuration");
|
||||||
tagData("ConfigurationType", "DynamicLibrary");
|
tagData("ConfigurationType", "Makefile");
|
||||||
tagData("UseOfMfc", "false");
|
tagData("UseDebugLibraries", "true");
|
||||||
tagData("PlatformToolset", "v120");
|
|
||||||
endTag();
|
endTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +113,14 @@ public class WinGammaPlatformVC10 extends WinGammaPlatform {
|
||||||
tag(cfg, "CodeAnalysisRules");
|
tag(cfg, "CodeAnalysisRules");
|
||||||
tag(cfg, "CodeAnalysisRuleAssemblies");
|
tag(cfg, "CodeAnalysisRuleAssemblies");
|
||||||
}
|
}
|
||||||
|
for (BuildConfig cfg : allConfigs) {
|
||||||
|
tagData(cfg, "NMakeBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile import-hotspot LOG=info");
|
||||||
|
tagData(cfg, "NMakeReBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot import-hotspot LOG=info");
|
||||||
|
tagData(cfg, "NMakeCleanCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot LOG=info");
|
||||||
|
tagData(cfg, "NMakeOutput", cfg.get("MakeOutput") + Util.sep + "jvm.dll");
|
||||||
|
tagData(cfg, "NMakePreprocessorDefinitions", Util.join(";", cfg.getDefines()));
|
||||||
|
tagData(cfg, "NMakeIncludeSearchPath", Util.join(";", cfg.getIncludes()));
|
||||||
|
}
|
||||||
endTag();
|
endTag();
|
||||||
|
|
||||||
for (BuildConfig cfg : allConfigs) {
|
for (BuildConfig cfg : allConfigs) {
|
||||||
|
@ -123,11 +133,6 @@ public class WinGammaPlatformVC10 extends WinGammaPlatform {
|
||||||
tagV(cfg.getV("LinkerFlags"));
|
tagV(cfg.getV("LinkerFlags"));
|
||||||
endTag();
|
endTag();
|
||||||
|
|
||||||
startTag("PreLinkEvent");
|
|
||||||
tagData("Message", BuildConfig.getFieldString(null, "PrelinkDescription"));
|
|
||||||
tagData("Command", cfg.expandFormat(BuildConfig.getFieldString(null, "PrelinkCommand").replace("\t", "\r\n")));
|
|
||||||
endTag();
|
|
||||||
|
|
||||||
endTag();
|
endTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,18 +167,13 @@ public class WinGammaPlatformVC10 extends WinGammaPlatform {
|
||||||
for (BuildConfig cfg : allConfigs) {
|
for (BuildConfig cfg : allConfigs) {
|
||||||
startTag(cfg, "PropertyGroup");
|
startTag(cfg, "PropertyGroup");
|
||||||
tagData("LocalDebuggerCommand", cfg.get("JdkTargetRoot") + "\\bin\\java.exe");
|
tagData("LocalDebuggerCommand", cfg.get("JdkTargetRoot") + "\\bin\\java.exe");
|
||||||
// The JVM loads some libraries using a path relative to
|
// Since we run "make hotspot-import", we get the correct jvm.dll by java.exe.
|
||||||
// itself because it expects to be in a JRE or a JDK. The java
|
// The '-XX:+PauseAtExit' option
|
||||||
// launcher's '-XXaltjvm=' option allows the JVM to be outside
|
|
||||||
// the JRE or JDK so '-Dsun.java.launcher.is_altjvm=true'
|
|
||||||
// forces a fake JAVA_HOME relative path to be used to
|
|
||||||
// find the other libraries. The '-XX:+PauseAtExit' option
|
|
||||||
// causes the VM to wait for key press before exiting; this
|
// causes the VM to wait for key press before exiting; this
|
||||||
// allows any stdout or stderr messages to be seen before
|
// allows any stdout or stderr messages to be seen before
|
||||||
// the cmdtool exits.
|
// the cmdtool exits.
|
||||||
tagData("LocalDebuggerCommandArguments", "-XXaltjvm=$(TargetDir) "
|
tagData("LocalDebuggerCommandArguments",
|
||||||
+ "-Dsun.java.launcher.is_altjvm=true "
|
"-XX:+UnlockDiagnosticVMOptions -XX:+PauseAtExit");
|
||||||
+ "-XX:+UnlockDiagnosticVMOptions -XX:+PauseAtExit");
|
|
||||||
tagData("LocalDebuggerEnvironment", "JAVA_HOME=" + cfg.get("JdkTargetRoot"));
|
tagData("LocalDebuggerEnvironment", "JAVA_HOME=" + cfg.get("JdkTargetRoot"));
|
||||||
endTag();
|
endTag();
|
||||||
}
|
}
|
||||||
|
@ -209,11 +209,6 @@ public class WinGammaPlatformVC10 extends WinGammaPlatform {
|
||||||
tagData("UniqueIdentifier", "{" + uuid.toString() + "}");
|
tagData("UniqueIdentifier", "{" + uuid.toString() + "}");
|
||||||
endTag();
|
endTag();
|
||||||
}
|
}
|
||||||
startTag("Filter", "Include", "Resource Files");
|
|
||||||
UUID uuid = UUID.randomUUID();
|
|
||||||
tagData("UniqueIdentifier", "{" + uuid.toString() + "}");
|
|
||||||
tagData("Extensions", "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe");
|
|
||||||
endTag();
|
|
||||||
endTag();
|
endTag();
|
||||||
|
|
||||||
//TODO - do I need to split cpp and hpp files?
|
//TODO - do I need to split cpp and hpp files?
|
67
hotspot/make/test/GtestImage.gmk
Normal file
67
hotspot/make/test/GtestImage.gmk
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016, 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
include $(SPEC)
|
||||||
|
include MakeBase.gmk
|
||||||
|
|
||||||
|
$(foreach v, $(JVM_VARIANTS), \
|
||||||
|
$(eval $(call SetupCopyFiles, COPY_GTEST_$v, \
|
||||||
|
SRC := $(HOTSPOT_OUTPUTDIR)/variant-$v/libjvm/gtest, \
|
||||||
|
DEST := $(TEST_IMAGE_DIR)/hotspot/gtest/$v, \
|
||||||
|
FILES := $(call SHARED_LIBRARY,jvm) gtestLauncher$(EXE_SUFFIX), \
|
||||||
|
)) \
|
||||||
|
$(eval TARGETS += $$(COPY_GTEST_$v)) \
|
||||||
|
)
|
||||||
|
|
||||||
|
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||||
|
$(foreach v, $(JVM_VARIANTS), \
|
||||||
|
$(eval $(call SetupCopyFiles, COPY_GTEST_MSVCR_$v, \
|
||||||
|
DEST := $(TEST_IMAGE_DIR)/hotspot/gtest/$v, \
|
||||||
|
FILES := $(MSVCR_DLL) $(MSVCP_DLL), \
|
||||||
|
FLATTEN := true, \
|
||||||
|
)) \
|
||||||
|
$(eval TARGETS += $$(COPY_GTEST_MSVCR_$v)) \
|
||||||
|
$(eval $(call SetupCopyFiles, COPY_GTEST_PDB_$v, \
|
||||||
|
SRC := $(HOTSPOT_OUTPUTDIR)/variant-$v/libjvm/gtest, \
|
||||||
|
DEST := $(TEST_IMAGE_DIR)/hotspot/gtest/$v, \
|
||||||
|
FILES := jvm.pdb gtestLauncher.pdb, \
|
||||||
|
)) \
|
||||||
|
$(eval TARGETS += $$(COPY_GTEST_PDB_$v)) \
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OPENJDK_TARGET_OS), solaris)
|
||||||
|
$(foreach v, $(JVM_VARIANTS), \
|
||||||
|
$(eval $(call SetupCopyFiles, COPY_GTEST_STLPORT_$v, \
|
||||||
|
DEST := $(TEST_IMAGE_DIR)/hotspot/gtest/$v, \
|
||||||
|
FILES := $(STLPORT_LIB), \
|
||||||
|
)) \
|
||||||
|
$(eval TARGETS += $$(COPY_GTEST_STLPORT_$v)) \
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: $(TARGETS)
|
|
@ -27,12 +27,12 @@
|
||||||
#include "interp_masm_aarch64.hpp"
|
#include "interp_masm_aarch64.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "interpreter/interpreterRuntime.hpp"
|
#include "interpreter/interpreterRuntime.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
#include "oops/arrayOop.hpp"
|
#include "oops/arrayOop.hpp"
|
||||||
#include "oops/markOop.hpp"
|
#include "oops/markOop.hpp"
|
||||||
#include "oops/methodData.hpp"
|
#include "oops/methodData.hpp"
|
||||||
#include "oops/method.hpp"
|
#include "oops/method.hpp"
|
||||||
#include "prims/jvmtiExport.hpp"
|
#include "prims/jvmtiExport.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "prims/jvmtiThreadState.hpp"
|
#include "prims/jvmtiThreadState.hpp"
|
||||||
#include "runtime/basicLock.hpp"
|
#include "runtime/basicLock.hpp"
|
||||||
#include "runtime/biasedLocking.hpp"
|
#include "runtime/biasedLocking.hpp"
|
||||||
|
@ -1450,7 +1450,7 @@ void InterpreterMacroAssembler::notify_method_entry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedefineClasses() tracing support for obsolete method entry
|
// RedefineClasses() tracing support for obsolete method entry
|
||||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
if (log_is_enabled(Trace, redefine, class, obsolete)) {
|
||||||
get_method(c_rarg1);
|
get_method(c_rarg1);
|
||||||
call_VM_leaf(
|
call_VM_leaf(
|
||||||
CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
|
CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
|
||||||
|
|
|
@ -31,9 +31,9 @@
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "interpreter/interp_masm.hpp"
|
#include "interpreter/interp_masm.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "oops/compiledICHolder.hpp"
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
#include "runtime/vframeArray.hpp"
|
#include "runtime/vframeArray.hpp"
|
||||||
#include "vmreg_aarch64.inline.hpp"
|
#include "vmreg_aarch64.inline.hpp"
|
||||||
|
@ -1781,7 +1781,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedefineClasses() tracing support for obsolete method entry
|
// RedefineClasses() tracing support for obsolete method entry
|
||||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
if (log_is_enabled(Trace, redefine, class, obsolete)) {
|
||||||
// protect the args we've loaded
|
// protect the args we've loaded
|
||||||
save_args(masm, total_c_args, c_arg, out_regs);
|
save_args(masm, total_c_args, c_arg, out_regs);
|
||||||
__ mov_metadata(c_rarg1, method());
|
__ mov_metadata(c_rarg1, method());
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include "interpreter/interp_masm.hpp"
|
#include "interpreter/interp_masm.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "oops/compiledICHolder.hpp"
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
#include "runtime/vframeArray.hpp"
|
#include "runtime/vframeArray.hpp"
|
||||||
#include "vmreg_ppc.inline.hpp"
|
#include "vmreg_ppc.inline.hpp"
|
||||||
|
|
|
@ -825,17 +825,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following routine generates a subroutine to throw an asynchronous
|
|
||||||
// UnknownError when an unsafe access gets a fault that could not be
|
|
||||||
// reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.)
|
|
||||||
//
|
|
||||||
address generate_handler_for_unsafe_access() {
|
|
||||||
StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
|
|
||||||
address start = __ function_entry();
|
|
||||||
__ unimplemented("StubRoutines::handler_for_unsafe_access", 93);
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(PRODUCT)
|
#if !defined(PRODUCT)
|
||||||
// Wrapper which calls oopDesc::is_oop_or_null()
|
// Wrapper which calls oopDesc::is_oop_or_null()
|
||||||
// Only called by MacroAssembler::verify_oop
|
// Only called by MacroAssembler::verify_oop
|
||||||
|
@ -3111,8 +3100,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false);
|
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false);
|
||||||
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false);
|
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false);
|
||||||
|
|
||||||
StubRoutines::_handler_for_unsafe_access_entry = generate_handler_for_unsafe_access();
|
|
||||||
|
|
||||||
// support for verify_oop (must happen after universe_init)
|
// support for verify_oop (must happen after universe_init)
|
||||||
StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop();
|
StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop();
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,13 @@
|
||||||
#include "interp_masm_sparc.hpp"
|
#include "interp_masm_sparc.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "interpreter/interpreterRuntime.hpp"
|
#include "interpreter/interpreterRuntime.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
#include "oops/arrayOop.hpp"
|
#include "oops/arrayOop.hpp"
|
||||||
#include "oops/markOop.hpp"
|
#include "oops/markOop.hpp"
|
||||||
#include "oops/methodData.hpp"
|
#include "oops/methodData.hpp"
|
||||||
#include "oops/method.hpp"
|
#include "oops/method.hpp"
|
||||||
#include "oops/methodCounters.hpp"
|
#include "oops/methodCounters.hpp"
|
||||||
#include "prims/jvmtiExport.hpp"
|
#include "prims/jvmtiExport.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "prims/jvmtiThreadState.hpp"
|
#include "prims/jvmtiThreadState.hpp"
|
||||||
#include "runtime/basicLock.hpp"
|
#include "runtime/basicLock.hpp"
|
||||||
#include "runtime/biasedLocking.hpp"
|
#include "runtime/biasedLocking.hpp"
|
||||||
|
@ -2645,7 +2645,7 @@ void InterpreterMacroAssembler::notify_method_entry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedefineClasses() tracing support for obsolete method entry
|
// RedefineClasses() tracing support for obsolete method entry
|
||||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
if (log_is_enabled(Trace, redefine, class, obsolete)) {
|
||||||
call_VM_leaf(noreg,
|
call_VM_leaf(noreg,
|
||||||
CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
|
CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
|
||||||
G2_thread, Lmethod);
|
G2_thread, Lmethod);
|
||||||
|
|
|
@ -28,9 +28,9 @@
|
||||||
#include "code/icBuffer.hpp"
|
#include "code/icBuffer.hpp"
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "oops/compiledICHolder.hpp"
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
#include "runtime/vframeArray.hpp"
|
#include "runtime/vframeArray.hpp"
|
||||||
#include "vmreg_sparc.inline.hpp"
|
#include "vmreg_sparc.inline.hpp"
|
||||||
|
@ -2450,7 +2450,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedefineClasses() tracing support for obsolete method entry
|
// RedefineClasses() tracing support for obsolete method entry
|
||||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
if (log_is_enabled(Trace, redefine, class, obsolete)) {
|
||||||
// create inner frame
|
// create inner frame
|
||||||
__ save_frame(0);
|
__ save_frame(0);
|
||||||
__ mov(G2_thread, L7_thread_cache);
|
__ mov(G2_thread, L7_thread_cache);
|
||||||
|
|
|
@ -64,20 +64,6 @@ static const Register& Lstub_temp = L2;
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
// Stub Code definitions
|
// Stub Code definitions
|
||||||
|
|
||||||
static address handle_unsafe_access() {
|
|
||||||
JavaThread* thread = JavaThread::current();
|
|
||||||
address pc = thread->saved_exception_pc();
|
|
||||||
address npc = thread->saved_exception_npc();
|
|
||||||
// pc is the instruction which we must emulate
|
|
||||||
// doing a no-op is fine: return garbage from the load
|
|
||||||
|
|
||||||
// request an async exception
|
|
||||||
thread->set_pending_unsafe_access_error();
|
|
||||||
|
|
||||||
// return address of next instruction to execute
|
|
||||||
return npc;
|
|
||||||
}
|
|
||||||
|
|
||||||
class StubGenerator: public StubCodeGenerator {
|
class StubGenerator: public StubCodeGenerator {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -746,62 +732,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
Label _atomic_add_stub; // called from other stubs
|
Label _atomic_add_stub; // called from other stubs
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------------
|
|
||||||
// The following routine generates a subroutine to throw an asynchronous
|
|
||||||
// UnknownError when an unsafe access gets a fault that could not be
|
|
||||||
// reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.)
|
|
||||||
//
|
|
||||||
// Arguments :
|
|
||||||
//
|
|
||||||
// trapping PC: O7
|
|
||||||
//
|
|
||||||
// Results:
|
|
||||||
// posts an asynchronous exception, skips the trapping instruction
|
|
||||||
//
|
|
||||||
|
|
||||||
address generate_handler_for_unsafe_access() {
|
|
||||||
StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
|
|
||||||
address start = __ pc();
|
|
||||||
|
|
||||||
const int preserve_register_words = (64 * 2);
|
|
||||||
Address preserve_addr(FP, (-preserve_register_words * wordSize) + STACK_BIAS);
|
|
||||||
|
|
||||||
Register Lthread = L7_thread_cache;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
__ save_frame(0);
|
|
||||||
__ mov(G1, L1);
|
|
||||||
__ mov(G2, L2);
|
|
||||||
__ mov(G3, L3);
|
|
||||||
__ mov(G4, L4);
|
|
||||||
__ mov(G5, L5);
|
|
||||||
for (i = 0; i < 64; i += 2) {
|
|
||||||
__ stf(FloatRegisterImpl::D, as_FloatRegister(i), preserve_addr, i * wordSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
address entry_point = CAST_FROM_FN_PTR(address, handle_unsafe_access);
|
|
||||||
BLOCK_COMMENT("call handle_unsafe_access");
|
|
||||||
__ call(entry_point, relocInfo::runtime_call_type);
|
|
||||||
__ delayed()->nop();
|
|
||||||
|
|
||||||
__ mov(L1, G1);
|
|
||||||
__ mov(L2, G2);
|
|
||||||
__ mov(L3, G3);
|
|
||||||
__ mov(L4, G4);
|
|
||||||
__ mov(L5, G5);
|
|
||||||
for (i = 0; i < 64; i += 2) {
|
|
||||||
__ ldf(FloatRegisterImpl::D, preserve_addr, as_FloatRegister(i), i * wordSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
__ verify_thread();
|
|
||||||
|
|
||||||
__ jmp(O0, 0);
|
|
||||||
__ delayed()->restore();
|
|
||||||
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Support for uint StubRoutine::Sparc::partial_subtype_check( Klass sub, Klass super );
|
// Support for uint StubRoutine::Sparc::partial_subtype_check( Klass sub, Klass super );
|
||||||
// Arguments :
|
// Arguments :
|
||||||
//
|
//
|
||||||
|
@ -5218,9 +5148,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError));
|
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError));
|
||||||
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call));
|
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call));
|
||||||
|
|
||||||
StubRoutines::_handler_for_unsafe_access_entry =
|
|
||||||
generate_handler_for_unsafe_access();
|
|
||||||
|
|
||||||
// support for verify_oop (must happen after universe_init)
|
// support for verify_oop (must happen after universe_init)
|
||||||
StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine();
|
StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine();
|
||||||
|
|
||||||
|
|
|
@ -26,12 +26,12 @@
|
||||||
#include "interp_masm_x86.hpp"
|
#include "interp_masm_x86.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "interpreter/interpreterRuntime.hpp"
|
#include "interpreter/interpreterRuntime.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
#include "oops/arrayOop.hpp"
|
#include "oops/arrayOop.hpp"
|
||||||
#include "oops/markOop.hpp"
|
#include "oops/markOop.hpp"
|
||||||
#include "oops/methodData.hpp"
|
#include "oops/methodData.hpp"
|
||||||
#include "oops/method.hpp"
|
#include "oops/method.hpp"
|
||||||
#include "prims/jvmtiExport.hpp"
|
#include "prims/jvmtiExport.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "prims/jvmtiThreadState.hpp"
|
#include "prims/jvmtiThreadState.hpp"
|
||||||
#include "runtime/basicLock.hpp"
|
#include "runtime/basicLock.hpp"
|
||||||
#include "runtime/biasedLocking.hpp"
|
#include "runtime/biasedLocking.hpp"
|
||||||
|
@ -1953,7 +1953,7 @@ void InterpreterMacroAssembler::notify_method_entry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedefineClasses() tracing support for obsolete method entry
|
// RedefineClasses() tracing support for obsolete method entry
|
||||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
if (log_is_enabled(Trace, redefine, class, obsolete)) {
|
||||||
NOT_LP64(get_thread(rthread);)
|
NOT_LP64(get_thread(rthread);)
|
||||||
get_method(rarg);
|
get_method(rarg);
|
||||||
call_VM_leaf(
|
call_VM_leaf(
|
||||||
|
|
|
@ -29,9 +29,9 @@
|
||||||
#include "code/icBuffer.hpp"
|
#include "code/icBuffer.hpp"
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "oops/compiledICHolder.hpp"
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
#include "runtime/vframeArray.hpp"
|
#include "runtime/vframeArray.hpp"
|
||||||
#include "vmreg_x86.inline.hpp"
|
#include "vmreg_x86.inline.hpp"
|
||||||
|
@ -1953,7 +1953,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedefineClasses() tracing support for obsolete method entry
|
// RedefineClasses() tracing support for obsolete method entry
|
||||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
if (log_is_enabled(Trace, redefine, class, obsolete)) {
|
||||||
__ mov_metadata(rax, method());
|
__ mov_metadata(rax, method());
|
||||||
__ call_VM_leaf(
|
__ call_VM_leaf(
|
||||||
CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
|
CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
|
||||||
|
|
|
@ -32,9 +32,9 @@
|
||||||
#include "code/icBuffer.hpp"
|
#include "code/icBuffer.hpp"
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "oops/compiledICHolder.hpp"
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
#include "runtime/vframeArray.hpp"
|
#include "runtime/vframeArray.hpp"
|
||||||
#include "vmreg_x86.inline.hpp"
|
#include "vmreg_x86.inline.hpp"
|
||||||
|
@ -2322,7 +2322,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||||
}
|
}
|
||||||
|
|
||||||
// RedefineClasses() tracing support for obsolete method entry
|
// RedefineClasses() tracing support for obsolete method entry
|
||||||
if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
|
if (log_is_enabled(Trace, redefine, class, obsolete)) {
|
||||||
// protect the args we've loaded
|
// protect the args we've loaded
|
||||||
save_args(masm, total_c_args, c_arg, out_regs);
|
save_args(masm, total_c_args, c_arg, out_regs);
|
||||||
__ mov_metadata(c_rarg1, method());
|
__ mov_metadata(c_rarg1, method());
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -63,21 +63,6 @@ const int FPU_CNTRL_WRD_MASK = 0xFFFF;
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
// Stub Code definitions
|
// Stub Code definitions
|
||||||
|
|
||||||
static address handle_unsafe_access() {
|
|
||||||
JavaThread* thread = JavaThread::current();
|
|
||||||
address pc = thread->saved_exception_pc();
|
|
||||||
// pc is the instruction which we must emulate
|
|
||||||
// doing a no-op is fine: return garbage from the load
|
|
||||||
// therefore, compute npc
|
|
||||||
address npc = Assembler::locate_next_instruction(pc);
|
|
||||||
|
|
||||||
// request an async exception
|
|
||||||
thread->set_pending_unsafe_access_error();
|
|
||||||
|
|
||||||
// return address of next instruction to execute
|
|
||||||
return npc;
|
|
||||||
}
|
|
||||||
|
|
||||||
class StubGenerator: public StubCodeGenerator {
|
class StubGenerator: public StubCodeGenerator {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -623,27 +608,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
// The following routine generates a subroutine to throw an asynchronous
|
|
||||||
// UnknownError when an unsafe access gets a fault that could not be
|
|
||||||
// reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.)
|
|
||||||
address generate_handler_for_unsafe_access() {
|
|
||||||
StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
|
|
||||||
address start = __ pc();
|
|
||||||
|
|
||||||
__ push(0); // hole for return address-to-be
|
|
||||||
__ pusha(); // push registers
|
|
||||||
Address next_pc(rsp, RegisterImpl::number_of_registers * BytesPerWord);
|
|
||||||
BLOCK_COMMENT("call handle_unsafe_access");
|
|
||||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, handle_unsafe_access)));
|
|
||||||
__ movptr(next_pc, rax); // stuff next address
|
|
||||||
__ popa();
|
|
||||||
__ ret(0); // jump to next address
|
|
||||||
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Non-destructive plausibility checks for oops
|
// Non-destructive plausibility checks for oops
|
||||||
|
|
||||||
|
@ -3865,9 +3829,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
// These are currently used by Solaris/Intel
|
// These are currently used by Solaris/Intel
|
||||||
StubRoutines::_atomic_xchg_entry = generate_atomic_xchg();
|
StubRoutines::_atomic_xchg_entry = generate_atomic_xchg();
|
||||||
|
|
||||||
StubRoutines::_handler_for_unsafe_access_entry =
|
|
||||||
generate_handler_for_unsafe_access();
|
|
||||||
|
|
||||||
// platform dependent
|
// platform dependent
|
||||||
create_control_words();
|
create_control_words();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -61,21 +61,6 @@ const int MXCSR_MASK = 0xFFC0; // Mask out any pending exceptions
|
||||||
|
|
||||||
// Stub Code definitions
|
// Stub Code definitions
|
||||||
|
|
||||||
static address handle_unsafe_access() {
|
|
||||||
JavaThread* thread = JavaThread::current();
|
|
||||||
address pc = thread->saved_exception_pc();
|
|
||||||
// pc is the instruction which we must emulate
|
|
||||||
// doing a no-op is fine: return garbage from the load
|
|
||||||
// therefore, compute npc
|
|
||||||
address npc = Assembler::locate_next_instruction(pc);
|
|
||||||
|
|
||||||
// request an async exception
|
|
||||||
thread->set_pending_unsafe_access_error();
|
|
||||||
|
|
||||||
// return address of next instruction to execute
|
|
||||||
return npc;
|
|
||||||
}
|
|
||||||
|
|
||||||
class StubGenerator: public StubCodeGenerator {
|
class StubGenerator: public StubCodeGenerator {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -989,32 +974,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following routine generates a subroutine to throw an
|
|
||||||
// asynchronous UnknownError when an unsafe access gets a fault that
|
|
||||||
// could not be reasonably prevented by the programmer. (Example:
|
|
||||||
// SIGBUS/OBJERR.)
|
|
||||||
address generate_handler_for_unsafe_access() {
|
|
||||||
StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
|
|
||||||
address start = __ pc();
|
|
||||||
|
|
||||||
__ push(0); // hole for return address-to-be
|
|
||||||
__ pusha(); // push registers
|
|
||||||
Address next_pc(rsp, RegisterImpl::number_of_registers * BytesPerWord);
|
|
||||||
|
|
||||||
// FIXME: this probably needs alignment logic
|
|
||||||
|
|
||||||
__ subptr(rsp, frame::arg_reg_save_area_bytes);
|
|
||||||
BLOCK_COMMENT("call handle_unsafe_access");
|
|
||||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, handle_unsafe_access)));
|
|
||||||
__ addptr(rsp, frame::arg_reg_save_area_bytes);
|
|
||||||
|
|
||||||
__ movptr(next_pc, rax); // stuff next address
|
|
||||||
__ popa();
|
|
||||||
__ ret(0); // jump to next address
|
|
||||||
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non-destructive plausibility checks for oops
|
// Non-destructive plausibility checks for oops
|
||||||
//
|
//
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
@ -5139,9 +5098,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
StubRoutines::_atomic_add_ptr_entry = generate_atomic_add_ptr();
|
StubRoutines::_atomic_add_ptr_entry = generate_atomic_add_ptr();
|
||||||
StubRoutines::_fence_entry = generate_orderaccess_fence();
|
StubRoutines::_fence_entry = generate_orderaccess_fence();
|
||||||
|
|
||||||
StubRoutines::_handler_for_unsafe_access_entry =
|
|
||||||
generate_handler_for_unsafe_access();
|
|
||||||
|
|
||||||
// platform dependent
|
// platform dependent
|
||||||
StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp();
|
StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp();
|
||||||
StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp();
|
StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp();
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "oops/compiledICHolder.hpp"
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
#include "runtime/vframeArray.hpp"
|
#include "runtime/vframeArray.hpp"
|
||||||
#include "vmreg_zero.inline.hpp"
|
#include "vmreg_zero.inline.hpp"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright 2007, 2008, 2010, 2015 Red Hat, Inc.
|
* Copyright 2007, 2008, 2010, 2015 Red Hat, Inc.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
|
@ -261,10 +261,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
StubRoutines::_atomic_add_entry = ShouldNotCallThisStub();
|
StubRoutines::_atomic_add_entry = ShouldNotCallThisStub();
|
||||||
StubRoutines::_atomic_add_ptr_entry = ShouldNotCallThisStub();
|
StubRoutines::_atomic_add_ptr_entry = ShouldNotCallThisStub();
|
||||||
StubRoutines::_fence_entry = ShouldNotCallThisStub();
|
StubRoutines::_fence_entry = ShouldNotCallThisStub();
|
||||||
|
|
||||||
// amd64 does this here, sparc does it in generate_all()
|
|
||||||
StubRoutines::_handler_for_unsafe_access_entry =
|
|
||||||
ShouldNotCallThisStub();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_all() {
|
void generate_all() {
|
||||||
|
|
|
@ -47,6 +47,12 @@
|
||||||
|
|
||||||
// Check core dump limit and report possible place where core can be found
|
// Check core dump limit and report possible place where core can be found
|
||||||
void os::check_dump_limit(char* buffer, size_t bufferSize) {
|
void os::check_dump_limit(char* buffer, size_t bufferSize) {
|
||||||
|
if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
|
||||||
|
jio_snprintf(buffer, bufferSize, "CreateCoredumpOnCrash is disabled from command line");
|
||||||
|
VMError::record_coredump_status(buffer, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
struct rlimit rlim;
|
struct rlimit rlim;
|
||||||
bool success;
|
bool success;
|
||||||
|
|
|
@ -392,11 +392,9 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
|
||||||
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
||||||
CompiledMethod* nm = cb->as_compiled_method_or_null();
|
CompiledMethod* nm = cb->as_compiled_method_or_null();
|
||||||
if (nm != NULL && nm->has_unsafe_access()) {
|
if (nm != NULL && nm->has_unsafe_access()) {
|
||||||
// We don't really need a stub here! Just set the pending exeption and
|
address next_pc = pc + 4;
|
||||||
// continue at the next instruction after the faulting read. Returning
|
next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
|
||||||
// garbage from this read is ok.
|
os::Aix::ucontext_set_pc(uc, next_pc);
|
||||||
thread->set_pending_unsafe_access_error();
|
|
||||||
os::Aix::ucontext_set_pc(uc, pc + 4);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,11 +413,9 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
|
||||||
}
|
}
|
||||||
else if (thread->thread_state() == _thread_in_vm &&
|
else if (thread->thread_state() == _thread_in_vm &&
|
||||||
sig == SIGBUS && thread->doing_unsafe_access()) {
|
sig == SIGBUS && thread->doing_unsafe_access()) {
|
||||||
// We don't really need a stub here! Just set the pending exeption and
|
address next_pc = pc + 4;
|
||||||
// continue at the next instruction after the faulting read. Returning
|
next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
|
||||||
// garbage from this read is ok.
|
os::Aix::ucontext_set_pc(uc, next_pc);
|
||||||
thread->set_pending_unsafe_access_error();
|
|
||||||
os::Aix::ucontext_set_pc(uc, pc + 4);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -584,7 +584,8 @@ JVM_handle_bsd_signal(int sig,
|
||||||
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
||||||
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
|
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
|
||||||
if (nm != NULL && nm->has_unsafe_access()) {
|
if (nm != NULL && nm->has_unsafe_access()) {
|
||||||
stub = StubRoutines::handler_for_unsafe_access();
|
address next_pc = Assembler::locate_next_instruction(pc);
|
||||||
|
stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -655,7 +656,8 @@ JVM_handle_bsd_signal(int sig,
|
||||||
} else if (thread->thread_state() == _thread_in_vm &&
|
} else if (thread->thread_state() == _thread_in_vm &&
|
||||||
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
|
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
|
||||||
thread->doing_unsafe_access()) {
|
thread->doing_unsafe_access()) {
|
||||||
stub = StubRoutines::handler_for_unsafe_access();
|
address next_pc = Assembler::locate_next_instruction(pc);
|
||||||
|
stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
|
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
|
||||||
|
|
|
@ -226,23 +226,6 @@ extern "C" void FetchNPFI () ;
|
||||||
extern "C" void FetchNResume () ;
|
extern "C" void FetchNResume () ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// An operation in Unsafe has faulted. We're going to return to the
|
|
||||||
// instruction after the faulting load or store. We also set
|
|
||||||
// pending_unsafe_access_error so that at some point in the future our
|
|
||||||
// user will get a helpful message.
|
|
||||||
static address handle_unsafe_access(JavaThread* thread, address pc) {
|
|
||||||
// pc is the instruction which we must emulate
|
|
||||||
// doing a no-op is fine: return garbage from the load
|
|
||||||
// therefore, compute npc
|
|
||||||
address npc = pc + NativeCall::instruction_size;
|
|
||||||
|
|
||||||
// request an async exception
|
|
||||||
thread->set_pending_unsafe_access_error();
|
|
||||||
|
|
||||||
// return address of next instruction to execute
|
|
||||||
return npc;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" JNIEXPORT int
|
extern "C" JNIEXPORT int
|
||||||
JVM_handle_linux_signal(int sig,
|
JVM_handle_linux_signal(int sig,
|
||||||
siginfo_t* info,
|
siginfo_t* info,
|
||||||
|
@ -387,7 +370,8 @@ JVM_handle_linux_signal(int sig,
|
||||||
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
||||||
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
|
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
|
||||||
if (nm != NULL && nm->has_unsafe_access()) {
|
if (nm != NULL && nm->has_unsafe_access()) {
|
||||||
stub = handle_unsafe_access(thread, pc);
|
address next_pc = pc + NativeCall::instruction_size;
|
||||||
|
stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -408,7 +392,8 @@ JVM_handle_linux_signal(int sig,
|
||||||
} else if (thread->thread_state() == _thread_in_vm &&
|
} else if (thread->thread_state() == _thread_in_vm &&
|
||||||
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
|
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
|
||||||
thread->doing_unsafe_access()) {
|
thread->doing_unsafe_access()) {
|
||||||
stub = handle_unsafe_access(thread, pc);
|
address next_pc = pc + NativeCall::instruction_size;
|
||||||
|
stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
|
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
|
||||||
|
|
|
@ -366,11 +366,9 @@ JVM_handle_linux_signal(int sig,
|
||||||
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
||||||
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
|
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
|
||||||
if (nm != NULL && nm->has_unsafe_access()) {
|
if (nm != NULL && nm->has_unsafe_access()) {
|
||||||
// We don't really need a stub here! Just set the pending exeption and
|
address next_pc = pc + 4;
|
||||||
// continue at the next instruction after the faulting read. Returning
|
next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
|
||||||
// garbage from this read is ok.
|
os::Linux::ucontext_set_pc(uc, next_pc);
|
||||||
thread->set_pending_unsafe_access_error();
|
|
||||||
os::Linux::ucontext_set_pc(uc, pc + 4);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,10 +383,8 @@ JVM_handle_linux_signal(int sig,
|
||||||
}
|
}
|
||||||
else if (thread->thread_state() == _thread_in_vm &&
|
else if (thread->thread_state() == _thread_in_vm &&
|
||||||
sig == SIGBUS && thread->doing_unsafe_access()) {
|
sig == SIGBUS && thread->doing_unsafe_access()) {
|
||||||
// We don't really need a stub here! Just set the pending exeption and
|
address next_pc = pc + 4;
|
||||||
// continue at the next instruction after the faulting read. Returning
|
next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
|
||||||
// garbage from this read is ok.
|
|
||||||
thread->set_pending_unsafe_access_error();
|
|
||||||
os::Linux::ucontext_set_pc(uc, pc + 4);
|
os::Linux::ucontext_set_pc(uc, pc + 4);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -433,14 +433,14 @@ inline static bool checkPollingPage(address pc, address fault, address* stub) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static bool checkByteBuffer(address pc, address* stub) {
|
inline static bool checkByteBuffer(address pc, address npc, address* stub) {
|
||||||
// BugId 4454115: A read from a MappedByteBuffer can fault
|
// BugId 4454115: A read from a MappedByteBuffer can fault
|
||||||
// here if the underlying file has been truncated.
|
// here if the underlying file has been truncated.
|
||||||
// Do not crash the VM in such a case.
|
// Do not crash the VM in such a case.
|
||||||
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
||||||
CompiledMethod* nm = cb->as_compiled_method_or_null();
|
CompiledMethod* nm = cb->as_compiled_method_or_null();
|
||||||
if (nm != NULL && nm->has_unsafe_access()) {
|
if (nm != NULL && nm->has_unsafe_access()) {
|
||||||
*stub = StubRoutines::handler_for_unsafe_access();
|
*stub = SharedRuntime::handle_unsafe_access(thread, npc);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -613,7 +613,7 @@ JVM_handle_linux_signal(int sig,
|
||||||
if (sig == SIGBUS &&
|
if (sig == SIGBUS &&
|
||||||
thread->thread_state() == _thread_in_vm &&
|
thread->thread_state() == _thread_in_vm &&
|
||||||
thread->doing_unsafe_access()) {
|
thread->doing_unsafe_access()) {
|
||||||
stub = StubRoutines::handler_for_unsafe_access();
|
stub = SharedRuntime::handle_unsafe_access(thread, npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread->thread_state() == _thread_in_Java) {
|
if (thread->thread_state() == _thread_in_Java) {
|
||||||
|
@ -625,7 +625,7 @@ JVM_handle_linux_signal(int sig,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sig == SIGBUS) && checkByteBuffer(pc, &stub)) {
|
if ((sig == SIGBUS) && checkByteBuffer(pc, npc, &stub)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -420,7 +420,8 @@ JVM_handle_linux_signal(int sig,
|
||||||
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
||||||
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
|
CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
|
||||||
if (nm != NULL && nm->has_unsafe_access()) {
|
if (nm != NULL && nm->has_unsafe_access()) {
|
||||||
stub = StubRoutines::handler_for_unsafe_access();
|
address next_pc = Assembler::locate_next_instruction(pc);
|
||||||
|
stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -469,7 +470,8 @@ JVM_handle_linux_signal(int sig,
|
||||||
} else if (thread->thread_state() == _thread_in_vm &&
|
} else if (thread->thread_state() == _thread_in_vm &&
|
||||||
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
|
sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
|
||||||
thread->doing_unsafe_access()) {
|
thread->doing_unsafe_access()) {
|
||||||
stub = StubRoutines::handler_for_unsafe_access();
|
address next_pc = Assembler::locate_next_instruction(pc);
|
||||||
|
stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
|
// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in
|
||||||
|
|
|
@ -441,7 +441,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
|
||||||
|
|
||||||
if (thread->thread_state() == _thread_in_vm) {
|
if (thread->thread_state() == _thread_in_vm) {
|
||||||
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
|
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
|
||||||
stub = StubRoutines::handler_for_unsafe_access();
|
stub = SharedRuntime::handle_unsafe_access(thread, npc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,7 +480,7 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
|
||||||
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
|
||||||
CompiledMethod* nm = cb->as_compiled_method_or_null();
|
CompiledMethod* nm = cb->as_compiled_method_or_null();
|
||||||
if (nm != NULL && nm->has_unsafe_access()) {
|
if (nm != NULL && nm->has_unsafe_access()) {
|
||||||
stub = StubRoutines::handler_for_unsafe_access();
|
stub = SharedRuntime::handle_unsafe_access(thread, npc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -503,7 +503,8 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
|
||||||
|
|
||||||
if (thread->thread_state() == _thread_in_vm) {
|
if (thread->thread_state() == _thread_in_vm) {
|
||||||
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
|
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
|
||||||
stub = StubRoutines::handler_for_unsafe_access();
|
address next_pc = Assembler::locate_next_instruction(pc);
|
||||||
|
stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +521,8 @@ JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid,
|
||||||
if (cb != NULL) {
|
if (cb != NULL) {
|
||||||
CompiledMethod* nm = cb->as_compiled_method_or_null();
|
CompiledMethod* nm = cb->as_compiled_method_or_null();
|
||||||
if (nm != NULL && nm->has_unsafe_access()) {
|
if (nm != NULL && nm->has_unsafe_access()) {
|
||||||
stub = StubRoutines::handler_for_unsafe_access();
|
address next_pc = Assembler::locate_next_instruction(pc);
|
||||||
|
stub = SharedRuntime::handle_unsafe_access(thread, next_pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,20 +198,6 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) {
|
||||||
case vmIntrinsics::_putLongVolatile:
|
case vmIntrinsics::_putLongVolatile:
|
||||||
case vmIntrinsics::_putFloatVolatile:
|
case vmIntrinsics::_putFloatVolatile:
|
||||||
case vmIntrinsics::_putDoubleVolatile:
|
case vmIntrinsics::_putDoubleVolatile:
|
||||||
case vmIntrinsics::_getByte_raw:
|
|
||||||
case vmIntrinsics::_getShort_raw:
|
|
||||||
case vmIntrinsics::_getChar_raw:
|
|
||||||
case vmIntrinsics::_getInt_raw:
|
|
||||||
case vmIntrinsics::_getLong_raw:
|
|
||||||
case vmIntrinsics::_getFloat_raw:
|
|
||||||
case vmIntrinsics::_getDouble_raw:
|
|
||||||
case vmIntrinsics::_putByte_raw:
|
|
||||||
case vmIntrinsics::_putShort_raw:
|
|
||||||
case vmIntrinsics::_putChar_raw:
|
|
||||||
case vmIntrinsics::_putInt_raw:
|
|
||||||
case vmIntrinsics::_putLong_raw:
|
|
||||||
case vmIntrinsics::_putFloat_raw:
|
|
||||||
case vmIntrinsics::_putDouble_raw:
|
|
||||||
case vmIntrinsics::_getShortUnaligned:
|
case vmIntrinsics::_getShortUnaligned:
|
||||||
case vmIntrinsics::_getCharUnaligned:
|
case vmIntrinsics::_getCharUnaligned:
|
||||||
case vmIntrinsics::_getIntUnaligned:
|
case vmIntrinsics::_getIntUnaligned:
|
||||||
|
|
|
@ -3465,20 +3465,6 @@ void GraphBuilder::build_graph_for_intrinsic(ciMethod* callee) {
|
||||||
case vmIntrinsics::_putLongVolatile : append_unsafe_put_obj(callee, T_LONG, true); return;
|
case vmIntrinsics::_putLongVolatile : append_unsafe_put_obj(callee, T_LONG, true); return;
|
||||||
case vmIntrinsics::_putFloatVolatile : append_unsafe_put_obj(callee, T_FLOAT, true); return;
|
case vmIntrinsics::_putFloatVolatile : append_unsafe_put_obj(callee, T_FLOAT, true); return;
|
||||||
case vmIntrinsics::_putDoubleVolatile : append_unsafe_put_obj(callee, T_DOUBLE, true); return;
|
case vmIntrinsics::_putDoubleVolatile : append_unsafe_put_obj(callee, T_DOUBLE, true); return;
|
||||||
case vmIntrinsics::_getByte_raw : append_unsafe_get_raw(callee, T_BYTE ); return;
|
|
||||||
case vmIntrinsics::_getShort_raw : append_unsafe_get_raw(callee, T_SHORT ); return;
|
|
||||||
case vmIntrinsics::_getChar_raw : append_unsafe_get_raw(callee, T_CHAR ); return;
|
|
||||||
case vmIntrinsics::_getInt_raw : append_unsafe_get_raw(callee, T_INT ); return;
|
|
||||||
case vmIntrinsics::_getLong_raw : append_unsafe_get_raw(callee, T_LONG ); return;
|
|
||||||
case vmIntrinsics::_getFloat_raw : append_unsafe_get_raw(callee, T_FLOAT ); return;
|
|
||||||
case vmIntrinsics::_getDouble_raw : append_unsafe_get_raw(callee, T_DOUBLE); return;
|
|
||||||
case vmIntrinsics::_putByte_raw : append_unsafe_put_raw(callee, T_BYTE ); return;
|
|
||||||
case vmIntrinsics::_putShort_raw : append_unsafe_put_raw(callee, T_SHORT ); return;
|
|
||||||
case vmIntrinsics::_putChar_raw : append_unsafe_put_raw(callee, T_CHAR ); return;
|
|
||||||
case vmIntrinsics::_putInt_raw : append_unsafe_put_raw(callee, T_INT ); return;
|
|
||||||
case vmIntrinsics::_putLong_raw : append_unsafe_put_raw(callee, T_LONG ); return;
|
|
||||||
case vmIntrinsics::_putFloat_raw : append_unsafe_put_raw(callee, T_FLOAT ); return;
|
|
||||||
case vmIntrinsics::_putDouble_raw : append_unsafe_put_raw(callee, T_DOUBLE); return;
|
|
||||||
case vmIntrinsics::_compareAndSwapLong:
|
case vmIntrinsics::_compareAndSwapLong:
|
||||||
case vmIntrinsics::_compareAndSwapInt:
|
case vmIntrinsics::_compareAndSwapInt:
|
||||||
case vmIntrinsics::_compareAndSwapObject: append_unsafe_CAS(callee); return;
|
case vmIntrinsics::_compareAndSwapObject: append_unsafe_CAS(callee); return;
|
||||||
|
|
|
@ -140,9 +140,10 @@ PerfCounter* ClassLoader::_unsafe_defineClassCallCounter = NULL;
|
||||||
PerfCounter* ClassLoader::_isUnsyncloadClass = NULL;
|
PerfCounter* ClassLoader::_isUnsyncloadClass = NULL;
|
||||||
PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL;
|
PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL;
|
||||||
|
|
||||||
ClassPathEntry* ClassLoader::_first_entry = NULL;
|
GrowableArray<ModuleClassPathList*>* ClassLoader::_xpatch_entries = NULL;
|
||||||
ClassPathEntry* ClassLoader::_last_entry = NULL;
|
ClassPathEntry* ClassLoader::_first_entry = NULL;
|
||||||
int ClassLoader::_num_entries = 0;
|
ClassPathEntry* ClassLoader::_last_entry = NULL;
|
||||||
|
int ClassLoader::_num_entries = 0;
|
||||||
ClassPathEntry* ClassLoader::_first_append_entry = NULL;
|
ClassPathEntry* ClassLoader::_first_append_entry = NULL;
|
||||||
bool ClassLoader::_has_jimage = false;
|
bool ClassLoader::_has_jimage = false;
|
||||||
#if INCLUDE_CDS
|
#if INCLUDE_CDS
|
||||||
|
@ -179,6 +180,44 @@ bool ClassLoader::string_ends_with(const char* str, const char* str_to_find) {
|
||||||
return (strncmp(str + (str_len - str_to_find_len), str_to_find, str_to_find_len) == 0);
|
return (strncmp(str + (str_len - str_to_find_len), str_to_find, str_to_find_len) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used to obtain the package name from a fully qualified class name.
|
||||||
|
// It is the responsibility of the caller to establish ResourceMark.
|
||||||
|
const char* ClassLoader::package_from_name(const char* class_name) {
|
||||||
|
const char* last_slash = strrchr(class_name, '/');
|
||||||
|
if (last_slash == NULL) {
|
||||||
|
// No package name
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
int length = last_slash - class_name;
|
||||||
|
|
||||||
|
// A class name could have just the slash character in the name,
|
||||||
|
// resulting in a negative length.
|
||||||
|
if (length <= 0) {
|
||||||
|
// No package name
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// drop name after last slash (including slash)
|
||||||
|
// Ex., "java/lang/String.class" => "java/lang"
|
||||||
|
char* pkg_name = NEW_RESOURCE_ARRAY(char, length + 1);
|
||||||
|
strncpy(pkg_name, class_name, length);
|
||||||
|
*(pkg_name+length) = '\0';
|
||||||
|
|
||||||
|
return (const char *)pkg_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a fully qualified class name, find its defining package in the class loader's
|
||||||
|
// package entry table.
|
||||||
|
static PackageEntry* get_package_entry(const char* class_name, ClassLoaderData* loader_data, TRAPS) {
|
||||||
|
ResourceMark rm(THREAD);
|
||||||
|
const char *pkg_name = ClassLoader::package_from_name(class_name);
|
||||||
|
if (pkg_name == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PackageEntryTable* pkgEntryTable = loader_data->packages();
|
||||||
|
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(pkg_name, CHECK_NULL);
|
||||||
|
return pkgEntryTable->lookup_only(pkg_symbol);
|
||||||
|
}
|
||||||
|
|
||||||
ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
|
ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
|
||||||
char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
|
char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
|
||||||
|
@ -281,8 +320,7 @@ u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_ter
|
||||||
#if INCLUDE_CDS
|
#if INCLUDE_CDS
|
||||||
u1* ClassPathZipEntry::open_versioned_entry(const char* name, jint* filesize, TRAPS) {
|
u1* ClassPathZipEntry::open_versioned_entry(const char* name, jint* filesize, TRAPS) {
|
||||||
u1* buffer = NULL;
|
u1* buffer = NULL;
|
||||||
if (!_is_boot_append) {
|
if (DumpSharedSpaces) {
|
||||||
assert(DumpSharedSpaces, "Should be called only for non-boot entries during dump time");
|
|
||||||
// We presume default is multi-release enabled
|
// We presume default is multi-release enabled
|
||||||
const char* multi_ver = Arguments::get_property("jdk.util.jar.enableMultiRelease");
|
const char* multi_ver = Arguments::get_property("jdk.util.jar.enableMultiRelease");
|
||||||
const char* verstr = Arguments::get_property("jdk.util.jar.version");
|
const char* verstr = Arguments::get_property("jdk.util.jar.version");
|
||||||
|
@ -399,31 +437,6 @@ ClassPathImageEntry::~ClassPathImageEntry() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassPathImageEntry::name_to_package(const char* name, char* buffer, int length) {
|
|
||||||
const char *pslash = strrchr(name, '/');
|
|
||||||
if (pslash == NULL) {
|
|
||||||
buffer[0] = '\0';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int len = pslash - name;
|
|
||||||
#if INCLUDE_CDS
|
|
||||||
if (len <= 0 && DumpSharedSpaces) {
|
|
||||||
buffer[0] = '\0';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
assert(len > 0, "Bad length for package name");
|
|
||||||
if (len >= length) {
|
|
||||||
buffer[0] = '\0';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// drop name after last slash (including slash)
|
|
||||||
// Ex., "java/lang/String.class" => "java/lang"
|
|
||||||
strncpy(buffer, name, len);
|
|
||||||
// ensure string termination (strncpy does not guarantee)
|
|
||||||
buffer[len] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
// For a class in a named module, look it up in the jimage file using this syntax:
|
// For a class in a named module, look it up in the jimage file using this syntax:
|
||||||
// /<module-name>/<package-name>/<base-class>
|
// /<module-name>/<package-name>/<base-class>
|
||||||
//
|
//
|
||||||
|
@ -436,15 +449,10 @@ ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
|
||||||
JImageLocationRef location = (*JImageFindResource)(_jimage, "", get_jimage_version_string(), name, &size);
|
JImageLocationRef location = (*JImageFindResource)(_jimage, "", get_jimage_version_string(), name, &size);
|
||||||
|
|
||||||
if (location == 0) {
|
if (location == 0) {
|
||||||
char package[JIMAGE_MAX_PATH];
|
ResourceMark rm;
|
||||||
name_to_package(name, package, JIMAGE_MAX_PATH);
|
const char* pkg_name = ClassLoader::package_from_name(name);
|
||||||
|
|
||||||
#if INCLUDE_CDS
|
if (pkg_name != NULL) {
|
||||||
if (package[0] == '\0' && DumpSharedSpaces) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (package[0] != '\0') {
|
|
||||||
if (!Universe::is_module_initialized()) {
|
if (!Universe::is_module_initialized()) {
|
||||||
location = (*JImageFindResource)(_jimage, "java.base", get_jimage_version_string(), name, &size);
|
location = (*JImageFindResource)(_jimage, "java.base", get_jimage_version_string(), name, &size);
|
||||||
#if INCLUDE_CDS
|
#if INCLUDE_CDS
|
||||||
|
@ -452,7 +460,7 @@ ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
|
||||||
// modules defined for other class loaders. So, for now, get their module
|
// modules defined for other class loaders. So, for now, get their module
|
||||||
// names from the "modules" jimage file.
|
// names from the "modules" jimage file.
|
||||||
if (DumpSharedSpaces && location == 0) {
|
if (DumpSharedSpaces && location == 0) {
|
||||||
const char* module_name = (*JImagePackageToModule)(_jimage, package);
|
const char* module_name = (*JImagePackageToModule)(_jimage, pkg_name);
|
||||||
if (module_name != NULL) {
|
if (module_name != NULL) {
|
||||||
location = (*JImageFindResource)(_jimage, module_name, get_jimage_version_string(), name, &size);
|
location = (*JImageFindResource)(_jimage, module_name, get_jimage_version_string(), name, &size);
|
||||||
}
|
}
|
||||||
|
@ -460,13 +468,7 @@ ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Get boot class loader's package entry table
|
PackageEntry* package_entry = get_package_entry(name, ClassLoaderData::the_null_class_loader_data(), THREAD);
|
||||||
PackageEntryTable* pkgEntryTable =
|
|
||||||
ClassLoaderData::the_null_class_loader_data()->packages();
|
|
||||||
// Get package's package entry
|
|
||||||
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package, CHECK_NULL);
|
|
||||||
PackageEntry* package_entry = pkgEntryTable->lookup_only(pkg_symbol);
|
|
||||||
|
|
||||||
if (package_entry != NULL) {
|
if (package_entry != NULL) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
// Get the module name
|
// Get the module name
|
||||||
|
@ -539,6 +541,33 @@ void ClassLoader::exit_with_path_failure(const char* error, const char* message)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ModuleClassPathList::ModuleClassPathList(Symbol* module_name) {
|
||||||
|
_module_name = module_name;
|
||||||
|
_module_first_entry = NULL;
|
||||||
|
_module_last_entry = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModuleClassPathList::~ModuleClassPathList() {
|
||||||
|
// Clean out each ClassPathEntry on list
|
||||||
|
ClassPathEntry* e = _module_first_entry;
|
||||||
|
while (e != NULL) {
|
||||||
|
ClassPathEntry* next_entry = e->next();
|
||||||
|
delete e;
|
||||||
|
e = next_entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleClassPathList::add_to_list(ClassPathEntry* new_entry) {
|
||||||
|
if (new_entry != NULL) {
|
||||||
|
if (_module_last_entry == NULL) {
|
||||||
|
_module_first_entry = _module_last_entry = new_entry;
|
||||||
|
} else {
|
||||||
|
_module_last_entry->set_next(new_entry);
|
||||||
|
_module_last_entry = new_entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ClassLoader::trace_class_path(const char* msg, const char* name) {
|
void ClassLoader::trace_class_path(const char* msg, const char* name) {
|
||||||
if (log_is_enabled(Info, class, path)) {
|
if (log_is_enabled(Info, class, path)) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
|
@ -616,6 +645,61 @@ bool ClassLoader::check_shared_paths_misc_info(void *buf, int size) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Construct the array of module/path pairs as specified to -Xpatch
|
||||||
|
// for the boot loader to search ahead of the jimage, if the class being
|
||||||
|
// loaded is defined to a module that has been specified to -Xpatch.
|
||||||
|
void ClassLoader::setup_xpatch_entries() {
|
||||||
|
Thread* THREAD = Thread::current();
|
||||||
|
GrowableArray<ModuleXPatchPath*>* xpatch_args = Arguments::get_xpatchprefix();
|
||||||
|
int num_of_entries = xpatch_args->length();
|
||||||
|
|
||||||
|
// Set up the boot loader's xpatch_entries list
|
||||||
|
_xpatch_entries = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<ModuleClassPathList*>(num_of_entries, true);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_of_entries; i++) {
|
||||||
|
const char* module_name = (xpatch_args->at(i))->module_name();
|
||||||
|
Symbol* const module_sym = SymbolTable::lookup(module_name, (int)strlen(module_name), CHECK);
|
||||||
|
assert(module_sym != NULL, "Failed to obtain Symbol for module name");
|
||||||
|
ModuleClassPathList* module_cpl = new ModuleClassPathList(module_sym);
|
||||||
|
|
||||||
|
char* class_path = (xpatch_args->at(i))->path_string();
|
||||||
|
int len = (int)strlen(class_path);
|
||||||
|
int end = 0;
|
||||||
|
// Iterate over the module's class path entries
|
||||||
|
for (int start = 0; start < len; start = end) {
|
||||||
|
while (class_path[end] && class_path[end] != os::path_separator()[0]) {
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
EXCEPTION_MARK;
|
||||||
|
ResourceMark rm(THREAD);
|
||||||
|
char* path = NEW_RESOURCE_ARRAY(char, end - start + 1);
|
||||||
|
strncpy(path, &class_path[start], end - start);
|
||||||
|
path[end - start] = '\0';
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if (os::stat(path, &st) == 0) {
|
||||||
|
// File or directory found
|
||||||
|
Thread* THREAD = Thread::current();
|
||||||
|
ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, CHECK);
|
||||||
|
// If the path specification is valid, enter it into this module's list
|
||||||
|
if (new_entry != NULL) {
|
||||||
|
module_cpl->add_to_list(new_entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (class_path[end] == os::path_separator()[0]) {
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the module into the list of -Xpatch entries only if
|
||||||
|
// valid ClassPathEntrys have been created
|
||||||
|
if (module_cpl->module_first_entry() != NULL) {
|
||||||
|
_xpatch_entries->push(module_cpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ClassLoader::setup_search_path(const char *class_path, bool bootstrap_search) {
|
void ClassLoader::setup_search_path(const char *class_path, bool bootstrap_search) {
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int len = (int)strlen(class_path);
|
int len = (int)strlen(class_path);
|
||||||
|
@ -847,8 +931,29 @@ bool ClassLoader::update_class_path_entry_list(const char *path,
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassLoader::print_bootclasspath() {
|
void ClassLoader::print_bootclasspath() {
|
||||||
ClassPathEntry* e = _first_entry;
|
ClassPathEntry* e;
|
||||||
tty->print("[bootclasspath= ");
|
tty->print("[bootclasspath= ");
|
||||||
|
|
||||||
|
// Print -Xpatch module/path specifications first
|
||||||
|
if (_xpatch_entries != NULL) {
|
||||||
|
ResourceMark rm;
|
||||||
|
int num_of_entries = _xpatch_entries->length();
|
||||||
|
for (int i = 0; i < num_of_entries; i++) {
|
||||||
|
ModuleClassPathList* mpl = _xpatch_entries->at(i);
|
||||||
|
tty->print("%s=", mpl->module_name()->as_C_string());
|
||||||
|
e = mpl->module_first_entry();
|
||||||
|
while (e != NULL) {
|
||||||
|
tty->print("%s", e->name());
|
||||||
|
e = e->next();
|
||||||
|
if (e != NULL) {
|
||||||
|
tty->print("%s", os::path_separator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tty->print(" ;");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e = _first_entry;
|
||||||
while (e != NULL) {
|
while (e != NULL) {
|
||||||
tty->print("%s ;", e->name());
|
tty->print("%s ;", e->name());
|
||||||
e = e->next();
|
e = e->next();
|
||||||
|
@ -942,13 +1047,15 @@ void ClassLoader::initialize_module_loader_map(JImageFile* jimage) {
|
||||||
return; // only needed for CDS dump time
|
return; // only needed for CDS dump time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResourceMark rm;
|
||||||
jlong size;
|
jlong size;
|
||||||
JImageLocationRef location = (*JImageFindResource)(jimage, "java.base", get_jimage_version_string(), MODULE_LOADER_MAP, &size);
|
JImageLocationRef location = (*JImageFindResource)(jimage, "java.base", get_jimage_version_string(), MODULE_LOADER_MAP, &size);
|
||||||
if (location == 0) {
|
if (location == 0) {
|
||||||
vm_exit_during_initialization(
|
vm_exit_during_initialization(
|
||||||
"Cannot find ModuleLoaderMap location from modules jimage.", NULL);
|
"Cannot find ModuleLoaderMap location from modules jimage.", NULL);
|
||||||
}
|
}
|
||||||
char* buffer = NEW_RESOURCE_ARRAY(char, size);
|
char* buffer = NEW_RESOURCE_ARRAY(char, size + 1);
|
||||||
|
buffer[size] = '\0';
|
||||||
jlong read = (*JImageGetResource)(jimage, location, buffer, size);
|
jlong read = (*JImageGetResource)(jimage, location, buffer, size);
|
||||||
if (read != size) {
|
if (read != size) {
|
||||||
vm_exit_during_initialization(
|
vm_exit_during_initialization(
|
||||||
|
@ -986,7 +1093,6 @@ void ClassLoader::initialize_module_loader_map(JImageFile* jimage) {
|
||||||
begin_ptr = ++end_ptr;
|
begin_ptr = ++end_ptr;
|
||||||
end_ptr = strchr(begin_ptr, '\n');
|
end_ptr = strchr(begin_ptr, '\n');
|
||||||
}
|
}
|
||||||
FREE_RESOURCE_ARRAY(u1, buffer, size);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1107,8 +1213,7 @@ s2 ClassLoader::module_to_classloader(const char* module_name) {
|
||||||
return APP_LOADER;
|
return APP_LOADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
s2 ClassLoader::classloader_type(Symbol* class_name, ClassPathEntry* e,
|
s2 ClassLoader::classloader_type(Symbol* class_name, ClassPathEntry* e, int classpath_index, TRAPS) {
|
||||||
int classpath_index, TRAPS) {
|
|
||||||
assert(DumpSharedSpaces, "Only used for CDS dump time");
|
assert(DumpSharedSpaces, "Only used for CDS dump time");
|
||||||
|
|
||||||
// obtain the classloader type based on the class name.
|
// obtain the classloader type based on the class name.
|
||||||
|
@ -1157,12 +1262,11 @@ const char* ClassLoader::file_name_for_class_name(const char* class_name,
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) {
|
instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) {
|
||||||
|
|
||||||
assert(name != NULL, "invariant");
|
assert(name != NULL, "invariant");
|
||||||
assert(THREAD->is_Java_thread(), "must be a JavaThread");
|
assert(THREAD->is_Java_thread(), "must be a JavaThread");
|
||||||
|
|
||||||
ResourceMark rm;
|
ResourceMark rm(THREAD);
|
||||||
HandleMark hm;
|
HandleMark hm(THREAD);
|
||||||
|
|
||||||
const char* const class_name = name->as_C_string();
|
const char* const class_name = name->as_C_string();
|
||||||
|
|
||||||
|
@ -1178,30 +1282,101 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_onl
|
||||||
// Lookup stream for parsing .class file
|
// Lookup stream for parsing .class file
|
||||||
ClassFileStream* stream = NULL;
|
ClassFileStream* stream = NULL;
|
||||||
s2 classpath_index = 0;
|
s2 classpath_index = 0;
|
||||||
|
ClassPathEntry* e = NULL;
|
||||||
|
|
||||||
// If DumpSharedSpaces is true, boot loader visibility boundaries are set
|
// If DumpSharedSpaces is true, boot loader visibility boundaries are set
|
||||||
// to be _first_entry to the end (all path entries).
|
// to be _first_entry to the end (all path entries). No -Xpatch entries are
|
||||||
|
// included since CDS and AppCDS are not supported if -Xpatch is specified.
|
||||||
//
|
//
|
||||||
// If search_append_only is true, boot loader visibility boundaries are
|
// If search_append_only is true, boot loader visibility boundaries are
|
||||||
// set to be _fist_append_entry to the end. This includes:
|
// set to be _first_append_entry to the end. This includes:
|
||||||
// [-Xbootclasspath/a]; [jvmti appended entries]
|
// [-Xbootclasspath/a]; [jvmti appended entries]
|
||||||
//
|
//
|
||||||
// If both DumpSharedSpaces and search_append_only are false, boot loader
|
// If both DumpSharedSpaces and search_append_only are false, boot loader
|
||||||
// visibility boundaries are set to be _first_entry to the entry before
|
// visibility boundaries are set to be _first_entry to the entry before
|
||||||
// the _first_append_entry. This would include:
|
// the _first_append_entry. This would include:
|
||||||
// [-Xpatch:<dirs>]; [exploded build | modules]
|
// [-Xpatch:<module>=<file>(<pathsep><file>)*]; [exploded build | jimage]
|
||||||
//
|
//
|
||||||
// DumpSharedSpaces and search_append_only are mutually exclusive and cannot
|
// DumpSharedSpaces and search_append_only are mutually exclusive and cannot
|
||||||
// be true at the same time.
|
// be true at the same time.
|
||||||
ClassPathEntry* e = (search_append_only ? _first_append_entry : _first_entry);
|
assert(!(DumpSharedSpaces && search_append_only), "DumpSharedSpaces and search_append_only are both true");
|
||||||
ClassPathEntry* last_e =
|
|
||||||
(search_append_only || DumpSharedSpaces ? NULL : _first_append_entry);
|
|
||||||
|
|
||||||
{
|
// Load Attempt #1: -Xpatch
|
||||||
|
// Determine the class' defining module. If it appears in the _xpatch_entries,
|
||||||
|
// attempt to load the class from those locations specific to the module.
|
||||||
|
// Note: The -Xpatch entries are never searched if the boot loader's
|
||||||
|
// visibility boundary is limited to only searching the append entries.
|
||||||
|
if (_xpatch_entries != NULL && !search_append_only && !DumpSharedSpaces) {
|
||||||
|
// Find the module in the boot loader's module entry table
|
||||||
|
PackageEntry* pkg_entry = get_package_entry(class_name, ClassLoaderData::the_null_class_loader_data(), THREAD);
|
||||||
|
ModuleEntry* mod_entry = (pkg_entry != NULL) ? pkg_entry->module() : NULL;
|
||||||
|
|
||||||
|
// If the module system has not defined java.base yet, then
|
||||||
|
// classes loaded are assumed to be defined to java.base.
|
||||||
|
// When java.base is eventually defined by the module system,
|
||||||
|
// all packages of classes that have been previously loaded
|
||||||
|
// are verified in ModuleEntryTable::verify_javabase_packages().
|
||||||
|
if (!Universe::is_module_initialized() &&
|
||||||
|
!ModuleEntryTable::javabase_defined() &&
|
||||||
|
mod_entry == NULL) {
|
||||||
|
mod_entry = ModuleEntryTable::javabase_module();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The module must be a named module
|
||||||
|
if (mod_entry != NULL && mod_entry->is_named()) {
|
||||||
|
int num_of_entries = _xpatch_entries->length();
|
||||||
|
const Symbol* class_module_name = mod_entry->name();
|
||||||
|
|
||||||
|
// Loop through all the xpatch entries looking for module
|
||||||
|
for (int i = 0; i < num_of_entries; i++) {
|
||||||
|
ModuleClassPathList* module_cpl = _xpatch_entries->at(i);
|
||||||
|
Symbol* module_cpl_name = module_cpl->module_name();
|
||||||
|
|
||||||
|
if (module_cpl_name->fast_compare(class_module_name) == 0) {
|
||||||
|
// Class' module has been located, attempt to load
|
||||||
|
// the class from the module's ClassPathEntry list.
|
||||||
|
e = module_cpl->module_first_entry();
|
||||||
|
while (e != NULL) {
|
||||||
|
stream = e->open_stream(file_name, CHECK_NULL);
|
||||||
|
// No context.check is required since both CDS
|
||||||
|
// and AppCDS are turned off if -Xpatch is specified.
|
||||||
|
if (NULL != stream) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
e = e->next();
|
||||||
|
}
|
||||||
|
// If the module was located in the xpatch entries, break out
|
||||||
|
// even if the class was not located successfully from that module's
|
||||||
|
// ClassPathEntry list. There will not be another valid entry for
|
||||||
|
// that module in the _xpatch_entries array.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load Attempt #2: [exploded build | jimage]
|
||||||
|
if (!search_append_only && (NULL == stream)) {
|
||||||
|
e = _first_entry;
|
||||||
|
while ((e != NULL) && (e != _first_append_entry)) {
|
||||||
|
stream = e->open_stream(file_name, CHECK_NULL);
|
||||||
|
if (!context.check(stream, classpath_index)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (NULL != stream) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
e = e->next();
|
||||||
|
++classpath_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load Attempt #3: [-Xbootclasspath/a]; [jvmti appended entries]
|
||||||
|
if ((search_append_only || DumpSharedSpaces) && (NULL == stream)) {
|
||||||
|
// For the boot loader append path search, must calculate
|
||||||
|
// the starting classpath_index prior to attempting to
|
||||||
|
// load the classfile.
|
||||||
if (search_append_only) {
|
if (search_append_only) {
|
||||||
// For the boot loader append path search, must calculate
|
|
||||||
// the starting classpath_index prior to attempting to
|
|
||||||
// load the classfile.
|
|
||||||
ClassPathEntry *tmp_e = _first_entry;
|
ClassPathEntry *tmp_e = _first_entry;
|
||||||
while ((tmp_e != NULL) && (tmp_e != _first_append_entry)) {
|
while ((tmp_e != NULL) && (tmp_e != _first_append_entry)) {
|
||||||
tmp_e = tmp_e->next();
|
tmp_e = tmp_e->next();
|
||||||
|
@ -1209,11 +1384,8 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_onl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to load the classfile from either:
|
e = _first_append_entry;
|
||||||
// - [-Xpatch:dir]; exploded build | modules
|
while (e != NULL) {
|
||||||
// or
|
|
||||||
// - [-Xbootclasspath/a]; [jvmti appended entries]
|
|
||||||
while ((e != NULL) && (e != last_e)) {
|
|
||||||
stream = e->open_stream(file_name, CHECK_NULL);
|
stream = e->open_stream(file_name, CHECK_NULL);
|
||||||
if (!context.check(stream, classpath_index)) {
|
if (!context.check(stream, classpath_index)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1383,10 +1555,23 @@ int ClassLoader::compute_Object_vtable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void classLoader_init() {
|
void classLoader_init1() {
|
||||||
ClassLoader::initialize();
|
ClassLoader::initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Complete the ClassPathEntry setup for the boot loader
|
||||||
|
void classLoader_init2() {
|
||||||
|
// Setup the list of module/path pairs for -Xpatch processing
|
||||||
|
// This must be done after the SymbolTable is created in order
|
||||||
|
// to use fast_compare on module names instead of a string compare.
|
||||||
|
if (Arguments::get_xpatchprefix() != NULL) {
|
||||||
|
ClassLoader::setup_xpatch_entries();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine if this is an exploded build
|
||||||
|
ClassLoader::set_has_jimage();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ClassLoader::get_canonical_path(const char* orig, char* out, int len) {
|
bool ClassLoader::get_canonical_path(const char* orig, char* out, int len) {
|
||||||
assert(orig != NULL && out != NULL && len > 0, "bad arguments");
|
assert(orig != NULL && out != NULL && len > 0, "bad arguments");
|
||||||
|
@ -1430,17 +1615,19 @@ void ClassLoader::create_javabase() {
|
||||||
}
|
}
|
||||||
ModuleEntryTable::set_javabase_module(jb_module);
|
ModuleEntryTable::set_javabase_module(jb_module);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// When looking for the jimage file, only
|
void ClassLoader::set_has_jimage() {
|
||||||
// search the boot loader's module path which
|
// Determine if this is an exploded build. When looking for
|
||||||
// can consist of [-Xpatch]; exploded build | modules
|
// the jimage file, only search the piece of the boot
|
||||||
// Do not search the boot loader's append path.
|
// loader's boot class path which contains [exploded build | jimage].
|
||||||
|
// Do not search the boot loader's xpatch entries or append path.
|
||||||
ClassPathEntry* e = _first_entry;
|
ClassPathEntry* e = _first_entry;
|
||||||
ClassPathEntry* last_e = _first_append_entry;
|
ClassPathEntry* last_e = _first_append_entry;
|
||||||
while ((e != NULL) && (e != last_e)) {
|
while ((e != NULL) && (e != last_e)) {
|
||||||
JImageFile *jimage = e->jimage();
|
JImageFile *jimage = e->jimage();
|
||||||
if (jimage != NULL && e->is_jrt()) {
|
if (jimage != NULL && e->is_jrt()) {
|
||||||
set_has_jimage(true);
|
_has_jimage = true;
|
||||||
#if INCLUDE_CDS
|
#if INCLUDE_CDS
|
||||||
ClassLoader::initialize_module_loader_map(jimage);
|
ClassLoader::initialize_module_loader_map(jimage);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -142,13 +142,30 @@ public:
|
||||||
JImageFile* jimage() const { return _jimage; }
|
JImageFile* jimage() const { return _jimage; }
|
||||||
ClassPathImageEntry(JImageFile* jimage, const char* name);
|
ClassPathImageEntry(JImageFile* jimage, const char* name);
|
||||||
~ClassPathImageEntry();
|
~ClassPathImageEntry();
|
||||||
void name_to_package(const char* name, char* package, int length);
|
|
||||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ModuleClassPathList contains a linked list of ClassPathEntry's
|
||||||
|
// that have been specified for a specific module. Currently,
|
||||||
|
// the only way to specify a module/path pair is via the -Xpatch
|
||||||
|
// command line option.
|
||||||
|
class ModuleClassPathList : public CHeapObj<mtClass> {
|
||||||
|
private:
|
||||||
|
Symbol* _module_name;
|
||||||
|
// First and last entries of class path entries for a specific module
|
||||||
|
ClassPathEntry* _module_first_entry;
|
||||||
|
ClassPathEntry* _module_last_entry;
|
||||||
|
public:
|
||||||
|
Symbol* module_name() const { return _module_name; }
|
||||||
|
ClassPathEntry* module_first_entry() const { return _module_first_entry; }
|
||||||
|
ModuleClassPathList(Symbol* module_name);
|
||||||
|
~ModuleClassPathList();
|
||||||
|
void add_to_list(ClassPathEntry* new_entry);
|
||||||
|
};
|
||||||
|
|
||||||
class SharedPathsMiscInfo;
|
class SharedPathsMiscInfo;
|
||||||
|
|
||||||
class ClassLoader: AllStatic {
|
class ClassLoader: AllStatic {
|
||||||
|
@ -195,21 +212,31 @@ class ClassLoader: AllStatic {
|
||||||
static PerfCounter* _isUnsyncloadClass;
|
static PerfCounter* _isUnsyncloadClass;
|
||||||
static PerfCounter* _load_instance_class_failCounter;
|
static PerfCounter* _load_instance_class_failCounter;
|
||||||
|
|
||||||
// First entry in linked list of ClassPathEntry instances.
|
// The boot class path consists of 3 ordered pieces:
|
||||||
// This consists of entries made up by:
|
// 1. the module/path pairs specified to -Xpatch
|
||||||
// - boot loader modules
|
// -Xpatch:<module>=<file>(<pathsep><file>)*
|
||||||
// [-Xpatch]; exploded build | modules;
|
// 2. the base piece
|
||||||
// - boot loader append path
|
// [exploded build | jimage]
|
||||||
// [-Xbootclasspath/a]; [jvmti appended entries]
|
// 3. boot loader append path
|
||||||
|
// [-Xbootclasspath/a]; [jvmti appended entries]
|
||||||
|
//
|
||||||
|
// The boot loader must obey this order when attempting
|
||||||
|
// to load a class.
|
||||||
|
|
||||||
|
// Contains the module/path pairs specified to -Xpatch
|
||||||
|
static GrowableArray<ModuleClassPathList*>* _xpatch_entries;
|
||||||
|
|
||||||
|
// Contains the ClassPathEntry instances that include
|
||||||
|
// both the base piece and the boot loader append path.
|
||||||
static ClassPathEntry* _first_entry;
|
static ClassPathEntry* _first_entry;
|
||||||
// Last entry in linked list of ClassPathEntry instances
|
// Last entry in linked list of ClassPathEntry instances
|
||||||
static ClassPathEntry* _last_entry;
|
static ClassPathEntry* _last_entry;
|
||||||
static int _num_entries;
|
static int _num_entries;
|
||||||
|
|
||||||
// Pointer into the linked list of ClassPathEntry instances.
|
|
||||||
// Marks the start of:
|
// Marks the start of:
|
||||||
// - the boot loader's append path
|
// - the boot loader's append path
|
||||||
// [-Xbootclasspath/a]; [jvmti appended entries]
|
// [-Xbootclasspath/a]; [jvmti appended entries]
|
||||||
|
// within the linked list of ClassPathEntry instances.
|
||||||
static ClassPathEntry* _first_append_entry;
|
static ClassPathEntry* _first_append_entry;
|
||||||
|
|
||||||
static const char* _shared_archive;
|
static const char* _shared_archive;
|
||||||
|
@ -325,11 +352,11 @@ class ClassLoader: AllStatic {
|
||||||
return _load_instance_class_failCounter;
|
return _load_instance_class_failCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets _has_jimage to TRUE if "modules" jimage file exists
|
// Set up the module/path pairs as specified to -Xpatch
|
||||||
static void set_has_jimage(bool val) {
|
static void setup_xpatch_entries();
|
||||||
_has_jimage = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Sets _has_jimage to TRUE if "modules" jimage file exists
|
||||||
|
static void set_has_jimage();
|
||||||
static bool has_jimage() { return _has_jimage; }
|
static bool has_jimage() { return _has_jimage; }
|
||||||
|
|
||||||
// Create the ModuleEntry for java.base
|
// Create the ModuleEntry for java.base
|
||||||
|
@ -416,6 +443,9 @@ class ClassLoader: AllStatic {
|
||||||
|
|
||||||
static bool string_ends_with(const char* str, const char* str_to_find);
|
static bool string_ends_with(const char* str, const char* str_to_find);
|
||||||
|
|
||||||
|
// obtain package name from a fully qualified class name
|
||||||
|
static const char* package_from_name(const char* class_name);
|
||||||
|
|
||||||
static bool is_jrt(const char* name) { return string_ends_with(name, MODULES_IMAGE_NAME); }
|
static bool is_jrt(const char* name) { return string_ends_with(name, MODULES_IMAGE_NAME); }
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include "memory/iterator.hpp"
|
#include "memory/iterator.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/orderAccess.inline.hpp"
|
#include "runtime/orderAccess.inline.hpp"
|
||||||
#include "utilities/hashtable.inline.hpp"
|
#include "utilities/hashtable.inline.hpp"
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,6 @@
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "oops/symbol.hpp"
|
#include "oops/symbol.hpp"
|
||||||
#include "oops/typeArrayOop.hpp"
|
#include "oops/typeArrayOop.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/fieldDescriptor.hpp"
|
#include "runtime/fieldDescriptor.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
|
|
|
@ -133,68 +133,31 @@ static PackageEntry* get_package_entry_by_name(Symbol* package,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if -Xpatch:<dirs> was specified. If so, prepend each <dir>/module_name,
|
// If using exploded build, append <java.home>/modules/module_name, if it exists,
|
||||||
// if it exists, to bootpath so boot loader can find the class files. Also, if
|
// to the system boot class path in order for the boot loader to locate class files.
|
||||||
// using exploded modules, append <java.home>/modules/module_name, if it exists,
|
static void add_to_exploded_build_list(char *module_name, TRAPS) {
|
||||||
// to bootpath so that its class files can be found by the boot loader.
|
assert(!ClassLoader::has_jimage(), "Exploded build not applicable");
|
||||||
static void add_to_boot_loader_list(char *module_name, TRAPS) {
|
// java.base is handled by os::set_boot_path
|
||||||
// java.base should be handled by argument parsing.
|
|
||||||
assert(strcmp(module_name, "java.base") != 0, "Unexpected java.base module name");
|
assert(strcmp(module_name, "java.base") != 0, "Unexpected java.base module name");
|
||||||
|
|
||||||
char file_sep = os::file_separator()[0];
|
char file_sep = os::file_separator()[0];
|
||||||
size_t module_len = strlen(module_name);
|
size_t module_len = strlen(module_name);
|
||||||
|
|
||||||
// If -Xpatch is set then add <patch-dir>/module_name paths.
|
const char* home = Arguments::get_java_home();
|
||||||
char** patch_dirs = Arguments::patch_dirs();
|
size_t len = strlen(home) + module_len + 32;
|
||||||
if (patch_dirs != NULL) {
|
char* path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
|
||||||
int dir_count = Arguments::patch_dirs_count();
|
jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name);
|
||||||
for (int x = 0; x < dir_count; x++) {
|
struct stat st;
|
||||||
// Really shouldn't be NULL, but check can't hurt
|
// See if exploded module path exists
|
||||||
if (patch_dirs[x] != NULL) {
|
if ((os::stat(path, &st) != 0)) {
|
||||||
size_t len = strlen(patch_dirs[x]);
|
FREE_C_HEAP_ARRAY(char, path);
|
||||||
if (len != 0) { // Ignore empty strings.
|
path = NULL;
|
||||||
len = len + module_len + 2;
|
|
||||||
char* prefix_path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
|
|
||||||
jio_snprintf(prefix_path, len, "%s%c%s", patch_dirs[x], file_sep, module_name);
|
|
||||||
|
|
||||||
// See if Xpatch module path exists.
|
|
||||||
struct stat st;
|
|
||||||
if ((os::stat(prefix_path, &st) != 0)) {
|
|
||||||
FREE_C_HEAP_ARRAY(char, prefix_path);
|
|
||||||
} else {
|
|
||||||
{
|
|
||||||
HandleMark hm;
|
|
||||||
Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
|
|
||||||
ObjectLocker ol(loader_lock, THREAD);
|
|
||||||
ClassLoader::prepend_to_list(prefix_path);
|
|
||||||
}
|
|
||||||
log_info(class, load)("opened: -Xpatch %s", prefix_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If "modules" jimage does not exist then assume exploded form
|
|
||||||
// ${java.home}/modules/<module-name>
|
|
||||||
char* path = NULL;
|
|
||||||
if (!ClassLoader::has_jimage()) {
|
|
||||||
const char* home = Arguments::get_java_home();
|
|
||||||
size_t len = strlen(home) + module_len + 32;
|
|
||||||
path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
|
|
||||||
jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name);
|
|
||||||
struct stat st;
|
|
||||||
// See if exploded module path exists.
|
|
||||||
if ((os::stat(path, &st) != 0)) {
|
|
||||||
FREE_C_HEAP_ARRAY(char, path);
|
|
||||||
path = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path != NULL) {
|
if (path != NULL) {
|
||||||
HandleMark hm;
|
HandleMark hm;
|
||||||
Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
|
Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
|
||||||
ObjectLocker ol(loader_lock, THREAD);
|
ObjectLocker ol(loader_lock, THREAD);
|
||||||
|
|
||||||
log_info(class, load)("opened: %s", path);
|
log_info(class, load)("opened: %s", path);
|
||||||
ClassLoader::add_to_list(path);
|
ClassLoader::add_to_list(path);
|
||||||
}
|
}
|
||||||
|
@ -498,13 +461,12 @@ void Modules::define_module(jobject module, jstring version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loader == NULL && !Universe::is_module_initialized()) {
|
// If the module is defined to the boot loader and an exploded build is being
|
||||||
// Now that the module is defined, if it is in the bootloader, make sure that
|
// used, prepend <java.home>/modules/modules_name, if it exists, to the system boot class path.
|
||||||
// its classes can be found. Check if -Xpatch:<path> was specified. If
|
if (loader == NULL &&
|
||||||
// so prepend <path>/module_name, if it exists, to bootpath. Also, if using
|
!Universe::is_module_initialized() &&
|
||||||
// exploded modules, prepend <java.home>/modules/module_name, if it exists,
|
!ClassLoader::has_jimage()) {
|
||||||
// to bootpath.
|
add_to_exploded_build_list(module_name, CHECK);
|
||||||
add_to_boot_loader_list(module_name, CHECK);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -580,20 +580,6 @@ bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) {
|
||||||
case vmIntrinsics::_putLongOpaque:
|
case vmIntrinsics::_putLongOpaque:
|
||||||
case vmIntrinsics::_putFloatOpaque:
|
case vmIntrinsics::_putFloatOpaque:
|
||||||
case vmIntrinsics::_putDoubleOpaque:
|
case vmIntrinsics::_putDoubleOpaque:
|
||||||
case vmIntrinsics::_getByte_raw:
|
|
||||||
case vmIntrinsics::_getShort_raw:
|
|
||||||
case vmIntrinsics::_getChar_raw:
|
|
||||||
case vmIntrinsics::_getInt_raw:
|
|
||||||
case vmIntrinsics::_getLong_raw:
|
|
||||||
case vmIntrinsics::_getFloat_raw:
|
|
||||||
case vmIntrinsics::_getDouble_raw:
|
|
||||||
case vmIntrinsics::_putByte_raw:
|
|
||||||
case vmIntrinsics::_putShort_raw:
|
|
||||||
case vmIntrinsics::_putChar_raw:
|
|
||||||
case vmIntrinsics::_putInt_raw:
|
|
||||||
case vmIntrinsics::_putLong_raw:
|
|
||||||
case vmIntrinsics::_putFloat_raw:
|
|
||||||
case vmIntrinsics::_putDouble_raw:
|
|
||||||
case vmIntrinsics::_getAndAddInt:
|
case vmIntrinsics::_getAndAddInt:
|
||||||
case vmIntrinsics::_getAndAddLong:
|
case vmIntrinsics::_getAndAddLong:
|
||||||
case vmIntrinsics::_getAndSetInt:
|
case vmIntrinsics::_getAndSetInt:
|
||||||
|
@ -634,8 +620,6 @@ bool vmIntrinsics::is_disabled_by_flags(const methodHandle& method) {
|
||||||
case vmIntrinsics::_putIntUnaligned:
|
case vmIntrinsics::_putIntUnaligned:
|
||||||
case vmIntrinsics::_putLongUnaligned:
|
case vmIntrinsics::_putLongUnaligned:
|
||||||
case vmIntrinsics::_allocateInstance:
|
case vmIntrinsics::_allocateInstance:
|
||||||
case vmIntrinsics::_getAddress_raw:
|
|
||||||
case vmIntrinsics::_putAddress_raw:
|
|
||||||
if (!InlineUnsafeOps || !UseUnalignedAccesses) return true;
|
if (!InlineUnsafeOps || !UseUnalignedAccesses) return true;
|
||||||
break;
|
break;
|
||||||
case vmIntrinsics::_hashCode:
|
case vmIntrinsics::_hashCode:
|
||||||
|
|
|
@ -1232,43 +1232,6 @@
|
||||||
do_intrinsic(_putIntUnaligned, jdk_internal_misc_Unsafe, putIntUnaligned_name, putInt_signature, F_R) \
|
do_intrinsic(_putIntUnaligned, jdk_internal_misc_Unsafe, putIntUnaligned_name, putInt_signature, F_R) \
|
||||||
do_intrinsic(_putLongUnaligned, jdk_internal_misc_Unsafe, putLongUnaligned_name, putLong_signature, F_R) \
|
do_intrinsic(_putLongUnaligned, jdk_internal_misc_Unsafe, putLongUnaligned_name, putLong_signature, F_R) \
|
||||||
\
|
\
|
||||||
/* %%% these are redundant except perhaps for getAddress, but Unsafe has native methods for them */ \
|
|
||||||
do_signature(getByte_raw_signature, "(J)B") \
|
|
||||||
do_signature(putByte_raw_signature, "(JB)V") \
|
|
||||||
do_signature(getShort_raw_signature, "(J)S") \
|
|
||||||
do_signature(putShort_raw_signature, "(JS)V") \
|
|
||||||
do_signature(getChar_raw_signature, "(J)C") \
|
|
||||||
do_signature(putChar_raw_signature, "(JC)V") \
|
|
||||||
do_signature(putInt_raw_signature, "(JI)V") \
|
|
||||||
do_alias(getLong_raw_signature, /*(J)J*/ long_long_signature) \
|
|
||||||
do_alias(putLong_raw_signature, /*(JJ)V*/ long_long_void_signature) \
|
|
||||||
do_signature(getFloat_raw_signature, "(J)F") \
|
|
||||||
do_signature(putFloat_raw_signature, "(JF)V") \
|
|
||||||
do_alias(getDouble_raw_signature, /*(J)D*/ long_double_signature) \
|
|
||||||
do_signature(putDouble_raw_signature, "(JD)V") \
|
|
||||||
do_alias(getAddress_raw_signature, /*(J)J*/ long_long_signature) \
|
|
||||||
do_alias(putAddress_raw_signature, /*(JJ)V*/ long_long_void_signature) \
|
|
||||||
\
|
|
||||||
do_name( getAddress_name, "getAddress") \
|
|
||||||
do_name( putAddress_name, "putAddress") \
|
|
||||||
\
|
|
||||||
do_intrinsic(_getByte_raw, jdk_internal_misc_Unsafe, getByte_name, getByte_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_getShort_raw, jdk_internal_misc_Unsafe, getShort_name, getShort_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_getChar_raw, jdk_internal_misc_Unsafe, getChar_name, getChar_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_getInt_raw, jdk_internal_misc_Unsafe, getInt_name, long_int_signature, F_R) \
|
|
||||||
do_intrinsic(_getLong_raw, jdk_internal_misc_Unsafe, getLong_name, getLong_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_getFloat_raw, jdk_internal_misc_Unsafe, getFloat_name, getFloat_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_getDouble_raw, jdk_internal_misc_Unsafe, getDouble_name, getDouble_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_getAddress_raw, jdk_internal_misc_Unsafe, getAddress_name, getAddress_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_putByte_raw, jdk_internal_misc_Unsafe, putByte_name, putByte_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_putShort_raw, jdk_internal_misc_Unsafe, putShort_name, putShort_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_putChar_raw, jdk_internal_misc_Unsafe, putChar_name, putChar_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_putInt_raw, jdk_internal_misc_Unsafe, putInt_name, putInt_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_putLong_raw, jdk_internal_misc_Unsafe, putLong_name, putLong_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_putFloat_raw, jdk_internal_misc_Unsafe, putFloat_name, putFloat_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_putDouble_raw, jdk_internal_misc_Unsafe, putDouble_name, putDouble_raw_signature, F_R) \
|
|
||||||
do_intrinsic(_putAddress_raw, jdk_internal_misc_Unsafe, putAddress_name, putAddress_raw_signature, F_R) \
|
|
||||||
\
|
|
||||||
do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
|
do_signature(compareAndSwapObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z") \
|
||||||
do_signature(compareAndExchangeObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") \
|
do_signature(compareAndExchangeObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") \
|
||||||
do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \
|
do_signature(compareAndSwapLong_signature, "(Ljava/lang/Object;JJJ)Z") \
|
||||||
|
|
|
@ -36,10 +36,10 @@
|
||||||
#include "compiler/directivesParser.hpp"
|
#include "compiler/directivesParser.hpp"
|
||||||
#include "compiler/disassembler.hpp"
|
#include "compiler/disassembler.hpp"
|
||||||
#include "interpreter/bytecode.hpp"
|
#include "interpreter/bytecode.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "oops/methodData.hpp"
|
#include "oops/methodData.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "prims/jvmtiImpl.hpp"
|
#include "prims/jvmtiImpl.hpp"
|
||||||
#include "runtime/atomic.inline.hpp"
|
#include "runtime/atomic.inline.hpp"
|
||||||
#include "runtime/orderAccess.inline.hpp"
|
#include "runtime/orderAccess.inline.hpp"
|
||||||
|
@ -2001,15 +2001,18 @@ bool nmethod::is_evol_dependent_on(Klass* dependee) {
|
||||||
Method* method = deps.method_argument(0);
|
Method* method = deps.method_argument(0);
|
||||||
for (int j = 0; j < dependee_methods->length(); j++) {
|
for (int j = 0; j < dependee_methods->length(); j++) {
|
||||||
if (dependee_methods->at(j) == method) {
|
if (dependee_methods->at(j) == method) {
|
||||||
// RC_TRACE macro has an embedded ResourceMark
|
if (log_is_enabled(Debug, redefine, class, nmethod)) {
|
||||||
RC_TRACE(0x01000000,
|
ResourceMark rm;
|
||||||
("Found evol dependency of nmethod %s.%s(%s) compile_id=%d on method %s.%s(%s)",
|
log_debug(redefine, class, nmethod)
|
||||||
_method->method_holder()->external_name(),
|
("Found evol dependency of nmethod %s.%s(%s) compile_id=%d on method %s.%s(%s)",
|
||||||
_method->name()->as_C_string(),
|
_method->method_holder()->external_name(),
|
||||||
_method->signature()->as_C_string(), compile_id(),
|
_method->name()->as_C_string(),
|
||||||
method->method_holder()->external_name(),
|
_method->signature()->as_C_string(),
|
||||||
method->name()->as_C_string(),
|
compile_id(),
|
||||||
method->signature()->as_C_string()));
|
method->method_holder()->external_name(),
|
||||||
|
method->name()->as_C_string(),
|
||||||
|
method->signature()->as_C_string());
|
||||||
|
}
|
||||||
if (TraceDependencies || LogCompilation)
|
if (TraceDependencies || LogCompilation)
|
||||||
deps.log_dependency(dependee);
|
deps.log_dependency(dependee);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -284,6 +284,10 @@ double G1Analytics::predict_object_copy_time_ms(size_t bytes_to_copy, bool durin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double G1Analytics::predict_cost_per_byte_ms() const {
|
||||||
|
return get_new_prediction(_cost_per_byte_ms_seq);
|
||||||
|
}
|
||||||
|
|
||||||
double G1Analytics::predict_constant_other_time_ms() const {
|
double G1Analytics::predict_constant_other_time_ms() const {
|
||||||
return get_new_prediction(_constant_other_time_ms_seq);
|
return get_new_prediction(_constant_other_time_ms_seq);
|
||||||
}
|
}
|
||||||
|
@ -326,4 +330,3 @@ void G1Analytics::update_recent_gc_times(double end_time_sec,
|
||||||
void G1Analytics::report_concurrent_mark_cleanup_times_ms(double ms) {
|
void G1Analytics::report_concurrent_mark_cleanup_times_ms(double ms) {
|
||||||
_concurrent_mark_cleanup_times_ms->add(ms);
|
_concurrent_mark_cleanup_times_ms->add(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -149,6 +149,8 @@ public:
|
||||||
size_t predict_rs_lengths() const;
|
size_t predict_rs_lengths() const;
|
||||||
size_t predict_pending_cards() const;
|
size_t predict_pending_cards() const;
|
||||||
|
|
||||||
|
double predict_cost_per_byte_ms() const;
|
||||||
|
|
||||||
// Add a new GC of the given duration and end time to the record.
|
// Add a new GC of the given duration and end time to the record.
|
||||||
void update_recent_gc_times(double end_time_sec, double elapsed_ms);
|
void update_recent_gc_times(double end_time_sec, double elapsed_ms);
|
||||||
void compute_pause_time_ratio(double interval_ms, double pause_time_ms);
|
void compute_pause_time_ratio(double interval_ms, double pause_time_ms);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,8 +25,8 @@
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "gc/parallel/gcTaskManager.hpp"
|
#include "gc/parallel/gcTaskManager.hpp"
|
||||||
#include "gc/parallel/gcTaskThread.hpp"
|
#include "gc/parallel/gcTaskThread.hpp"
|
||||||
#include "gc/shared/adaptiveSizePolicy.hpp"
|
|
||||||
#include "gc/shared/gcId.hpp"
|
#include "gc/shared/gcId.hpp"
|
||||||
|
#include "gc/shared/workerManager.hpp"
|
||||||
#include "logging/log.hpp"
|
#include "logging/log.hpp"
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
|
@ -34,6 +34,7 @@
|
||||||
#include "runtime/mutex.hpp"
|
#include "runtime/mutex.hpp"
|
||||||
#include "runtime/mutexLocker.hpp"
|
#include "runtime/mutexLocker.hpp"
|
||||||
#include "runtime/orderAccess.inline.hpp"
|
#include "runtime/orderAccess.inline.hpp"
|
||||||
|
#include "runtime/os.hpp"
|
||||||
|
|
||||||
//
|
//
|
||||||
// GCTask
|
// GCTask
|
||||||
|
@ -372,10 +373,28 @@ SynchronizedGCTaskQueue::~SynchronizedGCTaskQueue() {
|
||||||
GCTaskManager::GCTaskManager(uint workers) :
|
GCTaskManager::GCTaskManager(uint workers) :
|
||||||
_workers(workers),
|
_workers(workers),
|
||||||
_active_workers(0),
|
_active_workers(0),
|
||||||
_idle_workers(0) {
|
_idle_workers(0),
|
||||||
|
_created_workers(0) {
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GCTaskThread* GCTaskManager::install_worker(uint t) {
|
||||||
|
GCTaskThread* new_worker = GCTaskThread::create(this, t, _processor_assignment[t]);
|
||||||
|
set_thread(t, new_worker);
|
||||||
|
return new_worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCTaskManager::add_workers(bool initializing) {
|
||||||
|
os::ThreadType worker_type = os::pgc_thread;
|
||||||
|
_created_workers = WorkerManager::add_workers(this,
|
||||||
|
_active_workers,
|
||||||
|
(uint) _workers,
|
||||||
|
_created_workers,
|
||||||
|
worker_type,
|
||||||
|
initializing);
|
||||||
|
_active_workers = MIN2(_created_workers, _active_workers);
|
||||||
|
}
|
||||||
|
|
||||||
void GCTaskManager::initialize() {
|
void GCTaskManager::initialize() {
|
||||||
if (TraceGCTaskManager) {
|
if (TraceGCTaskManager) {
|
||||||
tty->print_cr("GCTaskManager::initialize: workers: %u", workers());
|
tty->print_cr("GCTaskManager::initialize: workers: %u", workers());
|
||||||
|
@ -394,28 +413,30 @@ void GCTaskManager::initialize() {
|
||||||
// Set up worker threads.
|
// Set up worker threads.
|
||||||
// Distribute the workers among the available processors,
|
// Distribute the workers among the available processors,
|
||||||
// unless we were told not to, or if the os doesn't want to.
|
// unless we were told not to, or if the os doesn't want to.
|
||||||
uint* processor_assignment = NEW_C_HEAP_ARRAY(uint, workers(), mtGC);
|
_processor_assignment = NEW_C_HEAP_ARRAY(uint, workers(), mtGC);
|
||||||
if (!BindGCTaskThreadsToCPUs ||
|
if (!BindGCTaskThreadsToCPUs ||
|
||||||
!os::distribute_processes(workers(), processor_assignment)) {
|
!os::distribute_processes(workers(), _processor_assignment)) {
|
||||||
for (uint a = 0; a < workers(); a += 1) {
|
for (uint a = 0; a < workers(); a += 1) {
|
||||||
processor_assignment[a] = sentinel_worker();
|
_processor_assignment[a] = sentinel_worker();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers(), mtGC);
|
_thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers(), mtGC);
|
||||||
for (uint t = 0; t < workers(); t += 1) {
|
_active_workers = ParallelGCThreads;
|
||||||
set_thread(t, GCTaskThread::create(this, t, processor_assignment[t]));
|
if (UseDynamicNumberOfGCThreads && !FLAG_IS_CMDLINE(ParallelGCThreads)) {
|
||||||
|
_active_workers = 1U;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(gc, task, thread) log;
|
Log(gc, task, thread) log;
|
||||||
if (log.is_trace()) {
|
if (log.is_trace()) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
outputStream* out = log.trace_stream();
|
outputStream* out = log.trace_stream();
|
||||||
out->print("GCTaskManager::initialize: distribution:");
|
out->print("GCTaskManager::initialize: distribution:");
|
||||||
for (uint t = 0; t < workers(); t += 1) {
|
for (uint t = 0; t < workers(); t += 1) {
|
||||||
out->print(" %u", processor_assignment[t]);
|
out->print(" %u", _processor_assignment[t]);
|
||||||
}
|
}
|
||||||
out->cr();
|
out->cr();
|
||||||
}
|
}
|
||||||
FREE_C_HEAP_ARRAY(uint, processor_assignment);
|
|
||||||
}
|
}
|
||||||
reset_busy_workers();
|
reset_busy_workers();
|
||||||
set_unblocked();
|
set_unblocked();
|
||||||
|
@ -426,9 +447,8 @@ void GCTaskManager::initialize() {
|
||||||
reset_completed_tasks();
|
reset_completed_tasks();
|
||||||
reset_barriers();
|
reset_barriers();
|
||||||
reset_emptied_queue();
|
reset_emptied_queue();
|
||||||
for (uint s = 0; s < workers(); s += 1) {
|
|
||||||
thread(s)->start();
|
add_workers(true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GCTaskManager::~GCTaskManager() {
|
GCTaskManager::~GCTaskManager() {
|
||||||
|
@ -437,13 +457,17 @@ GCTaskManager::~GCTaskManager() {
|
||||||
NoopGCTask::destroy(_noop_task);
|
NoopGCTask::destroy(_noop_task);
|
||||||
_noop_task = NULL;
|
_noop_task = NULL;
|
||||||
if (_thread != NULL) {
|
if (_thread != NULL) {
|
||||||
for (uint i = 0; i < workers(); i += 1) {
|
for (uint i = 0; i < created_workers(); i += 1) {
|
||||||
GCTaskThread::destroy(thread(i));
|
GCTaskThread::destroy(thread(i));
|
||||||
set_thread(i, NULL);
|
set_thread(i, NULL);
|
||||||
}
|
}
|
||||||
FREE_C_HEAP_ARRAY(GCTaskThread*, _thread);
|
FREE_C_HEAP_ARRAY(GCTaskThread*, _thread);
|
||||||
_thread = NULL;
|
_thread = NULL;
|
||||||
}
|
}
|
||||||
|
if (_processor_assignment != NULL) {
|
||||||
|
FREE_C_HEAP_ARRAY(uint, _processor_assignment);
|
||||||
|
_processor_assignment = NULL;
|
||||||
|
}
|
||||||
if (_resource_flag != NULL) {
|
if (_resource_flag != NULL) {
|
||||||
FREE_C_HEAP_ARRAY(bool, _resource_flag);
|
FREE_C_HEAP_ARRAY(bool, _resource_flag);
|
||||||
_resource_flag = NULL;
|
_resource_flag = NULL;
|
||||||
|
@ -470,6 +494,9 @@ void GCTaskManager::set_active_gang() {
|
||||||
"all_workers_active() is incorrect: "
|
"all_workers_active() is incorrect: "
|
||||||
"active %d ParallelGCThreads %u", active_workers(),
|
"active %d ParallelGCThreads %u", active_workers(),
|
||||||
ParallelGCThreads);
|
ParallelGCThreads);
|
||||||
|
_active_workers = MIN2(_active_workers, _workers);
|
||||||
|
// "add_workers" does not guarantee any additional workers
|
||||||
|
add_workers(false);
|
||||||
log_trace(gc, task)("GCTaskManager::set_active_gang(): "
|
log_trace(gc, task)("GCTaskManager::set_active_gang(): "
|
||||||
"all_workers_active() %d workers %d "
|
"all_workers_active() %d workers %d "
|
||||||
"active %d ParallelGCThreads %u",
|
"active %d ParallelGCThreads %u",
|
||||||
|
@ -499,7 +526,7 @@ void GCTaskManager::task_idle_workers() {
|
||||||
// is starting). Try later to release enough idle_workers
|
// is starting). Try later to release enough idle_workers
|
||||||
// to allow the desired number of active_workers.
|
// to allow the desired number of active_workers.
|
||||||
more_inactive_workers =
|
more_inactive_workers =
|
||||||
workers() - active_workers() - idle_workers();
|
created_workers() - active_workers() - idle_workers();
|
||||||
if (more_inactive_workers < 0) {
|
if (more_inactive_workers < 0) {
|
||||||
int reduced_active_workers = active_workers() + more_inactive_workers;
|
int reduced_active_workers = active_workers() + more_inactive_workers;
|
||||||
set_active_workers(reduced_active_workers);
|
set_active_workers(reduced_active_workers);
|
||||||
|
@ -507,7 +534,7 @@ void GCTaskManager::task_idle_workers() {
|
||||||
}
|
}
|
||||||
log_trace(gc, task)("JT: %d workers %d active %d idle %d more %d",
|
log_trace(gc, task)("JT: %d workers %d active %d idle %d more %d",
|
||||||
Threads::number_of_non_daemon_threads(),
|
Threads::number_of_non_daemon_threads(),
|
||||||
workers(),
|
created_workers(),
|
||||||
active_workers(),
|
active_workers(),
|
||||||
idle_workers(),
|
idle_workers(),
|
||||||
more_inactive_workers);
|
more_inactive_workers);
|
||||||
|
@ -517,7 +544,7 @@ void GCTaskManager::task_idle_workers() {
|
||||||
q->enqueue(IdleGCTask::create_on_c_heap());
|
q->enqueue(IdleGCTask::create_on_c_heap());
|
||||||
increment_idle_workers();
|
increment_idle_workers();
|
||||||
}
|
}
|
||||||
assert(workers() == active_workers() + idle_workers(),
|
assert(created_workers() == active_workers() + idle_workers(),
|
||||||
"total workers should equal active + inactive");
|
"total workers should equal active + inactive");
|
||||||
add_list(q);
|
add_list(q);
|
||||||
// GCTaskQueue* q was created in a ResourceArea so a
|
// GCTaskQueue* q was created in a ResourceArea so a
|
||||||
|
@ -539,14 +566,15 @@ void GCTaskManager::print_task_time_stamps() {
|
||||||
if (!log_is_enabled(Debug, gc, task, time)) {
|
if (!log_is_enabled(Debug, gc, task, time)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for(uint i=0; i<ParallelGCThreads; i++) {
|
uint num_thr = created_workers();
|
||||||
|
for(uint i=0; i < num_thr; i++) {
|
||||||
GCTaskThread* t = thread(i);
|
GCTaskThread* t = thread(i);
|
||||||
t->print_task_time_stamps();
|
t->print_task_time_stamps();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCTaskManager::print_threads_on(outputStream* st) {
|
void GCTaskManager::print_threads_on(outputStream* st) {
|
||||||
uint num_thr = workers();
|
uint num_thr = created_workers();
|
||||||
for (uint i = 0; i < num_thr; i++) {
|
for (uint i = 0; i < num_thr; i++) {
|
||||||
thread(i)->print_on(st);
|
thread(i)->print_on(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
|
@ -555,19 +583,20 @@ void GCTaskManager::print_threads_on(outputStream* st) {
|
||||||
|
|
||||||
void GCTaskManager::threads_do(ThreadClosure* tc) {
|
void GCTaskManager::threads_do(ThreadClosure* tc) {
|
||||||
assert(tc != NULL, "Null ThreadClosure");
|
assert(tc != NULL, "Null ThreadClosure");
|
||||||
uint num_thr = workers();
|
uint num_thr = created_workers();
|
||||||
for (uint i = 0; i < num_thr; i++) {
|
for (uint i = 0; i < num_thr; i++) {
|
||||||
tc->do_thread(thread(i));
|
tc->do_thread(thread(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GCTaskThread* GCTaskManager::thread(uint which) {
|
GCTaskThread* GCTaskManager::thread(uint which) {
|
||||||
assert(which < workers(), "index out of bounds");
|
assert(which < created_workers(), "index out of bounds");
|
||||||
assert(_thread[which] != NULL, "shouldn't have null thread");
|
assert(_thread[which] != NULL, "shouldn't have null thread");
|
||||||
return _thread[which];
|
return _thread[which];
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCTaskManager::set_thread(uint which, GCTaskThread* value) {
|
void GCTaskManager::set_thread(uint which, GCTaskThread* value) {
|
||||||
|
// "_created_workers" may not have been updated yet so use workers()
|
||||||
assert(which < workers(), "index out of bounds");
|
assert(which < workers(), "index out of bounds");
|
||||||
assert(value != NULL, "shouldn't have null thread");
|
assert(value != NULL, "shouldn't have null thread");
|
||||||
_thread[which] = value;
|
_thread[which] = value;
|
||||||
|
@ -728,7 +757,7 @@ uint GCTaskManager::decrement_busy_workers() {
|
||||||
|
|
||||||
void GCTaskManager::release_all_resources() {
|
void GCTaskManager::release_all_resources() {
|
||||||
// If you want this to be done atomically, do it in a WaitForBarrierGCTask.
|
// If you want this to be done atomically, do it in a WaitForBarrierGCTask.
|
||||||
for (uint i = 0; i < workers(); i += 1) {
|
for (uint i = 0; i < created_workers(); i += 1) {
|
||||||
set_resource_flag(i, true);
|
set_resource_flag(i, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -370,6 +370,7 @@ private:
|
||||||
Monitor* _monitor; // Notification of changes.
|
Monitor* _monitor; // Notification of changes.
|
||||||
SynchronizedGCTaskQueue* _queue; // Queue of tasks.
|
SynchronizedGCTaskQueue* _queue; // Queue of tasks.
|
||||||
GCTaskThread** _thread; // Array of worker threads.
|
GCTaskThread** _thread; // Array of worker threads.
|
||||||
|
uint _created_workers; // Number of workers created.
|
||||||
uint _active_workers; // Number of active workers.
|
uint _active_workers; // Number of active workers.
|
||||||
uint _busy_workers; // Number of busy workers.
|
uint _busy_workers; // Number of busy workers.
|
||||||
uint _blocking_worker; // The worker that's blocking.
|
uint _blocking_worker; // The worker that's blocking.
|
||||||
|
@ -381,6 +382,8 @@ private:
|
||||||
NoopGCTask* _noop_task; // The NoopGCTask instance.
|
NoopGCTask* _noop_task; // The NoopGCTask instance.
|
||||||
WaitHelper _wait_helper; // Used by inactive worker
|
WaitHelper _wait_helper; // Used by inactive worker
|
||||||
volatile uint _idle_workers; // Number of idled workers
|
volatile uint _idle_workers; // Number of idled workers
|
||||||
|
uint* _processor_assignment; // Worker to cpu mappings. May
|
||||||
|
// be used lazily
|
||||||
public:
|
public:
|
||||||
// Factory create and destroy methods.
|
// Factory create and destroy methods.
|
||||||
static GCTaskManager* create(uint workers) {
|
static GCTaskManager* create(uint workers) {
|
||||||
|
@ -546,6 +549,13 @@ protected:
|
||||||
uint active_workers() const {
|
uint active_workers() const {
|
||||||
return _active_workers;
|
return _active_workers;
|
||||||
}
|
}
|
||||||
|
uint created_workers() const {
|
||||||
|
return _created_workers;
|
||||||
|
}
|
||||||
|
// Create a GC worker and install into GCTaskManager
|
||||||
|
GCTaskThread* install_worker(uint worker_id);
|
||||||
|
// Add GC workers as needed.
|
||||||
|
void add_workers(bool initializing);
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -44,9 +44,6 @@ GCTaskThread::GCTaskThread(GCTaskManager* manager,
|
||||||
_time_stamps(NULL),
|
_time_stamps(NULL),
|
||||||
_time_stamp_index(0)
|
_time_stamp_index(0)
|
||||||
{
|
{
|
||||||
if (!os::create_thread(this, os::pgc_thread))
|
|
||||||
vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create GC thread. Out of system resources.");
|
|
||||||
|
|
||||||
set_id(which);
|
set_id(which);
|
||||||
set_name("ParGC Thread#%d", which);
|
set_name("ParGC Thread#%d", which);
|
||||||
}
|
}
|
||||||
|
@ -57,10 +54,6 @@ GCTaskThread::~GCTaskThread() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCTaskThread::start() {
|
|
||||||
os::start_thread(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
GCTaskTimeStamp* GCTaskThread::time_stamp_at(uint index) {
|
GCTaskTimeStamp* GCTaskThread::time_stamp_at(uint index) {
|
||||||
guarantee(index < GCTaskTimeStampEntries, "increase GCTaskTimeStampEntries");
|
guarantee(index < GCTaskTimeStampEntries, "increase GCTaskTimeStampEntries");
|
||||||
if (_time_stamps == NULL) {
|
if (_time_stamps == NULL) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -48,13 +48,13 @@ private:
|
||||||
|
|
||||||
bool _is_working; // True if participating in GC tasks
|
bool _is_working; // True if participating in GC tasks
|
||||||
|
|
||||||
public:
|
|
||||||
// Factory create and destroy methods.
|
// Factory create and destroy methods.
|
||||||
static GCTaskThread* create(GCTaskManager* manager,
|
static GCTaskThread* create(GCTaskManager* manager,
|
||||||
uint which,
|
uint which,
|
||||||
uint processor_id) {
|
uint processor_id) {
|
||||||
return new GCTaskThread(manager, which, processor_id);
|
return new GCTaskThread(manager, which, processor_id);
|
||||||
}
|
}
|
||||||
|
public:
|
||||||
static void destroy(GCTaskThread* manager) {
|
static void destroy(GCTaskThread* manager) {
|
||||||
if (manager != NULL) {
|
if (manager != NULL) {
|
||||||
delete manager;
|
delete manager;
|
||||||
|
@ -65,8 +65,6 @@ private:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
virtual void run();
|
virtual void run();
|
||||||
// Methods.
|
|
||||||
void start();
|
|
||||||
|
|
||||||
void print_task_time_stamps();
|
void print_task_time_stamps();
|
||||||
|
|
||||||
|
|
|
@ -220,13 +220,13 @@ void StealMarkingTask::do_it(GCTaskManager* manager, uint which) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// StealRegionCompactionTask
|
// CompactionWithStealingTask
|
||||||
//
|
//
|
||||||
|
|
||||||
StealRegionCompactionTask::StealRegionCompactionTask(ParallelTaskTerminator* t):
|
CompactionWithStealingTask::CompactionWithStealingTask(ParallelTaskTerminator* t):
|
||||||
_terminator(t) {}
|
_terminator(t) {}
|
||||||
|
|
||||||
void StealRegionCompactionTask::do_it(GCTaskManager* manager, uint which) {
|
void CompactionWithStealingTask::do_it(GCTaskManager* manager, uint which) {
|
||||||
assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
|
assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
|
||||||
|
|
||||||
ParCompactionManager* cm =
|
ParCompactionManager* cm =
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -195,16 +195,16 @@ class StealMarkingTask : public GCTask {
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// StealRegionCompactionTask
|
// CompactionWithStealingTask
|
||||||
//
|
//
|
||||||
// This task is used to distribute work to idle threads.
|
// This task is used to distribute work to idle threads.
|
||||||
//
|
//
|
||||||
|
|
||||||
class StealRegionCompactionTask : public GCTask {
|
class CompactionWithStealingTask : public GCTask {
|
||||||
private:
|
private:
|
||||||
ParallelTaskTerminator* const _terminator;
|
ParallelTaskTerminator* const _terminator;
|
||||||
public:
|
public:
|
||||||
StealRegionCompactionTask(ParallelTaskTerminator* t);
|
CompactionWithStealingTask(ParallelTaskTerminator* t);
|
||||||
|
|
||||||
char* name() { return (char *)"steal-region-task"; }
|
char* name() { return (char *)"steal-region-task"; }
|
||||||
ParallelTaskTerminator* terminator() { return _terminator; }
|
ParallelTaskTerminator* terminator() { return _terminator; }
|
||||||
|
|
|
@ -40,7 +40,7 @@ class ParCompactionManager : public CHeapObj<mtGC> {
|
||||||
friend class ParallelTaskTerminator;
|
friend class ParallelTaskTerminator;
|
||||||
friend class ParMarkBitMap;
|
friend class ParMarkBitMap;
|
||||||
friend class PSParallelCompact;
|
friend class PSParallelCompact;
|
||||||
friend class StealRegionCompactionTask;
|
friend class CompactionWithStealingTask;
|
||||||
friend class UpdateAndFillClosure;
|
friend class UpdateAndFillClosure;
|
||||||
friend class RefProcTaskExecutor;
|
friend class RefProcTaskExecutor;
|
||||||
friend class IdleGCTask;
|
friend class IdleGCTask;
|
||||||
|
|
|
@ -2371,7 +2371,7 @@ void PSParallelCompact::enqueue_region_stealing_tasks(
|
||||||
// Once a thread has drained it's stack, it should try to steal regions from
|
// Once a thread has drained it's stack, it should try to steal regions from
|
||||||
// other threads.
|
// other threads.
|
||||||
for (uint j = 0; j < parallel_gc_threads; j++) {
|
for (uint j = 0; j < parallel_gc_threads; j++) {
|
||||||
q->enqueue(new StealRegionCompactionTask(terminator_ptr));
|
q->enqueue(new CompactionWithStealingTask(terminator_ptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -130,10 +130,7 @@ uint AdaptiveSizePolicy::calc_default_active_workers(uintx total_workers,
|
||||||
uintx max_active_workers =
|
uintx max_active_workers =
|
||||||
MAX2(active_workers_by_JT, active_workers_by_heap_size);
|
MAX2(active_workers_by_JT, active_workers_by_heap_size);
|
||||||
|
|
||||||
// Limit the number of workers to the the number created,
|
new_active_workers = MIN2(max_active_workers, (uintx) total_workers);
|
||||||
// (workers()).
|
|
||||||
new_active_workers = MIN2(max_active_workers,
|
|
||||||
(uintx) total_workers);
|
|
||||||
|
|
||||||
// Increase GC workers instantly but decrease them more
|
// Increase GC workers instantly but decrease them more
|
||||||
// slowly.
|
// slowly.
|
||||||
|
@ -167,7 +164,7 @@ uint AdaptiveSizePolicy::calc_default_active_workers(uintx total_workers,
|
||||||
"Jiggled active workers too much");
|
"Jiggled active workers too much");
|
||||||
}
|
}
|
||||||
|
|
||||||
log_trace(gc, task)("GCTaskManager::calc_default_active_workers() : "
|
log_trace(gc, task)("GCTaskManager::calc_default_active_workers() : "
|
||||||
"active_workers(): " UINTX_FORMAT " new_active_workers: " UINTX_FORMAT " "
|
"active_workers(): " UINTX_FORMAT " new_active_workers: " UINTX_FORMAT " "
|
||||||
"prev_active_workers: " UINTX_FORMAT "\n"
|
"prev_active_workers: " UINTX_FORMAT "\n"
|
||||||
" active_workers_by_JT: " UINTX_FORMAT " active_workers_by_heap_size: " UINTX_FORMAT,
|
" active_workers_by_JT: " UINTX_FORMAT " active_workers_by_heap_size: " UINTX_FORMAT,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
77
hotspot/src/share/vm/gc/shared/workerManager.hpp
Normal file
77
hotspot/src/share/vm/gc/shared/workerManager.hpp
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 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_WORKERMANAGER_HPP
|
||||||
|
#define SHARE_VM_GC_SHARED_WORKERMANAGER_HPP
|
||||||
|
|
||||||
|
#include "gc/shared/adaptiveSizePolicy.hpp"
|
||||||
|
|
||||||
|
class WorkerManager : public AllStatic {
|
||||||
|
public:
|
||||||
|
// Create additional workers as needed.
|
||||||
|
// active_workers - number of workers being requested for an upcoming
|
||||||
|
// parallel task.
|
||||||
|
// total_workers - total number of workers. This is the maximum
|
||||||
|
// number possible.
|
||||||
|
// created_workers - number of workers already created. This maybe
|
||||||
|
// less than, equal to, or greater than active workers. If greater than
|
||||||
|
// or equal to active_workers, nothing is done.
|
||||||
|
// worker_type - type of thread.
|
||||||
|
// initializing - true if this is called to get the initial number of
|
||||||
|
// GC workers.
|
||||||
|
// If initializing is true, do a vm exit if the workers cannot be created.
|
||||||
|
// The initializing = true case is for JVM start up and failing to
|
||||||
|
// create all the worker at start should considered a problem so exit.
|
||||||
|
// If initializing = false, there are already some number of worker
|
||||||
|
// threads and a failure would not be optimal but should not be fatal.
|
||||||
|
template <class WorkerType>
|
||||||
|
static uint add_workers (WorkerType* holder,
|
||||||
|
uint active_workers,
|
||||||
|
uint total_workers,
|
||||||
|
uint created_workers,
|
||||||
|
os::ThreadType worker_type,
|
||||||
|
bool initializing) {
|
||||||
|
uint start = created_workers;
|
||||||
|
uint end = MIN2(active_workers, total_workers);
|
||||||
|
for (uint worker_id = start; worker_id < end; worker_id += 1) {
|
||||||
|
WorkerThread* new_worker = holder->install_worker(worker_id);
|
||||||
|
assert(new_worker != NULL, "Failed to allocate GangWorker");
|
||||||
|
if (new_worker == NULL || !os::create_thread(new_worker, worker_type)) {
|
||||||
|
if(initializing) {
|
||||||
|
vm_exit_out_of_memory(0, OOM_MALLOC_ERROR,
|
||||||
|
"Cannot create worker GC thread. Out of system resources.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
created_workers++;
|
||||||
|
os::start_thread(new_worker);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_trace(gc, task)("AdaptiveSizePolicy::add_workers() : "
|
||||||
|
"active_workers: %u created_workers: %u",
|
||||||
|
active_workers, created_workers);
|
||||||
|
|
||||||
|
return created_workers;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // SHARE_VM_GC_SHARED_WORKERMANAGER_HPP
|
|
@ -25,6 +25,7 @@
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "gc/shared/gcId.hpp"
|
#include "gc/shared/gcId.hpp"
|
||||||
#include "gc/shared/workgroup.hpp"
|
#include "gc/shared/workgroup.hpp"
|
||||||
|
#include "gc/shared/workerManager.hpp"
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
#include "runtime/atomic.inline.hpp"
|
#include "runtime/atomic.inline.hpp"
|
||||||
|
@ -35,37 +36,45 @@
|
||||||
// Definitions of WorkGang methods.
|
// Definitions of WorkGang methods.
|
||||||
|
|
||||||
// The current implementation will exit if the allocation
|
// The current implementation will exit if the allocation
|
||||||
// of any worker fails. Still, return a boolean so that
|
// of any worker fails.
|
||||||
// a future implementation can possibly do a partial
|
void AbstractWorkGang::initialize_workers() {
|
||||||
// initialization of the workers and report such to the
|
|
||||||
// caller.
|
|
||||||
bool AbstractWorkGang::initialize_workers() {
|
|
||||||
log_develop_trace(gc, workgang)("Constructing work gang %s with %u threads", name(), total_workers());
|
log_develop_trace(gc, workgang)("Constructing work gang %s with %u threads", name(), total_workers());
|
||||||
_workers = NEW_C_HEAP_ARRAY(AbstractGangWorker*, total_workers(), mtInternal);
|
_workers = NEW_C_HEAP_ARRAY(AbstractGangWorker*, total_workers(), mtInternal);
|
||||||
if (_workers == NULL) {
|
if (_workers == NULL) {
|
||||||
vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create GangWorker array.");
|
vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create GangWorker array.");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_active_workers = ParallelGCThreads;
|
||||||
|
if (UseDynamicNumberOfGCThreads && !FLAG_IS_CMDLINE(ParallelGCThreads)) {
|
||||||
|
_active_workers = 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_workers(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AbstractGangWorker* AbstractWorkGang::install_worker(uint worker_id) {
|
||||||
|
AbstractGangWorker* new_worker = allocate_worker(worker_id);
|
||||||
|
set_thread(worker_id, new_worker);
|
||||||
|
return new_worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractWorkGang::add_workers(bool initializing) {
|
||||||
|
|
||||||
os::ThreadType worker_type;
|
os::ThreadType worker_type;
|
||||||
if (are_ConcurrentGC_threads()) {
|
if (are_ConcurrentGC_threads()) {
|
||||||
worker_type = os::cgc_thread;
|
worker_type = os::cgc_thread;
|
||||||
} else {
|
} else {
|
||||||
worker_type = os::pgc_thread;
|
worker_type = os::pgc_thread;
|
||||||
}
|
}
|
||||||
for (uint worker = 0; worker < total_workers(); worker += 1) {
|
|
||||||
AbstractGangWorker* new_worker = allocate_worker(worker);
|
_created_workers = WorkerManager::add_workers(this,
|
||||||
assert(new_worker != NULL, "Failed to allocate GangWorker");
|
_active_workers,
|
||||||
_workers[worker] = new_worker;
|
_total_workers,
|
||||||
if (new_worker == NULL || !os::create_thread(new_worker, worker_type)) {
|
_created_workers,
|
||||||
vm_exit_out_of_memory(0, OOM_MALLOC_ERROR,
|
worker_type,
|
||||||
"Cannot create worker GC thread. Out of system resources.");
|
initializing);
|
||||||
return false;
|
_active_workers = MIN2(_created_workers, _active_workers);
|
||||||
}
|
|
||||||
if (!DisableStartThread) {
|
|
||||||
os::start_thread(new_worker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractGangWorker* AbstractWorkGang::worker(uint i) const {
|
AbstractGangWorker* AbstractWorkGang::worker(uint i) const {
|
||||||
|
@ -79,7 +88,7 @@ AbstractGangWorker* AbstractWorkGang::worker(uint i) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractWorkGang::print_worker_threads_on(outputStream* st) const {
|
void AbstractWorkGang::print_worker_threads_on(outputStream* st) const {
|
||||||
uint workers = total_workers();
|
uint workers = created_workers();
|
||||||
for (uint i = 0; i < workers; i++) {
|
for (uint i = 0; i < workers; i++) {
|
||||||
worker(i)->print_on(st);
|
worker(i)->print_on(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
|
@ -88,7 +97,7 @@ void AbstractWorkGang::print_worker_threads_on(outputStream* st) const {
|
||||||
|
|
||||||
void AbstractWorkGang::threads_do(ThreadClosure* tc) const {
|
void AbstractWorkGang::threads_do(ThreadClosure* tc) const {
|
||||||
assert(tc != NULL, "Null ThreadClosure");
|
assert(tc != NULL, "Null ThreadClosure");
|
||||||
uint workers = total_workers();
|
uint workers = created_workers();
|
||||||
for (uint i = 0; i < workers; i++) {
|
for (uint i = 0; i < workers; i++) {
|
||||||
tc->do_thread(worker(i));
|
tc->do_thread(worker(i));
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,8 @@ class AbstractWorkGang : public CHeapObj<mtInternal> {
|
||||||
uint _total_workers;
|
uint _total_workers;
|
||||||
// The currently active workers in this gang.
|
// The currently active workers in this gang.
|
||||||
uint _active_workers;
|
uint _active_workers;
|
||||||
|
// The count of created workers in the gang.
|
||||||
|
uint _created_workers;
|
||||||
// Printing support.
|
// Printing support.
|
||||||
const char* _name;
|
const char* _name;
|
||||||
|
|
||||||
|
@ -120,23 +122,32 @@ class AbstractWorkGang : public CHeapObj<mtInternal> {
|
||||||
const bool _are_GC_task_threads;
|
const bool _are_GC_task_threads;
|
||||||
const bool _are_ConcurrentGC_threads;
|
const bool _are_ConcurrentGC_threads;
|
||||||
|
|
||||||
|
void set_thread(uint worker_id, AbstractGangWorker* worker) {
|
||||||
|
_workers[worker_id] = worker;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AbstractWorkGang(const char* name, uint workers, bool are_GC_task_threads, bool are_ConcurrentGC_threads) :
|
AbstractWorkGang(const char* name, uint workers, bool are_GC_task_threads, bool are_ConcurrentGC_threads) :
|
||||||
_name(name),
|
_name(name),
|
||||||
_total_workers(workers),
|
_total_workers(workers),
|
||||||
_active_workers(UseDynamicNumberOfGCThreads ? 1U : workers),
|
_active_workers(UseDynamicNumberOfGCThreads ? 1U : workers),
|
||||||
|
_created_workers(0),
|
||||||
_are_GC_task_threads(are_GC_task_threads),
|
_are_GC_task_threads(are_GC_task_threads),
|
||||||
_are_ConcurrentGC_threads(are_ConcurrentGC_threads)
|
_are_ConcurrentGC_threads(are_ConcurrentGC_threads)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// Initialize workers in the gang. Return true if initialization succeeded.
|
// Initialize workers in the gang. Return true if initialization succeeded.
|
||||||
bool initialize_workers();
|
void initialize_workers();
|
||||||
|
|
||||||
bool are_GC_task_threads() const { return _are_GC_task_threads; }
|
bool are_GC_task_threads() const { return _are_GC_task_threads; }
|
||||||
bool are_ConcurrentGC_threads() const { return _are_ConcurrentGC_threads; }
|
bool are_ConcurrentGC_threads() const { return _are_ConcurrentGC_threads; }
|
||||||
|
|
||||||
uint total_workers() const { return _total_workers; }
|
uint total_workers() const { return _total_workers; }
|
||||||
|
|
||||||
|
uint created_workers() const {
|
||||||
|
return _created_workers;
|
||||||
|
}
|
||||||
|
|
||||||
virtual uint active_workers() const {
|
virtual uint active_workers() const {
|
||||||
assert(_active_workers <= _total_workers,
|
assert(_active_workers <= _total_workers,
|
||||||
"_active_workers: %u > _total_workers: %u", _active_workers, _total_workers);
|
"_active_workers: %u > _total_workers: %u", _active_workers, _total_workers);
|
||||||
|
@ -144,22 +155,29 @@ class AbstractWorkGang : public CHeapObj<mtInternal> {
|
||||||
"Unless dynamic should use total workers");
|
"Unless dynamic should use total workers");
|
||||||
return _active_workers;
|
return _active_workers;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_active_workers(uint v) {
|
void set_active_workers(uint v) {
|
||||||
assert(v <= _total_workers,
|
assert(v <= _total_workers,
|
||||||
"Trying to set more workers active than there are");
|
"Trying to set more workers active than there are");
|
||||||
_active_workers = MIN2(v, _total_workers);
|
_active_workers = MIN2(v, _total_workers);
|
||||||
|
add_workers(false /* exit_on_failure */);
|
||||||
assert(v != 0, "Trying to set active workers to 0");
|
assert(v != 0, "Trying to set active workers to 0");
|
||||||
_active_workers = MAX2(1U, _active_workers);
|
|
||||||
assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
|
assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
|
||||||
"Unless dynamic should use total workers");
|
"Unless dynamic should use total workers");
|
||||||
log_info(gc, task)("GC Workers: using %d out of %d", _active_workers, _total_workers);
|
log_info(gc, task)("GC Workers: using %d out of %d", _active_workers, _total_workers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add GC workers as needed.
|
||||||
|
void add_workers(bool initializing);
|
||||||
|
|
||||||
// Return the Ith worker.
|
// Return the Ith worker.
|
||||||
AbstractGangWorker* worker(uint i) const;
|
AbstractGangWorker* worker(uint i) const;
|
||||||
|
|
||||||
void threads_do(ThreadClosure* tc) const;
|
void threads_do(ThreadClosure* tc) const;
|
||||||
|
|
||||||
|
// Create a GC worker and install it into the work gang.
|
||||||
|
virtual AbstractGangWorker* install_worker(uint which);
|
||||||
|
|
||||||
// Debugging.
|
// Debugging.
|
||||||
const char* name() const { return _name; }
|
const char* name() const { return _name; }
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,10 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "interpreter/oopMapCache.hpp"
|
#include "interpreter/oopMapCache.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "runtime/signature.hpp"
|
#include "runtime/signature.hpp"
|
||||||
|
|
||||||
|
@ -469,10 +469,12 @@ void OopMapCache::flush_obsolete_entries() {
|
||||||
if (!_array[i].is_empty() && _array[i].method()->is_old()) {
|
if (!_array[i].is_empty() && _array[i].method()->is_old()) {
|
||||||
// Cache entry is occupied by an old redefined method and we don't want
|
// Cache entry is occupied by an old redefined method and we don't want
|
||||||
// to pin it down so flush the entry.
|
// to pin it down so flush the entry.
|
||||||
RC_TRACE(0x08000000, ("flush: %s(%s): cached entry @%d",
|
if (log_is_enabled(Debug, redefine, class, oopmap)) {
|
||||||
_array[i].method()->name()->as_C_string(),
|
ResourceMark rm;
|
||||||
_array[i].method()->signature()->as_C_string(), i));
|
log_debug(redefine, class, oopmap)
|
||||||
|
("flush: %s(%s): cached entry @%d",
|
||||||
|
_array[i].method()->name()->as_C_string(), _array[i].method()->signature()->as_C_string(), i);
|
||||||
|
}
|
||||||
_array[i].flush();
|
_array[i].flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,23 +32,28 @@
|
||||||
// (The tags 'all', 'disable' and 'help' are special tags that can
|
// (The tags 'all', 'disable' and 'help' are special tags that can
|
||||||
// not be used in log calls, and should not be listed below.)
|
// not be used in log calls, and should not be listed below.)
|
||||||
#define LOG_TAG_LIST \
|
#define LOG_TAG_LIST \
|
||||||
LOG_TAG(alloc) \
|
LOG_TAG(add) \
|
||||||
LOG_TAG(age) \
|
LOG_TAG(age) \
|
||||||
|
LOG_TAG(alloc) \
|
||||||
LOG_TAG(arguments) \
|
LOG_TAG(arguments) \
|
||||||
|
LOG_TAG(annotation) \
|
||||||
LOG_TAG(barrier) \
|
LOG_TAG(barrier) \
|
||||||
LOG_TAG(biasedlocking) \
|
LOG_TAG(biasedlocking) \
|
||||||
LOG_TAG(bot) \
|
LOG_TAG(bot) \
|
||||||
|
LOG_TAG(breakpoint) \
|
||||||
LOG_TAG(census) \
|
LOG_TAG(census) \
|
||||||
LOG_TAG(class) \
|
LOG_TAG(class) \
|
||||||
LOG_TAG(classhisto) \
|
LOG_TAG(classhisto) \
|
||||||
LOG_TAG(cleanup) \
|
LOG_TAG(cleanup) \
|
||||||
LOG_TAG(compaction) \
|
LOG_TAG(compaction) \
|
||||||
LOG_TAG(constraints) \
|
LOG_TAG(constraints) \
|
||||||
|
LOG_TAG(constantpool) \
|
||||||
LOG_TAG(coops) \
|
LOG_TAG(coops) \
|
||||||
LOG_TAG(cpu) \
|
LOG_TAG(cpu) \
|
||||||
LOG_TAG(cset) \
|
LOG_TAG(cset) \
|
||||||
LOG_TAG(data) \
|
LOG_TAG(data) \
|
||||||
LOG_TAG(defaultmethods) \
|
LOG_TAG(defaultmethods) \
|
||||||
|
LOG_TAG(dump) \
|
||||||
LOG_TAG(ergo) \
|
LOG_TAG(ergo) \
|
||||||
LOG_TAG(exceptions) \
|
LOG_TAG(exceptions) \
|
||||||
LOG_TAG(exit) \
|
LOG_TAG(exit) \
|
||||||
|
@ -57,6 +62,7 @@
|
||||||
LOG_TAG(heap) \
|
LOG_TAG(heap) \
|
||||||
LOG_TAG(humongous) \
|
LOG_TAG(humongous) \
|
||||||
LOG_TAG(ihop) \
|
LOG_TAG(ihop) \
|
||||||
|
LOG_TAG(iklass) \
|
||||||
LOG_TAG(init) \
|
LOG_TAG(init) \
|
||||||
LOG_TAG(itables) \
|
LOG_TAG(itables) \
|
||||||
LOG_TAG(jni) \
|
LOG_TAG(jni) \
|
||||||
|
@ -65,13 +71,20 @@
|
||||||
LOG_TAG(load) /* Trace all classes loaded */ \
|
LOG_TAG(load) /* Trace all classes loaded */ \
|
||||||
LOG_TAG(loader) \
|
LOG_TAG(loader) \
|
||||||
LOG_TAG(logging) \
|
LOG_TAG(logging) \
|
||||||
|
LOG_TAG(mark) \
|
||||||
LOG_TAG(marking) \
|
LOG_TAG(marking) \
|
||||||
|
LOG_TAG(methodcomparator) \
|
||||||
|
LOG_TAG(metadata) \
|
||||||
LOG_TAG(metaspace) \
|
LOG_TAG(metaspace) \
|
||||||
LOG_TAG(mmu) \
|
LOG_TAG(mmu) \
|
||||||
LOG_TAG(modules) \
|
LOG_TAG(modules) \
|
||||||
LOG_TAG(monitorinflation) \
|
LOG_TAG(monitorinflation) \
|
||||||
LOG_TAG(monitormismatch) \
|
LOG_TAG(monitormismatch) \
|
||||||
|
LOG_TAG(nmethod) \
|
||||||
|
LOG_TAG(normalize) \
|
||||||
LOG_TAG(objecttagging) \
|
LOG_TAG(objecttagging) \
|
||||||
|
LOG_TAG(obsolete) \
|
||||||
|
LOG_TAG(oopmap) \
|
||||||
LOG_TAG(os) \
|
LOG_TAG(os) \
|
||||||
LOG_TAG(pagesize) \
|
LOG_TAG(pagesize) \
|
||||||
LOG_TAG(path) \
|
LOG_TAG(path) \
|
||||||
|
@ -81,9 +94,11 @@
|
||||||
LOG_TAG(preorder) /* Trace all classes loaded in order referenced (not loaded) */ \
|
LOG_TAG(preorder) /* Trace all classes loaded in order referenced (not loaded) */ \
|
||||||
LOG_TAG(protectiondomain) /* "Trace protection domain verification" */ \
|
LOG_TAG(protectiondomain) /* "Trace protection domain verification" */ \
|
||||||
LOG_TAG(ref) \
|
LOG_TAG(ref) \
|
||||||
|
LOG_TAG(redefine) \
|
||||||
LOG_TAG(refine) \
|
LOG_TAG(refine) \
|
||||||
LOG_TAG(region) \
|
LOG_TAG(region) \
|
||||||
LOG_TAG(remset) \
|
LOG_TAG(remset) \
|
||||||
|
LOG_TAG(purge) \
|
||||||
LOG_TAG(resolve) \
|
LOG_TAG(resolve) \
|
||||||
LOG_TAG(safepoint) \
|
LOG_TAG(safepoint) \
|
||||||
LOG_TAG(scavenge) \
|
LOG_TAG(scavenge) \
|
||||||
|
@ -95,6 +110,8 @@
|
||||||
LOG_TAG(stats) \
|
LOG_TAG(stats) \
|
||||||
LOG_TAG(stringdedup) \
|
LOG_TAG(stringdedup) \
|
||||||
LOG_TAG(stringtable) \
|
LOG_TAG(stringtable) \
|
||||||
|
LOG_TAG(stackmap) \
|
||||||
|
LOG_TAG(subclass) \
|
||||||
LOG_TAG(survivor) \
|
LOG_TAG(survivor) \
|
||||||
LOG_TAG(sweep) \
|
LOG_TAG(sweep) \
|
||||||
LOG_TAG(task) \
|
LOG_TAG(task) \
|
||||||
|
@ -102,6 +119,8 @@
|
||||||
LOG_TAG(thread) \
|
LOG_TAG(thread) \
|
||||||
LOG_TAG(tlab) \
|
LOG_TAG(tlab) \
|
||||||
LOG_TAG(time) \
|
LOG_TAG(time) \
|
||||||
|
LOG_TAG(timer) \
|
||||||
|
LOG_TAG(update) \
|
||||||
LOG_TAG(unload) /* Trace unloading of classes */ \
|
LOG_TAG(unload) /* Trace unloading of classes */ \
|
||||||
LOG_TAG(verification) \
|
LOG_TAG(verification) \
|
||||||
LOG_TAG(verify) \
|
LOG_TAG(verify) \
|
||||||
|
|
|
@ -664,64 +664,6 @@ void* Arena::internal_malloc_4(size_t x) {
|
||||||
// Non-product code
|
// Non-product code
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
// The global operator new should never be called since it will usually indicate
|
|
||||||
// a memory leak. Use CHeapObj as the base class of such objects to make it explicit
|
|
||||||
// that they're allocated on the C heap.
|
|
||||||
// Commented out in product version to avoid conflicts with third-party C++ native code.
|
|
||||||
//
|
|
||||||
// In C++98/03 the throwing new operators are defined with the following signature:
|
|
||||||
//
|
|
||||||
// void* operator new(std::size_tsize) throw(std::bad_alloc);
|
|
||||||
// void* operator new[](std::size_tsize) throw(std::bad_alloc);
|
|
||||||
//
|
|
||||||
// while all the other (non-throwing) new and delete operators are defined with an empty
|
|
||||||
// throw clause (i.e. "operator delete(void* p) throw()") which means that they do not
|
|
||||||
// throw any exceptions (see section 18.4 of the C++ standard).
|
|
||||||
//
|
|
||||||
// In the new C++11/14 standard, the signature of the throwing new operators was changed
|
|
||||||
// by completely omitting the throw clause (which effectively means they could throw any
|
|
||||||
// exception) while all the other new/delete operators where changed to have a 'nothrow'
|
|
||||||
// clause instead of an empty throw clause.
|
|
||||||
//
|
|
||||||
// Unfortunately, the support for exception specifications among C++ compilers is still
|
|
||||||
// very fragile. While some more strict compilers like AIX xlC or HP aCC reject to
|
|
||||||
// override the default throwing new operator with a user operator with an empty throw()
|
|
||||||
// clause, the MS Visual C++ compiler warns for every non-empty throw clause like
|
|
||||||
// throw(std::bad_alloc) that it will ignore the exception specification. The following
|
|
||||||
// operator definitions have been checked to correctly work with all currently supported
|
|
||||||
// compilers and they should be upwards compatible with C++11/14. Therefore
|
|
||||||
// PLEASE BE CAREFUL if you change the signature of the following operators!
|
|
||||||
|
|
||||||
static void * zero = (void *) 0;
|
|
||||||
|
|
||||||
void* operator new(size_t size) /* throw(std::bad_alloc) */ {
|
|
||||||
fatal("Should not call global operator new");
|
|
||||||
return zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* operator new [](size_t size) /* throw(std::bad_alloc) */ {
|
|
||||||
fatal("Should not call global operator new[]");
|
|
||||||
return zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() {
|
|
||||||
fatal("Should not call global operator new");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* operator new [](size_t size, std::nothrow_t& nothrow_constant) throw() {
|
|
||||||
fatal("Should not call global operator new[]");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator delete(void* p) throw() {
|
|
||||||
fatal("Should not call global delete");
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator delete [](void* p) throw() {
|
|
||||||
fatal("Should not call global delete []");
|
|
||||||
}
|
|
||||||
|
|
||||||
void AllocatedObj::print() const { print_on(tty); }
|
void AllocatedObj::print() const { print_on(tty); }
|
||||||
void AllocatedObj::print_value() const { print_value_on(tty); }
|
void AllocatedObj::print_value() const { print_value_on(tty); }
|
||||||
|
|
||||||
|
|
|
@ -881,7 +881,7 @@ bool FileMapInfo::FileMapHeader::validate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Arguments::patch_dirs() != NULL) {
|
if (Arguments::get_xpatchprefix() != NULL) {
|
||||||
FileMapInfo::fail_continue("The shared archive file cannot be used with -Xpatch.");
|
FileMapInfo::fail_continue("The shared archive file cannot be used with -Xpatch.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
92
hotspot/src/share/vm/memory/operator_new.cpp
Normal file
92
hotspot/src/share/vm/memory/operator_new.cpp
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1997, 2014, 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 "utilities/debug.hpp"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
// Non-product code
|
||||||
|
|
||||||
|
#ifndef PRODUCT
|
||||||
|
// The global operator new should never be called since it will usually indicate
|
||||||
|
// a memory leak. Use CHeapObj as the base class of such objects to make it explicit
|
||||||
|
// that they're allocated on the C heap.
|
||||||
|
// Commented out in product version to avoid conflicts with third-party C++ native code.
|
||||||
|
//
|
||||||
|
// In C++98/03 the throwing new operators are defined with the following signature:
|
||||||
|
//
|
||||||
|
// void* operator new(std::size_tsize) throw(std::bad_alloc);
|
||||||
|
// void* operator new[](std::size_tsize) throw(std::bad_alloc);
|
||||||
|
//
|
||||||
|
// while all the other (non-throwing) new and delete operators are defined with an empty
|
||||||
|
// throw clause (i.e. "operator delete(void* p) throw()") which means that they do not
|
||||||
|
// throw any exceptions (see section 18.4 of the C++ standard).
|
||||||
|
//
|
||||||
|
// In the new C++11/14 standard, the signature of the throwing new operators was changed
|
||||||
|
// by completely omitting the throw clause (which effectively means they could throw any
|
||||||
|
// exception) while all the other new/delete operators where changed to have a 'nothrow'
|
||||||
|
// clause instead of an empty throw clause.
|
||||||
|
//
|
||||||
|
// Unfortunately, the support for exception specifications among C++ compilers is still
|
||||||
|
// very fragile. While some more strict compilers like AIX xlC or HP aCC reject to
|
||||||
|
// override the default throwing new operator with a user operator with an empty throw()
|
||||||
|
// clause, the MS Visual C++ compiler warns for every non-empty throw clause like
|
||||||
|
// throw(std::bad_alloc) that it will ignore the exception specification. The following
|
||||||
|
// operator definitions have been checked to correctly work with all currently supported
|
||||||
|
// compilers and they should be upwards compatible with C++11/14. Therefore
|
||||||
|
// PLEASE BE CAREFUL if you change the signature of the following operators!
|
||||||
|
|
||||||
|
static void * zero = (void *) 0;
|
||||||
|
|
||||||
|
void* operator new(size_t size) /* throw(std::bad_alloc) */ {
|
||||||
|
fatal("Should not call global operator new");
|
||||||
|
return zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* operator new [](size_t size) /* throw(std::bad_alloc) */ {
|
||||||
|
fatal("Should not call global operator new[]");
|
||||||
|
return zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() {
|
||||||
|
fatal("Should not call global operator new");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* operator new [](size_t size, std::nothrow_t& nothrow_constant) throw() {
|
||||||
|
fatal("Should not call global operator new[]");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* p) throw() {
|
||||||
|
fatal("Should not call global delete");
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete [](void* p) throw() {
|
||||||
|
fatal("Should not call global delete []");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // Non-product
|
|
@ -55,7 +55,6 @@
|
||||||
#include "oops/objArrayOop.inline.hpp"
|
#include "oops/objArrayOop.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "oops/typeArrayKlass.hpp"
|
#include "oops/typeArrayKlass.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/atomic.inline.hpp"
|
#include "runtime/atomic.inline.hpp"
|
||||||
#include "runtime/commandLineFlagConstraintList.hpp"
|
#include "runtime/commandLineFlagConstraintList.hpp"
|
||||||
|
|
|
@ -25,12 +25,12 @@
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "interpreter/rewriter.hpp"
|
#include "interpreter/rewriter.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "memory/universe.inline.hpp"
|
#include "memory/universe.inline.hpp"
|
||||||
#include "oops/cpCache.hpp"
|
#include "oops/cpCache.hpp"
|
||||||
#include "oops/objArrayOop.inline.hpp"
|
#include "oops/objArrayOop.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "prims/methodHandles.hpp"
|
#include "prims/methodHandles.hpp"
|
||||||
#include "runtime/atomic.inline.hpp"
|
#include "runtime/atomic.inline.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
|
@ -438,17 +438,14 @@ bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
|
||||||
// match old_method so need an update
|
// match old_method so need an update
|
||||||
// NOTE: can't use set_f2_as_vfinal_method as it asserts on different values
|
// NOTE: can't use set_f2_as_vfinal_method as it asserts on different values
|
||||||
_f2 = (intptr_t)new_method;
|
_f2 = (intptr_t)new_method;
|
||||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
if (log_is_enabled(Info, redefine, class, update)) {
|
||||||
|
ResourceMark rm;
|
||||||
if (!(*trace_name_printed)) {
|
if (!(*trace_name_printed)) {
|
||||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
|
||||||
RC_TRACE_MESG(("adjust: name=%s",
|
|
||||||
old_method->method_holder()->external_name()));
|
|
||||||
*trace_name_printed = true;
|
*trace_name_printed = true;
|
||||||
}
|
}
|
||||||
// RC_TRACE macro has an embedded ResourceMark
|
log_debug(redefine, class, update, constantpool)
|
||||||
RC_TRACE(0x00400000, ("cpc vf-entry update: %s(%s)",
|
("cpc vf-entry update: %s(%s)", new_method->name()->as_C_string(), new_method->signature()->as_C_string());
|
||||||
new_method->name()->as_C_string(),
|
|
||||||
new_method->signature()->as_C_string()));
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -465,17 +462,14 @@ bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
|
||||||
|
|
||||||
if (_f1 == old_method) {
|
if (_f1 == old_method) {
|
||||||
_f1 = new_method;
|
_f1 = new_method;
|
||||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
if (log_is_enabled(Info, redefine, class, update)) {
|
||||||
|
ResourceMark rm;
|
||||||
if (!(*trace_name_printed)) {
|
if (!(*trace_name_printed)) {
|
||||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
|
||||||
RC_TRACE_MESG(("adjust: name=%s",
|
|
||||||
old_method->method_holder()->external_name()));
|
|
||||||
*trace_name_printed = true;
|
*trace_name_printed = true;
|
||||||
}
|
}
|
||||||
// RC_TRACE macro has an embedded ResourceMark
|
log_debug(redefine, class, update, constantpool)
|
||||||
RC_TRACE(0x00400000, ("cpc entry update: %s(%s)",
|
("cpc entry update: %s(%s)", new_method->name()->as_C_string(), new_method->signature()->as_C_string());
|
||||||
new_method->name()->as_C_string(),
|
|
||||||
new_method->signature()->as_C_string()));
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,6 @@
|
||||||
#include "oops/symbol.hpp"
|
#include "oops/symbol.hpp"
|
||||||
#include "prims/jvmtiExport.hpp"
|
#include "prims/jvmtiExport.hpp"
|
||||||
#include "prims/jvmtiRedefineClasses.hpp"
|
#include "prims/jvmtiRedefineClasses.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "prims/jvmtiThreadState.hpp"
|
#include "prims/jvmtiThreadState.hpp"
|
||||||
#include "prims/methodComparator.hpp"
|
#include "prims/methodComparator.hpp"
|
||||||
#include "runtime/atomic.inline.hpp"
|
#include "runtime/atomic.inline.hpp"
|
||||||
|
@ -2574,17 +2573,17 @@ void InstanceKlass::adjust_default_methods(InstanceKlass* holder, bool* trace_na
|
||||||
assert(old_method != new_method, "sanity check");
|
assert(old_method != new_method, "sanity check");
|
||||||
|
|
||||||
default_methods()->at_put(index, new_method);
|
default_methods()->at_put(index, new_method);
|
||||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
if (log_is_enabled(Info, redefine, class, update)) {
|
||||||
|
ResourceMark rm;
|
||||||
if (!(*trace_name_printed)) {
|
if (!(*trace_name_printed)) {
|
||||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
log_info(redefine, class, update)
|
||||||
RC_TRACE_MESG(("adjust: klassname=%s default methods from name=%s",
|
("adjust: klassname=%s default methods from name=%s",
|
||||||
external_name(),
|
external_name(), old_method->method_holder()->external_name());
|
||||||
old_method->method_holder()->external_name()));
|
|
||||||
*trace_name_printed = true;
|
*trace_name_printed = true;
|
||||||
}
|
}
|
||||||
RC_TRACE(0x00100000, ("default method update: %s(%s) ",
|
log_debug(redefine, class, update, vtables)
|
||||||
new_method->name()->as_C_string(),
|
("default method update: %s(%s) ",
|
||||||
new_method->signature()->as_C_string()));
|
new_method->name()->as_C_string(), new_method->signature()->as_C_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3353,8 +3352,8 @@ void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
|
||||||
ClassLoaderData* loader_data = ik->class_loader_data();
|
ClassLoaderData* loader_data = ik->class_loader_data();
|
||||||
assert(loader_data != NULL, "should never be null");
|
assert(loader_data != NULL, "should never be null");
|
||||||
|
|
||||||
// RC_TRACE macro has an embedded ResourceMark
|
ResourceMark rm;
|
||||||
RC_TRACE(0x00000200, ("purge: %s: previous versions", ik->external_name()));
|
log_trace(redefine, class, iklass, purge)("%s: previous versions", ik->external_name());
|
||||||
|
|
||||||
// previous versions are linked together through the InstanceKlass
|
// previous versions are linked together through the InstanceKlass
|
||||||
InstanceKlass* pv_node = ik->previous_versions();
|
InstanceKlass* pv_node = ik->previous_versions();
|
||||||
|
@ -3372,8 +3371,7 @@ void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
|
||||||
// are executing. Unlink this previous_version.
|
// are executing. Unlink this previous_version.
|
||||||
// The previous version InstanceKlass is on the ClassLoaderData deallocate list
|
// The previous version InstanceKlass is on the ClassLoaderData deallocate list
|
||||||
// so will be deallocated during the next phase of class unloading.
|
// so will be deallocated during the next phase of class unloading.
|
||||||
RC_TRACE(0x00000200, ("purge: previous version " INTPTR_FORMAT " is dead",
|
log_trace(redefine, class, iklass, purge)("previous version " INTPTR_FORMAT " is dead", p2i(pv_node));
|
||||||
p2i(pv_node)));
|
|
||||||
// For debugging purposes.
|
// For debugging purposes.
|
||||||
pv_node->set_is_scratch_class();
|
pv_node->set_is_scratch_class();
|
||||||
pv_node->class_loader_data()->add_to_deallocate_list(pv_node);
|
pv_node->class_loader_data()->add_to_deallocate_list(pv_node);
|
||||||
|
@ -3383,8 +3381,7 @@ void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
|
||||||
version++;
|
version++;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
RC_TRACE(0x00000200, ("purge: previous version " INTPTR_FORMAT " is alive",
|
log_trace(redefine, class, iklass, purge)("previous version " INTPTR_FORMAT " is alive", p2i(pv_node));
|
||||||
p2i(pv_node)));
|
|
||||||
assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
|
assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
|
||||||
guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
|
guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
|
||||||
live_count++;
|
live_count++;
|
||||||
|
@ -3396,8 +3393,7 @@ void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
|
||||||
// longer running.
|
// longer running.
|
||||||
Array<Method*>* method_refs = pv_node->methods();
|
Array<Method*>* method_refs = pv_node->methods();
|
||||||
if (method_refs != NULL) {
|
if (method_refs != NULL) {
|
||||||
RC_TRACE(0x00000200, ("purge: previous methods length=%d",
|
log_trace(redefine, class, iklass, purge)("previous methods length=%d", method_refs->length());
|
||||||
method_refs->length()));
|
|
||||||
for (int j = 0; j < method_refs->length(); j++) {
|
for (int j = 0; j < method_refs->length(); j++) {
|
||||||
Method* method = method_refs->at(j);
|
Method* method = method_refs->at(j);
|
||||||
|
|
||||||
|
@ -3409,11 +3405,9 @@ void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
|
||||||
} else {
|
} else {
|
||||||
assert (method->is_obsolete() || method->is_running_emcp(),
|
assert (method->is_obsolete() || method->is_running_emcp(),
|
||||||
"emcp method cannot run after emcp bit is cleared");
|
"emcp method cannot run after emcp bit is cleared");
|
||||||
// RC_TRACE macro has an embedded ResourceMark
|
log_trace(redefine, class, iklass, purge)
|
||||||
RC_TRACE(0x00000200,
|
|
||||||
("purge: %s(%s): prev method @%d in version @%d is alive",
|
("purge: %s(%s): prev method @%d in version @%d is alive",
|
||||||
method->name()->as_C_string(),
|
method->name()->as_C_string(), method->signature()->as_C_string(), j, version);
|
||||||
method->signature()->as_C_string(), j, version));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3422,9 +3416,9 @@ void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
|
||||||
pv_node = pv_node->previous_versions();
|
pv_node = pv_node->previous_versions();
|
||||||
version++;
|
version++;
|
||||||
}
|
}
|
||||||
RC_TRACE(0x00000200,
|
log_trace(redefine, class, iklass, purge)
|
||||||
("purge: previous version stats: live=%d, deleted=%d", live_count,
|
("previous version stats: live=%d, deleted=%d",
|
||||||
deleted_count));
|
live_count, deleted_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3459,9 +3453,9 @@ void InstanceKlass::mark_newly_obsolete_methods(Array<Method*>* old_methods,
|
||||||
method->signature() == m_signature) {
|
method->signature() == m_signature) {
|
||||||
// The current RedefineClasses() call has made all EMCP
|
// The current RedefineClasses() call has made all EMCP
|
||||||
// versions of this method obsolete so mark it as obsolete
|
// versions of this method obsolete so mark it as obsolete
|
||||||
RC_TRACE(0x00000400,
|
log_trace(redefine, class, iklass, add)
|
||||||
("add: %s(%s): flush obsolete method @%d in version @%d",
|
("%s(%s): flush obsolete method @%d in version @%d",
|
||||||
m_name->as_C_string(), m_signature->as_C_string(), k, j));
|
m_name->as_C_string(), m_signature->as_C_string(), k, j);
|
||||||
|
|
||||||
method->set_is_obsolete();
|
method->set_is_obsolete();
|
||||||
break;
|
break;
|
||||||
|
@ -3493,9 +3487,9 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
|
||||||
assert(Thread::current()->is_VM_thread(),
|
assert(Thread::current()->is_VM_thread(),
|
||||||
"only VMThread can add previous versions");
|
"only VMThread can add previous versions");
|
||||||
|
|
||||||
// RC_TRACE macro has an embedded ResourceMark
|
ResourceMark rm;
|
||||||
RC_TRACE(0x00000400, ("adding previous version ref for %s, EMCP_cnt=%d",
|
log_trace(redefine, class, iklass, add)
|
||||||
scratch_class->external_name(), emcp_method_count));
|
("adding previous version ref for %s, EMCP_cnt=%d", scratch_class->external_name(), emcp_method_count);
|
||||||
|
|
||||||
// Clean out old previous versions
|
// Clean out old previous versions
|
||||||
purge_previous_versions(this);
|
purge_previous_versions(this);
|
||||||
|
@ -3511,7 +3505,7 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
|
||||||
// we don't need to add this as a previous version.
|
// we don't need to add this as a previous version.
|
||||||
ConstantPool* cp_ref = scratch_class->constants();
|
ConstantPool* cp_ref = scratch_class->constants();
|
||||||
if (!cp_ref->on_stack()) {
|
if (!cp_ref->on_stack()) {
|
||||||
RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running"));
|
log_trace(redefine, class, iklass, add)("scratch class not added; no methods are running");
|
||||||
// For debugging purposes.
|
// For debugging purposes.
|
||||||
scratch_class->set_is_scratch_class();
|
scratch_class->set_is_scratch_class();
|
||||||
scratch_class->class_loader_data()->add_to_deallocate_list(scratch_class());
|
scratch_class->class_loader_data()->add_to_deallocate_list(scratch_class());
|
||||||
|
@ -3534,17 +3528,17 @@ void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
|
||||||
// method may exit. If so, we would set a breakpoint in a method that
|
// method may exit. If so, we would set a breakpoint in a method that
|
||||||
// is never reached, but this won't be noticeable to the programmer.
|
// is never reached, but this won't be noticeable to the programmer.
|
||||||
old_method->set_running_emcp(true);
|
old_method->set_running_emcp(true);
|
||||||
RC_TRACE(0x00000400, ("add: EMCP method %s is on_stack " INTPTR_FORMAT,
|
log_trace(redefine, class, iklass, add)
|
||||||
old_method->name_and_sig_as_C_string(), p2i(old_method)));
|
("EMCP method %s is on_stack " INTPTR_FORMAT, old_method->name_and_sig_as_C_string(), p2i(old_method));
|
||||||
} else if (!old_method->is_obsolete()) {
|
} else if (!old_method->is_obsolete()) {
|
||||||
RC_TRACE(0x00000400, ("add: EMCP method %s is NOT on_stack " INTPTR_FORMAT,
|
log_trace(redefine, class, iklass, add)
|
||||||
old_method->name_and_sig_as_C_string(), p2i(old_method)));
|
("EMCP method %s is NOT on_stack " INTPTR_FORMAT, old_method->name_and_sig_as_C_string(), p2i(old_method));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add previous version if any methods are still running.
|
// Add previous version if any methods are still running.
|
||||||
RC_TRACE(0x00000400, ("add: scratch class added; one of its methods is on_stack"));
|
log_trace(redefine, class, iklass, add)("scratch class added; one of its methods is on_stack");
|
||||||
assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
|
assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
|
||||||
scratch_class->link_previous_versions(previous_versions());
|
scratch_class->link_previous_versions(previous_versions());
|
||||||
link_previous_versions(scratch_class());
|
link_previous_versions(scratch_class());
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include "oops/method.hpp"
|
#include "oops/method.hpp"
|
||||||
#include "oops/objArrayOop.hpp"
|
#include "oops/objArrayOop.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "utilities/copy.hpp"
|
#include "utilities/copy.hpp"
|
||||||
|
@ -887,19 +886,17 @@ void klassVtable::adjust_method_entries(InstanceKlass* holder, bool * trace_name
|
||||||
updated_default = adjust_default_method(index, old_method, new_method);
|
updated_default = adjust_default_method(index, old_method, new_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
if (log_is_enabled(Info, redefine, class, update)) {
|
||||||
|
ResourceMark rm;
|
||||||
if (!(*trace_name_printed)) {
|
if (!(*trace_name_printed)) {
|
||||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
log_info(redefine, class, update)
|
||||||
RC_TRACE_MESG(("adjust: klassname=%s for methods from name=%s",
|
("adjust: klassname=%s for methods from name=%s",
|
||||||
klass()->external_name(),
|
klass()->external_name(), old_method->method_holder()->external_name());
|
||||||
old_method->method_holder()->external_name()));
|
|
||||||
*trace_name_printed = true;
|
*trace_name_printed = true;
|
||||||
}
|
}
|
||||||
// RC_TRACE macro has an embedded ResourceMark
|
log_debug(redefine, class, update, vtables)
|
||||||
RC_TRACE(0x00100000, ("vtable method update: %s(%s), updated default = %s",
|
("vtable method update: %s(%s), updated default = %s",
|
||||||
new_method->name()->as_C_string(),
|
new_method->name()->as_C_string(), new_method->signature()->as_C_string(), updated_default ? "true" : "false");
|
||||||
new_method->signature()->as_C_string(),
|
|
||||||
updated_default ? "true" : "false"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1205,17 +1202,14 @@ void klassItable::adjust_method_entries(InstanceKlass* holder, bool * trace_name
|
||||||
|
|
||||||
ime->initialize(new_method);
|
ime->initialize(new_method);
|
||||||
|
|
||||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
if (log_is_enabled(Info, redefine, class, update)) {
|
||||||
|
ResourceMark rm;
|
||||||
if (!(*trace_name_printed)) {
|
if (!(*trace_name_printed)) {
|
||||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
|
||||||
RC_TRACE_MESG(("adjust: name=%s",
|
|
||||||
old_method->method_holder()->external_name()));
|
|
||||||
*trace_name_printed = true;
|
*trace_name_printed = true;
|
||||||
}
|
}
|
||||||
// RC_TRACE macro has an embedded ResourceMark
|
log_trace(redefine, class, update, itables)
|
||||||
RC_TRACE(0x00200000, ("itable method update: %s(%s)",
|
("itable method update: %s(%s)", new_method->name()->as_C_string(), new_method->signature()->as_C_string());
|
||||||
new_method->name()->as_C_string(),
|
|
||||||
new_method->signature()->as_C_string()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -409,22 +409,6 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
|
||||||
case vmIntrinsics::_putLong:
|
case vmIntrinsics::_putLong:
|
||||||
case vmIntrinsics::_putFloat:
|
case vmIntrinsics::_putFloat:
|
||||||
case vmIntrinsics::_putDouble:
|
case vmIntrinsics::_putDouble:
|
||||||
case vmIntrinsics::_getByte_raw:
|
|
||||||
case vmIntrinsics::_getShort_raw:
|
|
||||||
case vmIntrinsics::_getChar_raw:
|
|
||||||
case vmIntrinsics::_getInt_raw:
|
|
||||||
case vmIntrinsics::_getLong_raw:
|
|
||||||
case vmIntrinsics::_getFloat_raw:
|
|
||||||
case vmIntrinsics::_getDouble_raw:
|
|
||||||
case vmIntrinsics::_getAddress_raw:
|
|
||||||
case vmIntrinsics::_putByte_raw:
|
|
||||||
case vmIntrinsics::_putShort_raw:
|
|
||||||
case vmIntrinsics::_putChar_raw:
|
|
||||||
case vmIntrinsics::_putInt_raw:
|
|
||||||
case vmIntrinsics::_putLong_raw:
|
|
||||||
case vmIntrinsics::_putFloat_raw:
|
|
||||||
case vmIntrinsics::_putDouble_raw:
|
|
||||||
case vmIntrinsics::_putAddress_raw:
|
|
||||||
case vmIntrinsics::_getObjectVolatile:
|
case vmIntrinsics::_getObjectVolatile:
|
||||||
case vmIntrinsics::_getBooleanVolatile:
|
case vmIntrinsics::_getBooleanVolatile:
|
||||||
case vmIntrinsics::_getByteVolatile:
|
case vmIntrinsics::_getByteVolatile:
|
||||||
|
|
|
@ -93,7 +93,7 @@ class LibraryCallKit : public GraphKit {
|
||||||
Node* _result; // the result node, if any
|
Node* _result; // the result node, if any
|
||||||
int _reexecute_sp; // the stack pointer when bytecode needs to be reexecuted
|
int _reexecute_sp; // the stack pointer when bytecode needs to be reexecuted
|
||||||
|
|
||||||
const TypeOopPtr* sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type, bool is_native_ptr = false);
|
const TypeOopPtr* sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LibraryCallKit(JVMState* jvms, LibraryIntrinsic* intrinsic)
|
LibraryCallKit(JVMState* jvms, LibraryIntrinsic* intrinsic)
|
||||||
|
@ -247,7 +247,7 @@ class LibraryCallKit : public GraphKit {
|
||||||
void insert_pre_barrier(Node* base_oop, Node* offset, Node* pre_val, bool need_mem_bar);
|
void insert_pre_barrier(Node* base_oop, Node* offset, Node* pre_val, bool need_mem_bar);
|
||||||
|
|
||||||
typedef enum { Relaxed, Opaque, Volatile, Acquire, Release } AccessKind;
|
typedef enum { Relaxed, Opaque, Volatile, Acquire, Release } AccessKind;
|
||||||
bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, AccessKind kind, bool is_unaligned);
|
bool inline_unsafe_access(bool is_store, BasicType type, AccessKind kind, bool is_unaligned);
|
||||||
static bool klass_needs_init_guard(Node* kls);
|
static bool klass_needs_init_guard(Node* kls);
|
||||||
bool inline_unsafe_allocate();
|
bool inline_unsafe_allocate();
|
||||||
bool inline_unsafe_newArray(bool uninitialized);
|
bool inline_unsafe_newArray(bool uninitialized);
|
||||||
|
@ -475,7 +475,6 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
||||||
// Handle symbolic names for otherwise undistinguished boolean switches:
|
// Handle symbolic names for otherwise undistinguished boolean switches:
|
||||||
const bool is_store = true;
|
const bool is_store = true;
|
||||||
const bool is_compress = true;
|
const bool is_compress = true;
|
||||||
const bool is_native_ptr = true;
|
|
||||||
const bool is_static = true;
|
const bool is_static = true;
|
||||||
const bool is_volatile = true;
|
const bool is_volatile = true;
|
||||||
|
|
||||||
|
@ -555,113 +554,95 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
||||||
case vmIntrinsics::_inflateStringC:
|
case vmIntrinsics::_inflateStringC:
|
||||||
case vmIntrinsics::_inflateStringB: return inline_string_copy(!is_compress);
|
case vmIntrinsics::_inflateStringB: return inline_string_copy(!is_compress);
|
||||||
|
|
||||||
case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Relaxed, false);
|
case vmIntrinsics::_getObject: return inline_unsafe_access(!is_store, T_OBJECT, Relaxed, false);
|
||||||
case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Relaxed, false);
|
case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_store, T_BOOLEAN, Relaxed, false);
|
||||||
case vmIntrinsics::_getByte: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Relaxed, false);
|
case vmIntrinsics::_getByte: return inline_unsafe_access(!is_store, T_BYTE, Relaxed, false);
|
||||||
case vmIntrinsics::_getShort: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Relaxed, false);
|
case vmIntrinsics::_getShort: return inline_unsafe_access(!is_store, T_SHORT, Relaxed, false);
|
||||||
case vmIntrinsics::_getChar: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Relaxed, false);
|
case vmIntrinsics::_getChar: return inline_unsafe_access(!is_store, T_CHAR, Relaxed, false);
|
||||||
case vmIntrinsics::_getInt: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Relaxed, false);
|
case vmIntrinsics::_getInt: return inline_unsafe_access(!is_store, T_INT, Relaxed, false);
|
||||||
case vmIntrinsics::_getLong: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Relaxed, false);
|
case vmIntrinsics::_getLong: return inline_unsafe_access(!is_store, T_LONG, Relaxed, false);
|
||||||
case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Relaxed, false);
|
case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_store, T_FLOAT, Relaxed, false);
|
||||||
case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Relaxed, false);
|
case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_store, T_DOUBLE, Relaxed, false);
|
||||||
|
|
||||||
case vmIntrinsics::_putObject: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Relaxed, false);
|
case vmIntrinsics::_putObject: return inline_unsafe_access( is_store, T_OBJECT, Relaxed, false);
|
||||||
case vmIntrinsics::_putBoolean: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Relaxed, false);
|
case vmIntrinsics::_putBoolean: return inline_unsafe_access( is_store, T_BOOLEAN, Relaxed, false);
|
||||||
case vmIntrinsics::_putByte: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Relaxed, false);
|
case vmIntrinsics::_putByte: return inline_unsafe_access( is_store, T_BYTE, Relaxed, false);
|
||||||
case vmIntrinsics::_putShort: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Relaxed, false);
|
case vmIntrinsics::_putShort: return inline_unsafe_access( is_store, T_SHORT, Relaxed, false);
|
||||||
case vmIntrinsics::_putChar: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Relaxed, false);
|
case vmIntrinsics::_putChar: return inline_unsafe_access( is_store, T_CHAR, Relaxed, false);
|
||||||
case vmIntrinsics::_putInt: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Relaxed, false);
|
case vmIntrinsics::_putInt: return inline_unsafe_access( is_store, T_INT, Relaxed, false);
|
||||||
case vmIntrinsics::_putLong: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Relaxed, false);
|
case vmIntrinsics::_putLong: return inline_unsafe_access( is_store, T_LONG, Relaxed, false);
|
||||||
case vmIntrinsics::_putFloat: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Relaxed, false);
|
case vmIntrinsics::_putFloat: return inline_unsafe_access( is_store, T_FLOAT, Relaxed, false);
|
||||||
case vmIntrinsics::_putDouble: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Relaxed, false);
|
case vmIntrinsics::_putDouble: return inline_unsafe_access( is_store, T_DOUBLE, Relaxed, false);
|
||||||
|
|
||||||
case vmIntrinsics::_getByte_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_BYTE, Relaxed, false);
|
case vmIntrinsics::_getObjectVolatile: return inline_unsafe_access(!is_store, T_OBJECT, Volatile, false);
|
||||||
case vmIntrinsics::_getShort_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_SHORT, Relaxed, false);
|
case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_store, T_BOOLEAN, Volatile, false);
|
||||||
case vmIntrinsics::_getChar_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_CHAR, Relaxed, false);
|
case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_store, T_BYTE, Volatile, false);
|
||||||
case vmIntrinsics::_getInt_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_INT, Relaxed, false);
|
case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_store, T_SHORT, Volatile, false);
|
||||||
case vmIntrinsics::_getLong_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_LONG, Relaxed, false);
|
case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_store, T_CHAR, Volatile, false);
|
||||||
case vmIntrinsics::_getFloat_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_FLOAT, Relaxed, false);
|
case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_store, T_INT, Volatile, false);
|
||||||
case vmIntrinsics::_getDouble_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_DOUBLE, Relaxed, false);
|
case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_store, T_LONG, Volatile, false);
|
||||||
case vmIntrinsics::_getAddress_raw: return inline_unsafe_access( is_native_ptr, !is_store, T_ADDRESS, Relaxed, false);
|
case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_store, T_FLOAT, Volatile, false);
|
||||||
|
case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_store, T_DOUBLE, Volatile, false);
|
||||||
|
|
||||||
case vmIntrinsics::_putByte_raw: return inline_unsafe_access( is_native_ptr, is_store, T_BYTE, Relaxed, false);
|
case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access( is_store, T_OBJECT, Volatile, false);
|
||||||
case vmIntrinsics::_putShort_raw: return inline_unsafe_access( is_native_ptr, is_store, T_SHORT, Relaxed, false);
|
case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access( is_store, T_BOOLEAN, Volatile, false);
|
||||||
case vmIntrinsics::_putChar_raw: return inline_unsafe_access( is_native_ptr, is_store, T_CHAR, Relaxed, false);
|
case vmIntrinsics::_putByteVolatile: return inline_unsafe_access( is_store, T_BYTE, Volatile, false);
|
||||||
case vmIntrinsics::_putInt_raw: return inline_unsafe_access( is_native_ptr, is_store, T_INT, Relaxed, false);
|
case vmIntrinsics::_putShortVolatile: return inline_unsafe_access( is_store, T_SHORT, Volatile, false);
|
||||||
case vmIntrinsics::_putLong_raw: return inline_unsafe_access( is_native_ptr, is_store, T_LONG, Relaxed, false);
|
case vmIntrinsics::_putCharVolatile: return inline_unsafe_access( is_store, T_CHAR, Volatile, false);
|
||||||
case vmIntrinsics::_putFloat_raw: return inline_unsafe_access( is_native_ptr, is_store, T_FLOAT, Relaxed, false);
|
case vmIntrinsics::_putIntVolatile: return inline_unsafe_access( is_store, T_INT, Volatile, false);
|
||||||
case vmIntrinsics::_putDouble_raw: return inline_unsafe_access( is_native_ptr, is_store, T_DOUBLE, Relaxed, false);
|
case vmIntrinsics::_putLongVolatile: return inline_unsafe_access( is_store, T_LONG, Volatile, false);
|
||||||
case vmIntrinsics::_putAddress_raw: return inline_unsafe_access( is_native_ptr, is_store, T_ADDRESS, Relaxed, false);
|
case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access( is_store, T_FLOAT, Volatile, false);
|
||||||
|
case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access( is_store, T_DOUBLE, Volatile, false);
|
||||||
|
|
||||||
case vmIntrinsics::_getObjectVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Volatile, false);
|
case vmIntrinsics::_getShortUnaligned: return inline_unsafe_access(!is_store, T_SHORT, Relaxed, true);
|
||||||
case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Volatile, false);
|
case vmIntrinsics::_getCharUnaligned: return inline_unsafe_access(!is_store, T_CHAR, Relaxed, true);
|
||||||
case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Volatile, false);
|
case vmIntrinsics::_getIntUnaligned: return inline_unsafe_access(!is_store, T_INT, Relaxed, true);
|
||||||
case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Volatile, false);
|
case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_store, T_LONG, Relaxed, true);
|
||||||
case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Volatile, false);
|
|
||||||
case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Volatile, false);
|
|
||||||
case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Volatile, false);
|
|
||||||
case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Volatile, false);
|
|
||||||
case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Volatile, false);
|
|
||||||
|
|
||||||
case vmIntrinsics::_putObjectVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Volatile, false);
|
case vmIntrinsics::_putShortUnaligned: return inline_unsafe_access( is_store, T_SHORT, Relaxed, true);
|
||||||
case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Volatile, false);
|
case vmIntrinsics::_putCharUnaligned: return inline_unsafe_access( is_store, T_CHAR, Relaxed, true);
|
||||||
case vmIntrinsics::_putByteVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Volatile, false);
|
case vmIntrinsics::_putIntUnaligned: return inline_unsafe_access( is_store, T_INT, Relaxed, true);
|
||||||
case vmIntrinsics::_putShortVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Volatile, false);
|
case vmIntrinsics::_putLongUnaligned: return inline_unsafe_access( is_store, T_LONG, Relaxed, true);
|
||||||
case vmIntrinsics::_putCharVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Volatile, false);
|
|
||||||
case vmIntrinsics::_putIntVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Volatile, false);
|
|
||||||
case vmIntrinsics::_putLongVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Volatile, false);
|
|
||||||
case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Volatile, false);
|
|
||||||
case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Volatile, false);
|
|
||||||
|
|
||||||
case vmIntrinsics::_getShortUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Relaxed, true);
|
case vmIntrinsics::_getObjectAcquire: return inline_unsafe_access(!is_store, T_OBJECT, Acquire, false);
|
||||||
case vmIntrinsics::_getCharUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Relaxed, true);
|
case vmIntrinsics::_getBooleanAcquire: return inline_unsafe_access(!is_store, T_BOOLEAN, Acquire, false);
|
||||||
case vmIntrinsics::_getIntUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Relaxed, true);
|
case vmIntrinsics::_getByteAcquire: return inline_unsafe_access(!is_store, T_BYTE, Acquire, false);
|
||||||
case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Relaxed, true);
|
case vmIntrinsics::_getShortAcquire: return inline_unsafe_access(!is_store, T_SHORT, Acquire, false);
|
||||||
|
case vmIntrinsics::_getCharAcquire: return inline_unsafe_access(!is_store, T_CHAR, Acquire, false);
|
||||||
|
case vmIntrinsics::_getIntAcquire: return inline_unsafe_access(!is_store, T_INT, Acquire, false);
|
||||||
|
case vmIntrinsics::_getLongAcquire: return inline_unsafe_access(!is_store, T_LONG, Acquire, false);
|
||||||
|
case vmIntrinsics::_getFloatAcquire: return inline_unsafe_access(!is_store, T_FLOAT, Acquire, false);
|
||||||
|
case vmIntrinsics::_getDoubleAcquire: return inline_unsafe_access(!is_store, T_DOUBLE, Acquire, false);
|
||||||
|
|
||||||
case vmIntrinsics::_putShortUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Relaxed, true);
|
case vmIntrinsics::_putObjectRelease: return inline_unsafe_access( is_store, T_OBJECT, Release, false);
|
||||||
case vmIntrinsics::_putCharUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Relaxed, true);
|
case vmIntrinsics::_putBooleanRelease: return inline_unsafe_access( is_store, T_BOOLEAN, Release, false);
|
||||||
case vmIntrinsics::_putIntUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Relaxed, true);
|
case vmIntrinsics::_putByteRelease: return inline_unsafe_access( is_store, T_BYTE, Release, false);
|
||||||
case vmIntrinsics::_putLongUnaligned: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Relaxed, true);
|
case vmIntrinsics::_putShortRelease: return inline_unsafe_access( is_store, T_SHORT, Release, false);
|
||||||
|
case vmIntrinsics::_putCharRelease: return inline_unsafe_access( is_store, T_CHAR, Release, false);
|
||||||
|
case vmIntrinsics::_putIntRelease: return inline_unsafe_access( is_store, T_INT, Release, false);
|
||||||
|
case vmIntrinsics::_putLongRelease: return inline_unsafe_access( is_store, T_LONG, Release, false);
|
||||||
|
case vmIntrinsics::_putFloatRelease: return inline_unsafe_access( is_store, T_FLOAT, Release, false);
|
||||||
|
case vmIntrinsics::_putDoubleRelease: return inline_unsafe_access( is_store, T_DOUBLE, Release, false);
|
||||||
|
|
||||||
case vmIntrinsics::_getObjectAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Acquire, false);
|
case vmIntrinsics::_getObjectOpaque: return inline_unsafe_access(!is_store, T_OBJECT, Opaque, false);
|
||||||
case vmIntrinsics::_getBooleanAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Acquire, false);
|
case vmIntrinsics::_getBooleanOpaque: return inline_unsafe_access(!is_store, T_BOOLEAN, Opaque, false);
|
||||||
case vmIntrinsics::_getByteAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Acquire, false);
|
case vmIntrinsics::_getByteOpaque: return inline_unsafe_access(!is_store, T_BYTE, Opaque, false);
|
||||||
case vmIntrinsics::_getShortAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Acquire, false);
|
case vmIntrinsics::_getShortOpaque: return inline_unsafe_access(!is_store, T_SHORT, Opaque, false);
|
||||||
case vmIntrinsics::_getCharAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Acquire, false);
|
case vmIntrinsics::_getCharOpaque: return inline_unsafe_access(!is_store, T_CHAR, Opaque, false);
|
||||||
case vmIntrinsics::_getIntAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Acquire, false);
|
case vmIntrinsics::_getIntOpaque: return inline_unsafe_access(!is_store, T_INT, Opaque, false);
|
||||||
case vmIntrinsics::_getLongAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Acquire, false);
|
case vmIntrinsics::_getLongOpaque: return inline_unsafe_access(!is_store, T_LONG, Opaque, false);
|
||||||
case vmIntrinsics::_getFloatAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Acquire, false);
|
case vmIntrinsics::_getFloatOpaque: return inline_unsafe_access(!is_store, T_FLOAT, Opaque, false);
|
||||||
case vmIntrinsics::_getDoubleAcquire: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Acquire, false);
|
case vmIntrinsics::_getDoubleOpaque: return inline_unsafe_access(!is_store, T_DOUBLE, Opaque, false);
|
||||||
|
|
||||||
case vmIntrinsics::_putObjectRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Release, false);
|
case vmIntrinsics::_putObjectOpaque: return inline_unsafe_access( is_store, T_OBJECT, Opaque, false);
|
||||||
case vmIntrinsics::_putBooleanRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Release, false);
|
case vmIntrinsics::_putBooleanOpaque: return inline_unsafe_access( is_store, T_BOOLEAN, Opaque, false);
|
||||||
case vmIntrinsics::_putByteRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Release, false);
|
case vmIntrinsics::_putByteOpaque: return inline_unsafe_access( is_store, T_BYTE, Opaque, false);
|
||||||
case vmIntrinsics::_putShortRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Release, false);
|
case vmIntrinsics::_putShortOpaque: return inline_unsafe_access( is_store, T_SHORT, Opaque, false);
|
||||||
case vmIntrinsics::_putCharRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Release, false);
|
case vmIntrinsics::_putCharOpaque: return inline_unsafe_access( is_store, T_CHAR, Opaque, false);
|
||||||
case vmIntrinsics::_putIntRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Release, false);
|
case vmIntrinsics::_putIntOpaque: return inline_unsafe_access( is_store, T_INT, Opaque, false);
|
||||||
case vmIntrinsics::_putLongRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Release, false);
|
case vmIntrinsics::_putLongOpaque: return inline_unsafe_access( is_store, T_LONG, Opaque, false);
|
||||||
case vmIntrinsics::_putFloatRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Release, false);
|
case vmIntrinsics::_putFloatOpaque: return inline_unsafe_access( is_store, T_FLOAT, Opaque, false);
|
||||||
case vmIntrinsics::_putDoubleRelease: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Release, false);
|
case vmIntrinsics::_putDoubleOpaque: return inline_unsafe_access( is_store, T_DOUBLE, Opaque, false);
|
||||||
|
|
||||||
case vmIntrinsics::_getObjectOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, Opaque, false);
|
|
||||||
case vmIntrinsics::_getBooleanOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, Opaque, false);
|
|
||||||
case vmIntrinsics::_getByteOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, Opaque, false);
|
|
||||||
case vmIntrinsics::_getShortOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, Opaque, false);
|
|
||||||
case vmIntrinsics::_getCharOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_CHAR, Opaque, false);
|
|
||||||
case vmIntrinsics::_getIntOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_INT, Opaque, false);
|
|
||||||
case vmIntrinsics::_getLongOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_LONG, Opaque, false);
|
|
||||||
case vmIntrinsics::_getFloatOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_FLOAT, Opaque, false);
|
|
||||||
case vmIntrinsics::_getDoubleOpaque: return inline_unsafe_access(!is_native_ptr, !is_store, T_DOUBLE, Opaque, false);
|
|
||||||
|
|
||||||
case vmIntrinsics::_putObjectOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_OBJECT, Opaque, false);
|
|
||||||
case vmIntrinsics::_putBooleanOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_BOOLEAN, Opaque, false);
|
|
||||||
case vmIntrinsics::_putByteOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_BYTE, Opaque, false);
|
|
||||||
case vmIntrinsics::_putShortOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_SHORT, Opaque, false);
|
|
||||||
case vmIntrinsics::_putCharOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_CHAR, Opaque, false);
|
|
||||||
case vmIntrinsics::_putIntOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_INT, Opaque, false);
|
|
||||||
case vmIntrinsics::_putLongOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_LONG, Opaque, false);
|
|
||||||
case vmIntrinsics::_putFloatOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_FLOAT, Opaque, false);
|
|
||||||
case vmIntrinsics::_putDoubleOpaque: return inline_unsafe_access(!is_native_ptr, is_store, T_DOUBLE, Opaque, false);
|
|
||||||
|
|
||||||
case vmIntrinsics::_compareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap, Volatile);
|
case vmIntrinsics::_compareAndSwapObject: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap, Volatile);
|
||||||
case vmIntrinsics::_compareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmp_swap, Volatile);
|
case vmIntrinsics::_compareAndSwapInt: return inline_unsafe_load_store(T_INT, LS_cmp_swap, Volatile);
|
||||||
|
@ -2199,8 +2180,6 @@ bool LibraryCallKit::inline_number_methods(vmIntrinsics::ID id) {
|
||||||
|
|
||||||
//----------------------------inline_unsafe_access----------------------------
|
//----------------------------inline_unsafe_access----------------------------
|
||||||
|
|
||||||
const static BasicType T_ADDRESS_HOLDER = T_LONG;
|
|
||||||
|
|
||||||
// Helper that guards and inserts a pre-barrier.
|
// Helper that guards and inserts a pre-barrier.
|
||||||
void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset,
|
void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset,
|
||||||
Node* pre_val, bool need_mem_bar) {
|
Node* pre_val, bool need_mem_bar) {
|
||||||
|
@ -2301,13 +2280,12 @@ void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type, bool is_native_ptr) {
|
const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type) {
|
||||||
// Attempt to infer a sharper value type from the offset and base type.
|
// Attempt to infer a sharper value type from the offset and base type.
|
||||||
ciKlass* sharpened_klass = NULL;
|
ciKlass* sharpened_klass = NULL;
|
||||||
|
|
||||||
// See if it is an instance field, with an object type.
|
// See if it is an instance field, with an object type.
|
||||||
if (alias_type->field() != NULL) {
|
if (alias_type->field() != NULL) {
|
||||||
assert(!is_native_ptr, "native pointer op cannot use a java address");
|
|
||||||
if (alias_type->field()->type()->is_klass()) {
|
if (alias_type->field()->type()->is_klass()) {
|
||||||
sharpened_klass = alias_type->field()->type()->as_klass();
|
sharpened_klass = alias_type->field()->type()->as_klass();
|
||||||
}
|
}
|
||||||
|
@ -2340,7 +2318,7 @@ const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_store, const BasicType type, const AccessKind kind, const bool unaligned) {
|
bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, const AccessKind kind, const bool unaligned) {
|
||||||
if (callee()->is_static()) return false; // caller must have the capability!
|
if (callee()->is_static()) return false; // caller must have the capability!
|
||||||
guarantee(!is_store || kind != Acquire, "Acquire accesses can be produced only for loads");
|
guarantee(!is_store || kind != Acquire, "Acquire accesses can be produced only for loads");
|
||||||
guarantee( is_store || kind != Release, "Release accesses can be produced only for stores");
|
guarantee( is_store || kind != Release, "Release accesses can be produced only for stores");
|
||||||
|
@ -2355,31 +2333,17 @@ bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_stor
|
||||||
if (!is_store) {
|
if (!is_store) {
|
||||||
// Object getObject(Object base, int/long offset), etc.
|
// Object getObject(Object base, int/long offset), etc.
|
||||||
BasicType rtype = sig->return_type()->basic_type();
|
BasicType rtype = sig->return_type()->basic_type();
|
||||||
if (rtype == T_ADDRESS_HOLDER && callee()->name() == ciSymbol::getAddress_name())
|
|
||||||
rtype = T_ADDRESS; // it is really a C void*
|
|
||||||
assert(rtype == type, "getter must return the expected value");
|
assert(rtype == type, "getter must return the expected value");
|
||||||
if (!is_native_ptr) {
|
assert(sig->count() == 2, "oop getter has 2 arguments");
|
||||||
assert(sig->count() == 2, "oop getter has 2 arguments");
|
assert(sig->type_at(0)->basic_type() == T_OBJECT, "getter base is object");
|
||||||
assert(sig->type_at(0)->basic_type() == T_OBJECT, "getter base is object");
|
assert(sig->type_at(1)->basic_type() == T_LONG, "getter offset is correct");
|
||||||
assert(sig->type_at(1)->basic_type() == T_LONG, "getter offset is correct");
|
|
||||||
} else {
|
|
||||||
assert(sig->count() == 1, "native getter has 1 argument");
|
|
||||||
assert(sig->type_at(0)->basic_type() == T_LONG, "getter base is long");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// void putObject(Object base, int/long offset, Object x), etc.
|
// void putObject(Object base, int/long offset, Object x), etc.
|
||||||
assert(sig->return_type()->basic_type() == T_VOID, "putter must not return a value");
|
assert(sig->return_type()->basic_type() == T_VOID, "putter must not return a value");
|
||||||
if (!is_native_ptr) {
|
assert(sig->count() == 3, "oop putter has 3 arguments");
|
||||||
assert(sig->count() == 3, "oop putter has 3 arguments");
|
assert(sig->type_at(0)->basic_type() == T_OBJECT, "putter base is object");
|
||||||
assert(sig->type_at(0)->basic_type() == T_OBJECT, "putter base is object");
|
assert(sig->type_at(1)->basic_type() == T_LONG, "putter offset is correct");
|
||||||
assert(sig->type_at(1)->basic_type() == T_LONG, "putter offset is correct");
|
|
||||||
} else {
|
|
||||||
assert(sig->count() == 2, "native putter has 2 arguments");
|
|
||||||
assert(sig->type_at(0)->basic_type() == T_LONG, "putter base is long");
|
|
||||||
}
|
|
||||||
BasicType vtype = sig->type_at(sig->count()-1)->basic_type();
|
BasicType vtype = sig->type_at(sig->count()-1)->basic_type();
|
||||||
if (vtype == T_ADDRESS_HOLDER && callee()->name() == ciSymbol::putAddress_name())
|
|
||||||
vtype = T_ADDRESS; // it is really a C void*
|
|
||||||
assert(vtype == type, "putter must accept the expected value");
|
assert(vtype == type, "putter must accept the expected value");
|
||||||
}
|
}
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
@ -2396,27 +2360,22 @@ bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_stor
|
||||||
Node* offset = top();
|
Node* offset = top();
|
||||||
Node* val;
|
Node* val;
|
||||||
|
|
||||||
if (!is_native_ptr) {
|
// The base is either a Java object or a value produced by Unsafe.staticFieldBase
|
||||||
// The base is either a Java object or a value produced by Unsafe.staticFieldBase
|
Node* base = argument(1); // type: oop
|
||||||
Node* base = argument(1); // type: oop
|
// The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset
|
||||||
// The offset is a value produced by Unsafe.staticFieldOffset or Unsafe.objectFieldOffset
|
offset = argument(2); // type: long
|
||||||
offset = argument(2); // type: long
|
// We currently rely on the cookies produced by Unsafe.xxxFieldOffset
|
||||||
// We currently rely on the cookies produced by Unsafe.xxxFieldOffset
|
// to be plain byte offsets, which are also the same as those accepted
|
||||||
// to be plain byte offsets, which are also the same as those accepted
|
// by oopDesc::field_base.
|
||||||
// by oopDesc::field_base.
|
assert(Unsafe_field_offset_to_byte_offset(11) == 11,
|
||||||
assert(Unsafe_field_offset_to_byte_offset(11) == 11,
|
"fieldOffset must be byte-scaled");
|
||||||
"fieldOffset must be byte-scaled");
|
// 32-bit machines ignore the high half!
|
||||||
// 32-bit machines ignore the high half!
|
offset = ConvL2X(offset);
|
||||||
offset = ConvL2X(offset);
|
adr = make_unsafe_address(base, offset);
|
||||||
adr = make_unsafe_address(base, offset);
|
if (_gvn.type(base)->isa_ptr() != TypePtr::NULL_PTR) {
|
||||||
heap_base_oop = base;
|
heap_base_oop = base;
|
||||||
val = is_store ? argument(4) : NULL;
|
|
||||||
} else {
|
|
||||||
Node* ptr = argument(1); // type: long
|
|
||||||
ptr = ConvL2X(ptr); // adjust Java long to machine word
|
|
||||||
adr = make_unsafe_address(NULL, ptr);
|
|
||||||
val = is_store ? argument(3) : NULL;
|
|
||||||
}
|
}
|
||||||
|
val = is_store ? argument(4) : NULL;
|
||||||
|
|
||||||
const TypePtr *adr_type = _gvn.type(adr)->isa_ptr();
|
const TypePtr *adr_type = _gvn.type(adr)->isa_ptr();
|
||||||
|
|
||||||
|
@ -2498,11 +2457,11 @@ bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_stor
|
||||||
// SATB log buffer using the pre-barrier mechanism.
|
// SATB log buffer using the pre-barrier mechanism.
|
||||||
// Also we need to add memory barrier to prevent commoning reads
|
// Also we need to add memory barrier to prevent commoning reads
|
||||||
// from this field across safepoint since GC can change its value.
|
// from this field across safepoint since GC can change its value.
|
||||||
bool need_read_barrier = !is_native_ptr && !is_store &&
|
bool need_read_barrier = !is_store &&
|
||||||
offset != top() && heap_base_oop != top();
|
offset != top() && heap_base_oop != top();
|
||||||
|
|
||||||
if (!is_store && type == T_OBJECT) {
|
if (!is_store && type == T_OBJECT) {
|
||||||
const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type, is_native_ptr);
|
const TypeOopPtr* tjp = sharpen_unsafe_type(alias_type, adr_type);
|
||||||
if (tjp != NULL) {
|
if (tjp != NULL) {
|
||||||
value_type = tjp;
|
value_type = tjp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,11 +303,10 @@ void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {
|
||||||
if (method->is_running_emcp() &&
|
if (method->is_running_emcp() &&
|
||||||
method->name() == m_name &&
|
method->name() == m_name &&
|
||||||
method->signature() == m_signature) {
|
method->signature() == m_signature) {
|
||||||
RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)",
|
ResourceMark rm;
|
||||||
meth_act == &Method::set_breakpoint ? "sett" : "clear",
|
log_debug(redefine, class, breakpoint)
|
||||||
method->name()->as_C_string(),
|
("%sing breakpoint in %s(%s)", meth_act == &Method::set_breakpoint ? "sett" : "clear",
|
||||||
method->signature()->as_C_string()));
|
method->name()->as_C_string(), method->signature()->as_C_string());
|
||||||
|
|
||||||
(method->*meth_act)(_bci);
|
(method->*meth_act)(_bci);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -30,7 +30,6 @@
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "oops/objArrayKlass.hpp"
|
#include "oops/objArrayKlass.hpp"
|
||||||
#include "oops/objArrayOop.hpp"
|
#include "oops/objArrayOop.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/vm_operations.hpp"
|
#include "runtime/vm_operations.hpp"
|
||||||
|
|
||||||
// Introduction:
|
// Introduction:
|
||||||
|
|
|
@ -1,138 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* 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_PRIMS_JVMTIREDEFINECLASSESTRACE_HPP
|
|
||||||
#define SHARE_VM_PRIMS_JVMTIREDEFINECLASSESTRACE_HPP
|
|
||||||
|
|
||||||
// RedefineClasses tracing support via the TraceRedefineClasses
|
|
||||||
// option. A bit is assigned to each group of trace messages.
|
|
||||||
// Groups of messages are individually selectable. We have to use
|
|
||||||
// decimal values on the command line since the command option
|
|
||||||
// parsing logic doesn't like non-decimal numerics. The HEX values
|
|
||||||
// are used in the actual RC_TRACE() calls for sanity. To achieve
|
|
||||||
// the old cumulative behavior, pick the level after the one in
|
|
||||||
// which you are interested and subtract one, e.g., 33554431 will
|
|
||||||
// print every tracing message.
|
|
||||||
//
|
|
||||||
// 0x00000000 | 0 - default; no tracing messages
|
|
||||||
// 0x00000001 | 1 - name each target class before loading, after
|
|
||||||
// loading and after redefinition is completed
|
|
||||||
// 0x00000002 | 2 - print info if parsing, linking or
|
|
||||||
// verification throws an exception
|
|
||||||
// 0x00000004 | 4 - print timer info for the VM operation
|
|
||||||
// 0x00000008 | 8 - print subclass counter updates
|
|
||||||
// 0x00000010 | 16 - unused
|
|
||||||
// 0x00000020 | 32 - unused
|
|
||||||
// 0x00000040 | 64 - unused
|
|
||||||
// 0x00000080 | 128 - unused
|
|
||||||
// 0x00000100 | 256 - previous class weak reference addition
|
|
||||||
// 0x00000200 | 512 - previous class weak reference mgmt during
|
|
||||||
// class unloading checks (GC)
|
|
||||||
// 0x00000400 | 1024 - previous class weak reference mgmt during
|
|
||||||
// add previous ops (GC)
|
|
||||||
// 0x00000800 | 2048 - previous class breakpoint mgmt
|
|
||||||
// 0x00001000 | 4096 - detect calls to obsolete methods
|
|
||||||
// 0x00002000 | 8192 - fail a guarantee() in addition to detection
|
|
||||||
// 0x00004000 | 16384 - detect old/obsolete methods in metadata
|
|
||||||
// 0x00008000 | 32768 - old/new method matching/add/delete
|
|
||||||
// 0x00010000 | 65536 - impl details: CP size info
|
|
||||||
// 0x00020000 | 131072 - impl details: CP merge pass info
|
|
||||||
// 0x00040000 | 262144 - impl details: CP index maps
|
|
||||||
// 0x00080000 | 524288 - impl details: modified CP index values
|
|
||||||
// 0x00100000 | 1048576 - impl details: vtable updates
|
|
||||||
// 0x00200000 | 2097152 - impl details: itable updates
|
|
||||||
// 0x00400000 | 4194304 - impl details: constant pool cache updates
|
|
||||||
// 0x00800000 | 8388608 - impl details: methodComparator info
|
|
||||||
// 0x01000000 | 16777216 - impl details: nmethod evolution info
|
|
||||||
// 0x02000000 | 33554432 - impl details: annotation updates
|
|
||||||
// 0x04000000 | 67108864 - impl details: StackMapTable updates
|
|
||||||
// 0x08000000 | 134217728 - impl details: OopMapCache updates
|
|
||||||
// 0x10000000 | 268435456 - unused
|
|
||||||
// 0x20000000 | 536870912 - unused
|
|
||||||
// 0x40000000 | 1073741824 - unused
|
|
||||||
// 0x80000000 | 2147483648 - unused
|
|
||||||
|
|
||||||
// Macro for checking if TraceRedefineClasses has a specific bit
|
|
||||||
// enabled. Returns true if the bit specified by level is set.
|
|
||||||
#define RC_TRACE_ENABLED(level) ((TraceRedefineClasses & level) != 0)
|
|
||||||
|
|
||||||
// Macro for checking if TraceRedefineClasses has one or more bits
|
|
||||||
// set in a range of bit values. Returns true if one or more bits
|
|
||||||
// is set in the range from low..high inclusive. Assumes that low
|
|
||||||
// and high are single bit values.
|
|
||||||
//
|
|
||||||
// ((high << 1) - 1)
|
|
||||||
// Yields a mask that removes bits greater than the high bit value.
|
|
||||||
// This algorithm doesn't work with highest bit.
|
|
||||||
// ~(low - 1)
|
|
||||||
// Yields a mask that removes bits lower than the low bit value.
|
|
||||||
#define RC_TRACE_IN_RANGE(low, high) \
|
|
||||||
(((TraceRedefineClasses & ((high << 1) - 1)) & ~(low - 1)) != 0)
|
|
||||||
|
|
||||||
// Note: The ResourceMark is to cleanup resource allocated args.
|
|
||||||
// The "do {...} while (0)" is so we can use semi-colon at end of RC_TRACE().
|
|
||||||
#define RC_TRACE(level, args) do { \
|
|
||||||
if (RC_TRACE_ENABLED(level)) { \
|
|
||||||
ResourceMark rm; \
|
|
||||||
tty->print("RedefineClasses-0x%x: ", level); \
|
|
||||||
tty->print_cr args; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define RC_TRACE_NO_CR(level, args) do { \
|
|
||||||
if (RC_TRACE_ENABLED(level)) { \
|
|
||||||
ResourceMark rm; \
|
|
||||||
tty->print("RedefineClasses-0x%x: ", level); \
|
|
||||||
tty->print args; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define RC_TRACE_WITH_THREAD(level, thread, args) do { \
|
|
||||||
if (RC_TRACE_ENABLED(level)) { \
|
|
||||||
ResourceMark rm(thread); \
|
|
||||||
tty->print("RedefineClasses-0x%x: ", level); \
|
|
||||||
tty->print_cr args; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define RC_TRACE_MESG(args) do { \
|
|
||||||
ResourceMark rm; \
|
|
||||||
tty->print("RedefineClasses: "); \
|
|
||||||
tty->print_cr args; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
// Timer support macros. Only do timer operations if timer tracing is enabled.
|
|
||||||
// The "do {...} while (0)" is so we can use semi-colon at end of the macro.
|
|
||||||
#define RC_TIMER_START(t) do { \
|
|
||||||
if (RC_TRACE_ENABLED(0x00000004)) { \
|
|
||||||
t.start(); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
#define RC_TIMER_STOP(t) do { \
|
|
||||||
if (RC_TRACE_ENABLED(0x00000004)) { \
|
|
||||||
t.stop(); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSESTRACE_HPP
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "oops/symbol.hpp"
|
#include "oops/symbol.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "prims/methodComparator.hpp"
|
#include "prims/methodComparator.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "utilities/globalDefinitions.hpp"
|
#include "utilities/globalDefinitions.hpp"
|
||||||
|
@ -39,10 +38,12 @@ bool MethodComparator::methods_EMCP(Method* old_method, Method* new_method) {
|
||||||
if (old_method->code_size() != new_method->code_size())
|
if (old_method->code_size() != new_method->code_size())
|
||||||
return false;
|
return false;
|
||||||
if (check_stack_and_locals_size(old_method, new_method) != 0) {
|
if (check_stack_and_locals_size(old_method, new_method) != 0) {
|
||||||
// RC_TRACE macro has an embedded ResourceMark
|
if (log_is_enabled(Debug, redefine, class, methodcomparator)) {
|
||||||
RC_TRACE(0x00800000, ("Methods %s non-comparable with diagnosis %d",
|
ResourceMark rm;
|
||||||
old_method->name()->as_C_string(),
|
log_debug(redefine, class, methodcomparator)
|
||||||
check_stack_and_locals_size(old_method, new_method)));
|
("Methods %s non-comparable with diagnosis %d",
|
||||||
|
old_method->name()->as_C_string(), check_stack_and_locals_size(old_method, new_method));
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include "oops/objArrayOop.inline.hpp"
|
#include "oops/objArrayOop.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/methodHandles.hpp"
|
#include "prims/methodHandles.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "runtime/compilationPolicy.hpp"
|
#include "runtime/compilationPolicy.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
#include "runtime/timerTrace.hpp"
|
#include "runtime/timerTrace.hpp"
|
||||||
|
@ -1084,17 +1083,15 @@ void MemberNameTable::adjust_method_entries(InstanceKlass* holder, bool * trace_
|
||||||
|
|
||||||
java_lang_invoke_MemberName::set_vmtarget(mem_name, new_method);
|
java_lang_invoke_MemberName::set_vmtarget(mem_name, new_method);
|
||||||
|
|
||||||
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
|
if (log_is_enabled(Info, redefine, class, update)) {
|
||||||
|
ResourceMark rm;
|
||||||
if (!(*trace_name_printed)) {
|
if (!(*trace_name_printed)) {
|
||||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
|
||||||
RC_TRACE_MESG(("adjust: name=%s",
|
|
||||||
old_method->method_holder()->external_name()));
|
|
||||||
*trace_name_printed = true;
|
*trace_name_printed = true;
|
||||||
}
|
}
|
||||||
// RC_TRACE macro has an embedded ResourceMark
|
log_debug(redefine, class, update, constantpool)
|
||||||
RC_TRACE(0x00400000, ("MemberName method update: %s(%s)",
|
("MemberName method update: %s(%s)",
|
||||||
new_method->name()->as_C_string(),
|
new_method->name()->as_C_string(), new_method->signature()->as_C_string());
|
||||||
new_method->signature()->as_C_string()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -37,44 +37,44 @@
|
||||||
#include "utilities/globalDefinitions.hpp"
|
#include "utilities/globalDefinitions.hpp"
|
||||||
|
|
||||||
// setup and cleanup actions
|
// setup and cleanup actions
|
||||||
void StackWalkAnchor::setup_magic_on_entry(objArrayHandle frames_array) {
|
void JavaFrameStream::setup_magic_on_entry(objArrayHandle frames_array) {
|
||||||
frames_array->obj_at_put(magic_pos, _thread->threadObj());
|
frames_array->obj_at_put(magic_pos, _thread->threadObj());
|
||||||
_anchor = address_value();
|
_anchor = address_value();
|
||||||
assert(check_magic(frames_array), "invalid magic");
|
assert(check_magic(frames_array), "invalid magic");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StackWalkAnchor::check_magic(objArrayHandle frames_array) {
|
bool JavaFrameStream::check_magic(objArrayHandle frames_array) {
|
||||||
oop m1 = frames_array->obj_at(magic_pos);
|
oop m1 = frames_array->obj_at(magic_pos);
|
||||||
jlong m2 = _anchor;
|
jlong m2 = _anchor;
|
||||||
if (m1 == _thread->threadObj() && m2 == address_value()) return true;
|
if (m1 == _thread->threadObj() && m2 == address_value()) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle frames_array) {
|
bool JavaFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) {
|
||||||
bool ok = check_magic(frames_array);
|
bool ok = check_magic(frames_array);
|
||||||
frames_array->obj_at_put(magic_pos, NULL);
|
frames_array->obj_at_put(magic_pos, NULL);
|
||||||
_anchor = 0L;
|
_anchor = 0L;
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns StackWalkAnchor for the current stack being traversed.
|
// Returns JavaFrameStream for the current stack being traversed.
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// thread Current Java thread.
|
// thread Current Java thread.
|
||||||
// magic Magic value used for each stack walking
|
// magic Magic value used for each stack walking
|
||||||
// frames_array User-supplied buffers. The 0th element is reserved
|
// frames_array User-supplied buffers. The 0th element is reserved
|
||||||
// to this StackWalkAnchor to use
|
// to this JavaFrameStream to use
|
||||||
//
|
//
|
||||||
StackWalkAnchor* StackWalkAnchor::from_current(JavaThread* thread, jlong magic,
|
JavaFrameStream* JavaFrameStream::from_current(JavaThread* thread, jlong magic,
|
||||||
objArrayHandle frames_array)
|
objArrayHandle frames_array)
|
||||||
{
|
{
|
||||||
assert(thread != NULL && thread->is_Java_thread(), "");
|
assert(thread != NULL && thread->is_Java_thread(), "");
|
||||||
oop m1 = frames_array->obj_at(magic_pos);
|
oop m1 = frames_array->obj_at(magic_pos);
|
||||||
if (m1 != thread->threadObj()) return NULL;
|
if (m1 != thread->threadObj()) return NULL;
|
||||||
if (magic == 0L) return NULL;
|
if (magic == 0L) return NULL;
|
||||||
StackWalkAnchor* anchor = (StackWalkAnchor*) (intptr_t) magic;
|
JavaFrameStream* stream = (JavaFrameStream*) (intptr_t) magic;
|
||||||
if (!anchor->is_valid_in(thread, frames_array)) return NULL;
|
if (!stream->is_valid_in(thread, frames_array)) return NULL;
|
||||||
return anchor;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpacks one or more frames into user-supplied buffers.
|
// Unpacks one or more frames into user-supplied buffers.
|
||||||
|
@ -84,19 +84,19 @@ StackWalkAnchor* StackWalkAnchor::from_current(JavaThread* thread, jlong magic,
|
||||||
// In other words, do not leave any stale data in the vfst.
|
// In other words, do not leave any stale data in the vfst.
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// mode Restrict which frames to be decoded.
|
// mode Restrict which frames to be decoded.
|
||||||
// vfst vFrameStream.
|
// JavaFrameStream stream of javaVFrames
|
||||||
// max_nframes Maximum number of frames to be filled.
|
// max_nframes Maximum number of frames to be filled.
|
||||||
// start_index Start index to the user-supplied buffers.
|
// start_index Start index to the user-supplied buffers.
|
||||||
// frames_array Buffer to store Class or StackFrame in, starting at start_index.
|
// frames_array Buffer to store Class or StackFrame in, starting at start_index.
|
||||||
// frames array is a Class<?>[] array when only getting caller
|
// frames array is a Class<?>[] array when only getting caller
|
||||||
// reference, and a StackFrameInfo[] array (or derivative)
|
// reference, and a StackFrameInfo[] array (or derivative)
|
||||||
// otherwise. It should never be null.
|
// otherwise. It should never be null.
|
||||||
// end_index End index to the user-supplied buffers with unpacked frames.
|
// end_index End index to the user-supplied buffers with unpacked frames.
|
||||||
//
|
//
|
||||||
// Returns the number of frames whose information was transferred into the buffers.
|
// Returns the number of frames whose information was transferred into the buffers.
|
||||||
//
|
//
|
||||||
int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst,
|
int StackWalk::fill_in_frames(jlong mode, JavaFrameStream& stream,
|
||||||
int max_nframes, int start_index,
|
int max_nframes, int start_index,
|
||||||
objArrayHandle frames_array,
|
objArrayHandle frames_array,
|
||||||
int& end_index, TRAPS) {
|
int& end_index, TRAPS) {
|
||||||
|
@ -108,9 +108,9 @@ int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst,
|
||||||
assert(start_index + max_nframes <= frames_array->length(), "oob");
|
assert(start_index + max_nframes <= frames_array->length(), "oob");
|
||||||
|
|
||||||
int frames_decoded = 0;
|
int frames_decoded = 0;
|
||||||
for (; !vfst.at_end(); vfst.next()) {
|
for (; !stream.at_end(); stream.next()) {
|
||||||
Method* method = vfst.method();
|
Method* method = stream.method();
|
||||||
int bci = vfst.bci();
|
int bci = stream.bci();
|
||||||
|
|
||||||
if (method == NULL) continue;
|
if (method == NULL) continue;
|
||||||
if (!ShowHiddenFrames && StackWalk::skip_hidden_frames(mode)) {
|
if (!ShowHiddenFrames && StackWalk::skip_hidden_frames(mode)) {
|
||||||
|
@ -133,7 +133,7 @@ int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst,
|
||||||
if (live_frame_info(mode)) {
|
if (live_frame_info(mode)) {
|
||||||
assert (use_frames_array(mode), "Bad mode for get live frame");
|
assert (use_frames_array(mode), "Bad mode for get live frame");
|
||||||
Handle stackFrame(frames_array->obj_at(index));
|
Handle stackFrame(frames_array->obj_at(index));
|
||||||
fill_live_stackframe(stackFrame, method, bci, vfst.java_frame(), CHECK_0);
|
fill_live_stackframe(stackFrame, method, bci, stream.java_frame(), CHECK_0);
|
||||||
} else if (need_method_info(mode)) {
|
} else if (need_method_info(mode)) {
|
||||||
assert (use_frames_array(mode), "Bad mode for get stack frame");
|
assert (use_frames_array(mode), "Bad mode for get stack frame");
|
||||||
Handle stackFrame(frames_array->obj_at(index));
|
Handle stackFrame(frames_array->obj_at(index));
|
||||||
|
@ -294,6 +294,7 @@ oop StackWalk::walk(Handle stackStream, jlong mode,
|
||||||
int skip_frames, int frame_count, int start_index,
|
int skip_frames, int frame_count, int start_index,
|
||||||
objArrayHandle frames_array,
|
objArrayHandle frames_array,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
|
ResourceMark rm(THREAD);
|
||||||
JavaThread* jt = (JavaThread*)THREAD;
|
JavaThread* jt = (JavaThread*)THREAD;
|
||||||
if (TraceStackWalk) {
|
if (TraceStackWalk) {
|
||||||
tty->print_cr("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d",
|
tty->print_cr("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d",
|
||||||
|
@ -309,41 +310,39 @@ oop StackWalk::walk(Handle stackStream, jlong mode,
|
||||||
|
|
||||||
methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
|
methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
|
||||||
|
|
||||||
// Open up a traversable stream onto my stack.
|
// Setup traversal onto my stack.
|
||||||
// This stream will be made available by *reference* to the inner Java call.
|
RegisterMap regMap(jt, true);
|
||||||
StackWalkAnchor anchor(jt);
|
JavaFrameStream stream(jt, ®Map);
|
||||||
vframeStream& vfst = anchor.vframe_stream();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
while (!vfst.at_end()) {
|
while (!stream.at_end()) {
|
||||||
InstanceKlass* ik = vfst.method()->method_holder();
|
InstanceKlass* ik = stream.method()->method_holder();
|
||||||
if (ik != stackWalker_klass &&
|
if (ik != stackWalker_klass &&
|
||||||
ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) {
|
ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TraceStackWalk) {
|
if (TraceStackWalk) {
|
||||||
tty->print(" skip "); vfst.method()->print_short_name(); tty->print("\n");
|
tty->print(" skip "); stream.method()->print_short_name(); tty->print("\n");
|
||||||
}
|
}
|
||||||
vfst.next();
|
stream.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// stack frame has been traversed individually and resume stack walk
|
// stack frame has been traversed individually and resume stack walk
|
||||||
// from the stack frame at depth == skip_frames.
|
// from the stack frame at depth == skip_frames.
|
||||||
for (int n=0; n < skip_frames && !vfst.at_end(); vfst.next(), n++) {
|
for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
|
||||||
if (TraceStackWalk) {
|
if (TraceStackWalk) {
|
||||||
tty->print(" skip "); vfst.method()->print_short_name();
|
tty->print(" skip "); stream.method()->print_short_name();
|
||||||
tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT,
|
tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT,
|
||||||
p2i(vfst.frame_id()), p2i(vfst.frame_pc()));
|
p2i(stream.java_frame()->fr().id()),
|
||||||
|
p2i(stream.java_frame()->fr().pc()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Method* pointer in the vfst has a very short shelf life. Grab it now.
|
|
||||||
int end_index = start_index;
|
int end_index = start_index;
|
||||||
int numFrames = 0;
|
int numFrames = 0;
|
||||||
if (!vfst.at_end()) {
|
if (!stream.at_end()) {
|
||||||
numFrames = fill_in_frames(mode, vfst, frame_count, start_index,
|
numFrames = fill_in_frames(mode, stream, frame_count, start_index,
|
||||||
frames_array, end_index, CHECK_NULL);
|
frames_array, end_index, CHECK_NULL);
|
||||||
if (numFrames < 1) {
|
if (numFrames < 1) {
|
||||||
THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL);
|
THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL);
|
||||||
|
@ -356,19 +355,19 @@ oop StackWalk::walk(Handle stackStream, jlong mode,
|
||||||
// When JVM_CallStackWalk returns, it invalidates the stack stream.
|
// When JVM_CallStackWalk returns, it invalidates the stack stream.
|
||||||
JavaValue result(T_OBJECT);
|
JavaValue result(T_OBJECT);
|
||||||
JavaCallArguments args(stackStream);
|
JavaCallArguments args(stackStream);
|
||||||
args.push_long(anchor.address_value());
|
args.push_long(stream.address_value());
|
||||||
args.push_int(skip_frames);
|
args.push_int(skip_frames);
|
||||||
args.push_int(frame_count);
|
args.push_int(frame_count);
|
||||||
args.push_int(start_index);
|
args.push_int(start_index);
|
||||||
args.push_int(end_index);
|
args.push_int(end_index);
|
||||||
|
|
||||||
// Link the thread and vframe stream into the callee-visible object
|
// Link the thread and vframe stream into the callee-visible object
|
||||||
anchor.setup_magic_on_entry(frames_array);
|
stream.setup_magic_on_entry(frames_array);
|
||||||
|
|
||||||
JavaCalls::call(&result, m_doStackWalk, &args, THREAD);
|
JavaCalls::call(&result, m_doStackWalk, &args, THREAD);
|
||||||
|
|
||||||
// Do this before anything else happens, to disable any lingering stream objects
|
// Do this before anything else happens, to disable any lingering stream objects
|
||||||
bool ok = anchor.cleanup_magic_on_exit(frames_array);
|
bool ok = stream.cleanup_magic_on_exit(frames_array);
|
||||||
|
|
||||||
// Throw pending exception if we must
|
// Throw pending exception if we must
|
||||||
(void) (CHECK_NULL);
|
(void) (CHECK_NULL);
|
||||||
|
@ -379,7 +378,6 @@ oop StackWalk::walk(Handle stackStream, jlong mode,
|
||||||
|
|
||||||
// Return normally
|
// Return normally
|
||||||
return (oop)result.get_jobject();
|
return (oop)result.get_jobject();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk the next batch of stack frames
|
// Walk the next batch of stack frames
|
||||||
|
@ -400,8 +398,8 @@ jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic,
|
||||||
TRAPS)
|
TRAPS)
|
||||||
{
|
{
|
||||||
JavaThread* jt = (JavaThread*)THREAD;
|
JavaThread* jt = (JavaThread*)THREAD;
|
||||||
StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, frames_array);
|
JavaFrameStream* existing_stream = JavaFrameStream::from_current(jt, magic, frames_array);
|
||||||
if (existing_anchor == NULL) {
|
if (existing_stream == NULL) {
|
||||||
THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
|
THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,8 +408,8 @@ jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TraceStackWalk) {
|
if (TraceStackWalk) {
|
||||||
tty->print_cr("StackWalk::moreFrames frame_count %d existing_anchor " PTR_FORMAT " start %d frames %d",
|
tty->print_cr("StackWalk::moreFrames frame_count %d existing_stream " PTR_FORMAT " start %d frames %d",
|
||||||
frame_count, p2i(existing_anchor), start_index, frames_array->length());
|
frame_count, p2i(existing_stream), start_index, frames_array->length());
|
||||||
}
|
}
|
||||||
int end_index = start_index;
|
int end_index = start_index;
|
||||||
if (frame_count <= 0) {
|
if (frame_count <= 0) {
|
||||||
|
@ -421,12 +419,11 @@ jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic,
|
||||||
int count = frame_count + start_index;
|
int count = frame_count + start_index;
|
||||||
assert (frames_array->length() >= count, "not enough space in buffers");
|
assert (frames_array->length() >= count, "not enough space in buffers");
|
||||||
|
|
||||||
StackWalkAnchor& anchor = (*existing_anchor);
|
JavaFrameStream& stream = (*existing_stream);
|
||||||
vframeStream& vfst = anchor.vframe_stream();
|
if (!stream.at_end()) {
|
||||||
if (!vfst.at_end()) {
|
stream.next(); // advance past the last frame decoded in previous batch
|
||||||
vfst.next(); // this was the last frame decoded in the previous batch
|
if (!stream.at_end()) {
|
||||||
if (!vfst.at_end()) {
|
int n = fill_in_frames(mode, stream, frame_count, start_index,
|
||||||
int n = fill_in_frames(mode, vfst, frame_count, start_index,
|
|
||||||
frames_array, end_index, CHECK_0);
|
frames_array, end_index, CHECK_0);
|
||||||
if (n < 1) {
|
if (n < 1) {
|
||||||
THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
|
THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -29,21 +29,31 @@
|
||||||
#include "oops/oop.hpp"
|
#include "oops/oop.hpp"
|
||||||
#include "runtime/vframe.hpp"
|
#include "runtime/vframe.hpp"
|
||||||
|
|
||||||
class StackWalkAnchor : public StackObj {
|
//
|
||||||
|
// JavaFrameStream is used by StackWalker to iterate through Java stack frames
|
||||||
|
// on the given JavaThread.
|
||||||
|
//
|
||||||
|
class JavaFrameStream : public StackObj {
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
magic_pos = 0
|
magic_pos = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
JavaThread* _thread;
|
JavaThread* _thread;
|
||||||
vframeStream _vfst;
|
javaVFrame* _jvf;
|
||||||
jlong _anchor;
|
jlong _anchor;
|
||||||
public:
|
public:
|
||||||
StackWalkAnchor(JavaThread* thread)
|
JavaFrameStream(JavaThread* thread, RegisterMap* rm)
|
||||||
: _thread(thread), _vfst(thread), _anchor(0L) {}
|
: _thread(thread), _anchor(0L) {
|
||||||
|
_jvf = _thread->last_java_vframe(rm);
|
||||||
|
}
|
||||||
|
|
||||||
vframeStream& vframe_stream() { return _vfst; }
|
javaVFrame* java_frame() { return _jvf; }
|
||||||
JavaThread* thread() { return _thread; }
|
void next() { _jvf = _jvf->java_sender(); }
|
||||||
|
bool at_end() { return _jvf == NULL; }
|
||||||
|
|
||||||
|
Method* method() { return _jvf->method(); }
|
||||||
|
int bci() { return _jvf->bci(); }
|
||||||
|
|
||||||
void setup_magic_on_entry(objArrayHandle frames_array);
|
void setup_magic_on_entry(objArrayHandle frames_array);
|
||||||
bool check_magic(objArrayHandle frames_array);
|
bool check_magic(objArrayHandle frames_array);
|
||||||
|
@ -57,12 +67,12 @@ public:
|
||||||
return (jlong) castable_address(this);
|
return (jlong) castable_address(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static StackWalkAnchor* from_current(JavaThread* thread, jlong anchor, objArrayHandle frames_array);
|
static JavaFrameStream* from_current(JavaThread* thread, jlong magic, objArrayHandle frames_array);
|
||||||
};
|
};
|
||||||
|
|
||||||
class StackWalk : public AllStatic {
|
class StackWalk : public AllStatic {
|
||||||
private:
|
private:
|
||||||
static int fill_in_frames(jlong mode, vframeStream& vfst,
|
static int fill_in_frames(jlong mode, JavaFrameStream& stream,
|
||||||
int max_nframes, int start_index,
|
int max_nframes, int start_index,
|
||||||
objArrayHandle frames_array,
|
objArrayHandle frames_array,
|
||||||
int& end_index, TRAPS);
|
int& end_index, TRAPS);
|
||||||
|
|
|
@ -131,38 +131,137 @@ jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///// Data in the Java heap.
|
///// Data read/writes on the Java heap and in native (off-heap) memory
|
||||||
|
|
||||||
#define truncate_jboolean(x) ((x) & 1)
|
/**
|
||||||
#define truncate_jbyte(x) (x)
|
* Helper class for accessing memory.
|
||||||
#define truncate_jshort(x) (x)
|
*
|
||||||
#define truncate_jchar(x) (x)
|
* Normalizes values and wraps accesses in
|
||||||
#define truncate_jint(x) (x)
|
* JavaThread::doing_unsafe_access() if needed.
|
||||||
#define truncate_jlong(x) (x)
|
*/
|
||||||
#define truncate_jfloat(x) (x)
|
class MemoryAccess : StackObj {
|
||||||
#define truncate_jdouble(x) (x)
|
JavaThread* _thread;
|
||||||
|
jobject _obj;
|
||||||
|
jlong _offset;
|
||||||
|
|
||||||
#define GET_FIELD(obj, offset, type_name, v) \
|
// Resolves and returns the address of the memory access
|
||||||
oop p = JNIHandles::resolve(obj); \
|
void* addr() {
|
||||||
type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset)
|
return index_oop_from_field_offset_long(JNIHandles::resolve(_obj), _offset);
|
||||||
|
}
|
||||||
|
|
||||||
#define SET_FIELD(obj, offset, type_name, x) \
|
template <typename T>
|
||||||
oop p = JNIHandles::resolve(obj); \
|
T normalize(T x) {
|
||||||
*(type_name*)index_oop_from_field_offset_long(p, offset) = truncate_##type_name(x)
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
#define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
|
jboolean normalize(jboolean x) {
|
||||||
oop p = JNIHandles::resolve(obj); \
|
return x & 1;
|
||||||
if (support_IRIW_for_not_multiple_copy_atomic_cpu) { \
|
}
|
||||||
OrderAccess::fence(); \
|
|
||||||
} \
|
|
||||||
volatile type_name v = OrderAccess::load_acquire((volatile type_name*)index_oop_from_field_offset_long(p, offset));
|
|
||||||
|
|
||||||
#define SET_FIELD_VOLATILE(obj, offset, type_name, x) \
|
/**
|
||||||
oop p = JNIHandles::resolve(obj); \
|
* Helper class to wrap memory accesses in JavaThread::doing_unsafe_access()
|
||||||
OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), truncate_##type_name(x));
|
*/
|
||||||
|
class GuardUnsafeAccess {
|
||||||
|
JavaThread* _thread;
|
||||||
|
bool _active;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GuardUnsafeAccess(JavaThread* thread, jobject _obj) : _thread(thread) {
|
||||||
|
if (JNIHandles::resolve(_obj) == NULL) {
|
||||||
|
// native/off-heap access which may raise SIGBUS if accessing
|
||||||
|
// memory mapped file data in a region of the file which has
|
||||||
|
// been truncated and is now invalid
|
||||||
|
_thread->set_doing_unsafe_access(true);
|
||||||
|
_active = true;
|
||||||
|
} else {
|
||||||
|
_active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~GuardUnsafeAccess() {
|
||||||
|
if (_active) {
|
||||||
|
_thread->set_doing_unsafe_access(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
MemoryAccess(JavaThread* thread, jobject obj, jlong offset)
|
||||||
|
: _thread(thread), _obj(obj), _offset(offset) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T get() {
|
||||||
|
GuardUnsafeAccess guard(_thread, _obj);
|
||||||
|
|
||||||
|
T* p = (T*)addr();
|
||||||
|
|
||||||
|
T x = *p;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void put(T x) {
|
||||||
|
GuardUnsafeAccess guard(_thread, _obj);
|
||||||
|
|
||||||
|
T* p = (T*)addr();
|
||||||
|
|
||||||
|
*p = normalize(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get/SetObject must be special-cased, since it works with handles.
|
template <typename T>
|
||||||
|
T get_volatile() {
|
||||||
|
GuardUnsafeAccess guard(_thread, _obj);
|
||||||
|
|
||||||
|
T* p = (T*)addr();
|
||||||
|
|
||||||
|
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
|
||||||
|
OrderAccess::fence();
|
||||||
|
}
|
||||||
|
|
||||||
|
T x = OrderAccess::load_acquire((volatile T*)p);
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void put_volatile(T x) {
|
||||||
|
GuardUnsafeAccess guard(_thread, _obj);
|
||||||
|
|
||||||
|
T* p = (T*)addr();
|
||||||
|
|
||||||
|
OrderAccess::release_store_fence((volatile T*)p, normalize(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SUPPORTS_NATIVE_CX8
|
||||||
|
jlong get_jlong_locked() {
|
||||||
|
GuardUnsafeAccess guard(_thread, _obj);
|
||||||
|
|
||||||
|
MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
|
||||||
|
jlong* p = (jlong*)addr();
|
||||||
|
|
||||||
|
jlong x = Atomic::load(p);
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void put_jlong_locked(jlong x) {
|
||||||
|
GuardUnsafeAccess guard(_thread, _obj);
|
||||||
|
|
||||||
|
MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
|
||||||
|
jlong* p = (jlong*)addr();
|
||||||
|
|
||||||
|
Atomic::store(normalize(x), p);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get/PutObject must be special-cased, since it works with handles.
|
||||||
|
|
||||||
// These functions allow a null base pointer with an arbitrary address.
|
// These functions allow a null base pointer with an arbitrary address.
|
||||||
// But if the base pointer is non-null, the offset should make some sense.
|
// But if the base pointer is non-null, the offset should make some sense.
|
||||||
|
@ -208,7 +307,7 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj,
|
||||||
return ret;
|
return ret;
|
||||||
} UNSAFE_END
|
} UNSAFE_END
|
||||||
|
|
||||||
UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
|
UNSAFE_ENTRY(void, Unsafe_PutObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
|
||||||
oop x = JNIHandles::resolve(x_h);
|
oop x = JNIHandles::resolve(x_h);
|
||||||
oop p = JNIHandles::resolve(obj);
|
oop p = JNIHandles::resolve(obj);
|
||||||
|
|
||||||
|
@ -236,7 +335,7 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobj
|
||||||
return JNIHandles::make_local(env, v);
|
return JNIHandles::make_local(env, v);
|
||||||
} UNSAFE_END
|
} UNSAFE_END
|
||||||
|
|
||||||
UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
|
UNSAFE_ENTRY(void, Unsafe_PutObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
|
||||||
oop x = JNIHandles::resolve(x_h);
|
oop x = JNIHandles::resolve(x_h);
|
||||||
oop p = JNIHandles::resolve(obj);
|
oop p = JNIHandles::resolve(obj);
|
||||||
void* addr = index_oop_from_field_offset_long(p, offset);
|
void* addr = index_oop_from_field_offset_long(p, offset);
|
||||||
|
@ -301,25 +400,17 @@ UNSAFE_ENTRY(jlong, Unsafe_GetKlassPointer(JNIEnv *env, jobject unsafe, jobject
|
||||||
|
|
||||||
UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
|
UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
|
||||||
if (VM_Version::supports_cx8()) {
|
if (VM_Version::supports_cx8()) {
|
||||||
GET_FIELD_VOLATILE(obj, offset, jlong, v);
|
return MemoryAccess(thread, obj, offset).get_volatile<jlong>();
|
||||||
return v;
|
|
||||||
} else {
|
} else {
|
||||||
Handle p (THREAD, JNIHandles::resolve(obj));
|
return MemoryAccess(thread, obj, offset).get_jlong_locked();
|
||||||
jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
|
|
||||||
MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
|
|
||||||
jlong value = Atomic::load(addr);
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
} UNSAFE_END
|
} UNSAFE_END
|
||||||
|
|
||||||
UNSAFE_ENTRY(void, Unsafe_SetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) {
|
UNSAFE_ENTRY(void, Unsafe_PutLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) {
|
||||||
if (VM_Version::supports_cx8()) {
|
if (VM_Version::supports_cx8()) {
|
||||||
SET_FIELD_VOLATILE(obj, offset, jlong, x);
|
MemoryAccess(thread, obj, offset).put_volatile<jlong>(x);
|
||||||
} else {
|
} else {
|
||||||
Handle p (THREAD, JNIHandles::resolve(obj));
|
MemoryAccess(thread, obj, offset).put_jlong_locked(x);
|
||||||
jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
|
|
||||||
MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
|
|
||||||
Atomic::store(x, addr);
|
|
||||||
}
|
}
|
||||||
} UNSAFE_END
|
} UNSAFE_END
|
||||||
|
|
||||||
|
@ -337,15 +428,14 @@ UNSAFE_LEAF(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) {
|
||||||
return UseUnalignedAccesses;
|
return UseUnalignedAccesses;
|
||||||
} UNSAFE_END
|
} UNSAFE_END
|
||||||
|
|
||||||
#define DEFINE_GETSETOOP(java_type, Type) \
|
#define DEFINE_GETSETOOP(java_type, Type) \
|
||||||
\
|
\
|
||||||
UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
|
UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
|
||||||
GET_FIELD(obj, offset, java_type, v); \
|
return MemoryAccess(thread, obj, offset).get<java_type>(); \
|
||||||
return v; \
|
|
||||||
} UNSAFE_END \
|
} UNSAFE_END \
|
||||||
\
|
\
|
||||||
UNSAFE_ENTRY(void, Unsafe_Set##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
|
UNSAFE_ENTRY(void, Unsafe_Put##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
|
||||||
SET_FIELD(obj, offset, java_type, x); \
|
MemoryAccess(thread, obj, offset).put<java_type>(x); \
|
||||||
} UNSAFE_END \
|
} UNSAFE_END \
|
||||||
\
|
\
|
||||||
// END DEFINE_GETSETOOP.
|
// END DEFINE_GETSETOOP.
|
||||||
|
@ -364,12 +454,11 @@ DEFINE_GETSETOOP(jdouble, Double);
|
||||||
#define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \
|
#define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \
|
||||||
\
|
\
|
||||||
UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
|
UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
|
||||||
GET_FIELD_VOLATILE(obj, offset, java_type, v); \
|
return MemoryAccess(thread, obj, offset).get_volatile<java_type>(); \
|
||||||
return v; \
|
|
||||||
} UNSAFE_END \
|
} UNSAFE_END \
|
||||||
\
|
\
|
||||||
UNSAFE_ENTRY(void, Unsafe_Set##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
|
UNSAFE_ENTRY(void, Unsafe_Put##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
|
||||||
SET_FIELD_VOLATILE(obj, offset, java_type, x); \
|
MemoryAccess(thread, obj, offset).put_volatile<java_type>(x); \
|
||||||
} UNSAFE_END \
|
} UNSAFE_END \
|
||||||
\
|
\
|
||||||
// END DEFINE_GETSETOOP_VOLATILE.
|
// END DEFINE_GETSETOOP_VOLATILE.
|
||||||
|
@ -400,98 +489,6 @@ UNSAFE_LEAF(void, Unsafe_FullFence(JNIEnv *env, jobject unsafe)) {
|
||||||
OrderAccess::fence();
|
OrderAccess::fence();
|
||||||
} UNSAFE_END
|
} UNSAFE_END
|
||||||
|
|
||||||
////// Data in the C heap.
|
|
||||||
|
|
||||||
// Note: These do not throw NullPointerException for bad pointers.
|
|
||||||
// They just crash. Only a oop base pointer can generate a NullPointerException.
|
|
||||||
//
|
|
||||||
#define DEFINE_GETSETNATIVE(java_type, Type, native_type) \
|
|
||||||
\
|
|
||||||
UNSAFE_ENTRY(java_type, Unsafe_GetNative##Type(JNIEnv *env, jobject unsafe, jlong addr)) { \
|
|
||||||
void* p = addr_from_java(addr); \
|
|
||||||
JavaThread* t = JavaThread::current(); \
|
|
||||||
t->set_doing_unsafe_access(true); \
|
|
||||||
java_type x = *(volatile native_type*)p; \
|
|
||||||
t->set_doing_unsafe_access(false); \
|
|
||||||
return x; \
|
|
||||||
} UNSAFE_END \
|
|
||||||
\
|
|
||||||
UNSAFE_ENTRY(void, Unsafe_SetNative##Type(JNIEnv *env, jobject unsafe, jlong addr, java_type x)) { \
|
|
||||||
JavaThread* t = JavaThread::current(); \
|
|
||||||
t->set_doing_unsafe_access(true); \
|
|
||||||
void* p = addr_from_java(addr); \
|
|
||||||
*(volatile native_type*)p = x; \
|
|
||||||
t->set_doing_unsafe_access(false); \
|
|
||||||
} UNSAFE_END \
|
|
||||||
\
|
|
||||||
// END DEFINE_GETSETNATIVE.
|
|
||||||
|
|
||||||
DEFINE_GETSETNATIVE(jbyte, Byte, signed char)
|
|
||||||
DEFINE_GETSETNATIVE(jshort, Short, signed short);
|
|
||||||
DEFINE_GETSETNATIVE(jchar, Char, unsigned short);
|
|
||||||
DEFINE_GETSETNATIVE(jint, Int, jint);
|
|
||||||
// no long -- handled specially
|
|
||||||
DEFINE_GETSETNATIVE(jfloat, Float, float);
|
|
||||||
DEFINE_GETSETNATIVE(jdouble, Double, double);
|
|
||||||
|
|
||||||
#undef DEFINE_GETSETNATIVE
|
|
||||||
|
|
||||||
UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr)) {
|
|
||||||
JavaThread* t = JavaThread::current();
|
|
||||||
// We do it this way to avoid problems with access to heap using 64
|
|
||||||
// bit loads, as jlong in heap could be not 64-bit aligned, and on
|
|
||||||
// some CPUs (SPARC) it leads to SIGBUS.
|
|
||||||
t->set_doing_unsafe_access(true);
|
|
||||||
void* p = addr_from_java(addr);
|
|
||||||
jlong x;
|
|
||||||
|
|
||||||
if (is_ptr_aligned(p, sizeof(jlong)) == 0) {
|
|
||||||
// jlong is aligned, do a volatile access
|
|
||||||
x = *(volatile jlong*)p;
|
|
||||||
} else {
|
|
||||||
jlong_accessor acc;
|
|
||||||
acc.words[0] = ((volatile jint*)p)[0];
|
|
||||||
acc.words[1] = ((volatile jint*)p)[1];
|
|
||||||
x = acc.long_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
t->set_doing_unsafe_access(false);
|
|
||||||
|
|
||||||
return x;
|
|
||||||
} UNSAFE_END
|
|
||||||
|
|
||||||
UNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) {
|
|
||||||
JavaThread* t = JavaThread::current();
|
|
||||||
// see comment for Unsafe_GetNativeLong
|
|
||||||
t->set_doing_unsafe_access(true);
|
|
||||||
void* p = addr_from_java(addr);
|
|
||||||
|
|
||||||
if (is_ptr_aligned(p, sizeof(jlong))) {
|
|
||||||
// jlong is aligned, do a volatile access
|
|
||||||
*(volatile jlong*)p = x;
|
|
||||||
} else {
|
|
||||||
jlong_accessor acc;
|
|
||||||
acc.long_value = x;
|
|
||||||
((volatile jint*)p)[0] = acc.words[0];
|
|
||||||
((volatile jint*)p)[1] = acc.words[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
t->set_doing_unsafe_access(false);
|
|
||||||
} UNSAFE_END
|
|
||||||
|
|
||||||
|
|
||||||
UNSAFE_LEAF(jlong, Unsafe_GetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr)) {
|
|
||||||
void* p = addr_from_java(addr);
|
|
||||||
|
|
||||||
return addr_to_java(*(void**)p);
|
|
||||||
} UNSAFE_END
|
|
||||||
|
|
||||||
UNSAFE_LEAF(void, Unsafe_SetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) {
|
|
||||||
void* p = addr_from_java(addr);
|
|
||||||
*(void**)p = addr_from_java(x);
|
|
||||||
} UNSAFE_END
|
|
||||||
|
|
||||||
|
|
||||||
////// Allocation requests
|
////// Allocation requests
|
||||||
|
|
||||||
UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls)) {
|
UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls)) {
|
||||||
|
@ -980,8 +977,8 @@ UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, job
|
||||||
} UNSAFE_END
|
} UNSAFE_END
|
||||||
|
|
||||||
UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) {
|
UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) {
|
||||||
Handle p (THREAD, JNIHandles::resolve(obj));
|
Handle p(THREAD, JNIHandles::resolve(obj));
|
||||||
jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
|
jlong* addr = (jlong*)index_oop_from_field_offset_long(p(), offset);
|
||||||
|
|
||||||
#ifdef SUPPORTS_NATIVE_CX8
|
#ifdef SUPPORTS_NATIVE_CX8
|
||||||
return (jlong)(Atomic::cmpxchg(x, addr, e));
|
return (jlong)(Atomic::cmpxchg(x, addr, e));
|
||||||
|
@ -1017,7 +1014,7 @@ UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe,
|
||||||
|
|
||||||
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
|
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
|
||||||
oop p = JNIHandles::resolve(obj);
|
oop p = JNIHandles::resolve(obj);
|
||||||
jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
|
jint* addr = (jint *)index_oop_from_field_offset_long(p, offset);
|
||||||
|
|
||||||
return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
|
return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
|
||||||
} UNSAFE_END
|
} UNSAFE_END
|
||||||
|
@ -1143,20 +1140,16 @@ UNSAFE_ENTRY(jint, Unsafe_GetLoadAverage0(JNIEnv *env, jobject unsafe, jdoubleAr
|
||||||
|
|
||||||
#define DECLARE_GETPUTOOP(Type, Desc) \
|
#define DECLARE_GETPUTOOP(Type, Desc) \
|
||||||
{CC "get" #Type, CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type)}, \
|
{CC "get" #Type, CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type)}, \
|
||||||
{CC "put" #Type, CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Set##Type)}, \
|
{CC "put" #Type, CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Put##Type)}, \
|
||||||
{CC "get" #Type "Volatile", CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type##Volatile)}, \
|
{CC "get" #Type "Volatile", CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type##Volatile)}, \
|
||||||
{CC "put" #Type "Volatile", CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Set##Type##Volatile)}
|
{CC "put" #Type "Volatile", CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Put##Type##Volatile)}
|
||||||
|
|
||||||
|
|
||||||
#define DECLARE_GETPUTNATIVE(Byte, B) \
|
|
||||||
{CC "get" #Byte, CC "(" ADR ")" #B, FN_PTR(Unsafe_GetNative##Byte)}, \
|
|
||||||
{CC "put" #Byte, CC "(" ADR#B ")V", FN_PTR(Unsafe_SetNative##Byte)}
|
|
||||||
|
|
||||||
static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
|
static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
|
||||||
{CC "getObject", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObject)},
|
{CC "getObject", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObject)},
|
||||||
{CC "putObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObject)},
|
{CC "putObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutObject)},
|
||||||
{CC "getObjectVolatile",CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObjectVolatile)},
|
{CC "getObjectVolatile",CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObjectVolatile)},
|
||||||
{CC "putObjectVolatile",CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObjectVolatile)},
|
{CC "putObjectVolatile",CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutObjectVolatile)},
|
||||||
|
|
||||||
{CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)},
|
{CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)},
|
||||||
{CC "getJavaMirror", CC "(" ADR ")" CLS, FN_PTR(Unsafe_GetJavaMirror)},
|
{CC "getJavaMirror", CC "(" ADR ")" CLS, FN_PTR(Unsafe_GetJavaMirror)},
|
||||||
|
@ -1171,17 +1164,6 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
|
||||||
DECLARE_GETPUTOOP(Float, F),
|
DECLARE_GETPUTOOP(Float, F),
|
||||||
DECLARE_GETPUTOOP(Double, D),
|
DECLARE_GETPUTOOP(Double, D),
|
||||||
|
|
||||||
DECLARE_GETPUTNATIVE(Byte, B),
|
|
||||||
DECLARE_GETPUTNATIVE(Short, S),
|
|
||||||
DECLARE_GETPUTNATIVE(Char, C),
|
|
||||||
DECLARE_GETPUTNATIVE(Int, I),
|
|
||||||
DECLARE_GETPUTNATIVE(Long, J),
|
|
||||||
DECLARE_GETPUTNATIVE(Float, F),
|
|
||||||
DECLARE_GETPUTNATIVE(Double, D),
|
|
||||||
|
|
||||||
{CC "getAddress", CC "(" ADR ")" ADR, FN_PTR(Unsafe_GetNativeAddress)},
|
|
||||||
{CC "putAddress", CC "(" ADR "" ADR ")V", FN_PTR(Unsafe_SetNativeAddress)},
|
|
||||||
|
|
||||||
{CC "allocateMemory0", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory0)},
|
{CC "allocateMemory0", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory0)},
|
||||||
{CC "reallocateMemory0", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory0)},
|
{CC "reallocateMemory0", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory0)},
|
||||||
{CC "freeMemory0", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory0)},
|
{CC "freeMemory0", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory0)},
|
||||||
|
@ -1239,7 +1221,6 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
|
||||||
#undef DAC_Args
|
#undef DAC_Args
|
||||||
|
|
||||||
#undef DECLARE_GETPUTOOP
|
#undef DECLARE_GETPUTOOP
|
||||||
#undef DECLARE_GETPUTNATIVE
|
|
||||||
|
|
||||||
|
|
||||||
// This function is exported, used by NativeLookup.
|
// This function is exported, used by NativeLookup.
|
||||||
|
|
|
@ -84,8 +84,6 @@ const char* Arguments::_java_vendor_url_bug = DEFAULT_VENDOR_URL_BUG;
|
||||||
const char* Arguments::_sun_java_launcher = DEFAULT_JAVA_LAUNCHER;
|
const char* Arguments::_sun_java_launcher = DEFAULT_JAVA_LAUNCHER;
|
||||||
int Arguments::_sun_java_launcher_pid = -1;
|
int Arguments::_sun_java_launcher_pid = -1;
|
||||||
bool Arguments::_sun_java_launcher_is_altjvm = false;
|
bool Arguments::_sun_java_launcher_is_altjvm = false;
|
||||||
int Arguments::_patch_dirs_count = 0;
|
|
||||||
char** Arguments::_patch_dirs = NULL;
|
|
||||||
int Arguments::_bootclassloader_append_index = -1;
|
int Arguments::_bootclassloader_append_index = -1;
|
||||||
|
|
||||||
// These parameters are reset in method parse_vm_init_args()
|
// These parameters are reset in method parse_vm_init_args()
|
||||||
|
@ -112,6 +110,7 @@ SystemProperty *Arguments::_java_home = NULL;
|
||||||
SystemProperty *Arguments::_java_class_path = NULL;
|
SystemProperty *Arguments::_java_class_path = NULL;
|
||||||
SystemProperty *Arguments::_jdk_boot_class_path_append = NULL;
|
SystemProperty *Arguments::_jdk_boot_class_path_append = NULL;
|
||||||
|
|
||||||
|
GrowableArray<ModuleXPatchPath*> *Arguments::_xpatchprefix = NULL;
|
||||||
PathString *Arguments::_system_boot_class_path = NULL;
|
PathString *Arguments::_system_boot_class_path = NULL;
|
||||||
|
|
||||||
char* Arguments::_ext_dirs = NULL;
|
char* Arguments::_ext_dirs = NULL;
|
||||||
|
@ -421,6 +420,7 @@ static AliasedLoggingFlag const aliased_logging_flags[] = {
|
||||||
{ "TraceMonitorInflation", LogLevel::Debug, true, LOG_TAGS(monitorinflation) },
|
{ "TraceMonitorInflation", LogLevel::Debug, true, LOG_TAGS(monitorinflation) },
|
||||||
{ "TraceSafepointCleanupTime", LogLevel::Info, true, LOG_TAGS(safepoint, cleanup) },
|
{ "TraceSafepointCleanupTime", LogLevel::Info, true, LOG_TAGS(safepoint, cleanup) },
|
||||||
{ "TraceJVMTIObjectTagging", LogLevel::Debug, true, LOG_TAGS(jvmti, objecttagging) },
|
{ "TraceJVMTIObjectTagging", LogLevel::Debug, true, LOG_TAGS(jvmti, objecttagging) },
|
||||||
|
{ "TraceRedefineClasses", LogLevel::Info, false, LOG_TAGS(redefine, class) },
|
||||||
{ NULL, LogLevel::Off, false, LOG_TAGS(_NO_TAG) }
|
{ NULL, LogLevel::Off, false, LOG_TAGS(_NO_TAG) }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -580,204 +580,6 @@ static bool verify_special_jvm_flags() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Constructs the system boot class path from the following components, in order:
|
|
||||||
//
|
|
||||||
// prefix // from -Xpatch:...
|
|
||||||
// base // from os::get_system_properties()
|
|
||||||
// suffix // from -Xbootclasspath/a:...
|
|
||||||
//
|
|
||||||
// This could be AllStatic, but it isn't needed after argument processing is
|
|
||||||
// complete. After argument processing, the combined components are copied
|
|
||||||
// to Arguments::_system_boot_class_path via a call to Arguments::set_sysclasspath.
|
|
||||||
class ArgumentBootClassPath: public StackObj {
|
|
||||||
public:
|
|
||||||
ArgumentBootClassPath(const char* base);
|
|
||||||
~ArgumentBootClassPath();
|
|
||||||
|
|
||||||
inline void set_base(const char* base);
|
|
||||||
inline void add_prefix(const char* prefix);
|
|
||||||
inline void add_suffix_to_prefix(const char* suffix);
|
|
||||||
inline void add_suffix(const char* suffix);
|
|
||||||
inline void reset_path(const char* base);
|
|
||||||
|
|
||||||
inline const char* get_base() const { return _items[_bcp_base]; }
|
|
||||||
inline const char* get_prefix() const { return _items[_bcp_prefix]; }
|
|
||||||
inline const char* get_suffix() const { return _items[_bcp_suffix]; }
|
|
||||||
|
|
||||||
// Combine all the components into a single c-heap-allocated string; caller
|
|
||||||
// must free the string if/when no longer needed.
|
|
||||||
char* combined_path();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Utility routines.
|
|
||||||
static char* add_to_path(const char* path, const char* str, bool prepend);
|
|
||||||
static char* add_jars_to_path(char* path, const char* directory);
|
|
||||||
|
|
||||||
inline void reset_item_at(int index);
|
|
||||||
|
|
||||||
// Array indices for the items that make up the sysclasspath. All except the
|
|
||||||
// base are allocated in the C heap and freed by this class.
|
|
||||||
enum {
|
|
||||||
_bcp_prefix, // was -Xpatch:...
|
|
||||||
_bcp_base, // the default system boot class path
|
|
||||||
_bcp_suffix, // from -Xbootclasspath/a:...
|
|
||||||
_bcp_nitems // the number of items, must be last.
|
|
||||||
};
|
|
||||||
|
|
||||||
const char* _items[_bcp_nitems];
|
|
||||||
};
|
|
||||||
|
|
||||||
ArgumentBootClassPath::ArgumentBootClassPath(const char* base) {
|
|
||||||
memset(_items, 0, sizeof(_items));
|
|
||||||
_items[_bcp_base] = base;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArgumentBootClassPath::~ArgumentBootClassPath() {
|
|
||||||
// Free everything except the base.
|
|
||||||
for (int i = 0; i < _bcp_nitems; ++i) {
|
|
||||||
if (i != _bcp_base) reset_item_at(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ArgumentBootClassPath::set_base(const char* base) {
|
|
||||||
_items[_bcp_base] = base;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ArgumentBootClassPath::add_prefix(const char* prefix) {
|
|
||||||
_items[_bcp_prefix] = add_to_path(_items[_bcp_prefix], prefix, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ArgumentBootClassPath::add_suffix_to_prefix(const char* suffix) {
|
|
||||||
_items[_bcp_prefix] = add_to_path(_items[_bcp_prefix], suffix, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ArgumentBootClassPath::add_suffix(const char* suffix) {
|
|
||||||
_items[_bcp_suffix] = add_to_path(_items[_bcp_suffix], suffix, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ArgumentBootClassPath::reset_item_at(int index) {
|
|
||||||
assert(index < _bcp_nitems && index != _bcp_base, "just checking");
|
|
||||||
if (_items[index] != NULL) {
|
|
||||||
FREE_C_HEAP_ARRAY(char, _items[index]);
|
|
||||||
_items[index] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ArgumentBootClassPath::reset_path(const char* base) {
|
|
||||||
// Clear the prefix and suffix.
|
|
||||||
reset_item_at(_bcp_prefix);
|
|
||||||
reset_item_at(_bcp_suffix);
|
|
||||||
set_base(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// Combine the bootclasspath elements, some of which may be null, into a single
|
|
||||||
// c-heap-allocated string.
|
|
||||||
char* ArgumentBootClassPath::combined_path() {
|
|
||||||
assert(_items[_bcp_base] != NULL, "empty default sysclasspath");
|
|
||||||
|
|
||||||
size_t lengths[_bcp_nitems];
|
|
||||||
size_t total_len = 0;
|
|
||||||
|
|
||||||
const char separator = *os::path_separator();
|
|
||||||
|
|
||||||
// Get the lengths.
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < _bcp_nitems; ++i) {
|
|
||||||
if (i == _bcp_suffix) {
|
|
||||||
// Record index of boot loader's append path.
|
|
||||||
Arguments::set_bootclassloader_append_index((int)total_len);
|
|
||||||
}
|
|
||||||
if (_items[i] != NULL) {
|
|
||||||
lengths[i] = strlen(_items[i]);
|
|
||||||
// Include space for the separator char (or a NULL for the last item).
|
|
||||||
total_len += lengths[i] + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(total_len > 0, "empty sysclasspath not allowed");
|
|
||||||
|
|
||||||
// Copy the _items to a single string.
|
|
||||||
char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtArguments);
|
|
||||||
char* cp_tmp = cp;
|
|
||||||
for (i = 0; i < _bcp_nitems; ++i) {
|
|
||||||
if (_items[i] != NULL) {
|
|
||||||
memcpy(cp_tmp, _items[i], lengths[i]);
|
|
||||||
cp_tmp += lengths[i];
|
|
||||||
*cp_tmp++ = separator;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*--cp_tmp = '\0'; // Replace the extra separator.
|
|
||||||
return cp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: path must be c-heap-allocated (or NULL); it is freed if non-null.
|
|
||||||
char*
|
|
||||||
ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepend) {
|
|
||||||
char *cp;
|
|
||||||
|
|
||||||
assert(str != NULL, "just checking");
|
|
||||||
if (path == NULL) {
|
|
||||||
size_t len = strlen(str) + 1;
|
|
||||||
cp = NEW_C_HEAP_ARRAY(char, len, mtArguments);
|
|
||||||
memcpy(cp, str, len); // copy the trailing null
|
|
||||||
} else {
|
|
||||||
const char separator = *os::path_separator();
|
|
||||||
size_t old_len = strlen(path);
|
|
||||||
size_t str_len = strlen(str);
|
|
||||||
size_t len = old_len + str_len + 2;
|
|
||||||
|
|
||||||
if (prepend) {
|
|
||||||
cp = NEW_C_HEAP_ARRAY(char, len, mtArguments);
|
|
||||||
char* cp_tmp = cp;
|
|
||||||
memcpy(cp_tmp, str, str_len);
|
|
||||||
cp_tmp += str_len;
|
|
||||||
*cp_tmp = separator;
|
|
||||||
memcpy(++cp_tmp, path, old_len + 1); // copy the trailing null
|
|
||||||
FREE_C_HEAP_ARRAY(char, path);
|
|
||||||
} else {
|
|
||||||
cp = REALLOC_C_HEAP_ARRAY(char, path, len, mtArguments);
|
|
||||||
char* cp_tmp = cp + old_len;
|
|
||||||
*cp_tmp = separator;
|
|
||||||
memcpy(++cp_tmp, str, str_len + 1); // copy the trailing null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan the directory and append any jar or zip files found to path.
|
|
||||||
// Note: path must be c-heap-allocated (or NULL); it is freed if non-null.
|
|
||||||
char* ArgumentBootClassPath::add_jars_to_path(char* path, const char* directory) {
|
|
||||||
DIR* dir = os::opendir(directory);
|
|
||||||
if (dir == NULL) return path;
|
|
||||||
|
|
||||||
char dir_sep[2] = { '\0', '\0' };
|
|
||||||
size_t directory_len = strlen(directory);
|
|
||||||
const char fileSep = *os::file_separator();
|
|
||||||
if (directory[directory_len - 1] != fileSep) dir_sep[0] = fileSep;
|
|
||||||
|
|
||||||
/* Scan the directory for jars/zips, appending them to path. */
|
|
||||||
struct dirent *entry;
|
|
||||||
char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtArguments);
|
|
||||||
while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
|
|
||||||
const char* name = entry->d_name;
|
|
||||||
const char* ext = name + strlen(name) - 4;
|
|
||||||
bool isJarOrZip = ext > name &&
|
|
||||||
(os::file_name_strcmp(ext, ".jar") == 0 ||
|
|
||||||
os::file_name_strcmp(ext, ".zip") == 0);
|
|
||||||
if (isJarOrZip) {
|
|
||||||
char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name), mtArguments);
|
|
||||||
sprintf(jarpath, "%s%s%s", directory, dir_sep, name);
|
|
||||||
path = add_to_path(path, jarpath, false);
|
|
||||||
FREE_C_HEAP_ARRAY(char, jarpath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FREE_C_HEAP_ARRAY(char, dbuf);
|
|
||||||
os::closedir(dir);
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parses a size specification string.
|
// Parses a size specification string.
|
||||||
bool Arguments::atojulong(const char *s, julong* result) {
|
bool Arguments::atojulong(const char *s, julong* result) {
|
||||||
julong n = 0;
|
julong n = 0;
|
||||||
|
@ -1003,7 +805,9 @@ void log_deprecated_flag(const char* name, bool on, AliasedLoggingFlag alf) {
|
||||||
}
|
}
|
||||||
strncat(tagset_buffer, LogTag::name(tagSet[i]), max_tagset_len - strlen(tagset_buffer));
|
strncat(tagset_buffer, LogTag::name(tagSet[i]), max_tagset_len - strlen(tagset_buffer));
|
||||||
}
|
}
|
||||||
|
if (!alf.exactMatch) {
|
||||||
|
strncat(tagset_buffer, "*", max_tagset_len - strlen(tagset_buffer));
|
||||||
|
}
|
||||||
log_warning(arguments)("-XX:%s%s is deprecated. Will use -Xlog:%s=%s instead.",
|
log_warning(arguments)("-XX:%s%s is deprecated. Will use -Xlog:%s=%s instead.",
|
||||||
(on) ? "+" : "-",
|
(on) ? "+" : "-",
|
||||||
name,
|
name,
|
||||||
|
@ -1064,6 +868,11 @@ bool Arguments::parse_argument(const char* arg, Flag::Flags origin) {
|
||||||
Flag* flag;
|
Flag* flag;
|
||||||
|
|
||||||
// this scanf pattern matches both strings (handled here) and numbers (handled later))
|
// this scanf pattern matches both strings (handled here) and numbers (handled later))
|
||||||
|
AliasedLoggingFlag alf = catch_logging_aliases(name, true);
|
||||||
|
if (alf.alias_name != NULL) {
|
||||||
|
LogConfiguration::configure_stdout(alf.level, alf.exactMatch, alf.tag0, alf.tag1, alf.tag2, alf.tag3, alf.tag4, alf.tag5);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
real_name = handle_aliases_and_deprecation(name, warn_if_deprecated);
|
real_name = handle_aliases_and_deprecation(name, warn_if_deprecated);
|
||||||
if (real_name == NULL) {
|
if (real_name == NULL) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -2724,9 +2533,7 @@ Arguments::ArgsRange Arguments::parse_memory_size(const char* s,
|
||||||
jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
||||||
const JavaVMInitArgs *java_options_args,
|
const JavaVMInitArgs *java_options_args,
|
||||||
const JavaVMInitArgs *cmd_line_args) {
|
const JavaVMInitArgs *cmd_line_args) {
|
||||||
// For components of the system classpath.
|
bool xpatch_javabase = false;
|
||||||
ArgumentBootClassPath bcp(Arguments::get_sysclasspath());
|
|
||||||
bool bcp_assembly_required = false;
|
|
||||||
|
|
||||||
// Save default settings for some mode flags
|
// Save default settings for some mode flags
|
||||||
Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods;
|
Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods;
|
||||||
|
@ -2743,29 +2550,26 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
||||||
|
|
||||||
// Parse args structure generated from JAVA_TOOL_OPTIONS environment
|
// Parse args structure generated from JAVA_TOOL_OPTIONS environment
|
||||||
// variable (if present).
|
// variable (if present).
|
||||||
jint result = parse_each_vm_init_arg(
|
jint result = parse_each_vm_init_arg(java_tool_options_args, &xpatch_javabase, Flag::ENVIRON_VAR);
|
||||||
java_tool_options_args, &bcp, &bcp_assembly_required, Flag::ENVIRON_VAR);
|
|
||||||
if (result != JNI_OK) {
|
if (result != JNI_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse args structure generated from the command line flags.
|
// Parse args structure generated from the command line flags.
|
||||||
result = parse_each_vm_init_arg(cmd_line_args, &bcp, &bcp_assembly_required,
|
result = parse_each_vm_init_arg(cmd_line_args, &xpatch_javabase, Flag::COMMAND_LINE);
|
||||||
Flag::COMMAND_LINE);
|
|
||||||
if (result != JNI_OK) {
|
if (result != JNI_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse args structure generated from the _JAVA_OPTIONS environment
|
// Parse args structure generated from the _JAVA_OPTIONS environment
|
||||||
// variable (if present) (mimics classic VM)
|
// variable (if present) (mimics classic VM)
|
||||||
result = parse_each_vm_init_arg(
|
result = parse_each_vm_init_arg(java_options_args, &xpatch_javabase, Flag::ENVIRON_VAR);
|
||||||
java_options_args, &bcp, &bcp_assembly_required, Flag::ENVIRON_VAR);
|
|
||||||
if (result != JNI_OK) {
|
if (result != JNI_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do final processing now that all arguments have been parsed
|
// Do final processing now that all arguments have been parsed
|
||||||
result = finalize_vm_init_args(&bcp, bcp_assembly_required);
|
result = finalize_vm_init_args();
|
||||||
if (result != JNI_OK) {
|
if (result != JNI_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -2818,10 +2622,7 @@ bool valid_jdwp_agent(char *name, bool is_path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* xpatch_javabase, Flag::Flags origin) {
|
||||||
ArgumentBootClassPath* bcp_p,
|
|
||||||
bool* bcp_assembly_required_p,
|
|
||||||
Flag::Flags origin) {
|
|
||||||
// For match_option to return remaining or value part of option string
|
// For match_option to return remaining or value part of option string
|
||||||
const char* tail;
|
const char* tail;
|
||||||
|
|
||||||
|
@ -2877,8 +2678,8 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||||
return JNI_EINVAL;
|
return JNI_EINVAL;
|
||||||
// -bootclasspath/a:
|
// -bootclasspath/a:
|
||||||
} else if (match_option(option, "-Xbootclasspath/a:", &tail)) {
|
} else if (match_option(option, "-Xbootclasspath/a:", &tail)) {
|
||||||
bcp_p->add_suffix(tail);
|
Arguments::set_bootclassloader_append_index((int)strlen(Arguments::get_sysclasspath())+1);
|
||||||
*bcp_assembly_required_p = true;
|
Arguments::append_sysclasspath(tail);
|
||||||
// -bootclasspath/p:
|
// -bootclasspath/p:
|
||||||
} else if (match_option(option, "-Xbootclasspath/p:", &tail)) {
|
} else if (match_option(option, "-Xbootclasspath/p:", &tail)) {
|
||||||
jio_fprintf(defaultStream::output_stream(),
|
jio_fprintf(defaultStream::output_stream(),
|
||||||
|
@ -2938,9 +2739,8 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||||
if (tail != NULL) {
|
if (tail != NULL) {
|
||||||
char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtArguments), tail);
|
char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtArguments), tail);
|
||||||
add_init_agent("instrument", options, false);
|
add_init_agent("instrument", options, false);
|
||||||
// java agents need module java.instrument. Also -addmods ALL-SYSTEM because
|
// java agents need module java.instrument
|
||||||
// the java agent is in the unmamed module of the application class loader
|
if (!Arguments::append_to_addmods_property("java.instrument")) {
|
||||||
if (!Arguments::append_to_addmods_property("java.instrument,ALL-SYSTEM")) {
|
|
||||||
return JNI_ENOMEM;
|
return JNI_ENOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3218,37 +3018,30 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||||
return JNI_ERR;
|
return JNI_ERR;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (match_option(option, "-Djdk.launcher.patch.0=", &tail)) {
|
if (match_option(option, "-Djdk.launcher.patch.", &tail)) {
|
||||||
// -Xpatch
|
// -Djdk.launcher.patch.#=<module>=<file>(<pathsep><file>)*
|
||||||
int dir_count;
|
// The number, #, specified will be increasing with each -Xpatch
|
||||||
char** patch_dirs = os::split_path(tail, &dir_count);
|
// specified on the command line.
|
||||||
if (patch_dirs == NULL) {
|
// Pick up module name, following the -D property's equal sign.
|
||||||
jio_fprintf(defaultStream::output_stream(),
|
const char* property_equal = strchr(tail, '=');
|
||||||
"Bad value for -Xpatch.\n");
|
if (property_equal == NULL) {
|
||||||
|
jio_fprintf(defaultStream::output_stream(), "Missing '=' in -Xpatch specification\n");
|
||||||
return JNI_ERR;
|
return JNI_ERR;
|
||||||
}
|
} else {
|
||||||
set_patch_dirs(patch_dirs);
|
// Find the equal sign between the module name and the path specification
|
||||||
set_patch_dirs_count(dir_count);
|
const char* module_equal = strchr(property_equal + 1, '=');
|
||||||
|
if (module_equal == NULL) {
|
||||||
// Create a path for each patch dir consisting of dir/java.base.
|
jio_fprintf(defaultStream::output_stream(), "Bad value for -Xpatch, no module name specified\n");
|
||||||
char file_sep = os::file_separator()[0];
|
return JNI_ERR;
|
||||||
for (int x = 0; x < dir_count; x++) {
|
} else {
|
||||||
// Really shouldn't be NULL, but check can't hurt
|
// Pick out the module name, in between the two equal signs
|
||||||
if (patch_dirs[x] != NULL) {
|
size_t module_len = module_equal - property_equal - 1;
|
||||||
size_t len = strlen(patch_dirs[x]);
|
char* module_name = NEW_C_HEAP_ARRAY(char, module_len+1, mtArguments);
|
||||||
if (len != 0) { // Ignore empty strings.
|
memcpy(module_name, property_equal + 1, module_len);
|
||||||
len += 11; // file_sep + "java.base" + null terminator.
|
*(module_name + module_len) = '\0';
|
||||||
char* dir = NEW_C_HEAP_ARRAY(char, len, mtArguments);
|
// The path piece begins one past the module_equal sign
|
||||||
jio_snprintf(dir, len, "%s%cjava.base", patch_dirs[x], file_sep);
|
Arguments::add_xpatchprefix(module_name, module_equal + 1, xpatch_javabase);
|
||||||
|
FREE_C_HEAP_ARRAY(char, module_name);
|
||||||
// See if Xpatch module path exists.
|
|
||||||
struct stat st;
|
|
||||||
if ((os::stat(dir, &st) == 0)) {
|
|
||||||
bcp_p->add_prefix(dir);
|
|
||||||
*bcp_assembly_required_p = true;
|
|
||||||
}
|
|
||||||
FREE_C_HEAP_ARRAY(char, dir);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3511,6 +3304,27 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||||
return JNI_OK;
|
return JNI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Arguments::add_xpatchprefix(const char* module_name, const char* path, bool* xpatch_javabase) {
|
||||||
|
// For java.base check for duplicate -Xpatch options being specified on the command line.
|
||||||
|
// This check is only required for java.base, all other duplicate module specifications
|
||||||
|
// will be checked during module system initialization. The module system initialization
|
||||||
|
// will throw an ExceptionInInitializerError if this situation occurs.
|
||||||
|
if (strcmp(module_name, "java.base") == 0) {
|
||||||
|
if (*xpatch_javabase) {
|
||||||
|
vm_exit_during_initialization("Cannot specify java.base more than once to -Xpatch");
|
||||||
|
} else {
|
||||||
|
*xpatch_javabase = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create GrowableArray lazily, only if -Xpatch has been specified
|
||||||
|
if (_xpatchprefix == NULL) {
|
||||||
|
_xpatchprefix = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<ModuleXPatchPath*>(10, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_xpatchprefix->push(new ModuleXPatchPath(module_name, path));
|
||||||
|
}
|
||||||
|
|
||||||
// Set property jdk.boot.class.path.append to the contents of the bootclasspath
|
// Set property jdk.boot.class.path.append to the contents of the bootclasspath
|
||||||
// that follows either the jimage file or exploded module directories. The
|
// that follows either the jimage file or exploded module directories. The
|
||||||
// property will contain -Xbootclasspath/a and/or jvmti appended additions.
|
// property will contain -Xbootclasspath/a and/or jvmti appended additions.
|
||||||
|
@ -3609,7 +3423,7 @@ static int check_non_empty_dirs(const char* path) {
|
||||||
return nonEmptyDirs;
|
return nonEmptyDirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
jint Arguments::finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_assembly_required) {
|
jint Arguments::finalize_vm_init_args() {
|
||||||
// check if the default lib/endorsed directory exists; if so, error
|
// check if the default lib/endorsed directory exists; if so, error
|
||||||
char path[JVM_MAXPATHLEN];
|
char path[JVM_MAXPATHLEN];
|
||||||
const char* fileSep = os::file_separator();
|
const char* fileSep = os::file_separator();
|
||||||
|
@ -3645,17 +3459,7 @@ jint Arguments::finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_ass
|
||||||
return JNI_ERR;
|
return JNI_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bcp_assembly_required) {
|
Arguments::set_bootclassloader_append_index(((int)strlen(Arguments::get_sysclasspath()))+1);
|
||||||
// Assemble the bootclasspath elements into the final path.
|
|
||||||
char *combined_path = bcp_p->combined_path();
|
|
||||||
Arguments::set_sysclasspath(combined_path);
|
|
||||||
FREE_C_HEAP_ARRAY(char, combined_path);
|
|
||||||
} else {
|
|
||||||
// At this point in sysclasspath processing anything
|
|
||||||
// added would be considered in the boot loader's append path.
|
|
||||||
// Record this index, including +1 for the file separator character.
|
|
||||||
Arguments::set_bootclassloader_append_index(((int)strlen(Arguments::get_sysclasspath()))+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This must be done after all arguments have been processed.
|
// This must be done after all arguments have been processed.
|
||||||
// java_compiler() true means set to "NONE" or empty.
|
// java_compiler() true means set to "NONE" or empty.
|
||||||
|
@ -3704,6 +3508,12 @@ jint Arguments::finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_ass
|
||||||
UNSUPPORTED_OPTION(TieredCompilation);
|
UNSUPPORTED_OPTION(TieredCompilation);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if INCLUDE_JVMCI
|
||||||
|
if (EnableJVMCI && !append_to_addmods_property("jdk.vm.ci")) {
|
||||||
|
return JNI_ENOMEM;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// If we are running in a headless jre, force java.awt.headless property
|
// If we are running in a headless jre, force java.awt.headless property
|
||||||
// to be true unless the property has already been set.
|
// to be true unless the property has already been set.
|
||||||
// Also allow the OS environment variable JAVA_AWT_HEADLESS to set headless state.
|
// Also allow the OS environment variable JAVA_AWT_HEADLESS to set headless state.
|
||||||
|
@ -4005,7 +3815,7 @@ jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_
|
||||||
|
|
||||||
void Arguments::set_shared_spaces_flags() {
|
void Arguments::set_shared_spaces_flags() {
|
||||||
if (DumpSharedSpaces) {
|
if (DumpSharedSpaces) {
|
||||||
if (Arguments::patch_dirs() != NULL) {
|
if (Arguments::get_xpatchprefix() != NULL) {
|
||||||
vm_exit_during_initialization(
|
vm_exit_during_initialization(
|
||||||
"Cannot use the following option when dumping the shared archive", "-Xpatch");
|
"Cannot use the following option when dumping the shared archive", "-Xpatch");
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,17 +41,15 @@ extern "C" {
|
||||||
typedef jint (JNICALL *vfprintf_hook_t)(FILE *fp, const char *format, va_list args) ATTRIBUTE_PRINTF(2, 0);
|
typedef jint (JNICALL *vfprintf_hook_t)(FILE *fp, const char *format, va_list args) ATTRIBUTE_PRINTF(2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forward declarations
|
// PathString is used as:
|
||||||
class ArgumentBootClassPath;
|
// - the underlying value for a SystemProperty
|
||||||
|
// - the path portion of an -Xpatch module/path pair
|
||||||
// PathString is used as the underlying value container for a
|
// - the string that represents the system boot class path, Arguments::_system_boot_class_path.
|
||||||
// SystemProperty and for the string that represents the system
|
|
||||||
// boot class path, Arguments::_system_boot_class_path.
|
|
||||||
class PathString : public CHeapObj<mtArguments> {
|
class PathString : public CHeapObj<mtArguments> {
|
||||||
protected:
|
protected:
|
||||||
char* _value;
|
char* _value;
|
||||||
public:
|
public:
|
||||||
char* value() const { return _value; }
|
char* value() const { return _value; }
|
||||||
|
|
||||||
bool set_value(const char *value) {
|
bool set_value(const char *value) {
|
||||||
if (_value != NULL) {
|
if (_value != NULL) {
|
||||||
|
@ -92,7 +90,6 @@ class PathString : public CHeapObj<mtArguments> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor
|
|
||||||
PathString(const char* value) {
|
PathString(const char* value) {
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
_value = NULL;
|
_value = NULL;
|
||||||
|
@ -101,6 +98,43 @@ class PathString : public CHeapObj<mtArguments> {
|
||||||
strcpy(_value, value);
|
strcpy(_value, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~PathString() {
|
||||||
|
if (_value != NULL) {
|
||||||
|
FreeHeap(_value);
|
||||||
|
_value = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ModuleXPatchPath records the module/path pair as specified to -Xpatch.
|
||||||
|
class ModuleXPatchPath : public CHeapObj<mtInternal> {
|
||||||
|
private:
|
||||||
|
char* _module_name;
|
||||||
|
PathString* _path;
|
||||||
|
public:
|
||||||
|
ModuleXPatchPath(const char* module_name, const char* path) {
|
||||||
|
assert(module_name != NULL && path != NULL, "Invalid module name or path value");
|
||||||
|
size_t len = strlen(module_name) + 1;
|
||||||
|
_module_name = AllocateHeap(len, mtInternal);
|
||||||
|
strncpy(_module_name, module_name, len); // copy the trailing null
|
||||||
|
_path = new PathString(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ModuleXPatchPath() {
|
||||||
|
if (_module_name != NULL) {
|
||||||
|
FreeHeap(_module_name);
|
||||||
|
_module_name = NULL;
|
||||||
|
}
|
||||||
|
if (_path != NULL) {
|
||||||
|
delete _path;
|
||||||
|
_path = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set_path(const char* path) { _path->set_value(path); }
|
||||||
|
inline const char* module_name() const { return _module_name; }
|
||||||
|
inline char* path_string() const { return _path->value(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Element describing System and User (-Dkey=value flags) defined property.
|
// Element describing System and User (-Dkey=value flags) defined property.
|
||||||
|
@ -114,7 +148,7 @@ class SystemProperty : public PathString {
|
||||||
SystemProperty* _next;
|
SystemProperty* _next;
|
||||||
bool _internal;
|
bool _internal;
|
||||||
bool _writeable;
|
bool _writeable;
|
||||||
bool writeable() { return _writeable; }
|
bool writeable() { return _writeable; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Accessors
|
// Accessors
|
||||||
|
@ -314,10 +348,19 @@ class Arguments : AllStatic {
|
||||||
static SystemProperty *_java_class_path;
|
static SystemProperty *_java_class_path;
|
||||||
static SystemProperty *_jdk_boot_class_path_append;
|
static SystemProperty *_jdk_boot_class_path_append;
|
||||||
|
|
||||||
|
// -Xpatch:module=<file>(<pathsep><file>)*
|
||||||
|
// Each element contains the associated module name, path
|
||||||
|
// string pair as specified to -Xpatch.
|
||||||
|
static GrowableArray<ModuleXPatchPath*>* _xpatchprefix;
|
||||||
|
|
||||||
// The constructed value of the system class path after
|
// The constructed value of the system class path after
|
||||||
// argument processing and JVMTI OnLoad additions via
|
// argument processing and JVMTI OnLoad additions via
|
||||||
// calls to AddToBootstrapClassLoaderSearch. This is the
|
// calls to AddToBootstrapClassLoaderSearch. This is the
|
||||||
// final form before ClassLoader::setup_bootstrap_search().
|
// final form before ClassLoader::setup_bootstrap_search().
|
||||||
|
// Note: since -Xpatch is a module name/path pair, the system
|
||||||
|
// boot class path string no longer contains the "prefix" to
|
||||||
|
// the boot class path base piece as it did when
|
||||||
|
// -Xbootclasspath/p was supported.
|
||||||
static PathString *_system_boot_class_path;
|
static PathString *_system_boot_class_path;
|
||||||
|
|
||||||
// temporary: to emit warning if the default ext dirs are not empty.
|
// temporary: to emit warning if the default ext dirs are not empty.
|
||||||
|
@ -373,12 +416,6 @@ class Arguments : AllStatic {
|
||||||
// mark the boot loader's append path observability boundary.
|
// mark the boot loader's append path observability boundary.
|
||||||
static int _bootclassloader_append_index;
|
static int _bootclassloader_append_index;
|
||||||
|
|
||||||
// -Xpatch flag
|
|
||||||
static char** _patch_dirs;
|
|
||||||
static int _patch_dirs_count;
|
|
||||||
static void set_patch_dirs(char** dirs) { _patch_dirs = dirs; }
|
|
||||||
static void set_patch_dirs_count(int count) { _patch_dirs_count = count; }
|
|
||||||
|
|
||||||
// -Xdebug flag
|
// -Xdebug flag
|
||||||
static bool _xdebug_mode;
|
static bool _xdebug_mode;
|
||||||
static void set_xdebug_mode(bool arg) { _xdebug_mode = arg; }
|
static void set_xdebug_mode(bool arg) { _xdebug_mode = arg; }
|
||||||
|
@ -465,8 +502,8 @@ class Arguments : AllStatic {
|
||||||
static jint parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
static jint parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
||||||
const JavaVMInitArgs *java_options_args,
|
const JavaVMInitArgs *java_options_args,
|
||||||
const JavaVMInitArgs *cmd_line_args);
|
const JavaVMInitArgs *cmd_line_args);
|
||||||
static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, ArgumentBootClassPath* bcp_p, bool* bcp_assembly_required_p, Flag::Flags origin);
|
static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* xpatch_javabase, Flag::Flags origin);
|
||||||
static jint finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_assembly_required);
|
static jint finalize_vm_init_args();
|
||||||
static bool is_bad_option(const JavaVMOption* option, jboolean ignore, const char* option_type);
|
static bool is_bad_option(const JavaVMOption* option, jboolean ignore, const char* option_type);
|
||||||
|
|
||||||
static bool is_bad_option(const JavaVMOption* option, jboolean ignore) {
|
static bool is_bad_option(const JavaVMOption* option, jboolean ignore) {
|
||||||
|
@ -637,13 +674,12 @@ class Arguments : AllStatic {
|
||||||
return _bootclassloader_append_index;
|
return _bootclassloader_append_index;
|
||||||
}
|
}
|
||||||
static void set_bootclassloader_append_index(int value) {
|
static void set_bootclassloader_append_index(int value) {
|
||||||
_bootclassloader_append_index = value;
|
// Set only if the index has not been set yet
|
||||||
|
if (_bootclassloader_append_index == -1) {
|
||||||
|
_bootclassloader_append_index = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -Xpatch
|
|
||||||
static char** patch_dirs() { return _patch_dirs; }
|
|
||||||
static int patch_dirs_count() { return _patch_dirs_count; }
|
|
||||||
|
|
||||||
// -Xrun
|
// -Xrun
|
||||||
static AgentLibrary* libraries() { return _libraryList.first(); }
|
static AgentLibrary* libraries() { return _libraryList.first(); }
|
||||||
static bool init_libraries_at_startup() { return !_libraryList.is_empty(); }
|
static bool init_libraries_at_startup() { return !_libraryList.is_empty(); }
|
||||||
|
@ -701,8 +737,8 @@ class Arguments : AllStatic {
|
||||||
static void set_library_path(const char *value) { _java_library_path->set_value(value); }
|
static void set_library_path(const char *value) { _java_library_path->set_value(value); }
|
||||||
static void set_ext_dirs(char *value) { _ext_dirs = os::strdup_check_oom(value); }
|
static void set_ext_dirs(char *value) { _ext_dirs = os::strdup_check_oom(value); }
|
||||||
|
|
||||||
// Set up of the underlying system boot class path
|
// Set up the underlying pieces of the system boot class path
|
||||||
static void set_jdkbootclasspath_append();
|
static void add_xpatchprefix(const char *module_name, const char *path, bool* xpatch_javabase);
|
||||||
static void set_sysclasspath(const char *value) {
|
static void set_sysclasspath(const char *value) {
|
||||||
_system_boot_class_path->set_value(value);
|
_system_boot_class_path->set_value(value);
|
||||||
set_jdkbootclasspath_append();
|
set_jdkbootclasspath_append();
|
||||||
|
@ -711,11 +747,15 @@ class Arguments : AllStatic {
|
||||||
_system_boot_class_path->append_value(value);
|
_system_boot_class_path->append_value(value);
|
||||||
set_jdkbootclasspath_append();
|
set_jdkbootclasspath_append();
|
||||||
}
|
}
|
||||||
|
static void set_jdkbootclasspath_append();
|
||||||
|
|
||||||
static char* get_java_home() { return _java_home->value(); }
|
static GrowableArray<ModuleXPatchPath*>* get_xpatchprefix() { return _xpatchprefix; }
|
||||||
static char* get_dll_dir() { return _sun_boot_library_path->value(); }
|
|
||||||
static char* get_sysclasspath() { return _system_boot_class_path->value(); }
|
static char* get_sysclasspath() { return _system_boot_class_path->value(); }
|
||||||
static char* get_ext_dirs() { return _ext_dirs; }
|
static char* get_jdk_boot_class_path_append() { return _jdk_boot_class_path_append->value(); }
|
||||||
|
|
||||||
|
static char* get_java_home() { return _java_home->value(); }
|
||||||
|
static char* get_dll_dir() { return _sun_boot_library_path->value(); }
|
||||||
|
static char* get_ext_dirs() { return _ext_dirs; }
|
||||||
static char* get_appclasspath() { return _java_class_path->value(); }
|
static char* get_appclasspath() { return _java_class_path->value(); }
|
||||||
static void fix_appclasspath();
|
static void fix_appclasspath();
|
||||||
|
|
||||||
|
|
|
@ -1418,10 +1418,6 @@ public:
|
||||||
product(bool, StressLdcRewrite, false, \
|
product(bool, StressLdcRewrite, false, \
|
||||||
"Force ldc -> ldc_w rewrite during RedefineClasses") \
|
"Force ldc -> ldc_w rewrite during RedefineClasses") \
|
||||||
\
|
\
|
||||||
product(uintx, TraceRedefineClasses, 0, \
|
|
||||||
"Trace level for JVMTI RedefineClasses") \
|
|
||||||
range(0, 0xFFFFFFFF) \
|
|
||||||
\
|
|
||||||
/* change to false by default sometime after Mustang */ \
|
/* change to false by default sometime after Mustang */ \
|
||||||
product(bool, VerifyMergedCPBytecodes, true, \
|
product(bool, VerifyMergedCPBytecodes, true, \
|
||||||
"Verify bytecodes after RedefineClasses constant pool merging") \
|
"Verify bytecodes after RedefineClasses constant pool merging") \
|
||||||
|
@ -2070,6 +2066,9 @@ public:
|
||||||
notproduct(bool, VerboseInternalVMTests, false, \
|
notproduct(bool, VerboseInternalVMTests, false, \
|
||||||
"Turn on logging for internal VM tests.") \
|
"Turn on logging for internal VM tests.") \
|
||||||
\
|
\
|
||||||
|
product(bool, ExecutingUnitTests, false, \
|
||||||
|
"Whether the JVM is running unit tests or not") \
|
||||||
|
\
|
||||||
product_pd(bool, UseTLAB, "Use thread-local object allocation") \
|
product_pd(bool, UseTLAB, "Use thread-local object allocation") \
|
||||||
\
|
\
|
||||||
product_pd(bool, ResizeTLAB, \
|
product_pd(bool, ResizeTLAB, \
|
||||||
|
|
|
@ -52,7 +52,8 @@ void SuspendibleThreadSet_init() NOT_ALL_GCS_RETURN;
|
||||||
// Initialization done by Java thread in init_globals()
|
// Initialization done by Java thread in init_globals()
|
||||||
void management_init();
|
void management_init();
|
||||||
void bytecodes_init();
|
void bytecodes_init();
|
||||||
void classLoader_init();
|
void classLoader_init1();
|
||||||
|
void classLoader_init2(); // note: ClassLoader need 2-phase init
|
||||||
void compilationPolicy_init();
|
void compilationPolicy_init();
|
||||||
void codeCache_init();
|
void codeCache_init();
|
||||||
void VM_Version_init();
|
void VM_Version_init();
|
||||||
|
@ -102,7 +103,7 @@ jint init_globals() {
|
||||||
HandleMark hm;
|
HandleMark hm;
|
||||||
management_init();
|
management_init();
|
||||||
bytecodes_init();
|
bytecodes_init();
|
||||||
classLoader_init();
|
classLoader_init1();
|
||||||
compilationPolicy_init();
|
compilationPolicy_init();
|
||||||
codeCache_init();
|
codeCache_init();
|
||||||
CodeCacheExtensions::initialize();
|
CodeCacheExtensions::initialize();
|
||||||
|
@ -116,6 +117,7 @@ jint init_globals() {
|
||||||
if (status != JNI_OK)
|
if (status != JNI_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
classLoader_init2(); // after SymbolTable creation, set up -Xpatch entries
|
||||||
CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::Universe);
|
CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::Universe);
|
||||||
interpreter_init(); // before any methods loaded
|
interpreter_init(); // before any methods loaded
|
||||||
CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::Interpreter);
|
CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::Interpreter);
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "prims/forte.hpp"
|
#include "prims/forte.hpp"
|
||||||
#include "prims/jvmtiExport.hpp"
|
#include "prims/jvmtiExport.hpp"
|
||||||
#include "prims/jvmtiRedefineClassesTrace.hpp"
|
|
||||||
#include "prims/methodHandles.hpp"
|
#include "prims/methodHandles.hpp"
|
||||||
#include "prims/nativeLookup.hpp"
|
#include "prims/nativeLookup.hpp"
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
|
@ -603,27 +602,18 @@ void SharedRuntime::throw_and_post_jvmti_exception(JavaThread *thread, Symbol* n
|
||||||
}
|
}
|
||||||
|
|
||||||
// The interpreter code to call this tracing function is only
|
// The interpreter code to call this tracing function is only
|
||||||
// called/generated when TraceRedefineClasses has the right bits
|
// called/generated when UL is on for redefine, class and has the right level
|
||||||
// set. Since obsolete methods are never compiled, we don't have
|
// and tags. Since obsolete methods are never compiled, we don't have
|
||||||
// to modify the compilers to generate calls to this function.
|
// to modify the compilers to generate calls to this function.
|
||||||
//
|
//
|
||||||
JRT_LEAF(int, SharedRuntime::rc_trace_method_entry(
|
JRT_LEAF(int, SharedRuntime::rc_trace_method_entry(
|
||||||
JavaThread* thread, Method* method))
|
JavaThread* thread, Method* method))
|
||||||
assert(RC_TRACE_IN_RANGE(0x00001000, 0x00002000), "wrong call");
|
|
||||||
|
|
||||||
if (method->is_obsolete()) {
|
if (method->is_obsolete()) {
|
||||||
// We are calling an obsolete method, but this is not necessarily
|
// We are calling an obsolete method, but this is not necessarily
|
||||||
// an error. Our method could have been redefined just after we
|
// an error. Our method could have been redefined just after we
|
||||||
// fetched the Method* from the constant pool.
|
// fetched the Method* from the constant pool.
|
||||||
|
ResourceMark rm;
|
||||||
// RC_TRACE macro has an embedded ResourceMark
|
log_trace(redefine, class, obsolete)("calling obsolete method '%s'", method->name_and_sig_as_C_string());
|
||||||
RC_TRACE_WITH_THREAD(0x00001000, thread,
|
|
||||||
("calling obsolete method '%s'",
|
|
||||||
method->name_and_sig_as_C_string()));
|
|
||||||
if (RC_TRACE_ENABLED(0x00002000)) {
|
|
||||||
// this option is provided to debug calls to obsolete methods
|
|
||||||
guarantee(false, "faulting at call to an obsolete method.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
JRT_END
|
JRT_END
|
||||||
|
@ -1762,6 +1752,21 @@ methodHandle SharedRuntime::reresolve_call_site(JavaThread *thread, TRAPS) {
|
||||||
return callee_method;
|
return callee_method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
address SharedRuntime::handle_unsafe_access(JavaThread* thread, address next_pc) {
|
||||||
|
// The faulting unsafe accesses should be changed to throw the error
|
||||||
|
// synchronously instead. Meanwhile the faulting instruction will be
|
||||||
|
// skipped over (effectively turning it into a no-op) and an
|
||||||
|
// asynchronous exception will be raised which the thread will
|
||||||
|
// handle at a later point. If the instruction is a load it will
|
||||||
|
// return garbage.
|
||||||
|
|
||||||
|
// Request an async exception.
|
||||||
|
thread->set_pending_unsafe_access_error();
|
||||||
|
|
||||||
|
// Return address of next instruction to execute.
|
||||||
|
return next_pc;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void SharedRuntime::check_member_name_argument_is_last_argument(const methodHandle& method,
|
void SharedRuntime::check_member_name_argument_is_last_argument(const methodHandle& method,
|
||||||
const BasicType* sig_bt,
|
const BasicType* sig_bt,
|
||||||
|
|
|
@ -522,6 +522,8 @@ class SharedRuntime: AllStatic {
|
||||||
static address handle_wrong_method_abstract(JavaThread* thread);
|
static address handle_wrong_method_abstract(JavaThread* thread);
|
||||||
static address handle_wrong_method_ic_miss(JavaThread* thread);
|
static address handle_wrong_method_ic_miss(JavaThread* thread);
|
||||||
|
|
||||||
|
static address handle_unsafe_access(JavaThread* thread, address next_pc);
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
|
||||||
// Collect and print inline cache miss statistics
|
// Collect and print inline cache miss statistics
|
||||||
|
|
|
@ -55,7 +55,6 @@ address StubRoutines::_throw_IncompatibleClassChangeError_entry = NULL;
|
||||||
address StubRoutines::_throw_NullPointerException_at_call_entry = NULL;
|
address StubRoutines::_throw_NullPointerException_at_call_entry = NULL;
|
||||||
address StubRoutines::_throw_StackOverflowError_entry = NULL;
|
address StubRoutines::_throw_StackOverflowError_entry = NULL;
|
||||||
address StubRoutines::_throw_delayed_StackOverflowError_entry = NULL;
|
address StubRoutines::_throw_delayed_StackOverflowError_entry = NULL;
|
||||||
address StubRoutines::_handler_for_unsafe_access_entry = NULL;
|
|
||||||
jint StubRoutines::_verify_oop_count = 0;
|
jint StubRoutines::_verify_oop_count = 0;
|
||||||
address StubRoutines::_verify_oop_subroutine_entry = NULL;
|
address StubRoutines::_verify_oop_subroutine_entry = NULL;
|
||||||
address StubRoutines::_atomic_xchg_entry = NULL;
|
address StubRoutines::_atomic_xchg_entry = NULL;
|
||||||
|
|
|
@ -111,7 +111,6 @@ class StubRoutines: AllStatic {
|
||||||
static address _throw_NullPointerException_at_call_entry;
|
static address _throw_NullPointerException_at_call_entry;
|
||||||
static address _throw_StackOverflowError_entry;
|
static address _throw_StackOverflowError_entry;
|
||||||
static address _throw_delayed_StackOverflowError_entry;
|
static address _throw_delayed_StackOverflowError_entry;
|
||||||
static address _handler_for_unsafe_access_entry;
|
|
||||||
|
|
||||||
static address _atomic_xchg_entry;
|
static address _atomic_xchg_entry;
|
||||||
static address _atomic_xchg_ptr_entry;
|
static address _atomic_xchg_ptr_entry;
|
||||||
|
@ -288,10 +287,6 @@ class StubRoutines: AllStatic {
|
||||||
static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; }
|
static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; }
|
||||||
static address throw_delayed_StackOverflowError_entry() { return _throw_delayed_StackOverflowError_entry; }
|
static address throw_delayed_StackOverflowError_entry() { return _throw_delayed_StackOverflowError_entry; }
|
||||||
|
|
||||||
// Exceptions during unsafe access - should throw Java exception rather
|
|
||||||
// than crash.
|
|
||||||
static address handler_for_unsafe_access() { return _handler_for_unsafe_access_entry; }
|
|
||||||
|
|
||||||
static address atomic_xchg_entry() { return _atomic_xchg_entry; }
|
static address atomic_xchg_entry() { return _atomic_xchg_entry; }
|
||||||
static address atomic_xchg_ptr_entry() { return _atomic_xchg_ptr_entry; }
|
static address atomic_xchg_ptr_entry() { return _atomic_xchg_ptr_entry; }
|
||||||
static address atomic_store_entry() { return _atomic_store_entry; }
|
static address atomic_store_entry() { return _atomic_store_entry; }
|
||||||
|
|
|
@ -317,14 +317,6 @@ class vframeStreamCommon : StackObj {
|
||||||
intptr_t* frame_id() const { return _frame.id(); }
|
intptr_t* frame_id() const { return _frame.id(); }
|
||||||
address frame_pc() const { return _frame.pc(); }
|
address frame_pc() const { return _frame.pc(); }
|
||||||
|
|
||||||
javaVFrame* java_frame() {
|
|
||||||
vframe* vf = vframe::new_vframe(&_frame, &_reg_map, _thread);
|
|
||||||
if (vf->is_java_frame()) {
|
|
||||||
return (javaVFrame*)vf;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CodeBlob* cb() const { return _frame.cb(); }
|
CodeBlob* cb() const { return _frame.cb(); }
|
||||||
CompiledMethod* nm() const {
|
CompiledMethod* nm() const {
|
||||||
assert( cb() != NULL && cb()->is_compiled(), "usage");
|
assert( cb() != NULL && cb()->is_compiled(), "usage");
|
||||||
|
|
|
@ -1609,8 +1609,8 @@ JVM_ENTRY(void, jmm_SetVMGlobal(JNIEnv *env, jstring flag_name, jvalue new_value
|
||||||
}
|
}
|
||||||
char* name = java_lang_String::as_utf8_string(fn);
|
char* name = java_lang_String::as_utf8_string(fn);
|
||||||
|
|
||||||
FormatBuffer<80> err_msg("%s", "");
|
FormatBuffer<80> error_msg("%s", "");
|
||||||
int succeed = WriteableFlags::set_flag(name, new_value, Flag::MANAGEMENT, err_msg);
|
int succeed = WriteableFlags::set_flag(name, new_value, Flag::MANAGEMENT, error_msg);
|
||||||
|
|
||||||
if (succeed != Flag::SUCCESS) {
|
if (succeed != Flag::SUCCESS) {
|
||||||
if (succeed == Flag::MISSING_VALUE) {
|
if (succeed == Flag::MISSING_VALUE) {
|
||||||
|
@ -1619,7 +1619,7 @@ JVM_ENTRY(void, jmm_SetVMGlobal(JNIEnv *env, jstring flag_name, jvalue new_value
|
||||||
} else {
|
} else {
|
||||||
// all the other errors are reported as IAE with the appropriate error message
|
// all the other errors are reported as IAE with the appropriate error message
|
||||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
||||||
err_msg.buffer());
|
error_msg.buffer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(succeed == Flag::SUCCESS, "Setting flag should succeed");
|
assert(succeed == Flag::SUCCESS, "Setting flag should succeed");
|
||||||
|
|
|
@ -58,6 +58,8 @@
|
||||||
#include "trace/tracing.hpp"
|
#include "trace/tracing.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifndef ASSERT
|
#ifndef ASSERT
|
||||||
# ifdef _DEBUG
|
# ifdef _DEBUG
|
||||||
// NOTE: don't turn the lines below into a comment -- if you're getting
|
// NOTE: don't turn the lines below into a comment -- if you're getting
|
||||||
|
@ -187,7 +189,7 @@ bool error_is_suppressed(const char* file_name, int line_no) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_error_reported()) {
|
if (!is_error_reported() && !SuppressFatalErrorMessage) {
|
||||||
// print a friendly hint:
|
// print a friendly hint:
|
||||||
fdStream out(defaultStream::output_fd());
|
fdStream out(defaultStream::output_fd());
|
||||||
out.print_raw_cr("# To suppress the following error report, specify this argument");
|
out.print_raw_cr("# To suppress the following error report, specify this argument");
|
||||||
|
@ -262,6 +264,21 @@ void report_unimplemented(const char* file, int line) {
|
||||||
report_vm_error(file, line, "Unimplemented()");
|
report_vm_error(file, line, "Unimplemented()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
bool is_executing_unit_tests() {
|
||||||
|
return ExecutingUnitTests;
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_assert_msg(const char* msg, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, msg);
|
||||||
|
|
||||||
|
fprintf(stderr, "assert failed: %s\n", err_msg(FormatBufferDummy(), msg, ap).buffer());
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
#endif // ASSERT
|
||||||
|
|
||||||
void report_untested(const char* file, int line, const char* message) {
|
void report_untested(const char* file, int line, const char* message) {
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
warning("Untested: %s in %s: %d\n", message, file, line);
|
warning("Untested: %s in %s: %d\n", message, file, line);
|
||||||
|
|
|
@ -46,11 +46,15 @@ class FormatBufferResource : public FormatBufferBase {
|
||||||
FormatBufferResource(const char * format, ...) ATTRIBUTE_PRINTF(2, 3);
|
FormatBufferResource(const char * format, ...) ATTRIBUTE_PRINTF(2, 3);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FormatBufferDummy {};
|
||||||
|
|
||||||
// Use stack for buffer
|
// Use stack for buffer
|
||||||
template <size_t bufsz = FormatBufferBase::BufferSize>
|
template <size_t bufsz = FormatBufferBase::BufferSize>
|
||||||
class FormatBuffer : public FormatBufferBase {
|
class FormatBuffer : public FormatBufferBase {
|
||||||
public:
|
public:
|
||||||
inline FormatBuffer(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
|
inline FormatBuffer(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
|
||||||
|
// since va_list is unspecified type (can be char*), we use FormatBufferDummy to disambiguate these constructors
|
||||||
|
inline FormatBuffer(FormatBufferDummy dummy, const char* format, va_list ap) ATTRIBUTE_PRINTF(3, 0);
|
||||||
inline void append(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
|
inline void append(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
|
||||||
inline void print(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
|
inline void print(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);
|
||||||
inline void printv(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0);
|
inline void printv(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0);
|
||||||
|
@ -74,6 +78,11 @@ FormatBuffer<bufsz>::FormatBuffer(const char * format, ...) : FormatBufferBase(_
|
||||||
va_end(argp);
|
va_end(argp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <size_t bufsz>
|
||||||
|
FormatBuffer<bufsz>::FormatBuffer(FormatBufferDummy dummy, const char * format, va_list ap) : FormatBufferBase(_buffer) {
|
||||||
|
jio_vsnprintf(_buf, bufsz, format, ap);
|
||||||
|
}
|
||||||
|
|
||||||
template <size_t bufsz>
|
template <size_t bufsz>
|
||||||
FormatBuffer<bufsz>::FormatBuffer() : FormatBufferBase(_buffer) {
|
FormatBuffer<bufsz>::FormatBuffer() : FormatBufferBase(_buffer) {
|
||||||
_buf[0] = '\0';
|
_buf[0] = '\0';
|
||||||
|
@ -119,11 +128,13 @@ typedef FormatBuffer<> err_msg;
|
||||||
#define vmassert(p, ...) \
|
#define vmassert(p, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (!(p)) { \
|
if (!(p)) { \
|
||||||
|
if (is_executing_unit_tests()) { \
|
||||||
|
report_assert_msg(__VA_ARGS__); \
|
||||||
|
} \
|
||||||
report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", __VA_ARGS__); \
|
report_vm_error(__FILE__, __LINE__, "assert(" #p ") failed", __VA_ARGS__); \
|
||||||
BREAKPOINT; \
|
BREAKPOINT; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// For backward compatibility.
|
// For backward compatibility.
|
||||||
|
@ -210,10 +221,16 @@ void report_vm_error(const char* file, int line, const char* error_msg);
|
||||||
// ATTRIBUTE_PRINTF works with gcc >= 4.8 and any other compiler.
|
// ATTRIBUTE_PRINTF works with gcc >= 4.8 and any other compiler.
|
||||||
void report_vm_error(const char* file, int line, const char* error_msg,
|
void report_vm_error(const char* file, int line, const char* error_msg,
|
||||||
const char* detail_fmt, ...) ATTRIBUTE_PRINTF(4, 5);
|
const char* detail_fmt, ...) ATTRIBUTE_PRINTF(4, 5);
|
||||||
|
#ifdef ASSERT
|
||||||
|
void report_assert_msg(const char* msg, ...) ATTRIBUTE_PRINTF(1, 2);
|
||||||
|
#endif // ASSERT
|
||||||
#else
|
#else
|
||||||
// GCC < 4.8 warns because of empty format string. Warning can not be switched off selectively.
|
// GCC < 4.8 warns because of empty format string. Warning can not be switched off selectively.
|
||||||
void report_vm_error(const char* file, int line, const char* error_msg,
|
void report_vm_error(const char* file, int line, const char* error_msg,
|
||||||
const char* detail_fmt, ...);
|
const char* detail_fmt, ...);
|
||||||
|
#ifdef ASSERT
|
||||||
|
void report_assert_msg(const char* msg, ...);
|
||||||
|
#endif // ASSERT
|
||||||
#endif
|
#endif
|
||||||
void report_vm_status_error(const char* file, int line, const char* error_msg,
|
void report_vm_status_error(const char* file, int line, const char* error_msg,
|
||||||
int status, const char* detail);
|
int status, const char* detail);
|
||||||
|
@ -225,6 +242,11 @@ void report_should_not_reach_here(const char* file, int line);
|
||||||
void report_unimplemented(const char* file, int line);
|
void report_unimplemented(const char* file, int line);
|
||||||
void report_untested(const char* file, int line, const char* message);
|
void report_untested(const char* file, int line, const char* message);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
// unit test support
|
||||||
|
bool is_executing_unit_tests();
|
||||||
|
#endif // ASSERT
|
||||||
|
|
||||||
void warning(const char* format, ...) ATTRIBUTE_PRINTF(1, 2);
|
void warning(const char* format, ...) ATTRIBUTE_PRINTF(1, 2);
|
||||||
|
|
||||||
// Compile-time asserts. Cond must be a compile-time constant expression that
|
// Compile-time asserts. Cond must be a compile-time constant expression that
|
||||||
|
|
|
@ -290,8 +290,8 @@ const char* VMError::_current_step_info;
|
||||||
|
|
||||||
void VMError::report(outputStream* st, bool _verbose) {
|
void VMError::report(outputStream* st, bool _verbose) {
|
||||||
|
|
||||||
# define BEGIN if (_current_step == 0) { _current_step = 1;
|
# define BEGIN if (_current_step == 0) { _current_step = __LINE__;
|
||||||
# define STEP(n, s) } if (_current_step < n) { _current_step = n; _current_step_info = s;
|
# define STEP(s) } if (_current_step < __LINE__) { _current_step = __LINE__; _current_step_info = s;
|
||||||
# define END }
|
# define END }
|
||||||
|
|
||||||
// don't allocate large buffer on stack
|
// don't allocate large buffer on stack
|
||||||
|
@ -299,7 +299,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
STEP(10, "(printing fatal error message)")
|
STEP("printing fatal error message")
|
||||||
|
|
||||||
st->print_cr("#");
|
st->print_cr("#");
|
||||||
if (should_report_bug(_id)) {
|
if (should_report_bug(_id)) {
|
||||||
|
@ -314,21 +314,21 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
|
|
||||||
// test secondary error handling. Test it twice, to test that resetting
|
// test secondary error handling. Test it twice, to test that resetting
|
||||||
// error handler after a secondary crash works.
|
// error handler after a secondary crash works.
|
||||||
STEP(20, "(test secondary crash 1)")
|
STEP("test secondary crash 1")
|
||||||
if (_verbose && TestCrashInErrorHandler != 0) {
|
if (_verbose && TestCrashInErrorHandler != 0) {
|
||||||
st->print_cr("Will crash now (TestCrashInErrorHandler=" UINTX_FORMAT ")...",
|
st->print_cr("Will crash now (TestCrashInErrorHandler=" UINTX_FORMAT ")...",
|
||||||
TestCrashInErrorHandler);
|
TestCrashInErrorHandler);
|
||||||
controlled_crash(TestCrashInErrorHandler);
|
controlled_crash(TestCrashInErrorHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(30, "(test secondary crash 2)")
|
STEP("test secondary crash 2")
|
||||||
if (_verbose && TestCrashInErrorHandler != 0) {
|
if (_verbose && TestCrashInErrorHandler != 0) {
|
||||||
st->print_cr("Will crash now (TestCrashInErrorHandler=" UINTX_FORMAT ")...",
|
st->print_cr("Will crash now (TestCrashInErrorHandler=" UINTX_FORMAT ")...",
|
||||||
TestCrashInErrorHandler);
|
TestCrashInErrorHandler);
|
||||||
controlled_crash(TestCrashInErrorHandler);
|
controlled_crash(TestCrashInErrorHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(40, "(test safefetch in error handler)")
|
STEP("test safefetch in error handler")
|
||||||
// test whether it is safe to use SafeFetch32 in Crash Handler. Test twice
|
// test whether it is safe to use SafeFetch32 in Crash Handler. Test twice
|
||||||
// to test that resetting the signal handler works correctly.
|
// to test that resetting the signal handler works correctly.
|
||||||
if (_verbose && TestSafeFetchInErrorHandler) {
|
if (_verbose && TestSafeFetchInErrorHandler) {
|
||||||
|
@ -349,7 +349,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
}
|
}
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
||||||
STEP(50, "(printing type of error)")
|
STEP("printing type of error")
|
||||||
|
|
||||||
switch(_id) {
|
switch(_id) {
|
||||||
case OOM_MALLOC_ERROR:
|
case OOM_MALLOC_ERROR:
|
||||||
|
@ -384,7 +384,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(60, "(printing exception/signal name)")
|
STEP("printing exception/signal name")
|
||||||
|
|
||||||
st->print_cr("#");
|
st->print_cr("#");
|
||||||
st->print("# ");
|
st->print("# ");
|
||||||
|
@ -414,14 +414,14 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(70, "(printing current thread and pid)")
|
STEP("printing current thread and pid")
|
||||||
|
|
||||||
// process id, thread id
|
// process id, thread id
|
||||||
st->print(", pid=%d", os::current_process_id());
|
st->print(", pid=%d", os::current_process_id());
|
||||||
st->print(", tid=" UINTX_FORMAT, os::current_thread_id());
|
st->print(", tid=" UINTX_FORMAT, os::current_thread_id());
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
STEP(80, "(printing error message)")
|
STEP("printing error message")
|
||||||
|
|
||||||
if (should_report_bug(_id)) { // already printed the message.
|
if (should_report_bug(_id)) { // already printed the message.
|
||||||
// error message
|
// error message
|
||||||
|
@ -432,11 +432,11 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(90, "(printing Java version string)")
|
STEP("printing Java version string")
|
||||||
|
|
||||||
report_vm_version(st, buf, sizeof(buf));
|
report_vm_version(st, buf, sizeof(buf));
|
||||||
|
|
||||||
STEP(100, "(printing problematic frame)")
|
STEP("printing problematic frame")
|
||||||
|
|
||||||
// Print current frame if we have a context (i.e. it's a crash)
|
// Print current frame if we have a context (i.e. it's a crash)
|
||||||
if (_context) {
|
if (_context) {
|
||||||
|
@ -448,7 +448,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->print_cr("#");
|
st->print_cr("#");
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(110, "(printing core file information)")
|
STEP("printing core file information")
|
||||||
st->print("# ");
|
st->print("# ");
|
||||||
if (CreateCoredumpOnCrash) {
|
if (CreateCoredumpOnCrash) {
|
||||||
if (coredump_status) {
|
if (coredump_status) {
|
||||||
|
@ -462,13 +462,13 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
st->print_cr("#");
|
st->print_cr("#");
|
||||||
|
|
||||||
STEP(120, "(printing bug submit message)")
|
STEP("printing bug submit message")
|
||||||
|
|
||||||
if (should_report_bug(_id) && _verbose) {
|
if (should_report_bug(_id) && _verbose) {
|
||||||
print_bug_submit_message(st, _thread);
|
print_bug_submit_message(st, _thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(130, "(printing summary)" )
|
STEP("printing summary")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
|
@ -476,7 +476,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(140, "(printing VM option summary)" )
|
STEP("printing VM option summary")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
// VM options
|
// VM options
|
||||||
|
@ -484,20 +484,20 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(150, "(printing summary machine and OS info)")
|
STEP("printing summary machine and OS info")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
os::print_summary_info(st, buf, sizeof(buf));
|
os::print_summary_info(st, buf, sizeof(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STEP(160, "(printing date and time)" )
|
STEP("printing date and time")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
os::print_date_and_time(st, buf, sizeof(buf));
|
os::print_date_and_time(st, buf, sizeof(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(170, "(printing thread)" )
|
STEP("printing thread")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
|
@ -505,7 +505,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(180, "(printing current thread)" )
|
STEP("printing current thread")
|
||||||
|
|
||||||
// current thread
|
// current thread
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
|
@ -519,7 +519,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(190, "(printing current compile task)" )
|
STEP("printing current compile task")
|
||||||
|
|
||||||
if (_verbose && _thread && _thread->is_Compiler_thread()) {
|
if (_verbose && _thread && _thread->is_Compiler_thread()) {
|
||||||
CompilerThread* t = (CompilerThread*)_thread;
|
CompilerThread* t = (CompilerThread*)_thread;
|
||||||
|
@ -532,7 +532,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STEP(200, "(printing stack bounds)" )
|
STEP("printing stack bounds")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
st->print("Stack: ");
|
st->print("Stack: ");
|
||||||
|
@ -563,7 +563,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(210, "(printing native stack)" )
|
STEP("printing native stack")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) {
|
if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) {
|
||||||
|
@ -577,13 +577,13 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(220, "(printing Java stack)" )
|
STEP("printing Java stack")
|
||||||
|
|
||||||
if (_verbose && _thread && _thread->is_Java_thread()) {
|
if (_verbose && _thread && _thread->is_Java_thread()) {
|
||||||
print_stack_trace(st, (JavaThread*)_thread, buf, sizeof(buf));
|
print_stack_trace(st, (JavaThread*)_thread, buf, sizeof(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(230, "(printing target Java thread stack)" )
|
STEP("printing target Java thread stack")
|
||||||
|
|
||||||
// printing Java thread stack trace if it is involved in GC crash
|
// printing Java thread stack trace if it is involved in GC crash
|
||||||
if (_verbose && _thread && (_thread->is_Named_thread())) {
|
if (_verbose && _thread && (_thread->is_Named_thread())) {
|
||||||
|
@ -594,7 +594,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(240, "(printing siginfo)" )
|
STEP("printing siginfo")
|
||||||
|
|
||||||
// signal no, signal code, address that caused the fault
|
// signal no, signal code, address that caused the fault
|
||||||
if (_verbose && _siginfo) {
|
if (_verbose && _siginfo) {
|
||||||
|
@ -603,7 +603,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(245, "(CDS archive access warning)" )
|
STEP("CDS archive access warning")
|
||||||
|
|
||||||
// Print an explicit hint if we crashed on access to the CDS archive.
|
// Print an explicit hint if we crashed on access to the CDS archive.
|
||||||
if (_verbose && _siginfo) {
|
if (_verbose && _siginfo) {
|
||||||
|
@ -611,7 +611,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(250, "(printing register info)")
|
STEP("printing register info")
|
||||||
|
|
||||||
// decode register contents if possible
|
// decode register contents if possible
|
||||||
if (_verbose && _context && Universe::is_fully_initialized()) {
|
if (_verbose && _context && Universe::is_fully_initialized()) {
|
||||||
|
@ -619,7 +619,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(260, "(printing registers, top of stack, instructions near pc)")
|
STEP("printing registers, top of stack, instructions near pc")
|
||||||
|
|
||||||
// registers, top of stack, instructions near pc
|
// registers, top of stack, instructions near pc
|
||||||
if (_verbose && _context) {
|
if (_verbose && _context) {
|
||||||
|
@ -627,7 +627,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(265, "(printing code blob if possible)")
|
STEP("printing code blob if possible")
|
||||||
|
|
||||||
if (_verbose && _context) {
|
if (_verbose && _context) {
|
||||||
CodeBlob* cb = CodeCache::find_blob(_pc);
|
CodeBlob* cb = CodeCache::find_blob(_pc);
|
||||||
|
@ -652,7 +652,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(270, "(printing VM operation)" )
|
STEP("printing VM operation")
|
||||||
|
|
||||||
if (_verbose && _thread && _thread->is_VM_thread()) {
|
if (_verbose && _thread && _thread->is_VM_thread()) {
|
||||||
VMThread* t = (VMThread*)_thread;
|
VMThread* t = (VMThread*)_thread;
|
||||||
|
@ -664,7 +664,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(280, "(printing process)" )
|
STEP("printing process")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
|
@ -672,7 +672,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(290, "(printing all threads)" )
|
STEP("printing all threads")
|
||||||
|
|
||||||
// all threads
|
// all threads
|
||||||
if (_verbose && _thread) {
|
if (_verbose && _thread) {
|
||||||
|
@ -680,7 +680,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(300, "(printing VM state)" )
|
STEP("printing VM state")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
// Safepoint state
|
// Safepoint state
|
||||||
|
@ -702,7 +702,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(310, "(printing owned locks on error)" )
|
STEP("printing owned locks on error")
|
||||||
|
|
||||||
// mutexes/monitors that currently have an owner
|
// mutexes/monitors that currently have an owner
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
|
@ -710,7 +710,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(320, "(printing number of OutOfMemoryError and StackOverflow exceptions)")
|
STEP("printing number of OutOfMemoryError and StackOverflow exceptions")
|
||||||
|
|
||||||
if (_verbose && Exceptions::has_exception_counts()) {
|
if (_verbose && Exceptions::has_exception_counts()) {
|
||||||
st->print_cr("OutOfMemory and StackOverflow Exception counts:");
|
st->print_cr("OutOfMemory and StackOverflow Exception counts:");
|
||||||
|
@ -718,7 +718,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(330, "(printing compressed oops mode")
|
STEP("printing compressed oops mode")
|
||||||
|
|
||||||
if (_verbose && UseCompressedOops) {
|
if (_verbose && UseCompressedOops) {
|
||||||
Universe::print_compressed_oops_mode(st);
|
Universe::print_compressed_oops_mode(st);
|
||||||
|
@ -728,7 +728,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(340, "(printing heap information)" )
|
STEP("printing heap information")
|
||||||
|
|
||||||
if (_verbose && Universe::is_fully_initialized()) {
|
if (_verbose && Universe::is_fully_initialized()) {
|
||||||
Universe::heap()->print_on_error(st);
|
Universe::heap()->print_on_error(st);
|
||||||
|
@ -737,7 +737,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(350, "(printing code cache information)" )
|
STEP("printing code cache information")
|
||||||
|
|
||||||
if (_verbose && Universe::is_fully_initialized()) {
|
if (_verbose && Universe::is_fully_initialized()) {
|
||||||
// print code cache information before vm abort
|
// print code cache information before vm abort
|
||||||
|
@ -745,14 +745,14 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(360, "(printing ring buffers)" )
|
STEP("printing ring buffers")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
Events::print_all(st);
|
Events::print_all(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(370, "(printing dynamic libraries)" )
|
STEP("printing dynamic libraries")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
// dynamic libraries, or memory map
|
// dynamic libraries, or memory map
|
||||||
|
@ -760,7 +760,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(380, "(printing VM options)" )
|
STEP("printing VM options")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
// VM options
|
// VM options
|
||||||
|
@ -768,40 +768,40 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(390, "(printing warning if internal testing API used)" )
|
STEP("printing warning if internal testing API used")
|
||||||
|
|
||||||
if (WhiteBox::used()) {
|
if (WhiteBox::used()) {
|
||||||
st->print_cr("Unsupported internal testing APIs have been used.");
|
st->print_cr("Unsupported internal testing APIs have been used.");
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(395, "(printing log configuration)")
|
STEP("printing log configuration")
|
||||||
if (_verbose){
|
if (_verbose){
|
||||||
st->print_cr("Logging:");
|
st->print_cr("Logging:");
|
||||||
LogConfiguration::describe_current_configuration(st);
|
LogConfiguration::describe_current_configuration(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(400, "(printing all environment variables)" )
|
STEP("printing all environment variables")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
os::print_environment_variables(st, env_list);
|
os::print_environment_variables(st, env_list);
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(410, "(printing signal handlers)" )
|
STEP("printing signal handlers")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
os::print_signal_handlers(st, buf, sizeof(buf));
|
os::print_signal_handlers(st, buf, sizeof(buf));
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(420, "(Native Memory Tracking)" )
|
STEP("Native Memory Tracking")
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
MemTracker::error_report(st);
|
MemTracker::error_report(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(430, "(printing system)" )
|
STEP("printing system")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
|
@ -809,27 +809,27 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(440, "(printing OS information)" )
|
STEP("printing OS information")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
os::print_os_info(st);
|
os::print_os_info(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(450, "(printing CPU info)" )
|
STEP("printing CPU info")
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
os::print_cpu_info(st, buf, sizeof(buf));
|
os::print_cpu_info(st, buf, sizeof(buf));
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(460, "(printing memory info)" )
|
STEP("printing memory info")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
os::print_memory_info(st);
|
os::print_memory_info(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
STEP(470, "(printing internal vm info)" )
|
STEP("printing internal vm info")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
st->print_cr("vm_info: %s", Abstract_VM_Version::internal_vm_info_string());
|
st->print_cr("vm_info: %s", Abstract_VM_Version::internal_vm_info_string());
|
||||||
|
@ -837,7 +837,7 @@ void VMError::report(outputStream* st, bool _verbose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// print a defined marker to show that error handling finished correctly.
|
// print a defined marker to show that error handling finished correctly.
|
||||||
STEP(480, "(printing end marker)" )
|
STEP("printing end marker")
|
||||||
|
|
||||||
if (_verbose) {
|
if (_verbose) {
|
||||||
st->print_cr("END.");
|
st->print_cr("END.");
|
||||||
|
@ -858,35 +858,35 @@ void VMError::print_vm_info(outputStream* st) {
|
||||||
char buf[O_BUFLEN];
|
char buf[O_BUFLEN];
|
||||||
report_vm_version(st, buf, sizeof(buf));
|
report_vm_version(st, buf, sizeof(buf));
|
||||||
|
|
||||||
// STEP("(printing summary)")
|
// STEP("printing summary")
|
||||||
|
|
||||||
st->cr();
|
st->cr();
|
||||||
st->print_cr("--------------- S U M M A R Y ------------");
|
st->print_cr("--------------- S U M M A R Y ------------");
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(printing VM option summary)")
|
// STEP("printing VM option summary")
|
||||||
|
|
||||||
// VM options
|
// VM options
|
||||||
Arguments::print_summary_on(st);
|
Arguments::print_summary_on(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(printing summary machine and OS info)")
|
// STEP("printing summary machine and OS info")
|
||||||
|
|
||||||
os::print_summary_info(st, buf, sizeof(buf));
|
os::print_summary_info(st, buf, sizeof(buf));
|
||||||
|
|
||||||
// STEP("(printing date and time)")
|
// STEP("printing date and time")
|
||||||
|
|
||||||
os::print_date_and_time(st, buf, sizeof(buf));
|
os::print_date_and_time(st, buf, sizeof(buf));
|
||||||
|
|
||||||
// Skip: STEP("(printing thread)")
|
// Skip: STEP("printing thread")
|
||||||
|
|
||||||
// STEP("(printing process)")
|
// STEP("printing process")
|
||||||
|
|
||||||
st->cr();
|
st->cr();
|
||||||
st->print_cr("--------------- P R O C E S S ---------------");
|
st->print_cr("--------------- P R O C E S S ---------------");
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(printing number of OutOfMemoryError and StackOverflow exceptions)")
|
// STEP("printing number of OutOfMemoryError and StackOverflow exceptions")
|
||||||
|
|
||||||
if (Exceptions::has_exception_counts()) {
|
if (Exceptions::has_exception_counts()) {
|
||||||
st->print_cr("OutOfMemory and StackOverflow Exception counts:");
|
st->print_cr("OutOfMemory and StackOverflow Exception counts:");
|
||||||
|
@ -894,7 +894,7 @@ void VMError::print_vm_info(outputStream* st) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
// STEP("(printing compressed oops mode")
|
// STEP("printing compressed oops mode")
|
||||||
|
|
||||||
if (UseCompressedOops) {
|
if (UseCompressedOops) {
|
||||||
Universe::print_compressed_oops_mode(st);
|
Universe::print_compressed_oops_mode(st);
|
||||||
|
@ -904,7 +904,7 @@ void VMError::print_vm_info(outputStream* st) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
// STEP("(printing heap information)")
|
// STEP("printing heap information")
|
||||||
|
|
||||||
if (Universe::is_fully_initialized()) {
|
if (Universe::is_fully_initialized()) {
|
||||||
Universe::heap()->print_on_error(st);
|
Universe::heap()->print_on_error(st);
|
||||||
|
@ -913,7 +913,7 @@ void VMError::print_vm_info(outputStream* st) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
// STEP("(printing code cache information)")
|
// STEP("printing code cache information")
|
||||||
|
|
||||||
if (Universe::is_fully_initialized()) {
|
if (Universe::is_fully_initialized()) {
|
||||||
// print code cache information before vm abort
|
// print code cache information before vm abort
|
||||||
|
@ -921,77 +921,77 @@ void VMError::print_vm_info(outputStream* st) {
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
// STEP("(printing ring buffers)")
|
// STEP("printing ring buffers")
|
||||||
|
|
||||||
Events::print_all(st);
|
Events::print_all(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(printing dynamic libraries)")
|
// STEP("printing dynamic libraries")
|
||||||
|
|
||||||
// dynamic libraries, or memory map
|
// dynamic libraries, or memory map
|
||||||
os::print_dll_info(st);
|
os::print_dll_info(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(printing VM options)")
|
// STEP("printing VM options")
|
||||||
|
|
||||||
// VM options
|
// VM options
|
||||||
Arguments::print_on(st);
|
Arguments::print_on(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(printing warning if internal testing API used)")
|
// STEP("printing warning if internal testing API used")
|
||||||
|
|
||||||
if (WhiteBox::used()) {
|
if (WhiteBox::used()) {
|
||||||
st->print_cr("Unsupported internal testing APIs have been used.");
|
st->print_cr("Unsupported internal testing APIs have been used.");
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
// STEP("(printing log configuration)")
|
// STEP("printing log configuration")
|
||||||
st->print_cr("Logging:");
|
st->print_cr("Logging:");
|
||||||
LogConfiguration::describe(st);
|
LogConfiguration::describe(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(printing all environment variables)")
|
// STEP("printing all environment variables")
|
||||||
|
|
||||||
os::print_environment_variables(st, env_list);
|
os::print_environment_variables(st, env_list);
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(printing signal handlers)")
|
// STEP("printing signal handlers")
|
||||||
|
|
||||||
os::print_signal_handlers(st, buf, sizeof(buf));
|
os::print_signal_handlers(st, buf, sizeof(buf));
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(Native Memory Tracking)")
|
// STEP("Native Memory Tracking")
|
||||||
|
|
||||||
MemTracker::error_report(st);
|
MemTracker::error_report(st);
|
||||||
|
|
||||||
// STEP("(printing system)")
|
// STEP("printing system")
|
||||||
|
|
||||||
st->cr();
|
st->cr();
|
||||||
st->print_cr("--------------- S Y S T E M ---------------");
|
st->print_cr("--------------- S Y S T E M ---------------");
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(printing OS information)")
|
// STEP("printing OS information")
|
||||||
|
|
||||||
os::print_os_info(st);
|
os::print_os_info(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(printing CPU info)")
|
// STEP("printing CPU info")
|
||||||
|
|
||||||
os::print_cpu_info(st, buf, sizeof(buf));
|
os::print_cpu_info(st, buf, sizeof(buf));
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(printing memory info)")
|
// STEP("printing memory info")
|
||||||
|
|
||||||
os::print_memory_info(st);
|
os::print_memory_info(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// STEP("(printing internal vm info)")
|
// STEP("printing internal vm info")
|
||||||
|
|
||||||
st->print_cr("vm_info: %s", Abstract_VM_Version::internal_vm_info_string());
|
st->print_cr("vm_info: %s", Abstract_VM_Version::internal_vm_info_string());
|
||||||
st->cr();
|
st->cr();
|
||||||
|
|
||||||
// print a defined marker to show that error handling finished correctly.
|
// print a defined marker to show that error handling finished correctly.
|
||||||
// STEP("(printing end marker)")
|
// STEP("printing end marker")
|
||||||
|
|
||||||
st->print_cr("END.");
|
st->print_cr("END.");
|
||||||
}
|
}
|
||||||
|
@ -1190,7 +1190,7 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt
|
||||||
}
|
}
|
||||||
|
|
||||||
jio_snprintf(buffer, sizeof(buffer),
|
jio_snprintf(buffer, sizeof(buffer),
|
||||||
"[error occurred during error reporting %s, id 0x%x]",
|
"[error occurred during error reporting (%s), id 0x%x]",
|
||||||
_current_step_info, _id);
|
_current_step_info, _id);
|
||||||
if (log.is_open()) {
|
if (log.is_open()) {
|
||||||
log.cr();
|
log.cr();
|
||||||
|
|
|
@ -52,6 +52,11 @@ UNIQ = uniq
|
||||||
WC = wc
|
WC = wc
|
||||||
ZIP = zip
|
ZIP = zip
|
||||||
|
|
||||||
|
define NEWLINE
|
||||||
|
|
||||||
|
|
||||||
|
endef
|
||||||
|
|
||||||
# Get OS name from uname (Cygwin inexplicably adds _NT-5.1)
|
# Get OS name from uname (Cygwin inexplicably adds _NT-5.1)
|
||||||
UNAME_S := $(shell $(UNAME) -s | $(CUT) -f1 -d_)
|
UNAME_S := $(shell $(UNAME) -s | $(CUT) -f1 -d_)
|
||||||
ifeq ($(UNAME_S), SunOS)
|
ifeq ($(UNAME_S), SunOS)
|
||||||
|
@ -427,6 +432,20 @@ PHONY_LIST += hotspot_servertest servertest
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
|
# Run the native gtest tests from the test image
|
||||||
|
|
||||||
|
hotspot_gtest:
|
||||||
|
$(foreach v, $(JVM_VARIANTS), \
|
||||||
|
$(MAKE) hotspot_gtest$v $(NEWLINE) )
|
||||||
|
|
||||||
|
hotspot_gtestserver hotspot_gtestclient hotspot_gtestminimal: hotspot_gtest%:
|
||||||
|
$(TESTNATIVE_DIR)/hotspot/gtest/$*/gtestLauncher \
|
||||||
|
-jdk $(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)")
|
||||||
|
|
||||||
|
PHONY_LIST += hotspot_gtest hotspot_gtestserver hotspot_gtestclient \
|
||||||
|
hotspot_gtestminimal
|
||||||
|
|
||||||
|
################################################################
|
||||||
# Phony targets (e.g. these are not filenames)
|
# Phony targets (e.g. these are not filenames)
|
||||||
.PHONY: all clean prep $(PHONY_LIST)
|
.PHONY: all clean prep $(PHONY_LIST)
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,12 @@ groups=TEST.groups [closed/TEST.groups]
|
||||||
requires.extraPropDefns = ../../test/jtreg-ext/requires/VMProps.java
|
requires.extraPropDefns = ../../test/jtreg-ext/requires/VMProps.java
|
||||||
requires.properties=sun.arch.data.model
|
requires.properties=sun.arch.data.model
|
||||||
|
|
||||||
# Tests using jtreg 4.2 b01 features
|
# Tests using jtreg 4.2 b02 features
|
||||||
requiredVersion=4.2 b01
|
requiredVersion=4.2 b02
|
||||||
|
|
||||||
# Path to libraries in the topmost test directory. This is needed so @library
|
# Path to libraries in the topmost test directory. This is needed so @library
|
||||||
# does not need ../../ notation to reach them
|
# does not need ../../ notation to reach them
|
||||||
external.lib.roots = ../../
|
external.lib.roots = ../../
|
||||||
|
|
||||||
|
# Use new form of -Xpatch
|
||||||
|
useNewXpatch=true
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8136421
|
* @bug 8136421
|
||||||
|
* @ignore 8155216
|
||||||
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
|
* @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64")
|
||||||
* @library / /testlibrary /test/lib/
|
* @library / /testlibrary /test/lib/
|
||||||
* @library ../common/patches
|
* @library ../common/patches
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue