--- a/make/CompileToolsHotspot.gmk Wed Nov 15 09:31:17 2017 -0800
+++ b/make/CompileToolsHotspot.gmk Thu Nov 16 10:45:42 2017 -0800
@@ -67,6 +67,7 @@
$(SRC_DIR)/org.graalvm.compiler.phases.common/src \
$(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \
$(SRC_DIR)/org.graalvm.compiler.virtual/src \
+ $(SRC_DIR)/org.graalvm.graphio/src \
$(SRC_DIR)/org.graalvm.util/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \
@@ -125,6 +126,7 @@
$(SRC_DIR)/org.graalvm.compiler.nodeinfo/src \
$(SRC_DIR)/org.graalvm.compiler.options/src \
$(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \
+ $(SRC_DIR)/org.graalvm.graphio/src \
$(SRC_DIR)/org.graalvm.util/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \
$(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \
--- a/make/common/MakeBase.gmk Wed Nov 15 09:31:17 2017 -0800
+++ b/make/common/MakeBase.gmk Thu Nov 16 10:45:42 2017 -0800
@@ -473,15 +473,32 @@
$(subst $(SPACE),?,$(strip $1))
################################################################################
-# Make directory without forking mkdir if not needed
+# Make directory without forking mkdir if not needed.
+#
+# If a directory with an encoded space is provided, the wildcard function
+# sometimes returns false answers (typically if the dir existed when the
+# makefile was parsed, but was deleted by a previous rule). In that case, always
+# call mkdir regardless of what wildcard says.
+#
# 1: List of directories to create
MakeDir = \
$(strip \
- $(eval MakeDir_dirs_to_make := $(strip $(foreach d, $1, $(if $(wildcard $d), , \
- "$(call DecodeSpace, $d)")))) \
+ $(eval MakeDir_dirs_to_make := $(strip $(foreach d, $1, \
+ $(if $(findstring ?, $d), '$(call DecodeSpace, $d)', \
+ $(if $(wildcard $d), , $d) \
+ ) \
+ ))) \
$(if $(MakeDir_dirs_to_make), $(shell $(MKDIR) -p $(MakeDir_dirs_to_make))) \
)
+# Make directory for target file. Should handle spaces in filenames. Just
+# calling $(call MakeDir $(@D)) will not work if the directory contains a space
+# and the target file already exists. In that case, the target file will have
+# its wildcard ? resolved and the $(@D) will evaluate each space separated dir
+# part on its own.
+MakeTargetDir = \
+ $(call MakeDir, $(dir $(call EncodeSpace, $@)))
+
################################################################################
# Assign a variable only if it is empty
# Param 1 - Variable to assign
@@ -499,7 +516,7 @@
# If the source and target parent directories are the same, recursive copy doesn't work
# so we fall back on regular copy, which isn't preserving symlinks.
define install-file
- $(call MakeDir, $(@D))
+ $(call MakeTargetDir)
$(RM) '$(call DecodeSpace, $@)'
if [ '$(call DecodeSpace, $(dir $@))' != \
'$(call DecodeSpace, $(dir $(call EncodeSpace, $<)))' ]; then \
@@ -526,21 +543,21 @@
# If copying a soft link to a directory, need to delete the target first to avoid
# weird errors.
define install-file
- $(call MakeDir, $(@D))
+ $(call MakeTargetDir)
$(RM) '$(call DecodeSpace, $@)'
$(CP) -fRP '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'
if [ -n "`$(XATTR) -ls '$(call DecodeSpace, $@)'`" ]; then $(XATTR) -cs '$(call DecodeSpace, $@)'; fi
endef
else
define install-file
- $(call MakeDir, $(@D))
+ $(call MakeTargetDir)
$(CP) -fP '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'
endef
endif
# Variant of install file that does not preserve symlinks
define install-file-nolink
- $(call MakeDir, $(@D))
+ $(call MakeTargetDir)
$(CP) -f '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'
endef
@@ -590,13 +607,13 @@
# careful when using this on Windows since the symlink created is only valid in
# the unix emulation environment.
define link-file-relative
- $(call MakeDir, $(@D))
+ $(call MakeTargetDir)
$(RM) '$(call DecodeSpace, $@)'
$(LN) -s '$(call DecodeSpace, $(call RelativePath, $<, $(@D)))' '$(call DecodeSpace, $@)'
endef
define link-file-absolute
- $(call MakeDir, $(@D))
+ $(call MakeTargetDir)
$(RM) '$(call DecodeSpace, $@)'
$(LN) -s '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'
endef
--- a/make/copy/Copy-java.base.gmk Wed Nov 15 09:31:17 2017 -0800
+++ b/make/copy/Copy-java.base.gmk Thu Nov 16 10:45:42 2017 -0800
@@ -42,7 +42,7 @@
$(call install-file)
$(INCLUDE_DST_OS_DIR)/%.h: \
- $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_EXPORT_DIR)/native/include/%.h
+ $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/include/%.h
$(call install-file)
################################################################################
--- a/make/hotspot/lib/CompileJvm.gmk Wed Nov 15 09:31:17 2017 -0800
+++ b/make/hotspot/lib/CompileJvm.gmk Thu Nov 16 10:45:42 2017 -0800
@@ -57,8 +57,8 @@
$(patsubst %,-I%,$(filter-out $(JVM_VARIANT_OUTPUTDIR)/gensrc/%, $(JVM_SRC_DIRS))) \
-I$(JVM_VARIANT_OUTPUTDIR)/gensrc \
-I$(TOPDIR)/src/hotspot/share/precompiled \
- -I$(TOPDIR)/src/hotspot/share/prims \
-I$(TOPDIR)/src/java.base/share/native/include \
+ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/include \
#
# INCLUDE_SUFFIX_* is only meant for including the proper
--- a/make/hotspot/lib/CompileLibjsig.gmk Wed Nov 15 09:31:17 2017 -0800
+++ b/make/hotspot/lib/CompileLibjsig.gmk Thu Nov 16 10:45:42 2017 -0800
@@ -57,7 +57,7 @@
endif
else ifeq ($(OPENJDK_TARGET_OS), solaris)
- LIBJSIG_CFLAGS := -m64 -KPIC -mt -I $(TOPDIR)/src/hotspot/os/solaris
+ LIBJSIG_CFLAGS := -m64 -KPIC -mt -I $(TOPDIR)/src/java.base/unix/native/include
LIBJSIG_LDFLAGS := -m64 -mt -xnolib
LIBJSIG_LIBS := $(LIBDL)
--- a/make/mapfiles/libinstrument/mapfile-vers Wed Nov 15 09:31:17 2017 -0800
+++ b/make/mapfiles/libinstrument/mapfile-vers Thu Nov 16 10:45:42 2017 -0800
@@ -31,6 +31,7 @@
Agent_OnAttach;
Java_sun_instrument_InstrumentationImpl_isModifiableClass0;
Java_sun_instrument_InstrumentationImpl_isRetransformClassesSupported0;
+ Java_sun_instrument_InstrumentationImpl_setHasTransformers;
Java_sun_instrument_InstrumentationImpl_setHasRetransformableTransformers;
Java_sun_instrument_InstrumentationImpl_retransformClasses0;
Java_sun_instrument_InstrumentationImpl_getAllLoadedClasses0;
--- a/make/test/JtregNativeHotspot.gmk Wed Nov 15 09:31:17 2017 -0800
+++ b/make/test/JtregNativeHotspot.gmk Thu Nov 16 10:45:42 2017 -0800
@@ -63,6 +63,8 @@
$(TOPDIR)/test/hotspot/jtreg/runtime/RedefineTests \
$(TOPDIR)/test/hotspot/jtreg/compiler/floatingpoint/ \
$(TOPDIR)/test/hotspot/jtreg/compiler/calls \
+ $(TOPDIR)/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup \
+ $(TOPDIR)/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption \
$(TOPDIR)/test/hotspot/jtreg/serviceability/jvmti/GetOwnedMonitorInfo \
$(TOPDIR)/test/hotspot/jtreg/serviceability/jvmti/GetNamedModule \
$(TOPDIR)/test/hotspot/jtreg/serviceability/jvmti/IsModifiableModule \
--- a/src/hotspot/.mx.jvmci/.project Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>mx.jvmci</name>
- <comment></comment>
- <projects>
- <project>mx</project>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.python.pydev.PyDevBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.python.pydev.pythonNature</nature>
- </natures>
-</projectDescription>
--- a/src/hotspot/.mx.jvmci/.pydevproject Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?eclipse-pydev version="1.0"?><pydev_project>
-<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
-<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
-<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
-<path>/mx.jvmci</path>
-</pydev_pathproperty>
-<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
-<path>/mx</path>
-</pydev_pathproperty>
-
-</pydev_project>
--- a/src/hotspot/.mx.jvmci/mx_jvmci.py Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/.mx.jvmci/mx_jvmci.py Thu Nov 16 10:45:42 2017 -0800
@@ -42,11 +42,6 @@
JVMCI_VERSION = 9
-"""
-Top level directory of the JDK source workspace.
-"""
-_jdkSourceRoot = dirname(_suite.dir)
-
_JVMCI_JDK_TAG = 'jvmci'
_minVersion = mx.VersionSpec('1.9')
@@ -145,7 +140,7 @@
return True
def _makehelp():
- return subprocess.check_output([mx.gmake_cmd(), 'help'], cwd=_jdkSourceRoot)
+ return subprocess.check_output([mx.gmake_cmd(), 'help'], cwd=_get_jdk_dir())
def _runmake(args):
"""run the JDK make process
@@ -155,12 +150,12 @@
jdkBuildDir = _get_jdk_build_dir()
if not exists(jdkBuildDir):
- # JDK9 must be bootstrapped with a JDK8
- compliance = mx.JavaCompliance('8')
- jdk8 = mx.get_jdk(compliance.exactMatch, versionDescription=compliance.value)
+ # JDK10 must be bootstrapped with a JDK9
+ compliance = mx.JavaCompliance('9')
+ jdk9 = mx.get_jdk(compliance.exactMatch, versionDescription=compliance.value)
cmd = ['sh', 'configure', '--with-debug-level=' + _vm.debugLevel, '--with-native-debug-symbols=external', '--disable-precompiled-headers', '--with-jvm-features=graal',
- '--with-jvm-variants=' + _vm.jvmVariant, '--disable-warnings-as-errors', '--with-boot-jdk=' + jdk8.home, '--with-jvm-features=graal']
- mx.run(cmd, cwd=_jdkSourceRoot)
+ '--with-jvm-variants=' + _vm.jvmVariant, '--disable-warnings-as-errors', '--with-boot-jdk=' + jdk9.home, '--with-jvm-features=graal']
+ mx.run(cmd, cwd=_get_jdk_dir())
cmd = [mx.gmake_cmd(), 'CONF=' + _vm.debugLevel]
if mx.get_opts().verbose:
cmd.append('LOG=debug')
@@ -170,11 +165,11 @@
if not mx.get_opts().verbose:
mx.log('--------------- make execution ----------------------')
- mx.log('Working directory: ' + _jdkSourceRoot)
+ mx.log('Working directory: ' + _get_jdk_dir())
mx.log('Command line: ' + ' '.join(cmd))
mx.log('-----------------------------------------------------')
- mx.run(cmd, cwd=_jdkSourceRoot)
+ mx.run(cmd, cwd=_get_jdk_dir())
def _runmultimake(args):
"""run the JDK make process for one or more configurations"""
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -1489,6 +1489,17 @@
#undef INSN
+ // Aliases for short forms of orn
+void mvn(Register Rd, Register Rm,
+ enum shift_kind kind = LSL, unsigned shift = 0) {
+ orn(Rd, zr, Rm, kind, shift);
+}
+
+void mvnw(Register Rd, Register Rm,
+ enum shift_kind kind = LSL, unsigned shift = 0) {
+ ornw(Rd, zr, Rm, kind, shift);
+}
+
// Add/subtract (shifted register)
#define INSN(NAME, size, op) \
void NAME(Register Rd, Register Rn, Register Rm, \
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -2657,9 +2657,9 @@
__ adrp(res, ExternalAddress(StubRoutines::crc_table_addr()), offset);
if (offset) __ add(res, res, offset);
- __ ornw(crc, zr, crc); // ~crc
+ __ mvnw(crc, crc); // ~crc
__ update_byte_crc32(crc, val, res);
- __ ornw(res, zr, crc); // ~crc
+ __ mvnw(res, crc); // ~crc
}
void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
--- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1030,7 +1030,81 @@
}
void LIRGenerator::do_update_CRC32C(Intrinsic* x) {
- Unimplemented();
+ assert(UseCRC32CIntrinsics, "why are we here?");
+ // Make all state_for calls early since they can emit code
+ LIR_Opr result = rlock_result(x);
+ int flags = 0;
+ switch (x->id()) {
+ case vmIntrinsics::_updateBytesCRC32C:
+ case vmIntrinsics::_updateDirectByteBufferCRC32C: {
+ bool is_updateBytes = (x->id() == vmIntrinsics::_updateBytesCRC32C);
+ int offset = is_updateBytes ? arrayOopDesc::base_offset_in_bytes(T_BYTE) : 0;
+
+ LIRItem crc(x->argument_at(0), this);
+ LIRItem buf(x->argument_at(1), this);
+ LIRItem off(x->argument_at(2), this);
+ LIRItem end(x->argument_at(3), this);
+
+ buf.load_item();
+ off.load_nonconstant();
+ end.load_nonconstant();
+
+ // len = end - off
+ LIR_Opr len = end.result();
+ LIR_Opr tmpA = new_register(T_INT);
+ LIR_Opr tmpB = new_register(T_INT);
+ __ move(end.result(), tmpA);
+ __ move(off.result(), tmpB);
+ __ sub(tmpA, tmpB, tmpA);
+ len = tmpA;
+
+ LIR_Opr index = off.result();
+ if(off.result()->is_constant()) {
+ index = LIR_OprFact::illegalOpr;
+ offset += off.result()->as_jint();
+ }
+ LIR_Opr base_op = buf.result();
+
+ if (index->is_valid()) {
+ LIR_Opr tmp = new_register(T_LONG);
+ __ convert(Bytecodes::_i2l, index, tmp);
+ index = tmp;
+ }
+
+ if (offset) {
+ LIR_Opr tmp = new_pointer_register();
+ __ add(base_op, LIR_OprFact::intConst(offset), tmp);
+ base_op = tmp;
+ offset = 0;
+ }
+
+ LIR_Address* a = new LIR_Address(base_op,
+ index,
+ offset,
+ T_BYTE);
+ BasicTypeList signature(3);
+ signature.append(T_INT);
+ signature.append(T_ADDRESS);
+ signature.append(T_INT);
+ CallingConvention* cc = frame_map()->c_calling_convention(&signature);
+ const LIR_Opr result_reg = result_register_for(x->type());
+
+ LIR_Opr addr = new_pointer_register();
+ __ leal(LIR_OprFact::address(a), addr);
+
+ crc.load_item_force(cc->at(0));
+ __ move(addr, cc->at(1));
+ __ move(len, cc->at(2));
+
+ __ call_runtime_leaf(StubRoutines::updateBytesCRC32C(), getThreadTemp(), result_reg, cc->args());
+ __ move(result_reg, result);
+
+ break;
+ }
+ default: {
+ ShouldNotReachHere();
+ }
+ }
}
void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) {
--- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -431,11 +431,11 @@
// This is the sp before any possible extension (adapter/locals).
intptr_t* unextended_sp = interpreter_frame_sender_sp();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
if (map->update_map()) {
update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset));
}
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
return frame(sender_sp, unextended_sp, link(), sender_pc());
}
--- a/src/hotspot/cpu/aarch64/jni_aarch64.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 1997, 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. 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.
- */
-
-#ifndef _JAVASOFT_JNI_MD_H_
-#define _JAVASOFT_JNI_MD_H_
-
-#if defined(SOLARIS) || defined(LINUX) || defined(_ALLBSD_SOURCE)
-
-
-// Note: please do not change these without also changing jni_md.h in the JDK
-// repository
-#ifndef __has_attribute
- #define __has_attribute(x) 0
-#endif
-#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
- #define JNIEXPORT __attribute__((visibility("default")))
- #define JNIIMPORT __attribute__((visibility("default")))
-#else
- #define JNIEXPORT
- #define JNIIMPORT
-#endif
-
- #define JNICALL
- typedef int jint;
- typedef long jlong;
-
-#else
- #define JNIEXPORT __declspec(dllexport)
- #define JNIIMPORT __declspec(dllimport)
- #define JNICALL __stdcall
-
- typedef int jint;
- typedef __int64 jlong;
-#endif
-
-typedef signed char jbyte;
-
-#endif /* !_JAVASOFT_JNI_MD_H_ */
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "interpreter/interpreter.hpp"
@@ -38,7 +39,6 @@
#include "opto/compile.hpp"
#include "opto/intrinsicnode.hpp"
#include "opto/node.hpp"
-#include "prims/jvm.h"
#include "runtime/biasedLocking.hpp"
#include "runtime/icache.hpp"
#include "runtime/interfaceSupport.hpp"
@@ -2929,6 +2929,105 @@
eor(crc, crc, tmp);
}
+void MacroAssembler::kernel_crc32_using_crc32(Register crc, Register buf,
+ Register len, Register tmp0, Register tmp1, Register tmp2,
+ Register tmp3) {
+ Label CRC_by64_loop, CRC_by4_loop, CRC_by1_loop, CRC_less64, CRC_by64_pre, CRC_by32_loop, CRC_less32, L_exit;
+ assert_different_registers(crc, buf, len, tmp0, tmp1, tmp2, tmp3);
+
+ mvnw(crc, crc);
+
+ subs(len, len, 128);
+ br(Assembler::GE, CRC_by64_pre);
+ BIND(CRC_less64);
+ adds(len, len, 128-32);
+ br(Assembler::GE, CRC_by32_loop);
+ BIND(CRC_less32);
+ adds(len, len, 32-4);
+ br(Assembler::GE, CRC_by4_loop);
+ adds(len, len, 4);
+ br(Assembler::GT, CRC_by1_loop);
+ b(L_exit);
+
+ BIND(CRC_by32_loop);
+ ldp(tmp0, tmp1, Address(post(buf, 16)));
+ subs(len, len, 32);
+ crc32x(crc, crc, tmp0);
+ ldr(tmp2, Address(post(buf, 8)));
+ crc32x(crc, crc, tmp1);
+ ldr(tmp3, Address(post(buf, 8)));
+ crc32x(crc, crc, tmp2);
+ crc32x(crc, crc, tmp3);
+ br(Assembler::GE, CRC_by32_loop);
+ cmn(len, 32);
+ br(Assembler::NE, CRC_less32);
+ b(L_exit);
+
+ BIND(CRC_by4_loop);
+ ldrw(tmp0, Address(post(buf, 4)));
+ subs(len, len, 4);
+ crc32w(crc, crc, tmp0);
+ br(Assembler::GE, CRC_by4_loop);
+ adds(len, len, 4);
+ br(Assembler::LE, L_exit);
+ BIND(CRC_by1_loop);
+ ldrb(tmp0, Address(post(buf, 1)));
+ subs(len, len, 1);
+ crc32b(crc, crc, tmp0);
+ br(Assembler::GT, CRC_by1_loop);
+ b(L_exit);
+
+ BIND(CRC_by64_pre);
+ sub(buf, buf, 8);
+ ldp(tmp0, tmp1, Address(buf, 8));
+ crc32x(crc, crc, tmp0);
+ ldr(tmp2, Address(buf, 24));
+ crc32x(crc, crc, tmp1);
+ ldr(tmp3, Address(buf, 32));
+ crc32x(crc, crc, tmp2);
+ ldr(tmp0, Address(buf, 40));
+ crc32x(crc, crc, tmp3);
+ ldr(tmp1, Address(buf, 48));
+ crc32x(crc, crc, tmp0);
+ ldr(tmp2, Address(buf, 56));
+ crc32x(crc, crc, tmp1);
+ ldr(tmp3, Address(pre(buf, 64)));
+
+ b(CRC_by64_loop);
+
+ align(CodeEntryAlignment);
+ BIND(CRC_by64_loop);
+ subs(len, len, 64);
+ crc32x(crc, crc, tmp2);
+ ldr(tmp0, Address(buf, 8));
+ crc32x(crc, crc, tmp3);
+ ldr(tmp1, Address(buf, 16));
+ crc32x(crc, crc, tmp0);
+ ldr(tmp2, Address(buf, 24));
+ crc32x(crc, crc, tmp1);
+ ldr(tmp3, Address(buf, 32));
+ crc32x(crc, crc, tmp2);
+ ldr(tmp0, Address(buf, 40));
+ crc32x(crc, crc, tmp3);
+ ldr(tmp1, Address(buf, 48));
+ crc32x(crc, crc, tmp0);
+ ldr(tmp2, Address(buf, 56));
+ crc32x(crc, crc, tmp1);
+ ldr(tmp3, Address(pre(buf, 64)));
+ br(Assembler::GE, CRC_by64_loop);
+
+ // post-loop
+ crc32x(crc, crc, tmp2);
+ crc32x(crc, crc, tmp3);
+
+ sub(len, len, 64);
+ add(buf, buf, 8);
+ cmn(len, 128);
+ br(Assembler::NE, CRC_less64);
+ BIND(L_exit);
+ mvnw(crc, crc);
+}
+
/**
* @param crc register containing existing CRC (32-bit)
* @param buf register pointing to input byte buffer (byte*)
@@ -2942,58 +3041,13 @@
Label L_by16, L_by16_loop, L_by4, L_by4_loop, L_by1, L_by1_loop, L_exit;
unsigned long offset;
- ornw(crc, zr, crc);
-
if (UseCRC32) {
- Label CRC_by64_loop, CRC_by4_loop, CRC_by1_loop;
-
- subs(len, len, 64);
- br(Assembler::GE, CRC_by64_loop);
- adds(len, len, 64-4);
- br(Assembler::GE, CRC_by4_loop);
- adds(len, len, 4);
- br(Assembler::GT, CRC_by1_loop);
- b(L_exit);
-
- BIND(CRC_by4_loop);
- ldrw(tmp, Address(post(buf, 4)));
- subs(len, len, 4);
- crc32w(crc, crc, tmp);
- br(Assembler::GE, CRC_by4_loop);
- adds(len, len, 4);
- br(Assembler::LE, L_exit);
- BIND(CRC_by1_loop);
- ldrb(tmp, Address(post(buf, 1)));
- subs(len, len, 1);
- crc32b(crc, crc, tmp);
- br(Assembler::GT, CRC_by1_loop);
- b(L_exit);
-
- align(CodeEntryAlignment);
- BIND(CRC_by64_loop);
- subs(len, len, 64);
- ldp(tmp, tmp3, Address(post(buf, 16)));
- crc32x(crc, crc, tmp);
- crc32x(crc, crc, tmp3);
- ldp(tmp, tmp3, Address(post(buf, 16)));
- crc32x(crc, crc, tmp);
- crc32x(crc, crc, tmp3);
- ldp(tmp, tmp3, Address(post(buf, 16)));
- crc32x(crc, crc, tmp);
- crc32x(crc, crc, tmp3);
- ldp(tmp, tmp3, Address(post(buf, 16)));
- crc32x(crc, crc, tmp);
- crc32x(crc, crc, tmp3);
- br(Assembler::GE, CRC_by64_loop);
- adds(len, len, 64-4);
- br(Assembler::GE, CRC_by4_loop);
- adds(len, len, 4);
- br(Assembler::GT, CRC_by1_loop);
- BIND(L_exit);
- ornw(crc, zr, crc);
+ kernel_crc32_using_crc32(crc, buf, len, table0, table1, table2, table3);
return;
}
+ mvnw(crc, crc);
+
adrp(table0, ExternalAddress(StubRoutines::crc_table_addr()), offset);
if (offset) add(table0, table0, offset);
add(table1, table0, 1*256*sizeof(juint));
@@ -3171,7 +3225,7 @@
adds(len, len, 4);
br(Assembler::GT, L_by1_loop);
BIND(L_exit);
- ornw(crc, zr, crc);
+ mvnw(crc, crc);
}
/**
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -1261,6 +1261,9 @@
Register yz_idx1, Register yz_idx2,
Register tmp, Register tmp3, Register tmp4,
Register tmp7, Register product_hi);
+ void kernel_crc32_using_crc32(Register crc, Register buf,
+ Register len, Register tmp0, Register tmp1, Register tmp2,
+ Register tmp3);
public:
void multiply_to_len(Register x, Register xlen, Register y, Register ylen, Register z,
Register zlen, Register tmp1, Register tmp2, Register tmp3,
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -41,7 +41,7 @@
#ifdef COMPILER1
#include "c1/c1_Runtime1.hpp"
#endif
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
#include "adfiles/ad_aarch64.hpp"
#include "opto/runtime.hpp"
#endif
@@ -114,7 +114,7 @@
};
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
if (save_vectors) {
// Save upper half of vector registers
int vect_words = 32 * 8 / wordSize;
@@ -2688,7 +2688,7 @@
return 0;
}
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
//------------------------------generate_uncommon_trap_blob--------------------
void SharedRuntime::generate_uncommon_trap_blob() {
// Allocate space for the code
@@ -2894,7 +2894,7 @@
}
#endif
}
-#endif // COMPILER2
+#endif // COMPILER2_OR_JVMCI
//------------------------------generate_handler_blob------
@@ -3070,8 +3070,7 @@
return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true);
}
-
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
// This is here instead of runtime_x86_64.cpp because it uses SimpleRuntimeFrame
//
//------------------------------generate_exception_blob---------------------------
@@ -3200,4 +3199,4 @@
// Set exception blob
_exception_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1);
}
-#endif // COMPILER2
+#endif // COMPILER2_OR_JVMCI
--- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -4937,6 +4937,10 @@
StubRoutines::_crc_table_adr = (address)StubRoutines::aarch64::_crc_table;
StubRoutines::_updateBytesCRC32 = generate_updateBytesCRC32();
}
+
+ if (UseCRC32CIntrinsics) {
+ StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
+ }
}
void generate_all() {
@@ -5014,10 +5018,6 @@
StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB");
}
- if (UseCRC32CIntrinsics) {
- StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
- }
-
// generate Adler32 intrinsics code
if (UseAdler32Intrinsics) {
StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32();
--- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -472,7 +472,7 @@
#if INCLUDE_JVMCI
// Check if we need to take lock at entry of synchronized method. This can
// only occur on method entry so emit it only for vtos with step 0.
- if (UseJVMCICompiler && state == vtos && step == 0) {
+ if (EnableJVMCI && state == vtos && step == 0) {
Label L;
__ ldr(rscratch1, Address(rthread, Thread::pending_exception_offset()));
__ cbz(rscratch1, L);
@@ -483,7 +483,7 @@
__ bind(L);
} else {
#ifdef ASSERT
- if (UseJVMCICompiler) {
+ if (EnableJVMCI) {
Label L;
__ ldr(rscratch1, Address(rthread, Thread::pending_exception_offset()));
__ cbz(rscratch1, L);
@@ -984,9 +984,9 @@
__ adrp(tbl, ExternalAddress(StubRoutines::crc_table_addr()), offset);
__ add(tbl, tbl, offset);
- __ ornw(crc, zr, crc); // ~crc
+ __ mvnw(crc, crc); // ~crc
__ update_byte_crc32(crc, val, tbl);
- __ ornw(crc, zr, crc); // ~crc
+ __ mvnw(crc, crc); // ~crc
// result in c_rarg0
@@ -1061,8 +1061,44 @@
return NULL;
}
-// Not supported
+/**
+ * Method entry for intrinsic-candidate (non-native) methods:
+ * int java.util.zip.CRC32C.updateBytes(int crc, byte[] b, int off, int end)
+ * int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long buf, int off, int end)
+ * Unlike CRC32, CRC32C does not have any methods marked as native
+ * CRC32C also uses an "end" variable instead of the length variable CRC32 uses
+ */
address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
+ if (UseCRC32Intrinsics) {
+ address entry = __ pc();
+
+ // Prepare jump to stub using parameters from the stack
+ const Register crc = c_rarg0; // initial crc
+ const Register buf = c_rarg1; // source java byte array address
+ const Register len = c_rarg2; // len argument to the kernel
+
+ const Register end = len; // index of last element to process
+ const Register off = crc; // offset
+
+ __ ldrw(end, Address(esp)); // int end
+ __ ldrw(off, Address(esp, wordSize)); // int offset
+ __ sub(len, end, off);
+ __ ldr(buf, Address(esp, 2*wordSize)); // byte[] buf | long buf
+ __ add(buf, buf, off); // + offset
+ if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) {
+ __ ldrw(crc, Address(esp, 4*wordSize)); // long crc
+ } else {
+ __ add(buf, buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size
+ __ ldrw(crc, Address(esp, 3*wordSize)); // long crc
+ }
+
+ __ andr(sp, r13, -16); // Restore the caller's SP
+
+ // Jump to the stub.
+ __ b(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C()));
+
+ return entry;
+ }
return NULL;
}
--- a/src/hotspot/cpu/arm/compiledIC_arm.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/arm/compiledIC_arm.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -33,7 +33,7 @@
#include "runtime/safepoint.hpp"
// ----------------------------------------------------------------------------
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
#define __ _masm.
// emit call stub, compiled java to interpreter
address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
@@ -89,7 +89,7 @@
int CompiledStaticCall::reloc_to_interp_stub() {
return 10; // 4 in emit_to_interp_stub + 1 in Java_Static_Call
}
-#endif // COMPILER2 || JVMCI
+#endif // COMPILER2_OR_JVMCI
// size of C2 call stub, compiled java to interpretor
int CompiledStaticCall::to_interp_stub_size() {
--- a/src/hotspot/cpu/arm/interp_masm_arm.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/arm/interp_masm_arm.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "gc/shared/barrierSet.inline.hpp"
#include "gc/shared/cardTableModRefBS.inline.hpp"
#include "gc/shared/collectedHeap.hpp"
--- a/src/hotspot/cpu/arm/jni_arm.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2008, 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. 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.
- */
-
-#ifndef _JAVASOFT_JNI_MD_H_
-#define _JAVASOFT_JNI_MD_H_
-
-// Note: please do not change these without also changing jni_md.h in the JDK
-// repository
-#ifndef __has_attribute
- #define __has_attribute(x) 0
-#endif
-#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
- #define JNIEXPORT __attribute__((externally_visible,visibility("default")))
- #define JNIIMPORT __attribute__((externally_visible,visibility("default")))
-#else
- #define JNIEXPORT
- #define JNIIMPORT
-#endif
-
-#define JNICALL
-
-typedef int jint;
-#if defined(_LP64)
- typedef long jlong;
-#else
- typedef long long jlong;
-#endif
-typedef signed char jbyte;
-
-#endif /* !_JAVASOFT_JNI_MD_H_ */
--- a/src/hotspot/cpu/arm/methodHandles_arm.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/arm/methodHandles_arm.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -27,12 +27,12 @@
// Last synchronization: changeset f8c9417e3571
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/javaClasses.inline.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "prims/methodHandles.hpp"
#define __ _masm->
--- a/src/hotspot/cpu/arm/vm_version_arm_32.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/arm/vm_version_arm_32.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,9 +23,9 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/macroAssembler.inline.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "runtime/java.hpp"
#include "runtime/os.inline.hpp"
#include "runtime/stubCodeGenerator.hpp"
--- a/src/hotspot/cpu/arm/vm_version_arm_64.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/arm/vm_version_arm_64.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,9 +23,9 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/macroAssembler.inline.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "runtime/java.hpp"
#include "runtime/os.inline.hpp"
#include "runtime/stubCodeGenerator.hpp"
--- a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -941,7 +941,7 @@
inline void Assembler::vpmsumw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPMSUMW_OPCODE | vrt(d) | vra(a) | vrb(b)); }
// Vector Permute and Xor (introduced with Power 8)
-inline void Assembler::vpermxor( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c) { emit_int32( VPMSUMW_OPCODE | vrt(d) | vra(a) | vrb(b) | vrc(c)); }
+inline void Assembler::vpermxor( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c) { emit_int32( VPERMXOR_OPCODE | vrt(d) | vra(a) | vrb(b) | vrc(c)); }
// Transactional Memory instructions (introduced with Power 8)
inline void Assembler::tbegin_() { emit_int32( TBEGIN_OPCODE | rc(1)); }
--- a/src/hotspot/cpu/ppc/globals_ppc.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/ppc/globals_ppc.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -69,7 +69,7 @@
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
-define_pd_global(bool, UseMembar, false);
+define_pd_global(bool, UseMembar, true);
define_pd_global(bool, PreserveFramePointer, false);
--- a/src/hotspot/cpu/ppc/jni_ppc.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2013 SAP SE. 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.
- */
-
-#ifndef CPU_PPC_VM_JNI_PPC_H
-#define CPU_PPC_VM_JNI_PPC_H
-
-// Note: please do not change these without also changing jni_md.h in the JDK
-// repository
-#ifndef __has_attribute
- #define __has_attribute(x) 0
-#endif
-#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
- #define JNIEXPORT __attribute__((visibility("default")))
- #define JNIIMPORT __attribute__((visibility("default")))
-#else
- #define JNIEXPORT
- #define JNIIMPORT
-#endif
-
-#define JNICALL
-
-typedef int jint;
-
-#if defined(_LP64)
- typedef long jlong;
-#else
- typedef long long jlong;
-#endif
-
-typedef signed char jbyte;
-
-#endif // CPU_PPC_VM_JNI_PPC_H
--- a/src/hotspot/cpu/ppc/methodHandles_ppc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/ppc/methodHandles_ppc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -24,12 +24,12 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/macroAssembler.inline.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "interpreter/interpreter.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "prims/methodHandles.hpp"
#define __ _masm->
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1469,8 +1469,31 @@
}
// Save or restore single word registers.
for (int i = 0; i < total_in_args; i++) {
- // PPC64: pass ints as longs: must only deal with floats here.
- if (in_regs[i].first()->is_FloatRegister()) {
+ if (in_regs[i].first()->is_Register()) {
+ int offset = slot * VMRegImpl::stack_slot_size;
+ // Value lives in an input register. Save it on stack.
+ switch (in_sig_bt[i]) {
+ case T_BOOLEAN:
+ case T_CHAR:
+ case T_BYTE:
+ case T_SHORT:
+ case T_INT:
+ if (map != NULL) {
+ __ stw(in_regs[i].first()->as_Register(), offset, R1_SP);
+ } else {
+ __ lwa(in_regs[i].first()->as_Register(), offset, R1_SP);
+ }
+ slot++;
+ assert(slot <= stack_slots, "overflow (after INT or smaller stack slot)");
+ break;
+ case T_ARRAY:
+ case T_LONG:
+ // handled above
+ break;
+ case T_OBJECT:
+ default: ShouldNotReachHere();
+ }
+ } else if (in_regs[i].first()->is_FloatRegister()) {
if (in_sig_bt[i] == T_FLOAT) {
int offset = slot * VMRegImpl::stack_slot_size;
slot++;
--- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -24,11 +24,11 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/assembler.inline.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "compiler/disassembler.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "runtime/stubCodeGenerator.hpp"
@@ -109,7 +109,8 @@
if (PowerArchitecturePPC64 >= 8) {
if (FLAG_IS_DEFAULT(SuperwordUseVSX)) {
- FLAG_SET_ERGO(bool, SuperwordUseVSX, true);
+ // TODO: Switch on when it works stable. Currently, MachSpillCopyNode::implementation code is missing.
+ //FLAG_SET_ERGO(bool, SuperwordUseVSX, true);
}
} else {
if (SuperwordUseVSX) {
--- a/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -277,7 +277,7 @@
length.set_instruction(x->length());
length.load_item();
}
- if (needs_store_check) {
+ if (needs_store_check || x->check_boolean()) {
value.load_item();
} else {
value.load_for_store(x->elt_type());
@@ -327,11 +327,14 @@
// Needs GC write barriers.
pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */,
true /* do_load */, false /* patch */, NULL);
- __ move(value.result(), array_addr, null_check_info);
- // Seems to be a precise.
+ }
+
+ LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info);
+ __ move(result, array_addr, null_check_info);
+
+ if (obj_store) {
+ // Precise card mark
post_barrier(LIR_OprFact::address(array_addr), value.result());
- } else {
- __ move(value.result(), array_addr, null_check_info);
}
}
--- a/src/hotspot/cpu/s390/globals_s390.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/s390/globals_s390.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -71,7 +71,7 @@
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
-define_pd_global(bool, UseMembar, false);
+define_pd_global(bool, UseMembar, true);
define_pd_global(bool, PreserveFramePointer, false);
--- a/src/hotspot/cpu/s390/interp_masm_s390.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -843,6 +843,38 @@
verify_oop(Z_tos, state);
}
+void InterpreterMacroAssembler::narrow(Register result, Register ret_type) {
+ get_method(ret_type);
+ z_lg(ret_type, Address(ret_type, in_bytes(Method::const_offset())));
+ z_lb(ret_type, Address(ret_type, in_bytes(ConstMethod::result_type_offset())));
+
+ Label notBool, notByte, notChar, done;
+
+ // common case first
+ compareU32_and_branch(ret_type, T_INT, bcondEqual, done);
+
+ compareU32_and_branch(ret_type, T_BOOLEAN, bcondNotEqual, notBool);
+ z_nilf(result, 0x1);
+ z_bru(done);
+
+ bind(notBool);
+ compareU32_and_branch(ret_type, T_BYTE, bcondNotEqual, notByte);
+ z_lbr(result, result);
+ z_bru(done);
+
+ bind(notByte);
+ compareU32_and_branch(ret_type, T_CHAR, bcondNotEqual, notChar);
+ z_nilf(result, 0xffff);
+ z_bru(done);
+
+ bind(notChar);
+ // compareU32_and_branch(ret_type, T_SHORT, bcondNotEqual, notShort);
+ z_lhr(result, result);
+
+ // Nothing to do for T_INT
+ bind(done);
+}
+
// remove activation
//
// Unlock the receiver if this is a synchronized method.
--- a/src/hotspot/cpu/s390/interp_masm_s390.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/s390/interp_masm_s390.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -86,6 +86,8 @@
void dispatch_next_noverify_oop(TosState state, int step = 0);
void dispatch_via(TosState state, address* table);
+ void narrow(Register result, Register ret_type);
+
// Jump to an invoked target.
void prepare_to_jump_from_interpreted(Register method);
void jump_from_interpreted(Register method, Register temp);
--- a/src/hotspot/cpu/s390/jni_s390.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016 SAP SE. 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 _JAVASOFT_JNI_MD_H_
-#define _JAVASOFT_JNI_MD_H_
-
-#if defined(__GNUC__) && (__GNUC__ >= 4)
- #define JNIEXPORT __attribute__((visibility("default")))
- #define JNIIMPORT __attribute__((visibility("default")))
-#else
- #define JNIEXPORT
- #define JNIIMPORT
-#endif
-
-#define JNICALL
-
-typedef int jint;
-
-typedef long int jlong;
-
-typedef signed char jbyte;
-
-#endif // _JAVASOFT_JNI_MD_H_
--- a/src/hotspot/cpu/s390/methodHandles_s390.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/s390/methodHandles_s390.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -24,12 +24,12 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/macroAssembler.inline.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "interpreter/interpreter.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "prims/methodHandles.hpp"
#ifdef PRODUCT
--- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1309,15 +1309,42 @@
}
} else {
__ z_lg(reg, offset, Z_SP);
- slot += VMRegImpl::slots_per_word;
- assert(slot <= stack_slots, "overflow (after LONG/ARRAY stack slot)");
}
+ slot += VMRegImpl::slots_per_word;
+ assert(slot <= stack_slots, "overflow (after LONG/ARRAY stack slot)");
}
}
// Save or restore single word registers.
for (int i = 0; i < total_in_args; i++) {
- if (in_regs[i].first()->is_FloatRegister()) {
+ if (in_regs[i].first()->is_Register()) {
+ int offset = slot * VMRegImpl::stack_slot_size;
+ // Value lives in an input register. Save it on stack.
+ switch (in_sig_bt[i]) {
+ case T_BOOLEAN:
+ case T_CHAR:
+ case T_BYTE:
+ case T_SHORT:
+ case T_INT: {
+ const Register reg = in_regs[i].first()->as_Register();
+ Address stackaddr(Z_SP, offset);
+ if (map != NULL) {
+ __ z_st(reg, stackaddr);
+ } else {
+ __ z_lgf(reg, stackaddr);
+ }
+ slot++;
+ assert(slot <= stack_slots, "overflow (after INT or smaller stack slot)");
+ break;
+ }
+ case T_ARRAY:
+ case T_LONG:
+ // handled above
+ break;
+ case T_OBJECT:
+ default: ShouldNotReachHere();
+ }
+ } else if (in_regs[i].first()->is_FloatRegister()) {
if (in_sig_bt[i] == T_FLOAT) {
int offset = slot * VMRegImpl::stack_slot_size;
slot++;
@@ -1908,7 +1935,7 @@
case T_ARRAY:
if (is_critical_native) {
int body_arg = cix;
- cix -= 2; // Point to length arg.
+ cix -= 1; // Point to length arg.
unpack_array_argument(masm, in_regs[jix], in_elem_bt[jix], out_regs[body_arg], out_regs[cix], stack_slots);
break;
}
--- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -2377,6 +2377,12 @@
__ store_const(Address(RjvmtiState, JvmtiThreadState::earlyret_state_offset()),
JvmtiThreadState::earlyret_inactive, 4, 4, Z_R0_scratch);
+ if (state == itos) {
+ // Narrow result if state is itos but result type is smaller.
+ // Need to narrow in the return bytecode rather than in generate_return_entry
+ // since compiled code callers expect the result to already be narrowed.
+ __ narrow(Z_tos, Z_tmp_1); /* fall through */
+ }
__ remove_activation(state,
Z_tmp_1, // retaddr
false, // throw_monitor_exception
--- a/src/hotspot/cpu/s390/templateTable_s390.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/s390/templateTable_s390.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1174,8 +1174,20 @@
__ pop_i(Z_ARG3);
__ pop_ptr(Z_tmp_2);
// Z_tos : value
- // Z_ARG3 : index
+ // Z_ARG3 : index
// Z_tmp_2 : array
+
+ // Need to check whether array is boolean or byte
+ // since both types share the bastore bytecode.
+ __ load_klass(Z_tmp_1, Z_tmp_2);
+ __ z_llgf(Z_tmp_1, Address(Z_tmp_1, Klass::layout_helper_offset()));
+ __ z_tmll(Z_tmp_1, Klass::layout_helper_boolean_diffbit());
+ Label L_skip;
+ __ z_bfalse(L_skip);
+ // if it is a T_BOOLEAN array, mask the stored value to 0/1
+ __ z_nilf(Z_tos, 0x1);
+ __ bind(L_skip);
+
// No index shift necessary - pass 0.
index_check(Z_tmp_2, Z_ARG3, 0); // Prefer index in Z_ARG3.
__ z_stc(Z_tos,
@@ -2321,6 +2333,13 @@
__ bind(skip_register_finalizer);
}
+ if (state == itos) {
+ // Narrow result if state is itos but result type is smaller.
+ // Need to narrow in the return bytecode rather than in generate_return_entry
+ // since compiled code callers expect the result to already be narrowed.
+ __ narrow(Z_tos, Z_tmp_1); /* fall through */
+ }
+
__ remove_activation(state, Z_R14);
__ z_br(Z_R14);
}
--- a/src/hotspot/cpu/s390/vm_version_s390.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/s390/vm_version_s390.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -24,11 +24,11 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/assembler.inline.hpp"
#include "compiler/disassembler.hpp"
#include "code/compiledIC.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "runtime/java.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "vm_version_s390.hpp"
--- a/src/hotspot/cpu/sparc/globals_sparc.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/sparc/globals_sparc.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -74,7 +74,7 @@
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
-define_pd_global(bool, UseMembar, false);
+define_pd_global(bool, UseMembar, true);
define_pd_global(bool, PreserveFramePointer, false);
--- a/src/hotspot/cpu/sparc/jni_sparc.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 1997, 2017, 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.
- */
-
-// Note: please do not change these without also changing jni_md.h in the JDK
-// repository
-#ifndef __has_attribute
- #define __has_attribute(x) 0
-#endif
-#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
- #define JNIEXPORT __attribute__((visibility("default")))
- #define JNIIMPORT __attribute__((visibility("default")))
-#else
- #define JNIEXPORT
- #define JNIIMPORT
-#endif
-#define JNICALL
-
-typedef int jint;
-
-typedef long jlong;
-
-typedef signed char jbyte;
--- a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/macroAssembler.inline.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/cardTableModRefBS.hpp"
@@ -31,7 +32,6 @@
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/klass.inline.hpp"
-#include "prims/jvm.h"
#include "prims/methodHandles.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/interfaceSupport.hpp"
--- a/src/hotspot/cpu/sparc/methodHandles_sparc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/sparc/methodHandles_sparc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,13 +23,13 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/macroAssembler.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interp_masm.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "prims/methodHandles.hpp"
#define __ _masm->
--- a/src/hotspot/cpu/sparc/templateInterpreterGenerator_sparc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/sparc/templateInterpreterGenerator_sparc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -319,7 +319,7 @@
#if INCLUDE_JVMCI
// Check if we need to take lock at entry of synchronized method. This can
// only occur on method entry so emit it only for vtos with step 0.
- if (UseJVMCICompiler && state == vtos && step == 0) {
+ if (EnableJVMCI && state == vtos && step == 0) {
Label L;
Address pending_monitor_enter_addr(G2_thread, JavaThread::pending_monitorenter_offset());
__ ldbool(pending_monitor_enter_addr, Gtemp); // Load if pending monitor enter
@@ -331,7 +331,7 @@
__ bind(L);
} else {
#ifdef ASSERT
- if (UseJVMCICompiler) {
+ if (EnableJVMCI) {
Label L;
Address pending_monitor_enter_addr(G2_thread, JavaThread::pending_monitorenter_offset());
__ ldbool(pending_monitor_enter_addr, Gtemp); // Load if pending monitor enter
--- a/src/hotspot/cpu/sparc/vm_version_sparc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/sparc/vm_version_sparc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,11 +23,11 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/macroAssembler.inline.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "runtime/stubCodeGenerator.hpp"
--- a/src/hotspot/cpu/x86/frame_x86.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/x86/frame_x86.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -436,11 +436,11 @@
// This is the sp before any possible extension (adapter/locals).
intptr_t* unextended_sp = interpreter_frame_sender_sp();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
if (map->update_map()) {
update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset));
}
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
return frame(sender_sp, unextended_sp, link(), sender_pc());
}
--- a/src/hotspot/cpu/x86/globals_x86.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/x86/globals_x86.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -46,11 +46,11 @@
// the the vep is aligned at CodeEntryAlignment whereas c2 only aligns
// the uep and the vep doesn't get real alignment but just slops on by
// only assured that the entry instruction meets the 5 byte size requirement.
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
define_pd_global(intx, CodeEntryAlignment, 32);
#else
define_pd_global(intx, CodeEntryAlignment, 16);
-#endif // COMPILER2
+#endif // COMPILER2_OR_JVMCI
define_pd_global(intx, OptoLoopAlignment, 16);
define_pd_global(intx, InlineFrequencyCount, 100);
define_pd_global(intx, InlineSmallCode, 1000);
@@ -84,11 +84,7 @@
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
-#ifdef _ALLBSD_SOURCE
define_pd_global(bool, UseMembar, true);
-#else
-define_pd_global(bool, UseMembar, false);
-#endif
// GC Ergo Flags
define_pd_global(size_t, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread
--- a/src/hotspot/cpu/x86/jni_x86.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 1997, 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. 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.
- */
-
-#ifndef _JAVASOFT_JNI_MD_H_
-#define _JAVASOFT_JNI_MD_H_
-
-#if defined(_WIN32)
- #define JNIEXPORT __declspec(dllexport)
- #define JNIIMPORT __declspec(dllimport)
- #define JNICALL __stdcall
-
- typedef int jint;
- typedef __int64 jlong;
-#else
-
-// Note: please do not change these without also changing jni_md.h in the JDK
-// repository
-#ifndef __has_attribute
- #define __has_attribute(x) 0
-#endif
-#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
- #define JNIEXPORT __attribute__((visibility("default")))
- #define JNIIMPORT __attribute__((visibility("default")))
-#else
- #define JNIEXPORT
- #define JNIIMPORT
-#endif
-
- #define JNICALL
- typedef int jint;
-#if defined(_LP64)
- typedef long jlong;
-#else
- typedef long long jlong;
-#endif
-
-#endif
-
-typedef signed char jbyte;
-
-#endif /* !_JAVASOFT_JNI_MD_H_ */
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "compiler/disassembler.hpp"
@@ -32,7 +33,6 @@
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/klass.inline.hpp"
-#include "prims/jvm.h"
#include "prims/methodHandles.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/interfaceSupport.hpp"
--- a/src/hotspot/cpu/x86/methodHandles_x86.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/x86/methodHandles_x86.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,13 +23,13 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/macroAssembler.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "prims/methodHandles.hpp"
#define __ _masm->
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -151,7 +151,7 @@
if (UseAVX < 3) {
num_xmm_regs = num_xmm_regs/2;
}
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
if (save_vectors) {
assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX");
assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported");
@@ -260,7 +260,7 @@
}
}
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
if (save_vectors) {
off = ymm0_off;
int delta = ymm1_off - off;
@@ -270,7 +270,7 @@
off += delta;
}
}
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
// %%% These should all be a waste but we'll keep things as they were for now
if (true) {
@@ -323,7 +323,7 @@
__ addptr(rsp, frame::arg_reg_save_area_bytes);
}
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
if (restore_vectors) {
assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX");
assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported");
@@ -2183,7 +2183,7 @@
// critical natives they are offset down.
GrowableArray<int> arg_order(2 * total_in_args);
VMRegPair tmp_vmreg;
- tmp_vmreg.set1(rbx->as_VMReg());
+ tmp_vmreg.set2(rbx->as_VMReg());
if (!is_critical_native) {
for (int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0; i--, c_arg--) {
--- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, 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
@@ -3433,6 +3433,8 @@
}
address generate_libmExp() {
+ StubCodeMark mark(this, "StubRoutines", "libmExp");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -3458,6 +3460,8 @@
}
address generate_libmLog() {
+ StubCodeMark mark(this, "StubRoutines", "libmLog");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -3483,6 +3487,8 @@
}
address generate_libmLog10() {
+ StubCodeMark mark(this, "StubRoutines", "libmLog10");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -3508,6 +3514,8 @@
}
address generate_libmPow() {
+ StubCodeMark mark(this, "StubRoutines", "libmPow");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -3533,6 +3541,8 @@
}
address generate_libm_reduce_pi04l() {
+ StubCodeMark mark(this, "StubRoutines", "libm_reduce_pi04l");
+
address start = __ pc();
BLOCK_COMMENT("Entry:");
@@ -3543,6 +3553,8 @@
}
address generate_libm_sin_cos_huge() {
+ StubCodeMark mark(this, "StubRoutines", "libm_sin_cos_huge");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -3556,6 +3568,8 @@
}
address generate_libmSin() {
+ StubCodeMark mark(this, "StubRoutines", "libmSin");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -3579,6 +3593,8 @@
}
address generate_libmCos() {
+ StubCodeMark mark(this, "StubRoutines", "libmCos");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -3604,6 +3620,8 @@
}
address generate_libm_tan_cot_huge() {
+ StubCodeMark mark(this, "StubRoutines", "libm_tan_cot_huge");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -3617,6 +3635,8 @@
}
address generate_libmTan() {
+ StubCodeMark mark(this, "StubRoutines", "libmTan");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -4619,6 +4619,8 @@
}
address generate_libmExp() {
+ StubCodeMark mark(this, "StubRoutines", "libmExp");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -4646,6 +4648,8 @@
}
address generate_libmLog() {
+ StubCodeMark mark(this, "StubRoutines", "libmLog");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -4674,6 +4678,8 @@
}
address generate_libmLog10() {
+ StubCodeMark mark(this, "StubRoutines", "libmLog10");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -4701,6 +4707,8 @@
}
address generate_libmPow() {
+ StubCodeMark mark(this, "StubRoutines", "libmPow");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -4731,6 +4739,8 @@
}
address generate_libmSin() {
+ StubCodeMark mark(this, "StubRoutines", "libmSin");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -4770,6 +4780,8 @@
}
address generate_libmCos() {
+ StubCodeMark mark(this, "StubRoutines", "libmCos");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
@@ -4809,6 +4821,8 @@
}
address generate_libmTan() {
+ StubCodeMark mark(this, "StubRoutines", "libmTan");
+
address start = __ pc();
const XMMRegister x0 = xmm0;
--- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -257,7 +257,7 @@
#if INCLUDE_JVMCI
// Check if we need to take lock at entry of synchronized method. This can
// only occur on method entry so emit it only for vtos with step 0.
- if ((UseJVMCICompiler || UseAOT) && state == vtos && step == 0) {
+ if ((EnableJVMCI || UseAOT) && state == vtos && step == 0) {
Label L;
__ cmpb(Address(thread, JavaThread::pending_monitorenter_offset()), 0);
__ jcc(Assembler::zero, L);
@@ -270,7 +270,7 @@
__ bind(L);
} else {
#ifdef ASSERT
- if (UseJVMCICompiler) {
+ if (EnableJVMCI) {
Label L;
__ cmpb(Address(r15_thread, JavaThread::pending_monitorenter_offset()), 0);
__ jccb(Assembler::zero, L);
--- a/src/hotspot/cpu/x86/vm_version_x86.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/cpu/x86/vm_version_x86.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,12 +23,12 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "runtime/stubCodeGenerator.hpp"
@@ -944,7 +944,7 @@
}
}
#endif
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
if (MaxVectorSize > 0) {
if (!is_power_of_2(MaxVectorSize)) {
warning("MaxVectorSize must be a power of 2");
@@ -996,7 +996,7 @@
}
#endif // COMPILER2 && ASSERT
}
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
#ifdef COMPILER2
#ifdef _LP64
--- a/src/hotspot/cpu/zero/jni_zero.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2009 Red Hat, Inc.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. 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.
- */
-
-
-
-// Note: please do not change these without also changing jni_md.h in the JDK
-// repository
-#ifndef __has_attribute
- #define __has_attribute(x) 0
-#endif
-#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
- #define JNIEXPORT __attribute__((visibility("default")))
- #define JNIIMPORT __attribute__((visibility("default")))
-#else
- #define JNIEXPORT
- #define JNIIMPORT
-#endif
-#define JNICALL
-
-typedef int jint;
-typedef signed char jbyte;
-
-#ifdef _LP64
-typedef long jlong;
-#else
-typedef long long jlong;
-#endif
--- a/src/hotspot/os/aix/jvm_aix.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/aix/jvm_aix.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -24,7 +24,7 @@
*/
#include "precompiled.hpp"
-#include "prims/jvm.h"
+#include "jvm.h"
#include "runtime/interfaceSupport.hpp"
#include "runtime/osThread.hpp"
--- a/src/hotspot/os/aix/jvm_aix.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2013 SAP SE. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef OS_AIX_VM_JVM_AIX_H
-#define OS_AIX_VM_JVM_AIX_H
-
-// HotSpot integration note:
-//
-// This is derived from the JDK classic file:
-// "$JDK/src/solaris/javavm/export/jvm_md.h":15 (ver. 1.10 98/04/22)
-// All local includes have been commented out.
-
-#ifndef JVM_MD_H
-#define JVM_MD_H
-
-/*
- * This file is currently collecting system-specific dregs for the
- * JNI conversion, which should be sorted out later.
- */
-
-#include <dirent.h> /* For DIR */
-
-// Must redefine NULL because the macro gets redefined to int 0
-// by dirent.h. This redefinition is included later then the standard definition in
-// globalDefinitions_<compiler>.hpp and leads to assertions in the VM initialization.
-// We definitely need NULL to have the same lengh as an address pointer.
-#ifdef _LP64
-#undef NULL
-#define NULL 0L
-#else
-#ifndef NULL
-#define NULL 0
-#endif
-#endif
-
-#include <sys/param.h> /* For MAXPATHLEN */
-#include <sys/socket.h> /* For socklen_t */
-#include <unistd.h> /* For F_OK, R_OK, W_OK */
-
-#define JNI_ONLOAD_SYMBOLS {"JNI_OnLoad"}
-#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"}
-#define JVM_ONLOAD_SYMBOLS {"JVM_OnLoad"}
-#define AGENT_ONLOAD_SYMBOLS {"Agent_OnLoad"}
-#define AGENT_ONUNLOAD_SYMBOLS {"Agent_OnUnload"}
-#define AGENT_ONATTACH_SYMBOLS {"Agent_OnAttach"}
-
-#define JNI_LIB_PREFIX "lib"
-#define JNI_LIB_SUFFIX ".so"
-
-#define JVM_MAXPATHLEN MAXPATHLEN
-
-#define JVM_R_OK R_OK
-#define JVM_W_OK W_OK
-#define JVM_X_OK X_OK
-#define JVM_F_OK F_OK
-
-/*
- * File I/O
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-/* O Flags */
-
-#define JVM_O_RDONLY O_RDONLY
-#define JVM_O_WRONLY O_WRONLY
-#define JVM_O_RDWR O_RDWR
-#define JVM_O_O_APPEND O_APPEND
-#define JVM_O_EXCL O_EXCL
-#define JVM_O_CREAT O_CREAT
-
-/* Signal definitions */
-
-#define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */
-#define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */
-#define SHUTDOWN2_SIGNAL SIGINT
-#define SHUTDOWN3_SIGNAL SIGTERM
-
-#endif /* JVM_MD_H */
-
-#endif // OS_AIX_VM_JVM_AIX_H
--- a/src/hotspot/os/aix/os_aix.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/aix/os_aix.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -28,6 +28,7 @@
#pragma alloca
// no precompiled headers
+#include "jvm.h"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
@@ -35,7 +36,6 @@
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_aix.h"
#include "logging/log.hpp"
#include "libo4.hpp"
#include "libperfstat_aix.hpp"
@@ -49,7 +49,6 @@
#include "os_share_aix.hpp"
#include "porting_aix.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
@@ -3249,7 +3248,7 @@
}
// ReduceSignalUsage allows the user to override these handlers
- // see comments at the very top and jvm_solaris.h
+ // see comments at the very top and jvm_md.h
if (!ReduceSignalUsage) {
DO_SIGNAL_CHECK(SHUTDOWN1_SIGNAL);
DO_SIGNAL_CHECK(SHUTDOWN2_SIGNAL);
--- a/src/hotspot/os/bsd/decoder_machO.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/bsd/decoder_machO.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -25,7 +25,7 @@
#include "precompiled.hpp"
#ifdef __APPLE__
-#include "prims/jvm.h"
+#include "jvm.h"
#include "decoder_machO.hpp"
#include <cxxabi.h>
--- a/src/hotspot/os/bsd/jvm_bsd.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/bsd/jvm_bsd.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "prims/jvm.h"
+#include "jvm.h"
#include "runtime/interfaceSupport.hpp"
#include "runtime/osThread.hpp"
--- a/src/hotspot/os/bsd/jvm_bsd.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef OS_BSD_VM_JVM_BSD_H
-#define OS_BSD_VM_JVM_BSD_H
-
-/*
-// HotSpot integration note:
-//
-// This is derived from the JDK classic file:
-// "$JDK/src/solaris/javavm/export/jvm_md.h":15 (ver. 1.10 98/04/22)
-// All local includes have been commented out.
-*/
-
-#ifndef JVM_MD_H
-#define JVM_MD_H
-
-/*
- * This file is currently collecting system-specific dregs for the
- * JNI conversion, which should be sorted out later.
- */
-
-#include <dirent.h> /* For DIR */
-#include <sys/param.h> /* For MAXPATHLEN */
-#include <sys/socket.h> /* For socklen_t */
-#include <unistd.h> /* For F_OK, R_OK, W_OK */
-
-#define JNI_ONLOAD_SYMBOLS {"JNI_OnLoad"}
-#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"}
-#define JVM_ONLOAD_SYMBOLS {"JVM_OnLoad"}
-#define AGENT_ONLOAD_SYMBOLS {"Agent_OnLoad"}
-#define AGENT_ONUNLOAD_SYMBOLS {"Agent_OnUnload"}
-#define AGENT_ONATTACH_SYMBOLS {"Agent_OnAttach"}
-
-#define JNI_LIB_PREFIX "lib"
-#ifdef __APPLE__
-#define JNI_LIB_SUFFIX ".dylib"
-#else
-#define JNI_LIB_SUFFIX ".so"
-#endif
-
-// Hack: MAXPATHLEN is 4095 on some Bsd and 4096 on others. This may
-// cause problems if JVM and the rest of JDK are built on different
-// Bsd releases. Here we define JVM_MAXPATHLEN to be MAXPATHLEN + 1,
-// so buffers declared in VM are always >= 4096.
-#define JVM_MAXPATHLEN MAXPATHLEN + 1
-
-#define JVM_R_OK R_OK
-#define JVM_W_OK W_OK
-#define JVM_X_OK X_OK
-#define JVM_F_OK F_OK
-
-/*
- * File I/O
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-/* O Flags */
-
-#define JVM_O_RDONLY O_RDONLY
-#define JVM_O_WRONLY O_WRONLY
-#define JVM_O_RDWR O_RDWR
-#define JVM_O_O_APPEND O_APPEND
-#define JVM_O_EXCL O_EXCL
-#define JVM_O_CREAT O_CREAT
-
-/* Signal definitions */
-
-#define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */
-#define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */
-#define SHUTDOWN2_SIGNAL SIGINT
-#define SHUTDOWN3_SIGNAL SIGTERM
-
-#ifndef SIGRTMIN
-#ifdef __OpenBSD__
-#define SIGRTMIN 1
-#else
-#define SIGRTMIN 33
-#endif
-#endif
-#ifndef SIGRTMAX
-#ifdef __OpenBSD__
-#define SIGRTMAX 31
-#else
-#define SIGRTMAX 63
-#endif
-#endif
-#endif /* JVM_MD_H */
-
-#endif // OS_BSD_VM_JVM_BSD_H
--- a/src/hotspot/os/bsd/os_bsd.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/bsd/os_bsd.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
@@ -31,7 +32,6 @@
#include "compiler/compileBroker.hpp"
#include "compiler/disassembler.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_bsd.h"
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
@@ -39,7 +39,6 @@
#include "os_bsd.inline.hpp"
#include "os_share_bsd.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
@@ -3240,7 +3239,7 @@
// ReduceSignalUsage allows the user to override these handlers
- // see comments at the very top and jvm_solaris.h
+ // see comments at the very top and jvm_md.h
if (!ReduceSignalUsage) {
DO_SIGNAL_CHECK(SHUTDOWN1_SIGNAL);
DO_SIGNAL_CHECK(SHUTDOWN2_SIGNAL);
--- a/src/hotspot/os/linux/decoder_linux.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/linux/decoder_linux.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,7 +22,7 @@
*
*/
-#include "prims/jvm.h"
+#include "jvm.h"
#include "utilities/decoder_elf.hpp"
#include <cxxabi.h>
--- a/src/hotspot/os/linux/jvm_linux.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/linux/jvm_linux.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "prims/jvm.h"
+#include "jvm.h"
#include "runtime/interfaceSupport.hpp"
#include "runtime/osThread.hpp"
--- a/src/hotspot/os/linux/jvm_linux.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef OS_LINUX_VM_JVM_LINUX_H
-#define OS_LINUX_VM_JVM_LINUX_H
-
-/*
-// HotSpot integration note:
-//
-// This is derived from the JDK classic file:
-// "$JDK/src/solaris/javavm/export/jvm_md.h":15 (ver. 1.10 98/04/22)
-// All local includes have been commented out.
-*/
-
-#ifndef JVM_MD_H
-#define JVM_MD_H
-
-/*
- * This file is currently collecting system-specific dregs for the
- * JNI conversion, which should be sorted out later.
- */
-
-#include <dirent.h> /* For DIR */
-#include <sys/param.h> /* For MAXPATHLEN */
-#include <sys/socket.h> /* For socklen_t */
-#include <unistd.h> /* For F_OK, R_OK, W_OK */
-
-#define JNI_ONLOAD_SYMBOLS {"JNI_OnLoad"}
-#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"}
-#define JVM_ONLOAD_SYMBOLS {"JVM_OnLoad"}
-#define AGENT_ONLOAD_SYMBOLS {"Agent_OnLoad"}
-#define AGENT_ONUNLOAD_SYMBOLS {"Agent_OnUnload"}
-#define AGENT_ONATTACH_SYMBOLS {"Agent_OnAttach"}
-
-#define JNI_LIB_PREFIX "lib"
-#define JNI_LIB_SUFFIX ".so"
-
-// Hack: MAXPATHLEN is 4095 on some Linux and 4096 on others. This may
-// cause problems if JVM and the rest of JDK are built on different
-// Linux releases. Here we define JVM_MAXPATHLEN to be MAXPATHLEN + 1,
-// so buffers declared in VM are always >= 4096.
-#define JVM_MAXPATHLEN MAXPATHLEN + 1
-
-#define JVM_R_OK R_OK
-#define JVM_W_OK W_OK
-#define JVM_X_OK X_OK
-#define JVM_F_OK F_OK
-
-/*
- * File I/O
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-/* O Flags */
-
-#define JVM_O_RDONLY O_RDONLY
-#define JVM_O_WRONLY O_WRONLY
-#define JVM_O_RDWR O_RDWR
-#define JVM_O_O_APPEND O_APPEND
-#define JVM_O_EXCL O_EXCL
-#define JVM_O_CREAT O_CREAT
-
-/* Signal definitions */
-
-#define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */
-#define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */
-#define SHUTDOWN2_SIGNAL SIGINT
-#define SHUTDOWN3_SIGNAL SIGTERM
-
-#endif /* JVM_MD_H */
-
-#endif // OS_LINUX_VM_JVM_LINUX_H
--- a/src/hotspot/os/linux/os_linux.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/linux/os_linux.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
@@ -31,7 +32,6 @@
#include "compiler/compileBroker.hpp"
#include "compiler/disassembler.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_linux.h"
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
@@ -39,7 +39,6 @@
#include "os_linux.inline.hpp"
#include "os_share_linux.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
@@ -4664,7 +4663,7 @@
#endif
// ReduceSignalUsage allows the user to override these handlers
- // see comments at the very top and jvm_solaris.h
+ // see comments at the very top and jvm_md.h
if (!ReduceSignalUsage) {
DO_SIGNAL_CHECK(SHUTDOWN1_SIGNAL);
DO_SIGNAL_CHECK(SHUTDOWN2_SIGNAL);
--- a/src/hotspot/os/posix/os_posix.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/posix/os_posix.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,8 +22,8 @@
*
*/
+#include "jvm.h"
#include "utilities/globalDefinitions.hpp"
-#include "prims/jvm.h"
#include "runtime/frame.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/os.hpp"
--- a/src/hotspot/os/solaris/jvm_solaris.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/solaris/jvm_solaris.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "prims/jvm.h"
+#include "jvm.h"
#include "runtime/interfaceSupport.hpp"
#include "runtime/osThread.hpp"
--- a/src/hotspot/os/solaris/jvm_solaris.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef OS_SOLARIS_VM_JVM_SOLARIS_H
-#define OS_SOLARIS_VM_JVM_SOLARIS_H
-
-/*
-// HotSpot integration note:
-//
-// This is derived from the JDK classic file:
-// "$JDK/src/solaris/javavm/export/jvm_md.h":15 (ver. 1.10 98/04/22)
-// All local includes have been commented out.
-*/
-
-#ifndef JVM_MD_H
-#define JVM_MD_H
-
-/*
- * This file is currently collecting system-specific dregs for the
- * JNI conversion, which should be sorted out later.
- */
-
-#include <dirent.h> /* For DIR */
-#include <sys/param.h> /* For MAXPATHLEN */
-#include <sys/socket.h> /* For socklen_t */
-#include <unistd.h> /* For F_OK, R_OK, W_OK */
-#include <sys/int_types.h> /* for intptr_t types (64 Bit cleanliness) */
-
-#define JNI_ONLOAD_SYMBOLS {"JNI_OnLoad"}
-#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"}
-#define JVM_ONLOAD_SYMBOLS {"JVM_OnLoad"}
-#define AGENT_ONLOAD_SYMBOLS {"Agent_OnLoad"}
-#define AGENT_ONUNLOAD_SYMBOLS {"Agent_OnUnload"}
-#define AGENT_ONATTACH_SYMBOLS {"Agent_OnAttach"}
-
-#define JNI_LIB_PREFIX "lib"
-#define JNI_LIB_SUFFIX ".so"
-
-#define JVM_MAXPATHLEN MAXPATHLEN
-
-#define JVM_R_OK R_OK
-#define JVM_W_OK W_OK
-#define JVM_X_OK X_OK
-#define JVM_F_OK F_OK
-
-/*
- * File I/O
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-/* O Flags */
-
-#define JVM_O_RDONLY O_RDONLY
-#define JVM_O_WRONLY O_WRONLY
-#define JVM_O_RDWR O_RDWR
-#define JVM_O_O_APPEND O_APPEND
-#define JVM_O_EXCL O_EXCL
-#define JVM_O_CREAT O_CREAT
-
-/* Signal definitions */
-
-#define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */
-#define ASYNC_SIGNAL SIGJVM2 /* Event-based suspend/resume support */
-#define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */
-#define SHUTDOWN2_SIGNAL SIGINT
-#define SHUTDOWN3_SIGNAL SIGTERM
-
-/* With 1.4.1 libjsig added versioning: used in os_solaris.cpp and jsig.c */
-#define JSIG_VERSION_1_4_1 0x30140100
-
-#endif /* JVM_MD_H */
-
-#endif // OS_SOLARIS_VM_JVM_SOLARIS_H
--- a/src/hotspot/os/solaris/os_solaris.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/solaris/os_solaris.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
@@ -31,7 +32,6 @@
#include "compiler/compileBroker.hpp"
#include "compiler/disassembler.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_solaris.h"
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
@@ -39,7 +39,6 @@
#include "os_share_solaris.hpp"
#include "os_solaris.inline.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
--- a/src/hotspot/os/windows/jvm_windows.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/windows/jvm_windows.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "prims/jvm.h"
+#include "jvm.h"
#include "runtime/interfaceSupport.hpp"
#include "runtime/osThread.hpp"
--- a/src/hotspot/os/windows/jvm_windows.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 1998, 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.
- *
- */
-
-#ifndef OS_WINDOWS_VM_JVM_WINDOWS_H
-#define OS_WINDOWS_VM_JVM_WINDOWS_H
-
-#ifndef _JAVASOFT_JVM_MD_H_
-#define _JAVASOFT_JVM_MD_H_
-
-/*
- * This file is currently collecting system-specific dregs for the
- * JNI conversion, which should be sorted out later.
- */
-
-// JDK7 requires VS2010
-#if _MSC_VER >= 1600
-// JDK7 minimum platform requirement: Windows XP
-#if _WIN32_WINNT < 0x0501
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-#endif
-
-#include <windows.h>
-
-#include <Psapi.h>
-#include <Tlhelp32.h>
-
-typedef int socklen_t;
-
-#define JNI_ONLOAD_SYMBOLS {"_JNI_OnLoad@8", "JNI_OnLoad"}
-#define JNI_ONUNLOAD_SYMBOLS {"_JNI_OnUnload@8", "JNI_OnUnload"}
-#define JVM_ONLOAD_SYMBOLS {"_JVM_OnLoad@12", "JVM_OnLoad"}
-#define AGENT_ONLOAD_SYMBOLS {"_Agent_OnLoad@12", "Agent_OnLoad"}
-#define AGENT_ONUNLOAD_SYMBOLS {"_Agent_OnUnload@4", "Agent_OnUnload"}
-#define AGENT_ONATTACH_SYMBOLS {"_Agent_OnAttach@12", "Agent_OnAttach"}
-
-#define JNI_LIB_PREFIX ""
-#define JNI_LIB_SUFFIX ".dll"
-
-struct dirent {
- char d_name[MAX_PATH];
-};
-
-typedef struct {
- struct dirent dirent;
- char *path;
- HANDLE handle;
- WIN32_FIND_DATA find_data;
-} DIR;
-
-#include <stdlib.h>
-
-#define JVM_MAXPATHLEN _MAX_PATH
-
-#define JVM_R_OK 4
-#define JVM_W_OK 2
-#define JVM_X_OK 1
-#define JVM_F_OK 0
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-JNIEXPORT void * JNICALL
-JVM_GetThreadInterruptEvent();
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
-
-/*
- * File I/O
- */
-
-#include <sys/stat.h>
-
-/* O Flags */
-
-#define JVM_O_RDONLY O_RDONLY
-#define JVM_O_WRONLY O_WRONLY
-#define JVM_O_RDWR O_RDWR
-#define JVM_O_O_APPEND O_APPEND
-#define JVM_O_EXCL O_EXCL
-#define JVM_O_CREAT O_CREAT
-
-/* Signals */
-
-#define JVM_SIGINT SIGINT
-#define JVM_SIGTERM SIGTERM
-
-#define SHUTDOWN1_SIGNAL SIGINT /* Shutdown Hooks support. */
-#define SHUTDOWN2_SIGNAL SIGTERM
-
-#endif /* !_JAVASOFT_JVM_MD_H_ */
-
-#endif // OS_WINDOWS_VM_JVM_WINDOWS_H
--- a/src/hotspot/os/windows/os_windows.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/windows/os_windows.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -26,6 +26,7 @@
#define _WIN32_WINNT 0x0600
// no precompiled headers
+#include "jvm.h"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
@@ -34,7 +35,6 @@
#include "compiler/compileBroker.hpp"
#include "compiler/disassembler.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_windows.h"
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
@@ -42,7 +42,6 @@
#include "os_share_windows.hpp"
#include "os_windows.inline.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
@@ -100,6 +99,7 @@
#include <imagehlp.h> // For os::dll_address_to_function_name
// for enumerating dll libraries
#include <vdmdbg.h>
+#include <psapi.h>
// for timer info max values which include all bits
#define ALL_64_BITS CONST64(-1)
@@ -3656,7 +3656,7 @@
static INIT_ONCE init_once_crit_sect = INIT_ONCE_STATIC_INIT;
static CRITICAL_SECTION crit_sect;
- static volatile jint process_exiting = 0;
+ static volatile DWORD process_exiting = 0;
int i, j;
DWORD res;
HANDLE hproc, hthr;
@@ -3675,7 +3675,7 @@
if (what != EPT_THREAD) {
// Atomically set process_exiting before the critical section
// to increase the visibility between racing threads.
- Atomic::cmpxchg((jint)GetCurrentThreadId(), &process_exiting, 0);
+ Atomic::cmpxchg(GetCurrentThreadId(), &process_exiting, (DWORD)0);
}
EnterCriticalSection(&crit_sect);
@@ -3793,7 +3793,7 @@
if (!registered &&
OrderAccess::load_acquire(&process_exiting) != 0 &&
- process_exiting != (jint)GetCurrentThreadId()) {
+ process_exiting != GetCurrentThreadId()) {
// Some other thread is about to call exit(), so we don't let
// the current unregistered thread proceed to exit() or _endthreadex()
while (true) {
--- a/src/hotspot/os/windows/threadCritical_windows.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os/windows/threadCritical_windows.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -36,7 +36,7 @@
//
static bool initialized = false;
-static volatile jint lock_count = -1;
+static volatile int lock_count = -1;
static HANDLE lock_event;
static DWORD lock_owner = -1;
--- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -24,6 +24,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "asm/assembler.inline.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
@@ -32,12 +33,10 @@
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_aix.h"
#include "memory/allocation.inline.hpp"
#include "nativeInst_ppc.hpp"
#include "os_share_aix.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "porting_aix.hpp"
#include "runtime/arguments.hpp"
--- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "asm/macroAssembler.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
@@ -31,11 +32,9 @@
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_bsd.h"
#include "memory/allocation.inline.hpp"
#include "os_share_bsd.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
--- a/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/bsd_x86/thread_bsd_x86.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -73,7 +73,7 @@
frame ret_frame(ret_sp, ret_fp, addr.pc());
if (!ret_frame.safe_for_sender(jt)) {
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
// C2 and JVMCI use ebp as a general register see if NULL fp helps
frame ret_frame2(ret_sp, NULL, addr.pc());
if (!ret_frame2.safe_for_sender(jt)) {
@@ -84,7 +84,7 @@
#else
// nothing else to try if the frame isn't good
return false;
-#endif /* COMPILER2 || INCLUDE_JVMCI */
+#endif // COMPILER2_OR_JVMCI
}
*fr_addr = ret_frame;
return true;
--- a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -29,6 +29,7 @@
#endif
// no precompiled headers
+#include "jvm.h"
#include "assembler_zero.inline.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
@@ -36,12 +37,10 @@
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_bsd.h"
#include "memory/allocation.inline.hpp"
#include "nativeInst_zero.hpp"
#include "os_share_bsd.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
--- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -24,6 +24,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "asm/macroAssembler.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
@@ -33,11 +34,9 @@
#include "code/vtableStubs.hpp"
#include "code/nativeInst.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_linux.h"
#include "memory/allocation.inline.hpp"
#include "os_share_linux.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
@@ -234,8 +233,17 @@
}
intptr_t* _get_previous_fp() {
- register intptr_t **ebp __asm__ (SPELL_REG_FP);
- return (intptr_t*) *ebp; // we want what it points to.
+ register intptr_t **fp __asm__ (SPELL_REG_FP);
+
+ // fp is for this frame (_get_previous_fp). We want the fp for the
+ // caller of os::current_frame*(), so go up two frames. However, for
+ // optimized builds, _get_previous_fp() will be inlined, so only go
+ // up 1 frame in that case.
+ #ifdef _NMT_NOINLINE_
+ return **(intptr_t***)fp;
+ #else
+ return *fp;
+ #endif
}
--- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "assembler_arm.inline.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
@@ -30,12 +31,10 @@
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_linux.h"
#include "memory/allocation.inline.hpp"
#include "nativeInst_arm.hpp"
#include "os_share_linux.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -24,6 +24,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "asm/assembler.inline.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
@@ -32,12 +33,10 @@
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_linux.h"
#include "memory/allocation.inline.hpp"
#include "nativeInst_ppc.hpp"
#include "os_share_linux.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
--- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -26,6 +26,7 @@
// This file is organized as os_linux_x86.cpp.
// no precompiled headers
+#include "jvm.h"
#include "asm/assembler.inline.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
@@ -35,12 +36,10 @@
#include "code/vtableStubs.hpp"
#include "compiler/disassembler.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_linux.h"
#include "memory/allocation.inline.hpp"
#include "nativeInst_s390.hpp"
#include "os_share_linux.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
--- a/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "asm/macroAssembler.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
@@ -31,12 +32,10 @@
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_linux.h"
#include "memory/allocation.inline.hpp"
#include "nativeInst_sparc.hpp"
#include "os_share_linux.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
--- a/src/hotspot/os_cpu/linux_sparc/vm_version_linux_sparc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/linux_sparc/vm_version_linux_sparc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,58 +27,326 @@
#include "runtime/os.hpp"
#include "vm_version_sparc.hpp"
-static bool cpuinfo_field_contains(const char* field, const char* value) {
- char line[1024];
- bool rv = false;
+
+#define CPUINFO_LINE_SIZE 1024
+
+
+class CPUinfo {
+public:
+ CPUinfo(const char* field) : _string(NULL) {
+
+ char line[CPUINFO_LINE_SIZE];
+ FILE* fp = fopen("/proc/cpuinfo", "r");
- FILE* fp = fopen("/proc/cpuinfo", "r");
- if (fp == NULL) {
- return rv;
- }
+ if (fp != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ assert(strlen(line) < sizeof(line) - 1,
+ "buffer too small (%d)", CPUINFO_LINE_SIZE);
+
+ const char* vstr = match_field(line, field);
- while (fgets(line, sizeof(line), fp) != NULL) {
- assert(strlen(line) < sizeof(line) - 1, "buffer line[1024] is too small.");
- if (strncmp(line, field, strlen(field)) == 0) {
- if (strstr(line, value) != NULL) {
- rv = true;
+ if (vstr != NULL) {
+ // We have a matching line and a valid starting point to the value of
+ // the field, copy the string for keeps.
+ _string = strdup(vstr);
+ break;
+ }
}
- break;
+ fclose(fp);
}
}
- fclose(fp);
- return rv;
+ ~CPUinfo() { os::free((void*)_string); }
+
+ const char* value() const { return _string; }
+
+ bool valid() const { return _string != NULL; }
+
+ bool match(const char* s) const {
+ return valid() ? strcmp(_string, s) == 0 : false;
+ }
+
+private:
+ const char* _string;
+
+ const char* match_field(char line[CPUINFO_LINE_SIZE], const char* field);
+ const char* match_alo(const char* text, const char* exp);
+ const char* match_seq(const char* text, const char* seq);
+};
+
+/* Given a line of text read from /proc/cpuinfo, determine if the property header
+ * matches the field specified, according to the following regexp: "<field>"\W+:\W+
+ *
+ * If we have a matching expression, return a pointer to the first character after
+ * the matching pattern, i.e. the "value", otherwise return NULL.
+ */
+const char* CPUinfo::match_field(char line[CPUINFO_LINE_SIZE], const char* field) {
+ return match_alo(match_seq(match_alo(match_seq(line, field), "\t "), ":"), "\t ");
}
-static bool detect_niagara() {
- return cpuinfo_field_contains("cpu", "Niagara");
+/* Match a sequence of at-least-one character in the string expression (exp) to
+ * the text input.
+ */
+const char* CPUinfo::match_alo(const char* text, const char* exp) {
+ if (text == NULL) return NULL;
+
+ const char* chp;
+
+ for (chp = &text[0]; *chp != '\0'; chp++) {
+ if (strchr(exp, *chp) == NULL) break;
+ }
+
+ return text < chp ? chp : NULL;
}
-static bool detect_M_family() {
- return cpuinfo_field_contains("cpu", "SPARC-M");
-}
+/* Match an exact sequence of characters as specified by the string expression
+ * (seq) to the text input.
+ */
+const char* CPUinfo::match_seq(const char* text, const char* seq) {
+ if (text == NULL) return NULL;
-static bool detect_blkinit() {
- return cpuinfo_field_contains("cpucaps", "blkinit");
+ while (*seq != '\0') {
+ if (*seq != *text++) break; else seq++;
+ }
+
+ return *seq == '\0' ? text : NULL;
}
-int VM_Version::platform_features(int features) {
- // Default to generic v9
- features = generic_v9_m;
+
+typedef struct {
+ const uint32_t hash;
+ bool seen;
+ const char* const name;
+ const uint64_t mask;
+} FeatureEntry;
+
+
+static uint64_t parse_features(FeatureEntry feature_tbl[], const char input[]);
+
+
+void VM_Version::platform_features() {
+
+ // Some of the features reported via "cpucaps", such as; 'flush', 'stbar',
+ // 'swap', 'muldiv', 'ultra3', 'blkinit', 'n2', 'mul32', 'div32', 'fsmuld'
+ // and 'v8plus', are either SPARC V8, supported by all HW or simply nonsense
+ // (the 'ultra3' "property").
+ //
+ // Entries marked as 'NYI' are not yet supported via "cpucaps" but are
+ // expected to have the names used in the table below (these are SPARC M7
+ // features or more recent).
+ //
+ // NOTE: Table sorted on lookup/hash ID.
- if (detect_niagara()) {
- log_info(os, cpu)("Detected Linux on Niagara");
- features = niagara1_m | T_family_m;
+ static FeatureEntry s_feature_tbl[] = {
+ { 0x006f, false, "v9", ISA_v9_msk }, // Mandatory
+ { 0x00a6, false, "md5", ISA_md5_msk },
+ { 0x00ce, false, "adi", ISA_adi_msk }, // NYI
+ { 0x00d7, false, "ima", ISA_ima_msk },
+ { 0x00d9, false, "aes", ISA_aes_msk },
+ { 0x00db, false, "hpc", ISA_hpc_msk },
+ { 0x00dc, false, "des", ISA_des_msk },
+ { 0x00ed, false, "sha1", ISA_sha1_msk },
+ { 0x00f2, false, "vis", ISA_vis1_msk },
+ { 0x0104, false, "vis2", ISA_vis2_msk },
+ { 0x0105, false, "vis3", ISA_vis3_msk },
+ { 0x0114, false, "sha512", ISA_sha512_msk },
+ { 0x0119, false, "sha256", ISA_sha256_msk },
+ { 0x011a, false, "fmaf", ISA_fmaf_msk },
+ { 0x0132, false, "popc", ISA_popc_msk },
+ { 0x0140, false, "crc32c", ISA_crc32c_msk },
+ { 0x0147, false, "vis3b", ISA_vis3b_msk }, // NYI
+ { 0x017e, false, "pause", ISA_pause_msk },
+ { 0x0182, false, "mwait", ISA_mwait_msk }, // NYI
+ { 0x018b, false, "mpmul", ISA_mpmul_msk },
+ { 0x018e, false, "sparc5", ISA_sparc5_msk }, // NYI
+ { 0x01a9, false, "cbcond", ISA_cbcond_msk },
+ { 0x01c3, false, "vamask", ISA_vamask_msk }, // NYI
+ { 0x01ca, false, "kasumi", ISA_kasumi_msk },
+ { 0x01e3, false, "xmpmul", ISA_xmpmul_msk }, // NYI
+ { 0x022c, false, "montmul", ISA_mont_msk },
+ { 0x0234, false, "montsqr", ISA_mont_msk },
+ { 0x0238, false, "camellia", ISA_camellia_msk },
+ { 0x024a, false, "ASIBlkInit", ISA_blk_init_msk },
+ { 0x0284, false, "xmontmul", ISA_xmont_msk }, // NYI
+ { 0x02e6, false, "pause_nsec", ISA_pause_nsec_msk }, // NYI
+
+ { 0x0000, false, NULL, 0 }
+ };
+
+ CPUinfo caps("cpucaps"); // Read "cpucaps" from /proc/cpuinfo.
+
+ assert(caps.valid(), "must be");
+
+ _features = parse_features(s_feature_tbl, caps.value());
+
+ assert(has_v9(), "must be"); // Basic SPARC-V9 required (V8 not supported).
+
+ CPUinfo type("type");
+
+ bool is_sun4v = type.match("sun4v"); // All Oracle SPARC + Fujitsu Athena+
+ bool is_sun4u = type.match("sun4u"); // All other Fujitsu
+
+ uint64_t synthetic = 0;
+
+ if (is_sun4v) {
+ // Indirect and direct branches are equally fast.
+ synthetic = CPU_fast_ind_br_msk;
+ // Fast IDIV, BIS and LD available on Niagara Plus.
+ if (has_vis2()) {
+ synthetic |= (CPU_fast_idiv_msk | CPU_fast_ld_msk);
+ // ...on Core C4 however, we prefer not to use BIS.
+ if (!has_sparc5()) {
+ synthetic |= CPU_fast_bis_msk;
+ }
+ }
+ // Niagara Core C3 supports fast RDPC and block zeroing.
+ if (has_ima()) {
+ synthetic |= (CPU_fast_rdpc_msk | CPU_blk_zeroing_msk);
+ }
+ // Niagara Core C3 and C4 have slow CMOVE.
+ if (!has_ima()) {
+ synthetic |= CPU_fast_cmove_msk;
+ }
+ } else if (is_sun4u) {
+ // SPARC64 only have fast IDIV and RDPC.
+ synthetic |= (CPU_fast_idiv_msk | CPU_fast_rdpc_msk);
+ } else {
+ log_info(os, cpu)("Unable to derive CPU features: %s", type.value());
}
- if (detect_M_family()) {
- log_info(os, cpu)("Detected Linux on M family");
- features = sun4v_m | generic_v9_m | M_family_m | T_family_m;
+ _features += synthetic; // Including CPU derived/synthetic features.
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+static uint32_t uhash32(const char name[]);
+
+static void update_table(FeatureEntry feature_tbl[], uint32_t hv,
+ const char* ch1p,
+ const char* endp);
+
+/* Given a feature table, parse the input text holding the string value of
+ * 'cpucaps' as reported by '/proc/cpuinfo', in order to complete the table
+ * with information on each admissible feature (whether present or not).
+ *
+ * Return the composite bit-mask representing the features found.
+ */
+static uint64_t parse_features(FeatureEntry feature_tbl[], const char input[]) {
+ log_info(os, cpu)("Parse CPU features: %s\n", input);
+
+#ifdef ASSERT
+ // Verify that hash value entries in the table are unique and ordered.
+
+ uint32_t prev = 0;
+
+ for (uint k = 0; feature_tbl[k].name != NULL; k++) {
+ feature_tbl[k].seen = false;
+
+ assert(feature_tbl[k].hash == uhash32(feature_tbl[k].name),
+ "feature '%s' has mismatching hash 0x%08x (expected 0x%08x).\n",
+ feature_tbl[k].name,
+ feature_tbl[k].hash,
+ uhash32(feature_tbl[k].name));
+
+ assert(prev < feature_tbl[k].hash,
+ "feature '%s' has invalid hash 0x%08x (previous is 0x%08x).\n",
+ feature_tbl[k].name,
+ feature_tbl[k].hash,
+ prev);
+
+ prev = feature_tbl[k].hash;
+ }
+#endif
+ // Identify features from the input, consisting of a string with features
+ // separated by commas (or whitespace), e.g. "flush,muldiv,v9,mul32,div32,
+ // v8plus,popc,vis".
+
+ uint32_t hv = 0;
+ const char* ch1p = &input[0];
+ uint i = 0;
+
+ do {
+ char ch = input[i];
+
+ if (isalnum(ch) || ch == '_') {
+ hv += (ch - 32u);
+ }
+ else if (isspace(ch) || ch == ',' || ch == '\0') { // end-of-token
+ if (ch1p < &input[i]) {
+ update_table(feature_tbl, hv, ch1p, &input[i]);
+ }
+ ch1p = &input[i + 1]; hv = 0;
+ } else {
+ // Handle non-accepted input robustly.
+ log_info(os, cpu)("Bad token in feature string: '%c' (0x%02x).\n", ch, ch);
+ ch1p = &input[i + 1]; hv = 0;
+ }
+ }
+ while (input[i++] != '\0');
+
+ // Compute actual bit-mask representation.
+
+ uint64_t mask = 0;
+
+ for (uint k = 0; feature_tbl[k].name != NULL; k++) {
+ mask |= feature_tbl[k].seen ? feature_tbl[k].mask : 0;
}
- if (detect_blkinit()) {
- features |= blk_init_instructions_m;
+ return mask;
+}
+
+static uint32_t uhash32(const char name[]) {
+ uint32_t hv = 0;
+
+ for (uint i = 0; name[i] != '\0'; i++) {
+ hv += (name[i] - 32u);
}
- return features;
+ return hv;
}
+
+static bool verify_match(const char name[], const char* ch1p, const char* endp);
+
+static void update_table(FeatureEntry feature_tbl[], uint32_t hv, const char* ch1p, const char* endp) {
+ assert(ch1p < endp, "at least one character");
+
+ // Look for a hash value in the table. Since this table is a small one (and
+ // is expected to stay small), we use a simple linear search (iff the table
+ // grows large, we may consider to adopt a binary ditto, or a perfect hash).
+
+ for (uint k = 0; feature_tbl[k].name != NULL; k++) {
+ uint32_t hash = feature_tbl[k].hash;
+
+ if (hash < hv) continue;
+
+ if (hash == hv) {
+ const char* name = feature_tbl[k].name;
+
+ if (verify_match(name, ch1p, endp)) {
+ feature_tbl[k].seen = true;
+ break;
+ }
+ }
+
+ // Either a non-matching feature (when hash == hv) or hash > hv. In either
+ // case we break out of the loop and terminate the search (note that the
+ // table is assumed to be uniquely sorted on the hash).
+
+ break;
+ }
+}
+
+static bool verify_match(const char name[], const char* ch1p, const char* endp) {
+ size_t len = strlen(name);
+
+ if (len != static_cast<size_t>(endp - ch1p)) {
+ return false;
+ }
+
+ for (uint i = 0; ch1p + i < endp; i++) {
+ if (name[i] != ch1p[i]) return false;
+ }
+
+ return true;
+}
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "asm/macroAssembler.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
@@ -31,11 +32,9 @@
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_linux.h"
#include "memory/allocation.inline.hpp"
#include "os_share_linux.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
--- a/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/linux_x86/thread_linux_x86.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -74,7 +74,7 @@
frame ret_frame(ret_sp, ret_fp, addr.pc());
if (!ret_frame.safe_for_sender(jt)) {
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
// C2 and JVMCI use ebp as a general register see if NULL fp helps
frame ret_frame2(ret_sp, NULL, addr.pc());
if (!ret_frame2.safe_for_sender(jt)) {
@@ -85,7 +85,7 @@
#else
// nothing else to try if the frame isn't good
return false;
-#endif /* COMPILER2 || INCLUDE_JVMCI */
+#endif // COMPILER2_OR_JVMCI
}
*fr_addr = ret_frame;
return true;
--- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -24,6 +24,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "assembler_zero.inline.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
@@ -31,12 +32,10 @@
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_linux.h"
#include "memory/allocation.inline.hpp"
#include "nativeInst_zero.hpp"
#include "os_share_linux.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
--- a/src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/solaris_sparc/os_solaris_sparc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "asm/macroAssembler.hpp"
#include "macroAssembler_sparc.hpp"
#include "classfile/classLoader.hpp"
@@ -32,12 +33,10 @@
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_solaris.h"
#include "memory/allocation.inline.hpp"
#include "nativeInst_sparc.hpp"
#include "os_share_solaris.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
--- a/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/solaris_x86/os_solaris_x86.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "asm/macroAssembler.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
@@ -31,11 +32,9 @@
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_solaris.h"
#include "memory/allocation.inline.hpp"
#include "os_share_solaris.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
--- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
// no precompiled headers
+#include "jvm.h"
#include "asm/macroAssembler.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
@@ -30,13 +31,11 @@
#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "jvm_windows.h"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "nativeInst_x86.hpp"
#include "os_share_windows.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/extendedPC.hpp"
--- a/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/os_cpu/windows_x86/thread_windows_x86.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -81,7 +81,7 @@
frame ret_frame(ret_sp, ret_fp, addr.pc());
if (!ret_frame.safe_for_sender(jt)) {
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
// C2 and JVMCI use ebp as a general register see if NULL fp helps
frame ret_frame2(ret_sp, NULL, addr.pc());
if (!ret_frame2.safe_for_sender(jt)) {
@@ -92,7 +92,7 @@
#else
// nothing else to try if the frame isn't good
return false;
-#endif /* COMPILER2 || INCLUDE_JVMCI */
+#endif // COMPILER2_OR_JVMCI
}
*fr_addr = ret_frame;
return true;
--- a/src/hotspot/share/aot/aotCodeHeap.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/aot/aotCodeHeap.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -490,6 +490,8 @@
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_checkcast_arraycopy", address, StubRoutines::_checkcast_arraycopy);
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_generic_arraycopy", address, StubRoutines::_generic_arraycopy);
+
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_aescrypt_encryptBlock", address, StubRoutines::_aescrypt_encryptBlock);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_aescrypt_decryptBlock", address, StubRoutines::_aescrypt_decryptBlock);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_cipherBlockChaining_encryptAESCrypt", address, StubRoutines::_cipherBlockChaining_encryptAESCrypt);
--- a/src/hotspot/share/aot/aotLoader.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/aot/aotLoader.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,12 +22,12 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "aot/aotCodeHeap.hpp"
#include "aot/aotLoader.inline.hpp"
#include "jvmci/jvmciRuntime.hpp"
#include "oops/method.hpp"
-#include "prims/jvm.h"
#include "runtime/os.hpp"
#include "runtime/timerTrace.hpp"
--- a/src/hotspot/share/c1/c1_CFGPrinter.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/c1/c1_CFGPrinter.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,13 +23,13 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "c1/c1_CFGPrinter.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_LIR.hpp"
#include "c1/c1_LinearScan.hpp"
#include "c1/c1_ValueStack.hpp"
-#include "prims/jvm.h"
#ifndef PRODUCT
--- a/src/hotspot/share/c1/c1_Canonicalizer.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/c1/c1_Canonicalizer.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -40,6 +40,10 @@
void set_constant(jlong x) { set_canonical(new Constant(new LongConstant(x))); }
void set_constant(jfloat x) { set_canonical(new Constant(new FloatConstant(x))); }
void set_constant(jdouble x) { set_canonical(new Constant(new DoubleConstant(x))); }
+#ifdef _WINDOWS
+ // jint is defined as long in jni_md.h, so convert from int to jint
+ void set_constant(int x) { set_constant((jint)x); }
+#endif
void move_const_to_right(Op2* x);
void do_Op2(Op2* x);
void do_UnsafeRawOp(UnsafeRawOp* x);
--- a/src/hotspot/share/c1/c1_Compiler.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/c1/c1_Compiler.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -213,7 +213,7 @@
case vmIntrinsics::_updateCRC32:
case vmIntrinsics::_updateBytesCRC32:
case vmIntrinsics::_updateByteBufferCRC32:
-#if defined(SPARC) || defined(S390) || defined(PPC64)
+#if defined(SPARC) || defined(S390) || defined(PPC64) || defined(AARCH64)
case vmIntrinsics::_updateBytesCRC32C:
case vmIntrinsics::_updateDirectByteBufferCRC32C:
#endif
--- a/src/hotspot/share/c1/c1_LinearScan.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/c1/c1_LinearScan.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -2507,7 +2507,7 @@
// use).
ConstantOopWriteValue* LinearScan::_oop_null_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantOopWriteValue(NULL);
ConstantIntValue* LinearScan::_int_m1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(-1);
-ConstantIntValue* LinearScan::_int_0_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(0);
+ConstantIntValue* LinearScan::_int_0_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue((jint)0);
ConstantIntValue* LinearScan::_int_1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(1);
ConstantIntValue* LinearScan::_int_2_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(2);
LocationValue* _illegal_value = new (ResourceObj::C_HEAP, mtCompiler) LocationValue(Location());
--- a/src/hotspot/share/ci/ciEnv.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/ci/ciEnv.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "ci/ciConstant.hpp"
#include "ci/ciEnv.hpp"
#include "ci/ciField.hpp"
@@ -49,7 +50,6 @@
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "prims/jvmtiExport.hpp"
#include "runtime/init.hpp"
#include "runtime/reflection.hpp"
--- a/src/hotspot/share/ci/ciFlags.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/ci/ciFlags.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -25,9 +25,9 @@
#ifndef SHARE_VM_CI_CIFLAGS_HPP
#define SHARE_VM_CI_CIFLAGS_HPP
+#include "jvm.h"
#include "ci/ciClassList.hpp"
#include "memory/allocation.hpp"
-#include "prims/jvm.h"
#include "utilities/accessFlags.hpp"
#include "utilities/ostream.hpp"
--- a/src/hotspot/share/ci/ciReplay.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/ci/ciReplay.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "ci/ciMethodData.hpp"
#include "ci/ciReplay.hpp"
#include "ci/ciSymbol.hpp"
@@ -33,7 +34,6 @@
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "utilities/copy.hpp"
#include "utilities/macros.hpp"
@@ -790,7 +790,7 @@
while (field_signature[rank] == '[') {
rank++;
}
- int* dims = NEW_RESOURCE_ARRAY(int, rank);
+ jint* dims = NEW_RESOURCE_ARRAY(jint, rank);
dims[0] = length;
for (int i = 1; i < rank; i++) {
dims[i] = 1; // These aren't relevant to the compiler
--- a/src/hotspot/share/classfile/altHashing.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/altHashing.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -42,15 +42,15 @@
juint AltHashing::compute_seed() {
jlong nanos = os::javaTimeNanos();
jlong now = os::javaTimeMillis();
- int SEED_MATERIAL[8] = {
- (int) object_hash(SystemDictionary::String_klass()),
- (int) object_hash(SystemDictionary::System_klass()),
- os::random(), // current thread isn't a java thread
- (int) (((julong)nanos) >> 32),
- (int) nanos,
- (int) (((julong)now) >> 32),
- (int) now,
- (int) (os::javaTimeNanos() >> 2)
+ jint SEED_MATERIAL[8] = {
+ (jint) object_hash(SystemDictionary::String_klass()),
+ (jint) object_hash(SystemDictionary::System_klass()),
+ (jint) os::random(), // current thread isn't a java thread
+ (jint) (((julong)nanos) >> 32),
+ (jint) nanos,
+ (jint) (((julong)now) >> 32),
+ (jint) now,
+ (jint) (os::javaTimeNanos() >> 2)
};
return murmur3_32(SEED_MATERIAL, 8);
@@ -167,7 +167,7 @@
}
// Hash used for the seed.
-juint AltHashing::murmur3_32(juint seed, const int* data, int len) {
+juint AltHashing::murmur3_32(juint seed, const jint* data, int len) {
juint h1 = seed;
int off = 0;
@@ -202,6 +202,6 @@
return h1;
}
-juint AltHashing::murmur3_32(const int* data, int len) {
+juint AltHashing::murmur3_32(const jint* data, int len) {
return murmur3_32(0, data, len);
}
--- a/src/hotspot/share/classfile/altHashing.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/altHashing.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -43,8 +43,8 @@
static juint Integer_rotateLeft(juint i, int distance) {
return (i << distance) | (i >> (32 - distance));
}
- static juint murmur3_32(const int* data, int len);
- static juint murmur3_32(juint seed, const int* data, int len);
+ static juint murmur3_32(const jint* data, int len);
+ static juint murmur3_32(juint seed, const jint* data, int len);
public:
static juint compute_seed();
--- a/src/hotspot/share/classfile/classFileParser.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/classFileParser.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,6 +22,7 @@
*
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "aot/aotLoader.hpp"
#include "classfile/classFileParser.hpp"
#include "classfile/classFileStream.hpp"
@@ -54,7 +55,6 @@
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
-#include "prims/jvm.h"
#include "prims/jvmtiExport.hpp"
#include "prims/jvmtiThreadState.hpp"
#include "runtime/javaCalls.hpp"
--- a/src/hotspot/share/classfile/classLoader.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/classLoader.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.inline.hpp"
@@ -53,7 +54,6 @@
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/compilationPolicy.hpp"
--- a/src/hotspot/share/classfile/classLoaderData.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/classLoaderData.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -604,40 +604,27 @@
const int _boot_loader_dictionary_size = 1009;
const int _default_loader_dictionary_size = 107;
-const int _prime_array_size = 8; // array of primes for system dictionary size
-const int _average_depth_goal = 3; // goal for lookup length
-const int _primelist[_prime_array_size] = {107, 1009, 2017, 4049, 5051, 10103, 20201, 40423};
-
-// Calculate a "good" dictionary size based
-// on predicted or current loaded classes count.
-static int calculate_dictionary_size(int classcount) {
- int newsize = _primelist[0];
- if (classcount > 0 && !DumpSharedSpaces) {
- int index = 0;
- int desiredsize = classcount/_average_depth_goal;
- for (newsize = _primelist[index]; index < _prime_array_size -1;
- newsize = _primelist[++index]) {
- if (desiredsize <= newsize) {
- break;
- }
- }
- }
- return newsize;
-}
Dictionary* ClassLoaderData::create_dictionary() {
assert(!is_anonymous(), "anonymous class loader data do not have a dictionary");
int size;
+ bool resizable = false;
if (_the_null_class_loader_data == NULL) {
size = _boot_loader_dictionary_size;
+ resizable = true;
} else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) {
size = 1; // there's only one class in relection class loader and no initiated classes
} else if (is_system_class_loader_data()) {
- size = calculate_dictionary_size(PredictedLoadedClassCount);
+ size = _boot_loader_dictionary_size;
+ resizable = true;
} else {
size = _default_loader_dictionary_size;
+ resizable = true;
}
- return new Dictionary(this, size);
+ if (!DynamicallyResizeSystemDictionaries || DumpSharedSpaces || UseSharedSpaces) {
+ resizable = false;
+ }
+ return new Dictionary(this, size, resizable);
}
// Unloading support
@@ -1325,6 +1312,19 @@
}
}
+int ClassLoaderDataGraph::resize_if_needed() {
+ assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
+ int resized = 0;
+ if (Dictionary::does_any_dictionary_needs_resizing()) {
+ FOR_ALL_DICTIONARY(cld) {
+ if (cld->dictionary()->resize_if_needed()) {
+ resized++;
+ }
+ }
+ }
+ return resized;
+}
+
void ClassLoaderDataGraph::post_class_unload_events() {
#if INCLUDE_TRACE
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
--- a/src/hotspot/share/classfile/classLoaderData.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/classLoaderData.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -143,6 +143,8 @@
}
}
+ static int resize_if_needed();
+
static bool has_metaspace_oom() { return _metaspace_oom; }
static void set_metaspace_oom(bool value) { _metaspace_oom = value; }
--- a/src/hotspot/share/classfile/compactHashtable.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/compactHashtable.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,12 +23,12 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/compactHashtable.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "logging/logMessage.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceShared.hpp"
-#include "prims/jvm.h"
#include "runtime/vmThread.hpp"
#include "utilities/numberSeq.hpp"
#include <sys/stat.h>
--- a/src/hotspot/share/classfile/dictionary.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/dictionary.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -29,6 +29,7 @@
#include "classfile/protectionDomainCache.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
+#include "gc/shared/gcLocker.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/iterator.hpp"
@@ -39,6 +40,11 @@
#include "runtime/orderAccess.inline.hpp"
#include "utilities/hashtable.inline.hpp"
+// Optimization: if any dictionary needs resizing, we set this flag,
+// so that we dont't have to walk all dictionaries to check if any actually
+// needs resizing, which is costly to do at Safepoint.
+bool Dictionary::_some_dictionary_needs_resizing = false;
+
size_t Dictionary::entry_size() {
if (DumpSharedSpaces) {
return SystemDictionaryShared::dictionary_entry_size();
@@ -47,15 +53,17 @@
}
}
-Dictionary::Dictionary(ClassLoaderData* loader_data, int table_size)
- : _loader_data(loader_data), Hashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size()) {
+Dictionary::Dictionary(ClassLoaderData* loader_data, int table_size, bool resizable)
+ : _loader_data(loader_data), _resizable(resizable), _needs_resizing(false),
+ Hashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size()) {
};
Dictionary::Dictionary(ClassLoaderData* loader_data,
int table_size, HashtableBucket<mtClass>* t,
- int number_of_entries)
- : _loader_data(loader_data), Hashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size(), t, number_of_entries) {
+ int number_of_entries, bool resizable)
+ : _loader_data(loader_data), _resizable(resizable), _needs_resizing(false),
+ Hashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size(), t, number_of_entries) {
};
Dictionary::~Dictionary() {
@@ -96,6 +104,60 @@
FREE_C_HEAP_ARRAY(char, entry);
}
+const int _resize_load_trigger = 5; // load factor that will trigger the resize
+const double _resize_factor = 2.0; // by how much we will resize using current number of entries
+const int _resize_max_size = 40423; // the max dictionary size allowed
+const int _primelist[] = {107, 1009, 2017, 4049, 5051, 10103, 20201, _resize_max_size};
+const int _prime_array_size = sizeof(_primelist)/sizeof(int);
+
+// Calculate next "good" dictionary size based on requested count
+static int calculate_dictionary_size(int requested) {
+ int newsize = _primelist[0];
+ int index = 0;
+ for (newsize = _primelist[index]; index < (_prime_array_size - 1);
+ newsize = _primelist[++index]) {
+ if (requested <= newsize) {
+ break;
+ }
+ }
+ return newsize;
+}
+
+bool Dictionary::does_any_dictionary_needs_resizing() {
+ return Dictionary::_some_dictionary_needs_resizing;
+}
+
+void Dictionary::check_if_needs_resize() {
+ if (_resizable == true) {
+ if (number_of_entries() > (_resize_load_trigger*table_size())) {
+ _needs_resizing = true;
+ Dictionary::_some_dictionary_needs_resizing = true;
+ }
+ }
+}
+
+bool Dictionary::resize_if_needed() {
+ int desired_size = 0;
+ if (_needs_resizing == true) {
+ desired_size = calculate_dictionary_size((int)(_resize_factor*number_of_entries()));
+ if (desired_size >= _resize_max_size) {
+ desired_size = _resize_max_size;
+ // We have reached the limit, turn resizing off
+ _resizable = false;
+ }
+ if ((desired_size != 0) && (desired_size != table_size())) {
+ if (!resize(desired_size)) {
+ // Something went wrong, turn resizing off
+ _resizable = false;
+ }
+ }
+ }
+
+ _needs_resizing = false;
+ Dictionary::_some_dictionary_needs_resizing = false;
+
+ return (desired_size != 0);
+}
bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
#ifdef ASSERT
@@ -264,14 +326,16 @@
// also cast to volatile; we do this to ensure store order is maintained
// by the compilers.
-void Dictionary::add_klass(int index, unsigned int hash, Symbol* class_name,
+void Dictionary::add_klass(unsigned int hash, Symbol* class_name,
InstanceKlass* obj) {
assert_locked_or_safepoint(SystemDictionary_lock);
assert(obj != NULL, "adding NULL obj");
assert(obj->name() == class_name, "sanity check on name");
DictionaryEntry* entry = new_entry(hash, obj);
+ int index = hash_to_index(hash);
add_entry(index, entry);
+ check_if_needs_resize();
}
@@ -299,8 +363,11 @@
}
-InstanceKlass* Dictionary::find(int index, unsigned int hash, Symbol* name,
+InstanceKlass* Dictionary::find(unsigned int hash, Symbol* name,
Handle protection_domain) {
+ NoSafepointVerifier nsv;
+
+ int index = hash_to_index(hash);
DictionaryEntry* entry = get_entry(index, hash, name);
if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) {
return entry->instance_klass();
@@ -350,13 +417,24 @@
}
-bool Dictionary::is_valid_protection_domain(int index, unsigned int hash,
+bool Dictionary::is_valid_protection_domain(unsigned int hash,
Symbol* name,
Handle protection_domain) {
+ int index = hash_to_index(hash);
DictionaryEntry* entry = get_entry(index, hash, name);
return entry->is_valid_protection_domain(protection_domain);
}
+#if INCLUDE_CDS
+static bool is_jfr_event_class(Klass *k) {
+ while (k) {
+ if (k->name()->equals("jdk/jfr/Event")) {
+ return true;
+ }
+ k = k->super();
+ }
+ return false;
+}
void Dictionary::reorder_dictionary_for_sharing() {
@@ -368,14 +446,22 @@
while (p != NULL) {
DictionaryEntry* next = p->next();
InstanceKlass*ik = p->instance_klass();
- // we cannot include signed classes in the archive because the certificates
- // used during dump time may be different than those used during
- // runtime (due to expiration, etc).
if (ik->signers() != NULL) {
+ // We cannot include signed classes in the archive because the certificates
+ // used during dump time may be different than those used during
+ // runtime (due to expiration, etc).
ResourceMark rm;
tty->print_cr("Preload Warning: Skipping %s from signed JAR",
ik->name()->as_C_string());
free_entry(p);
+ } else if (is_jfr_event_class(ik)) {
+ // We cannot include JFR event classes because they need runtime-specific
+ // instrumentation in order to work with -XX:FlightRecorderOptions=retransform=false.
+ // There are only a small number of these classes, so it's not worthwhile to
+ // support them and make CDS more complicated.
+ ResourceMark rm;
+ tty->print_cr("Skipping JFR event class %s", ik->name()->as_C_string());
+ free_entry(p);
} else {
p->set_next(master_list);
master_list = p;
@@ -400,7 +486,7 @@
set_entry(index, p);
}
}
-
+#endif
SymbolPropertyTable::SymbolPropertyTable(int table_size)
: Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry))
--- a/src/hotspot/share/classfile/dictionary.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/dictionary.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -43,6 +43,11 @@
class Dictionary : public Hashtable<InstanceKlass*, mtClass> {
friend class VMStructs;
+ static bool _some_dictionary_needs_resizing;
+ bool _resizable;
+ bool _needs_resizing;
+ void check_if_needs_resize();
+
ClassLoaderData* _loader_data; // backpointer to owning loader
ClassLoaderData* loader_data() const { return _loader_data; }
@@ -51,13 +56,16 @@
protected:
static size_t entry_size();
public:
- Dictionary(ClassLoaderData* loader_data, int table_size);
- Dictionary(ClassLoaderData* loader_data, int table_size, HashtableBucket<mtClass>* t, int number_of_entries);
+ Dictionary(ClassLoaderData* loader_data, int table_size, bool resizable = false);
+ Dictionary(ClassLoaderData* loader_data, int table_size, HashtableBucket<mtClass>* t, int number_of_entries, bool resizable = false);
~Dictionary();
+ static bool does_any_dictionary_needs_resizing();
+ bool resize_if_needed();
+
DictionaryEntry* new_entry(unsigned int hash, InstanceKlass* klass);
- void add_klass(int index, unsigned int hash, Symbol* class_name, InstanceKlass* obj);
+ void add_klass(unsigned int hash, Symbol* class_name, InstanceKlass* obj);
InstanceKlass* find_class(int index, unsigned int hash, Symbol* name);
@@ -79,8 +87,8 @@
void do_unloading();
// Protection domains
- InstanceKlass* find(int index, unsigned int hash, Symbol* name, Handle protection_domain);
- bool is_valid_protection_domain(int index, unsigned int hash,
+ InstanceKlass* find(unsigned int hash, Symbol* name, Handle protection_domain);
+ bool is_valid_protection_domain(unsigned int hash,
Symbol* name,
Handle protection_domain);
void add_protection_domain(int index, unsigned int hash,
@@ -88,7 +96,7 @@
Handle protection_domain, TRAPS);
// Sharing support
- void reorder_dictionary_for_sharing();
+ void reorder_dictionary_for_sharing() NOT_CDS_RETURN;
void print_on(outputStream* st) const;
void verify();
--- a/src/hotspot/share/classfile/javaClasses.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/javaClasses.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -2258,8 +2258,9 @@
void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS) {
ResourceMark rm(THREAD);
- Handle k (THREAD, stackFrame->obj_field(_declaringClass_offset));
- InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(k()));
+ Handle mname(THREAD, stackFrame->obj_field(java_lang_StackFrameInfo::_memberName_offset));
+ Klass* clazz = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(mname()));
+ InstanceKlass* holder = InstanceKlass::cast(clazz);
Method* method = java_lang_StackFrameInfo::get_method(stackFrame, holder, CHECK);
short version = stackFrame->short_field(_version_offset);
@@ -2270,7 +2271,6 @@
void java_lang_StackFrameInfo::compute_offsets() {
Klass* k = SystemDictionary::StackFrameInfo_klass();
- compute_offset(_declaringClass_offset, k, vmSymbols::declaringClass_name(), vmSymbols::class_signature());
compute_offset(_memberName_offset, k, vmSymbols::memberName_name(), vmSymbols::object_signature());
compute_offset(_bci_offset, k, vmSymbols::bci_name(), vmSymbols::short_signature());
STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
@@ -3679,7 +3679,6 @@
int java_lang_StackTraceElement::classLoaderName_offset;
int java_lang_StackTraceElement::declaringClass_offset;
int java_lang_StackTraceElement::declaringClassObject_offset;
-int java_lang_StackFrameInfo::_declaringClass_offset;
int java_lang_StackFrameInfo::_memberName_offset;
int java_lang_StackFrameInfo::_bci_offset;
int java_lang_StackFrameInfo::_version_offset;
@@ -3732,11 +3731,6 @@
element->obj_field_put(declaringClassObject_offset, value);
}
-// Support for java_lang_StackFrameInfo
-void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) {
- element->obj_field_put(_declaringClass_offset, value);
-}
-
void java_lang_StackFrameInfo::set_version(oop element, short value) {
element->short_field_put(_version_offset, value);
}
--- a/src/hotspot/share/classfile/javaClasses.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/javaClasses.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -1370,7 +1370,6 @@
class java_lang_StackFrameInfo: AllStatic {
private:
- static int _declaringClass_offset;
static int _memberName_offset;
static int _bci_offset;
static int _version_offset;
@@ -1379,7 +1378,6 @@
public:
// Setters
- static void set_declaringClass(oop info, oop value);
static void set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, TRAPS);
static void set_bci(oop info, int value);
--- a/src/hotspot/share/classfile/modules.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/modules.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/classFileParser.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.inline.hpp"
@@ -40,7 +41,6 @@
#include "logging/logStream.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
-#include "prims/jvm.h"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
--- a/src/hotspot/share/classfile/systemDictionary.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/systemDictionary.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "aot/aotLoader.hpp"
#include "classfile/classFileParser.hpp"
#include "classfile/classFileStream.hpp"
@@ -61,7 +62,6 @@
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "oops/typeArrayKlass.hpp"
-#include "prims/jvm.h"
#include "prims/jvmtiEnvBase.hpp"
#include "prims/resolvedMethodTable.hpp"
#include "prims/methodHandles.hpp"
@@ -371,7 +371,6 @@
ClassLoaderData* loader_data = class_loader_data(class_loader);
Dictionary* dictionary = loader_data->dictionary();
unsigned int d_hash = dictionary->compute_hash(child_name);
- int d_index = dictionary->hash_to_index(d_hash);
unsigned int p_hash = placeholders()->compute_hash(child_name);
int p_index = placeholders()->hash_to_index(p_hash);
// can't throw error holding a lock
@@ -379,7 +378,7 @@
bool throw_circularity_error = false;
{
MutexLocker mu(SystemDictionary_lock, THREAD);
- Klass* childk = find_class(d_index, d_hash, child_name, dictionary);
+ Klass* childk = find_class(d_hash, child_name, dictionary);
Klass* quicksuperk;
// to support // loading: if child done loading, just return superclass
// if class_name, & class_loader don't match:
@@ -487,9 +486,9 @@
Symbol* kn = klass->name();
unsigned int d_hash = dictionary->compute_hash(kn);
- int d_index = dictionary->hash_to_index(d_hash);
MutexLocker mu(SystemDictionary_lock, THREAD);
+ int d_index = dictionary->hash_to_index(d_hash);
dictionary->add_protection_domain(d_index, d_hash, klass,
protection_domain, THREAD);
}
@@ -555,7 +554,6 @@
ClassLoaderData* loader_data = class_loader_data(class_loader);
Dictionary* dictionary = loader_data->dictionary();
unsigned int d_hash = dictionary->compute_hash(name);
- int d_index = dictionary->hash_to_index(d_hash);
unsigned int p_hash = placeholders()->compute_hash(name);
int p_index = placeholders()->hash_to_index(p_hash);
@@ -579,7 +577,7 @@
if (!class_loader.is_null() && is_parallelCapable(class_loader)) {
MutexLocker mu(SystemDictionary_lock, THREAD);
// Check if classloading completed while we were loading superclass or waiting
- return find_class(d_index, d_hash, name, dictionary);
+ return find_class(d_hash, name, dictionary);
}
// must loop to both handle other placeholder updates
@@ -589,7 +587,7 @@
while (super_load_in_progress) {
MutexLocker mu(SystemDictionary_lock, THREAD);
// Check if classloading completed while we were loading superclass or waiting
- InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
+ InstanceKlass* check = find_class(d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so just return it
return check;
@@ -670,6 +668,7 @@
class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
ClassLoaderData *loader_data = register_loader(class_loader, CHECK_NULL);
Dictionary* dictionary = loader_data->dictionary();
+ unsigned int d_hash = dictionary->compute_hash(name);
// Do lookup to see if class already exist and the protection domain
// has the right access
@@ -677,11 +676,10 @@
// All subsequent calls use find_class, and set has_loaded_class so that
// before we return a result we call out to java to check for valid protection domain
// to allow returning the Klass* and add it to the pd_set if it is valid
- unsigned int d_hash = dictionary->compute_hash(name);
- int d_index = dictionary->hash_to_index(d_hash);
- Klass* probe = dictionary->find(d_index, d_hash, name, protection_domain);
- if (probe != NULL) return probe;
-
+ {
+ Klass* probe = dictionary->find(d_hash, name, protection_domain);
+ if (probe != NULL) return probe;
+ }
// Non-bootstrap class loaders will call out to class loader and
// define via jvm/jni_DefineClass which will acquire the
@@ -716,7 +714,7 @@
{
MutexLocker mu(SystemDictionary_lock, THREAD);
- InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
+ InstanceKlass* check = find_class(d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so just return it
class_has_been_loaded = true;
@@ -800,7 +798,7 @@
double_lock_wait(lockObject, THREAD);
}
// Check if classloading completed while we were waiting
- InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
+ InstanceKlass* check = find_class(d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so just return it
k = check;
@@ -825,7 +823,7 @@
// i.e. now that we hold the LOAD_INSTANCE token on loading this class/CL
// one final check if the load has already completed
// class loaders holding the ObjectLock shouldn't find the class here
- InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
+ InstanceKlass* check = find_class(d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so return it after checking/adding protection domain
k = check;
@@ -858,7 +856,7 @@
if (k == NULL && HAS_PENDING_EXCEPTION
&& PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
MutexLocker mu(SystemDictionary_lock, THREAD);
- InstanceKlass* check = find_class(d_index, d_hash, name, dictionary);
+ InstanceKlass* check = find_class(d_hash, name, dictionary);
if (check != NULL) {
// Klass is already loaded, so just use it
k = check;
@@ -873,7 +871,7 @@
if (!HAS_PENDING_EXCEPTION && k != NULL &&
k->class_loader() != class_loader()) {
- check_constraints(d_index, d_hash, k, class_loader, false, THREAD);
+ check_constraints(d_hash, k, class_loader, false, THREAD);
// Need to check for a PENDING_EXCEPTION again; check_constraints
// can throw and doesn't use the CHECK macro.
@@ -881,7 +879,7 @@
{ // Grabbing the Compile_lock prevents systemDictionary updates
// during compilations.
MutexLocker mu(Compile_lock, THREAD);
- update_dictionary(d_index, d_hash, p_index, p_hash,
+ update_dictionary(d_hash, p_index, p_hash,
k, class_loader, THREAD);
}
@@ -923,7 +921,7 @@
if (protection_domain() == NULL) return k;
// Check the protection domain has the right access
- if (dictionary->is_valid_protection_domain(d_index, d_hash, name,
+ if (dictionary->is_valid_protection_domain(d_hash, name,
protection_domain)) {
return k;
}
@@ -965,8 +963,7 @@
Dictionary* dictionary = loader_data->dictionary();
unsigned int d_hash = dictionary->compute_hash(class_name);
- int d_index = dictionary->hash_to_index(d_hash);
- return dictionary->find(d_index, d_hash, class_name,
+ return dictionary->find(d_hash, class_name,
protection_domain);
}
@@ -1644,8 +1641,7 @@
Symbol* name_h = k->name();
Dictionary* dictionary = loader_data->dictionary();
unsigned int d_hash = dictionary->compute_hash(name_h);
- int d_index = dictionary->hash_to_index(d_hash);
- check_constraints(d_index, d_hash, k, class_loader_h, true, CHECK);
+ check_constraints(d_hash, k, class_loader_h, true, CHECK);
// Register class just loaded with class loader (placed in Vector)
// Note we do this before updating the dictionary, as this can
@@ -1673,7 +1669,7 @@
// Add to systemDictionary - so other classes can see it.
// Grabs and releases SystemDictionary_lock
- update_dictionary(d_index, d_hash, p_index, p_hash,
+ update_dictionary(d_hash, p_index, p_hash,
k, class_loader_h, THREAD);
}
k->eager_initialize(THREAD);
@@ -1715,7 +1711,6 @@
Dictionary* dictionary = loader_data->dictionary();
unsigned int d_hash = dictionary->compute_hash(name_h);
- int d_index = dictionary->hash_to_index(d_hash);
// Hold SD lock around find_class and placeholder creation for DEFINE_CLASS
unsigned int p_hash = placeholders()->compute_hash(name_h);
@@ -1726,7 +1721,7 @@
MutexLocker mu(SystemDictionary_lock, THREAD);
// First check if class already defined
if (UnsyncloadClass || (is_parallelDefine(class_loader))) {
- InstanceKlass* check = find_class(d_index, d_hash, name_h, dictionary);
+ InstanceKlass* check = find_class(d_hash, name_h, dictionary);
if (check != NULL) {
return check;
}
@@ -1748,7 +1743,7 @@
placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD);
SystemDictionary_lock->notify_all();
#ifdef ASSERT
- InstanceKlass* check = find_class(d_index, d_hash, name_h, dictionary);
+ InstanceKlass* check = find_class(d_hash, name_h, dictionary);
assert(check != NULL, "definer missed recording success");
#endif
return probe->instance_klass();
@@ -1823,10 +1818,11 @@
// ----------------------------------------------------------------------------
// Lookup
-InstanceKlass* SystemDictionary::find_class(int index, unsigned int hash,
+InstanceKlass* SystemDictionary::find_class(unsigned int hash,
Symbol* class_name,
Dictionary* dictionary) {
assert_locked_or_safepoint(SystemDictionary_lock);
+ int index = dictionary->hash_to_index(hash);
return dictionary->find_class(index, hash, class_name);
}
@@ -1856,8 +1852,7 @@
Dictionary* dictionary = loader_data->dictionary();
unsigned int d_hash = dictionary->compute_hash(class_name);
- int d_index = dictionary->hash_to_index(d_hash);
- return find_class(d_index, d_hash, class_name, dictionary);
+ return find_class(d_hash, class_name, dictionary);
}
@@ -2210,7 +2205,7 @@
// if defining is true, then LinkageError if already in dictionary
// if initiating loader, then ok if InstanceKlass matches existing entry
-void SystemDictionary::check_constraints(int d_index, unsigned int d_hash,
+void SystemDictionary::check_constraints(unsigned int d_hash,
InstanceKlass* k,
Handle class_loader, bool defining,
TRAPS) {
@@ -2222,7 +2217,7 @@
MutexLocker mu(SystemDictionary_lock, THREAD);
- InstanceKlass* check = find_class(d_index, d_hash, name, loader_data->dictionary());
+ InstanceKlass* check = find_class(d_hash, name, loader_data->dictionary());
if (check != NULL) {
// if different InstanceKlass - duplicate class definition,
// else - ok, class loaded by a different thread in parallel,
@@ -2270,7 +2265,7 @@
// Update class loader data dictionary - done after check_constraint and add_to_hierachy
// have been called.
-void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash,
+void SystemDictionary::update_dictionary(unsigned int d_hash,
int p_index, unsigned int p_hash,
InstanceKlass* k,
Handle class_loader,
@@ -2305,13 +2300,13 @@
// Make a new dictionary entry.
Dictionary* dictionary = loader_data->dictionary();
- InstanceKlass* sd_check = find_class(d_index, d_hash, name, dictionary);
+ InstanceKlass* sd_check = find_class(d_hash, name, dictionary);
if (sd_check == NULL) {
- dictionary->add_klass(d_index, d_hash, name, k);
+ dictionary->add_klass(d_hash, name, k);
notice_modification();
}
#ifdef ASSERT
- sd_check = find_class(d_index, d_hash, name, dictionary);
+ sd_check = find_class(d_hash, name, dictionary);
assert (sd_check != NULL, "should have entry in dictionary");
// Note: there may be a placeholder entry: for circularity testing
// or for parallel defines
@@ -2388,16 +2383,14 @@
Dictionary* dictionary1 = loader_data1->dictionary();
unsigned int d_hash1 = dictionary1->compute_hash(constraint_name);
- int d_index1 = dictionary1->hash_to_index(d_hash1);
Dictionary* dictionary2 = loader_data2->dictionary();
unsigned int d_hash2 = dictionary2->compute_hash(constraint_name);
- int d_index2 = dictionary2->hash_to_index(d_hash2);
{
MutexLocker mu_s(SystemDictionary_lock, THREAD);
- InstanceKlass* klass1 = find_class(d_index1, d_hash1, constraint_name, dictionary1);
- InstanceKlass* klass2 = find_class(d_index2, d_hash2, constraint_name, dictionary2);
+ InstanceKlass* klass1 = find_class(d_hash1, constraint_name, dictionary1);
+ InstanceKlass* klass2 = find_class(d_hash2, constraint_name, dictionary2);
return constraints()->add_entry(constraint_name, klass1, class_loader1,
klass2, class_loader2);
}
@@ -2855,9 +2848,11 @@
return _pd_cache_table->get(protection_domain);
}
+#if INCLUDE_CDS
void SystemDictionary::reorder_dictionary_for_sharing() {
ClassLoaderData::the_null_class_loader_data()->dictionary()->reorder_dictionary_for_sharing();
}
+#endif
size_t SystemDictionary::count_bytes_for_buckets() {
return ClassLoaderData::the_null_class_loader_data()->dictionary()->count_bytes_for_buckets();
--- a/src/hotspot/share/classfile/systemDictionary.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/systemDictionary.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -384,7 +384,7 @@
public:
// Sharing support.
- static void reorder_dictionary_for_sharing();
+ static void reorder_dictionary_for_sharing() NOT_CDS_RETURN;
static void combine_shared_dictionaries();
static size_t count_bytes_for_buckets();
static size_t count_bytes_for_table();
@@ -655,11 +655,8 @@
// Setup link to hierarchy
static void add_to_hierarchy(InstanceKlass* k, TRAPS);
- // We pass in the hashtable index so we can calculate it outside of
- // the SystemDictionary_lock.
-
// Basic find on loaded classes
- static InstanceKlass* find_class(int index, unsigned int hash,
+ static InstanceKlass* find_class(unsigned int hash,
Symbol* name, Dictionary* dictionary);
static InstanceKlass* find_class(Symbol* class_name, ClassLoaderData* loader_data);
@@ -685,10 +682,10 @@
static void initialize_preloaded_classes(TRAPS);
// Class loader constraints
- static void check_constraints(int index, unsigned int hash,
+ static void check_constraints(unsigned int hash,
InstanceKlass* k, Handle loader,
bool defining, TRAPS);
- static void update_dictionary(int d_index, unsigned int d_hash,
+ static void update_dictionary(unsigned int d_hash,
int p_index, unsigned int p_hash,
InstanceKlass* k, Handle loader,
TRAPS);
--- a/src/hotspot/share/classfile/verifier.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/verifier.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/classFileStream.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/stackMapTable.hpp"
@@ -40,7 +41,6 @@
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "oops/typeArrayOop.hpp"
-#include "prims/jvm.h"
#include "runtime/fieldDescriptor.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/interfaceSupport.hpp"
--- a/src/hotspot/share/classfile/vmSymbols.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/vmSymbols.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,12 +23,12 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/vmSymbols.hpp"
#include "compiler/compilerDirectives.hpp"
#include "memory/oopFactory.hpp"
#include "memory/metaspaceClosure.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/handles.inline.hpp"
#include "utilities/xmlstream.hpp"
--- a/src/hotspot/share/classfile/vmSymbols.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/classfile/vmSymbols.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -429,7 +429,6 @@
template(append_name, "append") \
template(klass_name, "klass") \
template(array_klass_name, "array_klass") \
- template(declaringClass_name, "declaringClass") \
template(memberName_name, "memberName") \
template(mid_name, "mid") \
template(cpref_name, "cpref") \
--- a/src/hotspot/share/code/codeBlob.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/code/codeBlob.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "code/codeBlob.hpp"
#include "code/codeCache.hpp"
#include "code/relocInfo.hpp"
@@ -33,7 +34,6 @@
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "prims/forte.hpp"
-#include "prims/jvm.h"
#include "runtime/handles.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/mutexLocker.hpp"
--- a/src/hotspot/share/code/codeBlob.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/code/codeBlob.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -49,21 +49,35 @@
// CodeBlob - superclass for all entries in the CodeCache.
//
// Subtypes are:
-// CompiledMethod : Compiled Java methods (include method that calls to native code)
-// nmethod : JIT Compiled Java methods
-// RuntimeBlob : Non-compiled method code; generated glue code
-// RuntimeStub : Call to VM runtime methods
-// DeoptimizationBlob : Used for deoptimization
-// ExceptionBlob : Used for stack unrolling
-// SafepointBlob : Used to handle illegal instruction exceptions
+// CompiledMethod : Compiled Java methods (include method that calls to native code)
+// nmethod : JIT Compiled Java methods
+// AOTCompiledMethod : AOT Compiled Java methods - Not in the CodeCache!
+// AOTCompiledMethod objects are allocated in the C-Heap, the code they
+// point to is allocated in the AOTCodeHeap which is in the C-Heap as
+// well (i.e. it's the memory where the shared library was loaded to)
+// RuntimeBlob : Non-compiled method code; generated glue code
+// BufferBlob : Used for non-relocatable code such as interpreter, stubroutines, etc.
+// AdapterBlob : Used to hold C2I/I2C adapters
+// MethodHandlesAdapterBlob : Used to hold MethodHandles adapters
+// RuntimeStub : Call to VM runtime methods
+// SingletonBlob : Super-class for all blobs that exist in only one instance
+// DeoptimizationBlob : Used for deoptimization
+// ExceptionBlob : Used for stack unrolling
+// SafepointBlob : Used to handle illegal instruction exceptions
+// UncommonTrapBlob : Used to handle uncommon traps
//
//
-// Layout:
+// Layout (all except AOTCompiledMethod) : continuous in the CodeCache
// - header
// - relocation
// - content space
// - instruction space
// - data space
+//
+// Layout (AOTCompiledMethod) : in the C-Heap
+// - header -\
+// ... |
+// - code <-/
class CodeBlobLayout;
--- a/src/hotspot/share/code/nmethod.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/code/nmethod.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
#include "code/dependencies.hpp"
@@ -41,7 +42,6 @@
#include "memory/resourceArea.hpp"
#include "oops/methodData.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "prims/jvmtiImpl.hpp"
#include "runtime/atomic.hpp"
#include "runtime/orderAccess.inline.hpp"
@@ -409,6 +409,7 @@
#if INCLUDE_JVMCI
_jvmci_installed_code = NULL;
_speculation_log = NULL;
+ _jvmci_installed_code_triggers_unloading = false;
#endif
}
@@ -461,8 +462,8 @@
AbstractCompiler* compiler,
int comp_level
#if INCLUDE_JVMCI
- , Handle installed_code,
- Handle speculationLog
+ , jweak installed_code,
+ jweak speculationLog
#endif
)
{
@@ -642,8 +643,8 @@
AbstractCompiler* compiler,
int comp_level
#if INCLUDE_JVMCI
- , Handle installed_code,
- Handle speculation_log
+ , jweak installed_code,
+ jweak speculation_log
#endif
)
: CompiledMethod(method, "nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false),
@@ -671,8 +672,14 @@
set_ctable_begin(header_begin() + _consts_offset);
#if INCLUDE_JVMCI
- _jvmci_installed_code = installed_code();
- _speculation_log = (instanceOop)speculation_log();
+ _jvmci_installed_code = installed_code;
+ _speculation_log = speculation_log;
+ oop obj = JNIHandles::resolve(installed_code);
+ if (obj == NULL || (obj->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(obj))) {
+ _jvmci_installed_code_triggers_unloading = false;
+ } else {
+ _jvmci_installed_code_triggers_unloading = true;
+ }
if (compiler->is_jvmci()) {
// JVMCI might not produce any stub sections
@@ -1026,8 +1033,6 @@
" unloadable, Method*(" INTPTR_FORMAT
"), cause(" INTPTR_FORMAT ")",
p2i(this), p2i(_method), p2i(cause));
- if (!Universe::heap()->is_gc_active())
- cause->klass()->print_on(&ls);
}
// Unlink the osr method, so we do not look this up again
if (is_osr_method()) {
@@ -1077,14 +1082,8 @@
#if INCLUDE_JVMCI
// The method can only be unloaded after the pointer to the installed code
// Java wrapper is no longer alive. Here we need to clear out this weak
- // reference to the dead object. Nulling out the reference has to happen
- // after the method is unregistered since the original value may be still
- // tracked by the rset.
+ // reference to the dead object.
maybe_invalidate_installed_code();
- // Clear these out after the nmethod has been unregistered and any
- // updates to the InstalledCode instance have been performed.
- _jvmci_installed_code = NULL;
- _speculation_log = NULL;
#endif
// The Method* is gone at this point
@@ -1246,10 +1245,6 @@
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
if (nmethod_needs_unregister) {
Universe::heap()->unregister_nmethod(this);
-#ifdef JVMCI
- _jvmci_installed_code = NULL;
- _speculation_log = NULL;
-#endif
}
flush_dependencies(NULL);
}
@@ -1314,6 +1309,11 @@
CodeCache::drop_scavenge_root_nmethod(this);
}
+#if INCLUDE_JVMCI
+ assert(_jvmci_installed_code == NULL, "should have been nulled out when transitioned to zombie");
+ assert(_speculation_log == NULL, "should have been nulled out when transitioned to zombie");
+#endif
+
CodeBlob::flush();
CodeCache::free(this);
}
@@ -1500,29 +1500,18 @@
#if INCLUDE_JVMCI
bool nmethod::do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) {
- bool is_unloaded = false;
- // Follow JVMCI method
- BarrierSet* bs = Universe::heap()->barrier_set();
if (_jvmci_installed_code != NULL) {
- if (_jvmci_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_jvmci_installed_code)) {
- if (!is_alive->do_object_b(_jvmci_installed_code)) {
+ if (JNIHandles::is_global_weak_cleared(_jvmci_installed_code)) {
+ if (_jvmci_installed_code_triggers_unloading) {
+ // jweak reference processing has already cleared the referent
+ make_unloaded(is_alive, NULL);
+ return true;
+ } else {
clear_jvmci_installed_code();
}
- } else {
- if (can_unload(is_alive, (oop*)&_jvmci_installed_code, unloading_occurred)) {
- return true;
- }
}
}
-
- if (_speculation_log != NULL) {
- if (!is_alive->do_object_b(_speculation_log)) {
- bs->write_ref_nmethod_pre(&_speculation_log, this);
- _speculation_log = NULL;
- bs->write_ref_nmethod_post(&_speculation_log, this);
- }
- }
- return is_unloaded;
+ return false;
}
#endif
@@ -1594,15 +1583,6 @@
// (See comment above.)
}
-#if INCLUDE_JVMCI
- if (_jvmci_installed_code != NULL) {
- f->do_oop((oop*) &_jvmci_installed_code);
- }
- if (_speculation_log != NULL) {
- f->do_oop((oop*) &_speculation_log);
- }
-#endif
-
RelocIterator iter(this, low_boundary);
while (iter.next()) {
@@ -2860,43 +2840,49 @@
#if INCLUDE_JVMCI
void nmethod::clear_jvmci_installed_code() {
- // write_ref_method_pre/post can only be safely called at a
- // safepoint or while holding the CodeCache_lock
- assert(CodeCache_lock->is_locked() ||
- SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency");
+ assert_locked_or_safepoint(Patching_lock);
if (_jvmci_installed_code != NULL) {
- // This must be done carefully to maintain nmethod remembered sets properly
- BarrierSet* bs = Universe::heap()->barrier_set();
- bs->write_ref_nmethod_pre(&_jvmci_installed_code, this);
+ JNIHandles::destroy_weak_global(_jvmci_installed_code);
_jvmci_installed_code = NULL;
- bs->write_ref_nmethod_post(&_jvmci_installed_code, this);
+ }
+}
+
+void nmethod::clear_speculation_log() {
+ assert_locked_or_safepoint(Patching_lock);
+ if (_speculation_log != NULL) {
+ JNIHandles::destroy_weak_global(_speculation_log);
+ _speculation_log = NULL;
}
}
void nmethod::maybe_invalidate_installed_code() {
assert(Patching_lock->is_locked() ||
SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency");
- oop installed_code = jvmci_installed_code();
+ oop installed_code = JNIHandles::resolve(_jvmci_installed_code);
if (installed_code != NULL) {
+ // Update the values in the InstalledCode instance if it still refers to this nmethod
nmethod* nm = (nmethod*)InstalledCode::address(installed_code);
- if (nm == NULL || nm != this) {
- // The link has been broken or the InstalledCode instance is
- // associated with another nmethod so do nothing.
- return;
+ if (nm == this) {
+ if (!is_alive()) {
+ // Break the link between nmethod and InstalledCode such that the nmethod
+ // can subsequently be flushed safely. The link must be maintained while
+ // the method could have live activations since invalidateInstalledCode
+ // might want to invalidate all existing activations.
+ InstalledCode::set_address(installed_code, 0);
+ InstalledCode::set_entryPoint(installed_code, 0);
+ } else if (is_not_entrant()) {
+ // Remove the entry point so any invocation will fail but keep
+ // the address link around that so that existing activations can
+ // be invalidated.
+ InstalledCode::set_entryPoint(installed_code, 0);
+ }
}
- if (!is_alive()) {
- // Break the link between nmethod and InstalledCode such that the nmethod
- // can subsequently be flushed safely. The link must be maintained while
- // the method could have live activations since invalidateInstalledCode
- // might want to invalidate all existing activations.
- InstalledCode::set_address(installed_code, 0);
- InstalledCode::set_entryPoint(installed_code, 0);
- } else if (is_not_entrant()) {
- // Remove the entry point so any invocation will fail but keep
- // the address link around that so that existing activations can
- // be invalidated.
- InstalledCode::set_entryPoint(installed_code, 0);
- }
+ }
+ if (!is_alive()) {
+ // Clear these out after the nmethod has been unregistered and any
+ // updates to the InstalledCode instance have been performed.
+ clear_jvmci_installed_code();
+ clear_speculation_log();
}
}
@@ -2916,45 +2902,49 @@
{
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
// This relationship can only be checked safely under a lock
- assert(nm == NULL || !nm->is_alive() || nm->jvmci_installed_code() == installedCode(), "sanity check");
+ assert(!nm->is_alive() || nm->jvmci_installed_code() == installedCode(), "sanity check");
}
#endif
if (nm->is_alive()) {
- // The nmethod state machinery maintains the link between the
- // HotSpotInstalledCode and nmethod* so as long as the nmethod appears to be
- // alive assume there is work to do and deoptimize the nmethod.
+ // Invalidating the InstalledCode means we want the nmethod
+ // to be deoptimized.
nm->mark_for_deoptimization();
VM_Deoptimize op;
VMThread::execute(&op);
}
+ // Multiple threads could reach this point so we now need to
+ // lock and re-check the link to the nmethod so that only one
+ // thread clears it.
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
- // Check that it's still associated with the same nmethod and break
- // the link if it is.
if (InstalledCode::address(installedCode) == nativeMethod) {
- InstalledCode::set_address(installedCode, 0);
+ InstalledCode::set_address(installedCode, 0);
}
}
+oop nmethod::jvmci_installed_code() {
+ return JNIHandles::resolve(_jvmci_installed_code);
+}
+
+oop nmethod::speculation_log() {
+ return JNIHandles::resolve(_speculation_log);
+}
+
char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) {
if (!this->is_compiled_by_jvmci()) {
return NULL;
}
- oop installedCode = this->jvmci_installed_code();
- if (installedCode != NULL) {
- oop installedCodeName = NULL;
- if (installedCode->is_a(InstalledCode::klass())) {
- installedCodeName = InstalledCode::name(installedCode);
+ oop installed_code = JNIHandles::resolve(_jvmci_installed_code);
+ if (installed_code != NULL) {
+ oop installed_code_name = NULL;
+ if (installed_code->is_a(InstalledCode::klass())) {
+ installed_code_name = InstalledCode::name(installed_code);
}
- if (installedCodeName != NULL) {
- return java_lang_String::as_utf8_string(installedCodeName, buf, (int)buflen);
- } else {
- jio_snprintf(buf, buflen, "null");
- return buf;
+ if (installed_code_name != NULL) {
+ return java_lang_String::as_utf8_string(installed_code_name, buf, (int)buflen);
}
}
- jio_snprintf(buf, buflen, "noInstalledCode");
- return buf;
+ return NULL;
}
#endif
--- a/src/hotspot/share/code/nmethod.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/code/nmethod.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -63,9 +63,22 @@
jmethodID _jmethod_id; // Cache of method()->jmethod_id()
#if INCLUDE_JVMCI
- // Needed to keep nmethods alive that are not the default nmethod for the associated Method.
- oop _jvmci_installed_code;
- oop _speculation_log;
+ // A weak reference to an InstalledCode object associated with
+ // this nmethod.
+ jweak _jvmci_installed_code;
+
+ // A weak reference to a SpeculationLog object associated with
+ // this nmethod.
+ jweak _speculation_log;
+
+ // Determines whether this nmethod is unloaded when the
+ // referent in _jvmci_installed_code is cleared. This
+ // will be false if the referent is initialized to a
+ // HotSpotNMethod object whose isDefault field is true.
+ // That is, installed code other than a "default"
+ // HotSpotNMethod causes nmethod unloading.
+ // This field is ignored once _jvmci_installed_code is NULL.
+ bool _jvmci_installed_code_triggers_unloading;
#endif
// To support simple linked-list chaining of nmethods:
@@ -192,8 +205,8 @@
AbstractCompiler* compiler,
int comp_level
#if INCLUDE_JVMCI
- , Handle installed_code,
- Handle speculation_log
+ , jweak installed_code,
+ jweak speculation_log
#endif
);
@@ -236,8 +249,8 @@
AbstractCompiler* compiler,
int comp_level
#if INCLUDE_JVMCI
- , Handle installed_code = Handle(),
- Handle speculation_log = Handle()
+ , jweak installed_code = NULL,
+ jweak speculation_log = NULL
#endif
);
@@ -433,27 +446,46 @@
void set_method(Method* method) { _method = method; }
#if INCLUDE_JVMCI
- oop jvmci_installed_code() { return _jvmci_installed_code ; }
+ // Gets the InstalledCode object associated with this nmethod
+ // which may be NULL if this nmethod was not compiled by JVMCI
+ // or the weak reference has been cleared.
+ oop jvmci_installed_code();
+
+ // Copies the value of the name field in the InstalledCode
+ // object (if any) associated with this nmethod into buf.
+ // Returns the value of buf if it was updated otherwise NULL.
char* jvmci_installed_code_name(char* buf, size_t buflen);
- // Update the state of any InstalledCode instance associated with
+ // Updates the state of the InstalledCode (if any) associated with
// this nmethod based on the current value of _state.
void maybe_invalidate_installed_code();
- // Helper function to invalidate InstalledCode instances
+ // Deoptimizes the nmethod (if any) in the address field of a given
+ // InstalledCode object. The address field is zeroed upon return.
static void invalidate_installed_code(Handle installed_code, TRAPS);
- oop speculation_log() { return _speculation_log ; }
+ // Gets the SpeculationLog object associated with this nmethod
+ // which may be NULL if this nmethod was not compiled by JVMCI
+ // or the weak reference has been cleared.
+ oop speculation_log();
private:
+ // Deletes the weak reference (if any) to the InstalledCode object
+ // associated with this nmethod.
void clear_jvmci_installed_code();
+ // Deletes the weak reference (if any) to the SpeculationLog object
+ // associated with this nmethod.
+ void clear_speculation_log();
+
public:
#endif
protected:
virtual bool do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive, bool unloading_occurred);
#if INCLUDE_JVMCI
+ // See comment for _jvmci_installed_code_triggers_unloading field.
+ // Returns whether this nmethod was unloaded.
virtual bool do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred);
#endif
--- a/src/hotspot/share/code/relocInfo.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/code/relocInfo.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -489,7 +489,7 @@
#ifndef _LP64
_target = (address) (intptr_t)unpack_1_int();
#else
- int32_t lo, hi;
+ jint lo, hi;
unpack_2_ints(lo, hi);
jlong t = jlong_from(hi, lo);;
_target = (address) t;
--- a/src/hotspot/share/code/scopeDesc.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/code/scopeDesc.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -228,7 +228,7 @@
}
}
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
if (NOT_JVMCI(DoEscapeAnalysis &&) is_top() && _objects != NULL) {
st->print_cr(" Objects");
for (int i = 0; i < _objects->length(); i++) {
@@ -239,7 +239,7 @@
st->cr();
}
}
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
}
#endif
--- a/src/hotspot/share/compiler/compileBroker.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/compiler/compileBroker.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
@@ -40,7 +41,6 @@
#include "oops/methodData.hpp"
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "prims/nativeLookup.hpp"
#include "prims/whitebox.hpp"
#include "runtime/arguments.hpp"
@@ -108,7 +108,7 @@
bool CompileBroker::_initialized = false;
volatile bool CompileBroker::_should_block = false;
-volatile jint CompileBroker::_print_compilation_warning = 0;
+volatile int CompileBroker::_print_compilation_warning = 0;
volatile jint CompileBroker::_should_compile_new_jobs = run_compilation;
// The installed compiler(s)
--- a/src/hotspot/share/compiler/compileBroker.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/compiler/compileBroker.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -217,7 +217,7 @@
static int _sum_nmethod_code_size;
static long _peak_compilation_time;
- static volatile jint _print_compilation_warning;
+ static volatile int _print_compilation_warning;
static JavaThread* make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, bool compiler_thread, TRAPS);
static void init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count);
--- a/src/hotspot/share/compiler/compileLog.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/compiler/compileLog.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,12 +23,12 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "ci/ciMethod.hpp"
#include "code/codeCache.hpp"
#include "compiler/compileLog.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/method.hpp"
-#include "prims/jvm.h"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
--- a/src/hotspot/share/compiler/compilerOracle.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/compiler/compilerOracle.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "compiler/compilerOracle.hpp"
#include "compiler/methodMatcher.hpp"
#include "memory/allocation.inline.hpp"
@@ -31,7 +32,6 @@
#include "oops/klass.hpp"
#include "oops/method.hpp"
#include "oops/symbol.hpp"
-#include "prims/jvm.h"
#include "runtime/handles.inline.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/os.hpp"
--- a/src/hotspot/share/compiler/oopMap.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/compiler/oopMap.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -268,9 +268,9 @@
#if !defined(TIERED) && !defined(INCLUDE_JVMCI)
COMPILER1_PRESENT(ShouldNotReachHere();)
#endif // !defined(TIERED) && !defined(INCLUDE_JVMCI)
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTable::add(derived, base);
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
}
@@ -461,12 +461,12 @@
#if !defined(TIERED) && !defined(INCLUDE_JVMCI)
COMPILER1_PRESENT(return false);
#endif // !TIERED
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
OopMapStream oms(this,OopMapValue::derived_oop_value);
return oms.is_done();
#else
return false;
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
}
#endif //PRODUCT
@@ -726,7 +726,7 @@
//------------------------------DerivedPointerTable---------------------------
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
class DerivedPointerEntry : public CHeapObj<mtCompiler> {
private:
@@ -819,4 +819,4 @@
_active = false;
}
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
--- a/src/hotspot/share/compiler/oopMap.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/compiler/oopMap.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -427,7 +427,7 @@
// oops, it is filled in with references to all locations that contains a
// derived oop (assumed to be very few). When the GC is complete, the derived
// pointers are updated based on their base pointers new value and an offset.
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
class DerivedPointerTable : public AllStatic {
friend class VMStructs;
private:
@@ -463,6 +463,6 @@
}
}
};
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
#endif // SHARE_VM_COMPILER_OOPMAP_HPP
--- a/src/hotspot/share/gc/cms/cmsHeap.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/cms/cmsHeap.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -39,14 +39,16 @@
class WorkGang;
class CMSHeap : public GenCollectedHeap {
+
+protected:
+ virtual void check_gen_kinds();
+
public:
CMSHeap(GenCollectorPolicy *policy);
// Returns JNI_OK on success
virtual jint initialize();
- virtual void check_gen_kinds();
-
// Convenience function to be used in situations where the heap type can be
// asserted to be this type.
static CMSHeap* heap();
@@ -70,10 +72,6 @@
// supports. Caller does not hold the Heap_lock on entry.
void collect(GCCause::Cause cause);
- bool is_in_closed_subset(const void* p) const {
- return is_in_reserved(p);
- }
-
bool card_mark_must_follow_store() const {
return true;
}
--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -57,6 +57,7 @@
// Defaults are 0 so things will break badly if incorrectly initialized.
size_t CompactibleFreeListSpace::IndexSetStart = 0;
size_t CompactibleFreeListSpace::IndexSetStride = 0;
+size_t CompactibleFreeListSpace::_min_chunk_size_in_bytes = 0;
size_t MinChunkSize = 0;
@@ -66,8 +67,8 @@
// MinChunkSize should be a multiple of MinObjAlignment and be large enough
// for chunks to contain a FreeChunk.
- size_t min_chunk_size_in_bytes = align_up(sizeof(FreeChunk), MinObjAlignmentInBytes);
- MinChunkSize = min_chunk_size_in_bytes / BytesPerWord;
+ _min_chunk_size_in_bytes = align_up(sizeof(FreeChunk), MinObjAlignmentInBytes);
+ MinChunkSize = _min_chunk_size_in_bytes / BytesPerWord;
assert(IndexSetStart == 0 && IndexSetStride == 0, "already set");
IndexSetStart = MinChunkSize;
--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -118,6 +118,7 @@
};
static size_t IndexSetStart;
static size_t IndexSetStride;
+ static size_t _min_chunk_size_in_bytes;
private:
enum FitStrategyOptions {
@@ -134,6 +135,7 @@
// A lock protecting the free lists and free blocks;
// mutable because of ubiquity of locking even for otherwise const methods
mutable Mutex _freelistLock;
+
// Locking verifier convenience function
void assert_locked() const PRODUCT_RETURN;
void assert_locked(const Mutex* lock) const PRODUCT_RETURN;
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -2296,7 +2296,7 @@
// way with the marking information used by GC.
NoRefDiscovery no_discovery(ref_processor());
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTableDeactivate dpt_deact;
#endif
@@ -2869,7 +2869,7 @@
print_eden_and_survivor_chunk_arrays();
{
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTableDeactivate dpt_deact;
#endif
if (CMSParallelInitialMarkEnabled) {
@@ -4171,7 +4171,7 @@
print_eden_and_survivor_chunk_arrays();
{
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTableDeactivate dpt_deact;
#endif
--- a/src/hotspot/share/gc/cms/vmStructs_cms.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/cms/vmStructs_cms.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -30,7 +30,8 @@
static_field) \
nonstatic_field(CompactibleFreeListSpace, _collector, CMSCollector*) \
nonstatic_field(CompactibleFreeListSpace, _bt, BlockOffsetArrayNonContigSpace) \
- \
+ static_field(CompactibleFreeListSpace, _min_chunk_size_in_bytes, size_t) \
+ nonstatic_field(CMSBitMap, _bmStartWord, HeapWord*) \
nonstatic_field(CMSBitMap, _bmWordSize, size_t) \
nonstatic_field(CMSBitMap, _shifter, const int) \
nonstatic_field(CMSBitMap, _bm, BitMapView) \
@@ -63,6 +64,7 @@
declare_toplevel_type(LinearAllocBlock)
#define VM_INT_CONSTANTS_CMS(declare_constant) \
+ declare_constant(CompactibleFreeListSpace::IndexSetSize) \
declare_constant(Generation::ConcurrentMarkSweep) \
#endif // SHARE_VM_GC_CMS_VMSTRUCTS_CMS_HPP
--- a/src/hotspot/share/gc/g1/concurrentG1Refine.cpp Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,370 +0,0 @@
-/*
- * Copyright (c) 2001, 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/g1/concurrentG1Refine.hpp"
-#include "gc/g1/concurrentG1RefineThread.hpp"
-#include "gc/g1/g1YoungRemSetSamplingThread.hpp"
-#include "logging/log.hpp"
-#include "runtime/java.hpp"
-#include "runtime/thread.hpp"
-#include "utilities/debug.hpp"
-#include "utilities/globalDefinitions.hpp"
-#include "utilities/pair.hpp"
-#include <math.h>
-
-// Arbitrary but large limits, to simplify some of the zone calculations.
-// The general idea is to allow expressions like
-// MIN2(x OP y, max_XXX_zone)
-// without needing to check for overflow in "x OP y", because the
-// ranges for x and y have been restricted.
-STATIC_ASSERT(sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2));
-const size_t max_yellow_zone = LP64_ONLY(max_jint) NOT_LP64(max_jshort);
-const size_t max_green_zone = max_yellow_zone / 2;
-const size_t max_red_zone = INT_MAX; // For dcqs.set_max_completed_queue.
-STATIC_ASSERT(max_yellow_zone <= max_red_zone);
-
-// Range check assertions for green zone values.
-#define assert_zone_constraints_g(green) \
- do { \
- size_t azc_g_green = (green); \
- assert(azc_g_green <= max_green_zone, \
- "green exceeds max: " SIZE_FORMAT, azc_g_green); \
- } while (0)
-
-// Range check assertions for green and yellow zone values.
-#define assert_zone_constraints_gy(green, yellow) \
- do { \
- size_t azc_gy_green = (green); \
- size_t azc_gy_yellow = (yellow); \
- assert_zone_constraints_g(azc_gy_green); \
- assert(azc_gy_yellow <= max_yellow_zone, \
- "yellow exceeds max: " SIZE_FORMAT, azc_gy_yellow); \
- assert(azc_gy_green <= azc_gy_yellow, \
- "green (" SIZE_FORMAT ") exceeds yellow (" SIZE_FORMAT ")", \
- azc_gy_green, azc_gy_yellow); \
- } while (0)
-
-// Range check assertions for green, yellow, and red zone values.
-#define assert_zone_constraints_gyr(green, yellow, red) \
- do { \
- size_t azc_gyr_green = (green); \
- size_t azc_gyr_yellow = (yellow); \
- size_t azc_gyr_red = (red); \
- assert_zone_constraints_gy(azc_gyr_green, azc_gyr_yellow); \
- assert(azc_gyr_red <= max_red_zone, \
- "red exceeds max: " SIZE_FORMAT, azc_gyr_red); \
- assert(azc_gyr_yellow <= azc_gyr_red, \
- "yellow (" SIZE_FORMAT ") exceeds red (" SIZE_FORMAT ")", \
- azc_gyr_yellow, azc_gyr_red); \
- } while (0)
-
-// Logging tag sequence for refinement control updates.
-#define CTRL_TAGS gc, ergo, refine
-
-// For logging zone values, ensuring consistency of level and tags.
-#define LOG_ZONES(...) log_debug( CTRL_TAGS )(__VA_ARGS__)
-
-// Package for pair of refinement thread activation and deactivation
-// thresholds. The activation and deactivation levels are resp. the first
-// and second values of the pair.
-typedef Pair<size_t, size_t> Thresholds;
-inline size_t activation_level(const Thresholds& t) { return t.first; }
-inline size_t deactivation_level(const Thresholds& t) { return t.second; }
-
-static Thresholds calc_thresholds(size_t green_zone,
- size_t yellow_zone,
- uint worker_i) {
- double yellow_size = yellow_zone - green_zone;
- double step = yellow_size / ConcurrentG1Refine::thread_num();
- if (worker_i == 0) {
- // Potentially activate worker 0 more aggressively, to keep
- // available buffers near green_zone value. When yellow_size is
- // large we don't want to allow a full step to accumulate before
- // doing any processing, as that might lead to significantly more
- // than green_zone buffers to be processed by update_rs.
- step = MIN2(step, ParallelGCThreads / 2.0);
- }
- size_t activate_offset = static_cast<size_t>(ceil(step * (worker_i + 1)));
- size_t deactivate_offset = static_cast<size_t>(floor(step * worker_i));
- return Thresholds(green_zone + activate_offset,
- green_zone + deactivate_offset);
-}
-
-ConcurrentG1Refine::ConcurrentG1Refine(size_t green_zone,
- size_t yellow_zone,
- size_t red_zone,
- size_t min_yellow_zone_size) :
- _threads(NULL),
- _sample_thread(NULL),
- _n_worker_threads(thread_num()),
- _green_zone(green_zone),
- _yellow_zone(yellow_zone),
- _red_zone(red_zone),
- _min_yellow_zone_size(min_yellow_zone_size)
-{
- assert_zone_constraints_gyr(green_zone, yellow_zone, red_zone);
-}
-
-static size_t calc_min_yellow_zone_size() {
- size_t step = G1ConcRefinementThresholdStep;
- uint n_workers = ConcurrentG1Refine::thread_num();
- if ((max_yellow_zone / step) < n_workers) {
- return max_yellow_zone;
- } else {
- return step * n_workers;
- }
-}
-
-static size_t calc_init_green_zone() {
- size_t green = G1ConcRefinementGreenZone;
- if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) {
- green = ParallelGCThreads;
- }
- return MIN2(green, max_green_zone);
-}
-
-static size_t calc_init_yellow_zone(size_t green, size_t min_size) {
- size_t config = G1ConcRefinementYellowZone;
- size_t size = 0;
- if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) {
- size = green * 2;
- } else if (green < config) {
- size = config - green;
- }
- size = MAX2(size, min_size);
- size = MIN2(size, max_yellow_zone);
- return MIN2(green + size, max_yellow_zone);
-}
-
-static size_t calc_init_red_zone(size_t green, size_t yellow) {
- size_t size = yellow - green;
- if (!FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) {
- size_t config = G1ConcRefinementRedZone;
- if (yellow < config) {
- size = MAX2(size, config - yellow);
- }
- }
- return MIN2(yellow + size, max_red_zone);
-}
-
-ConcurrentG1Refine* ConcurrentG1Refine::create(jint* ecode) {
- size_t min_yellow_zone_size = calc_min_yellow_zone_size();
- size_t green_zone = calc_init_green_zone();
- size_t yellow_zone = calc_init_yellow_zone(green_zone, min_yellow_zone_size);
- size_t red_zone = calc_init_red_zone(green_zone, yellow_zone);
-
- LOG_ZONES("Initial Refinement Zones: "
- "green: " SIZE_FORMAT ", "
- "yellow: " SIZE_FORMAT ", "
- "red: " SIZE_FORMAT ", "
- "min yellow size: " SIZE_FORMAT,
- green_zone, yellow_zone, red_zone, min_yellow_zone_size);
-
- ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(green_zone,
- yellow_zone,
- red_zone,
- min_yellow_zone_size);
-
- if (cg1r == NULL) {
- *ecode = JNI_ENOMEM;
- vm_shutdown_during_initialization("Could not create ConcurrentG1Refine");
- return NULL;
- }
-
- cg1r->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(ConcurrentG1RefineThread*, cg1r->_n_worker_threads, mtGC);
- if (cg1r->_threads == NULL) {
- *ecode = JNI_ENOMEM;
- vm_shutdown_during_initialization("Could not allocate an array for ConcurrentG1RefineThread");
- return NULL;
- }
-
- uint worker_id_offset = DirtyCardQueueSet::num_par_ids();
-
- ConcurrentG1RefineThread *next = NULL;
- for (uint i = cg1r->_n_worker_threads - 1; i != UINT_MAX; i--) {
- Thresholds thresholds = calc_thresholds(green_zone, yellow_zone, i);
- ConcurrentG1RefineThread* t =
- new ConcurrentG1RefineThread(cg1r,
- next,
- worker_id_offset,
- i,
- activation_level(thresholds),
- deactivation_level(thresholds));
- assert(t != NULL, "Conc refine should have been created");
- if (t->osthread() == NULL) {
- *ecode = JNI_ENOMEM;
- vm_shutdown_during_initialization("Could not create ConcurrentG1RefineThread");
- return NULL;
- }
-
- assert(t->cg1r() == cg1r, "Conc refine thread should refer to this");
- cg1r->_threads[i] = t;
- next = t;
- }
-
- cg1r->_sample_thread = new G1YoungRemSetSamplingThread();
- if (cg1r->_sample_thread->osthread() == NULL) {
- *ecode = JNI_ENOMEM;
- vm_shutdown_during_initialization("Could not create G1YoungRemSetSamplingThread");
- return NULL;
- }
-
- *ecode = JNI_OK;
- return cg1r;
-}
-
-void ConcurrentG1Refine::stop() {
- for (uint i = 0; i < _n_worker_threads; i++) {
- _threads[i]->stop();
- }
- _sample_thread->stop();
-}
-
-void ConcurrentG1Refine::update_thread_thresholds() {
- for (uint i = 0; i < _n_worker_threads; i++) {
- Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, i);
- _threads[i]->update_thresholds(activation_level(thresholds),
- deactivation_level(thresholds));
- }
-}
-
-ConcurrentG1Refine::~ConcurrentG1Refine() {
- for (uint i = 0; i < _n_worker_threads; i++) {
- delete _threads[i];
- }
- FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _threads);
-
- delete _sample_thread;
-}
-
-void ConcurrentG1Refine::threads_do(ThreadClosure *tc) {
- worker_threads_do(tc);
- tc->do_thread(_sample_thread);
-}
-
-void ConcurrentG1Refine::worker_threads_do(ThreadClosure * tc) {
- for (uint i = 0; i < _n_worker_threads; i++) {
- tc->do_thread(_threads[i]);
- }
-}
-
-uint ConcurrentG1Refine::thread_num() {
- return G1ConcRefinementThreads;
-}
-
-void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const {
- for (uint i = 0; i < _n_worker_threads; ++i) {
- _threads[i]->print_on(st);
- st->cr();
- }
- _sample_thread->print_on(st);
- st->cr();
-}
-
-static size_t calc_new_green_zone(size_t green,
- double update_rs_time,
- size_t update_rs_processed_buffers,
- double goal_ms) {
- // Adjust green zone based on whether we're meeting the time goal.
- // Limit to max_green_zone.
- const double inc_k = 1.1, dec_k = 0.9;
- if (update_rs_time > goal_ms) {
- if (green > 0) {
- green = static_cast<size_t>(green * dec_k);
- }
- } else if (update_rs_time < goal_ms &&
- update_rs_processed_buffers > green) {
- green = static_cast<size_t>(MAX2(green * inc_k, green + 1.0));
- green = MIN2(green, max_green_zone);
- }
- return green;
-}
-
-static size_t calc_new_yellow_zone(size_t green, size_t min_yellow_size) {
- size_t size = green * 2;
- size = MAX2(size, min_yellow_size);
- return MIN2(green + size, max_yellow_zone);
-}
-
-static size_t calc_new_red_zone(size_t green, size_t yellow) {
- return MIN2(yellow + (yellow - green), max_red_zone);
-}
-
-void ConcurrentG1Refine::update_zones(double update_rs_time,
- size_t update_rs_processed_buffers,
- double goal_ms) {
- log_trace( CTRL_TAGS )("Updating Refinement Zones: "
- "update_rs time: %.3fms, "
- "update_rs buffers: " SIZE_FORMAT ", "
- "update_rs goal time: %.3fms",
- update_rs_time,
- update_rs_processed_buffers,
- goal_ms);
-
- _green_zone = calc_new_green_zone(_green_zone,
- update_rs_time,
- update_rs_processed_buffers,
- goal_ms);
- _yellow_zone = calc_new_yellow_zone(_green_zone, _min_yellow_zone_size);
- _red_zone = calc_new_red_zone(_green_zone, _yellow_zone);
-
- assert_zone_constraints_gyr(_green_zone, _yellow_zone, _red_zone);
- LOG_ZONES("Updated Refinement Zones: "
- "green: " SIZE_FORMAT ", "
- "yellow: " SIZE_FORMAT ", "
- "red: " SIZE_FORMAT,
- _green_zone, _yellow_zone, _red_zone);
-}
-
-void ConcurrentG1Refine::adjust(double update_rs_time,
- size_t update_rs_processed_buffers,
- double goal_ms) {
- DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
-
- if (G1UseAdaptiveConcRefinement) {
- update_zones(update_rs_time, update_rs_processed_buffers, goal_ms);
- update_thread_thresholds();
-
- // Change the barrier params
- if (_n_worker_threads == 0) {
- // Disable dcqs notification when there are no threads to notify.
- dcqs.set_process_completed_threshold(INT_MAX);
- } else {
- // Worker 0 is the primary; wakeup is via dcqs notification.
- STATIC_ASSERT(max_yellow_zone <= INT_MAX);
- size_t activate = _threads[0]->activation_threshold();
- dcqs.set_process_completed_threshold((int)activate);
- }
- dcqs.set_max_completed_queue((int)red_zone());
- }
-
- size_t curr_queue_size = dcqs.completed_buffers_num();
- if (curr_queue_size >= yellow_zone()) {
- dcqs.set_completed_queue_padding(curr_queue_size);
- } else {
- dcqs.set_completed_queue_padding(0);
- }
- dcqs.notify_if_necessary();
-}
--- a/src/hotspot/share/gc/g1/concurrentG1Refine.hpp Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2001, 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_G1_CONCURRENTG1REFINE_HPP
-#define SHARE_VM_GC_G1_CONCURRENTG1REFINE_HPP
-
-#include "memory/allocation.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-// Forward decl
-class CardTableEntryClosure;
-class ConcurrentG1RefineThread;
-class G1YoungRemSetSamplingThread;
-class outputStream;
-class ThreadClosure;
-
-class ConcurrentG1Refine: public CHeapObj<mtGC> {
- G1YoungRemSetSamplingThread* _sample_thread;
-
- ConcurrentG1RefineThread** _threads;
- uint _n_worker_threads;
- /*
- * The value of the update buffer queue length falls into one of 3 zones:
- * green, yellow, red. If the value is in [0, green) nothing is
- * done, the buffers are left unprocessed to enable the caching effect of the
- * dirtied cards. In the yellow zone [green, yellow) the concurrent refinement
- * threads are gradually activated. In [yellow, red) all threads are
- * running. If the length becomes red (max queue length) the mutators start
- * processing the buffers.
- *
- * There are some interesting cases (when G1UseAdaptiveConcRefinement
- * is turned off):
- * 1) green = yellow = red = 0. In this case the mutator will process all
- * buffers. Except for those that are created by the deferred updates
- * machinery during a collection.
- * 2) green = 0. Means no caching. Can be a good way to minimize the
- * amount of time spent updating rsets during a collection.
- */
- size_t _green_zone;
- size_t _yellow_zone;
- size_t _red_zone;
- size_t _min_yellow_zone_size;
-
- ConcurrentG1Refine(size_t green_zone,
- size_t yellow_zone,
- size_t red_zone,
- size_t min_yellow_zone_size);
-
- // Update green/yellow/red zone values based on how well goals are being met.
- void update_zones(double update_rs_time,
- size_t update_rs_processed_buffers,
- double goal_ms);
-
- // Update thread thresholds to account for updated zone values.
- void update_thread_thresholds();
-
- public:
- ~ConcurrentG1Refine();
-
- // Returns ConcurrentG1Refine instance if succeeded to create/initialize ConcurrentG1Refine and ConcurrentG1RefineThread.
- // Otherwise, returns NULL with error code.
- static ConcurrentG1Refine* create(jint* ecode);
-
- void stop();
-
- void adjust(double update_rs_time, size_t update_rs_processed_buffers, double goal_ms);
-
- // Iterate over all concurrent refinement threads
- void threads_do(ThreadClosure *tc);
-
- // Iterate over all worker refinement threads
- void worker_threads_do(ThreadClosure * tc);
-
- // The RS sampling thread has nothing to do with refinement, but is here for now.
- G1YoungRemSetSamplingThread * sampling_thread() const { return _sample_thread; }
-
- static uint thread_num();
-
- void print_worker_threads_on(outputStream* st) const;
-
- size_t green_zone() const { return _green_zone; }
- size_t yellow_zone() const { return _yellow_zone; }
- size_t red_zone() const { return _red_zone; }
-};
-
-#endif // SHARE_VM_GC_G1_CONCURRENTG1REFINE_HPP
--- a/src/hotspot/share/gc/g1/concurrentG1RefineThread.cpp Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/g1/concurrentG1Refine.hpp"
-#include "gc/g1/concurrentG1RefineThread.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
-#include "gc/g1/g1RemSet.hpp"
-#include "gc/shared/suspendibleThreadSet.hpp"
-#include "logging/log.hpp"
-#include "memory/resourceArea.hpp"
-#include "runtime/handles.inline.hpp"
-#include "runtime/mutexLocker.hpp"
-
-ConcurrentG1RefineThread::
-ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next,
- uint worker_id_offset, uint worker_id,
- size_t activate, size_t deactivate) :
- ConcurrentGCThread(),
- _worker_id_offset(worker_id_offset),
- _worker_id(worker_id),
- _active(false),
- _next(next),
- _monitor(NULL),
- _cg1r(cg1r),
- _vtime_accum(0.0),
- _activation_threshold(activate),
- _deactivation_threshold(deactivate)
-{
-
- // Each thread has its own monitor. The i-th thread is responsible for signaling
- // to thread i+1 if the number of buffers in the queue exceeds a threshold for this
- // thread. Monitors are also used to wake up the threads during termination.
- // The 0th (primary) worker is notified by mutator threads and has a special monitor.
- if (!is_primary()) {
- _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true,
- Monitor::_safepoint_check_never);
- } else {
- _monitor = DirtyCardQ_CBL_mon;
- }
-
- // set name
- set_name("G1 Refine#%d", worker_id);
- create_and_start();
-}
-
-void ConcurrentG1RefineThread::update_thresholds(size_t activate,
- size_t deactivate) {
- assert(deactivate < activate, "precondition");
- _activation_threshold = activate;
- _deactivation_threshold = deactivate;
-}
-
-void ConcurrentG1RefineThread::wait_for_completed_buffers() {
- MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
- while (!should_terminate() && !is_active()) {
- _monitor->wait(Mutex::_no_safepoint_check_flag);
- }
-}
-
-bool ConcurrentG1RefineThread::is_active() {
- DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
- return is_primary() ? dcqs.process_completed_buffers() : _active;
-}
-
-void ConcurrentG1RefineThread::activate() {
- MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
- if (!is_primary()) {
- set_active(true);
- } else {
- DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
- dcqs.set_process_completed(true);
- }
- _monitor->notify();
-}
-
-void ConcurrentG1RefineThread::deactivate() {
- MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
- if (!is_primary()) {
- set_active(false);
- } else {
- DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
- dcqs.set_process_completed(false);
- }
-}
-
-void ConcurrentG1RefineThread::run_service() {
- _vtime_start = os::elapsedVTime();
-
- while (!should_terminate()) {
- // Wait for work
- wait_for_completed_buffers();
- if (should_terminate()) {
- break;
- }
-
- size_t buffers_processed = 0;
- DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
- log_debug(gc, refine)("Activated %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT,
- _worker_id, _activation_threshold, dcqs.completed_buffers_num());
-
- {
- SuspendibleThreadSetJoiner sts_join;
-
- while (!should_terminate()) {
- if (sts_join.should_yield()) {
- sts_join.yield();
- continue; // Re-check for termination after yield delay.
- }
-
- size_t curr_buffer_num = dcqs.completed_buffers_num();
- // If the number of the buffers falls down into the yellow zone,
- // that means that the transition period after the evacuation pause has ended.
- if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) {
- dcqs.set_completed_queue_padding(0);
- }
-
- // Check if we need to activate the next thread.
- if ((_next != NULL) &&
- !_next->is_active() &&
- (curr_buffer_num > _next->_activation_threshold)) {
- _next->activate();
- }
-
- // Process the next buffer, if there are enough left.
- if (!dcqs.refine_completed_buffer_concurrently(_worker_id + _worker_id_offset, _deactivation_threshold)) {
- break; // Deactivate, number of buffers fell below threshold.
- }
- ++buffers_processed;
- }
- }
-
- deactivate();
- log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT
- ", current: " SIZE_FORMAT ", processed: " SIZE_FORMAT,
- _worker_id, _deactivation_threshold,
- dcqs.completed_buffers_num(),
- buffers_processed);
-
- if (os::supports_vtime()) {
- _vtime_accum = (os::elapsedVTime() - _vtime_start);
- } else {
- _vtime_accum = 0.0;
- }
- }
-
- log_debug(gc, refine)("Stopping %d", _worker_id);
-}
-
-void ConcurrentG1RefineThread::stop_service() {
- MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
- _monitor->notify();
-}
--- a/src/hotspot/share/gc/g1/concurrentG1RefineThread.hpp Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2001, 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_G1_CONCURRENTG1REFINETHREAD_HPP
-#define SHARE_VM_GC_G1_CONCURRENTG1REFINETHREAD_HPP
-
-#include "gc/g1/dirtyCardQueue.hpp"
-#include "gc/shared/concurrentGCThread.hpp"
-
-// Forward Decl.
-class CardTableEntryClosure;
-class ConcurrentG1Refine;
-
-// One or more G1 Concurrent Refinement Threads may be active if concurrent
-// refinement is in progress.
-class ConcurrentG1RefineThread: public ConcurrentGCThread {
- friend class VMStructs;
- friend class G1CollectedHeap;
-
- double _vtime_start; // Initial virtual time.
- double _vtime_accum; // Accumulated virtual time.
- uint _worker_id;
- uint _worker_id_offset;
-
- // The refinement threads collection is linked list. A predecessor can activate a successor
- // when the number of the rset update buffer crosses a certain threshold. A successor
- // would self-deactivate when the number of the buffers falls below the threshold.
- bool _active;
- ConcurrentG1RefineThread* _next;
- Monitor* _monitor;
- ConcurrentG1Refine* _cg1r;
-
- // This thread's activation/deactivation thresholds
- size_t _activation_threshold;
- size_t _deactivation_threshold;
-
- void wait_for_completed_buffers();
-
- void set_active(bool x) { _active = x; }
- bool is_active();
- void activate();
- void deactivate();
-
- bool is_primary() { return (_worker_id == 0); }
-
- void run_service();
- void stop_service();
-
-public:
- // Constructor
- ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next,
- uint worker_id_offset, uint worker_id,
- size_t activate, size_t deactivate);
-
- void update_thresholds(size_t activate, size_t deactivate);
- size_t activation_threshold() const { return _activation_threshold; }
-
- // Total virtual time so far.
- double vtime_accum() { return _vtime_accum; }
-
- ConcurrentG1Refine* cg1r() { return _cg1r; }
-};
-
-#endif // SHARE_VM_GC_G1_CONCURRENTG1REFINETHREAD_HPP
--- a/src/hotspot/share/gc/g1/concurrentMarkThread.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/concurrentMarkThread.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -111,16 +111,31 @@
}
};
-// Marking pauses can be scheduled flexibly, so we might delay marking to meet MMU.
+double ConcurrentMarkThread::mmu_sleep_time(G1Policy* g1_policy, bool remark) {
+ // There are 3 reasons to use SuspendibleThreadSetJoiner.
+ // 1. To avoid concurrency problem.
+ // - G1MMUTracker::add_pause(), when_sec() and its variation(when_ms() etc..) can be called
+ // concurrently from ConcurrentMarkThread and VMThread.
+ // 2. If currently a gc is running, but it has not yet updated the MMU,
+ // we will not forget to consider that pause in the MMU calculation.
+ // 3. If currently a gc is running, ConcurrentMarkThread will wait it to be finished.
+ // And then sleep for predicted amount of time by delay_to_keep_mmu().
+ SuspendibleThreadSetJoiner sts_join;
+
+ const G1Analytics* analytics = g1_policy->analytics();
+ double now = os::elapsedTime();
+ double prediction_ms = remark ? analytics->predict_remark_time_ms()
+ : analytics->predict_cleanup_time_ms();
+ G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker();
+ return mmu_tracker->when_ms(now, prediction_ms);
+}
+
void ConcurrentMarkThread::delay_to_keep_mmu(G1Policy* g1_policy, bool remark) {
- const G1Analytics* analytics = g1_policy->analytics();
if (g1_policy->adaptive_young_list_length()) {
- double now = os::elapsedTime();
- double prediction_ms = remark ? analytics->predict_remark_time_ms()
- : analytics->predict_cleanup_time_ms();
- G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker();
- jlong sleep_time_ms = mmu_tracker->when_ms(now, prediction_ms);
- os::sleep(this, sleep_time_ms, false);
+ jlong sleep_time_ms = mmu_sleep_time(g1_policy, remark);
+ if (!cm()->has_aborted() && sleep_time_ms > 0) {
+ os::sleep(this, sleep_time_ms, false);
+ }
}
}
@@ -349,9 +364,11 @@
if (!cm()->has_aborted()) {
delay_to_keep_mmu(g1_policy, false /* cleanup */);
- CMCleanUp cl_cl(_cm);
- VM_CGC_Operation op(&cl_cl, "Pause Cleanup");
- VMThread::execute(&op);
+ if (!cm()->has_aborted()) {
+ CMCleanUp cl_cl(_cm);
+ VM_CGC_Operation op(&cl_cl, "Pause Cleanup");
+ VMThread::execute(&op);
+ }
} else {
// We don't want to update the marking status if a GC pause
// is already underway.
--- a/src/hotspot/share/gc/g1/concurrentMarkThread.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/concurrentMarkThread.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -55,7 +55,9 @@
ConcurrentGCPhaseManager::Stack _phase_manager_stack;
void sleepBeforeNextCycle();
+ // Delay marking to meet MMU.
void delay_to_keep_mmu(G1Policy* g1_policy, bool remark);
+ double mmu_sleep_time(G1Policy* g1_policy, bool remark);
void run_service();
void stop_service();
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -29,14 +29,14 @@
#include "code/codeCache.hpp"
#include "code/icBuffer.hpp"
#include "gc/g1/bufferingOopClosure.hpp"
-#include "gc/g1/concurrentG1Refine.hpp"
-#include "gc/g1/concurrentG1RefineThread.hpp"
#include "gc/g1/concurrentMarkThread.inline.hpp"
#include "gc/g1/g1Allocator.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectionSet.hpp"
#include "gc/g1/g1CollectorPolicy.hpp"
#include "gc/g1/g1CollectorState.hpp"
+#include "gc/g1/g1ConcurrentRefine.hpp"
+#include "gc/g1/g1ConcurrentRefineThread.hpp"
#include "gc/g1/g1EvacStats.inline.hpp"
#include "gc/g1/g1FullGCScope.hpp"
#include "gc/g1/g1GCPhaseTimes.hpp"
@@ -54,6 +54,7 @@
#include "gc/g1/g1SerialFullCollector.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/g1YCTypes.hpp"
+#include "gc/g1/g1YoungRemSetSamplingThread.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "gc/g1/heapRegionSet.inline.hpp"
@@ -1541,6 +1542,7 @@
G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* collector_policy) :
CollectedHeap(),
+ _young_gen_sampling_thread(NULL),
_collector_policy(collector_policy),
_gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()),
_gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()),
@@ -1554,7 +1556,7 @@
_bot(NULL),
_hot_card_cache(NULL),
_g1_rem_set(NULL),
- _cg1r(NULL),
+ _cr(NULL),
_g1mm(NULL),
_preserved_marks_set(true /* in_c_heap */),
_secondary_free_list("Secondary Free List", new SecondaryFreeRegionListMtSafeChecker()),
@@ -1633,10 +1635,19 @@
jint G1CollectedHeap::initialize_concurrent_refinement() {
jint ecode = JNI_OK;
- _cg1r = ConcurrentG1Refine::create(&ecode);
+ _cr = G1ConcurrentRefine::create(&ecode);
return ecode;
}
+jint G1CollectedHeap::initialize_young_gen_sampling_thread() {
+ _young_gen_sampling_thread = new G1YoungRemSetSamplingThread();
+ if (_young_gen_sampling_thread->osthread() == NULL) {
+ vm_shutdown_during_initialization("Could not create G1YoungRemSetSamplingThread");
+ return JNI_ENOMEM;
+ }
+ return JNI_OK;
+}
+
jint G1CollectedHeap::initialize() {
CollectedHeap::pre_initialize();
os::enable_vtime();
@@ -1789,10 +1800,15 @@
return ecode;
}
+ ecode = initialize_young_gen_sampling_thread();
+ if (ecode != JNI_OK) {
+ return ecode;
+ }
+
JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
DirtyCardQ_FL_lock,
- (int)concurrent_g1_refine()->yellow_zone(),
- (int)concurrent_g1_refine()->red_zone(),
+ (int)concurrent_refine()->yellow_zone(),
+ (int)concurrent_refine()->red_zone(),
Shared_DirtyCardQ_lock,
NULL, // fl_owner
true); // init_free_ids
@@ -1836,7 +1852,8 @@
// Stop all concurrent threads. We do this to make sure these threads
// do not continue to execute and access resources (e.g. logging)
// that are destroyed during shutdown.
- _cg1r->stop();
+ _cr->stop();
+ _young_gen_sampling_thread->stop();
_cmThread->stop();
if (G1StringDedup::is_enabled()) {
G1StringDedup::stop();
@@ -2390,9 +2407,8 @@
st->print(" %-20s", "garbage-first heap");
st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K",
capacity()/K, used_unlocked()/K);
- st->print(" [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ")",
+ st->print(" [" PTR_FORMAT ", " PTR_FORMAT ")",
p2i(_hrm.reserved().start()),
- p2i(_hrm.reserved().start() + _hrm.length() + HeapRegion::GrainWords),
p2i(_hrm.reserved().end()));
st->cr();
st->print(" region size " SIZE_FORMAT "K, ", HeapRegion::GrainBytes / K);
@@ -2437,7 +2453,8 @@
_cmThread->print_on(st);
st->cr();
_cm->print_worker_threads_on(st);
- _cg1r->print_worker_threads_on(st); // also prints the sample thread
+ _cr->print_threads_on(st);
+ _young_gen_sampling_thread->print_on(st);
if (G1StringDedup::is_enabled()) {
G1StringDedup::print_worker_threads_on(st);
}
@@ -2447,7 +2464,8 @@
workers()->threads_do(tc);
tc->do_thread(_cmThread);
_cm->threads_do(tc);
- _cg1r->threads_do(tc); // also iterates over the sample thread
+ _cr->threads_do(tc);
+ tc->do_thread(_young_gen_sampling_thread);
if (G1StringDedup::is_enabled()) {
G1StringDedup::threads_do(tc);
}
@@ -2579,7 +2597,7 @@
// FIXME: what is this about?
// I'm ignoring the "fill_newgen()" call if "alloc_event_enabled"
// is set.
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
assert(DerivedPointerTable::is_empty(), "derived pointer present");
#endif
// always_do_update_barrier = true;
@@ -2992,7 +3010,7 @@
_verifier->check_bitmaps("GC Start");
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
@@ -3622,7 +3640,7 @@
class G1KlassCleaningTask : public StackObj {
BoolObjectClosure* _is_alive;
- volatile jint _clean_klass_tree_claimed;
+ volatile int _clean_klass_tree_claimed;
ClassLoaderDataGraphKlassIteratorAtomic _klass_iterator;
public:
@@ -3638,7 +3656,7 @@
return false;
}
- return Atomic::cmpxchg(1, (jint*)&_clean_klass_tree_claimed, 0) == 0;
+ return Atomic::cmpxchg(1, &_clean_klass_tree_claimed, 0) == 0;
}
InstanceKlass* claim_next_klass() {
@@ -3675,7 +3693,7 @@
class G1ResolvedMethodCleaningTask : public StackObj {
BoolObjectClosure* _is_alive;
- volatile jint _resolved_method_task_claimed;
+ volatile int _resolved_method_task_claimed;
public:
G1ResolvedMethodCleaningTask(BoolObjectClosure* is_alive) :
_is_alive(is_alive), _resolved_method_task_claimed(0) {}
@@ -3684,7 +3702,7 @@
if (_resolved_method_task_claimed) {
return false;
}
- return Atomic::cmpxchg(1, (jint*)&_resolved_method_task_claimed, 0) == 0;
+ return Atomic::cmpxchg(1, &_resolved_method_task_claimed, 0) == 0;
}
// These aren't big, one thread can do it all.
@@ -4421,7 +4439,7 @@
purge_code_root_memory();
redirty_logged_cards();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
double start = os::elapsedTime();
DerivedPointerTable::update_pointers();
g1_policy()->phase_times()->record_derived_pointer_table_update_time((os::elapsedTime() - start) * 1000.0);
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -73,10 +73,11 @@
class G1Policy;
class G1HotCardCache;
class G1RemSet;
+class G1YoungRemSetSamplingThread;
class HeapRegionRemSetIterator;
class G1ConcurrentMark;
class ConcurrentMarkThread;
-class ConcurrentG1Refine;
+class G1ConcurrentRefine;
class GenerationCounters;
class STWGCTimer;
class G1NewTracer;
@@ -142,6 +143,8 @@
friend class G1CheckCSetFastTableClosure;
private:
+ G1YoungRemSetSamplingThread* _young_gen_sampling_thread;
+
WorkGang* _workers;
G1CollectorPolicy* _collector_policy;
@@ -553,6 +556,8 @@
// during GC into global variables.
void merge_per_thread_state_info(G1ParScanThreadStateSet* per_thread_states);
public:
+ G1YoungRemSetSamplingThread* sampling_thread() const { return _young_gen_sampling_thread; }
+
WorkGang* workers() const { return _workers; }
G1Allocator* allocator() {
@@ -806,7 +811,7 @@
ConcurrentMarkThread* _cmThread;
// The concurrent refiner.
- ConcurrentG1Refine* _cg1r;
+ G1ConcurrentRefine* _cr;
// The parallel task queues
RefToScanQueueSet *_task_queues;
@@ -959,6 +964,7 @@
private:
jint initialize_concurrent_refinement();
+ jint initialize_young_gen_sampling_thread();
public:
// Initialize the G1CollectedHeap to have the initial and
// maximum sizes and remembered and barrier sets
@@ -1389,7 +1395,7 @@
// Refinement
- ConcurrentG1Refine* concurrent_g1_refine() const { return _cg1r; }
+ G1ConcurrentRefine* concurrent_refine() const { return _cr; }
// Optimized nmethod scanning support routines
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/g1/g1ConcurrentRefine.hpp"
+#include "gc/g1/g1ConcurrentRefineThread.hpp"
+#include "logging/log.hpp"
+#include "runtime/java.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/pair.hpp"
+#include <math.h>
+
+// Arbitrary but large limits, to simplify some of the zone calculations.
+// The general idea is to allow expressions like
+// MIN2(x OP y, max_XXX_zone)
+// without needing to check for overflow in "x OP y", because the
+// ranges for x and y have been restricted.
+STATIC_ASSERT(sizeof(LP64_ONLY(jint) NOT_LP64(jshort)) <= (sizeof(size_t)/2));
+const size_t max_yellow_zone = LP64_ONLY(max_jint) NOT_LP64(max_jshort);
+const size_t max_green_zone = max_yellow_zone / 2;
+const size_t max_red_zone = INT_MAX; // For dcqs.set_max_completed_queue.
+STATIC_ASSERT(max_yellow_zone <= max_red_zone);
+
+// Range check assertions for green zone values.
+#define assert_zone_constraints_g(green) \
+ do { \
+ size_t azc_g_green = (green); \
+ assert(azc_g_green <= max_green_zone, \
+ "green exceeds max: " SIZE_FORMAT, azc_g_green); \
+ } while (0)
+
+// Range check assertions for green and yellow zone values.
+#define assert_zone_constraints_gy(green, yellow) \
+ do { \
+ size_t azc_gy_green = (green); \
+ size_t azc_gy_yellow = (yellow); \
+ assert_zone_constraints_g(azc_gy_green); \
+ assert(azc_gy_yellow <= max_yellow_zone, \
+ "yellow exceeds max: " SIZE_FORMAT, azc_gy_yellow); \
+ assert(azc_gy_green <= azc_gy_yellow, \
+ "green (" SIZE_FORMAT ") exceeds yellow (" SIZE_FORMAT ")", \
+ azc_gy_green, azc_gy_yellow); \
+ } while (0)
+
+// Range check assertions for green, yellow, and red zone values.
+#define assert_zone_constraints_gyr(green, yellow, red) \
+ do { \
+ size_t azc_gyr_green = (green); \
+ size_t azc_gyr_yellow = (yellow); \
+ size_t azc_gyr_red = (red); \
+ assert_zone_constraints_gy(azc_gyr_green, azc_gyr_yellow); \
+ assert(azc_gyr_red <= max_red_zone, \
+ "red exceeds max: " SIZE_FORMAT, azc_gyr_red); \
+ assert(azc_gyr_yellow <= azc_gyr_red, \
+ "yellow (" SIZE_FORMAT ") exceeds red (" SIZE_FORMAT ")", \
+ azc_gyr_yellow, azc_gyr_red); \
+ } while (0)
+
+// Logging tag sequence for refinement control updates.
+#define CTRL_TAGS gc, ergo, refine
+
+// For logging zone values, ensuring consistency of level and tags.
+#define LOG_ZONES(...) log_debug( CTRL_TAGS )(__VA_ARGS__)
+
+// Package for pair of refinement thread activation and deactivation
+// thresholds. The activation and deactivation levels are resp. the first
+// and second values of the pair.
+typedef Pair<size_t, size_t> Thresholds;
+inline size_t activation_level(const Thresholds& t) { return t.first; }
+inline size_t deactivation_level(const Thresholds& t) { return t.second; }
+
+static Thresholds calc_thresholds(size_t green_zone,
+ size_t yellow_zone,
+ uint worker_i) {
+ double yellow_size = yellow_zone - green_zone;
+ double step = yellow_size / G1ConcurrentRefine::thread_num();
+ if (worker_i == 0) {
+ // Potentially activate worker 0 more aggressively, to keep
+ // available buffers near green_zone value. When yellow_size is
+ // large we don't want to allow a full step to accumulate before
+ // doing any processing, as that might lead to significantly more
+ // than green_zone buffers to be processed by update_rs.
+ step = MIN2(step, ParallelGCThreads / 2.0);
+ }
+ size_t activate_offset = static_cast<size_t>(ceil(step * (worker_i + 1)));
+ size_t deactivate_offset = static_cast<size_t>(floor(step * worker_i));
+ return Thresholds(green_zone + activate_offset,
+ green_zone + deactivate_offset);
+}
+
+G1ConcurrentRefine::G1ConcurrentRefine(size_t green_zone,
+ size_t yellow_zone,
+ size_t red_zone,
+ size_t min_yellow_zone_size) :
+ _threads(NULL),
+ _n_worker_threads(thread_num()),
+ _green_zone(green_zone),
+ _yellow_zone(yellow_zone),
+ _red_zone(red_zone),
+ _min_yellow_zone_size(min_yellow_zone_size)
+{
+ assert_zone_constraints_gyr(green_zone, yellow_zone, red_zone);
+}
+
+static size_t calc_min_yellow_zone_size() {
+ size_t step = G1ConcRefinementThresholdStep;
+ uint n_workers = G1ConcurrentRefine::thread_num();
+ if ((max_yellow_zone / step) < n_workers) {
+ return max_yellow_zone;
+ } else {
+ return step * n_workers;
+ }
+}
+
+static size_t calc_init_green_zone() {
+ size_t green = G1ConcRefinementGreenZone;
+ if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) {
+ green = ParallelGCThreads;
+ }
+ return MIN2(green, max_green_zone);
+}
+
+static size_t calc_init_yellow_zone(size_t green, size_t min_size) {
+ size_t config = G1ConcRefinementYellowZone;
+ size_t size = 0;
+ if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) {
+ size = green * 2;
+ } else if (green < config) {
+ size = config - green;
+ }
+ size = MAX2(size, min_size);
+ size = MIN2(size, max_yellow_zone);
+ return MIN2(green + size, max_yellow_zone);
+}
+
+static size_t calc_init_red_zone(size_t green, size_t yellow) {
+ size_t size = yellow - green;
+ if (!FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) {
+ size_t config = G1ConcRefinementRedZone;
+ if (yellow < config) {
+ size = MAX2(size, config - yellow);
+ }
+ }
+ return MIN2(yellow + size, max_red_zone);
+}
+
+G1ConcurrentRefine* G1ConcurrentRefine::create(jint* ecode) {
+ size_t min_yellow_zone_size = calc_min_yellow_zone_size();
+ size_t green_zone = calc_init_green_zone();
+ size_t yellow_zone = calc_init_yellow_zone(green_zone, min_yellow_zone_size);
+ size_t red_zone = calc_init_red_zone(green_zone, yellow_zone);
+
+ LOG_ZONES("Initial Refinement Zones: "
+ "green: " SIZE_FORMAT ", "
+ "yellow: " SIZE_FORMAT ", "
+ "red: " SIZE_FORMAT ", "
+ "min yellow size: " SIZE_FORMAT,
+ green_zone, yellow_zone, red_zone, min_yellow_zone_size);
+
+ G1ConcurrentRefine* cr = new G1ConcurrentRefine(green_zone,
+ yellow_zone,
+ red_zone,
+ min_yellow_zone_size);
+
+ if (cr == NULL) {
+ *ecode = JNI_ENOMEM;
+ vm_shutdown_during_initialization("Could not create G1ConcurrentRefine");
+ return NULL;
+ }
+
+ cr->_threads = NEW_C_HEAP_ARRAY_RETURN_NULL(G1ConcurrentRefineThread*, cr->_n_worker_threads, mtGC);
+ if (cr->_threads == NULL) {
+ *ecode = JNI_ENOMEM;
+ vm_shutdown_during_initialization("Could not allocate an array for G1ConcurrentRefineThread");
+ return NULL;
+ }
+
+ uint worker_id_offset = DirtyCardQueueSet::num_par_ids();
+
+ G1ConcurrentRefineThread *next = NULL;
+ for (uint i = cr->_n_worker_threads - 1; i != UINT_MAX; i--) {
+ Thresholds thresholds = calc_thresholds(green_zone, yellow_zone, i);
+ G1ConcurrentRefineThread* t =
+ new G1ConcurrentRefineThread(cr,
+ next,
+ worker_id_offset,
+ i,
+ activation_level(thresholds),
+ deactivation_level(thresholds));
+ assert(t != NULL, "Conc refine should have been created");
+ if (t->osthread() == NULL) {
+ *ecode = JNI_ENOMEM;
+ vm_shutdown_during_initialization("Could not create G1ConcurrentRefineThread");
+ return NULL;
+ }
+
+ assert(t->cr() == cr, "Conc refine thread should refer to this");
+ cr->_threads[i] = t;
+ next = t;
+ }
+
+ *ecode = JNI_OK;
+ return cr;
+}
+
+void G1ConcurrentRefine::stop() {
+ for (uint i = 0; i < _n_worker_threads; i++) {
+ _threads[i]->stop();
+ }
+}
+
+void G1ConcurrentRefine::update_thread_thresholds() {
+ for (uint i = 0; i < _n_worker_threads; i++) {
+ Thresholds thresholds = calc_thresholds(_green_zone, _yellow_zone, i);
+ _threads[i]->update_thresholds(activation_level(thresholds),
+ deactivation_level(thresholds));
+ }
+}
+
+G1ConcurrentRefine::~G1ConcurrentRefine() {
+ for (uint i = 0; i < _n_worker_threads; i++) {
+ delete _threads[i];
+ }
+ FREE_C_HEAP_ARRAY(G1ConcurrentRefineThread*, _threads);
+}
+
+void G1ConcurrentRefine::threads_do(ThreadClosure *tc) {
+ for (uint i = 0; i < _n_worker_threads; i++) {
+ tc->do_thread(_threads[i]);
+ }
+}
+
+uint G1ConcurrentRefine::thread_num() {
+ return G1ConcRefinementThreads;
+}
+
+void G1ConcurrentRefine::print_threads_on(outputStream* st) const {
+ for (uint i = 0; i < _n_worker_threads; ++i) {
+ _threads[i]->print_on(st);
+ st->cr();
+ }
+}
+
+static size_t calc_new_green_zone(size_t green,
+ double update_rs_time,
+ size_t update_rs_processed_buffers,
+ double goal_ms) {
+ // Adjust green zone based on whether we're meeting the time goal.
+ // Limit to max_green_zone.
+ const double inc_k = 1.1, dec_k = 0.9;
+ if (update_rs_time > goal_ms) {
+ if (green > 0) {
+ green = static_cast<size_t>(green * dec_k);
+ }
+ } else if (update_rs_time < goal_ms &&
+ update_rs_processed_buffers > green) {
+ green = static_cast<size_t>(MAX2(green * inc_k, green + 1.0));
+ green = MIN2(green, max_green_zone);
+ }
+ return green;
+}
+
+static size_t calc_new_yellow_zone(size_t green, size_t min_yellow_size) {
+ size_t size = green * 2;
+ size = MAX2(size, min_yellow_size);
+ return MIN2(green + size, max_yellow_zone);
+}
+
+static size_t calc_new_red_zone(size_t green, size_t yellow) {
+ return MIN2(yellow + (yellow - green), max_red_zone);
+}
+
+void G1ConcurrentRefine::update_zones(double update_rs_time,
+ size_t update_rs_processed_buffers,
+ double goal_ms) {
+ log_trace( CTRL_TAGS )("Updating Refinement Zones: "
+ "update_rs time: %.3fms, "
+ "update_rs buffers: " SIZE_FORMAT ", "
+ "update_rs goal time: %.3fms",
+ update_rs_time,
+ update_rs_processed_buffers,
+ goal_ms);
+
+ _green_zone = calc_new_green_zone(_green_zone,
+ update_rs_time,
+ update_rs_processed_buffers,
+ goal_ms);
+ _yellow_zone = calc_new_yellow_zone(_green_zone, _min_yellow_zone_size);
+ _red_zone = calc_new_red_zone(_green_zone, _yellow_zone);
+
+ assert_zone_constraints_gyr(_green_zone, _yellow_zone, _red_zone);
+ LOG_ZONES("Updated Refinement Zones: "
+ "green: " SIZE_FORMAT ", "
+ "yellow: " SIZE_FORMAT ", "
+ "red: " SIZE_FORMAT,
+ _green_zone, _yellow_zone, _red_zone);
+}
+
+void G1ConcurrentRefine::adjust(double update_rs_time,
+ size_t update_rs_processed_buffers,
+ double goal_ms) {
+ DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+
+ if (G1UseAdaptiveConcRefinement) {
+ update_zones(update_rs_time, update_rs_processed_buffers, goal_ms);
+ update_thread_thresholds();
+
+ // Change the barrier params
+ if (_n_worker_threads == 0) {
+ // Disable dcqs notification when there are no threads to notify.
+ dcqs.set_process_completed_threshold(INT_MAX);
+ } else {
+ // Worker 0 is the primary; wakeup is via dcqs notification.
+ STATIC_ASSERT(max_yellow_zone <= INT_MAX);
+ size_t activate = _threads[0]->activation_threshold();
+ dcqs.set_process_completed_threshold((int)activate);
+ }
+ dcqs.set_max_completed_queue((int)red_zone());
+ }
+
+ size_t curr_queue_size = dcqs.completed_buffers_num();
+ if (curr_queue_size >= yellow_zone()) {
+ dcqs.set_completed_queue_padding(curr_queue_size);
+ } else {
+ dcqs.set_completed_queue_padding(0);
+ }
+ dcqs.notify_if_necessary();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2001, 2017, 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_G1_G1CONCURRENTREFINE_HPP
+#define SHARE_VM_GC_G1_G1CONCURRENTREFINE_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+// Forward decl
+class CardTableEntryClosure;
+class G1ConcurrentRefineThread;
+class outputStream;
+class ThreadClosure;
+
+class G1ConcurrentRefine : public CHeapObj<mtGC> {
+ G1ConcurrentRefineThread** _threads;
+ uint _n_worker_threads;
+ /*
+ * The value of the update buffer queue length falls into one of 3 zones:
+ * green, yellow, red. If the value is in [0, green) nothing is
+ * done, the buffers are left unprocessed to enable the caching effect of the
+ * dirtied cards. In the yellow zone [green, yellow) the concurrent refinement
+ * threads are gradually activated. In [yellow, red) all threads are
+ * running. If the length becomes red (max queue length) the mutators start
+ * processing the buffers.
+ *
+ * There are some interesting cases (when G1UseAdaptiveConcRefinement
+ * is turned off):
+ * 1) green = yellow = red = 0. In this case the mutator will process all
+ * buffers. Except for those that are created by the deferred updates
+ * machinery during a collection.
+ * 2) green = 0. Means no caching. Can be a good way to minimize the
+ * amount of time spent updating rsets during a collection.
+ */
+ size_t _green_zone;
+ size_t _yellow_zone;
+ size_t _red_zone;
+ size_t _min_yellow_zone_size;
+
+ G1ConcurrentRefine(size_t green_zone,
+ size_t yellow_zone,
+ size_t red_zone,
+ size_t min_yellow_zone_size);
+
+ // Update green/yellow/red zone values based on how well goals are being met.
+ void update_zones(double update_rs_time,
+ size_t update_rs_processed_buffers,
+ double goal_ms);
+
+ // Update thread thresholds to account for updated zone values.
+ void update_thread_thresholds();
+
+ public:
+ ~G1ConcurrentRefine();
+
+ // Returns a G1ConcurrentRefine instance if succeeded to create/initialize G1ConcurrentRefine and G1ConcurrentRefineThreads.
+ // Otherwise, returns NULL with error code.
+ static G1ConcurrentRefine* create(jint* ecode);
+
+ void stop();
+
+ void adjust(double update_rs_time, size_t update_rs_processed_buffers, double goal_ms);
+
+ // Iterate over all concurrent refinement threads applying the given closure.
+ void threads_do(ThreadClosure *tc);
+
+ static uint thread_num();
+
+ void print_threads_on(outputStream* st) const;
+
+ size_t green_zone() const { return _green_zone; }
+ size_t yellow_zone() const { return _yellow_zone; }
+ size_t red_zone() const { return _red_zone; }
+};
+
+#endif // SHARE_VM_GC_G1_G1CONCURRENTREFINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/g1/g1ConcurrentRefine.hpp"
+#include "gc/g1/g1ConcurrentRefineThread.hpp"
+#include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1RemSet.hpp"
+#include "gc/shared/suspendibleThreadSet.hpp"
+#include "logging/log.hpp"
+#include "memory/resourceArea.hpp"
+#include "runtime/handles.inline.hpp"
+#include "runtime/mutexLocker.hpp"
+
+G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr,
+ G1ConcurrentRefineThread *next,
+ uint worker_id_offset,
+ uint worker_id,
+ size_t activate,
+ size_t deactivate) :
+ ConcurrentGCThread(),
+ _worker_id_offset(worker_id_offset),
+ _worker_id(worker_id),
+ _active(false),
+ _next(next),
+ _monitor(NULL),
+ _cr(cr),
+ _vtime_accum(0.0),
+ _activation_threshold(activate),
+ _deactivation_threshold(deactivate)
+{
+
+ // Each thread has its own monitor. The i-th thread is responsible for signaling
+ // to thread i+1 if the number of buffers in the queue exceeds a threshold for this
+ // thread. Monitors are also used to wake up the threads during termination.
+ // The 0th (primary) worker is notified by mutator threads and has a special monitor.
+ if (!is_primary()) {
+ _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true,
+ Monitor::_safepoint_check_never);
+ } else {
+ _monitor = DirtyCardQ_CBL_mon;
+ }
+
+ // set name
+ set_name("G1 Refine#%d", worker_id);
+ create_and_start();
+}
+
+void G1ConcurrentRefineThread::update_thresholds(size_t activate,
+ size_t deactivate) {
+ assert(deactivate < activate, "precondition");
+ _activation_threshold = activate;
+ _deactivation_threshold = deactivate;
+}
+
+void G1ConcurrentRefineThread::wait_for_completed_buffers() {
+ MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+ while (!should_terminate() && !is_active()) {
+ _monitor->wait(Mutex::_no_safepoint_check_flag);
+ }
+}
+
+bool G1ConcurrentRefineThread::is_active() {
+ DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+ return is_primary() ? dcqs.process_completed_buffers() : _active;
+}
+
+void G1ConcurrentRefineThread::activate() {
+ MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+ if (!is_primary()) {
+ set_active(true);
+ } else {
+ DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+ dcqs.set_process_completed(true);
+ }
+ _monitor->notify();
+}
+
+void G1ConcurrentRefineThread::deactivate() {
+ MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+ if (!is_primary()) {
+ set_active(false);
+ } else {
+ DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+ dcqs.set_process_completed(false);
+ }
+}
+
+void G1ConcurrentRefineThread::run_service() {
+ _vtime_start = os::elapsedVTime();
+
+ while (!should_terminate()) {
+ // Wait for work
+ wait_for_completed_buffers();
+ if (should_terminate()) {
+ break;
+ }
+
+ size_t buffers_processed = 0;
+ DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+ log_debug(gc, refine)("Activated %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT,
+ _worker_id, _activation_threshold, dcqs.completed_buffers_num());
+
+ {
+ SuspendibleThreadSetJoiner sts_join;
+
+ while (!should_terminate()) {
+ if (sts_join.should_yield()) {
+ sts_join.yield();
+ continue; // Re-check for termination after yield delay.
+ }
+
+ size_t curr_buffer_num = dcqs.completed_buffers_num();
+ // If the number of the buffers falls down into the yellow zone,
+ // that means that the transition period after the evacuation pause has ended.
+ if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cr()->yellow_zone()) {
+ dcqs.set_completed_queue_padding(0);
+ }
+
+ // Check if we need to activate the next thread.
+ if ((_next != NULL) &&
+ !_next->is_active() &&
+ (curr_buffer_num > _next->_activation_threshold)) {
+ _next->activate();
+ }
+
+ // Process the next buffer, if there are enough left.
+ if (!dcqs.refine_completed_buffer_concurrently(_worker_id + _worker_id_offset, _deactivation_threshold)) {
+ break; // Deactivate, number of buffers fell below threshold.
+ }
+ ++buffers_processed;
+ }
+ }
+
+ deactivate();
+ log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT
+ ", current: " SIZE_FORMAT ", processed: " SIZE_FORMAT,
+ _worker_id, _deactivation_threshold,
+ dcqs.completed_buffers_num(),
+ buffers_processed);
+
+ if (os::supports_vtime()) {
+ _vtime_accum = (os::elapsedVTime() - _vtime_start);
+ } else {
+ _vtime_accum = 0.0;
+ }
+ }
+
+ log_debug(gc, refine)("Stopping %d", _worker_id);
+}
+
+void G1ConcurrentRefineThread::stop_service() {
+ MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
+ _monitor->notify();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2001, 2017, 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_G1_G1CONCURRENTREFINETHREAD_HPP
+#define SHARE_VM_GC_G1_G1CONCURRENTREFINETHREAD_HPP
+
+#include "gc/g1/dirtyCardQueue.hpp"
+#include "gc/shared/concurrentGCThread.hpp"
+
+// Forward Decl.
+class CardTableEntryClosure;
+class G1ConcurrentRefine;
+
+// One or more G1 Concurrent Refinement Threads may be active if concurrent
+// refinement is in progress.
+class G1ConcurrentRefineThread: public ConcurrentGCThread {
+ friend class VMStructs;
+ friend class G1CollectedHeap;
+
+ double _vtime_start; // Initial virtual time.
+ double _vtime_accum; // Accumulated virtual time.
+ uint _worker_id;
+ uint _worker_id_offset;
+
+ // The refinement threads collection is linked list. A predecessor can activate a successor
+ // when the number of the rset update buffer crosses a certain threshold. A successor
+ // would self-deactivate when the number of the buffers falls below the threshold.
+ bool _active;
+ G1ConcurrentRefineThread* _next;
+ Monitor* _monitor;
+ G1ConcurrentRefine* _cr;
+
+ // This thread's activation/deactivation thresholds
+ size_t _activation_threshold;
+ size_t _deactivation_threshold;
+
+ void wait_for_completed_buffers();
+
+ void set_active(bool x) { _active = x; }
+ bool is_active();
+ void activate();
+ void deactivate();
+
+ bool is_primary() { return (_worker_id == 0); }
+
+ void run_service();
+ void stop_service();
+
+public:
+ // Constructor
+ G1ConcurrentRefineThread(G1ConcurrentRefine* cr, G1ConcurrentRefineThread* next,
+ uint worker_id_offset, uint worker_id,
+ size_t activate, size_t deactivate);
+
+ void update_thresholds(size_t activate, size_t deactivate);
+ size_t activation_threshold() const { return _activation_threshold; }
+
+ // Total virtual time so far.
+ double vtime_accum() { return _vtime_accum; }
+
+ G1ConcurrentRefine* cr() { return _cr; }
+};
+
+#endif // SHARE_VM_GC_G1_G1CONCURRENTREFINETHREAD_HPP
--- a/src/hotspot/share/gc/g1/g1DefaultPolicy.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/g1DefaultPolicy.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,12 +23,12 @@
*/
#include "precompiled.hpp"
-#include "gc/g1/concurrentG1Refine.hpp"
#include "gc/g1/concurrentMarkThread.inline.hpp"
#include "gc/g1/g1Analytics.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1CollectionSet.hpp"
#include "gc/g1/g1ConcurrentMark.hpp"
+#include "gc/g1/g1ConcurrentRefine.hpp"
#include "gc/g1/g1DefaultPolicy.hpp"
#include "gc/g1/g1HotCardCache.hpp"
#include "gc/g1/g1IHOPControl.hpp"
@@ -745,7 +745,7 @@
} else {
update_rs_time_goal_ms -= scan_hcc_time_ms;
}
- _g1->concurrent_g1_refine()->adjust(average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms,
+ _g1->concurrent_refine()->adjust(average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms,
phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS),
update_rs_time_goal_ms);
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -414,7 +414,7 @@
debug_time("Redirty Cards", _recorded_redirty_logged_cards_time_ms);
trace_phase(_gc_par_phases[RedirtyCards]);
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
debug_time("DerivedPointerTable Update", _cur_derived_pointer_table_update_time_ms);
#endif
--- a/src/hotspot/share/gc/g1/g1MMUTracker.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/g1MMUTracker.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, 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
@@ -112,19 +112,7 @@
}
}
-// basically the _internal call does not remove expired entries
-// this is for trying things out in the future and a couple
-// of other places (debugging)
-
double G1MMUTrackerQueue::when_sec(double current_time, double pause_time) {
- MutexLockerEx x(MMUTracker_lock, Mutex::_no_safepoint_check_flag);
- remove_expired_entries(current_time);
-
- return when_internal(current_time, pause_time);
-}
-
-double G1MMUTrackerQueue::when_internal(double current_time,
- double pause_time) {
// if the pause is over the maximum, just assume that it's the maximum
double adjusted_pause_time =
(pause_time > max_gc_time()) ? max_gc_time() : pause_time;
--- a/src/hotspot/share/gc/g1/g1MMUTracker.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/g1MMUTracker.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -134,8 +134,6 @@
void remove_expired_entries(double current_time);
double calculate_gc_time(double current_time);
- double when_internal(double current_time, double pause_time);
-
public:
G1MMUTrackerQueue(double time_slice, double max_gc_time);
--- a/src/hotspot/share/gc/g1/g1MarkSweep.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/g1MarkSweep.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -62,7 +62,7 @@
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
HandleMark hm; // Discard invalid handles created during gc
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
#ifdef ASSERT
@@ -96,7 +96,7 @@
// Prepare compaction.
mark_sweep_phase2();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
// Don't add any more derived pointers during phase3
DerivedPointerTable::set_active(false);
#endif
@@ -111,7 +111,7 @@
BiasedLocking::restore_marks();
GenMarkSweep::deallocate_stacks();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
// Now update the derived pointers.
DerivedPointerTable::update_pointers();
#endif
@@ -204,7 +204,7 @@
if (VerifyDuringGC) {
HandleMark hm; // handle scope
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTableDeactivate dpt_deact;
#endif
g1h->prepare_for_verify();
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,10 +23,10 @@
*/
#include "precompiled.hpp"
-#include "gc/g1/concurrentG1Refine.hpp"
#include "gc/g1/dirtyCardQueue.hpp"
#include "gc/g1/g1BlockOffsetTable.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1ConcurrentRefine.hpp"
#include "gc/g1/g1FromCardCache.hpp"
#include "gc/g1/g1GCPhaseTimes.hpp"
#include "gc/g1/g1HotCardCache.hpp"
@@ -298,7 +298,7 @@
}
uint G1RemSet::num_par_rem_sets() {
- return MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads);
+ return MAX2(DirtyCardQueueSet::num_par_ids() + G1ConcurrentRefine::thread_num(), ParallelGCThreads);
}
void G1RemSet::initialize(size_t capacity, uint max_regions) {
--- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,9 +23,9 @@
*/
#include "precompiled.hpp"
-#include "gc/g1/concurrentG1Refine.hpp"
-#include "gc/g1/concurrentG1RefineThread.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1ConcurrentRefine.hpp"
+#include "gc/g1/g1ConcurrentRefineThread.hpp"
#include "gc/g1/g1RemSet.inline.hpp"
#include "gc/g1/g1RemSetSummary.hpp"
#include "gc/g1/g1YoungRemSetSamplingThread.hpp"
@@ -45,7 +45,7 @@
}
virtual void do_thread(Thread* t) {
- ConcurrentG1RefineThread* crt = (ConcurrentG1RefineThread*) t;
+ G1ConcurrentRefineThread* crt = (G1ConcurrentRefineThread*) t;
_summary->set_rs_thread_vtime(_counter, crt->vtime_accum());
_counter++;
}
@@ -59,12 +59,13 @@
_num_coarsenings = HeapRegionRemSet::n_coarsenings();
- ConcurrentG1Refine * cg1r = G1CollectedHeap::heap()->concurrent_g1_refine();
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+ G1ConcurrentRefine* cg1r = g1h->concurrent_refine();
if (_rs_threads_vtimes != NULL) {
GetRSThreadVTimeClosure p(this);
- cg1r->worker_threads_do(&p);
+ cg1r->threads_do(&p);
}
- set_sampling_thread_vtime(cg1r->sampling_thread()->vtime_accum());
+ set_sampling_thread_vtime(g1h->sampling_thread()->vtime_accum());
}
void G1RemSetSummary::set_rs_thread_vtime(uint thread, double value) {
@@ -85,7 +86,7 @@
_num_processed_buf_mutator(0),
_num_processed_buf_rs_threads(0),
_num_coarsenings(0),
- _num_vtimes(ConcurrentG1Refine::thread_num()),
+ _num_vtimes(G1ConcurrentRefine::thread_num()),
_rs_threads_vtimes(NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC)),
_sampling_thread_vtime(0.0f) {
@@ -98,7 +99,7 @@
_num_processed_buf_mutator(0),
_num_processed_buf_rs_threads(0),
_num_coarsenings(0),
- _num_vtimes(ConcurrentG1Refine::thread_num()),
+ _num_vtimes(G1ConcurrentRefine::thread_num()),
_rs_threads_vtimes(NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC)),
_sampling_thread_vtime(0.0f) {
update();
--- a/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -214,52 +214,3 @@
}
}
}
-
-void G1SATBCardTableModRefBS::write_ref_nmethod_post(oop* dst, nmethod* nm) {
- oop obj = oopDesc::load_heap_oop(dst);
- if (obj != NULL) {
- G1CollectedHeap* g1h = G1CollectedHeap::heap();
- HeapRegion* hr = g1h->heap_region_containing(obj);
- hr->add_strong_code_root(nm);
- }
-}
-
-class G1EnsureLastRefToRegion : public OopClosure {
- G1CollectedHeap* _g1h;
- HeapRegion* _hr;
- oop* _dst;
-
- bool _value;
-public:
- G1EnsureLastRefToRegion(G1CollectedHeap* g1h, HeapRegion* hr, oop* dst) :
- _g1h(g1h), _hr(hr), _dst(dst), _value(true) {}
-
- void do_oop(oop* p) {
- if (_value && p != _dst) {
- oop obj = oopDesc::load_heap_oop(p);
- if (obj != NULL) {
- HeapRegion* hr = _g1h->heap_region_containing(obj);
- if (hr == _hr) {
- // Another reference to the same region.
- _value = false;
- }
- }
- }
- }
- void do_oop(narrowOop* p) { ShouldNotReachHere(); }
- bool value() const { return _value; }
-};
-
-void G1SATBCardTableModRefBS::write_ref_nmethod_pre(oop* dst, nmethod* nm) {
- oop obj = oopDesc::load_heap_oop(dst);
- if (obj != NULL) {
- G1CollectedHeap* g1h = G1CollectedHeap::heap();
- HeapRegion* hr = g1h->heap_region_containing(obj);
- G1EnsureLastRefToRegion ensure_last_ref(g1h, hr, dst);
- nm->oops_do(&ensure_last_ref);
- if (ensure_last_ref.value()) {
- // Last reference to this region, remove the nmethod from the rset.
- hr->remove_strong_code_root(nm);
- }
- }
-}
--- a/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -95,9 +95,6 @@
jbyte val = _byte_map[card_index];
return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
}
- virtual void write_ref_nmethod_pre(oop* dst, nmethod* nm);
- virtual void write_ref_nmethod_post(oop* dst, nmethod* nm);
-
};
template<>
--- a/src/hotspot/share/gc/g1/g1_globals.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/g1_globals.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, 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
@@ -74,10 +74,10 @@
"in milliseconds.") \
range(1.0, DBL_MAX) \
\
- product(intx, G1RefProcDrainInterval, 10, \
+ product(int, G1RefProcDrainInterval, 10, \
"The number of discovered reference objects to process before " \
"draining concurrent marking work queues.") \
- range(1, max_intx) \
+ range(1, INT_MAX) \
\
experimental(double, G1LastPLABAverageOccupancy, 50.0, \
"The expected average occupancy of the last PLAB in " \
--- a/src/hotspot/share/gc/g1/heapRegionManager.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/heapRegionManager.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,8 +23,8 @@
*/
#include "precompiled.hpp"
-#include "gc/g1/concurrentG1Refine.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1ConcurrentRefine.hpp"
#include "gc/g1/heapRegion.hpp"
#include "gc/g1/heapRegionManager.inline.hpp"
#include "gc/g1/heapRegionSet.inline.hpp"
--- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,9 +23,9 @@
*/
#include "precompiled.hpp"
-#include "gc/g1/concurrentG1Refine.hpp"
#include "gc/g1/g1BlockOffsetTable.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1ConcurrentRefine.hpp"
#include "gc/g1/g1CardLiveData.inline.hpp"
#include "gc/g1/heapRegionManager.inline.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
--- a/src/hotspot/share/gc/g1/satbMarkQueue.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/g1/satbMarkQueue.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,12 +23,12 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/satbMarkQueue.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/mutexLocker.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/thread.hpp"
--- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -192,7 +192,7 @@
allocate_stacks();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
@@ -203,7 +203,7 @@
mark_sweep_phase2();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
// Don't add any more derived pointers during phase3
assert(DerivedPointerTable::is_active(), "Sanity");
DerivedPointerTable::set_active(false);
@@ -252,7 +252,7 @@
CodeCache::gc_epilogue();
JvmtiExport::gc_epilogue();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTable::update_pointers();
#endif
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1032,7 +1032,7 @@
CodeCache::gc_epilogue();
JvmtiExport::gc_epilogue();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTable::update_pointers();
#endif
@@ -1783,7 +1783,7 @@
CodeCache::gc_prologue();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
@@ -1799,7 +1799,7 @@
&& GCCause::is_user_requested_gc(gc_cause);
summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc);
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
assert(DerivedPointerTable::is_active(), "Sanity");
DerivedPointerTable::set_active(false);
#endif
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -331,7 +331,7 @@
save_to_space_top_before_gc();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
@@ -601,7 +601,7 @@
assert(young_gen->to_space()->is_empty(), "to space should be empty now");
}
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
DerivedPointerTable::update_pointers();
#endif
--- a/src/hotspot/share/gc/serial/genMarkSweep.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -92,7 +92,7 @@
mark_sweep_phase2();
// Don't add any more derived pointers during phase3
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
assert(DerivedPointerTable::is_active(), "Sanity");
DerivedPointerTable::set_active(false);
#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/serial/serialHeap.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/serial/serialHeap.hpp"
+
+SerialHeap::SerialHeap(GenCollectorPolicy* policy) : GenCollectedHeap(policy) {}
+
+void SerialHeap::check_gen_kinds() {
+ assert(young_gen()->kind() == Generation::DefNew,
+ "Wrong youngest generation type");
+ assert(old_gen()->kind() == Generation::MarkSweepCompact,
+ "Wrong generation kind");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/serial/serialHeap.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017, 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_SERIAL_SERIALHEAP_HPP
+#define SHARE_VM_GC_SERIAL_SERIALHEAP_HPP
+
+#include "gc/shared/genCollectedHeap.hpp"
+
+class GenCollectorPolicy;
+
+class SerialHeap : public GenCollectedHeap {
+protected:
+ virtual void check_gen_kinds();
+
+public:
+ SerialHeap(GenCollectorPolicy* policy);
+
+ virtual Name kind() const {
+ return CollectedHeap::SerialHeap;
+ }
+
+ virtual const char* name() const {
+ return "Serial";
+ }
+
+ // override
+ virtual bool is_in_closed_subset(const void* p) const {
+ return is_in(p);
+ }
+
+ virtual bool card_mark_must_follow_store() const {
+ return false;
+ }
+
+};
+
+#endif // SHARE_VM_GC_CMS_CMSHEAP_HPP
--- a/src/hotspot/share/gc/shared/ageTable.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/ageTable.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "gc/shared/ageTable.inline.hpp"
#include "gc/shared/ageTableTracer.hpp"
#include "gc/shared/collectedHeap.hpp"
@@ -30,7 +31,6 @@
#include "memory/resourceArea.hpp"
#include "logging/log.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "utilities/copy.hpp"
/* Copyright (c) 1992, 2016, Oracle and/or its affiliates, and Stanford University.
--- a/src/hotspot/share/gc/shared/allocTracer.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/allocTracer.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -26,9 +26,11 @@
#include "gc/shared/allocTracer.hpp"
#include "runtime/handles.hpp"
#include "trace/tracing.hpp"
+#include "trace/traceMacros.hpp"
#include "utilities/globalDefinitions.hpp"
-void AllocTracer::send_allocation_outside_tlab_event(Klass* klass, size_t alloc_size) {
+void AllocTracer::send_allocation_outside_tlab(Klass* klass, HeapWord* obj, size_t alloc_size, Thread* thread) {
+ TRACE_ALLOCATION(obj, alloc_size, thread);
EventObjectAllocationOutsideTLAB event;
if (event.should_commit()) {
event.set_objectClass(klass);
@@ -37,7 +39,8 @@
}
}
-void AllocTracer::send_allocation_in_new_tlab_event(Klass* klass, size_t tlab_size, size_t alloc_size) {
+void AllocTracer::send_allocation_in_new_tlab(Klass* klass, HeapWord* obj, size_t tlab_size, size_t alloc_size, Thread* thread) {
+ TRACE_ALLOCATION(obj, tlab_size, thread);
EventObjectAllocationInNewTLAB event;
if (event.should_commit()) {
event.set_objectClass(klass);
--- a/src/hotspot/share/gc/shared/allocTracer.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/allocTracer.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -30,8 +30,8 @@
class AllocTracer : AllStatic {
public:
- static void send_allocation_outside_tlab_event(Klass* klass, size_t alloc_size);
- static void send_allocation_in_new_tlab_event(Klass* klass, size_t tlab_size, size_t alloc_size);
+ static void send_allocation_outside_tlab(Klass* klass, HeapWord* obj, size_t alloc_size, Thread* thread);
+ static void send_allocation_in_new_tlab(Klass* klass, HeapWord* obj, size_t tlab_size, size_t alloc_size, Thread* thread);
static void send_allocation_requiring_gc_event(size_t size, uint gcId);
};
--- a/src/hotspot/share/gc/shared/barrierSet.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/barrierSet.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -120,9 +120,6 @@
static void static_write_ref_array_pre(HeapWord* start, size_t count);
static void static_write_ref_array_post(HeapWord* start, size_t count);
- virtual void write_ref_nmethod_pre(oop* dst, nmethod* nm) {}
- virtual void write_ref_nmethod_post(oop* dst, nmethod* nm) {}
-
protected:
virtual void write_ref_array_work(MemRegion mr) = 0;
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -241,7 +241,7 @@
void CollectedHeap::pre_initialize() {
// Used for ReduceInitialCardMarks (when COMPILER2 is used);
// otherwise remains unused.
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
_defer_initial_card_mark = is_server_compilation_mode_vm() && ReduceInitialCardMarks && can_elide_tlab_store_barriers()
&& (DeferInitialCardMark || card_mark_must_follow_store());
#else
@@ -313,7 +313,7 @@
return NULL;
}
- AllocTracer::send_allocation_in_new_tlab_event(klass, new_tlab_size * HeapWordSize, size * HeapWordSize);
+ AllocTracer::send_allocation_in_new_tlab(klass, obj, new_tlab_size * HeapWordSize, size * HeapWordSize, thread);
if (ZeroTLAB) {
// ..and clear it.
@@ -545,7 +545,7 @@
" to threads list is doomed to failure!");
for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
if (use_tlab) thread->tlab().make_parsable(retire_tlabs);
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
// The deferred store barriers must all have been flushed to the
// card-table (or other remembered set structure) before GC starts
// processing the card-table (or other remembered set).
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -81,9 +81,10 @@
//
// CollectedHeap
// GenCollectedHeap
+// SerialHeap
+// CMSHeap
// G1CollectedHeap
// ParallelScavengeHeap
-// CMSHeap
//
class CollectedHeap : public CHeapObj<mtInternal> {
friend class VMStructs;
@@ -193,7 +194,7 @@
public:
enum Name {
- GenCollectedHeap,
+ SerialHeap,
ParallelScavengeHeap,
G1CollectedHeap,
CMSHeap
--- a/src/hotspot/share/gc/shared/collectedHeap.inline.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/collectedHeap.inline.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -156,7 +156,7 @@
"Unexpected exception, will result in uninitialized storage");
THREAD->incr_allocated_bytes(size * HeapWordSize);
- AllocTracer::send_allocation_outside_tlab_event(klass, size * HeapWordSize);
+ AllocTracer::send_allocation_outside_tlab(klass, result, size * HeapWordSize, THREAD);
return result;
}
--- a/src/hotspot/share/gc/shared/gcId.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/gcId.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,8 +23,8 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "gc/shared/gcId.hpp"
-#include "prims/jvm.h"
#include "runtime/safepoint.hpp"
#include "runtime/thread.inline.hpp"
--- a/src/hotspot/share/gc/shared/gcTimer.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/gcTimer.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -26,7 +26,6 @@
#define SHARE_VM_GC_SHARED_GCTIMER_HPP
#include "memory/allocation.hpp"
-#include "prims/jni_md.h"
#include "utilities/macros.hpp"
#include "utilities/ticks.hpp"
--- a/src/hotspot/share/gc/shared/gcTraceTime.inline.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/gcTraceTime.inline.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -32,7 +32,6 @@
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/universe.hpp"
-#include "prims/jni_md.h"
#include "utilities/ticks.hpp"
#define LOG_STOP_HEAP_FORMAT SIZE_FORMAT "M->" SIZE_FORMAT "M(" SIZE_FORMAT "M)"
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -153,13 +153,6 @@
_gen_policy->initialize_gc_policy_counters();
}
-void GenCollectedHeap::check_gen_kinds() {
- assert(young_gen()->kind() == Generation::DefNew,
- "Wrong youngest generation type");
- assert(old_gen()->kind() == Generation::MarkSweepCompact,
- "Wrong generation kind");
-}
-
void GenCollectedHeap::ref_processing_init() {
_young_gen->ref_processor_init();
_old_gen->ref_processor_init();
@@ -984,7 +977,7 @@
GenCollectedHeap* GenCollectedHeap::heap() {
CollectedHeap* heap = Universe::heap();
assert(heap != NULL, "Uninitialized access to GenCollectedHeap::heap()");
- assert(heap->kind() == CollectedHeap::GenCollectedHeap ||
+ assert(heap->kind() == CollectedHeap::SerialHeap ||
heap->kind() == CollectedHeap::CMSHeap, "Not a GenCollectedHeap");
return (GenCollectedHeap*) heap;
}
@@ -1067,11 +1060,11 @@
};
void GenCollectedHeap::gc_epilogue(bool full) {
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
assert(DerivedPointerTable::is_empty(), "derived pointer present");
size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr()));
guarantee(is_client_compilation_mode_vm() || actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
-#endif /* COMPILER2 || INCLUDE_JVMCI */
+#endif // COMPILER2_OR_JVMCI
resize_all_tlabs();
--- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -83,6 +83,12 @@
bool run_verification, bool clear_soft_refs,
bool restore_marks_for_biased_locking);
+ // Reserve aligned space for the heap as needed by the contained generations.
+ char* allocate(size_t alignment, ReservedSpace* heap_rs);
+
+ // Initialize ("weak") refs processing support
+ void ref_processing_init();
+
protected:
// The set of potentially parallel tasks in root scanning.
@@ -134,31 +140,18 @@
// we absolutely __must__ clear soft refs?
bool must_clear_all_soft_refs();
+ GenCollectedHeap(GenCollectorPolicy *policy);
+
+ virtual void check_gen_kinds() = 0;
+
public:
- GenCollectedHeap(GenCollectorPolicy *policy);
// Returns JNI_OK on success
virtual jint initialize();
- // Reserve aligned space for the heap as needed by the contained generations.
- char* allocate(size_t alignment, ReservedSpace* heap_rs);
-
// Does operations required after initialization has been done.
void post_initialize();
- virtual void check_gen_kinds();
-
- // Initialize ("weak") refs processing support
- virtual void ref_processing_init();
-
- virtual Name kind() const {
- return CollectedHeap::GenCollectedHeap;
- }
-
- virtual const char* name() const {
- return "Serial";
- }
-
Generation* young_gen() const { return _young_gen; }
Generation* old_gen() const { return _old_gen; }
@@ -215,11 +208,6 @@
// assertion checking or verification only.
bool is_in(const void* p) const;
- // override
- virtual bool is_in_closed_subset(const void* p) const {
- return is_in(p);
- }
-
// Returns true if the reference is to an object in the reserved space
// for the young generation.
// Assumes the the young gen address range is less than that of the old gen.
@@ -286,10 +274,6 @@
return true;
}
- virtual bool card_mark_must_follow_store() const {
- return false;
- }
-
// We don't need barriers for stores to objects in the
// young gen and, a fortiori, for initializing stores to
// objects therein. This applies to DefNew+Tenured and ParNew+CMS
--- a/src/hotspot/share/gc/shared/weakProcessor.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/gc/shared/weakProcessor.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -26,10 +26,13 @@
#include "gc/shared/weakProcessor.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/jniHandles.hpp"
+#include "trace/tracing.hpp"
+#include "trace/traceMacros.hpp"
void WeakProcessor::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive) {
JNIHandles::weak_oops_do(is_alive, keep_alive);
JvmtiExport::weak_oops_do(is_alive, keep_alive);
+ TRACE_WEAK_OOPS_DO(is_alive, keep_alive);
}
void WeakProcessor::oops_do(OopClosure* closure) {
--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -87,14 +87,15 @@
// State accessors
void InterpreterRuntime::set_bcp_and_mdp(address bcp, JavaThread *thread) {
- last_frame(thread).interpreter_frame_set_bcp(bcp);
+ LastFrameAccessor last_frame(thread);
+ last_frame.set_bcp(bcp);
if (ProfileInterpreter) {
// ProfileTraps uses MDOs independently of ProfileInterpreter.
// That is why we must check both ProfileInterpreter and mdo != NULL.
- MethodData* mdo = last_frame(thread).interpreter_frame_method()->method_data();
+ MethodData* mdo = last_frame.method()->method_data();
if (mdo != NULL) {
NEEDS_CLEANUP;
- last_frame(thread).interpreter_frame_set_mdp(mdo->bci_to_dp(last_frame(thread).interpreter_frame_bci()));
+ last_frame.set_mdp(mdo->bci_to_dp(last_frame.bci()));
}
}
}
@@ -105,8 +106,9 @@
IRT_ENTRY(void, InterpreterRuntime::ldc(JavaThread* thread, bool wide))
// access constant pool
- ConstantPool* pool = method(thread)->constants();
- int index = wide ? get_index_u2(thread, Bytecodes::_ldc_w) : get_index_u1(thread, Bytecodes::_ldc);
+ LastFrameAccessor last_frame(thread);
+ ConstantPool* pool = last_frame.method()->constants();
+ int index = wide ? last_frame.get_index_u2(Bytecodes::_ldc_w) : last_frame.get_index_u1(Bytecodes::_ldc);
constantTag tag = pool->tag_at(index);
assert (tag.is_unresolved_klass() || tag.is_klass(), "wrong ldc call");
@@ -119,13 +121,14 @@
assert(bytecode == Bytecodes::_fast_aldc ||
bytecode == Bytecodes::_fast_aldc_w, "wrong bc");
ResourceMark rm(thread);
- methodHandle m (thread, method(thread));
- Bytecode_loadconstant ldc(m, bci(thread));
+ LastFrameAccessor last_frame(thread);
+ methodHandle m (thread, last_frame.method());
+ Bytecode_loadconstant ldc(m, last_frame.bci());
oop result = ldc.resolve_constant(CHECK);
#ifdef ASSERT
{
// The bytecode wrappers aren't GC-safe so construct a new one
- Bytecode_loadconstant ldc2(m, bci(thread));
+ Bytecode_loadconstant ldc2(m, last_frame.bci());
oop coop = m->constants()->resolved_references()->obj_at(ldc2.cache_index());
assert(result == coop, "expected result for assembly code");
}
@@ -182,10 +185,11 @@
IRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* thread, jint* first_size_address))
// We may want to pass in more arguments - could make this slightly faster
- ConstantPool* constants = method(thread)->constants();
- int i = get_index_u2(thread, Bytecodes::_multianewarray);
- Klass* klass = constants->klass_at(i, CHECK);
- int nof_dims = number_of_dimensions(thread);
+ LastFrameAccessor last_frame(thread);
+ ConstantPool* constants = last_frame.method()->constants();
+ int i = last_frame.get_index_u2(Bytecodes::_multianewarray);
+ Klass* klass = constants->klass_at(i, CHECK);
+ int nof_dims = last_frame.number_of_dimensions();
assert(klass->is_klass(), "not a class");
assert(nof_dims >= 1, "multianewarray rank must be nonzero");
@@ -217,8 +221,9 @@
// Quicken instance-of and check-cast bytecodes
IRT_ENTRY(void, InterpreterRuntime::quicken_io_cc(JavaThread* thread))
// Force resolving; quicken the bytecode
- int which = get_index_u2(thread, Bytecodes::_checkcast);
- ConstantPool* cpool = method(thread)->constants();
+ LastFrameAccessor last_frame(thread);
+ int which = last_frame.get_index_u2(Bytecodes::_checkcast);
+ ConstantPool* cpool = last_frame.method()->constants();
// We'd expect to assert that we're only here to quicken bytecodes, but in a multithreaded
// program we might have seen an unquick'd bytecode in the interpreter but have another
// thread quicken the bytecode before we get here.
@@ -257,8 +262,9 @@
// If necessary, create an MDO to hold the information, and record it.
void InterpreterRuntime::note_trap(JavaThread* thread, int reason, TRAPS) {
assert(ProfileTraps, "call me only if profiling");
- methodHandle trap_method(thread, method(thread));
- int trap_bci = trap_method->bci_from(bcp(thread));
+ LastFrameAccessor last_frame(thread);
+ methodHandle trap_method(thread, last_frame.method());
+ int trap_bci = trap_method->bci_from(last_frame.bcp());
note_trap_inner(thread, reason, trap_method, trap_bci, THREAD);
}
@@ -391,12 +397,13 @@
// invoke w/o arguments (i.e., as if one were inside the call).
IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThread* thread, oopDesc* exception))
+ LastFrameAccessor last_frame(thread);
Handle h_exception(thread, exception);
- methodHandle h_method (thread, method(thread));
+ methodHandle h_method (thread, last_frame.method());
constantPoolHandle h_constants(thread, h_method->constants());
bool should_repeat;
int handler_bci;
- int current_bci = bci(thread);
+ int current_bci = last_frame.bci();
if (thread->frames_to_pop_failed_realloc() > 0) {
// Allocation of scalar replaced object used in this frame
@@ -493,7 +500,7 @@
// notify JVMTI of an exception throw; JVMTI will detect if this is a first
// time throw or a stack unwinding throw and accordingly notify the debugger
if (JvmtiExport::can_post_on_exceptions()) {
- JvmtiExport::post_exception_throw(thread, h_method(), bcp(thread), h_exception());
+ JvmtiExport::post_exception_throw(thread, h_method(), last_frame.bcp(), h_exception());
}
#ifdef CC_INTERP
@@ -556,20 +563,21 @@
Thread* THREAD = thread;
// resolve field
fieldDescriptor info;
- constantPoolHandle pool(thread, method(thread)->constants());
- methodHandle m(thread, method(thread));
+ LastFrameAccessor last_frame(thread);
+ constantPoolHandle pool(thread, last_frame.method()->constants());
+ methodHandle m(thread, last_frame.method());
bool is_put = (bytecode == Bytecodes::_putfield || bytecode == Bytecodes::_nofast_putfield ||
bytecode == Bytecodes::_putstatic);
bool is_static = (bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic);
{
JvmtiHideSingleStepping jhss(thread);
- LinkResolver::resolve_field_access(info, pool, get_index_u2_cpcache(thread, bytecode),
+ LinkResolver::resolve_field_access(info, pool, last_frame.get_index_u2_cpcache(bytecode),
m, bytecode, CHECK);
} // end JvmtiHideSingleStepping
// check if link resolution caused cpCache to be updated
- ConstantPoolCacheEntry* cp_cache_entry = cache_entry(thread);
+ ConstantPoolCacheEntry* cp_cache_entry = last_frame.cache_entry();
if (cp_cache_entry->is_resolved(bytecode)) return;
// compute auxiliary field attributes
@@ -718,16 +726,17 @@
void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code bytecode) {
Thread* THREAD = thread;
+ LastFrameAccessor last_frame(thread);
// extract receiver from the outgoing argument list if necessary
Handle receiver(thread, NULL);
if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface ||
bytecode == Bytecodes::_invokespecial) {
ResourceMark rm(thread);
- methodHandle m (thread, method(thread));
- Bytecode_invoke call(m, bci(thread));
+ methodHandle m (thread, last_frame.method());
+ Bytecode_invoke call(m, last_frame.bci());
Symbol* signature = call.signature();
- receiver = Handle(thread,
- thread->last_frame().interpreter_callee_receiver(signature));
+ receiver = Handle(thread, last_frame.callee_receiver(signature));
+
assert(Universe::heap()->is_in_reserved_or_null(receiver()),
"sanity check");
assert(receiver.is_null() ||
@@ -737,12 +746,12 @@
// resolve method
CallInfo info;
- constantPoolHandle pool(thread, method(thread)->constants());
+ constantPoolHandle pool(thread, last_frame.method()->constants());
{
JvmtiHideSingleStepping jhss(thread);
LinkResolver::resolve_invoke(info, receiver, pool,
- get_index_u2_cpcache(thread, bytecode), bytecode,
+ last_frame.get_index_u2_cpcache(bytecode), bytecode,
CHECK);
if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
int retry_count = 0;
@@ -754,14 +763,14 @@
"Could not resolve to latest version of redefined method");
// method is redefined in the middle of resolve so re-try.
LinkResolver::resolve_invoke(info, receiver, pool,
- get_index_u2_cpcache(thread, bytecode), bytecode,
+ last_frame.get_index_u2_cpcache(bytecode), bytecode,
CHECK);
}
}
} // end JvmtiHideSingleStepping
// check if link resolution caused cpCache to be updated
- ConstantPoolCacheEntry* cp_cache_entry = cache_entry(thread);
+ ConstantPoolCacheEntry* cp_cache_entry = last_frame.cache_entry();
if (cp_cache_entry->is_resolved(bytecode)) return;
#ifdef ASSERT
@@ -825,33 +834,35 @@
void InterpreterRuntime::resolve_invokehandle(JavaThread* thread) {
Thread* THREAD = thread;
const Bytecodes::Code bytecode = Bytecodes::_invokehandle;
+ LastFrameAccessor last_frame(thread);
// resolve method
CallInfo info;
- constantPoolHandle pool(thread, method(thread)->constants());
+ constantPoolHandle pool(thread, last_frame.method()->constants());
{
JvmtiHideSingleStepping jhss(thread);
LinkResolver::resolve_invoke(info, Handle(), pool,
- get_index_u2_cpcache(thread, bytecode), bytecode,
+ last_frame.get_index_u2_cpcache(bytecode), bytecode,
CHECK);
} // end JvmtiHideSingleStepping
- ConstantPoolCacheEntry* cp_cache_entry = cache_entry(thread);
+ ConstantPoolCacheEntry* cp_cache_entry = last_frame.cache_entry();
cp_cache_entry->set_method_handle(pool, info);
}
// First time execution: Resolve symbols, create a permanent CallSite object.
void InterpreterRuntime::resolve_invokedynamic(JavaThread* thread) {
Thread* THREAD = thread;
+ LastFrameAccessor last_frame(thread);
const Bytecodes::Code bytecode = Bytecodes::_invokedynamic;
//TO DO: consider passing BCI to Java.
- // int caller_bci = method(thread)->bci_from(bcp(thread));
+ // int caller_bci = last_frame.method()->bci_from(last_frame.bcp());
// resolve method
CallInfo info;
- constantPoolHandle pool(thread, method(thread)->constants());
- int index = get_index_u4(thread, bytecode);
+ constantPoolHandle pool(thread, last_frame.method()->constants());
+ int index = last_frame.get_index_u4(bytecode);
{
JvmtiHideSingleStepping jhss(thread);
LinkResolver::resolve_invoke(info, Handle(), pool,
@@ -905,11 +916,19 @@
// nm could have been unloaded so look it up again. It's unsafe
// to examine nm directly since it might have been freed and used
// for something else.
- frame fr = thread->last_frame();
- Method* method = fr.interpreter_frame_method();
- int bci = method->bci_from(fr.interpreter_frame_bcp());
+ LastFrameAccessor last_frame(thread);
+ Method* method = last_frame.method();
+ int bci = method->bci_from(last_frame.bcp());
nm = method->lookup_osr_nmethod_for(bci, CompLevel_none, false);
}
+ if (nm != NULL && thread->is_interp_only_mode()) {
+ // Normally we never get an nm if is_interp_only_mode() is true, because
+ // policy()->event has a check for this and won't compile the method when
+ // true. However, it's possible for is_interp_only_mode() to become true
+ // during the compilation. We don't want to return the nm in that case
+ // because we want to continue to execute interpreted.
+ nm = NULL;
+ }
#ifndef PRODUCT
if (TraceOnStackReplacement) {
if (nm != NULL) {
@@ -927,11 +946,11 @@
// flag, in case this method triggers classloading which will call into Java.
UnlockFlagSaver fs(thread);
- frame fr = thread->last_frame();
- assert(fr.is_interpreted_frame(), "must come from interpreter");
- methodHandle method(thread, fr.interpreter_frame_method());
+ LastFrameAccessor last_frame(thread);
+ assert(last_frame.is_interpreted_frame(), "must come from interpreter");
+ methodHandle method(thread, last_frame.method());
const int branch_bci = branch_bcp != NULL ? method->bci_from(branch_bcp) : InvocationEntryBci;
- const int bci = branch_bcp != NULL ? method->bci_from(fr.interpreter_frame_bcp()) : InvocationEntryBci;
+ const int bci = branch_bcp != NULL ? method->bci_from(last_frame.bcp()) : InvocationEntryBci;
assert(!HAS_PENDING_EXCEPTION, "Should not have any exceptions pending");
nmethod* osr_nm = CompilationPolicy::policy()->event(method, method, branch_bci, bci, CompLevel_none, NULL, thread);
@@ -947,9 +966,9 @@
if (UseBiasedLocking) {
ResourceMark rm;
GrowableArray<Handle>* objects_to_revoke = new GrowableArray<Handle>();
- for( BasicObjectLock *kptr = fr.interpreter_frame_monitor_end();
- kptr < fr.interpreter_frame_monitor_begin();
- kptr = fr.next_monitor_in_interpreter_frame(kptr) ) {
+ for( BasicObjectLock *kptr = last_frame.monitor_end();
+ kptr < last_frame.monitor_begin();
+ kptr = last_frame.next_monitor(kptr) ) {
if( kptr->obj() != NULL ) {
objects_to_revoke->append(Handle(THREAD, kptr->obj()));
}
@@ -974,9 +993,9 @@
UnlockFlagSaver fs(thread);
assert(ProfileInterpreter, "must be profiling interpreter");
- frame fr = thread->last_frame();
- assert(fr.is_interpreted_frame(), "must come from interpreter");
- methodHandle method(thread, fr.interpreter_frame_method());
+ LastFrameAccessor last_frame(thread);
+ assert(last_frame.is_interpreted_frame(), "must come from interpreter");
+ methodHandle method(thread, last_frame.method());
Method::build_interpreter_method_data(method, THREAD);
if (HAS_PENDING_EXCEPTION) {
assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here");
@@ -1021,9 +1040,9 @@
assert(ProfileInterpreter, "must be profiling interpreter");
ResourceMark rm(thread);
HandleMark hm(thread);
- frame fr = thread->last_frame();
- assert(fr.is_interpreted_frame(), "must come from interpreter");
- MethodData* h_mdo = fr.interpreter_frame_method()->method_data();
+ LastFrameAccessor last_frame(thread);
+ assert(last_frame.is_interpreted_frame(), "must come from interpreter");
+ MethodData* h_mdo = last_frame.method()->method_data();
// Grab a lock to ensure atomic access to setting the return bci and
// the displacement. This can block and GC, invalidating all naked oops.
@@ -1031,11 +1050,11 @@
// ProfileData is essentially a wrapper around a derived oop, so we
// need to take the lock before making any ProfileData structures.
- ProfileData* data = h_mdo->data_at(h_mdo->dp_to_di(fr.interpreter_frame_mdp()));
+ ProfileData* data = h_mdo->data_at(h_mdo->dp_to_di(last_frame.mdp()));
guarantee(data != NULL, "profile data must be valid");
RetData* rdata = data->as_RetData();
address new_mdp = rdata->fixup_ret(return_bci, h_mdo);
- fr.interpreter_frame_set_mdp(new_mdp);
+ last_frame.set_mdp(new_mdp);
IRT_END
IRT_ENTRY(MethodCounters*, InterpreterRuntime::build_method_counters(JavaThread* thread, Method* m))
@@ -1060,7 +1079,8 @@
// We are called during regular safepoints and when the VM is
// single stepping. If any thread is marked for single stepping,
// then we may have JVMTI work to do.
- JvmtiExport::at_single_stepping_point(thread, method(thread), bcp(thread));
+ LastFrameAccessor last_frame(thread);
+ JvmtiExport::at_single_stepping_point(thread, last_frame.method(), last_frame.bcp());
}
IRT_END
@@ -1083,7 +1103,8 @@
}
InstanceKlass* cp_entry_f1 = InstanceKlass::cast(cp_entry->f1_as_klass());
jfieldID fid = jfieldIDWorkaround::to_jfieldID(cp_entry_f1, cp_entry->f2_as_index(), is_static);
- JvmtiExport::post_field_access(thread, method(thread), bcp(thread), cp_entry_f1, h_obj, fid);
+ LastFrameAccessor last_frame(thread);
+ JvmtiExport::post_field_access(thread, last_frame.method(), last_frame.bcp(), cp_entry_f1, h_obj, fid);
IRT_END
IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread,
@@ -1138,17 +1159,20 @@
h_obj = Handle(thread, obj);
}
- JvmtiExport::post_raw_field_modification(thread, method(thread), bcp(thread), ik, h_obj,
+ LastFrameAccessor last_frame(thread);
+ JvmtiExport::post_raw_field_modification(thread, last_frame.method(), last_frame.bcp(), ik, h_obj,
fid, sig_type, &fvalue);
IRT_END
IRT_ENTRY(void, InterpreterRuntime::post_method_entry(JavaThread *thread))
- JvmtiExport::post_method_entry(thread, InterpreterRuntime::method(thread), InterpreterRuntime::last_frame(thread));
+ LastFrameAccessor last_frame(thread);
+ JvmtiExport::post_method_entry(thread, last_frame.method(), last_frame.get_frame());
IRT_END
IRT_ENTRY(void, InterpreterRuntime::post_method_exit(JavaThread *thread))
- JvmtiExport::post_method_exit(thread, InterpreterRuntime::method(thread), InterpreterRuntime::last_frame(thread));
+ LastFrameAccessor last_frame(thread);
+ JvmtiExport::post_method_exit(thread, last_frame.method(), last_frame.get_frame());
IRT_END
IRT_LEAF(int, InterpreterRuntime::interpreter_contains(address pc))
@@ -1372,10 +1396,10 @@
ResetNoHandleMark rnm; // In a LEAF entry.
HandleMark hm;
ResourceMark rm;
- frame fr = thread->last_frame();
- assert(fr.is_interpreted_frame(), "");
- jint bci = fr.interpreter_frame_bci();
- methodHandle mh(thread, fr.interpreter_frame_method());
+ LastFrameAccessor last_frame(thread);
+ assert(last_frame.is_interpreted_frame(), "");
+ jint bci = last_frame.bci();
+ methodHandle mh(thread, last_frame.method());
Bytecode_invoke invoke(mh, bci);
ArgumentSizeComputer asc(invoke.signature());
int size_of_arguments = (asc.size() + (invoke.has_receiver() ? 1 : 0)); // receiver
@@ -1421,10 +1445,10 @@
// The generated code still uses call_VM because that will set up the frame pointer for
// bcp and method.
IRT_LEAF(intptr_t, InterpreterRuntime::trace_bytecode(JavaThread* thread, intptr_t preserve_this_value, intptr_t tos, intptr_t tos2))
- const frame f = thread->last_frame();
- assert(f.is_interpreted_frame(), "must be an interpreted frame");
- methodHandle mh(thread, f.interpreter_frame_method());
- BytecodeTracer::trace(mh, f.interpreter_frame_bcp(), tos, tos2);
+ LastFrameAccessor last_frame(thread);
+ assert(last_frame.is_interpreted_frame(), "must be an interpreted frame");
+ methodHandle mh(thread, last_frame.method());
+ BytecodeTracer::trace(mh, last_frame.bcp(), tos, tos2);
return preserve_this_value;
IRT_END
#endif // !PRODUCT
--- a/src/hotspot/share/interpreter/interpreterRuntime.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/interpreter/interpreterRuntime.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -42,29 +42,54 @@
friend class PrintingClosure; // for method and bcp
private:
- // Helper functions to access current interpreter state
- static frame last_frame(JavaThread *thread) { return thread->last_frame(); }
- static Method* method(JavaThread *thread) { return last_frame(thread).interpreter_frame_method(); }
- static address bcp(JavaThread *thread) { return last_frame(thread).interpreter_frame_bcp(); }
- static int bci(JavaThread *thread) { return last_frame(thread).interpreter_frame_bci(); }
- static void set_bcp_and_mdp(address bcp, JavaThread*thread);
- static Bytecodes::Code code(JavaThread *thread) {
+ // Helper class to access current interpreter state
+ class LastFrameAccessor : public StackObj {
+ frame _last_frame;
+ public:
+ LastFrameAccessor(JavaThread* thread) {
+ assert(thread == Thread::current(), "sanity");
+ _last_frame = thread->last_frame();
+ }
+ bool is_interpreted_frame() const { return _last_frame.is_interpreted_frame(); }
+ Method* method() const { return _last_frame.interpreter_frame_method(); }
+ address bcp() const { return _last_frame.interpreter_frame_bcp(); }
+ int bci() const { return _last_frame.interpreter_frame_bci(); }
+ address mdp() const { return _last_frame.interpreter_frame_mdp(); }
+
+ void set_bcp(address bcp) { _last_frame.interpreter_frame_set_bcp(bcp); }
+ void set_mdp(address dp) { _last_frame.interpreter_frame_set_mdp(dp); }
+
// pass method to avoid calling unsafe bcp_to_method (partial fix 4926272)
- return Bytecodes::code_at(method(thread), bcp(thread));
- }
- static Bytecode bytecode(JavaThread *thread) { return Bytecode(method(thread), bcp(thread)); }
- static int get_index_u1(JavaThread *thread, Bytecodes::Code bc)
- { return bytecode(thread).get_index_u1(bc); }
- static int get_index_u2(JavaThread *thread, Bytecodes::Code bc)
- { return bytecode(thread).get_index_u2(bc); }
- static int get_index_u2_cpcache(JavaThread *thread, Bytecodes::Code bc)
- { return bytecode(thread).get_index_u2_cpcache(bc); }
- static int get_index_u4(JavaThread *thread, Bytecodes::Code bc)
- { return bytecode(thread).get_index_u4(bc); }
- static int number_of_dimensions(JavaThread *thread) { return bcp(thread)[3]; }
+ Bytecodes::Code code() const { return Bytecodes::code_at(method(), bcp()); }
+
+ Bytecode bytecode() const { return Bytecode(method(), bcp()); }
+ int get_index_u1(Bytecodes::Code bc) const { return bytecode().get_index_u1(bc); }
+ int get_index_u2(Bytecodes::Code bc) const { return bytecode().get_index_u2(bc); }
+ int get_index_u2_cpcache(Bytecodes::Code bc) const
+ { return bytecode().get_index_u2_cpcache(bc); }
+ int get_index_u4(Bytecodes::Code bc) const { return bytecode().get_index_u4(bc); }
+ int number_of_dimensions() const { return bcp()[3]; }
+ ConstantPoolCacheEntry* cache_entry_at(int i) const
+ { return method()->constants()->cache()->entry_at(i); }
+ ConstantPoolCacheEntry* cache_entry() const { return cache_entry_at(Bytes::get_native_u2(bcp() + 1)); }
- static ConstantPoolCacheEntry* cache_entry_at(JavaThread *thread, int i) { return method(thread)->constants()->cache()->entry_at(i); }
- static ConstantPoolCacheEntry* cache_entry(JavaThread *thread) { return cache_entry_at(thread, Bytes::get_native_u2(bcp(thread) + 1)); }
+ oop callee_receiver(Symbol* signature) {
+ return _last_frame.interpreter_callee_receiver(signature);
+ }
+ BasicObjectLock* monitor_begin() const {
+ return _last_frame.interpreter_frame_monitor_begin();
+ }
+ BasicObjectLock* monitor_end() const {
+ return _last_frame.interpreter_frame_monitor_end();
+ }
+ BasicObjectLock* next_monitor(BasicObjectLock* current) const {
+ return _last_frame.next_monitor_in_interpreter_frame(current);
+ }
+
+ frame& get_frame() { return _last_frame; }
+ };
+
+ static void set_bcp_and_mdp(address bcp, JavaThread*thread);
static void note_trap_inner(JavaThread* thread, int reason,
const methodHandle& trap_method, int trap_bci, TRAPS);
static void note_trap(JavaThread *thread, int reason, TRAPS);
@@ -139,7 +164,7 @@
static void _breakpoint(JavaThread* thread, Method* method, address bcp);
static Bytecodes::Code get_original_bytecode_at(JavaThread* thread, Method* method, address bcp);
static void set_original_bytecode_at(JavaThread* thread, Method* method, address bcp, Bytecodes::Code new_code);
- static bool is_breakpoint(JavaThread *thread) { return Bytecodes::code_or_bp_at(bcp(thread)) == Bytecodes::_breakpoint; }
+ static bool is_breakpoint(JavaThread *thread) { return Bytecodes::code_or_bp_at(LastFrameAccessor(thread).bcp()) == Bytecodes::_breakpoint; }
// Safepoints
static void at_safepoint(JavaThread* thread);
--- a/src/hotspot/share/interpreter/linkResolver.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/interpreter/linkResolver.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/defaultMethods.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/resolutionErrors.hpp"
@@ -42,7 +43,6 @@
#include "oops/method.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "prims/methodHandles.hpp"
#include "prims/nativeLookup.hpp"
#include "runtime/compilationPolicy.hpp"
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -45,7 +45,7 @@
// use).
ConstantOopWriteValue* CodeInstaller::_oop_null_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantOopWriteValue(NULL);
ConstantIntValue* CodeInstaller::_int_m1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(-1);
-ConstantIntValue* CodeInstaller::_int_0_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(0);
+ConstantIntValue* CodeInstaller::_int_0_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue((jint)0);
ConstantIntValue* CodeInstaller::_int_1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(1);
ConstantIntValue* CodeInstaller::_int_2_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(2);
LocationValue* CodeInstaller::_illegal_value = new (ResourceObj::C_HEAP, mtCompiler) LocationValue(Location());
--- a/src/hotspot/share/jvmci/jvmciCompiler.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/jvmci/jvmciCompiler.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,10 +22,10 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/javaCalls.hpp"
#include "runtime/handles.hpp"
#include "jvmci/jvmciJavaClasses.hpp"
--- a/src/hotspot/share/jvmci/jvmciCompiler.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/jvmci/jvmciCompiler.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -55,10 +55,13 @@
public:
JVMCICompiler();
- static JVMCICompiler* instance(TRAPS) {
+ static JVMCICompiler* instance(bool require_non_null, TRAPS) {
if (!EnableJVMCI) {
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVMCI is not enabled")
}
+ if (_instance == NULL && require_non_null) {
+ THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "The JVMCI compiler instance has not been created");
+ }
return _instance;
}
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1000,7 +1000,7 @@
return -1;
C2V_END
-C2V_VMENTRY(void, setNotInlineableOrCompileable,(JNIEnv *, jobject, jobject jvmci_method))
+C2V_VMENTRY(void, setNotInlinableOrCompilable,(JNIEnv *, jobject, jobject jvmci_method))
methodHandle method = CompilerToVM::asMethod(jvmci_method);
method->set_not_c1_compilable();
method->set_not_c2_compilable();
@@ -1018,7 +1018,7 @@
Handle installed_code_handle(THREAD, JNIHandles::resolve(installed_code));
Handle speculation_log_handle(THREAD, JNIHandles::resolve(speculation_log));
- JVMCICompiler* compiler = JVMCICompiler::instance(CHECK_JNI_ERR);
+ JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK_JNI_ERR);
TraceTime install_time("installCode", JVMCICompiler::codeInstallTimer());
bool is_immutable_PIC = HotSpotCompiledCode::isImmutablePIC(compiled_code_handle) > 0;
@@ -1039,7 +1039,7 @@
if (result != JVMCIEnv::ok) {
assert(cb == NULL, "should be");
} else {
- if (!installed_code_handle.is_null()) {
+ if (installed_code_handle.not_null()) {
assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type");
nmethod::invalidate_installed_code(installed_code_handle, CHECK_0);
{
@@ -1058,13 +1058,6 @@
HotSpotInstalledCode::set_codeSize(installed_code_handle, cb->code_size());
}
}
- nmethod* nm = cb->as_nmethod_or_null();
- if (nm != NULL && installed_code_handle->is_scavengable()) {
- assert(nm->detect_scavenge_root_oops(), "nm should be scavengable if installed_code is scavengable");
- if (!UseG1GC) {
- assert(nm->on_scavenge_root_list(), "nm should be on scavengable list");
- }
- }
}
}
return result;
@@ -1143,7 +1136,7 @@
C2V_END
C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv *jniEnv, jobject))
- JVMCICompiler* compiler = JVMCICompiler::instance(CHECK);
+ JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK);
CompilerStatistics* stats = compiler->stats();
stats->_standard.reset();
stats->_osr.reset();
@@ -1697,7 +1690,7 @@
}
while (length > 0) {
jbyte* start = array->byte_at_addr(offset);
- tty->write((char*) start, MIN2(length, O_BUFLEN));
+ tty->write((char*) start, MIN2(length, (jint)O_BUFLEN));
length -= O_BUFLEN;
offset += O_BUFLEN;
}
@@ -1820,7 +1813,7 @@
{CC "getImplementor", CC "(" HS_RESOLVED_KLASS ")" HS_RESOLVED_KLASS, FN_PTR(getImplementor)},
{CC "getStackTraceElement", CC "(" HS_RESOLVED_METHOD "I)" STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)},
{CC "methodIsIgnoredBySecurityStackWalk", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)},
- {CC "setNotInlineableOrCompileable", CC "(" HS_RESOLVED_METHOD ")V", FN_PTR(setNotInlineableOrCompileable)},
+ {CC "setNotInlinableOrCompilable", CC "(" HS_RESOLVED_METHOD ")V", FN_PTR(setNotInlinableOrCompilable)},
{CC "isCompilable", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(isCompilable)},
{CC "hasNeverInlineDirective", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(hasNeverInlineDirective)},
{CC "shouldInlineMethod", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(shouldInlineMethod)},
--- a/src/hotspot/share/jvmci/jvmciEnv.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/jvmci/jvmciEnv.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -521,7 +521,9 @@
debug_info, dependencies, code_buffer,
frame_words, oop_map_set,
handler_table, &implicit_tbl,
- compiler, comp_level, installed_code, speculation_log);
+ compiler, comp_level,
+ JNIHandles::make_weak_global(installed_code),
+ JNIHandles::make_weak_global(speculation_log));
// Free codeBlobs
//code_buffer->free_blob();
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,6 +22,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "asm/codeBuffer.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "code/codeCache.hpp"
@@ -37,7 +38,6 @@
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "oops/objArrayOop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/biasedLocking.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/reflection.hpp"
@@ -611,7 +611,7 @@
}
JRT_END
-JRT_ENTRY(jint, JVMCIRuntime::test_deoptimize_call_int(JavaThread* thread, int value))
+JRT_ENTRY(int, JVMCIRuntime::test_deoptimize_call_int(JavaThread* thread, int value))
deopt_caller();
return value;
JRT_END
@@ -821,28 +821,37 @@
}
CompLevel JVMCIRuntime::adjust_comp_level_inner(const methodHandle& method, bool is_osr, CompLevel level, JavaThread* thread) {
- JVMCICompiler* compiler = JVMCICompiler::instance(thread);
+ JVMCICompiler* compiler = JVMCICompiler::instance(false, thread);
if (compiler != NULL && compiler->is_bootstrapping()) {
return level;
}
- if (!is_HotSpotJVMCIRuntime_initialized() || !_comp_level_adjustment) {
+ if (!is_HotSpotJVMCIRuntime_initialized() || _comp_level_adjustment == JVMCIRuntime::none) {
// JVMCI cannot participate in compilation scheduling until
// JVMCI is initialized and indicates it wants to participate.
return level;
}
#define CHECK_RETURN THREAD); \
-if (HAS_PENDING_EXCEPTION) { \
- Handle exception(THREAD, PENDING_EXCEPTION); \
- CLEAR_PENDING_EXCEPTION; \
-\
- java_lang_Throwable::java_printStackTrace(exception, THREAD); \
if (HAS_PENDING_EXCEPTION) { \
+ Handle exception(THREAD, PENDING_EXCEPTION); \
CLEAR_PENDING_EXCEPTION; \
+ \
+ if (exception->is_a(SystemDictionary::ThreadDeath_klass())) { \
+ /* In the special case of ThreadDeath, we need to reset the */ \
+ /* pending async exception so that it is propagated. */ \
+ thread->set_pending_async_exception(exception()); \
+ return level; \
+ } \
+ tty->print("Uncaught exception while adjusting compilation level: "); \
+ java_lang_Throwable::print(exception(), tty); \
+ tty->cr(); \
+ java_lang_Throwable::print_stack_trace(exception, tty); \
+ if (HAS_PENDING_EXCEPTION) { \
+ CLEAR_PENDING_EXCEPTION; \
+ } \
+ return level; \
} \
- return level; \
-} \
-(void)(0
+ (void)(0
Thread* THREAD = thread;
--- a/src/hotspot/share/jvmci/jvmci_globals.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/jvmci/jvmci_globals.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,8 +23,8 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "jvmci/jvmci_globals.hpp"
-#include "prims/jvm.h"
#include "utilities/defaultStream.hpp"
#include "runtime/globals_extension.hpp"
--- a/src/hotspot/share/logging/logConfiguration.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/logging/logConfiguration.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,6 +22,7 @@
*
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logging/log.hpp"
#include "logging/logConfiguration.hpp"
#include "logging/logDecorations.hpp"
@@ -34,7 +35,6 @@
#include "logging/logTagSet.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "runtime/os.inline.hpp"
#include "runtime/semaphore.hpp"
#include "utilities/globalDefinitions.hpp"
--- a/src/hotspot/share/logging/logDecorations.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/logging/logDecorations.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,9 +22,9 @@
*
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logging/logConfiguration.hpp"
#include "logging/logDecorations.hpp"
-#include "prims/jvm.h"
#include "runtime/os.inline.hpp"
#include "runtime/thread.inline.hpp"
#include "services/management.hpp"
--- a/src/hotspot/share/logging/logFileOutput.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/logging/logFileOutput.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,11 +22,11 @@
*
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logging/log.hpp"
#include "logging/logConfiguration.hpp"
#include "logging/logFileOutput.hpp"
#include "memory/allocation.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/arguments.hpp"
#include "runtime/os.inline.hpp"
#include "utilities/globalDefinitions.hpp"
--- a/src/hotspot/share/logging/logFileStreamOutput.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/logging/logFileStreamOutput.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,12 +22,12 @@
*
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logging/logDecorators.hpp"
#include "logging/logDecorations.hpp"
#include "logging/logFileStreamOutput.hpp"
#include "logging/logMessageBuffer.hpp"
#include "memory/allocation.inline.hpp"
-#include "prims/jvm.h"
static bool initialized;
static union {
--- a/src/hotspot/share/logging/logOutput.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/logging/logOutput.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,11 +22,11 @@
*
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logging/logFileStreamOutput.hpp"
#include "logging/logOutput.hpp"
#include "logging/logTagSet.hpp"
#include "memory/allocation.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.inline.hpp"
--- a/src/hotspot/share/logging/logTagSet.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/logging/logTagSet.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,6 +22,7 @@
*
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logging/logDecorations.hpp"
#include "logging/logFileStreamOutput.hpp"
#include "logging/logLevel.hpp"
@@ -31,7 +32,6 @@
#include "logging/logTagSet.hpp"
#include "logging/logTagSetDescriptions.hpp"
#include "memory/allocation.inline.hpp"
-#include "prims/jvm.h"
#include "utilities/ostream.hpp"
LogTagSet* LogTagSet::_list = NULL;
--- a/src/hotspot/share/memory/filemap.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/memory/filemap.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/classLoader.hpp"
#include "classfile/compactHashtable.inline.hpp"
#include "classfile/sharedClassUtil.hpp"
@@ -42,7 +43,6 @@
#include "memory/metaspaceShared.hpp"
#include "memory/oopFactory.hpp"
#include "oops/objArrayOop.hpp"
-#include "prims/jvm.h"
#include "prims/jvmtiExport.hpp"
#include "runtime/arguments.hpp"
#include "runtime/java.hpp"
--- a/src/hotspot/share/memory/heap.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/memory/heap.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -160,7 +160,18 @@
char* high_boundary() const { return _memory.high_boundary(); }
bool contains(const void* p) const { return low_boundary() <= p && p < high(); }
- bool contains_blob(const CodeBlob* blob) const { return contains(blob->code_begin()); }
+ bool contains_blob(const CodeBlob* blob) const {
+ // AOT CodeBlobs (i.e. AOTCompiledMethod) objects aren't allocated in the AOTCodeHeap but on the C-Heap.
+ // Only the code they are pointing to is located in the AOTCodeHeap. All other CodeBlobs are allocated
+ // directly in their corresponding CodeHeap with their code appended to the actual C++ object.
+ // So all CodeBlobs except AOTCompiledMethod are continuous in memory with their data and code while
+ // AOTCompiledMethod and their code/data is distributed in the C-Heap. This means we can use the
+ // address of a CodeBlob object in order to locate it in its heap while we have to use the address
+ // of the actual code an AOTCompiledMethod object is pointing to in order to locate it.
+ // Notice that for an ordinary CodeBlob with code size zero, code_begin() may point beyond the object!
+ const void* start = AOT_ONLY( (code_blob_type() == CodeBlobType::AOT) ? blob->code_begin() : ) (void*)blob;
+ return contains(start);
+ }
virtual void* find_start(void* p) const; // returns the block containing p or NULL
virtual CodeBlob* find_blob_unsafe(void* start) const;
--- a/src/hotspot/share/memory/metachunk.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/memory/metachunk.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -55,8 +55,8 @@
_container(container)
{
_top = initial_top();
+ set_is_tagged_free(false);
#ifdef ASSERT
- set_is_tagged_free(false);
mangle(uninitMetaWordVal);
#endif
}
--- a/src/hotspot/share/memory/metachunk.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/memory/metachunk.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -102,7 +102,7 @@
// Current allocation top.
MetaWord* _top;
- DEBUG_ONLY(bool _is_tagged_free;)
+ bool _is_tagged_free;
MetaWord* initial_top() const { return (MetaWord*)this + overhead(); }
MetaWord* top() const { return _top; }
@@ -138,10 +138,8 @@
size_t used_word_size() const;
size_t free_word_size() const;
-#ifdef ASSERT
bool is_tagged_free() { return _is_tagged_free; }
void set_is_tagged_free(bool v) { _is_tagged_free = v; }
-#endif
bool contains(const void* ptr) { return bottom() <= ptr && ptr < _top; }
--- a/src/hotspot/share/memory/metaspace.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/memory/metaspace.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -108,6 +108,18 @@
return (ChunkIndex) (i+1);
}
+static const char* scale_unit(size_t scale) {
+ switch(scale) {
+ case 1: return "BYTES";
+ case K: return "KB";
+ case M: return "MB";
+ case G: return "GB";
+ default:
+ ShouldNotReachHere();
+ return NULL;
+ }
+}
+
volatile intptr_t MetaspaceGC::_capacity_until_GC = 0;
uint MetaspaceGC::_shrink_factor = 0;
bool MetaspaceGC::_should_concurrent_collect = false;
@@ -176,7 +188,7 @@
void locked_get_statistics(ChunkManagerStatistics* stat) const;
void get_statistics(ChunkManagerStatistics* stat) const;
- static void print_statistics(const ChunkManagerStatistics* stat, outputStream* out);
+ static void print_statistics(const ChunkManagerStatistics* stat, outputStream* out, size_t scale);
public:
@@ -283,7 +295,7 @@
// Prints composition for both non-class and (if available)
// class chunk manager.
- static void print_all_chunkmanagers(outputStream* out);
+ static void print_all_chunkmanagers(outputStream* out, size_t scale = 1);
};
class SmallBlocks : public CHeapObj<mtClass> {
@@ -480,6 +492,7 @@
#endif
void print_on(outputStream* st) const;
+ void print_map(outputStream* st, bool is_class) const;
};
#define assert_is_aligned(value, alignment) \
@@ -531,6 +544,94 @@
}
}
+void VirtualSpaceNode::print_map(outputStream* st, bool is_class) const {
+
+ // Format:
+ // <ptr>
+ // <ptr> . .. . . ..
+ // SSxSSMMMMMMMMMMMMMMMMsssXX
+ // 112114444444444444444
+ // <ptr> . .. . . ..
+ // SSxSSMMMMMMMMMMMMMMMMsssXX
+ // 112114444444444444444
+
+ if (bottom() == top()) {
+ return;
+ }
+
+ // First line: dividers for every med-chunk-sized interval
+ // Second line: a dot for the start of a chunk
+ // Third line: a letter per chunk type (x,s,m,h), uppercase if in use.
+
+ const size_t spec_chunk_size = is_class ? ClassSpecializedChunk : SpecializedChunk;
+ const size_t small_chunk_size = is_class ? ClassSmallChunk : SmallChunk;
+ const size_t med_chunk_size = is_class ? ClassMediumChunk : MediumChunk;
+
+ int line_len = 100;
+ const size_t section_len = align_up(spec_chunk_size * line_len, med_chunk_size);
+ line_len = (int)(section_len / spec_chunk_size);
+
+ char* line1 = (char*)os::malloc(line_len, mtInternal);
+ char* line2 = (char*)os::malloc(line_len, mtInternal);
+ char* line3 = (char*)os::malloc(line_len, mtInternal);
+ int pos = 0;
+ const MetaWord* p = bottom();
+ const Metachunk* chunk = (const Metachunk*)p;
+ const MetaWord* chunk_end = p + chunk->word_size();
+ while (p < top()) {
+ if (pos == line_len) {
+ pos = 0;
+ st->fill_to(22);
+ st->print_raw(line1, line_len);
+ st->cr();
+ st->fill_to(22);
+ st->print_raw(line2, line_len);
+ st->cr();
+ }
+ if (pos == 0) {
+ st->print(PTR_FORMAT ":", p2i(p));
+ }
+ if (p == chunk_end) {
+ chunk = (Metachunk*)p;
+ chunk_end = p + chunk->word_size();
+ }
+ if (p == (const MetaWord*)chunk) {
+ // chunk starts.
+ line1[pos] = '.';
+ } else {
+ line1[pos] = ' ';
+ }
+ // Line 2: chunk type (x=spec, s=small, m=medium, h=humongous), uppercase if
+ // chunk is in use.
+ const bool chunk_is_free = ((Metachunk*)chunk)->is_tagged_free();
+ if (chunk->word_size() == spec_chunk_size) {
+ line2[pos] = chunk_is_free ? 'x' : 'X';
+ } else if (chunk->word_size() == small_chunk_size) {
+ line2[pos] = chunk_is_free ? 's' : 'S';
+ } else if (chunk->word_size() == med_chunk_size) {
+ line2[pos] = chunk_is_free ? 'm' : 'M';
+ } else if (chunk->word_size() > med_chunk_size) {
+ line2[pos] = chunk_is_free ? 'h' : 'H';
+ } else {
+ ShouldNotReachHere();
+ }
+ p += spec_chunk_size;
+ pos ++;
+ }
+ if (pos > 0) {
+ st->fill_to(22);
+ st->print_raw(line1, pos);
+ st->cr();
+ st->fill_to(22);
+ st->print_raw(line2, pos);
+ st->cr();
+ }
+ os::free(line1);
+ os::free(line2);
+ os::free(line3);
+}
+
+
#ifdef ASSERT
uintx VirtualSpaceNode::container_count_slow() {
uintx count = 0;
@@ -637,6 +738,7 @@
void purge(ChunkManager* chunk_manager);
void print_on(outputStream* st) const;
+ void print_map(outputStream* st) const;
class VirtualSpaceListIterator : public StackObj {
VirtualSpaceNode* _virtual_spaces;
@@ -1449,6 +1551,18 @@
}
}
+void VirtualSpaceList::print_map(outputStream* st) const {
+ VirtualSpaceNode* list = virtual_space_list();
+ VirtualSpaceListIterator iter(list);
+ unsigned i = 0;
+ while (iter.repeat()) {
+ st->print_cr("Node %u:", i);
+ VirtualSpaceNode* node = iter.get_next();
+ node->print_map(st, this->is_class());
+ i ++;
+ }
+}
+
// MetaspaceGC methods
// VM_CollectForMetadataAllocation is the vm operation used to GC.
@@ -1724,7 +1838,6 @@
#endif
// ChunkManager methods
-
size_t ChunkManager::free_chunks_total_words() {
return _free_chunks_total;
}
@@ -1923,11 +2036,10 @@
// Remove it from the links to this freelist
chunk->set_next(NULL);
chunk->set_prev(NULL);
-#ifdef ASSERT
+
// Chunk is no longer on any freelist. Setting to false make container_count_slow()
// work.
chunk->set_is_tagged_free(false);
-#endif
chunk->container()->inc_container_count();
slow_locked_verify();
@@ -1995,7 +2107,7 @@
chunk_size_name(index), p2i(chunk), chunk->word_size());
}
chunk->container()->dec_container_count();
- DEBUG_ONLY(chunk->set_is_tagged_free(true);)
+ chunk->set_is_tagged_free(true);
// Chunk has been added; update counters.
account_for_added_chunk(chunk);
@@ -2057,22 +2169,45 @@
locked_get_statistics(stat);
}
-void ChunkManager::print_statistics(const ChunkManagerStatistics* stat, outputStream* out) {
+void ChunkManager::print_statistics(const ChunkManagerStatistics* stat, outputStream* out, size_t scale) {
size_t total = 0;
+ assert(scale == 1 || scale == K || scale == M || scale == G, "Invalid scale");
+
+ const char* unit = scale_unit(scale);
for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) {
- out->print_cr(" " SIZE_FORMAT " %s (" SIZE_FORMAT " bytes) chunks, total " SIZE_FORMAT " bytes",
- stat->num_by_type[i], chunk_size_name(i),
- stat->single_size_by_type[i],
- stat->total_size_by_type[i]);
+ out->print(" " SIZE_FORMAT " %s (" SIZE_FORMAT " bytes) chunks, total ",
+ stat->num_by_type[i], chunk_size_name(i),
+ stat->single_size_by_type[i]);
+ if (scale == 1) {
+ out->print_cr(SIZE_FORMAT " bytes", stat->total_size_by_type[i]);
+ } else {
+ out->print_cr("%.2f%s", (float)stat->total_size_by_type[i] / scale, unit);
+ }
+
total += stat->total_size_by_type[i];
}
- out->print_cr(" " SIZE_FORMAT " humongous chunks, total " SIZE_FORMAT " bytes",
- stat->num_humongous_chunks, stat->total_size_humongous_chunks);
+
+
total += stat->total_size_humongous_chunks;
- out->print_cr(" total size: " SIZE_FORMAT ".", total);
+
+ if (scale == 1) {
+ out->print_cr(" " SIZE_FORMAT " humongous chunks, total " SIZE_FORMAT " bytes",
+ stat->num_humongous_chunks, stat->total_size_humongous_chunks);
+
+ out->print_cr(" total size: " SIZE_FORMAT " bytes.", total);
+ } else {
+ out->print_cr(" " SIZE_FORMAT " humongous chunks, total %.2f%s",
+ stat->num_humongous_chunks,
+ (float)stat->total_size_humongous_chunks / scale, unit);
+
+ out->print_cr(" total size: %.2f%s.", (float)total / scale, unit);
+ }
+
}
-void ChunkManager::print_all_chunkmanagers(outputStream* out) {
+void ChunkManager::print_all_chunkmanagers(outputStream* out, size_t scale) {
+ assert(scale == 1 || scale == K || scale == M || scale == G, "Invalid scale");
+
// Note: keep lock protection only to retrieving statistics; keep printing
// out of lock protection
ChunkManagerStatistics stat;
@@ -2080,7 +2215,7 @@
const ChunkManager* const non_class_cm = Metaspace::chunk_manager_metadata();
if (non_class_cm != NULL) {
non_class_cm->get_statistics(&stat);
- ChunkManager::print_statistics(&stat, out);
+ ChunkManager::print_statistics(&stat, out, scale);
} else {
out->print_cr("unavailable.");
}
@@ -2088,7 +2223,7 @@
const ChunkManager* const class_cm = Metaspace::chunk_manager_class();
if (class_cm != NULL) {
class_cm->get_statistics(&stat);
- ChunkManager::print_statistics(&stat, out);
+ ChunkManager::print_statistics(&stat, out, scale);
} else {
out->print_cr("unavailable.");
}
@@ -2911,9 +3046,9 @@
size_t free_bytes = free_bytes_slow(mdtype);
size_t used_and_free = used_bytes + free_bytes +
free_chunks_capacity_bytes;
- out->print_cr(" Chunk accounting: used in chunks " SIZE_FORMAT
+ out->print_cr(" Chunk accounting: (used in chunks " SIZE_FORMAT
"K + unused in chunks " SIZE_FORMAT "K + "
- " capacity in free chunks " SIZE_FORMAT "K = " SIZE_FORMAT
+ " capacity in free chunks " SIZE_FORMAT "K) = " SIZE_FORMAT
"K capacity in allocated chunks " SIZE_FORMAT "K",
used_bytes / K,
free_bytes / K,
@@ -2981,6 +3116,194 @@
}
}
+class MetadataStats VALUE_OBJ_CLASS_SPEC {
+private:
+ size_t _capacity;
+ size_t _used;
+ size_t _free;
+ size_t _waste;
+
+public:
+ MetadataStats() : _capacity(0), _used(0), _free(0), _waste(0) { }
+ MetadataStats(size_t capacity, size_t used, size_t free, size_t waste)
+ : _capacity(capacity), _used(used), _free(free), _waste(waste) { }
+
+ void add(const MetadataStats& stats) {
+ _capacity += stats.capacity();
+ _used += stats.used();
+ _free += stats.free();
+ _waste += stats.waste();
+ }
+
+ size_t capacity() const { return _capacity; }
+ size_t used() const { return _used; }
+ size_t free() const { return _free; }
+ size_t waste() const { return _waste; }
+
+ void print_on(outputStream* out, size_t scale) const;
+};
+
+
+void MetadataStats::print_on(outputStream* out, size_t scale) const {
+ const char* unit = scale_unit(scale);
+ out->print_cr("capacity=%10.2f%s used=%10.2f%s free=%10.2f%s waste=%10.2f%s",
+ (float)capacity() / scale, unit,
+ (float)used() / scale, unit,
+ (float)free() / scale, unit,
+ (float)waste() / scale, unit);
+}
+
+class PrintCLDMetaspaceInfoClosure : public CLDClosure {
+private:
+ outputStream* _out;
+ size_t _scale;
+
+ size_t _total_count;
+ MetadataStats _total_metadata;
+ MetadataStats _total_class;
+
+ size_t _total_anon_count;
+ MetadataStats _total_anon_metadata;
+ MetadataStats _total_anon_class;
+
+public:
+ PrintCLDMetaspaceInfoClosure(outputStream* out, size_t scale = K)
+ : _out(out), _scale(scale), _total_count(0), _total_anon_count(0) { }
+
+ ~PrintCLDMetaspaceInfoClosure() {
+ print_summary();
+ }
+
+ void do_cld(ClassLoaderData* cld) {
+ assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
+
+ if (cld->is_unloading()) return;
+ Metaspace* msp = cld->metaspace_or_null();
+ if (msp == NULL) {
+ return;
+ }
+
+ bool anonymous = false;
+ if (cld->is_anonymous()) {
+ _out->print_cr("ClassLoader: for anonymous class");
+ anonymous = true;
+ } else {
+ ResourceMark rm;
+ _out->print_cr("ClassLoader: %s", cld->loader_name());
+ }
+
+ print_metaspace(msp, anonymous);
+ _out->cr();
+ }
+
+private:
+ void print_metaspace(Metaspace* msp, bool anonymous);
+ void print_summary() const;
+};
+
+void PrintCLDMetaspaceInfoClosure::print_metaspace(Metaspace* msp, bool anonymous){
+ assert(msp != NULL, "Sanity");
+ SpaceManager* vsm = msp->vsm();
+ const char* unit = scale_unit(_scale);
+
+ size_t capacity = vsm->sum_capacity_in_chunks_in_use() * BytesPerWord;
+ size_t used = vsm->sum_used_in_chunks_in_use() * BytesPerWord;
+ size_t free = vsm->sum_free_in_chunks_in_use() * BytesPerWord;
+ size_t waste = vsm->sum_waste_in_chunks_in_use() * BytesPerWord;
+
+ _total_count ++;
+ MetadataStats metadata_stats(capacity, used, free, waste);
+ _total_metadata.add(metadata_stats);
+
+ if (anonymous) {
+ _total_anon_count ++;
+ _total_anon_metadata.add(metadata_stats);
+ }
+
+ _out->print(" Metadata ");
+ metadata_stats.print_on(_out, _scale);
+
+ if (Metaspace::using_class_space()) {
+ vsm = msp->class_vsm();
+
+ capacity = vsm->sum_capacity_in_chunks_in_use() * BytesPerWord;
+ used = vsm->sum_used_in_chunks_in_use() * BytesPerWord;
+ free = vsm->sum_free_in_chunks_in_use() * BytesPerWord;
+ waste = vsm->sum_waste_in_chunks_in_use() * BytesPerWord;
+
+ MetadataStats class_stats(capacity, used, free, waste);
+ _total_class.add(class_stats);
+
+ if (anonymous) {
+ _total_anon_class.add(class_stats);
+ }
+
+ _out->print(" Class data ");
+ class_stats.print_on(_out, _scale);
+ }
+}
+
+void PrintCLDMetaspaceInfoClosure::print_summary() const {
+ const char* unit = scale_unit(_scale);
+ _out->cr();
+ _out->print_cr("Summary:");
+
+ MetadataStats total;
+ total.add(_total_metadata);
+ total.add(_total_class);
+
+ _out->print(" Total class loaders=" SIZE_FORMAT_W(6) " ", _total_count);
+ total.print_on(_out, _scale);
+
+ _out->print(" Metadata ");
+ _total_metadata.print_on(_out, _scale);
+
+ if (Metaspace::using_class_space()) {
+ _out->print(" Class data ");
+ _total_class.print_on(_out, _scale);
+ }
+ _out->cr();
+
+ MetadataStats total_anon;
+ total_anon.add(_total_anon_metadata);
+ total_anon.add(_total_anon_class);
+
+ _out->print("For anonymous classes=" SIZE_FORMAT_W(6) " ", _total_anon_count);
+ total_anon.print_on(_out, _scale);
+
+ _out->print(" Metadata ");
+ _total_anon_metadata.print_on(_out, _scale);
+
+ if (Metaspace::using_class_space()) {
+ _out->print(" Class data ");
+ _total_anon_class.print_on(_out, _scale);
+ }
+}
+
+void MetaspaceAux::print_metadata_for_nmt(outputStream* out, size_t scale) {
+ const char* unit = scale_unit(scale);
+ out->print_cr("Metaspaces:");
+ out->print_cr(" Metadata space: reserved=" SIZE_FORMAT_W(10) "%s committed=" SIZE_FORMAT_W(10) "%s",
+ reserved_bytes(Metaspace::NonClassType) / scale, unit,
+ committed_bytes(Metaspace::NonClassType) / scale, unit);
+ if (Metaspace::using_class_space()) {
+ out->print_cr(" Class space: reserved=" SIZE_FORMAT_W(10) "%s committed=" SIZE_FORMAT_W(10) "%s",
+ reserved_bytes(Metaspace::ClassType) / scale, unit,
+ committed_bytes(Metaspace::ClassType) / scale, unit);
+ }
+
+ out->cr();
+ ChunkManager::print_all_chunkmanagers(out, scale);
+
+ out->cr();
+ out->print_cr("Per-classloader metadata:");
+ out->cr();
+
+ PrintCLDMetaspaceInfoClosure cl(out, scale);
+ ClassLoaderDataGraph::cld_do(&cl);
+}
+
+
// Dump global metaspace things from the end of ClassLoaderDataGraph
void MetaspaceAux::dump(outputStream* out) {
out->print_cr("All Metaspace:");
@@ -2989,6 +3312,31 @@
print_waste(out);
}
+// Prints an ASCII representation of the given space.
+void MetaspaceAux::print_metaspace_map(outputStream* out, Metaspace::MetadataType mdtype) {
+ MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
+ const bool for_class = mdtype == Metaspace::ClassType ? true : false;
+ VirtualSpaceList* const vsl = for_class ? Metaspace::class_space_list() : Metaspace::space_list();
+ if (vsl != NULL) {
+ if (for_class) {
+ if (!Metaspace::using_class_space()) {
+ out->print_cr("No Class Space.");
+ return;
+ }
+ out->print_raw("---- Metaspace Map (Class Space) ----");
+ } else {
+ out->print_raw("---- Metaspace Map (Non-Class Space) ----");
+ }
+ // Print legend:
+ out->cr();
+ out->print_cr("Chunk Types (uppercase chunks are in use): x-specialized, s-small, m-medium, h-humongous.");
+ out->cr();
+ VirtualSpaceList* const vsl = for_class ? Metaspace::class_space_list() : Metaspace::space_list();
+ vsl->print_map(out);
+ out->cr();
+ }
+}
+
void MetaspaceAux::verify_free_chunks() {
Metaspace::chunk_manager_metadata()->verify();
if (Metaspace::using_class_space()) {
@@ -3627,6 +3975,7 @@
}
LogStream ls(log.info());
MetaspaceAux::dump(&ls);
+ MetaspaceAux::print_metaspace_map(&ls, mdtype);
ChunkManager::print_all_chunkmanagers(&ls);
}
--- a/src/hotspot/share/memory/metaspace.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/memory/metaspace.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -63,6 +63,7 @@
class MetaWord;
class Mutex;
class outputStream;
+class PrintCLDMetaspaceInfoClosure;
class SpaceManager;
class VirtualSpaceList;
@@ -87,6 +88,7 @@
friend class MetaspaceAux;
friend class MetaspaceShared;
friend class CollectorPolicy;
+ friend class PrintCLDMetaspaceInfoClosure;
public:
enum MetadataType {
@@ -347,6 +349,8 @@
return min_chunk_size_words() * BytesPerWord;
}
+ static void print_metadata_for_nmt(outputStream* out, size_t scale = K);
+
static bool has_chunk_free_list(Metaspace::MetadataType mdtype);
static MetaspaceChunkFreeListSummary chunk_free_list_summary(Metaspace::MetadataType mdtype);
@@ -357,6 +361,10 @@
static void print_class_waste(outputStream* out);
static void print_waste(outputStream* out);
+
+ // Prints an ASCII representation of the given space.
+ static void print_metaspace_map(outputStream* out, Metaspace::MetadataType mdtype);
+
static void dump(outputStream* out);
static void verify_free_chunks();
// Checks that the values returned by allocated_capacity_bytes() and
--- a/src/hotspot/share/memory/metaspaceShared.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/memory/metaspaceShared.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/classListParser.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/dictionary.hpp"
@@ -55,7 +56,6 @@
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
#include "oops/typeArrayKlass.hpp"
-#include "prims/jvm.h"
#include "prims/jvmtiRedefineClasses.hpp"
#include "runtime/timerTrace.hpp"
#include "runtime/os.hpp"
--- a/src/hotspot/share/memory/universe.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/memory/universe.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -32,10 +32,10 @@
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "code/dependencies.hpp"
+#include "gc/serial/serialHeap.hpp"
#include "gc/shared/cardTableModRefBS.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "gc/shared/gcLocker.inline.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/generation.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/space.hpp"
@@ -762,7 +762,7 @@
return Universe::create_heap_with_policy<CMSHeap, ConcurrentMarkSweepPolicy>();
#endif
} else if (UseSerialGC) {
- return Universe::create_heap_with_policy<GenCollectedHeap, MarkSweepPolicy>();
+ return Universe::create_heap_with_policy<SerialHeap, MarkSweepPolicy>();
}
ShouldNotReachHere();
--- a/src/hotspot/share/oops/constantPool.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/oops/constantPool.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/classLoaderData.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/metadataOnStackMark.hpp"
@@ -41,7 +42,6 @@
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/fieldType.hpp"
#include "runtime/init.hpp"
#include "runtime/javaCalls.hpp"
@@ -305,14 +305,9 @@
constantPoolHandle cp(THREAD, this);
for (int index = 1; index < length(); index++) { // Index 0 is unused
- if (tag_at(index).is_string()) {
- Symbol* sym = cp->unresolved_string_at(index);
- // Look up only. Only resolve references to already interned strings.
- oop str = StringTable::lookup(sym);
- if (str != NULL) {
- int cache_index = cp->cp_to_object_index(index);
- cp->string_at_put(index, cache_index, str);
- }
+ if (tag_at(index).is_string() && !cp->is_pseudo_string_at(index)) {
+ int cache_index = cp->cp_to_object_index(index);
+ string_at_impl(cp, index, cache_index, CHECK);
}
}
}
--- a/src/hotspot/share/oops/generateOopMap.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/oops/generateOopMap.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,13 +23,13 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "interpreter/bytecodeStream.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "oops/generateOopMap.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
-#include "prims/jvm.h"
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/relocator.hpp"
@@ -2146,8 +2146,14 @@
// Append method name
char msg_buffer2[512];
jio_snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg_buffer, method()->name()->as_C_string());
- _exception = Exceptions::new_exception(Thread::current(),
- vmSymbols::java_lang_LinkageError(), msg_buffer2);
+ if (Thread::current()->can_call_java()) {
+ _exception = Exceptions::new_exception(Thread::current(),
+ vmSymbols::java_lang_LinkageError(), msg_buffer2);
+ } else {
+ // We cannot instantiate an exception object from a compiler thread.
+ // Exit the VM with a useful error message.
+ fatal("%s", msg_buffer2);
+ }
}
void GenerateOopMap::report_error(const char *format, ...) {
@@ -2159,14 +2165,7 @@
void GenerateOopMap::verify_error(const char *format, ...) {
// We do not distinguish between different types of errors for verification
// errors. Let the verifier give a better message.
- const char *msg = "Illegal class file encountered. Try running with -Xverify:all";
- _got_error = true;
- // Append method name
- char msg_buffer2[512];
- jio_snprintf(msg_buffer2, sizeof(msg_buffer2), "%s in method %s", msg,
- method()->name()->as_C_string());
- _exception = Exceptions::new_exception(Thread::current(),
- vmSymbols::java_lang_LinkageError(), msg_buffer2);
+ report_error("Illegal class file encountered. Try running with -Xverify:all");
}
//
--- a/src/hotspot/share/oops/instanceKlass.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/oops/instanceKlass.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "aot/aotLoader.hpp"
#include "classfile/classFileParser.hpp"
#include "classfile/classFileStream.hpp"
@@ -59,7 +60,6 @@
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
-#include "prims/jvm.h"
#include "prims/jvmtiExport.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
#include "prims/jvmtiThreadState.hpp"
--- a/src/hotspot/share/oops/klassVtable.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/oops/klassVtable.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "gc/shared/gcLocker.hpp"
@@ -36,7 +37,6 @@
#include "oops/method.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "utilities/copy.hpp"
--- a/src/hotspot/share/oops/method.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/oops/method.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -271,7 +271,7 @@
int highest_osr_comp_level() const;
void set_highest_osr_comp_level(int level);
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
// Count of times method was exited via exception while interpreting
void interpreter_throwout_increment(TRAPS) {
MethodCounters* mcs = get_method_counters(CHECK);
@@ -426,7 +426,7 @@
return (mcs == NULL) ? 0 : mcs->interpreter_invocation_count();
}
}
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
int increment_interpreter_invocation_count(TRAPS) {
if (TieredCompilation) ShouldNotReachHere();
MethodCounters* mcs = get_method_counters(CHECK_0);
--- a/src/hotspot/share/oops/methodCounters.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/oops/methodCounters.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -40,7 +40,7 @@
#if INCLUDE_AOT
Method* _method; // Back link to Method
#endif
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
int _interpreter_invocation_count; // Count of times invoked (reused as prev_event_count in tiered)
u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
#endif
@@ -130,7 +130,7 @@
MetaspaceObj::Type type() const { return MethodCountersType; }
void clear_counters();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
int interpreter_invocation_count() {
return _interpreter_invocation_count;
@@ -154,7 +154,7 @@
_interpreter_throwout_count = count;
}
-#else // defined(COMPILER2) || INCLUDE_JVMCI
+#else // COMPILER2_OR_JVMCI
int interpreter_invocation_count() {
return 0;
@@ -170,7 +170,7 @@
assert(count == 0, "count must be 0");
}
-#endif // defined(COMPILER2) || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
#if INCLUDE_JVMTI
u2 number_of_breakpoints() const { return _number_of_breakpoints; }
@@ -213,7 +213,7 @@
return byte_offset_of(MethodCounters, _nmethod_age);
}
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
static ByteSize interpreter_invocation_counter_offset() {
return byte_offset_of(MethodCounters, _interpreter_invocation_count);
@@ -223,14 +223,14 @@
return offset_of(MethodCounters, _interpreter_invocation_count);
}
-#else // defined(COMPILER2) || INCLUDE_JVMCI
+#else // COMPILER2_OR_JVMCI
static ByteSize interpreter_invocation_counter_offset() {
ShouldNotReachHere();
return in_ByteSize(0);
}
-#endif // defined(COMPILER2) || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
static ByteSize invocation_counter_offset() {
return byte_offset_of(MethodCounters, _invocation_counter);
--- a/src/hotspot/share/opto/castnode.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/opto/castnode.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -237,8 +237,8 @@
if (in_type != NULL && this_type != NULL &&
(in_type->_lo != this_type->_lo ||
in_type->_hi != this_type->_hi)) {
- int lo1 = this_type->_lo;
- int hi1 = this_type->_hi;
+ jint lo1 = this_type->_lo;
+ jint hi1 = this_type->_hi;
int w1 = this_type->_widen;
if (lo1 >= 0) {
--- a/src/hotspot/share/opto/loopTransform.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/opto/loopTransform.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -2129,7 +2129,7 @@
// Look for trip_counter + offset vs limit
Node *rc_exp = cmp->in(1);
Node *limit = cmp->in(2);
- jint scale_con= 1; // Assume trip counter not scaled
+ int scale_con= 1; // Assume trip counter not scaled
Node *limit_c = get_ctrl(limit);
if( loop->is_member(get_loop(limit_c) ) ) {
--- a/src/hotspot/share/opto/mulnode.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/opto/mulnode.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -235,13 +235,13 @@
const TypeInt *r1 = t1->is_int();
// Fetch endpoints of all ranges
- int32_t lo0 = r0->_lo;
+ jint lo0 = r0->_lo;
double a = (double)lo0;
- int32_t hi0 = r0->_hi;
+ jint hi0 = r0->_hi;
double b = (double)hi0;
- int32_t lo1 = r1->_lo;
+ jint lo1 = r1->_lo;
double c = (double)lo1;
- int32_t hi1 = r1->_hi;
+ jint hi1 = r1->_hi;
double d = (double)hi1;
// Compute all endpoints & check for overflow
--- a/src/hotspot/share/opto/output.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/opto/output.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -577,10 +577,10 @@
// arbitrary, and are not tied to any machine-level encodings.)
#ifdef _LP64
if( t->base() == Type::DoubleBot || t->base() == Type::DoubleCon ) {
- array->append(new ConstantIntValue(0));
+ array->append(new ConstantIntValue((jint)0));
array->append(new_loc_value( _regalloc, regnum, Location::dbl ));
} else if ( t->base() == Type::Long ) {
- array->append(new ConstantIntValue(0));
+ array->append(new ConstantIntValue((jint)0));
array->append(new_loc_value( _regalloc, regnum, Location::lng ));
} else if ( t->base() == Type::RawPtr ) {
// jsr/ret return address which must be restored into a the full
@@ -663,7 +663,7 @@
case Type::DoubleCon: {
jdouble d = t->is_double_constant()->getd();
#ifdef _LP64
- array->append(new ConstantIntValue(0));
+ array->append(new ConstantIntValue((jint)0));
array->append(new ConstantDoubleValue(d));
#else
// Repack the double as two jints.
@@ -683,7 +683,7 @@
case Type::Long: {
jlong d = t->is_long()->get_con();
#ifdef _LP64
- array->append(new ConstantIntValue(0));
+ array->append(new ConstantIntValue((jint)0));
array->append(new ConstantLongValue(d));
#else
// Repack the long as two jints.
--- a/src/hotspot/share/opto/parse3.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/opto/parse3.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -412,11 +412,11 @@
// The original expression was of this form: new T[length0][length1]...
// It is often the case that the lengths are small (except the last).
// If that happens, use the fast 1-d creator a constant number of times.
- const jint expand_limit = MIN2((jint)MultiArrayExpandLimit, 100);
- jint expand_count = 1; // count of allocations in the expansion
- jint expand_fanout = 1; // running total fanout
+ const int expand_limit = MIN2((int)MultiArrayExpandLimit, 100);
+ int expand_count = 1; // count of allocations in the expansion
+ int expand_fanout = 1; // running total fanout
for (j = 0; j < ndimensions-1; j++) {
- jint dim_con = find_int_con(length[j], -1);
+ int dim_con = find_int_con(length[j], -1);
expand_fanout *= dim_con;
expand_count += expand_fanout; // count the level-J sub-arrays
if (dim_con <= 0
--- a/src/hotspot/share/opto/phaseX.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/opto/phaseX.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -723,7 +723,7 @@
//------------------------------intcon-----------------------------------------
// Fast integer constant. Same as "transform(new ConINode(TypeInt::make(i)))"
-ConINode* PhaseTransform::intcon(int i) {
+ConINode* PhaseTransform::intcon(jint i) {
// Small integer? Check cache! Check that cached node is not dead
if (i >= _icon_min && i <= _icon_max) {
ConINode* icon = _icons[i-_icon_min];
--- a/src/hotspot/share/opto/split_if.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/opto/split_if.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -116,9 +116,23 @@
assert( bol->is_Bool(), "" );
if (bol->outcnt() == 1) {
Node* use = bol->unique_out();
- Node *use_c = use->is_If() ? use->in(0) : get_ctrl(use);
- if (use_c == blk1 || use_c == blk2) {
- continue;
+ if (use->Opcode() == Op_Opaque4) {
+ if (use->outcnt() == 1) {
+ Node* iff = use->unique_out();
+ assert(iff->is_If(), "unexpected node type");
+ Node *use_c = iff->in(0);
+ if (use_c == blk1 || use_c == blk2) {
+ continue;
+ }
+ }
+ } else {
+ // We might see an Opaque1 from a loop limit check here
+ assert(use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1, "unexpected node type");
+ Node *use_c = use->is_If() ? use->in(0) : get_ctrl(use);
+ if (use_c == blk1 || use_c == blk2) {
+ assert(use->is_CMove(), "unexpected node type");
+ continue;
+ }
}
}
if (get_ctrl(bol) == blk1 || get_ctrl(bol) == blk2) {
@@ -129,17 +143,40 @@
bol->dump();
}
#endif
- for (DUIterator_Last jmin, j = bol->last_outs(jmin); j >= jmin; --j) {
- // Uses are either IfNodes or CMoves
- Node* iff = bol->last_out(j);
- assert( iff->in(1) == bol, "" );
- // Get control block of either the CMove or the If input
- Node *iff_ctrl = iff->is_If() ? iff->in(0) : get_ctrl(iff);
- Node *x = bol->clone();
- register_new_node(x, iff_ctrl);
- _igvn.replace_input_of(iff, 1, x);
+ for (DUIterator j = bol->outs(); bol->has_out(j); j++) {
+ Node* u = bol->out(j);
+ // Uses are either IfNodes, CMoves or Opaque4
+ if (u->Opcode() == Op_Opaque4) {
+ assert(u->in(1) == bol, "bad input");
+ for (DUIterator_Last kmin, k = u->last_outs(kmin); k >= kmin; --k) {
+ Node* iff = u->last_out(k);
+ assert(iff->is_If() || iff->is_CMove(), "unexpected node type");
+ assert( iff->in(1) == u, "" );
+ // Get control block of either the CMove or the If input
+ Node *iff_ctrl = iff->is_If() ? iff->in(0) : get_ctrl(iff);
+ Node *x1 = bol->clone();
+ Node *x2 = u->clone();
+ register_new_node(x1, iff_ctrl);
+ register_new_node(x2, iff_ctrl);
+ _igvn.replace_input_of(x2, 1, x1);
+ _igvn.replace_input_of(iff, 1, x2);
+ }
+ _igvn.remove_dead_node(u);
+ --j;
+ } else {
+ // We might see an Opaque1 from a loop limit check here
+ assert(u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1, "unexpected node type");
+ assert(u->in(1) == bol, "");
+ // Get control block of either the CMove or the If input
+ Node *u_ctrl = u->is_If() ? u->in(0) : get_ctrl(u);
+ assert(u_ctrl != blk1 && u_ctrl != blk2, "won't converge");
+ Node *x = bol->clone();
+ register_new_node(x, u_ctrl);
+ _igvn.replace_input_of(u, 1, x);
+ --j;
+ }
}
- _igvn.remove_dead_node( bol );
+ _igvn.remove_dead_node(bol);
--i;
}
}
--- a/src/hotspot/share/opto/superword.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/opto/superword.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -2168,10 +2168,12 @@
CountedLoopNode *cl = lpt()->_head->as_CountedLoop();
Compile* C = _phase->C;
if (_packset.length() == 0) {
- // Instigate more unrolling for optimization when vectorization fails.
- C->set_major_progress();
- cl->set_notpassed_slp();
- cl->mark_do_unroll_only();
+ if (cl->is_main_loop()) {
+ // Instigate more unrolling for optimization when vectorization fails.
+ C->set_major_progress();
+ cl->set_notpassed_slp();
+ cl->mark_do_unroll_only();
+ }
return;
}
@@ -2417,6 +2419,9 @@
}//for (int i = 0; i < _block.length(); i++)
C->set_max_vector_size(max_vlen_in_bytes);
+ if (max_vlen_in_bytes > 0) {
+ cl->mark_loop_vectorized();
+ }
if (SuperWordLoopUnrollAnalysis) {
if (cl->has_passed_slp()) {
@@ -2439,7 +2444,6 @@
}
if (do_reserve_copy()) {
- cl->mark_loop_vectorized();
if (can_process_post_loop) {
// Now create the difference of trip and limit and use it as our mask index.
// Note: We limited the unroll of the vectorized loop so that
--- a/src/hotspot/share/opto/type.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/opto/type.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1503,7 +1503,7 @@
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
int TypeInt::hash(void) const {
- return java_add(java_add(_lo, _hi), java_add(_widen, (int)Type::Int));
+ return java_add(java_add(_lo, _hi), java_add((jint)_widen, (jint)Type::Int));
}
//------------------------------is_finite--------------------------------------
@@ -2505,7 +2505,7 @@
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
int TypePtr::hash(void) const {
- return java_add(java_add(_ptr, _offset), java_add( hash_speculative(), _inline_depth));
+ return java_add(java_add((jint)_ptr, (jint)_offset), java_add((jint)hash_speculative(), (jint)_inline_depth));
;
}
@@ -3338,8 +3338,8 @@
// Type-specific hashing function.
int TypeOopPtr::hash(void) const {
return
- java_add(java_add(const_oop() ? const_oop()->hash() : 0, _klass_is_exact),
- java_add(_instance_id, TypePtr::hash()));
+ java_add(java_add((jint)(const_oop() ? const_oop()->hash() : 0), (jint)_klass_is_exact),
+ java_add((jint)_instance_id, (jint)TypePtr::hash()));
}
//------------------------------dump2------------------------------------------
@@ -3946,7 +3946,7 @@
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
int TypeInstPtr::hash(void) const {
- int hash = java_add(klass()->hash(), TypeOopPtr::hash());
+ int hash = java_add((jint)klass()->hash(), (jint)TypeOopPtr::hash());
return hash;
}
@@ -4871,7 +4871,7 @@
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
int TypeKlassPtr::hash(void) const {
- return java_add(klass()->hash(), TypePtr::hash());
+ return java_add((jint)klass()->hash(), (jint)TypePtr::hash());
}
//------------------------------singleton--------------------------------------
--- a/src/hotspot/share/precompiled/precompiled.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/precompiled/precompiled.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -27,6 +27,7 @@
#ifndef DONT_USE_PRECOMPILED_HEADER
# include "jni.h"
+# include "jvm.h"
# include "asm/assembler.hpp"
# include "asm/assembler.inline.hpp"
# include "asm/codeBuffer.hpp"
@@ -160,7 +161,6 @@
# include "oops/symbol.hpp"
# include "oops/typeArrayKlass.hpp"
# include "oops/typeArrayOop.hpp"
-# include "prims/jvm.h"
# include "prims/jvmtiExport.hpp"
# include "prims/methodHandles.hpp"
# include "runtime/arguments.hpp"
--- a/src/hotspot/share/prims/jni.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/prims/jni.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "jni.h"
+#include "jvm.h"
#include "ci/ciReplay.hpp"
#include "classfile/altHashing.hpp"
#include "classfile/classFileStream.hpp"
@@ -55,7 +56,6 @@
#include "prims/jniCheck.hpp"
#include "prims/jniExport.hpp"
#include "prims/jniFastGetField.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/jvmtiThreadState.hpp"
@@ -263,7 +263,7 @@
#ifdef ASSERT
Histogram* JNIHistogram;
- static volatile jint JNIHistogram_lock = 0;
+ static volatile int JNIHistogram_lock = 0;
class JNIHistogramElement : public HistogramElement {
public:
@@ -3277,9 +3277,9 @@
// Initialization state for three routines below relating to
// java.nio.DirectBuffers
-static jint directBufferSupportInitializeStarted = 0;
-static volatile jint directBufferSupportInitializeEnded = 0;
-static volatile jint directBufferSupportInitializeFailed = 0;
+static int directBufferSupportInitializeStarted = 0;
+static volatile int directBufferSupportInitializeEnded = 0;
+static volatile int directBufferSupportInitializeFailed = 0;
static jclass bufferClass = NULL;
static jclass directBufferClass = NULL;
static jclass directByteBufferClass = NULL;
@@ -3844,9 +3844,9 @@
extern const struct JNIInvokeInterface_ jni_InvokeInterface;
// Global invocation API vars
-volatile jint vm_created = 0;
+volatile int vm_created = 0;
// Indicate whether it is safe to recreate VM
-volatile jint safe_to_recreate_vm = 1;
+volatile int safe_to_recreate_vm = 1;
struct JavaVM_ main_vm = {&jni_InvokeInterface};
@@ -3949,7 +3949,7 @@
// JVMCI is initialized on a CompilerThread
if (BootstrapJVMCI) {
JavaThread* THREAD = thread;
- JVMCICompiler* compiler = JVMCICompiler::instance(CATCH);
+ JVMCICompiler* compiler = JVMCICompiler::instance(true, CATCH);
compiler->bootstrap(THREAD);
if (HAS_PENDING_EXCEPTION) {
HandleMark hm;
@@ -4045,7 +4045,7 @@
HOTSPOT_JNI_GETCREATEDJAVAVMS_ENTRY((void **) vm_buf, bufLen, (uintptr_t *) numVMs);
- if (vm_created) {
+ if (vm_created == 1) {
if (numVMs != NULL) *numVMs = 1;
if (bufLen > 0) *vm_buf = (JavaVM *)(&main_vm);
} else {
@@ -4065,7 +4065,7 @@
jint res = JNI_ERR;
DT_RETURN_MARK(DestroyJavaVM, jint, (const jint&)res);
- if (!vm_created) {
+ if (vm_created == 0) {
res = JNI_ERR;
return res;
}
@@ -4086,7 +4086,7 @@
ThreadStateTransition::transition_from_native(thread, _thread_in_vm);
if (Threads::destroy_vm()) {
// Should not change thread state, VM is gone
- vm_created = false;
+ vm_created = 0;
res = JNI_OK;
return res;
} else {
@@ -4226,7 +4226,7 @@
jint JNICALL jni_AttachCurrentThread(JavaVM *vm, void **penv, void *_args) {
HOTSPOT_JNI_ATTACHCURRENTTHREAD_ENTRY(vm, penv, _args);
- if (!vm_created) {
+ if (vm_created == 0) {
HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN((uint32_t) JNI_ERR);
return JNI_ERR;
}
@@ -4285,7 +4285,7 @@
jint ret = JNI_ERR;
DT_RETURN_MARK(GetEnv, jint, (const jint&)ret);
- if (!vm_created) {
+ if (vm_created == 0) {
*penv = NULL;
ret = JNI_EDETACHED;
return ret;
@@ -4336,7 +4336,7 @@
jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *_args) {
HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_ENTRY(vm, penv, _args);
- if (!vm_created) {
+ if (vm_created == 0) {
HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN((uint32_t) JNI_ERR);
return JNI_ERR;
}
--- a/src/hotspot/share/prims/jniCheck.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/prims/jniCheck.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "jni.h"
+#include "jvm.h"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
@@ -32,7 +33,6 @@
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "prims/jniCheck.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "runtime/fieldDescriptor.hpp"
#include "runtime/handles.hpp"
--- a/src/hotspot/share/prims/jni_md.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 1997, 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.
- */
-
-#include "utilities/macros.hpp"
-
-/* Switch to the correct jni_md.h file without reliance on -I options. */
-#include CPU_HEADER_H(jni)
-
-/*
- The local copies of JNI header files may be refreshed
- from a JDK distribution by means of these commands:
-
- cp ${JDK_DIST}/solaris/include/solaris/jni_md.h ./jni_sparc.h
- cp ${JDK_DIST}/win32/include/win32/jni_md.h ./jni_i486.h
- cp ${JDK_DIST}/win32/include/jni.h ./jni.h
-
-*/
--- a/src/hotspot/share/prims/jvm.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/prims/jvm.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.inline.hpp"
@@ -46,7 +47,6 @@
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/jvmtiThreadState.hpp"
@@ -215,7 +215,7 @@
#ifdef ASSERT
Histogram* JVMHistogram;
- volatile jint JVMHistogram_lock = 0;
+ volatile int JVMHistogram_lock = 0;
class JVMHistogramElement : public HistogramElement {
public:
@@ -3766,7 +3766,7 @@
// when we add a new capability in the jvm_version_info struct, we should also
// consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat
// counter defined in runtimeService.cpp.
- info->is_attachable = AttachListener::is_attach_supported();
+ info->is_attach_supported = AttachListener::is_attach_supported();
}
JVM_END
--- a/src/hotspot/share/prims/jvm.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1373 +0,0 @@
-/*
- * Copyright (c) 1997, 2017, 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_JVM_H
-#define SHARE_VM_PRIMS_JVM_H
-
-#include "jni.h"
-#include "utilities/macros.hpp"
-
-#include OS_HEADER_H(jvm)
-
-#ifndef _JAVASOFT_JVM_H_
-#define _JAVASOFT_JVM_H_
-
-// HotSpot integration note:
-//
-// This file and jvm.h used with the JDK are identical,
-// except for the three includes removed below
-
-// #include <sys/stat.h>
-// #include "jni.h"
-// #include "jvm_md.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * This file contains additional functions exported from the VM.
- * These functions are complementary to the standard JNI support.
- * There are three parts to this file:
- *
- * First, this file contains the VM-related functions needed by native
- * libraries in the standard Java API. For example, the java.lang.Object
- * class needs VM-level functions that wait for and notify monitors.
- *
- * Second, this file contains the functions and constant definitions
- * needed by the byte code verifier and class file format checker.
- * These functions allow the verifier and format checker to be written
- * in a VM-independent way.
- *
- * Third, this file contains various I/O and nerwork operations needed
- * by the standard Java I/O and network APIs.
- */
-
-/*
- * Bump the version number when either of the following happens:
- *
- * 1. There is a change in JVM_* functions.
- *
- * 2. There is a change in the contract between VM and Java classes.
- * For example, if the VM relies on a new private field in Thread
- * class.
- */
-
-#define JVM_INTERFACE_VERSION 5
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetMethodParameters(JNIEnv *env, jobject method);
-
-JNIEXPORT jint JNICALL
-JVM_GetInterfaceVersion(void);
-
-/*************************************************************************
- PART 1: Functions for Native Libraries
- ************************************************************************/
-/*
- * java.lang.Object
- */
-JNIEXPORT jint JNICALL
-JVM_IHashCode(JNIEnv *env, jobject obj);
-
-JNIEXPORT void JNICALL
-JVM_MonitorWait(JNIEnv *env, jobject obj, jlong ms);
-
-JNIEXPORT void JNICALL
-JVM_MonitorNotify(JNIEnv *env, jobject obj);
-
-JNIEXPORT void JNICALL
-JVM_MonitorNotifyAll(JNIEnv *env, jobject obj);
-
-JNIEXPORT jobject JNICALL
-JVM_Clone(JNIEnv *env, jobject obj);
-
-/*
- * java.lang.String
- */
-JNIEXPORT jstring JNICALL
-JVM_InternString(JNIEnv *env, jstring str);
-
-/*
- * java.lang.System
- */
-JNIEXPORT jlong JNICALL
-JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored);
-
-JNIEXPORT jlong JNICALL
-JVM_NanoTime(JNIEnv *env, jclass ignored);
-
-JNIEXPORT jlong JNICALL
-JVM_GetNanoTimeAdjustment(JNIEnv *env, jclass ignored, jlong offset_secs);
-
-JNIEXPORT void JNICALL
-JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,
- jobject dst, jint dst_pos, jint length);
-
-JNIEXPORT jobject JNICALL
-JVM_InitProperties(JNIEnv *env, jobject p);
-
-/*
- * java.lang.Runtime
- */
-
-JNIEXPORT void JNICALL
-JVM_Halt(jint code);
-
-JNIEXPORT void JNICALL
-JVM_GC(void);
-
-/* Returns the number of real-time milliseconds that have elapsed since the
- * least-recently-inspected heap object was last inspected by the garbage
- * collector.
- *
- * For simple stop-the-world collectors this value is just the time
- * since the most recent collection. For generational collectors it is the
- * time since the oldest generation was most recently collected. Other
- * collectors are free to return a pessimistic estimate of the elapsed time, or
- * simply the time since the last full collection was performed.
- *
- * Note that in the presence of reference objects, a given object that is no
- * longer strongly reachable may have to be inspected multiple times before it
- * can be reclaimed.
- */
-JNIEXPORT jlong JNICALL
-JVM_MaxObjectInspectionAge(void);
-
-JNIEXPORT jlong JNICALL
-JVM_TotalMemory(void);
-
-JNIEXPORT jlong JNICALL
-JVM_FreeMemory(void);
-
-JNIEXPORT jlong JNICALL
-JVM_MaxMemory(void);
-
-JNIEXPORT jint JNICALL
-JVM_ActiveProcessorCount(void);
-
-JNIEXPORT void * JNICALL
-JVM_LoadLibrary(const char *name);
-
-JNIEXPORT void JNICALL
-JVM_UnloadLibrary(void * handle);
-
-JNIEXPORT void * JNICALL
-JVM_FindLibraryEntry(void *handle, const char *name);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsSupportedJNIVersion(jint version);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetVmArguments(JNIEnv *env);
-
-/*
- * java.lang.Throwable
- */
-JNIEXPORT void JNICALL
-JVM_FillInStackTrace(JNIEnv *env, jobject throwable);
-
-/*
- * java.lang.StackTraceElement
- */
-JNIEXPORT void JNICALL
-JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throwable);
-
-JNIEXPORT void JNICALL
-JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo);
-
-/*
- * java.lang.StackWalker
- */
-enum {
- JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x02,
- JVM_STACKWALK_GET_CALLER_CLASS = 0x04,
- JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20,
- JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100
-};
-
-JNIEXPORT jobject JNICALL
-JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
- jint skip_frames, jint frame_count, jint start_index,
- jobjectArray frames);
-
-JNIEXPORT jint JNICALL
-JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,
- jint frame_count, jint start_index,
- jobjectArray frames);
-
-/*
- * java.lang.Thread
- */
-JNIEXPORT void JNICALL
-JVM_StartThread(JNIEnv *env, jobject thread);
-
-JNIEXPORT void JNICALL
-JVM_StopThread(JNIEnv *env, jobject thread, jobject exception);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsThreadAlive(JNIEnv *env, jobject thread);
-
-JNIEXPORT void JNICALL
-JVM_SuspendThread(JNIEnv *env, jobject thread);
-
-JNIEXPORT void JNICALL
-JVM_ResumeThread(JNIEnv *env, jobject thread);
-
-JNIEXPORT void JNICALL
-JVM_SetThreadPriority(JNIEnv *env, jobject thread, jint prio);
-
-JNIEXPORT void JNICALL
-JVM_Yield(JNIEnv *env, jclass threadClass);
-
-JNIEXPORT void JNICALL
-JVM_Sleep(JNIEnv *env, jclass threadClass, jlong millis);
-
-JNIEXPORT jobject JNICALL
-JVM_CurrentThread(JNIEnv *env, jclass threadClass);
-
-JNIEXPORT jint JNICALL
-JVM_CountStackFrames(JNIEnv *env, jobject thread);
-
-JNIEXPORT void JNICALL
-JVM_Interrupt(JNIEnv *env, jobject thread);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsInterrupted(JNIEnv *env, jobject thread, jboolean clearInterrupted);
-
-JNIEXPORT jboolean JNICALL
-JVM_HoldsLock(JNIEnv *env, jclass threadClass, jobject obj);
-
-JNIEXPORT void JNICALL
-JVM_DumpAllStacks(JNIEnv *env, jclass unused);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetAllThreads(JNIEnv *env, jclass dummy);
-
-JNIEXPORT void JNICALL
-JVM_SetNativeThreadName(JNIEnv *env, jobject jthread, jstring name);
-
-/* getStackTrace() and getAllStackTraces() method */
-JNIEXPORT jobjectArray JNICALL
-JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads);
-
-/*
- * java.lang.SecurityManager
- */
-JNIEXPORT jclass JNICALL
-JVM_CurrentLoadedClass(JNIEnv *env);
-
-JNIEXPORT jobject JNICALL
-JVM_CurrentClassLoader(JNIEnv *env);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetClassContext(JNIEnv *env);
-
-JNIEXPORT jint JNICALL
-JVM_ClassDepth(JNIEnv *env, jstring name);
-
-JNIEXPORT jint JNICALL
-JVM_ClassLoaderDepth(JNIEnv *env);
-
-/*
- * java.lang.Package
- */
-JNIEXPORT jstring JNICALL
-JVM_GetSystemPackage(JNIEnv *env, jstring name);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetSystemPackages(JNIEnv *env);
-
-/*
- * java.lang.ref.Reference
- */
-JNIEXPORT jobject JNICALL
-JVM_GetAndClearReferencePendingList(JNIEnv *env);
-
-JNIEXPORT jboolean JNICALL
-JVM_HasReferencePendingList(JNIEnv *env);
-
-JNIEXPORT void JNICALL
-JVM_WaitForReferencePendingList(JNIEnv *env);
-
-/*
- * java.io.ObjectInputStream
- */
-JNIEXPORT jobject JNICALL
-JVM_LatestUserDefinedLoader(JNIEnv *env);
-
-/*
- * java.lang.reflect.Array
- */
-JNIEXPORT jint JNICALL
-JVM_GetArrayLength(JNIEnv *env, jobject arr);
-
-JNIEXPORT jobject JNICALL
-JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index);
-
-JNIEXPORT jvalue JNICALL
-JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode);
-
-JNIEXPORT void JNICALL
-JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val);
-
-JNIEXPORT void JNICALL
-JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v,
- unsigned char vCode);
-
-JNIEXPORT jobject JNICALL
-JVM_NewArray(JNIEnv *env, jclass eltClass, jint length);
-
-JNIEXPORT jobject JNICALL
-JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim);
-
-/*
- * java.lang.Class and java.lang.ClassLoader
- */
-
-#define JVM_CALLER_DEPTH -1
-
-/*
- * Returns the class in which the code invoking the native method
- * belongs.
- *
- * Note that in JDK 1.1, native methods did not create a frame.
- * In 1.2, they do. Therefore native methods like Class.forName
- * can no longer look at the current frame for the caller class.
- */
-JNIEXPORT jclass JNICALL
-JVM_GetCallerClass(JNIEnv *env, int n);
-
-/*
- * Find primitive classes
- * utf: class name
- */
-JNIEXPORT jclass JNICALL
-JVM_FindPrimitiveClass(JNIEnv *env, const char *utf);
-
-/*
- * Find a class from a boot class loader. Returns NULL if class not found.
- */
-JNIEXPORT jclass JNICALL
-JVM_FindClassFromBootLoader(JNIEnv *env, const char *name);
-
-/*
- * Find a class from a given class loader. Throws ClassNotFoundException.
- * name: name of class
- * init: whether initialization is done
- * loader: class loader to look up the class. This may not be the same as the caller's
- * class loader.
- * caller: initiating class. The initiating class may be null when a security
- * manager is not installed.
- */
-JNIEXPORT jclass JNICALL
-JVM_FindClassFromCaller(JNIEnv *env, const char *name, jboolean init,
- jobject loader, jclass caller);
-
-/*
- * Find a class from a given class.
- */
-JNIEXPORT jclass JNICALL
-JVM_FindClassFromClass(JNIEnv *env, const char *name, jboolean init,
- jclass from);
-
-/* Find a loaded class cached by the VM */
-JNIEXPORT jclass JNICALL
-JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name);
-
-/* Define a class */
-JNIEXPORT jclass JNICALL
-JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
- jsize len, jobject pd);
-
-/* Define a class with a source (added in JDK1.5) */
-JNIEXPORT jclass JNICALL
-JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader,
- const jbyte *buf, jsize len, jobject pd,
- const char *source);
-
-/*
- * Module support funcions
- */
-
-/*
- * Define a module with the specified packages and bind the module to the
- * given class loader.
- * module: module to define
- * is_open: specifies if module is open (currently ignored)
- * version: the module version
- * location: the module location
- * packages: list of packages in the module
- * num_packages: number of packages in the module
- */
-JNIEXPORT void JNICALL
-JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version,
- jstring location, const char* const* packages, jsize num_packages);
-
-/*
- * Set the boot loader's unnamed module.
- * module: boot loader's unnamed module
- */
-JNIEXPORT void JNICALL
-JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module);
-
-/*
- * Do a qualified export of a package.
- * from_module: module containing the package to export
- * package: name of the package to export
- * to_module: module to export the package to
- */
-JNIEXPORT void JNICALL
-JVM_AddModuleExports(JNIEnv *env, jobject from_module, const char* package, jobject to_module);
-
-/*
- * Do an export of a package to all unnamed modules.
- * from_module: module containing the package to export
- * package: name of the package to export to all unnamed modules
- */
-JNIEXPORT void JNICALL
-JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, const char* package);
-
-/*
- * Do an unqualified export of a package.
- * from_module: module containing the package to export
- * package: name of the package to export
- */
-JNIEXPORT void JNICALL
-JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, const char* package);
-
-/*
- * Add a module to the list of modules that a given module can read.
- * from_module: module requesting read access
- * source_module: module that from_module wants to read
- */
-JNIEXPORT void JNICALL
-JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module);
-
-/*
- * Reflection support functions
- */
-
-JNIEXPORT jstring JNICALL
-JVM_GetClassName(JNIEnv *env, jclass cls);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetClassInterfaces(JNIEnv *env, jclass cls);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsInterface(JNIEnv *env, jclass cls);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetClassSigners(JNIEnv *env, jclass cls);
-
-JNIEXPORT void JNICALL
-JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers);
-
-JNIEXPORT jobject JNICALL
-JVM_GetProtectionDomain(JNIEnv *env, jclass cls);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsArrayClass(JNIEnv *env, jclass cls);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsPrimitiveClass(JNIEnv *env, jclass cls);
-
-JNIEXPORT jint JNICALL
-JVM_GetClassModifiers(JNIEnv *env, jclass cls);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass);
-
-JNIEXPORT jclass JNICALL
-JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass);
-
-JNIEXPORT jstring JNICALL
-JVM_GetSimpleBinaryName(JNIEnv *env, jclass ofClass);
-
-/* Generics support (JDK 1.5) */
-JNIEXPORT jstring JNICALL
-JVM_GetClassSignature(JNIEnv *env, jclass cls);
-
-/* Annotations support (JDK 1.5) */
-JNIEXPORT jbyteArray JNICALL
-JVM_GetClassAnnotations(JNIEnv *env, jclass cls);
-
-/* Annotations support (JDK 1.6) */
-
-/* Type use annotations support (JDK 1.8) */
-
-JNIEXPORT jbyteArray JNICALL
-JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls);
-
-// field is a handle to a java.lang.reflect.Field object
-JNIEXPORT jbyteArray JNICALL
-JVM_GetFieldTypeAnnotations(JNIEnv *env, jobject field);
-
-// method is a handle to a java.lang.reflect.Method object
-JNIEXPORT jbyteArray JNICALL
-JVM_GetMethodTypeAnnotations(JNIEnv *env, jobject method);
-
-/*
- * New (JDK 1.4) reflection implementation
- */
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly);
-
-/* Differs from JVM_GetClassModifiers in treatment of inner classes.
- This returns the access flags for the class as specified in the
- class file rather than searching the InnerClasses attribute (if
- present) to find the source-level access flags. Only the values of
- the low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be
- valid. */
-JNIEXPORT jint JNICALL
-JVM_GetClassAccessFlags(JNIEnv *env, jclass cls);
-
-/*
- * Constant pool access; currently used to implement reflective access to annotations (JDK 1.5)
- */
-
-JNIEXPORT jobject JNICALL
-JVM_GetClassConstantPool(JNIEnv *env, jclass cls);
-
-JNIEXPORT jint JNICALL JVM_ConstantPoolGetSize
-(JNIEnv *env, jobject obj, jobject unused);
-
-JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAtIfLoaded
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAtIfLoaded
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jobject JNICALL JVM_ConstantPoolGetFieldAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jobject JNICALL JVM_ConstantPoolGetFieldAtIfLoaded
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jobjectArray JNICALL JVM_ConstantPoolGetMemberRefInfoAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jobjectArray JNICALL JVM_ConstantPoolGetNameAndTypeRefInfoAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jint JNICALL JVM_ConstantPoolGetNameAndTypeRefIndexAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jint JNICALL JVM_ConstantPoolGetClassRefIndexAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jint JNICALL JVM_ConstantPoolGetIntAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jlong JNICALL JVM_ConstantPoolGetLongAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jfloat JNICALL JVM_ConstantPoolGetFloatAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jdouble JNICALL JVM_ConstantPoolGetDoubleAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jstring JNICALL JVM_ConstantPoolGetStringAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jstring JNICALL JVM_ConstantPoolGetUTF8At
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jbyte JNICALL JVM_ConstantPoolGetTagAt
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-/*
- * java.security.*
- */
-
-JNIEXPORT jobject JNICALL
-JVM_DoPrivileged(JNIEnv *env, jclass cls,
- jobject action, jobject context, jboolean wrapException);
-
-JNIEXPORT jobject JNICALL
-JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls);
-
-JNIEXPORT jobject JNICALL
-JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls);
-
-/*
- * Signal support, used to implement the shutdown sequence. Every VM must
- * support JVM_SIGINT and JVM_SIGTERM, raising the former for user interrupts
- * (^C) and the latter for external termination (kill, system shutdown, etc.).
- * Other platform-dependent signal values may also be supported.
- */
-
-JNIEXPORT void * JNICALL
-JVM_RegisterSignal(jint sig, void *handler);
-
-JNIEXPORT jboolean JNICALL
-JVM_RaiseSignal(jint sig);
-
-JNIEXPORT jint JNICALL
-JVM_FindSignal(const char *name);
-
-/*
- * Retrieve the assertion directives for the specified class.
- */
-JNIEXPORT jboolean JNICALL
-JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls);
-
-/*
- * Retrieve the assertion directives from the VM.
- */
-JNIEXPORT jobject JNICALL
-JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused);
-
-/*
- * java.util.concurrent.atomic.AtomicLong
- */
-JNIEXPORT jboolean JNICALL
-JVM_SupportsCX8(void);
-
-/*************************************************************************
- PART 2: Support for the Verifier and Class File Format Checker
- ************************************************************************/
-/*
- * Return the class name in UTF format. The result is valid
- * until JVM_ReleaseUTf is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetClassNameUTF(JNIEnv *env, jclass cb);
-
-/*
- * Returns the constant pool types in the buffer provided by "types."
- */
-JNIEXPORT void JNICALL
-JVM_GetClassCPTypes(JNIEnv *env, jclass cb, unsigned char *types);
-
-/*
- * Returns the number of Constant Pool entries.
- */
-JNIEXPORT jint JNICALL
-JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cb);
-
-/*
- * Returns the number of *declared* fields or methods.
- */
-JNIEXPORT jint JNICALL
-JVM_GetClassFieldsCount(JNIEnv *env, jclass cb);
-
-JNIEXPORT jint JNICALL
-JVM_GetClassMethodsCount(JNIEnv *env, jclass cb);
-
-/*
- * Returns the CP indexes of exceptions raised by a given method.
- * Places the result in the given buffer.
- *
- * The method is identified by method_index.
- */
-JNIEXPORT void JNICALL
-JVM_GetMethodIxExceptionIndexes(JNIEnv *env, jclass cb, jint method_index,
- unsigned short *exceptions);
-/*
- * Returns the number of exceptions raised by a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxExceptionsCount(JNIEnv *env, jclass cb, jint method_index);
-
-/*
- * Returns the byte code sequence of a given method.
- * Places the result in the given buffer.
- *
- * The method is identified by method_index.
- */
-JNIEXPORT void JNICALL
-JVM_GetMethodIxByteCode(JNIEnv *env, jclass cb, jint method_index,
- unsigned char *code);
-
-/*
- * Returns the length of the byte code sequence of a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cb, jint method_index);
-
-/*
- * A structure used to a capture exception table entry in a Java method.
- */
-typedef struct {
- jint start_pc;
- jint end_pc;
- jint handler_pc;
- jint catchType;
-} JVM_ExceptionTableEntryType;
-
-/*
- * Returns the exception table entry at entry_index of a given method.
- * Places the result in the given buffer.
- *
- * The method is identified by method_index.
- */
-JNIEXPORT void JNICALL
-JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cb, jint method_index,
- jint entry_index,
- JVM_ExceptionTableEntryType *entry);
-
-/*
- * Returns the length of the exception table of a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cb, int index);
-
-/*
- * Returns the modifiers of a given field.
- * The field is identified by field_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetFieldIxModifiers(JNIEnv *env, jclass cb, int index);
-
-/*
- * Returns the modifiers of a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxModifiers(JNIEnv *env, jclass cb, int index);
-
-/*
- * Returns the number of local variables of a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cb, int index);
-
-/*
- * Returns the number of arguments (including this pointer) of a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxArgsSize(JNIEnv *env, jclass cb, int index);
-
-/*
- * Returns the maximum amount of stack (in words) used by a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cb, int index);
-
-/*
- * Is a given method a constructor.
- * The method is identified by method_index.
- */
-JNIEXPORT jboolean JNICALL
-JVM_IsConstructorIx(JNIEnv *env, jclass cb, int index);
-
-/*
- * Is the given method generated by the VM.
- * The method is identified by method_index.
- */
-JNIEXPORT jboolean JNICALL
-JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cb, int index);
-
-/*
- * Returns the name of a given method in UTF format.
- * The result remains valid until JVM_ReleaseUTF is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the signature of a given method in UTF format.
- * The result remains valid until JVM_ReleaseUTF is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the name of the field refered to at a given constant pool
- * index.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the name of the method refered to at a given constant pool
- * index.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the signature of the method refered to at a given constant pool
- * index.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the signature of the field refered to at a given constant pool
- * index.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the class name refered to at a given constant pool index.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPClassNameUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the class name refered to at a given constant pool index.
- *
- * The constant pool entry must refer to a CONSTANT_Fieldref.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the class name refered to at a given constant pool index.
- *
- * The constant pool entry must refer to CONSTANT_Methodref or
- * CONSTANT_InterfaceMethodref.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the modifiers of a field in calledClass. The field is
- * referred to in class cb at constant pool entry index.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- *
- * Returns -1 if the field does not exist in calledClass.
- */
-JNIEXPORT jint JNICALL
-JVM_GetCPFieldModifiers(JNIEnv *env, jclass cb, int index, jclass calledClass);
-
-/*
- * Returns the modifiers of a method in calledClass. The method is
- * referred to in class cb at constant pool entry index.
- *
- * Returns -1 if the method does not exist in calledClass.
- */
-JNIEXPORT jint JNICALL
-JVM_GetCPMethodModifiers(JNIEnv *env, jclass cb, int index, jclass calledClass);
-
-/*
- * Releases the UTF string obtained from the VM.
- */
-JNIEXPORT void JNICALL
-JVM_ReleaseUTF(const char *utf);
-
-/*
- * Compare if two classes are in the same package.
- */
-JNIEXPORT jboolean JNICALL
-JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2);
-
-/* Constants in class files */
-
-#define JVM_ACC_PUBLIC 0x0001 /* visible to everyone */
-#define JVM_ACC_PRIVATE 0x0002 /* visible only to the defining class */
-#define JVM_ACC_PROTECTED 0x0004 /* visible to subclasses */
-#define JVM_ACC_STATIC 0x0008 /* instance variable is static */
-#define JVM_ACC_FINAL 0x0010 /* no further subclassing, overriding */
-#define JVM_ACC_SYNCHRONIZED 0x0020 /* wrap method call in monitor lock */
-#define JVM_ACC_SUPER 0x0020 /* funky handling of invokespecial */
-#define JVM_ACC_VOLATILE 0x0040 /* can not cache in registers */
-#define JVM_ACC_BRIDGE 0x0040 /* bridge method generated by compiler */
-#define JVM_ACC_TRANSIENT 0x0080 /* not persistent */
-#define JVM_ACC_VARARGS 0x0080 /* method declared with variable number of args */
-#define JVM_ACC_NATIVE 0x0100 /* implemented in C */
-#define JVM_ACC_INTERFACE 0x0200 /* class is an interface */
-#define JVM_ACC_ABSTRACT 0x0400 /* no definition provided */
-#define JVM_ACC_STRICT 0x0800 /* strict floating point */
-#define JVM_ACC_SYNTHETIC 0x1000 /* compiler-generated class, method or field */
-#define JVM_ACC_ANNOTATION 0x2000 /* annotation type */
-#define JVM_ACC_ENUM 0x4000 /* field is declared as element of enum */
-#define JVM_ACC_MODULE 0x8000 /* module-info class file */
-
-#define JVM_ACC_PUBLIC_BIT 0
-#define JVM_ACC_PRIVATE_BIT 1
-#define JVM_ACC_PROTECTED_BIT 2
-#define JVM_ACC_STATIC_BIT 3
-#define JVM_ACC_FINAL_BIT 4
-#define JVM_ACC_SYNCHRONIZED_BIT 5
-#define JVM_ACC_SUPER_BIT 5
-#define JVM_ACC_VOLATILE_BIT 6
-#define JVM_ACC_BRIDGE_BIT 6
-#define JVM_ACC_TRANSIENT_BIT 7
-#define JVM_ACC_VARARGS_BIT 7
-#define JVM_ACC_NATIVE_BIT 8
-#define JVM_ACC_INTERFACE_BIT 9
-#define JVM_ACC_ABSTRACT_BIT 10
-#define JVM_ACC_STRICT_BIT 11
-#define JVM_ACC_SYNTHETIC_BIT 12
-#define JVM_ACC_ANNOTATION_BIT 13
-#define JVM_ACC_ENUM_BIT 14
-
-// NOTE: replicated in SA in vm/agent/sun/jvm/hotspot/utilities/ConstantTag.java
-enum {
- JVM_CONSTANT_Utf8 = 1,
- JVM_CONSTANT_Unicode, /* unused */
- JVM_CONSTANT_Integer,
- JVM_CONSTANT_Float,
- JVM_CONSTANT_Long,
- JVM_CONSTANT_Double,
- JVM_CONSTANT_Class,
- JVM_CONSTANT_String,
- JVM_CONSTANT_Fieldref,
- JVM_CONSTANT_Methodref,
- JVM_CONSTANT_InterfaceMethodref,
- JVM_CONSTANT_NameAndType,
- JVM_CONSTANT_MethodHandle = 15, // JSR 292
- JVM_CONSTANT_MethodType = 16, // JSR 292
- //JVM_CONSTANT_(unused) = 17, // JSR 292 early drafts only
- JVM_CONSTANT_InvokeDynamic = 18, // JSR 292
- JVM_CONSTANT_ExternalMax = 18 // Last tag found in classfiles
-};
-
-/* JVM_CONSTANT_MethodHandle subtypes */
-enum {
- JVM_REF_getField = 1,
- JVM_REF_getStatic = 2,
- JVM_REF_putField = 3,
- JVM_REF_putStatic = 4,
- JVM_REF_invokeVirtual = 5,
- JVM_REF_invokeStatic = 6,
- JVM_REF_invokeSpecial = 7,
- JVM_REF_newInvokeSpecial = 8,
- JVM_REF_invokeInterface = 9
-};
-
-/* Used in the newarray instruction. */
-
-#define JVM_T_BOOLEAN 4
-#define JVM_T_CHAR 5
-#define JVM_T_FLOAT 6
-#define JVM_T_DOUBLE 7
-#define JVM_T_BYTE 8
-#define JVM_T_SHORT 9
-#define JVM_T_INT 10
-#define JVM_T_LONG 11
-
-/* JVM method signatures */
-
-#define JVM_SIGNATURE_ARRAY '['
-#define JVM_SIGNATURE_BYTE 'B'
-#define JVM_SIGNATURE_CHAR 'C'
-#define JVM_SIGNATURE_CLASS 'L'
-#define JVM_SIGNATURE_ENDCLASS ';'
-#define JVM_SIGNATURE_ENUM 'E'
-#define JVM_SIGNATURE_FLOAT 'F'
-#define JVM_SIGNATURE_DOUBLE 'D'
-#define JVM_SIGNATURE_FUNC '('
-#define JVM_SIGNATURE_ENDFUNC ')'
-#define JVM_SIGNATURE_INT 'I'
-#define JVM_SIGNATURE_LONG 'J'
-#define JVM_SIGNATURE_SHORT 'S'
-#define JVM_SIGNATURE_VOID 'V'
-#define JVM_SIGNATURE_BOOLEAN 'Z'
-
-/*
- * A function defined by the byte-code verifier and called by the VM.
- * This is not a function implemented in the VM.
- *
- * Returns JNI_FALSE if verification fails. A detailed error message
- * will be places in msg_buf, whose length is specified by buf_len.
- */
-typedef jboolean (*verifier_fn_t)(JNIEnv *env,
- jclass cb,
- char * msg_buf,
- jint buf_len);
-
-
-/*
- * Support for a VM-independent class format checker.
- */
-typedef struct {
- unsigned long code; /* byte code */
- unsigned long excs; /* exceptions */
- unsigned long etab; /* catch table */
- unsigned long lnum; /* line number */
- unsigned long lvar; /* local vars */
-} method_size_info;
-
-typedef struct {
- unsigned int constants; /* constant pool */
- unsigned int fields;
- unsigned int methods;
- unsigned int interfaces;
- unsigned int fields2; /* number of static 2-word fields */
- unsigned int innerclasses; /* # of records in InnerClasses attr */
-
- method_size_info clinit; /* memory used in clinit */
- method_size_info main; /* used everywhere else */
-} class_size_info;
-
-/*
- * Functions defined in libjava.so to perform string conversions.
- *
- */
-
-typedef jstring (*to_java_string_fn_t)(JNIEnv *env, char *str);
-
-typedef char *(*to_c_string_fn_t)(JNIEnv *env, jstring s, jboolean *b);
-
-/* This is the function defined in libjava.so that performs class
- * format checks. This functions fills in size information about
- * the class file and returns:
- *
- * 0: good
- * -1: out of memory
- * -2: bad format
- * -3: unsupported version
- * -4: bad class name
- */
-
-typedef jint (*check_format_fn_t)(char *class_name,
- unsigned char *data,
- unsigned int data_size,
- class_size_info *class_size,
- char *message_buffer,
- jint buffer_length,
- jboolean measure_only,
- jboolean check_relaxed);
-
-#define JVM_RECOGNIZED_CLASS_MODIFIERS (JVM_ACC_PUBLIC | \
- JVM_ACC_FINAL | \
- JVM_ACC_SUPER | \
- JVM_ACC_INTERFACE | \
- JVM_ACC_ABSTRACT | \
- JVM_ACC_ANNOTATION | \
- JVM_ACC_ENUM | \
- JVM_ACC_SYNTHETIC)
-
-#define JVM_RECOGNIZED_FIELD_MODIFIERS (JVM_ACC_PUBLIC | \
- JVM_ACC_PRIVATE | \
- JVM_ACC_PROTECTED | \
- JVM_ACC_STATIC | \
- JVM_ACC_FINAL | \
- JVM_ACC_VOLATILE | \
- JVM_ACC_TRANSIENT | \
- JVM_ACC_ENUM | \
- JVM_ACC_SYNTHETIC)
-
-#define JVM_RECOGNIZED_METHOD_MODIFIERS (JVM_ACC_PUBLIC | \
- JVM_ACC_PRIVATE | \
- JVM_ACC_PROTECTED | \
- JVM_ACC_STATIC | \
- JVM_ACC_FINAL | \
- JVM_ACC_SYNCHRONIZED | \
- JVM_ACC_BRIDGE | \
- JVM_ACC_VARARGS | \
- JVM_ACC_NATIVE | \
- JVM_ACC_ABSTRACT | \
- JVM_ACC_STRICT | \
- JVM_ACC_SYNTHETIC)
-
-/*
- * This is the function defined in libjava.so to perform path
- * canonicalization. VM call this function before opening jar files
- * to load system classes.
- *
- */
-
-typedef int (*canonicalize_fn_t)(JNIEnv *env, char *orig, char *out, int len);
-
-/*************************************************************************
- PART 3: I/O and Network Support
- ************************************************************************/
-
-/*
- * Convert a pathname into native format. This function does syntactic
- * cleanup, such as removing redundant separator characters. It modifies
- * the given pathname string in place.
- */
-JNIEXPORT char * JNICALL
-JVM_NativePath(char *);
-
-/*
- * The standard printing functions supported by the Java VM. (Should they
- * be renamed to JVM_* in the future?
- */
-
-/* jio_snprintf() and jio_vsnprintf() behave like snprintf(3) and vsnprintf(3),
- * respectively, with the following differences:
- * - The string written to str is always zero-terminated, also in case of
- * truncation (count is too small to hold the result string), unless count
- * is 0. In case of truncation count-1 characters are written and '\0'
- * appendend.
- * - If count is too small to hold the whole string, -1 is returned across
- * all platforms. */
-JNIEXPORT int
-jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
-
-JNIEXPORT int
-jio_snprintf(char *str, size_t count, const char *fmt, ...);
-
-JNIEXPORT int
-jio_fprintf(FILE *, const char *fmt, ...);
-
-JNIEXPORT int
-jio_vfprintf(FILE *, const char *fmt, va_list args);
-
-
-JNIEXPORT void * JNICALL
-JVM_RawMonitorCreate(void);
-
-JNIEXPORT void JNICALL
-JVM_RawMonitorDestroy(void *mon);
-
-JNIEXPORT jint JNICALL
-JVM_RawMonitorEnter(void *mon);
-
-JNIEXPORT void JNICALL
-JVM_RawMonitorExit(void *mon);
-
-/*
- * java.lang.reflect.Method
- */
-JNIEXPORT jobject JNICALL
-JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0);
-
-/*
- * java.lang.reflect.Constructor
- */
-JNIEXPORT jobject JNICALL
-JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0);
-
-/*
- * java.lang.management support
- */
-JNIEXPORT void* JNICALL
-JVM_GetManagement(jint version);
-
-/*
- * com.sun.tools.attach.VirtualMachine support
- *
- * Initialize the agent properties with the properties maintained in the VM.
- */
-JNIEXPORT jobject JNICALL
-JVM_InitAgentProperties(JNIEnv *env, jobject agent_props);
-
-JNIEXPORT jstring JNICALL
-JVM_GetTemporaryDirectory(JNIEnv *env);
-
-/* Generics reflection support.
- *
- * Returns information about the given class's EnclosingMethod
- * attribute, if present, or null if the class had no enclosing
- * method.
- *
- * If non-null, the returned array contains three elements. Element 0
- * is the java.lang.Class of which the enclosing method is a member,
- * and elements 1 and 2 are the java.lang.Strings for the enclosing
- * method's name and descriptor, respectively.
- */
-JNIEXPORT jobjectArray JNICALL
-JVM_GetEnclosingMethodInfo(JNIEnv* env, jclass ofClass);
-
-/* =========================================================================
- * The following defines a private JVM interface that the JDK can query
- * for the JVM version and capabilities. sun.misc.Version defines
- * the methods for getting the VM version and its capabilities.
- *
- * When a new bit is added, the following should be updated to provide
- * access to the new capability:
- * HS: JVM_GetVersionInfo and Abstract_VM_Version class
- * SDK: Version class
- *
- * Similary, a private JDK interface JDK_GetVersionInfo0 is defined for
- * JVM to query for the JDK version and capabilities.
- *
- * When a new bit is added, the following should be updated to provide
- * access to the new capability:
- * HS: JDK_Version class
- * SDK: JDK_GetVersionInfo0
- *
- * ==========================================================================
- */
-typedef struct {
- unsigned int jvm_version; /* Encoded $VNUM as defined by JEP-223 */
- unsigned int patch_version : 8; /* JEP-223 patch version */
- unsigned int reserved3 : 8;
- unsigned int reserved1 : 16;
- unsigned int reserved2;
-
- /* The following bits represents JVM supports that JDK has dependency on.
- * JDK can use these bits to determine which JVM version
- * and support it has to maintain runtime compatibility.
- *
- * When a new bit is added in a minor or update release, make sure
- * the new bit is also added in the main/baseline.
- */
- unsigned int is_attachable : 1;
- unsigned int : 31;
- unsigned int : 32;
- unsigned int : 32;
-} jvm_version_info;
-
-#define JVM_VERSION_MAJOR(version) ((version & 0xFF000000) >> 24)
-#define JVM_VERSION_MINOR(version) ((version & 0x00FF0000) >> 16)
-#define JVM_VERSION_SECURITY(version) ((version & 0x0000FF00) >> 8)
-#define JVM_VERSION_BUILD(version) ((version & 0x000000FF))
-
-JNIEXPORT void JNICALL
-JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size);
-
-typedef struct {
- unsigned int jdk_version; /* Encoded $VNUM as defined by JEP-223 */
- unsigned int patch_version : 8; /* JEP-223 patch version */
- unsigned int reserved3 : 8;
- unsigned int reserved1 : 16;
- unsigned int reserved2;
-
- /* The following bits represents new JDK supports that VM has dependency on.
- * VM implementation can use these bits to determine which JDK version
- * and support it has to maintain runtime compatibility.
- *
- * When a new bit is added in a minor or update release, make sure
- * the new bit is also added in the main/baseline.
- */
- unsigned int thread_park_blocker : 1;
- unsigned int post_vm_init_hook_enabled : 1;
- unsigned int pending_list_uses_discovered_field : 1;
- unsigned int : 29;
- unsigned int : 32;
- unsigned int : 32;
-} jdk_version_info;
-
-#define JDK_VERSION_MAJOR(version) ((version & 0xFF000000) >> 24)
-#define JDK_VERSION_MINOR(version) ((version & 0x00FF0000) >> 16)
-#define JDK_VERSION_SECURITY(version) ((version & 0x0000FF00) >> 8)
-#define JDK_VERSION_BUILD(version) ((version & 0x000000FF))
-
-/*
- * This is the function JDK_GetVersionInfo0 defined in libjava.so
- * that is dynamically looked up by JVM.
- */
-typedef void (*jdk_version_info_fn_t)(jdk_version_info* info, size_t info_size);
-
-/*
- * This structure is used by the launcher to get the default thread
- * stack size from the VM using JNI_GetDefaultJavaVMInitArgs() with a
- * version of 1.1. As it is not supported otherwise, it has been removed
- * from jni.h
- */
-typedef struct JDK1_1InitArgs {
- jint version;
-
- char **properties;
- jint checkSource;
- jint nativeStackSize;
- jint javaStackSize;
- jint minHeapSize;
- jint maxHeapSize;
- jint verifyMode;
- char *classpath;
-
- jint (JNICALL *vfprintf)(FILE *fp, const char *format, va_list args);
- void (JNICALL *exit)(jint code);
- void (JNICALL *abort)(void);
-
- jint enableClassGC;
- jint enableVerboseGC;
- jint disableAsyncGC;
- jint verbose;
- jboolean debugging;
- jint debugPort;
-} JDK1_1InitArgs;
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
-
-#endif /* !_JAVASOFT_JVM_H_ */
-
-#endif // SHARE_VM_PRIMS_JVM_H
--- a/src/hotspot/share/prims/jvmtiEnvBase.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -741,7 +741,7 @@
// Save JNI local handles for any objects that this frame owns.
jvmtiError
JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread* java_thread,
- javaVFrame *jvf, GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list, int stack_depth) {
+ javaVFrame *jvf, GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list, jint stack_depth) {
jvmtiError err = JVMTI_ERROR_NONE;
ResourceMark rm;
--- a/src/hotspot/share/prims/jvmtiImpl.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/prims/jvmtiImpl.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -523,7 +523,7 @@
//
// Constructor for non-object getter
-VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, int index, BasicType type)
+VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type)
: _thread(thread)
, _calling_thread(NULL)
, _depth(depth)
@@ -536,7 +536,7 @@
}
// Constructor for object or non-object setter
-VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, int index, BasicType type, jvalue value)
+VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type, jvalue value)
: _thread(thread)
, _calling_thread(NULL)
, _depth(depth)
--- a/src/hotspot/share/prims/jvmtiTagMap.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/prims/jvmtiTagMap.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -2006,7 +2006,7 @@
jlong thread_tag,
jint depth,
jmethodID method,
- jint slot,
+ int slot,
oop obj) {
assert(ServiceUtil::visible_oop(obj), "checking");
--- a/src/hotspot/share/prims/methodHandles.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/prims/methodHandles.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -27,7 +27,6 @@
#include "classfile/javaClasses.hpp"
#include "classfile/vmSymbols.hpp"
-#include "prims/jvm.h"
#include "runtime/frame.inline.hpp"
#include "runtime/globals.hpp"
#include "runtime/interfaceSupport.hpp"
--- a/src/hotspot/share/prims/nativeLookup.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/prims/nativeLookup.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -293,10 +293,12 @@
char* critical_name = critical_jni_name(method);
// Compute argument size
- int args_size = 1 // JNIEnv
- + (method->is_static() ? 1 : 0) // class for static methods
- + method->size_of_parameters(); // actual parameters
-
+ int args_size = method->size_of_parameters();
+ for (SignatureStream ss(signature); !ss.at_return_type(); ss.next()) {
+ if (ss.is_array()) {
+ args_size += T_INT_size; // array length parameter
+ }
+ }
// 1) Try JNI short style
entry = lookup_critical_style(method, critical_name, "", args_size, true);
--- a/src/hotspot/share/prims/perf.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/prims/perf.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -24,11 +24,11 @@
#include "precompiled.hpp"
#include "jni.h"
+#include "jvm.h"
#include "classfile/vmSymbols.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/interfaceSupport.hpp"
#include "runtime/perfData.hpp"
#include "runtime/perfMemory.hpp"
--- a/src/hotspot/share/prims/stackwalk.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/prims/stackwalk.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -272,9 +272,8 @@
return array_h;
}
-// Fill StackFrameInfo with declaringClass and bci and initialize memberName
+// Fill StackFrameInfo with bci and initialize memberName
void BaseFrameStream::fill_stackframe(Handle stackFrame, const methodHandle& method, TRAPS) {
- java_lang_StackFrameInfo::set_declaringClass(stackFrame(), method->method_holder()->java_mirror());
java_lang_StackFrameInfo::set_method_and_bci(stackFrame, method, bci(), THREAD);
}
--- a/src/hotspot/share/prims/unsafe.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/prims/unsafe.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "jni.h"
+#include "jvm.h"
#include "classfile/classFileStream.hpp"
#include "classfile/vmSymbols.hpp"
#include "memory/allocation.inline.hpp"
@@ -31,7 +32,6 @@
#include "oops/fieldStreams.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "prims/unsafe.hpp"
#include "runtime/atomic.hpp"
#include "runtime/globals.hpp"
--- a/src/hotspot/share/prims/whitebox.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/prims/whitebox.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1715,6 +1715,10 @@
}
WB_END
+WB_ENTRY(jboolean, WB_AreOpenArchiveHeapObjectsMapped(JNIEnv* env))
+ return MetaspaceShared::open_archive_heap_region_mapped();
+WB_END
+
WB_ENTRY(jboolean, WB_IsCDSIncludedInVmBuild(JNIEnv* env))
#if INCLUDE_CDS
return true;
@@ -2031,6 +2035,7 @@
{CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass },
{CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored },
{CC"getResolvedReferences", CC"(Ljava/lang/Class;)Ljava/lang/Object;", (void*)&WB_GetResolvedReferences},
+ {CC"areOpenArchiveHeapObjectsMapped", CC"()Z", (void*)&WB_AreOpenArchiveHeapObjectsMapped},
{CC"isCDSIncludedInVmBuild", CC"()Z", (void*)&WB_IsCDSIncludedInVmBuild },
{CC"clearInlineCaches0", CC"(Z)V", (void*)&WB_ClearInlineCaches },
{CC"addCompilerDirective", CC"(Ljava/lang/String;)I",
--- a/src/hotspot/share/runtime/arguments.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/arguments.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/classLoader.hpp"
#include "classfile/javaAssertions.hpp"
#include "classfile/moduleEntry.hpp"
@@ -39,7 +40,6 @@
#include "memory/allocation.inline.hpp"
#include "memory/universe.inline.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "prims/jvmtiExport.hpp"
#include "runtime/arguments.hpp"
#include "runtime/arguments_ext.hpp"
@@ -382,6 +382,8 @@
{ "MaxRAMFraction", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() },
{ "MinRAMFraction", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() },
{ "InitialRAMFraction", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() },
+ { "UseMembar", JDK_Version::jdk(10), JDK_Version::jdk(11), JDK_Version::jdk(12) },
+ { "IgnoreUnverifiableClassesDuringDump", JDK_Version::jdk(10), JDK_Version::undefined(), JDK_Version::undefined() },
// --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in:
{ "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() },
@@ -395,6 +397,10 @@
{ "MinSleepInterval", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) },
{ "PermSize", JDK_Version::undefined(), JDK_Version::jdk(8), JDK_Version::undefined() },
{ "MaxPermSize", JDK_Version::undefined(), JDK_Version::jdk(8), JDK_Version::undefined() },
+ { "SharedReadWriteSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
+ { "SharedReadOnlySize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
+ { "SharedMiscDataSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
+ { "SharedMiscCodeSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
#ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS
{ "dep > obs", JDK_Version::jdk(9), JDK_Version::jdk(8), JDK_Version::undefined() },
@@ -1859,7 +1865,7 @@
#endif
select_gc();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
// Shared spaces work fine with other GCs but causes bytecode rewriting
// to be disabled, which hurts interpreter performance and decreases
// server performance. When -server is specified, keep the default off
@@ -2088,9 +2094,10 @@
// respecting the maximum and minimum sizes of the heap.
if (FLAG_IS_DEFAULT(MaxHeapSize)) {
julong reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100);
- if (phys_mem <= (julong)((MaxHeapSize * MinRAMPercentage) / 100)) {
+ const julong reasonable_min = (julong)((phys_mem * MinRAMPercentage) / 100);
+ if (reasonable_min < MaxHeapSize) {
// Small physical memory, so use a minimum fraction of it for the heap
- reasonable_max = (julong)((phys_mem * MinRAMPercentage) / 100);
+ reasonable_max = reasonable_min;
} else {
// Not-small physical memory, so require a heap at least
// as large as MaxHeapSize
--- a/src/hotspot/share/runtime/biasedLocking.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/biasedLocking.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -145,7 +145,9 @@
return info;
}
-static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) {
+// After the call, *biased_locker will be set to obj->mark()->biased_locker() if biased_locker != NULL,
+// AND it is a living thread. Otherwise it will not be updated, (i.e. the caller is responsible for initialization).
+static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread, JavaThread** biased_locker) {
markOop mark = obj->mark();
if (!mark->has_bias_pattern()) {
if (log_is_enabled(Info, biasedlocking)) {
@@ -298,6 +300,11 @@
}
}
+ // If requested, return information on which thread held the bias
+ if (biased_locker != NULL) {
+ *biased_locker = biased_thread;
+ }
+
return BiasedLocking::BIAS_REVOKED;
}
@@ -418,7 +425,7 @@
// At this point we're done. All we have to do is potentially
// adjust the header of the given object to revoke its bias.
- revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread);
+ revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread, NULL);
} else {
if (log_is_enabled(Info, biasedlocking)) {
ResourceMark rm;
@@ -440,14 +447,14 @@
oop owner = mon_info->owner();
markOop mark = owner->mark();
if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
- revoke_bias(owner, false, true, requesting_thread);
+ revoke_bias(owner, false, true, requesting_thread, NULL);
}
}
}
// Must force the bias of the passed object to be forcibly revoked
// as well to ensure guarantees to callers
- revoke_bias(o, false, true, requesting_thread);
+ revoke_bias(o, false, true, requesting_thread, NULL);
}
log_info(biasedlocking)("* Ending bulk revocation");
@@ -486,19 +493,22 @@
GrowableArray<Handle>* _objs;
JavaThread* _requesting_thread;
BiasedLocking::Condition _status_code;
+ traceid _biased_locker_id;
public:
VM_RevokeBias(Handle* obj, JavaThread* requesting_thread)
: _obj(obj)
, _objs(NULL)
, _requesting_thread(requesting_thread)
- , _status_code(BiasedLocking::NOT_BIASED) {}
+ , _status_code(BiasedLocking::NOT_BIASED)
+ , _biased_locker_id(0) {}
VM_RevokeBias(GrowableArray<Handle>* objs, JavaThread* requesting_thread)
: _obj(NULL)
, _objs(objs)
, _requesting_thread(requesting_thread)
- , _status_code(BiasedLocking::NOT_BIASED) {}
+ , _status_code(BiasedLocking::NOT_BIASED)
+ , _biased_locker_id(0) {}
virtual VMOp_Type type() const { return VMOp_RevokeBias; }
@@ -525,7 +535,11 @@
virtual void doit() {
if (_obj != NULL) {
log_info(biasedlocking)("Revoking bias with potentially per-thread safepoint:");
- _status_code = revoke_bias((*_obj)(), false, false, _requesting_thread);
+ JavaThread* biased_locker = NULL;
+ _status_code = revoke_bias((*_obj)(), false, false, _requesting_thread, &biased_locker);
+ if (biased_locker != NULL) {
+ _biased_locker_id = THREAD_TRACE_ID(biased_locker);
+ }
clean_up_cached_monitor_info();
return;
} else {
@@ -537,6 +551,10 @@
BiasedLocking::Condition status_code() const {
return _status_code;
}
+
+ traceid biased_locker() const {
+ return _biased_locker_id;
+ }
};
@@ -645,7 +663,7 @@
ResourceMark rm;
log_info(biasedlocking)("Revoking bias by walking my own stack:");
EventBiasedLockSelfRevocation event;
- BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD);
+ BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD, NULL);
((JavaThread*) THREAD)->set_cached_monitor_info(NULL);
assert(cond == BIAS_REVOKED, "why not?");
if (event.should_commit()) {
@@ -661,6 +679,7 @@
event.set_lockClass(k);
// Subtract 1 to match the id of events committed inside the safepoint
event.set_safepointId(SafepointSynchronize::safepoint_counter() - 1);
+ event.set_previousOwner(revoke.biased_locker());
event.commit();
}
return revoke.status_code();
@@ -700,7 +719,7 @@
oop obj = h_obj();
HeuristicsResult heuristics = update_heuristics(obj, false);
if (heuristics == HR_SINGLE_REVOKE) {
- revoke_bias(obj, false, false, NULL);
+ revoke_bias(obj, false, false, NULL, NULL);
} else if ((heuristics == HR_BULK_REBIAS) ||
(heuristics == HR_BULK_REVOKE)) {
bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL);
@@ -716,7 +735,7 @@
oop obj = (objs->at(i))();
HeuristicsResult heuristics = update_heuristics(obj, false);
if (heuristics == HR_SINGLE_REVOKE) {
- revoke_bias(obj, false, false, NULL);
+ revoke_bias(obj, false, false, NULL, NULL);
} else if ((heuristics == HR_BULK_REBIAS) ||
(heuristics == HR_BULK_REVOKE)) {
bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL);
--- a/src/hotspot/share/runtime/commandLineFlagRangeList.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/commandLineFlagRangeList.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,10 +23,10 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "gc/shared/referenceProcessor.hpp"
-#include "prims/jvm.h"
#include "oops/markOop.hpp"
#include "runtime/arguments.hpp"
#include "runtime/commandLineFlagConstraintList.hpp"
--- a/src/hotspot/share/runtime/deoptimization.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/deoptimization.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "code/debugInfoRec.hpp"
@@ -40,7 +41,6 @@
#include "oops/oop.inline.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/verifyOopClosure.hpp"
-#include "prims/jvm.h"
#include "prims/jvmtiThreadState.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/compilationPolicy.hpp"
@@ -192,7 +192,7 @@
bool realloc_failures = false;
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
// Reallocate the non-escaping objects and restore their fields. Then
// relock objects if synchronization on them was eliminated.
#ifndef INCLUDE_JVMCI
@@ -282,7 +282,7 @@
}
}
#endif // INCLUDE_JVMCI
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
ScopeDesc* trap_scope = chunk->at(0)->scope();
Handle exceptionObject;
@@ -303,7 +303,7 @@
NoSafepointVerifier no_safepoint;
vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk, realloc_failures);
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
if (realloc_failures) {
pop_frames_failed_reallocs(thread, array);
}
@@ -792,7 +792,7 @@
Deoptimization::DeoptAction Deoptimization::_unloaded_action
= Deoptimization::Action_reinterpret;
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS) {
Handle pending_exception(THREAD, thread->pending_exception());
const char* exception_file = thread->exception_file();
@@ -1151,7 +1151,7 @@
}
}
#endif
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures) {
Events::log(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, p2i(fr.pc()), p2i(fr.sp()));
@@ -1211,7 +1211,7 @@
return array;
}
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array) {
// Reallocation of some scalar replaced objects failed. Record
// that we need to pop all the interpreter frames for the
@@ -1443,7 +1443,7 @@
return mdo;
}
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
void Deoptimization::load_class_by_index(const constantPoolHandle& constant_pool, int index, TRAPS) {
// in case of an unresolved klass entry, load the class.
if (constant_pool->tag_at(index).is_unresolved_klass()) {
@@ -1674,19 +1674,9 @@
tty->print(" compiler=%s compile_id=%d", nm->compiler_name(), nm->compile_id());
#if INCLUDE_JVMCI
if (nm->is_nmethod()) {
- oop installedCode = nm->as_nmethod()->jvmci_installed_code();
- if (installedCode != NULL) {
- oop installedCodeName = NULL;
- if (installedCode->is_a(InstalledCode::klass())) {
- installedCodeName = InstalledCode::name(installedCode);
- }
- if (installedCodeName != NULL) {
- tty->print(" (JVMCI: installedCodeName=%s) ", java_lang_String::as_utf8_string(installedCodeName));
- } else {
- tty->print(" (JVMCI: installed code has no name) ");
- }
- } else if (nm->is_compiled_by_jvmci()) {
- tty->print(" (JVMCI: no installed code) ");
+ char* installed_code_name = nm->as_nmethod()->jvmci_installed_code_name(buf, sizeof(buf));
+ if (installed_code_name != NULL) {
+ tty->print(" (JVMCI: installed code name=%s) ", installed_code_name);
}
}
#endif
@@ -2360,7 +2350,7 @@
if (xtty != NULL) xtty->tail("statistics");
}
}
-#else // COMPILER2 || INCLUDE_JVMCI
+#else // COMPILER2_OR_JVMCI
// Stubs for C1 only system.
@@ -2396,4 +2386,4 @@
return buf;
}
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
--- a/src/hotspot/share/runtime/deoptimization.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/deoptimization.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -151,7 +151,7 @@
// executing in a particular CodeBlob if UseBiasedLocking is enabled
static void revoke_biases_of_monitors(CodeBlob* cb);
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
JVMCI_ONLY(public:)
// Support for restoring non-escaping objects
@@ -162,7 +162,7 @@
static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread, bool realloc_failures);
static void pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array);
NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects, bool realloc_failures);)
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
public:
static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures);
--- a/src/hotspot/share/runtime/frame.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/frame.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1148,7 +1148,7 @@
// make sure we have the right receiver type
}
}
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
assert(DerivedPointerTable::is_empty(), "must be empty before verify");
#endif
oops_do_internal(&VerifyOopClosure::verify_oop, NULL, (RegisterMap*)map, false);
--- a/src/hotspot/share/runtime/globals.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/globals.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,9 +23,9 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/arguments.hpp"
#include "runtime/globals.hpp"
#include "runtime/globals_extension.hpp"
--- a/src/hotspot/share/runtime/globals.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/globals.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -99,11 +99,11 @@
#define CI_COMPILER_COUNT 0
#else
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
#define CI_COMPILER_COUNT 2
#else
#define CI_COMPILER_COUNT 1
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
#endif // no compilers
@@ -1144,8 +1144,8 @@
notproduct(bool, PrintSystemDictionaryAtExit, false, \
"Print the system dictionary at exit") \
\
- experimental(intx, PredictedLoadedClassCount, 0, \
- "Experimental: Tune loaded class cache starting size") \
+ diagnostic(bool, DynamicallyResizeSystemDictionaries, true, \
+ "Dynamically resize system dictionaries as needed") \
\
diagnostic(bool, UnsyncloadClass, false, \
"Unstable: VM calls loadClass unsynchronized. Custom " \
@@ -3901,18 +3901,6 @@
"If PrintSharedArchiveAndExit is true, also print the shared " \
"dictionary") \
\
- product(size_t, SharedReadWriteSize, 0, \
- "Deprecated") \
- \
- product(size_t, SharedReadOnlySize, 0, \
- "Deprecated") \
- \
- product(size_t, SharedMiscDataSize, 0, \
- "Deprecated") \
- \
- product(size_t, SharedMiscCodeSize, 0, \
- "Deprecated") \
- \
product(size_t, SharedBaseAddress, LP64_ONLY(32*G) \
NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)), \
"Address to allocate shared memory region for class data") \
@@ -3922,7 +3910,7 @@
"Average number of symbols per bucket in shared table") \
range(2, 246) \
\
- diagnostic(bool, IgnoreUnverifiableClassesDuringDump, false, \
+ diagnostic(bool, IgnoreUnverifiableClassesDuringDump, true, \
"Do not quit -Xshare:dump even if we encounter unverifiable " \
"classes. Just exclude them from the shared dictionary.") \
\
--- a/src/hotspot/share/runtime/handles.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/handles.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -99,7 +99,7 @@
while (bottom < top) {
// This test can be moved up but for now check every oop.
- assert(oopDesc::is_oop(*bottom), "handle should point to oop");
+ assert(oopDesc::is_oop(*bottom, true), "handle should point to oop");
f->do_oop(bottom++);
}
--- a/src/hotspot/share/runtime/init.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/init.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -60,7 +60,11 @@
jint universe_init(); // depends on codeCache_init and stubRoutines_init
#if INCLUDE_ALL_GCS
// depends on universe_init, must be before interpreter_init (currently only on SPARC)
+#ifndef ZERO
void g1_barrier_stubs_init() NOT_SPARC({});
+#else
+void g1_barrier_stubs_init() {};
+#endif
#endif
void interpreter_init(); // before any methods loaded
void invocationCounter_init(); // before any methods loaded
--- a/src/hotspot/share/runtime/interfaceSupport.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/interfaceSupport.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -47,7 +47,7 @@
Histogram* RuntimeHistogram;
RuntimeHistogramElement::RuntimeHistogramElement(const char* elementName) {
- static volatile jint RuntimeHistogram_lock = 0;
+ static volatile int RuntimeHistogram_lock = 0;
_name = elementName;
uintx count = 0;
--- a/src/hotspot/share/runtime/java.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/java.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "aot/aotLoader.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/stringTable.hpp"
@@ -49,7 +50,6 @@
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
-#include "prims/jvm.h"
#include "prims/jvmtiExport.hpp"
#include "runtime/arguments.hpp"
#include "runtime/biasedLocking.hpp"
--- a/src/hotspot/share/runtime/jniHandles.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/jniHandles.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -30,6 +30,7 @@
#include "runtime/jniHandles.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/thread.inline.hpp"
+#include "trace/traceMacros.hpp"
#include "utilities/align.hpp"
#if INCLUDE_ALL_GCS
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
@@ -126,6 +127,11 @@
template oop JNIHandles::resolve_jweak<true>(jweak);
template oop JNIHandles::resolve_jweak<false>(jweak);
+bool JNIHandles::is_global_weak_cleared(jweak handle) {
+ assert(is_jweak(handle), "not a weak handle");
+ return guard_value<false>(jweak_ref(handle)) == NULL;
+}
+
void JNIHandles::destroy_global(jobject handle) {
if (handle != NULL) {
assert(is_global_handle(handle), "Invalid delete of global JNI handle");
--- a/src/hotspot/share/runtime/jniHandles.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/jniHandles.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -82,6 +82,7 @@
// Weak global handles
static jobject make_weak_global(Handle obj);
static void destroy_weak_global(jobject handle);
+ static bool is_global_weak_cleared(jweak handle); // Test jweak without resolution
// Sentinel marking deleted handles in block. Note that we cannot store NULL as
// the sentinel, since clearing weak global JNI refs are done by storing NULL in
--- a/src/hotspot/share/runtime/mutexLocker.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/mutexLocker.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -116,7 +116,6 @@
Monitor* SecondaryFreeList_lock = NULL;
Mutex* OldSets_lock = NULL;
Monitor* RootRegionScan_lock = NULL;
-Mutex* MMUTracker_lock = NULL;
Monitor* GCTaskManager_lock = NULL;
@@ -130,7 +129,6 @@
Monitor* JfrMsg_lock = NULL;
Mutex* JfrBuffer_lock = NULL;
Mutex* JfrStream_lock = NULL;
-Mutex* JfrThreadGroups_lock = NULL;
#endif
#ifndef SUPPORTS_NATIVE_CX8
@@ -193,7 +191,6 @@
def(SecondaryFreeList_lock , PaddedMonitor, leaf , true, Monitor::_safepoint_check_never);
def(OldSets_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never);
def(RootRegionScan_lock , PaddedMonitor, leaf , true, Monitor::_safepoint_check_never);
- def(MMUTracker_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never);
def(StringDedupQueue_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never);
def(StringDedupTable_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never);
@@ -282,7 +279,6 @@
#if INCLUDE_TRACE
def(JfrMsg_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_always);
def(JfrBuffer_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never);
- def(JfrThreadGroups_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_always);
def(JfrStream_lock , PaddedMutex , leaf+1, true, Monitor::_safepoint_check_never); // ensure to rank lower than 'safepoint'
def(JfrStacktrace_lock , PaddedMutex , special, true, Monitor::_safepoint_check_sometimes);
#endif
--- a/src/hotspot/share/runtime/mutexLocker.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/mutexLocker.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -117,8 +117,6 @@
extern Monitor* SecondaryFreeList_lock; // protects the secondary free region list
extern Mutex* OldSets_lock; // protects the old region sets
extern Monitor* RootRegionScan_lock; // used to notify that the CM threads have finished scanning the IM snapshot regions
-extern Mutex* MMUTracker_lock; // protects the MMU
- // tracker data structures
extern Mutex* Management_lock; // a lock used to serialize JVM management
extern Monitor* Service_lock; // a lock used for service thread operation
@@ -130,7 +128,6 @@
extern Monitor* JfrMsg_lock; // protects JFR messaging
extern Mutex* JfrBuffer_lock; // protects JFR buffer operations
extern Mutex* JfrStream_lock; // protects JFR stream access
-extern Mutex* JfrThreadGroups_lock; // protects JFR access to Thread Groups
#endif
#ifndef SUPPORTS_NATIVE_CX8
--- a/src/hotspot/share/runtime/os.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/os.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/classLoader.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/moduleEntry.hpp"
@@ -41,7 +42,6 @@
#endif
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "prims/privilegedStack.hpp"
#include "runtime/arguments.hpp"
--- a/src/hotspot/share/runtime/os.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/os.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -25,8 +25,8 @@
#ifndef SHARE_VM_RUNTIME_OS_HPP
#define SHARE_VM_RUNTIME_OS_HPP
+#include "jvm.h"
#include "jvmtifiles/jvmti.h"
-#include "prims/jvm.h"
#include "runtime/extendedPC.hpp"
#include "runtime/handles.hpp"
#include "utilities/macros.hpp"
--- a/src/hotspot/share/runtime/perfData.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/perfData.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,10 +23,10 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/vmSymbols.hpp"
#include "logging/log.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/mutex.hpp"
@@ -420,11 +420,11 @@
PerfStringVariable* PerfDataManager::create_string_variable(CounterNS ns,
const char* name,
- jint max_length,
+ int max_length,
const char* s,
TRAPS) {
- if (max_length == 0 && s != NULL) max_length = (jint)strlen(s);
+ if (max_length == 0 && s != NULL) max_length = (int)strlen(s);
assert(max_length != 0, "PerfStringVariable with length 0");
--- a/src/hotspot/share/runtime/perfMemory.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/perfMemory.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,9 +23,9 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/arguments.hpp"
#include "runtime/java.hpp"
#include "runtime/mutex.hpp"
@@ -51,7 +51,7 @@
char* PerfMemory::_end = NULL;
char* PerfMemory::_top = NULL;
size_t PerfMemory::_capacity = 0;
-jint PerfMemory::_initialized = false;
+int PerfMemory::_initialized = false;
PerfDataPrologue* PerfMemory::_prologue = NULL;
bool PerfMemory::_destroyed = false;
--- a/src/hotspot/share/runtime/perfMemory.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/perfMemory.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -120,7 +120,7 @@
static char* _top;
static size_t _capacity;
static PerfDataPrologue* _prologue;
- static jint _initialized;
+ static int _initialized;
static bool _destroyed;
static void create_memory_region(size_t sizep);
--- a/src/hotspot/share/runtime/reflection.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/reflection.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/javaClasses.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
@@ -38,7 +39,6 @@
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "prims/jvmtiExport.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
--- a/src/hotspot/share/runtime/rframe.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/rframe.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -155,7 +155,7 @@
void RFrame::print(const char* kind) {
#ifndef PRODUCT
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
int cnt = top_method()->interpreter_invocation_count();
#else
int cnt = top_method()->invocation_count();
--- a/src/hotspot/share/runtime/safepoint.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/safepoint.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/classLoaderData.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
@@ -618,6 +619,14 @@
ClassLoaderDataGraph::purge_if_needed();
event_safepoint_cleanup_task_commit(event, name);
}
+
+ if (!_subtasks.is_task_claimed(SafepointSynchronize::SAFEPOINT_CLEANUP_SYSTEM_DICTIONARY_RESIZE)) {
+ const char* name = "resizing system dictionaries";
+ EventSafepointCleanupTask event;
+ TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup));
+ ClassLoaderDataGraph::resize_if_needed();
+ event_safepoint_cleanup_task_commit(event, name);
+ }
_subtasks.all_tasks_completed(_num_workers);
}
};
--- a/src/hotspot/share/runtime/safepoint.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/safepoint.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -83,6 +83,7 @@
SAFEPOINT_CLEANUP_SYMBOL_TABLE_REHASH,
SAFEPOINT_CLEANUP_STRING_TABLE_REHASH,
SAFEPOINT_CLEANUP_CLD_PURGE,
+ SAFEPOINT_CLEANUP_SYSTEM_DICTIONARY_RESIZE,
// Leave this one last.
SAFEPOINT_CLEANUP_NUM_TASKS
};
--- a/src/hotspot/share/runtime/sharedRuntime.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "aot/aotLoader.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
@@ -45,7 +46,6 @@
#include "oops/objArrayKlass.hpp"
#include "oops/oop.inline.hpp"
#include "prims/forte.hpp"
-#include "prims/jvm.h"
#include "prims/jvmtiExport.hpp"
#include "prims/methodHandles.hpp"
#include "prims/nativeLookup.hpp"
@@ -102,13 +102,13 @@
_resolve_static_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C), "resolve_static_call");
_resolve_static_call_entry = _resolve_static_call_blob->entry_point();
-#if defined(COMPILER2) || INCLUDE_JVMCI
+#if COMPILER2_OR_JVMCI
// Vectors are generated only by C2 and JVMCI.
bool support_wide = is_wide_vector(MaxVectorSize);
if (support_wide) {
_polling_page_vectors_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_VECTOR_LOOP);
}
-#endif // COMPILER2 || INCLUDE_JVMCI
+#endif // COMPILER2_OR_JVMCI
_polling_page_safepoint_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_LOOP);
_polling_page_return_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_RETURN);
--- a/src/hotspot/share/runtime/stackValue.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/stackValue.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -191,12 +191,12 @@
void StackValue::print_on(outputStream* st) const {
switch(_type) {
case T_INT:
- st->print("%d (int) %f (float) %x (hex)", *(int *)&_i, *(float *)&_i, *(int *)&_i);
+ st->print("%d (int) %f (float) %x (hex)", *(int *)&_integer_value, *(float *)&_integer_value, *(int *)&_integer_value);
break;
case T_OBJECT:
- _o()->print_value_on(st);
- st->print(" <" INTPTR_FORMAT ">", p2i((address)_o()));
+ _handle_value()->print_value_on(st);
+ st->print(" <" INTPTR_FORMAT ">", p2i((address)_handle_value()));
break;
case T_CONFLICT:
--- a/src/hotspot/share/runtime/stackValue.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/stackValue.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -31,63 +31,63 @@
class StackValue : public ResourceObj {
private:
BasicType _type;
- intptr_t _i; // Blank java stack slot value
- Handle _o; // Java stack slot value interpreted as a Handle
+ intptr_t _integer_value; // Blank java stack slot value
+ Handle _handle_value; // Java stack slot value interpreted as a Handle
public:
StackValue(intptr_t value) {
- _type = T_INT;
- _i = value;
+ _type = T_INT;
+ _integer_value = value;
}
StackValue(Handle value, intptr_t scalar_replaced = 0) {
- _type = T_OBJECT;
- _i = scalar_replaced;
- _o = value;
- assert(_i == 0 || _o.is_null(), "not null object should not be marked as scalar replaced");
+ _type = T_OBJECT;
+ _integer_value = scalar_replaced;
+ _handle_value = value;
+ assert(_integer_value == 0 || _handle_value.is_null(), "not null object should not be marked as scalar replaced");
}
StackValue() {
- _type = T_CONFLICT;
- _i = 0;
+ _type = T_CONFLICT;
+ _integer_value = 0;
}
// Only used during deopt- preserve object type.
StackValue(intptr_t o, BasicType t) {
assert(t == T_OBJECT, "should not be used");
- _type = t;
- _i = o;
+ _type = t;
+ _integer_value = o;
}
Handle get_obj() const {
assert(type() == T_OBJECT, "type check");
- return _o;
+ return _handle_value;
}
bool obj_is_scalar_replaced() const {
assert(type() == T_OBJECT, "type check");
- return _i != 0;
+ return _integer_value != 0;
}
void set_obj(Handle value) {
assert(type() == T_OBJECT, "type check");
- _o = value;
+ _handle_value = value;
}
intptr_t get_int() const {
assert(type() == T_INT, "type check");
- return _i;
+ return _integer_value;
}
// For special case in deopt.
intptr_t get_int(BasicType t) const {
assert(t == T_OBJECT && type() == T_OBJECT, "type check");
- return _i;
+ return _integer_value;
}
void set_int(intptr_t value) {
assert(type() == T_INT, "type check");
- _i = value;
+ _integer_value = value;
}
BasicType type() const { return _type; }
@@ -95,11 +95,11 @@
bool equal(StackValue *value) {
if (_type != value->_type) return false;
if (_type == T_OBJECT)
- return (_o == value->_o);
+ return (_handle_value == value->_handle_value);
else {
assert(_type == T_INT, "sanity check");
// [phh] compare only low addressed portions of intptr_t slots
- return (*(int *)&_i == *(int *)&value->_i);
+ return (*(int *)&_integer_value == *(int *)&value->_integer_value);
}
}
--- a/src/hotspot/share/runtime/thread.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/thread.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/classLoader.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/moduleEntry.hpp"
@@ -51,7 +52,6 @@
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "oops/verifyOopClosure.hpp"
-#include "prims/jvm.h"
#include "prims/jvm_misc.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/jvmtiThreadState.hpp"
@@ -762,7 +762,7 @@
// GC Support
bool Thread::claim_oops_do_par_case(int strong_roots_parity) {
- jint thread_parity = _oops_do_parity;
+ int thread_parity = _oops_do_parity;
if (thread_parity != strong_roots_parity) {
jint res = Atomic::cmpxchg(strong_roots_parity, &_oops_do_parity, thread_parity);
if (res == thread_parity) {
@@ -3724,7 +3724,7 @@
}
// initialize compiler(s)
-#if defined(COMPILER1) || defined(COMPILER2) || INCLUDE_JVMCI
+#if defined(COMPILER1) || COMPILER2_OR_JVMCI
CompileBroker::compilation_init(CHECK_JNI_ERR);
#endif
--- a/src/hotspot/share/runtime/thread.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/thread.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -244,7 +244,7 @@
// The parity of the last strong_roots iteration in which this thread was
// claimed as a task.
- jint _oops_do_parity;
+ int _oops_do_parity;
public:
void set_last_handle_mark(HandleMark* mark) { _last_handle_mark = mark; }
--- a/src/hotspot/share/runtime/vmStructs.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/vmStructs.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -47,6 +47,7 @@
#include "gc/parallel/immutableSpace.hpp"
#include "gc/parallel/mutableSpace.hpp"
#include "gc/serial/defNewGeneration.hpp"
+#include "gc/serial/serialHeap.hpp"
#include "gc/serial/tenuredGeneration.hpp"
#include "gc/cms/cmsHeap.hpp"
#include "gc/shared/cardTableRS.hpp"
@@ -356,7 +357,7 @@
nonstatic_field(Symbol, _length, unsigned short) \
unchecked_nonstatic_field(Symbol, _body, sizeof(jbyte)) /* NOTE: no type */ \
nonstatic_field(Symbol, _body[0], jbyte) \
- nonstatic_field(TypeArrayKlass, _max_length, int) \
+ nonstatic_field(TypeArrayKlass, _max_length, jint) \
\
/***********************/ \
/* Constant Pool Cache */ \
@@ -579,7 +580,7 @@
static_field(PerfMemory, _top, char*) \
static_field(PerfMemory, _capacity, size_t) \
static_field(PerfMemory, _prologue, PerfDataPrologue*) \
- static_field(PerfMemory, _initialized, jint) \
+ static_field(PerfMemory, _initialized, int) \
\
/***************/ \
/* SymbolTable */ \
@@ -1465,6 +1466,7 @@
declare_toplevel_type(CollectedHeap) \
declare_type(GenCollectedHeap, CollectedHeap) \
declare_type(CMSHeap, GenCollectedHeap) \
+ declare_type(SerialHeap, GenCollectedHeap) \
declare_toplevel_type(Generation) \
declare_type(DefNewGeneration, Generation) \
declare_type(CardGeneration, Generation) \
@@ -2175,6 +2177,7 @@
declare_toplevel_type(vframeArray) \
declare_toplevel_type(vframeArrayElement) \
declare_toplevel_type(Annotations*) \
+ declare_type(OopMapValue, StackObj) \
\
/***************/ \
/* Miscellaneous types */ \
@@ -2257,7 +2260,8 @@
\
declare_constant(G1SATBCardTableModRefBS::g1_young_gen) \
\
- declare_constant(CollectedHeap::GenCollectedHeap) \
+ declare_constant(CollectedHeap::SerialHeap) \
+ declare_constant(CollectedHeap::CMSHeap) \
declare_constant(CollectedHeap::ParallelScavengeHeap) \
declare_constant(CollectedHeap::G1CollectedHeap) \
\
--- a/src/hotspot/share/runtime/vm_operations.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/vm_operations.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -230,6 +230,10 @@
JNIHandles::print_on(_out);
}
+void VM_PrintMetadata::doit() {
+ MetaspaceAux::print_metadata_for_nmt(_out, _scale);
+}
+
VM_FindDeadlocks::~VM_FindDeadlocks() {
if (_deadlocks != NULL) {
DeadlockCycle* cycle = _deadlocks;
--- a/src/hotspot/share/runtime/vm_operations.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/runtime/vm_operations.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -111,6 +111,7 @@
template(ThreadsSuspendJVMTI) \
template(ICBufferFull) \
template(ScavengeMonitors) \
+ template(PrintMetadata) \
class VM_Operation: public CHeapObj<mtInternal> {
public:
@@ -374,6 +375,17 @@
void doit();
};
+class VM_PrintMetadata : public VM_Operation {
+ private:
+ outputStream* _out;
+ size_t _scale;
+ public:
+ VM_PrintMetadata(outputStream* out, size_t scale) : _out(out), _scale(scale) {};
+
+ VMOp_Type type() const { return VMOp_PrintMetadata; }
+ void doit();
+};
+
class DeadlockCycle;
class VM_FindDeadlocks: public VM_Operation {
private:
--- a/src/hotspot/share/services/diagnosticArgument.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/services/diagnosticArgument.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,9 +23,9 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "runtime/thread.hpp"
#include "services/diagnosticArgument.hpp"
--- a/src/hotspot/share/services/diagnosticCommand.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/services/diagnosticCommand.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/classLoaderStats.hpp"
#include "classfile/compactHashtable.hpp"
#include "compiler/compileBroker.hpp"
@@ -30,7 +31,6 @@
#include "gc/shared/vmGCOperations.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/globals.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/os.hpp"
--- a/src/hotspot/share/services/diagnosticFramework.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/services/diagnosticFramework.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,10 +23,10 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/javaCalls.hpp"
#include "runtime/mutexLocker.hpp"
#include "services/diagnosticArgument.hpp"
--- a/src/hotspot/share/services/heapDumper.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/services/heapDumper.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
@@ -34,7 +35,6 @@
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/javaCalls.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/os.hpp"
--- a/src/hotspot/share/services/mallocSiteTable.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/services/mallocSiteTable.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -235,8 +235,8 @@
void MallocSiteTable::AccessLock::exclusiveLock() {
- jint target;
- jint val;
+ int target;
+ int val;
assert(_lock_state != ExclusiveLock, "Can only call once");
assert(*_lock >= 0, "Can not content exclusive lock");
--- a/src/hotspot/share/services/memTracker.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/services/memTracker.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,8 +22,8 @@
*
*/
#include "precompiled.hpp"
+#include "jvm.h"
-#include "prims/jvm.h"
#include "runtime/mutex.hpp"
#include "services/memBaseline.hpp"
#include "services/memReporter.hpp"
--- a/src/hotspot/share/services/memoryService.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/services/memoryService.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -86,7 +86,7 @@
void MemoryService::set_universe_heap(CollectedHeap* heap) {
CollectedHeap::Name kind = heap->kind();
switch (kind) {
- case CollectedHeap::GenCollectedHeap :
+ case CollectedHeap::SerialHeap :
case CollectedHeap::CMSHeap : {
add_gen_collected_heap_info(GenCollectedHeap::heap());
break;
--- a/src/hotspot/share/services/nmtDCmd.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/services/nmtDCmd.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,8 @@
#include "precompiled.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/mutexLocker.hpp"
+#include "runtime/vmThread.hpp"
+#include "runtime/vm_operations.hpp"
#include "services/nmtDCmd.hpp"
#include "services/memReporter.hpp"
#include "services/memTracker.hpp"
@@ -38,6 +40,8 @@
_detail("detail", "request runtime to report memory allocation >= "
"1K by each callsite.",
"BOOLEAN", false, "false"),
+ _metadata("metadata", "request runtime to report metadata information",
+ "BOOLEAN", false, "false"),
_baseline("baseline", "request runtime to baseline current memory usage, " \
"so it can be compared against in later time.",
"BOOLEAN", false, "false"),
@@ -57,6 +61,7 @@
"STRING", false, "KB") {
_dcmdparser.add_dcmd_option(&_summary);
_dcmdparser.add_dcmd_option(&_detail);
+ _dcmdparser.add_dcmd_option(&_metadata);
_dcmdparser.add_dcmd_option(&_baseline);
_dcmdparser.add_dcmd_option(&_summary_diff);
_dcmdparser.add_dcmd_option(&_detail_diff);
@@ -92,6 +97,7 @@
int nopt = 0;
if (_summary.is_set() && _summary.value()) { ++nopt; }
if (_detail.is_set() && _detail.value()) { ++nopt; }
+ if (_metadata.is_set() && _metadata.value()) { ++nopt; }
if (_baseline.is_set() && _baseline.value()) { ++nopt; }
if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; }
if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; }
@@ -100,7 +106,7 @@
if (nopt > 1) {
output()->print_cr("At most one of the following option can be specified: " \
- "summary, detail, baseline, summary.diff, detail.diff, shutdown");
+ "summary, detail, metadata, baseline, summary.diff, detail.diff, shutdown");
return;
} else if (nopt == 0) {
if (_summary.is_set()) {
@@ -118,9 +124,13 @@
report(true, scale_unit);
} else if (_detail.value()) {
if (!check_detail_tracking_level(output())) {
- return;
- }
+ return;
+ }
report(false, scale_unit);
+ } else if (_metadata.value()) {
+ size_t scale = get_scale(_scale.value());
+ VM_PrintMetadata op(output(), scale);
+ VMThread::execute(&op);
} else if (_baseline.value()) {
MemBaseline& baseline = MemTracker::get_baseline();
if (!baseline.baseline(MemTracker::tracking_level() != NMT_detail)) {
--- a/src/hotspot/share/services/nmtDCmd.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/services/nmtDCmd.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -39,6 +39,7 @@
protected:
DCmdArgument<bool> _summary;
DCmdArgument<bool> _detail;
+ DCmdArgument<bool> _metadata;
DCmdArgument<bool> _baseline;
DCmdArgument<bool> _summary_diff;
DCmdArgument<bool> _detail_diff;
--- a/src/hotspot/share/trace/traceMacros.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/trace/traceMacros.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -41,6 +41,8 @@
#define TRACE_REGISTER_NATIVES ((void*)((address_word)(&trace_register_natives)))
#define TRACE_START() JNI_OK
#define TRACE_INITIALIZE() JNI_OK
+#define TRACE_ALLOCATION(obj, size, thread)
+#define TRACE_WEAK_OOPS_DO(is_alive, f)
#define TRACE_VM_EXIT()
#define TRACE_VM_ERROR()
#define TRACE_SUSPEND_THREAD(t)
--- a/src/hotspot/share/trace/traceevents.xml Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/trace/traceevents.xml Thu Nov 16 10:45:42 2017 -0800
@@ -108,6 +108,7 @@
description="Revoked bias of object" has_thread="true" has_stacktrace="true" is_instant="false">
<value type="CLASS" field="lockClass" label="Lock Class" description="Class of object whose biased lock was revoked"/>
<value type="INTEGER" field="safepointId" label="Safepoint Identifier" relation="SafepointId"/>
+ <value type="THREAD" field="previousOwner" label="Previous Owner" description="Thread owning the bias before revocation"/>
</event>
<event id="BiasedLockSelfRevocation" path="java/biased_lock_self_revocation" label="Biased Lock Self Revocation"
--- a/src/hotspot/share/utilities/accessFlags.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/accessFlags.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -25,8 +25,8 @@
#ifndef SHARE_VM_UTILITIES_ACCESSFLAGS_HPP
#define SHARE_VM_UTILITIES_ACCESSFLAGS_HPP
+#include "jvm.h"
#include "memory/allocation.hpp"
-#include "prims/jvm.h"
#include "utilities/macros.hpp"
// AccessFlags is an abstraction over Java access flags.
--- a/src/hotspot/share/utilities/constantTag.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/constantTag.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -25,8 +25,8 @@
#ifndef SHARE_VM_UTILITIES_CONSTANTTAG_HPP
#define SHARE_VM_UTILITIES_CONSTANTTAG_HPP
+#include "jvm.h"
#include "memory/allocation.hpp"
-#include "prims/jvm.h"
// constant tags in Java .class files
--- a/src/hotspot/share/utilities/debug.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/debug.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "code/icBuffer.hpp"
@@ -36,7 +37,6 @@
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "prims/privilegedStack.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
@@ -276,7 +276,7 @@
}
void report_java_out_of_memory(const char* message) {
- static jint out_of_memory_reported = 0;
+ static int out_of_memory_reported = 0;
// A number of threads may attempt to report OutOfMemoryError at around the
// same time. To avoid dumping the heap or executing the data collection
--- a/src/hotspot/share/utilities/decoder.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/decoder.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "prims/jvm.h"
+#include "jvm.h"
#include "runtime/os.hpp"
#include "utilities/decoder.hpp"
#include "utilities/vmError.hpp"
--- a/src/hotspot/share/utilities/elfStringTable.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/elfStringTable.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -26,8 +26,8 @@
#if !defined(_WINDOWS) && !defined(__APPLE__)
+#include "jvm.h"
#include "memory/allocation.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/os.hpp"
#include "utilities/elfStringTable.hpp"
--- a/src/hotspot/share/utilities/formatBuffer.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/formatBuffer.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,8 +23,8 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "memory/allocation.hpp"
-#include "prims/jvm.h"
#include "utilities/formatBuffer.hpp"
#include <stdarg.h>
--- a/src/hotspot/share/utilities/formatBuffer.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/formatBuffer.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -25,8 +25,8 @@
#ifndef SHARE_VM_UTILITIES_FORMATBUFFER_HPP
#define SHARE_VM_UTILITIES_FORMATBUFFER_HPP
+#include "jvm.h"
#include "utilities/globalDefinitions.hpp"
-#include "prims/jvm.h"
#include <stdarg.h>
// Simple class to format the ctor arguments into a fixed-sized buffer.
--- a/src/hotspot/share/utilities/globalDefinitions_xlc.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/globalDefinitions_xlc.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -86,6 +86,7 @@
// In this case you need to copy the following defines to a position after #include <dirent.h>
// (see jmv_aix.h).
#ifdef AIX
+ #include <dirent.h>
#ifdef _LP64
#undef NULL
#define NULL 0L
--- a/src/hotspot/share/utilities/growableArray.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/growableArray.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -402,7 +402,7 @@
// matching key according to the static compare function. Insert
// that element is not already in the list. Assumes the list is
// already sorted according to compare function.
- template <int compare(const E&, const E&)> E insert_sorted(E& key) {
+ template <int compare(const E&, const E&)> E insert_sorted(const E& key) {
bool found;
int location = find_sorted<E, compare>(key, found);
if (!found) {
--- a/src/hotspot/share/utilities/hashtable.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/hashtable.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -264,6 +264,49 @@
}
}
+template <MEMFLAGS F> bool BasicHashtable<F>::resize(int new_size) {
+ assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+
+ // Allocate new buckets
+ HashtableBucket<F>* buckets_new = NEW_C_HEAP_ARRAY2_RETURN_NULL(HashtableBucket<F>, new_size, F, CURRENT_PC);
+ if (buckets_new == NULL) {
+ return false;
+ }
+
+ // Clear the new buckets
+ for (int i = 0; i < new_size; i++) {
+ buckets_new[i].clear();
+ }
+
+ int table_size_old = _table_size;
+ // hash_to_index() uses _table_size, so switch the sizes now
+ _table_size = new_size;
+
+ // Move entries from the old table to a new table
+ for (int index_old = 0; index_old < table_size_old; index_old++) {
+ for (BasicHashtableEntry<F>* p = _buckets[index_old].get_entry(); p != NULL; ) {
+ BasicHashtableEntry<F>* next = p->next();
+ bool keep_shared = p->is_shared();
+ int index_new = hash_to_index(p->hash());
+
+ p->set_next(buckets_new[index_new].get_entry());
+ buckets_new[index_new].set_entry(p);
+
+ if (keep_shared) {
+ p->set_shared();
+ }
+ p = next;
+ }
+ }
+
+ // The old backets now can be released
+ BasicHashtable<F>::free_buckets();
+
+ // Switch to the new storage
+ _buckets = buckets_new;
+
+ return true;
+}
// Dump footprint and bucket length statistics
//
--- a/src/hotspot/share/utilities/hashtable.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/hashtable.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -237,6 +237,8 @@
int number_of_entries() const { return _number_of_entries; }
+ bool resize(int new_size);
+
template <class T> void verify_table(const char* table_name) PRODUCT_RETURN;
};
@@ -281,7 +283,6 @@
HashtableEntry<T, F>** bucket_addr(int i) {
return (HashtableEntry<T, F>**)BasicHashtable<F>::bucket_addr(i);
}
-
};
template <class T, MEMFLAGS F> class RehashableHashtable : public Hashtable<T, F> {
--- a/src/hotspot/share/utilities/macros.hpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/macros.hpp Thu Nov 16 10:45:42 2017 -0800
@@ -322,7 +322,9 @@
#endif
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+#ifndef BSD
#define BSD
+#endif // BSD defined in <sys/param.h>
#define BSD_ONLY(code) code
#define NOT_BSD(code)
#else
--- a/src/hotspot/share/utilities/ostream.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/ostream.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,9 +23,9 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "compiler/compileLog.hpp"
#include "oops/oop.inline.hpp"
-#include "prims/jvm.h"
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
#include "runtime/vm_version.hpp"
--- a/src/hotspot/share/utilities/vmError.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/src/hotspot/share/utilities/vmError.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -23,12 +23,12 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "code/codeCache.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "logging/logConfiguration.hpp"
-#include "prims/jvm.h"
#include "prims/whitebox.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
--- a/src/java.base/macosx/native/include/jni_md.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 1996, 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. 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.
- */
-
-#ifndef _JAVASOFT_JNI_MD_H_
-#define _JAVASOFT_JNI_MD_H_
-
-#define JNIEXPORT __attribute__((visibility("default")))
-#define JNIIMPORT __attribute__((visibility("default")))
-#define JNICALL
-
-typedef int jint;
-#ifdef _LP64 /* 64-bit */
-typedef long jlong;
-#else
-typedef long long jlong;
-#endif
-
-typedef signed char jbyte;
-
-#endif /* !_JAVASOFT_JNI_MD_H_ */
--- a/src/java.base/macosx/native/include/jvm_md.h Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 1997, 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. 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.
- */
-
-#ifndef _JAVASOFT_JVM_MD_H_
-#define _JAVASOFT_JVM_MD_H_
-
-/*
- * This file is currently collecting system-specific dregs for the
- * JNI conversion, which should be sorted out later.
- */
-
-#include <dirent.h> /* For DIR */
-#include <sys/param.h> /* For MAXPATHLEN */
-#include <unistd.h> /* For F_OK, R_OK, W_OK */
-#include <stddef.h> /* For ptrdiff_t */
-#include <stdint.h> /* For uintptr_t */
-
-#define JNI_ONLOAD_SYMBOLS {"JNI_OnLoad"}
-#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"}
-
-#define JNI_LIB_PREFIX "lib"
-#define JNI_LIB_SUFFIX ".dylib"
-#define VERSIONED_JNI_LIB_NAME(NAME, VERSION) JNI_LIB_PREFIX NAME "." VERSION JNI_LIB_SUFFIX
-#define JNI_LIB_NAME(NAME) JNI_LIB_PREFIX NAME JNI_LIB_SUFFIX
-
-#define JVM_MAXPATHLEN MAXPATHLEN
-
-#define JVM_R_OK R_OK
-#define JVM_W_OK W_OK
-#define JVM_X_OK X_OK
-#define JVM_F_OK F_OK
-
-/*
- * File I/O
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-
-/* O Flags */
-
-#define JVM_O_RDONLY O_RDONLY
-#define JVM_O_WRONLY O_WRONLY
-#define JVM_O_RDWR O_RDWR
-#define JVM_O_O_APPEND O_APPEND
-#define JVM_O_EXCL O_EXCL
-#define JVM_O_CREAT O_CREAT
-
-/* Signals */
-
-#define JVM_SIGINT SIGINT
-#define JVM_SIGTERM SIGTERM
-
-
-#endif /* !_JAVASOFT_JVM_MD_H_ */
--- a/src/java.base/share/classes/java/lang/StackFrameInfo.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/lang/StackFrameInfo.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -32,14 +32,12 @@
import java.lang.invoke.MethodType;
class StackFrameInfo implements StackFrame {
+ private final byte RETAIN_CLASS_REF = 0x01;
+
private final static JavaLangInvokeAccess JLIA =
SharedSecrets.getJavaLangInvokeAccess();
- // Footprint improvement: MemberName::clazz can replace
- // StackFrameInfo::declaringClass.
-
- private final StackWalker walker;
- private final Class<?> declaringClass;
+ private final byte flags;
private final Object memberName;
private final short bci;
private volatile StackTraceElement ste;
@@ -49,8 +47,7 @@
* to use
*/
StackFrameInfo(StackWalker walker) {
- this.walker = walker;
- this.declaringClass = null;
+ this.flags = walker.retainClassRef ? RETAIN_CLASS_REF : 0;
this.bci = -1;
this.memberName = JLIA.newMemberName();
}
@@ -58,20 +55,20 @@
// package-private called by StackStreamFactory to skip
// the capability check
Class<?> declaringClass() {
- return declaringClass;
+ return JLIA.getDeclaringClass(memberName);
}
// ----- implementation of StackFrame methods
@Override
public String getClassName() {
- return declaringClass.getName();
+ return declaringClass().getName();
}
@Override
public Class<?> getDeclaringClass() {
- walker.ensureAccessEnabled(RETAIN_CLASS_REFERENCE);
- return declaringClass;
+ ensureRetainClassRefEnabled();
+ return declaringClass();
}
@Override
@@ -81,7 +78,7 @@
@Override
public MethodType getMethodType() {
- walker.ensureAccessEnabled(RETAIN_CLASS_REFERENCE);
+ ensureRetainClassRefEnabled();
return JLIA.getMethodType(memberName);
}
@@ -137,4 +134,10 @@
}
return s;
}
+
+ private void ensureRetainClassRefEnabled() {
+ if ((flags & RETAIN_CLASS_REF) == 0) {
+ throw new UnsupportedOperationException("No access to RETAIN_CLASS_REFERENCE");
+ }
+ }
}
--- a/src/java.base/share/classes/java/lang/StackWalker.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/lang/StackWalker.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -296,6 +296,7 @@
private final Set<Option> options;
private final ExtendedOption extendedOption;
private final int estimateDepth;
+ final boolean retainClassRef; // cached for performance
/**
* Returns a {@code StackWalker} instance.
@@ -412,6 +413,7 @@
this.options = options;
this.estimateDepth = estimateDepth;
this.extendedOption = extendedOption;
+ this.retainClassRef = hasOption(Option.RETAIN_CLASS_REFERENCE);
}
private static void checkPermission(Set<Option> options) {
@@ -590,7 +592,7 @@
*/
@CallerSensitive
public Class<?> getCallerClass() {
- if (!options.contains(Option.RETAIN_CLASS_REFERENCE)) {
+ if (!retainClassRef) {
throw new UnsupportedOperationException("This stack walker " +
"does not have RETAIN_CLASS_REFERENCE access");
}
@@ -617,11 +619,4 @@
boolean hasLocalsOperandsOption() {
return extendedOption == ExtendedOption.LOCALS_AND_OPERANDS;
}
-
- void ensureAccessEnabled(Option access) {
- if (!hasOption(access)) {
- throw new UnsupportedOperationException("No access to " + access +
- ": " + options.toString());
- }
- }
}
--- a/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java Thu Nov 16 10:45:42 2017 -0800
@@ -25,25 +25,21 @@
package java.lang.invoke;
-import jdk.internal.loader.BootLoader;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.FieldVisitor;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.vm.annotation.Stable;
import sun.invoke.util.ValueConversions;
-import sun.invoke.util.Wrapper;
-import java.lang.invoke.LambdaForm.NamedFunction;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.lang.reflect.Field;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.function.Function;
+import java.util.ArrayList;
+import java.util.List;
import static java.lang.invoke.LambdaForm.BasicType;
import static java.lang.invoke.LambdaForm.BasicType.*;
-import static java.lang.invoke.MethodHandleStatics.*;
-import static jdk.internal.org.objectweb.asm.Opcodes.*;
+import static java.lang.invoke.LambdaForm.BasicType.V_TYPE_NUM;
+import static java.lang.invoke.LambdaForm.BasicType.V_TYPE_NUM;
+import static java.lang.invoke.LambdaForm.BasicType.V_TYPE_NUM;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandleStatics.newInternalError;
+import static java.lang.invoke.MethodHandleStatics.uncaughtException;
/**
* The flavor of method handle which emulates an invoke instruction
@@ -56,7 +52,7 @@
/*non-public*/ BoundMethodHandle(MethodType type, LambdaForm form) {
super(type, form);
- assert(speciesData() == speciesData(form));
+ assert(speciesData() == speciesDataFor(form));
}
//
@@ -70,13 +66,13 @@
case L_TYPE:
return bindSingle(type, form, x); // Use known fast path.
case I_TYPE:
- return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor().invokeBasic(type, form, ValueConversions.widenSubword(x));
+ return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(I_TYPE_NUM).factory().invokeBasic(type, form, ValueConversions.widenSubword(x));
case J_TYPE:
- return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor().invokeBasic(type, form, (long) x);
+ return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(J_TYPE_NUM).factory().invokeBasic(type, form, (long) x);
case F_TYPE:
- return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor().invokeBasic(type, form, (float) x);
+ return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(F_TYPE_NUM).factory().invokeBasic(type, form, (float) x);
case D_TYPE:
- return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor().invokeBasic(type, form, (double) x);
+ return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(D_TYPE_NUM).factory().invokeBasic(type, form, (double) x);
default : throw newInternalError("unexpected xtype: " + xtype);
}
} catch (Throwable t) {
@@ -98,6 +94,7 @@
BoundMethodHandle bindArgumentL(int pos, Object value) {
return editor().bindArgumentL(this, pos, value);
}
+
/*non-public*/
BoundMethodHandle bindArgumentI(int pos, int value) {
return editor().bindArgumentI(this, pos, value);
@@ -114,7 +111,6 @@
BoundMethodHandle bindArgumentD(int pos, double value) {
return editor().bindArgumentD(this, pos, value);
}
-
@Override
BoundMethodHandle rebind() {
if (!tooComplex()) {
@@ -137,28 +133,29 @@
static BoundMethodHandle makeReinvoker(MethodHandle target) {
LambdaForm form = DelegatingMethodHandle.makeReinvokerForm(
target, MethodTypeForm.LF_REBIND,
- Species_L.SPECIES_DATA, Species_L.SPECIES_DATA.getterFunction(0));
+ Species_L.BMH_SPECIES, Species_L.BMH_SPECIES.getterFunction(0));
return Species_L.make(target.type(), form, target);
}
/**
- * Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
+ * Return the {@link BoundMethodHandle.SpeciesData} instance representing this BMH species. All subclasses must provide a
* static field containing this value, and they must accordingly implement this method.
*/
- /*non-public*/ abstract SpeciesData speciesData();
+ /*non-public*/ abstract BoundMethodHandle.SpeciesData speciesData();
- /*non-public*/ static SpeciesData speciesData(LambdaForm form) {
+ /*non-public*/ static BoundMethodHandle.SpeciesData speciesDataFor(LambdaForm form) {
Object c = form.names[0].constraint;
- if (c instanceof SpeciesData)
+ if (c instanceof SpeciesData) {
return (SpeciesData) c;
+ }
// if there is no BMH constraint, then use the null constraint
- return SpeciesData.EMPTY;
+ return SPECIALIZER.topSpecies();
}
/**
* Return the number of fields in this BMH. Equivalent to speciesData().fieldCount().
*/
- /*non-public*/ abstract int fieldCount();
+ /*non-public*/ final int fieldCount() { return speciesData().fieldCount(); }
@Override
Object internalProperties() {
@@ -167,7 +164,7 @@
@Override
final String internalValues() {
- int count = speciesData().fieldCount();
+ int count = fieldCount();
if (count == 1) {
return "[" + arg(0) + "]";
}
@@ -180,17 +177,18 @@
/*non-public*/ final Object arg(int i) {
try {
- switch (speciesData().fieldType(i)) {
- case L_TYPE: return speciesData().getters[i].invokeBasic(this);
- case I_TYPE: return (int) speciesData().getters[i].invokeBasic(this);
- case J_TYPE: return (long) speciesData().getters[i].invokeBasic(this);
- case F_TYPE: return (float) speciesData().getters[i].invokeBasic(this);
- case D_TYPE: return (double) speciesData().getters[i].invokeBasic(this);
+ Class<?> fieldType = speciesData().fieldTypes().get(i);
+ switch (BasicType.basicType(fieldType)) {
+ case L_TYPE: return speciesData().getter(i).invokeBasic(this);
+ case I_TYPE: return (int) speciesData().getter(i).invokeBasic(this);
+ case J_TYPE: return (long) speciesData().getter(i).invokeBasic(this);
+ case F_TYPE: return (float) speciesData().getter(i).invokeBasic(this);
+ case D_TYPE: return (double) speciesData().getter(i).invokeBasic(this);
}
} catch (Throwable ex) {
throw uncaughtException(ex);
}
- throw new InternalError("unexpected type: " + speciesData().typeChars+"."+i);
+ throw new InternalError("unexpected type: " + speciesData().key()+"."+i);
}
//
@@ -210,20 +208,21 @@
private // make it private to force users to access the enclosing class first
static final class Species_L extends BoundMethodHandle {
+
final Object argL0;
+
private Species_L(MethodType mt, LambdaForm lf, Object argL0) {
super(mt, lf);
this.argL0 = argL0;
}
+
@Override
/*non-public*/ SpeciesData speciesData() {
- return SPECIES_DATA;
+ return BMH_SPECIES;
}
- @Override
- /*non-public*/ int fieldCount() {
- return 1;
- }
- /*non-public*/ static final SpeciesData SPECIES_DATA = new SpeciesData("L", Species_L.class);
+
+ /*non-public*/ static @Stable SpeciesData BMH_SPECIES;
+
/*non-public*/ static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0) {
return new Species_L(mt, lf, argL0);
}
@@ -234,7 +233,7 @@
@Override
/*non-public*/ final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
try {
- return (BoundMethodHandle) SPECIES_DATA.extendWith(L_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
+ return (BoundMethodHandle) BMH_SPECIES.extendWith(L_TYPE_NUM).factory().invokeBasic(mt, lf, argL0, narg);
} catch (Throwable ex) {
throw uncaughtException(ex);
}
@@ -242,7 +241,7 @@
@Override
/*non-public*/ final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
try {
- return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
+ return (BoundMethodHandle) BMH_SPECIES.extendWith(I_TYPE_NUM).factory().invokeBasic(mt, lf, argL0, narg);
} catch (Throwable ex) {
throw uncaughtException(ex);
}
@@ -250,7 +249,7 @@
@Override
/*non-public*/ final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
try {
- return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
+ return (BoundMethodHandle) BMH_SPECIES.extendWith(J_TYPE_NUM).factory().invokeBasic(mt, lf, argL0, narg);
} catch (Throwable ex) {
throw uncaughtException(ex);
}
@@ -258,7 +257,7 @@
@Override
/*non-public*/ final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
try {
- return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
+ return (BoundMethodHandle) BMH_SPECIES.extendWith(F_TYPE_NUM).factory().invokeBasic(mt, lf, argL0, narg);
} catch (Throwable ex) {
throw uncaughtException(ex);
}
@@ -266,7 +265,7 @@
@Override
/*non-public*/ final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
try {
- return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
+ return (BoundMethodHandle) BMH_SPECIES.extendWith(D_TYPE_NUM).factory().invokeBasic(mt, lf, argL0, narg);
} catch (Throwable ex) {
throw uncaughtException(ex);
}
@@ -277,601 +276,177 @@
// BMH species meta-data
//
- /**
- * Meta-data wrapper for concrete BMH types.
- * Each BMH type corresponds to a given sequence of basic field types (LIJFD).
- * The fields are immutable; their values are fully specified at object construction.
- * Each BMH type supplies an array of getter functions which may be used in lambda forms.
- * A BMH is constructed by cloning a shorter BMH and adding one or more new field values.
- * The shortest possible BMH has zero fields; its class is SimpleMethodHandle.
- * BMH species are not interrelated by subtyping, even though it would appear that
- * a shorter BMH could serve as a supertype of a longer one which extends it.
- */
- static class SpeciesData {
- private final String typeChars;
- private final BasicType[] typeCodes;
- private final Class<? extends BoundMethodHandle> clazz;
- // Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH
- // Therefore, we need a non-final link in the chain. Use array elements.
- @Stable private final MethodHandle[] constructor;
- @Stable private final MethodHandle[] getters;
- @Stable private final NamedFunction[] nominalGetters;
- @Stable private final SpeciesData[] extensions;
+ /*non-public*/
+ static final class SpeciesData extends ClassSpecializer<BoundMethodHandle, String, SpeciesData>.SpeciesData {
+ // This array is filled in lazily, as new species come into being over time.
+ @Stable final private SpeciesData[] extensions = new SpeciesData[ARG_TYPE_LIMIT];
- /*non-public*/ int fieldCount() {
- return typeCodes.length;
- }
- /*non-public*/ BasicType fieldType(int i) {
- return typeCodes[i];
- }
- /*non-public*/ char fieldTypeChar(int i) {
- return typeChars.charAt(i);
+ public SpeciesData(Specializer outer, String key) {
+ outer.super(key);
}
- String fieldSignature() {
- return typeChars;
- }
- public Class<? extends BoundMethodHandle> fieldHolder() {
- return clazz;
- }
- public String toString() {
- return "SpeciesData<"+fieldSignature()+">";
+
+ @Override
+ protected String deriveClassName() {
+ String typeString = deriveTypeString();
+ if (typeString.isEmpty()) {
+ return SimpleMethodHandle.class.getName();
+ }
+ return BoundMethodHandle.class.getName() + "$Species_" + typeString;
}
- /**
- * Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that
- * represents a MH bound to a generic invoker, which in turn forwards to the corresponding
- * getter.
- */
- NamedFunction getterFunction(int i) {
- NamedFunction nf = nominalGetters[i];
- assert(nf.memberDeclaringClassOrNull() == fieldHolder());
- assert(nf.returnType() == fieldType(i));
- return nf;
- }
-
- NamedFunction[] getterFunctions() {
- return nominalGetters;
- }
-
- MethodHandle[] getterHandles() { return getters; }
-
- MethodHandle constructor() {
- return constructor[0];
+ @Override
+ protected List<Class<?>> deriveFieldTypes(String key) {
+ ArrayList<Class<?>> types = new ArrayList<>(key.length());
+ for (int i = 0; i < key.length(); i++) {
+ types.add(basicType(key.charAt(i)).basicTypeClass());
+ }
+ return types;
}
- static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
-
- SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
- this.typeChars = types;
- this.typeCodes = basicTypes(types);
- this.clazz = clazz;
- if (!INIT_DONE) {
- this.constructor = new MethodHandle[1]; // only one ctor
- this.getters = new MethodHandle[types.length()];
- this.nominalGetters = new NamedFunction[types.length()];
- } else {
- this.constructor = Factory.makeCtors(clazz, types, null);
- this.getters = Factory.makeGetters(clazz, types, null);
- this.nominalGetters = Factory.makeNominalGetters(types, null, this.getters);
- }
- this.extensions = new SpeciesData[ARG_TYPE_LIMIT];
+ @Override
+ protected String deriveTypeString() {
+ // (If/when we have to add nominal types, just inherit the more complex default.)
+ return key();
}
- private void initForBootstrap() {
- assert(!INIT_DONE);
- if (constructor() == null) {
- String types = typeChars;
- CACHE.put(types, this);
- Factory.makeCtors(clazz, types, this.constructor);
- Factory.makeGetters(clazz, types, this.getters);
- Factory.makeNominalGetters(types, this.nominalGetters, this.getters);
+ @Override
+ protected MethodHandle deriveTransformHelper(MemberName transform, int whichtm) {
+ if (whichtm == Specializer.TN_COPY_NO_EXTEND) {
+ return factory();
+ } else if (whichtm < ARG_TYPE_LIMIT) {
+ return extendWith((byte) whichtm).factory();
+ } else {
+ throw newInternalError("bad transform");
}
}
- private static final ConcurrentMap<String, SpeciesData> CACHE = new ConcurrentHashMap<>();
- private static final boolean INIT_DONE; // set after <clinit> finishes...
-
- SpeciesData extendWith(byte type) {
- return extendWith(BasicType.basicType(type));
- }
-
- SpeciesData extendWith(BasicType type) {
- int ord = type.ordinal();
- SpeciesData d = extensions[ord];
- if (d != null) return d;
- extensions[ord] = d = get(typeChars+type.basicTypeChar());
- return d;
+ @Override
+ protected <X> List<X> deriveTransformHelperArguments(MemberName transform, int whichtm, List<X> args, List<X> fields) {
+ assert(verifyTHAargs(transform, whichtm, args, fields));
+ // The rule is really simple: Keep the first two arguments
+ // the same, then put in the fields, then put any other argument.
+ args.addAll(2, fields);
+ return args;
}
- private static SpeciesData get(String types) {
- return CACHE.computeIfAbsent(types, new Function<String, SpeciesData>() {
- @Override
- public SpeciesData apply(String types) {
- Class<? extends BoundMethodHandle> bmhcl = Factory.getConcreteBMHClass(types);
- // SpeciesData instantiation may throw VirtualMachineError because of
- // code cache overflow...
- SpeciesData speciesData = new SpeciesData(types, bmhcl);
- // CHM.computeIfAbsent ensures only one SpeciesData will be set
- // successfully on the concrete BMH class if ever
- Factory.setSpeciesDataToConcreteBMHClass(bmhcl, speciesData);
- // the concrete BMH class is published via SpeciesData instance
- // returned here only after it's SPECIES_DATA field is set
- return speciesData;
- }
- });
- }
-
- /**
- * This is to be called when assertions are enabled. It checks whether SpeciesData for all of the statically
- * defined species subclasses of BoundMethodHandle has been added to the SpeciesData cache. See below in the
- * static initializer for
- */
- static boolean speciesDataCachePopulated() {
- Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
- for (Class<?> c : rootCls.getDeclaredClasses()) {
- if (rootCls.isAssignableFrom(c)) {
- final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
- SpeciesData d = Factory.getSpeciesDataFromConcreteBMHClass(cbmh);
- assert(d != null) : cbmh.getName();
- assert(d.clazz == cbmh);
- assert(CACHE.get(d.typeChars) == d);
- }
+ private boolean verifyTHAargs(MemberName transform, int whichtm, List<?> args, List<?> fields) {
+ assert(transform == Specializer.BMH_TRANSFORMS.get(whichtm));
+ assert(args.size() == transform.getMethodType().parameterCount());
+ assert(fields.size() == this.fieldCount());
+ final int MH_AND_LF = 2;
+ if (whichtm == Specializer.TN_COPY_NO_EXTEND) {
+ assert(transform.getMethodType().parameterCount() == MH_AND_LF);
+ } else if (whichtm < ARG_TYPE_LIMIT) {
+ assert(transform.getMethodType().parameterCount() == MH_AND_LF+1);
+ final BasicType type = basicType((byte) whichtm);
+ assert(transform.getParameterTypes()[MH_AND_LF] == type.basicTypeClass());
+ } else {
+ return false;
}
return true;
}
- static {
- // Pre-fill the BMH species-data cache with EMPTY and all BMH's inner subclasses.
- EMPTY.initForBootstrap();
- Species_L.SPECIES_DATA.initForBootstrap();
- // check that all static SpeciesData instances have been initialized
- assert speciesDataCachePopulated();
- // Note: Do not simplify this, because INIT_DONE must not be
- // a compile-time constant during bootstrapping.
- INIT_DONE = Boolean.TRUE;
+ /*non-public*/ SpeciesData extendWith(byte typeNum) {
+ SpeciesData sd = extensions[typeNum];
+ if (sd != null) return sd;
+ sd = SPECIALIZER.findSpecies(key() + BasicType.basicType(typeNum).basicTypeChar());
+ extensions[typeNum] = sd;
+ return sd;
}
}
- static SpeciesData getSpeciesData(String types) {
- return SpeciesData.get(types);
+ /*non-public*/
+ static final Specializer SPECIALIZER = new Specializer();
+ static {
+ SimpleMethodHandle.BMH_SPECIES = BoundMethodHandle.SPECIALIZER.findSpecies("");
+ Species_L.BMH_SPECIES = BoundMethodHandle.SPECIALIZER.findSpecies("L");
}
- /**
- * Generation of concrete BMH classes.
- *
- * A concrete BMH species is fit for binding a number of values adhering to a
- * given type pattern. Reference types are erased.
- *
- * BMH species are cached by type pattern.
- *
- * A BMH species has a number of fields with the concrete (possibly erased) types of
- * bound values. Setters are provided as an API in BMH. Getters are exposed as MHs,
- * which can be included as names in lambda forms.
- */
- static class Factory {
+ /*non-public*/
+ static final class Specializer extends ClassSpecializer<BoundMethodHandle, String, SpeciesData> {
+
+ private static final MemberName SPECIES_DATA_ACCESSOR;
- private static final String JLO_SIG = "Ljava/lang/Object;";
- private static final String MH = "java/lang/invoke/MethodHandle";
- private static final String MH_SIG = "L"+MH+";";
- private static final String BMH = "java/lang/invoke/BoundMethodHandle";
- private static final String BMH_NAME = "java.lang.invoke.BoundMethodHandle";
- private static final String BMH_SIG = "L"+BMH+";";
- private static final String SPECIES_DATA = "java/lang/invoke/BoundMethodHandle$SpeciesData";
- private static final String SPECIES_DATA_SIG = "L"+SPECIES_DATA+";";
- private static final String STABLE_SIG = "Ljdk/internal/vm/annotation/Stable;";
+ static {
+ try {
+ SPECIES_DATA_ACCESSOR = IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BoundMethodHandle.class,
+ "speciesData", MethodType.methodType(BoundMethodHandle.SpeciesData.class));
+ } catch (ReflectiveOperationException ex) {
+ throw newInternalError("Bootstrap link error", ex);
+ }
+ }
- private static final String SPECIES_PREFIX_NAME = "Species_";
- private static final String SPECIES_PREFIX_PATH = BMH + "$" + SPECIES_PREFIX_NAME;
- private static final String SPECIES_CLASS_PREFIX = BMH_NAME + "$" + SPECIES_PREFIX_NAME;
-
- private static final String BMHSPECIES_DATA_EWI_SIG = "(B)" + SPECIES_DATA_SIG;
- private static final String MYSPECIES_DATA_SIG = "()" + SPECIES_DATA_SIG;
- private static final String INT_SIG = "()I";
+ private Specializer() {
+ super( // Reified type parameters:
+ BoundMethodHandle.class, String.class, BoundMethodHandle.SpeciesData.class,
+ // Principal constructor type:
+ MethodType.methodType(void.class, MethodType.class, LambdaForm.class),
+ // Required linkage between class and species:
+ SPECIES_DATA_ACCESSOR,
+ "BMH_SPECIES",
+ BMH_TRANSFORMS);
+ }
- private static final String SIG_INCIPIT = "(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;";
+ @Override
+ protected String topSpeciesKey() {
+ return "";
+ }
- private static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" };
-
- private static final ConcurrentMap<String, Class<? extends BoundMethodHandle>> CLASS_CACHE = new ConcurrentHashMap<>();
+ @Override
+ protected BoundMethodHandle.SpeciesData newSpeciesData(String key) {
+ return new BoundMethodHandle.SpeciesData(this, key);
+ }
- /**
- * Get a concrete subclass of BMH for a given combination of bound types.
- *
- * @param types the type signature, wherein reference types are erased to 'L'
- * @return the concrete BMH class
- */
- static Class<? extends BoundMethodHandle> getConcreteBMHClass(String types) {
- // CHM.computeIfAbsent ensures generateConcreteBMHClass is called
- // only once per key.
- return CLASS_CACHE.computeIfAbsent(
- types, new Function<String, Class<? extends BoundMethodHandle>>() {
- @Override
- public Class<? extends BoundMethodHandle> apply(String types) {
- String shortTypes = LambdaForm.shortenSignature(types);
- String className = SPECIES_CLASS_PREFIX + shortTypes;
- Class<?> c = BootLoader.loadClassOrNull(className);
- if (TRACE_RESOLVE) {
- System.out.println("[BMH_RESOLVE] " + shortTypes +
- (c != null ? " (success)" : " (fail)") );
- }
- if (c != null) {
- return c.asSubclass(BoundMethodHandle.class);
- } else {
- // Not pregenerated, generate the class
- return generateConcreteBMHClass(shortTypes, types);
- }
- }
- });
+ static final List<MemberName> BMH_TRANSFORMS;
+ static final int TN_COPY_NO_EXTEND = V_TYPE_NUM;
+ static {
+ final Class<BoundMethodHandle> BMH = BoundMethodHandle.class;
+ // copyWithExtendLIJFD + copyWith
+ try {
+ BMH_TRANSFORMS = List.of(
+ IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BMH, "copyWithExtendL", MethodType.methodType(BMH, MethodType.class, LambdaForm.class, Object.class)),
+ IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BMH, "copyWithExtendI", MethodType.methodType(BMH, MethodType.class, LambdaForm.class, int.class)),
+ IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BMH, "copyWithExtendJ", MethodType.methodType(BMH, MethodType.class, LambdaForm.class, long.class)),
+ IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BMH, "copyWithExtendF", MethodType.methodType(BMH, MethodType.class, LambdaForm.class, float.class)),
+ IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BMH, "copyWithExtendD", MethodType.methodType(BMH, MethodType.class, LambdaForm.class, double.class)),
+ IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BMH, "copyWith", MethodType.methodType(BMH, MethodType.class, LambdaForm.class))
+ );
+ } catch (ReflectiveOperationException ex) {
+ throw newInternalError("Failed resolving copyWith methods", ex);
+ }
+
+ // as it happens, there is one transform per BasicType including V_TYPE
+ assert(BMH_TRANSFORMS.size() == TYPE_LIMIT);
}
/**
- * Generate a concrete subclass of BMH for a given combination of bound types.
- *
- * A concrete BMH species adheres to the following schema:
+ * Generation of concrete BMH classes.
*
- * <pre>
- * class Species_[[types]] extends BoundMethodHandle {
- * [[fields]]
- * final SpeciesData speciesData() { return SpeciesData.get("[[types]]"); }
- * }
- * </pre>
- *
- * The {@code [[types]]} signature is precisely the string that is passed to this
- * method.
- *
- * The {@code [[fields]]} section consists of one field definition per character in
- * the type signature, adhering to the naming schema described in the definition of
- * {@link #makeFieldName}.
- *
- * For example, a concrete BMH species for two reference and one integral bound values
- * would have the following shape:
+ * A concrete BMH species is fit for binding a number of values adhering to a
+ * given type pattern. Reference types are erased.
*
- * <pre>
- * class BoundMethodHandle { ... private static
- * final class Species_LLI extends BoundMethodHandle {
- * final Object argL0;
- * final Object argL1;
- * final int argI2;
- * private Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
- * super(mt, lf);
- * this.argL0 = argL0;
- * this.argL1 = argL1;
- * this.argI2 = argI2;
- * }
- * final SpeciesData speciesData() { return SPECIES_DATA; }
- * final int fieldCount() { return 3; }
- * @Stable static SpeciesData SPECIES_DATA; // injected afterwards
- * static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
- * return new Species_LLI(mt, lf, argL0, argL1, argI2);
- * }
- * final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) {
- * return new Species_LLI(mt, lf, argL0, argL1, argI2);
- * }
- * final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
- * return SPECIES_DATA.extendWith(L_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
- * }
- * final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
- * return SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
- * }
- * final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
- * return SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
- * }
- * final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
- * return SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
- * }
- * public final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
- * return SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
- * }
- * }
- * </pre>
+ * BMH species are cached by type pattern.
*
- * @param types the type signature, wherein reference types are erased to 'L'
- * @return the generated concrete BMH class
+ * A BMH species has a number of fields with the concrete (possibly erased) types of
+ * bound values. Setters are provided as an API in BMH. Getters are exposed as MHs,
+ * which can be included as names in lambda forms.
*/
- static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String shortTypes,
- String types) {
- final String className = speciesInternalClassName(shortTypes);
- byte[] classFile = generateConcreteBMHClassBytes(shortTypes, types, className);
-
- // load class
- InvokerBytecodeGenerator.maybeDump(className, classFile);
- Class<? extends BoundMethodHandle> bmhClass =
- UNSAFE.defineClass(className, classFile, 0, classFile.length,
- BoundMethodHandle.class.getClassLoader(), null)
- .asSubclass(BoundMethodHandle.class);
-
- return bmhClass;
- }
-
- static String speciesInternalClassName(String shortTypes) {
- return SPECIES_PREFIX_PATH + shortTypes;
- }
-
- static byte[] generateConcreteBMHClassBytes(final String shortTypes,
- final String types, final String className) {
- final String sourceFile = SPECIES_PREFIX_NAME + shortTypes;
-
- final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
- final int NOT_ACC_PUBLIC = 0; // not ACC_PUBLIC
- cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
- cw.visitSource(sourceFile, null);
-
- // emit static types and SPECIES_DATA fields
- FieldVisitor fw = cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null);
- fw.visitAnnotation(STABLE_SIG, true);
- fw.visitEnd();
-
- // emit bound argument fields
- for (int i = 0; i < types.length(); ++i) {
- final char t = types.charAt(i);
- final String fieldName = makeFieldName(types, i);
- final String fieldDesc = t == 'L' ? JLO_SIG : String.valueOf(t);
- cw.visitField(ACC_FINAL, fieldName, fieldDesc, null, null).visitEnd();
- }
-
- MethodVisitor mv;
-
- // emit constructor
- mv = cw.visitMethod(ACC_PRIVATE, "<init>", makeSignature(types, true), null, null);
- mv.visitCode();
- mv.visitVarInsn(ALOAD, 0); // this
- mv.visitVarInsn(ALOAD, 1); // type
- mv.visitVarInsn(ALOAD, 2); // form
-
- mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true), false);
-
- for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
- // i counts the arguments, j counts corresponding argument slots
- char t = types.charAt(i);
- mv.visitVarInsn(ALOAD, 0);
- mv.visitVarInsn(typeLoadOp(t), j + 3); // parameters start at 3
- mv.visitFieldInsn(PUTFIELD, className, makeFieldName(types, i), typeSig(t));
- if (t == 'J' || t == 'D') {
- ++j; // adjust argument register access
- }
- }
-
- mv.visitInsn(RETURN);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
-
- // emit implementation of speciesData()
- mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null);
- mv.visitCode();
- mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
- mv.visitInsn(ARETURN);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
-
- // emit implementation of fieldCount()
- mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "fieldCount", INT_SIG, null, null);
- mv.visitCode();
- int fc = types.length();
- if (fc <= (ICONST_5 - ICONST_0)) {
- mv.visitInsn(ICONST_0 + fc);
- } else {
- mv.visitIntInsn(SIPUSH, fc);
- }
- mv.visitInsn(IRETURN);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
- // emit make() ...factory method wrapping constructor
- mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_STATIC, "make", makeSignature(types, false), null, null);
- mv.visitCode();
- // make instance
- mv.visitTypeInsn(NEW, className);
- mv.visitInsn(DUP);
- // load mt, lf
- mv.visitVarInsn(ALOAD, 0); // type
- mv.visitVarInsn(ALOAD, 1); // form
- // load factory method arguments
- for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
- // i counts the arguments, j counts corresponding argument slots
- char t = types.charAt(i);
- mv.visitVarInsn(typeLoadOp(t), j + 2); // parameters start at 3
- if (t == 'J' || t == 'D') {
- ++j; // adjust argument register access
- }
- }
-
- // finally, invoke the constructor and return
- mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false);
- mv.visitInsn(ARETURN);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
-
- // emit copyWith()
- mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWith", makeSignature("", false), null, null);
- mv.visitCode();
- // make instance
- mv.visitTypeInsn(NEW, className);
- mv.visitInsn(DUP);
- // load mt, lf
- mv.visitVarInsn(ALOAD, 1);
- mv.visitVarInsn(ALOAD, 2);
- // put fields on the stack
- emitPushFields(types, className, mv);
- // finally, invoke the constructor and return
- mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false);
- mv.visitInsn(ARETURN);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
-
- // for each type, emit copyWithExtendT()
- for (BasicType type : BasicType.ARG_TYPES) {
- int ord = type.ordinal();
- char btChar = type.basicTypeChar();
- mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWithExtend" + btChar, makeSignature(String.valueOf(btChar), false), null, E_THROWABLE);
- mv.visitCode();
- // return SPECIES_DATA.extendWith(t).constructor().invokeBasic(mt, lf, argL0, ..., narg)
- // obtain constructor
- mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
- int iconstInsn = ICONST_0 + ord;
- assert(iconstInsn <= ICONST_5);
- mv.visitInsn(iconstInsn);
- mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWith", BMHSPECIES_DATA_EWI_SIG, false);
- mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "constructor", "()" + MH_SIG, false);
- // load mt, lf
- mv.visitVarInsn(ALOAD, 1);
- mv.visitVarInsn(ALOAD, 2);
- // put fields on the stack
- emitPushFields(types, className, mv);
- // put narg on stack
- mv.visitVarInsn(typeLoadOp(btChar), 3);
- // finally, invoke the constructor and return
- mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + btChar, false), false);
- mv.visitInsn(ARETURN);
- mv.visitMaxs(0, 0);
- mv.visitEnd();
- }
-
- cw.visitEnd();
-
- return cw.toByteArray();
- }
-
- private static int typeLoadOp(char t) {
- switch (t) {
- case 'L': return ALOAD;
- case 'I': return ILOAD;
- case 'J': return LLOAD;
- case 'F': return FLOAD;
- case 'D': return DLOAD;
- default : throw newInternalError("unrecognized type " + t);
+ class Factory extends ClassSpecializer<BoundMethodHandle, String, BoundMethodHandle.SpeciesData>.Factory {
+ @Override
+ protected String chooseFieldName(Class<?> type, int index) {
+ return "arg" + super.chooseFieldName(type, index);
}
}
- private static void emitPushFields(String types, String className, MethodVisitor mv) {
- for (int i = 0; i < types.length(); ++i) {
- char tc = types.charAt(i);
- mv.visitVarInsn(ALOAD, 0);
- mv.visitFieldInsn(GETFIELD, className, makeFieldName(types, i), typeSig(tc));
- }
- }
-
- static String typeSig(char t) {
- return t == 'L' ? JLO_SIG : String.valueOf(t);
- }
-
- //
- // Getter MH generation.
- //
-
- private static MethodHandle makeGetter(Class<?> cbmhClass, String types, int index) {
- String fieldName = makeFieldName(types, index);
- Class<?> fieldType = Wrapper.forBasicType(types.charAt(index)).primitiveType();
- try {
- return LOOKUP.findGetter(cbmhClass, fieldName, fieldType);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- throw newInternalError(e);
- }
+ @Override
+ protected Factory makeFactory() {
+ return new Factory();
}
-
- static MethodHandle[] makeGetters(Class<?> cbmhClass, String types, MethodHandle[] mhs) {
- if (mhs == null) mhs = new MethodHandle[types.length()];
- for (int i = 0; i < mhs.length; ++i) {
- mhs[i] = makeGetter(cbmhClass, types, i);
- assert(mhs[i].internalMemberName().getDeclaringClass() == cbmhClass);
- }
- return mhs;
- }
-
- static MethodHandle[] makeCtors(Class<? extends BoundMethodHandle> cbmh, String types, MethodHandle mhs[]) {
- if (mhs == null) mhs = new MethodHandle[1];
- if (types.equals("")) return mhs; // hack for empty BMH species
- mhs[0] = makeCbmhCtor(cbmh, types);
- return mhs;
- }
-
- static NamedFunction[] makeNominalGetters(String types, NamedFunction[] nfs, MethodHandle[] getters) {
- if (nfs == null) nfs = new NamedFunction[types.length()];
- for (int i = 0; i < nfs.length; ++i) {
- nfs[i] = new NamedFunction(getters[i]);
- }
- return nfs;
- }
-
- //
- // Auxiliary methods.
- //
-
- static SpeciesData getSpeciesDataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) {
- try {
- Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA");
- return (SpeciesData) F_SPECIES_DATA.get(null);
- } catch (ReflectiveOperationException ex) {
- throw newInternalError(ex);
- }
- }
+ }
- static void setSpeciesDataToConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh, SpeciesData speciesData) {
- try {
- Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA");
- // ## FIXME: annotation parser can't create proxy classes until module system is fully initialzed
- // assert F_SPECIES_DATA.getDeclaredAnnotation(Stable.class) != null;
- F_SPECIES_DATA.set(null, speciesData);
- } catch (ReflectiveOperationException ex) {
- throw newInternalError(ex);
- }
- }
-
- /**
- * Field names in concrete BMHs adhere to this pattern:
- * arg + type + index
- * where type is a single character (L, I, J, F, D).
- */
- private static String makeFieldName(String types, int index) {
- assert index >= 0 && index < types.length();
- return "arg" + types.charAt(index) + index;
- }
-
- private static String makeSignature(String types, boolean ctor) {
- StringBuilder buf = new StringBuilder(SIG_INCIPIT);
- int len = types.length();
- for (int i = 0; i < len; i++) {
- buf.append(typeSig(types.charAt(i)));
- }
- return buf.append(')').append(ctor ? "V" : BMH_SIG).toString();
- }
-
- private static MethodType makeConstructorType(String types) {
- int length = types.length();
- Class<?> ptypes[] = new Class<?>[length + 2];
- ptypes[0] = MethodType.class;
- ptypes[1] = LambdaForm.class;
- for (int i = 0; i < length; i++) {
- ptypes[i + 2] = BasicType.basicType(types.charAt(i)).basicTypeClass();
- }
- return MethodType.makeImpl(BoundMethodHandle.class, ptypes, true);
- }
-
- static MethodHandle makeCbmhCtor(Class<? extends BoundMethodHandle> cbmh, String types) {
- try {
- return LOOKUP.findStatic(cbmh, "make", makeConstructorType(types));
- } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | TypeNotPresentException e) {
- throw newInternalError(e);
- }
- }
- }
-
- static final Lookup LOOKUP = Lookup.IMPL_LOOKUP;
-
- /**
- * All subclasses must provide such a value describing their type signature.
- */
- static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY;
-
- private static final SpeciesData[] SPECIES_DATA_CACHE = new SpeciesData[6];
- private static SpeciesData checkCache(int size, String types) {
- int idx = size - 1;
- SpeciesData data = SPECIES_DATA_CACHE[idx];
- if (data != null) return data;
- SPECIES_DATA_CACHE[idx] = data = getSpeciesData(types);
- return data;
- }
- static SpeciesData speciesData_L() { return checkCache(1, "L"); }
- static SpeciesData speciesData_LL() { return checkCache(2, "LL"); }
- static SpeciesData speciesData_LLL() { return checkCache(3, "LLL"); }
- static SpeciesData speciesData_LLLL() { return checkCache(4, "LLLL"); }
- static SpeciesData speciesData_LLLLL() { return checkCache(5, "LLLLL"); }
+ static SpeciesData speciesData_L() { return Species_L.BMH_SPECIES; }
+ static SpeciesData speciesData_LL() { return SPECIALIZER.findSpecies("LL"); }
+ static SpeciesData speciesData_LLL() { return SPECIALIZER.findSpecies("LLL"); }
+ static SpeciesData speciesData_LLLL() { return SPECIALIZER.findSpecies("LLLL"); }
+ static SpeciesData speciesData_LLLLL() { return SPECIALIZER.findSpecies("LLLLL"); }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,1030 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+package java.lang.invoke;
+
+import jdk.internal.loader.BootLoader;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.FieldVisitor;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.vm.annotation.Stable;
+import sun.invoke.util.BytecodeName;
+
+import java.lang.reflect.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+
+import static java.lang.invoke.LambdaForm.*;
+import static java.lang.invoke.MethodHandleNatives.Constants.REF_getStatic;
+import static java.lang.invoke.MethodHandleNatives.Constants.REF_putStatic;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+/**
+ * Class specialization code.
+ * @param <T> top class under which species classes are created.
+ * @param <K> key which identifies individual specializations.
+ * @param <S> species data type.
+ */
+/*non-public*/
+abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesData> {
+ private final Class<T> topClass;
+ private final Class<K> keyType;
+ private final Class<S> metaType;
+ private final MemberName sdAccessor;
+ private final String sdFieldName;
+ private final List<MemberName> transformMethods;
+ private final MethodType baseConstructorType;
+ private final S topSpecies;
+ private final ConcurrentMap<K, S> cache = new ConcurrentHashMap<>();
+ private final Factory factory;
+ private @Stable boolean topClassIsSuper;
+
+ /** Return the top type mirror, for type {@code T} */
+ public final Class<T> topClass() { return topClass; }
+
+ /** Return the key type mirror, for type {@code K} */
+ public final Class<K> keyType() { return keyType; }
+
+ /** Return the species metadata type mirror, for type {@code S} */
+ public final Class<S> metaType() { return metaType; }
+
+ /** Report the leading arguments (if any) required by every species factory.
+ * Every species factory adds its own field types as additional arguments,
+ * but these arguments always come first, in every factory method.
+ */
+ protected MethodType baseConstructorType() { return baseConstructorType; }
+
+ /** Return the trivial species for the null sequence of arguments. */
+ protected final S topSpecies() { return topSpecies; }
+
+ /** Return the list of transform methods originally given at creation of this specializer. */
+ protected final List<MemberName> transformMethods() { return transformMethods; }
+
+ /** Return the factory object used to build and load concrete species code. */
+ protected final Factory factory() { return factory; }
+
+ /**
+ * Constructor for this class specializer.
+ * @param topClass type mirror for T
+ * @param keyType type mirror for K
+ * @param metaType type mirror for S
+ * @param baseConstructorType principal constructor type
+ * @param sdAccessor the method used to get the speciesData
+ * @param sdFieldName the name of the species data field, inject the speciesData object
+ * @param transformMethods optional list of transformMethods
+ */
+ protected ClassSpecializer(Class<T> topClass,
+ Class<K> keyType,
+ Class<S> metaType,
+ MethodType baseConstructorType,
+ MemberName sdAccessor,
+ String sdFieldName,
+ List<MemberName> transformMethods) {
+ this.topClass = topClass;
+ this.keyType = keyType;
+ this.metaType = metaType;
+ this.sdAccessor = sdAccessor;
+ // FIXME: use List.copyOf once 8177290 is in
+ this.transformMethods = List.of(transformMethods.toArray(new MemberName[transformMethods.size()]));
+ this.sdFieldName = sdFieldName;
+ this.baseConstructorType = baseConstructorType.changeReturnType(void.class);
+ this.factory = makeFactory();
+ K tsk = topSpeciesKey();
+ S topSpecies = null;
+ if (tsk != null && topSpecies == null) {
+ // if there is a key, build the top species if needed:
+ topSpecies = findSpecies(tsk);
+ }
+ this.topSpecies = topSpecies;
+ }
+
+ // Utilities for subclass constructors:
+ protected static <T> Constructor<T> reflectConstructor(Class<T> defc, Class<?>... ptypes) {
+ try {
+ return defc.getDeclaredConstructor(ptypes);
+ } catch (NoSuchMethodException ex) {
+ throw newIAE(defc.getName()+"("+MethodType.methodType(void.class, ptypes)+")", ex);
+ }
+ }
+
+ protected static Field reflectField(Class<?> defc, String name) {
+ try {
+ return defc.getDeclaredField(name);
+ } catch (NoSuchFieldException ex) {
+ throw newIAE(defc.getName()+"."+name, ex);
+ }
+ }
+
+ private static RuntimeException newIAE(String message, Throwable cause) {
+ return new IllegalArgumentException(message, cause);
+ }
+
+ public final S findSpecies(K key) {
+ S speciesData = cache.computeIfAbsent(key, new Function<>() {
+ @Override
+ public S apply(K key1) {
+ return factory.loadSpecies(newSpeciesData(key1));
+ }
+ });
+ // Note: Species instantiation may throw VirtualMachineError because of
+ // code cache overflow. If this happens the species bytecode may be
+ // loaded but not linked to its species metadata (with MH's etc).
+ // That will cause a throw out of CHM.computeIfAbsent,
+ // which will shut down the caller thread.
+ //
+ // In a latter attempt to get the same species, the already-loaded
+ // class will be present in the system dictionary, causing an
+ // error when the species generator tries to reload it.
+ // We try to detect this case and link the pre-existing code.
+ //
+ // Although it would be better to start fresh by loading a new
+ // copy, we have to salvage the previously loaded but broken code.
+ // (As an alternative, we might spin a new class with a new name,
+ // or use the anonymous class mechanism.)
+ //
+ // In the end, as long as everybody goes through the same CHM,
+ // CHM.computeIfAbsent will ensure only one SpeciesData will be set
+ // successfully on a concrete class if ever.
+ // The concrete class is published via SpeciesData instance
+ // returned here only after the class and species data are linked together.
+ assert(speciesData != null);
+ return speciesData;
+ }
+
+ /**
+ * Meta-data wrapper for concrete subtypes of the top class.
+ * Each concrete subtype corresponds to a given sequence of basic field types (LIJFD).
+ * The fields are immutable; their values are fully specified at object construction.
+ * Each species supplies an array of getter functions which may be used in lambda forms.
+ * A concrete value is always constructed from the full tuple of its field values,
+ * accompanied by the required constructor parameters.
+ * There *may* also be transforms which cloning a species instance and
+ * either replace a constructor parameter or add one or more new field values.
+ * The shortest possible species has zero fields.
+ * Subtypes are not interrelated among themselves by subtyping, even though
+ * it would appear that a shorter species could serve as a supertype of a
+ * longer one which extends it.
+ */
+ public abstract class SpeciesData {
+ // Bootstrapping requires circular relations Class -> SpeciesData -> Class
+ // Therefore, we need non-final links in the chain. Use @Stable fields.
+ private final K key;
+ private final List<Class<?>> fieldTypes;
+ @Stable private Class<? extends T> speciesCode;
+ @Stable private List<MethodHandle> factories;
+ @Stable private List<MethodHandle> getters;
+ @Stable private List<LambdaForm.NamedFunction> nominalGetters;
+ @Stable private final MethodHandle[] transformHelpers = new MethodHandle[transformMethods.size()];
+
+ protected SpeciesData(K key) {
+ this.key = keyType.cast(Objects.requireNonNull(key));
+ List<Class<?>> types = deriveFieldTypes(key);
+ // TODO: List.copyOf
+ int arity = types.size();
+ this.fieldTypes = List.of(types.toArray(new Class<?>[arity]));
+ }
+
+ public final K key() {
+ return key;
+ }
+
+ protected final List<Class<?>> fieldTypes() {
+ return fieldTypes;
+ }
+
+ protected final int fieldCount() {
+ return fieldTypes.size();
+ }
+
+ protected ClassSpecializer<T,K,S> outer() {
+ return ClassSpecializer.this;
+ }
+
+ protected final boolean isResolved() {
+ return speciesCode != null && factories != null && !factories.isEmpty();
+ }
+
+ @Override public String toString() {
+ return metaType.getSimpleName() + "[" + key.toString() + " => " + (isResolved() ? speciesCode.getSimpleName() : "UNRESOLVED") + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ return key.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ClassSpecializer.SpeciesData)) {
+ return false;
+ }
+ @SuppressWarnings("rawtypes")
+ ClassSpecializer.SpeciesData that = (ClassSpecializer.SpeciesData) obj;
+ return this.outer() == that.outer() && this.key.equals(that.key);
+ }
+
+ /** Throws NPE if this species is not yet resolved. */
+ protected final Class<? extends T> speciesCode() {
+ return Objects.requireNonNull(speciesCode);
+ }
+
+ /**
+ * Return a {@link MethodHandle} which can get the indexed field of this species.
+ * The return type is the type of the species field it accesses.
+ * The argument type is the {@code fieldHolder} class of this species.
+ */
+ protected MethodHandle getter(int i) {
+ return getters.get(i);
+ }
+
+ /**
+ * Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that
+ * represents a MH bound to a generic invoker, which in turn forwards to the corresponding
+ * getter.
+ */
+ protected LambdaForm.NamedFunction getterFunction(int i) {
+ LambdaForm.NamedFunction nf = nominalGetters.get(i);
+ assert(nf.memberDeclaringClassOrNull() == speciesCode());
+ assert(nf.returnType() == BasicType.basicType(fieldTypes.get(i)));
+ return nf;
+ }
+
+ protected List<LambdaForm.NamedFunction> getterFunctions() {
+ return nominalGetters;
+ }
+
+ protected List<MethodHandle> getters() {
+ return getters;
+ }
+
+ protected MethodHandle factory() {
+ return factories.get(0);
+ }
+
+ protected MethodHandle transformHelper(int whichtm) {
+ MethodHandle mh = transformHelpers[whichtm];
+ if (mh != null) return mh;
+ mh = deriveTransformHelper(transformMethods().get(whichtm), whichtm);
+ // Do a little type checking before we start using the MH.
+ // (It will be called with invokeBasic, so this is our only chance.)
+ final MethodType mt = transformHelperType(whichtm);
+ mh = mh.asType(mt);
+ return transformHelpers[whichtm] = mh;
+ }
+
+ private final MethodType transformHelperType(int whichtm) {
+ MemberName tm = transformMethods().get(whichtm);
+ ArrayList<Class<?>> args = new ArrayList<>();
+ ArrayList<Class<?>> fields = new ArrayList<>();
+ Collections.addAll(args, tm.getParameterTypes());
+ fields.addAll(fieldTypes());
+ List<Class<?>> helperArgs = deriveTransformHelperArguments(tm, whichtm, args, fields);
+ return MethodType.methodType(tm.getReturnType(), helperArgs);
+ }
+
+ // Hooks for subclasses:
+
+ /**
+ * Given a key, derive the list of field types, which all instances of this
+ * species must store.
+ */
+ protected abstract List<Class<?>> deriveFieldTypes(K key);
+
+ /**
+ * Given the index of a method in the transforms list, supply a factory
+ * method that takes the arguments of the transform, plus the local fields,
+ * and produce a value of the required type.
+ * You can override this to return null or throw if there are no transforms.
+ * This method exists so that the transforms can be "grown" lazily.
+ * This is necessary if the transform *adds* a field to an instance,
+ * which sometimtes requires the creation, on the fly, of an extended species.
+ * This method is only called once for any particular parameter.
+ * The species caches the result in a private array.
+ *
+ * @param transform the transform being implemented
+ * @param whichtm the index of that transform in the original list of transforms
+ * @return the method handle which creates a new result from a mix of transform
+ * arguments and field values
+ */
+ protected abstract MethodHandle deriveTransformHelper(MemberName transform, int whichtm);
+
+ /**
+ * During code generation, this method is called once per transform to determine
+ * what is the mix of arguments to hand to the transform-helper. The bytecode
+ * which marshals these arguments is open-coded in the species-specific transform.
+ * The two lists are of opaque objects, which you shouldn't do anything with besides
+ * reordering them into the output list. (They are both mutable, to make editing
+ * easier.) The imputed types of the args correspond to the transform's parameter
+ * list, while the imputed types of the fields correspond to the species field types.
+ * After code generation, this method may be called occasionally by error-checking code.
+ *
+ * @param transform the transform being implemented
+ * @param whichtm the index of that transform in the original list of transforms
+ * @param args a list of opaque objects representing the incoming transform arguments
+ * @param fields a list of opaque objects representing the field values of the receiver
+ * @param <X> the common element type of the various lists
+ * @return a new list
+ */
+ protected abstract <X> List<X> deriveTransformHelperArguments(MemberName transform, int whichtm,
+ List<X> args, List<X> fields);
+
+ /** Given a key, generate the name of the class which implements the species for that key.
+ * This algorithm must be stable.
+ *
+ * @return class name, which by default is {@code outer().topClass().getName() + "$Species_" + deriveTypeString(key)}
+ */
+ protected String deriveClassName() {
+ return outer().topClass().getName() + "$Species_" + deriveTypeString();
+ }
+
+ /**
+ * Default implementation collects basic type characters,
+ * plus possibly type names, if some types don't correspond
+ * to basic types.
+ *
+ * @return a string suitable for use in a class name
+ */
+ protected String deriveTypeString() {
+ List<Class<?>> types = fieldTypes();
+ StringBuilder buf = new StringBuilder();
+ StringBuilder end = new StringBuilder();
+ for (Class<?> type : types) {
+ BasicType basicType = BasicType.basicType(type);
+ if (basicType.basicTypeClass() == type) {
+ buf.append(basicType.basicTypeChar());
+ } else {
+ buf.append('V');
+ end.append(classSig(type));
+ }
+ }
+ String typeString;
+ if (end.length() > 0) {
+ typeString = BytecodeName.toBytecodeName(buf.append("_").append(end).toString());
+ } else {
+ typeString = buf.toString();
+ }
+ return LambdaForm.shortenSignature(typeString);
+ }
+
+ /**
+ * Report what immediate super-class to use for the concrete class of this species.
+ * Normally this is {@code topClass}, but if that is an interface, the factory must override.
+ * The super-class must provide a constructor which takes the {@code baseConstructorType} arguments, if any.
+ * This hook also allows the code generator to use more than one canned supertype for species.
+ *
+ * @return the super-class of the class to be generated
+ */
+ protected Class<? extends T> deriveSuperClass() {
+ final Class<T> topc = topClass();
+ if (!topClassIsSuper) {
+ try {
+ final Constructor<T> con = reflectConstructor(topc, baseConstructorType().parameterArray());
+ if (!topc.isInterface() && !Modifier.isPrivate(con.getModifiers())) {
+ topClassIsSuper = true;
+ }
+ } catch (Exception|InternalError ex) {
+ // fall through...
+ }
+ if (!topClassIsSuper) {
+ throw newInternalError("must override if the top class cannot serve as a super class");
+ }
+ }
+ return topc;
+ }
+ }
+
+ protected abstract S newSpeciesData(K key);
+
+ protected K topSpeciesKey() {
+ return null; // null means don't report a top species
+ }
+
+ /**
+ * Code generation support for instances.
+ * Subclasses can modify the behavior.
+ */
+ public class Factory {
+ /**
+ * Get a concrete subclass of the top class for a given combination of bound types.
+ *
+ * @param speciesData the species requiring the class, not yet linked
+ * @return a linked version of the same species
+ */
+ S loadSpecies(S speciesData) {
+ String className = speciesData.deriveClassName();
+ assert(className.indexOf('/') < 0) : className;
+ Class<?> salvage = null;
+ try {
+ salvage = BootLoader.loadClassOrNull(className);
+ if (TRACE_RESOLVE && salvage != null) {
+ // Used by jlink species pregeneration plugin, see
+ // jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin
+ System.out.println("[SPECIES_RESOLVE] " + className + " (salvaged)");
+ }
+ } catch (Error ex) {
+ if (TRACE_RESOLVE) {
+ System.out.println("[SPECIES_FRESOLVE] " + className + " (Error) " + ex.getMessage());
+ }
+ }
+ final Class<? extends T> speciesCode;
+ if (salvage != null) {
+ speciesCode = salvage.asSubclass(topClass());
+ factory.linkSpeciesDataToCode(speciesData, speciesCode);
+ factory.linkCodeToSpeciesData(speciesCode, speciesData, true);
+ } else {
+ // Not pregenerated, generate the class
+ try {
+ speciesCode = generateConcreteSpeciesCode(className, speciesData);
+ if (TRACE_RESOLVE) {
+ // Used by jlink species pregeneration plugin, see
+ // jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin
+ System.out.println("[SPECIES_RESOLVE] " + className + " (generated)");
+ }
+ // This operation causes a lot of churn:
+ linkSpeciesDataToCode(speciesData, speciesCode);
+ // This operation commits the relation, but causes little churn:
+ linkCodeToSpeciesData(speciesCode, speciesData, false);
+ } catch (Error ex) {
+ if (TRACE_RESOLVE) {
+ System.out.println("[SPECIES_RESOLVE] " + className + " (Error #2)" );
+ }
+ // We can get here if there is a race condition loading a class.
+ // Or maybe we are out of resources. Back out of the CHM.get and retry.
+ throw ex;
+ }
+ }
+
+ if (!speciesData.isResolved()) {
+ throw newInternalError("bad species class linkage for " + className + ": " + speciesData);
+ }
+ assert(speciesData == factory.loadSpeciesDataFromCode(speciesCode));
+ return speciesData;
+ }
+
+ /**
+ * Generate a concrete subclass of the top class for a given combination of bound types.
+ *
+ * A concrete species subclass roughly matches the following schema:
+ *
+ * <pre>
+ * class Species_[[types]] extends [[T]] {
+ * final [[S]] speciesData() { return ... }
+ * static [[T]] make([[fields]]) { return ... }
+ * [[fields]]
+ * final [[T]] transform([[args]]) { return ... }
+ * }
+ * </pre>
+ *
+ * The {@code [[types]]} signature is precisely the key for the species.
+ *
+ * The {@code [[fields]]} section consists of one field definition per character in
+ * the type signature, adhering to the naming schema described in the definition of
+ * {@link #chooseFieldName}.
+ *
+ * For example, a concrete species for two references and one integral bound value
+ * has a shape like the following:
+ *
+ * <pre>
+ * class TopClass { ... private static
+ * final class Species_LLI extends TopClass {
+ * final Object argL0;
+ * final Object argL1;
+ * final int argI2;
+ * private Species_LLI(CT ctarg, ..., Object argL0, Object argL1, int argI2) {
+ * super(ctarg, ...);
+ * this.argL0 = argL0;
+ * this.argL1 = argL1;
+ * this.argI2 = argI2;
+ * }
+ * final SpeciesData speciesData() { return BMH_SPECIES; }
+ * @Stable static SpeciesData BMH_SPECIES; // injected afterwards
+ * static TopClass make(CT ctarg, ..., Object argL0, Object argL1, int argI2) {
+ * return new Species_LLI(ctarg, ..., argL0, argL1, argI2);
+ * }
+ * final TopClass copyWith(CT ctarg, ...) {
+ * return new Species_LLI(ctarg, ..., argL0, argL1, argI2);
+ * }
+ * // two transforms, for the sake of illustration:
+ * final TopClass copyWithExtendL(CT ctarg, ..., Object narg) {
+ * return BMH_SPECIES.transform(L_TYPE).invokeBasic(ctarg, ..., argL0, argL1, argI2, narg);
+ * }
+ * final TopClass copyWithExtendI(CT ctarg, ..., int narg) {
+ * return BMH_SPECIES.transform(I_TYPE).invokeBasic(ctarg, ..., argL0, argL1, argI2, narg);
+ * }
+ * }
+ * </pre>
+ *
+ * @param className of the species
+ * @param speciesData what species we are generating
+ * @return the generated concrete TopClass class
+ */
+ Class<? extends T> generateConcreteSpeciesCode(String className, ClassSpecializer<T,K,S>.SpeciesData speciesData) {
+ byte[] classFile = generateConcreteSpeciesCodeFile(className, speciesData);
+
+ // load class
+ InvokerBytecodeGenerator.maybeDump(classBCName(className), classFile);
+ Class<?> speciesCode;
+
+ ClassLoader cl = topClass().getClassLoader();
+ ProtectionDomain pd = null;
+ if (cl != null) {
+ pd = AccessController.doPrivileged(
+ new PrivilegedAction<>() {
+ @Override
+ public ProtectionDomain run() {
+ return topClass().getProtectionDomain();
+ }
+ });
+ }
+ try {
+ speciesCode = UNSAFE.defineClass(className, classFile, 0, classFile.length, cl, pd);
+ } catch (Exception ex) {
+ throw newInternalError(ex);
+ }
+
+ return speciesCode.asSubclass(topClass());
+ }
+
+ // These are named like constants because there is only one per specialization scheme:
+ private final String SPECIES_DATA = classBCName(metaType);
+ private final String SPECIES_DATA_SIG = classSig(SPECIES_DATA);
+ private final String SPECIES_DATA_NAME = sdAccessor.getName();
+ private final int SPECIES_DATA_MODS = sdAccessor.getModifiers();
+ private final List<String> TRANSFORM_NAMES; // derived from transformMethods
+ private final List<MethodType> TRANSFORM_TYPES;
+ private final List<Integer> TRANSFORM_MODS;
+ {
+ // Tear apart transformMethods to get the names, types, and modifiers.
+ List<String> tns = new ArrayList<>();
+ List<MethodType> tts = new ArrayList<>();
+ List<Integer> tms = new ArrayList<>();
+ for (int i = 0; i < transformMethods.size(); i++) {
+ MemberName tm = transformMethods.get(i);
+ tns.add(tm.getName());
+ final MethodType tt = tm.getMethodType();
+ tts.add(tt);
+ tms.add(tm.getModifiers());
+ }
+ TRANSFORM_NAMES = List.of(tns.toArray(new String[0]));
+ TRANSFORM_TYPES = List.of(tts.toArray(new MethodType[0]));
+ TRANSFORM_MODS = List.of(tms.toArray(new Integer[0]));
+ }
+ private static final int ACC_PPP = ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED;
+
+ /*non-public*/ byte[] generateConcreteSpeciesCodeFile(String className0, ClassSpecializer<T,K,S>.SpeciesData speciesData) {
+ final String className = classBCName(className0);
+ final String superClassName = classBCName(speciesData.deriveSuperClass());
+
+ final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
+ final int NOT_ACC_PUBLIC = 0; // not ACC_PUBLIC
+ cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, superClassName, null);
+
+ final String sourceFile = className.substring(className.lastIndexOf('.')+1);
+ cw.visitSource(sourceFile, null);
+
+ // emit static types and BMH_SPECIES fields
+ FieldVisitor fw = cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, sdFieldName, SPECIES_DATA_SIG, null, null);
+ fw.visitAnnotation(STABLE_SIG, true);
+ fw.visitEnd();
+
+ // handy holder for dealing with groups of typed values (ctor arguments and fields)
+ class Var {
+ final int index;
+ final String name;
+ final Class<?> type;
+ final String desc;
+ final BasicType basicType;
+ final int slotIndex;
+ Var(int index, int slotIndex) {
+ this.index = index;
+ this.slotIndex = slotIndex;
+ name = null; type = null; desc = null;
+ basicType = BasicType.V_TYPE;
+ }
+ Var(String name, Class<?> type, Var prev) {
+ int slotIndex = prev.nextSlotIndex();
+ int index = prev.nextIndex();
+ if (name == null) name = "x";
+ if (name.endsWith("#"))
+ name = name.substring(0, name.length()-1) + index;
+ assert(!type.equals(void.class));
+ String desc = classSig(type);
+ BasicType basicType = BasicType.basicType(type);
+ this.index = index;
+ this.name = name;
+ this.type = type;
+ this.desc = desc;
+ this.basicType = basicType;
+ this.slotIndex = slotIndex;
+ }
+ Var lastOf(List<Var> vars) {
+ int n = vars.size();
+ return (n == 0 ? this : vars.get(n-1));
+ }
+ <X> List<Var> fromTypes(List<X> types) {
+ Var prev = this;
+ ArrayList<Var> result = new ArrayList<>(types.size());
+ int i = 0;
+ for (X x : types) {
+ String vn = name;
+ Class<?> vt;
+ if (x instanceof Class) {
+ vt = (Class<?>) x;
+ // make the names friendlier if debugging
+ assert((vn = vn + "_" + (i++)) != null);
+ } else {
+ @SuppressWarnings("unchecked")
+ Var v = (Var) x;
+ vn = v.name;
+ vt = v.type;
+ }
+ prev = new Var(vn, vt, prev);
+ result.add(prev);
+ }
+ return result;
+ }
+
+ int slotSize() { return basicType.basicTypeSlots(); }
+ int nextIndex() { return index + (slotSize() == 0 ? 0 : 1); }
+ int nextSlotIndex() { return slotIndex >= 0 ? slotIndex + slotSize() : slotIndex; }
+ boolean isInHeap() { return slotIndex < 0; }
+ void emitVarInstruction(int asmop, MethodVisitor mv) {
+ if (asmop == ALOAD)
+ asmop = typeLoadOp(basicType.basicTypeChar());
+ else
+ throw new AssertionError("bad op="+asmop+" for desc="+desc);
+ mv.visitVarInsn(asmop, slotIndex);
+ }
+ public void emitFieldInsn(int asmop, MethodVisitor mv) {
+ mv.visitFieldInsn(asmop, className, name, desc);
+ }
+ }
+
+ final Var NO_THIS = new Var(0, 0),
+ AFTER_THIS = new Var(0, 1),
+ IN_HEAP = new Var(0, -1);
+
+ // figure out the field types
+ final List<Class<?>> fieldTypes = speciesData.fieldTypes();
+ final List<Var> fields = new ArrayList<>(fieldTypes.size());
+ {
+ Var nextF = IN_HEAP;
+ for (Class<?> ft : fieldTypes) {
+ String fn = chooseFieldName(ft, nextF.nextIndex());
+ nextF = new Var(fn, ft, nextF);
+ fields.add(nextF);
+ }
+ }
+
+ // emit bound argument fields
+ for (Var field : fields) {
+ cw.visitField(ACC_FINAL, field.name, field.desc, null, null).visitEnd();
+ }
+
+ MethodVisitor mv;
+
+ // emit implementation of speciesData()
+ mv = cw.visitMethod((SPECIES_DATA_MODS & ACC_PPP) + ACC_FINAL,
+ SPECIES_DATA_NAME, "()" + SPECIES_DATA_SIG, null, null);
+ mv.visitCode();
+ mv.visitFieldInsn(GETSTATIC, className, sdFieldName, SPECIES_DATA_SIG);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+
+ // figure out the constructor arguments
+ MethodType superCtorType = ClassSpecializer.this.baseConstructorType();
+ MethodType thisCtorType = superCtorType.appendParameterTypes(fieldTypes);
+
+ // emit constructor
+ {
+ mv = cw.visitMethod(ACC_PRIVATE,
+ "<init>", methodSig(thisCtorType), null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0); // this
+
+ final List<Var> ctorArgs = AFTER_THIS.fromTypes(superCtorType.parameterList());
+ for (Var ca : ctorArgs) {
+ ca.emitVarInstruction(ALOAD, mv);
+ }
+
+ // super(ca...)
+ mv.visitMethodInsn(INVOKESPECIAL, superClassName,
+ "<init>", methodSig(superCtorType), false);
+
+ // store down fields
+ Var lastFV = AFTER_THIS.lastOf(ctorArgs);
+ for (Var f : fields) {
+ // this.argL1 = argL1
+ mv.visitVarInsn(ALOAD, 0); // this
+ lastFV = new Var(f.name, f.type, lastFV);
+ lastFV.emitVarInstruction(ALOAD, mv);
+ f.emitFieldInsn(PUTFIELD, mv);
+ }
+
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+
+ // emit make() ...factory method wrapping constructor
+ {
+ MethodType ftryType = thisCtorType.changeReturnType(topClass());
+ mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_STATIC,
+ "make", methodSig(ftryType), null, null);
+ mv.visitCode();
+ // make instance
+ mv.visitTypeInsn(NEW, className);
+ mv.visitInsn(DUP);
+ // load factory method arguments: ctarg... and arg...
+ for (Var v : NO_THIS.fromTypes(ftryType.parameterList())) {
+ v.emitVarInstruction(ALOAD, mv);
+ }
+
+ // finally, invoke the constructor and return
+ mv.visitMethodInsn(INVOKESPECIAL, className,
+ "<init>", methodSig(thisCtorType), false);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+
+ // For each transform, emit the customized override of the transform method.
+ // This method mixes together some incoming arguments (from the transform's
+ // static type signature) with the field types themselves, and passes
+ // the resulting mish-mosh of values to a method handle produced by
+ // the species itself. (Typically this method handle is the factory
+ // method of this species or a related one.)
+ for (int whichtm = 0; whichtm < TRANSFORM_NAMES.size(); whichtm++) {
+ final String TNAME = TRANSFORM_NAMES.get(whichtm);
+ final MethodType TTYPE = TRANSFORM_TYPES.get(whichtm);
+ final int TMODS = TRANSFORM_MODS.get(whichtm);
+ mv = cw.visitMethod((TMODS & ACC_PPP) | ACC_FINAL,
+ TNAME, TTYPE.toMethodDescriptorString(), null, E_THROWABLE);
+ mv.visitCode();
+ // return a call to the corresponding "transform helper", something like this:
+ // MY_SPECIES.transformHelper(whichtm).invokeBasic(ctarg, ..., argL0, ..., xarg)
+ mv.visitFieldInsn(GETSTATIC, className,
+ sdFieldName, SPECIES_DATA_SIG);
+ emitIntConstant(whichtm, mv);
+ mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA,
+ "transformHelper", "(I)" + MH_SIG, false);
+
+ List<Var> targs = AFTER_THIS.fromTypes(TTYPE.parameterList());
+ List<Var> tfields = new ArrayList<>(fields);
+ // mix them up and load them for the transform helper:
+ List<Var> helperArgs = speciesData.deriveTransformHelperArguments(transformMethods.get(whichtm), whichtm, targs, tfields);
+ List<Class<?>> helperTypes = new ArrayList<>(helperArgs.size());
+ for (Var ha : helperArgs) {
+ helperTypes.add(ha.basicType.basicTypeClass());
+ if (ha.isInHeap()) {
+ assert(tfields.contains(ha));
+ mv.visitVarInsn(ALOAD, 0);
+ ha.emitFieldInsn(GETFIELD, mv);
+ } else {
+ assert(targs.contains(ha));
+ ha.emitVarInstruction(ALOAD, mv);
+ }
+ }
+
+ // jump into the helper (which is probably a factory method)
+ final Class<?> rtype = TTYPE.returnType();
+ final BasicType rbt = BasicType.basicType(rtype);
+ MethodType invokeBasicType = MethodType.methodType(rbt.basicTypeClass(), helperTypes);
+ mv.visitMethodInsn(INVOKEVIRTUAL, MH,
+ "invokeBasic", methodSig(invokeBasicType), false);
+ if (rbt == BasicType.L_TYPE) {
+ mv.visitTypeInsn(CHECKCAST, classBCName(rtype));
+ mv.visitInsn(ARETURN);
+ } else {
+ throw newInternalError("NYI: transform of type "+rtype);
+ }
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+
+ private int typeLoadOp(char t) {
+ switch (t) {
+ case 'L': return ALOAD;
+ case 'I': return ILOAD;
+ case 'J': return LLOAD;
+ case 'F': return FLOAD;
+ case 'D': return DLOAD;
+ default : throw newInternalError("unrecognized type " + t);
+ }
+ }
+
+ private void emitIntConstant(int con, MethodVisitor mv) {
+ if (ICONST_M1 - ICONST_0 <= con && con <= ICONST_5 - ICONST_0)
+ mv.visitInsn(ICONST_0 + con);
+ else if (con == (byte) con)
+ mv.visitIntInsn(BIPUSH, con);
+ else if (con == (short) con)
+ mv.visitIntInsn(SIPUSH, con);
+ else {
+ mv.visitLdcInsn(con);
+ }
+
+ }
+
+ //
+ // Getter MH generation.
+ //
+
+ private MethodHandle findGetter(Class<?> speciesCode, List<Class<?>> types, int index) {
+ Class<?> fieldType = types.get(index);
+ String fieldName = chooseFieldName(fieldType, index);
+ try {
+ return IMPL_LOOKUP.findGetter(speciesCode, fieldName, fieldType);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw newInternalError(e);
+ }
+ }
+
+ private List<MethodHandle> findGetters(Class<?> speciesCode, List<Class<?>> types) {
+ MethodHandle[] mhs = new MethodHandle[types.size()];
+ for (int i = 0; i < mhs.length; ++i) {
+ mhs[i] = findGetter(speciesCode, types, i);
+ assert(mhs[i].internalMemberName().getDeclaringClass() == speciesCode);
+ }
+ return List.of(mhs);
+ }
+
+ private List<MethodHandle> findFactories(Class<? extends T> speciesCode, List<Class<?>> types) {
+ MethodHandle[] mhs = new MethodHandle[1];
+ mhs[0] = findFactory(speciesCode, types);
+ return List.of(mhs);
+ }
+
+ List<LambdaForm.NamedFunction> makeNominalGetters(List<Class<?>> types, List<MethodHandle> getters) {
+ LambdaForm.NamedFunction[] nfs = new LambdaForm.NamedFunction[types.size()];
+ for (int i = 0; i < nfs.length; ++i) {
+ nfs[i] = new LambdaForm.NamedFunction(getters.get(i));
+ }
+ return List.of(nfs);
+ }
+
+ //
+ // Auxiliary methods.
+ //
+
+ protected void linkSpeciesDataToCode(ClassSpecializer<T,K,S>.SpeciesData speciesData, Class<? extends T> speciesCode) {
+ speciesData.speciesCode = speciesCode.asSubclass(topClass);
+ final List<Class<?>> types = speciesData.fieldTypes;
+ speciesData.factories = this.findFactories(speciesCode, types);
+ speciesData.getters = this.findGetters(speciesCode, types);
+ speciesData.nominalGetters = this.makeNominalGetters(types, speciesData.getters);
+ }
+
+ private Field reflectSDField(Class<? extends T> speciesCode) {
+ final Field field = reflectField(speciesCode, sdFieldName);
+ assert(field.getType() == metaType);
+ assert(Modifier.isStatic(field.getModifiers()));
+ return field;
+ }
+
+ private S readSpeciesDataFromCode(Class<? extends T> speciesCode) {
+ try {
+ MemberName sdField = IMPL_LOOKUP.resolveOrFail(REF_getStatic, speciesCode, sdFieldName, metaType);
+ Object base = MethodHandleNatives.staticFieldBase(sdField);
+ long offset = MethodHandleNatives.staticFieldOffset(sdField);
+ UNSAFE.loadFence();
+ return metaType.cast(UNSAFE.getObject(base, offset));
+ } catch (Error err) {
+ throw err;
+ } catch (Exception ex) {
+ throw newInternalError("Failed to load speciesData from speciesCode: " + speciesCode.getName(), ex);
+ } catch (Throwable t) {
+ throw uncaughtException(t);
+ }
+ }
+
+ protected S loadSpeciesDataFromCode(Class<? extends T> speciesCode) {
+ if (speciesCode == topClass()) {
+ return topSpecies;
+ }
+ S result = readSpeciesDataFromCode(speciesCode);
+ if (result.outer() != ClassSpecializer.this) {
+ throw newInternalError("wrong class");
+ }
+ return result;
+ }
+
+ protected void linkCodeToSpeciesData(Class<? extends T> speciesCode, ClassSpecializer<T,K,S>.SpeciesData speciesData, boolean salvage) {
+ try {
+ assert(readSpeciesDataFromCode(speciesCode) == null ||
+ (salvage && readSpeciesDataFromCode(speciesCode).equals(speciesData)));
+
+ MemberName sdField = IMPL_LOOKUP.resolveOrFail(REF_putStatic, speciesCode, sdFieldName, metaType);
+ Object base = MethodHandleNatives.staticFieldBase(sdField);
+ long offset = MethodHandleNatives.staticFieldOffset(sdField);
+ UNSAFE.storeFence();
+ UNSAFE.putObject(base, offset, speciesData);
+ UNSAFE.storeFence();
+ } catch (Error err) {
+ throw err;
+ } catch (Exception ex) {
+ throw newInternalError("Failed to link speciesData to speciesCode: " + speciesCode.getName(), ex);
+ } catch (Throwable t) {
+ throw uncaughtException(t);
+ }
+ }
+
+ /**
+ * Field names in concrete species classes adhere to this pattern:
+ * type + index, where type is a single character (L, I, J, F, D).
+ * The factory subclass can customize this.
+ * The name is purely cosmetic, since it applies to a private field.
+ */
+ protected String chooseFieldName(Class<?> type, int index) {
+ BasicType bt = BasicType.basicType(type);
+ return "" + bt.basicTypeChar() + index;
+ }
+
+ MethodHandle findFactory(Class<? extends T> speciesCode, List<Class<?>> types) {
+ final MethodType type = baseConstructorType().changeReturnType(topClass()).appendParameterTypes(types);
+ try {
+ return IMPL_LOOKUP.findStatic(speciesCode, "make", type);
+ } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | TypeNotPresentException e) {
+ throw newInternalError(e);
+ }
+ }
+ }
+
+ /** Hook that virtualizes the Factory class, allowing subclasses to extend it. */
+ protected Factory makeFactory() {
+ return new Factory();
+ }
+
+
+ // Other misc helpers:
+ private static final String MH = "java/lang/invoke/MethodHandle";
+ private static final String MH_SIG = "L" + MH + ";";
+ private static final String STABLE = "jdk/internal/vm/annotation/Stable";
+ private static final String STABLE_SIG = "L" + STABLE + ";";
+ private static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" };
+ static {
+ assert(MH_SIG.equals(classSig(MethodHandle.class)));
+ assert(MH.equals(classBCName(MethodHandle.class)));
+ }
+
+ static String methodSig(MethodType mt) {
+ return mt.toMethodDescriptorString();
+ }
+ static String classSig(Class<?> cls) {
+ if (cls.isPrimitive() || cls.isArray())
+ return MethodType.methodType(cls).toMethodDescriptorString().substring(2);
+ return classSig(classBCName(cls));
+ }
+ static String classSig(String bcName) {
+ assert(bcName.indexOf('.') < 0);
+ assert(!bcName.endsWith(";"));
+ assert(!bcName.startsWith("["));
+ return "L" + bcName + ";";
+ }
+ static String classBCName(Class<?> cls) {
+ return classBCName(className(cls));
+ }
+ static String classBCName(String str) {
+ assert(str.indexOf('/') < 0) : str;
+ return str.replace('.', '/');
+ }
+ static String className(Class<?> cls) {
+ assert(!cls.isArray() && !cls.isPrimitive());
+ return cls.getName();
+ }
+}
--- a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java Thu Nov 16 10:45:42 2017 -0800
@@ -25,14 +25,14 @@
package java.lang.invoke;
-import java.util.Map;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;
+import sun.invoke.util.Wrapper;
+
import java.util.ArrayList;
import java.util.HashSet;
-import sun.invoke.util.Wrapper;
-
-import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import java.util.List;
+import java.util.Map;
/**
* Helper class to assist the GenerateJLIClassesPlugin to get access to
@@ -118,8 +118,7 @@
// require an even more complex naming scheme
LambdaForm reinvoker = makeReinvokerFor(methodTypes[i]);
forms.add(reinvoker);
- String speciesSig = BoundMethodHandle
- .speciesData(reinvoker).fieldSignature();
+ String speciesSig = BoundMethodHandle.speciesDataFor(reinvoker).key();
assert(speciesSig.equals("L"));
names.add(reinvoker.kind.defaultLambdaName + "_" + speciesSig);
@@ -205,20 +204,19 @@
DelegatingMethodHandle.NF_getTarget);
}
- static Map.Entry<String, byte[]> generateConcreteBMHClassBytes(
- final String types) {
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ static Map.Entry<String, byte[]> generateConcreteBMHClassBytes(final String types) {
for (char c : types.toCharArray()) {
if ("LIJFD".indexOf(c) < 0) {
throw new IllegalArgumentException("All characters must "
+ "correspond to a basic field type: LIJFD");
}
}
- String shortTypes = LambdaForm.shortenSignature(types);
- final String className =
- BoundMethodHandle.Factory.speciesInternalClassName(shortTypes);
- return Map.entry(className,
- BoundMethodHandle.Factory.generateConcreteBMHClassBytes(
- shortTypes, types, className));
+ final BoundMethodHandle.SpeciesData species = BoundMethodHandle.SPECIALIZER.findSpecies(types);
+ final String className = species.speciesCode().getName();
+ final ClassSpecializer.Factory factory = BoundMethodHandle.SPECIALIZER.factory();
+ final byte[] code = factory.generateConcreteSpeciesCodeFile(className, species);
+ return Map.entry(className.replace('.', '/'), code);
}
}
--- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Thu Nov 16 10:45:42 2017 -0800
@@ -183,8 +183,7 @@
new java.security.PrivilegedAction<>() {
public Void run() {
try {
- String dumpName = className;
- //dumpName = dumpName.replace('/', '-');
+ String dumpName = className.replace('.','/');
File dumpFile = new File(DUMP_CLASS_FILES_DIR, dumpName+".class");
System.out.println("dump: " + dumpFile);
dumpFile.getParentFile().mkdirs();
@@ -630,7 +629,7 @@
String name = form.kind.methodName;
switch (form.kind) {
case BOUND_REINVOKER: {
- name = name + "_" + BoundMethodHandle.speciesData(form).fieldSignature();
+ name = name + "_" + BoundMethodHandle.speciesDataFor(form).key();
return resolveFrom(name, invokerType, DelegatingMethodHandle.Holder.class);
}
case DELEGATE: return resolveFrom(name, invokerType, DelegatingMethodHandle.Holder.class);
--- a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java Thu Nov 16 10:45:42 2017 -0800
@@ -143,12 +143,22 @@
D_TYPE('D', double.class, Wrapper.DOUBLE), // all primitive types
V_TYPE('V', void.class, Wrapper.VOID); // not valid in all contexts
- static final BasicType[] ALL_TYPES = BasicType.values();
- static final BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1);
+ static final @Stable BasicType[] ALL_TYPES = BasicType.values();
+ static final @Stable BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1);
static final int ARG_TYPE_LIMIT = ARG_TYPES.length;
static final int TYPE_LIMIT = ALL_TYPES.length;
+ // Derived int constants, which (unlike the enums) can be constant folded.
+ // We can remove them when JDK-8161245 is fixed.
+ static final byte
+ L_TYPE_NUM = (byte) L_TYPE.ordinal(),
+ I_TYPE_NUM = (byte) I_TYPE.ordinal(),
+ J_TYPE_NUM = (byte) J_TYPE.ordinal(),
+ F_TYPE_NUM = (byte) F_TYPE.ordinal(),
+ D_TYPE_NUM = (byte) D_TYPE.ordinal(),
+ V_TYPE_NUM = (byte) V_TYPE.ordinal();
+
final char btChar;
final Class<?> btClass;
final Wrapper btWrapper;
@@ -679,6 +689,9 @@
Class<?> rtype = signatureReturn(sig).btClass;
return MethodType.makeImpl(rtype, ptypes, true);
}
+ static MethodType basicMethodType(MethodType mt) {
+ return signatureType(basicTypeSignature(mt));
+ }
/**
* Check if i-th name is a call to MethodHandleImpl.selectAlternative.
@@ -1291,14 +1304,28 @@
assert(sigp == sig.length);
return String.valueOf(sig);
}
+
+ /** Hack to make signatures more readable when they show up in method names.
+ * Signature should start with a sequence of uppercase ASCII letters.
+ * Runs of three or more are replaced by a single letter plus a decimal repeat count.
+ * A tail of anything other than uppercase ASCII is passed through unchanged.
+ * @param signature sequence of uppercase ASCII letters with possible repetitions
+ * @return same sequence, with repetitions counted by decimal numerals
+ */
public static String shortenSignature(String signature) {
- // Hack to make signatures more readable when they show up in method names.
final int NO_CHAR = -1, MIN_RUN = 3;
int c0, c1 = NO_CHAR, c1reps = 0;
StringBuilder buf = null;
int len = signature.length();
if (len < MIN_RUN) return signature;
for (int i = 0; i <= len; i++) {
+ if (c1 != NO_CHAR && !('A' <= c1 && c1 <= 'Z')) {
+ // wrong kind of char; bail out here
+ if (buf != null) {
+ buf.append(signature.substring(i - c1reps, len));
+ }
+ break;
+ }
// shift in the next char:
c0 = c1; c1 = (i == len ? NO_CHAR : signature.charAt(i));
if (c1 == c0) { ++c1reps; continue; }
@@ -1342,7 +1369,7 @@
this.arguments = that.arguments;
this.constraint = constraint;
assert(constraint == null || isParam()); // only params have constraints
- assert(constraint == null || constraint instanceof BoundMethodHandle.SpeciesData || constraint instanceof Class);
+ assert(constraint == null || constraint instanceof ClassSpecializer.SpeciesData || constraint instanceof Class);
}
Name(MethodHandle function, Object... arguments) {
this(new NamedFunction(function), arguments);
--- a/src/java.base/share/classes/java/lang/invoke/LambdaFormBuffer.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaFormBuffer.java Thu Nov 16 10:45:42 2017 -0800
@@ -27,6 +27,8 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
+
import static java.lang.invoke.LambdaForm.*;
import static java.lang.invoke.LambdaForm.BasicType.*;
@@ -325,15 +327,15 @@
* whose function is in the corresponding position in newFns.
* Only do this if the arguments are exactly equal to the given.
*/
- LambdaFormBuffer replaceFunctions(NamedFunction[] oldFns, NamedFunction[] newFns,
+ LambdaFormBuffer replaceFunctions(List<NamedFunction> oldFns, List<NamedFunction> newFns,
Object... forArguments) {
assert(inTrans());
- if (oldFns.length == 0) return this;
+ if (oldFns.isEmpty()) return this;
for (int i = arity; i < length; i++) {
Name n = names[i];
- int nfi = indexOf(n.function, oldFns);
+ int nfi = oldFns.indexOf(n.function);
if (nfi >= 0 && Arrays.equals(n.arguments, forArguments)) {
- changeName(i, new Name(newFns[nfi], n.arguments));
+ changeName(i, new Name(newFns.get(nfi), n.arguments));
}
}
return this;
--- a/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java Thu Nov 16 10:45:42 2017 -0800
@@ -381,10 +381,11 @@
/// Editing methods for method handles. These need to have fast paths.
private BoundMethodHandle.SpeciesData oldSpeciesData() {
- return BoundMethodHandle.speciesData(lambdaForm);
+ return BoundMethodHandle.speciesDataFor(lambdaForm);
}
+
private BoundMethodHandle.SpeciesData newSpeciesData(BasicType type) {
- return oldSpeciesData().extendWith(type);
+ return oldSpeciesData().extendWith((byte) type.ordinal());
}
BoundMethodHandle bindArgumentL(BoundMethodHandle mh, int pos, Object value) {
@@ -461,7 +462,7 @@
buf.replaceParameterByNewExpression(pos, new Name(getter, newBaseAddress));
} else {
// cannot bind the MH arg itself, unless oldData is empty
- assert(oldData == BoundMethodHandle.SpeciesData.EMPTY);
+ assert(oldData == BoundMethodHandle.SPECIALIZER.topSpecies());
newBaseAddress = new Name(L_TYPE).withConstraint(newData);
buf.replaceParameterByNewExpression(0, new Name(getter, newBaseAddress));
buf.insertParameter(0, newBaseAddress);
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Thu Nov 16 10:45:42 2017 -0800
@@ -776,11 +776,11 @@
if (PROFILE_GWT) {
int[] counts = new int[2];
mh = (BoundMethodHandle)
- BoundMethodHandle.speciesData_LLLL().constructor().invokeBasic(type, form,
+ BoundMethodHandle.speciesData_LLLL().factory().invokeBasic(type, form,
(Object) test, (Object) profile(target), (Object) profile(fallback), counts);
} else {
mh = (BoundMethodHandle)
- BoundMethodHandle.speciesData_LLL().constructor().invokeBasic(type, form,
+ BoundMethodHandle.speciesData_LLL().factory().invokeBasic(type, form,
(Object) test, (Object) profile(target), (Object) profile(fallback));
}
} catch (Throwable ex) {
@@ -1089,7 +1089,7 @@
BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
BoundMethodHandle mh;
try {
- mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, (Object) target, (Object) exType,
+ mh = (BoundMethodHandle) data.factory().invokeBasic(type, form, (Object) target, (Object) exType,
(Object) catcher, (Object) collectArgs, (Object) unboxResult);
} catch (Throwable ex) {
throw uncaughtException(ex);
@@ -1784,6 +1784,11 @@
MemberName memberName = (MemberName)mname;
return memberName.getName();
}
+ @Override
+ public Class<?> getDeclaringClass(Object mname) {
+ MemberName memberName = (MemberName)mname;
+ return memberName.getDeclaringClass();
+ }
@Override
public MethodType getMethodType(Object mname) {
@@ -1885,7 +1890,7 @@
BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
BoundMethodHandle mh;
try {
- mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, (Object) clauseData,
+ mh = (BoundMethodHandle) data.factory().invokeBasic(type, form, (Object) clauseData,
(Object) collectArgs, (Object) unboxResult);
} catch (Throwable ex) {
throw uncaughtException(ex);
@@ -2128,7 +2133,7 @@
BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLL();
BoundMethodHandle mh;
try {
- mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, (Object) target, (Object) cleanup,
+ mh = (BoundMethodHandle) data.factory().invokeBasic(type, form, (Object) target, (Object) cleanup,
(Object) collectArgs, (Object) unboxResult);
} catch (Throwable ex) {
throw uncaughtException(ex);
--- a/src/java.base/share/classes/java/lang/invoke/SimpleMethodHandle.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/SimpleMethodHandle.java Thu Nov 16 10:45:42 2017 -0800
@@ -25,6 +25,8 @@
package java.lang.invoke;
+import jdk.internal.vm.annotation.Stable;
+
import static java.lang.invoke.LambdaForm.BasicType.*;
import static java.lang.invoke.MethodHandleStatics.*;
@@ -33,6 +35,7 @@
* @author jrose
*/
final class SimpleMethodHandle extends BoundMethodHandle {
+
private SimpleMethodHandle(MethodType type, LambdaForm form) {
super(type, form);
}
@@ -41,10 +44,11 @@
return new SimpleMethodHandle(type, form);
}
- /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY;
+ /*non-public*/ static @Stable BoundMethodHandle.SpeciesData BMH_SPECIES;
- /*non-public*/ public SpeciesData speciesData() {
- return SPECIES_DATA;
+ @Override
+ /*non-public*/ BoundMethodHandle.SpeciesData speciesData() {
+ return BMH_SPECIES;
}
@Override
@@ -58,18 +62,13 @@
}
@Override
- /*non-public*/ public int fieldCount() {
- return 0;
- }
-
- @Override
/*non-public*/ final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
return BoundMethodHandle.bindSingle(mt, lf, narg); // Use known fast path.
}
@Override
/*non-public*/ final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
try {
- return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, narg);
+ return (BoundMethodHandle) BMH_SPECIES.extendWith(I_TYPE_NUM).factory().invokeBasic(mt, lf, narg);
} catch (Throwable ex) {
throw uncaughtException(ex);
}
@@ -77,7 +76,7 @@
@Override
/*non-public*/ final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
try {
- return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, narg);
+ return (BoundMethodHandle) BMH_SPECIES.extendWith(J_TYPE_NUM).factory().invokeBasic(mt, lf, narg);
} catch (Throwable ex) {
throw uncaughtException(ex);
}
@@ -85,7 +84,7 @@
@Override
/*non-public*/ final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
try {
- return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, narg);
+ return (BoundMethodHandle) BMH_SPECIES.extendWith(F_TYPE_NUM).factory().invokeBasic(mt, lf, narg);
} catch (Throwable ex) {
throw uncaughtException(ex);
}
@@ -93,7 +92,7 @@
@Override
/*non-public*/ final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
try {
- return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, narg);
+ return (BoundMethodHandle) BMH_SPECIES.extendWith(D_TYPE_NUM).factory().invokeBasic(mt, lf, narg);
} catch (Throwable ex) {
throw uncaughtException(ex);
}
--- a/src/java.base/share/classes/java/net/InetAddress.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/net/InetAddress.java Thu Nov 16 10:45:42 2017 -0800
@@ -1133,7 +1133,7 @@
/**
* Create an instance of the NameService interface based on
- * the setting of the {@codejdk.net.hosts.file} system property.
+ * the setting of the {@code jdk.net.hosts.file} system property.
*
* <p>The default NameService is the PlatformNameService, which typically
* delegates name and address resolution calls to the underlying
--- a/src/java.base/share/classes/java/util/stream/AbstractTask.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/util/stream/AbstractTask.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
import java.util.Spliterator;
import java.util.concurrent.CountedCompleter;
import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinWorkerThread;
/**
* Abstract base class for most fork-join tasks used to implement stream ops.
@@ -88,13 +89,7 @@
K extends AbstractTask<P_IN, P_OUT, R, K>>
extends CountedCompleter<R> {
- /**
- * Default target factor of leaf tasks for parallel decomposition.
- * To allow load balancing, we over-partition, currently to approximately
- * four tasks per processor, which enables others to help out
- * if leaf tasks are uneven or some processors are otherwise busy.
- */
- static final int LEAF_TARGET = ForkJoinPool.getCommonPoolParallelism() << 2;
+ private static final int LEAF_TARGET = ForkJoinPool.getCommonPoolParallelism() << 2;
/** The pipeline helper, common to all tasks in a computation */
protected final PipelineHelper<P_OUT> helper;
@@ -157,6 +152,22 @@
}
/**
+ * Default target of leaf tasks for parallel decomposition.
+ * To allow load balancing, we over-partition, currently to approximately
+ * four tasks per processor, which enables others to help out
+ * if leaf tasks are uneven or some processors are otherwise busy.
+ */
+ public static int getLeafTarget() {
+ Thread t = Thread.currentThread();
+ if (t instanceof ForkJoinWorkerThread) {
+ return ((ForkJoinWorkerThread) t).getPool().getParallelism() << 2;
+ }
+ else {
+ return LEAF_TARGET;
+ }
+ }
+
+ /**
* Constructs a new node of type T whose parent is the receiver; must call
* the AbstractTask(T, Spliterator) constructor with the receiver and the
* provided Spliterator.
@@ -181,7 +192,7 @@
* @return suggested target leaf size
*/
public static long suggestTargetSize(long sizeEstimate) {
- long est = sizeEstimate / LEAF_TARGET;
+ long est = sizeEstimate / getLeafTarget();
return est > 0L ? est : 1L;
}
--- a/src/java.base/share/classes/java/util/stream/ForEachOps.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/util/stream/ForEachOps.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,6 @@
import java.util.Spliterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountedCompleter;
-import java.util.concurrent.ForkJoinTask;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
@@ -378,7 +377,7 @@
this.spliterator = spliterator;
this.targetSize = AbstractTask.suggestTargetSize(spliterator.estimateSize());
// Size map to avoid concurrent re-sizes
- this.completionMap = new ConcurrentHashMap<>(Math.max(16, AbstractTask.LEAF_TARGET << 1));
+ this.completionMap = new ConcurrentHashMap<>(Math.max(16, AbstractTask.getLeafTarget() << 1));
this.action = action;
this.leftPredecessor = null;
}
--- a/src/java.base/share/classes/java/util/stream/StreamSpliterators.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/java/util/stream/StreamSpliterators.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -897,7 +897,7 @@
* Note: The source spliterator may report {@code ORDERED} since that
* spliterator be the result of a previous pipeline stage that was
* collected to a {@code Node}. It is the order of the pipeline stage
- * that governs whether the this slice spliterator is to be used or not.
+ * that governs whether this slice spliterator is to be used or not.
*/
abstract static class UnorderedSliceSpliterator<T, T_SPLITR extends Spliterator<T>> {
static final int CHUNK_SIZE = 1 << 7;
@@ -914,7 +914,7 @@
this.unlimited = limit < 0;
this.skipThreshold = limit >= 0 ? limit : 0;
this.chunkSize = limit >= 0 ? (int)Math.min(CHUNK_SIZE,
- ((skip + limit) / AbstractTask.LEAF_TARGET) + 1) : CHUNK_SIZE;
+ ((skip + limit) / AbstractTask.getLeafTarget()) + 1) : CHUNK_SIZE;
this.permits = new AtomicLong(limit >= 0 ? skip + limit : skip);
}
--- a/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/classes/jdk/internal/misc/JavaLangInvokeAccess.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,34 +30,40 @@
public interface JavaLangInvokeAccess {
/**
- * Create a new MemberName instance. Used by {@see StackFrameInfo}.
+ * Create a new MemberName instance. Used by {@code StackFrameInfo}.
*/
Object newMemberName();
/**
- * Returns the name for the given MemberName. Used by {@see StackFrameInfo}.
+ * Returns the name for the given MemberName. Used by {@code StackFrameInfo}.
*/
String getName(Object mname);
/**
* Returns the {@code MethodType} for the given MemberName.
- * Used by {@see StackFrameInfo}.
+ * Used by {@code StackFrameInfo}.
*/
MethodType getMethodType(Object mname);
/**
* Returns the descriptor for the given MemberName.
- * Used by {@see StackFrameInfo}.
+ * Used by {@code StackFrameInfo}.
*/
String getMethodDescriptor(Object mname);
/**
- * Returns {@code true} if the given MemberName is a native method. Used by
- * {@see StackFrameInfo}.
+ * Returns {@code true} if the given MemberName is a native method.
+ * Used by {@code StackFrameInfo}.
*/
boolean isNative(Object mname);
/**
+ * Returns the declaring class for the given MemberName.
+ * Used by {@code StackFrameInfo}.
+ */
+ Class<?> getDeclaringClass(Object mname);
+
+ /**
* Returns a {@code byte[]} representation of a class implementing
* DirectMethodHandle of each pairwise combination of {@code MethodType} and
* an {@code int} representing method type. Used by
--- a/src/java.base/share/native/include/classfile_constants.h Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/native/include/classfile_constants.h Thu Nov 16 10:45:42 2017 -0800
@@ -54,9 +54,29 @@
JVM_ACC_STRICT = 0x0800,
JVM_ACC_SYNTHETIC = 0x1000,
JVM_ACC_ANNOTATION = 0x2000,
- JVM_ACC_ENUM = 0x4000
+ JVM_ACC_ENUM = 0x4000,
+ JVM_ACC_MODULE = 0x8000
};
+#define JVM_ACC_PUBLIC_BIT 0
+#define JVM_ACC_PRIVATE_BIT 1
+#define JVM_ACC_PROTECTED_BIT 2
+#define JVM_ACC_STATIC_BIT 3
+#define JVM_ACC_FINAL_BIT 4
+#define JVM_ACC_SYNCHRONIZED_BIT 5
+#define JVM_ACC_SUPER_BIT 5
+#define JVM_ACC_VOLATILE_BIT 6
+#define JVM_ACC_BRIDGE_BIT 6
+#define JVM_ACC_TRANSIENT_BIT 7
+#define JVM_ACC_VARARGS_BIT 7
+#define JVM_ACC_NATIVE_BIT 8
+#define JVM_ACC_INTERFACE_BIT 9
+#define JVM_ACC_ABSTRACT_BIT 10
+#define JVM_ACC_STRICT_BIT 11
+#define JVM_ACC_SYNTHETIC_BIT 12
+#define JVM_ACC_ANNOTATION_BIT 13
+#define JVM_ACC_ENUM_BIT 14
+
/* Used in newarray instruction. */
enum {
@@ -86,8 +106,9 @@
JVM_CONSTANT_InterfaceMethodref = 11,
JVM_CONSTANT_NameAndType = 12,
JVM_CONSTANT_MethodHandle = 15, // JSR 292
- JVM_CONSTANT_MethodType = 16, // JSR 292
- JVM_CONSTANT_InvokeDynamic = 18
+ JVM_CONSTANT_MethodType = 16, // JSR 292
+ JVM_CONSTANT_InvokeDynamic = 18,
+ JVM_CONSTANT_ExternalMax = 18
};
/* JVM_CONSTANT_MethodHandle subtypes */
--- a/src/java.base/share/native/include/jvm.h Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/share/native/include/jvm.h Thu Nov 16 10:45:42 2017 -0800
@@ -1155,20 +1155,25 @@
* be renamed to JVM_* in the future?
*/
-/*
- * BE CAREFUL! The following functions do not implement the
- * full feature set of standard C printf formats.
- */
-int
+/* jio_snprintf() and jio_vsnprintf() behave like snprintf(3) and vsnprintf(3),
+ * respectively, with the following differences:
+ * - The string written to str is always zero-terminated, also in case of
+ * truncation (count is too small to hold the result string), unless count
+ * is 0. In case of truncation count-1 characters are written and '\0'
+ * appendend.
+ * - If count is too small to hold the whole string, -1 is returned across
+ * all platforms. */
+
+JNIEXPORT int
jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
-int
+JNIEXPORT int
jio_snprintf(char *str, size_t count, const char *fmt, ...);
-int
+JNIEXPORT int
jio_fprintf(FILE *, const char *fmt, ...);
-int
+JNIEXPORT int
jio_vfprintf(FILE *, const char *fmt, va_list args);
--- a/src/java.base/solaris/native/libjsig/jsig.c Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/solaris/native/libjsig/jsig.c Thu Nov 16 10:45:42 2017 -0800
@@ -37,7 +37,7 @@
#include <dlfcn.h>
#include <thread.h>
#include <synch.h>
-#include "jvm_solaris.h"
+#include "jvm_md.h"
#define bool int
#define true 1
--- a/src/java.base/unix/native/include/jni_md.h Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/unix/native/include/jni_md.h Thu Nov 16 10:45:42 2017 -0800
@@ -30,8 +30,13 @@
#define __has_attribute(x) 0
#endif
#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
- #define JNIEXPORT __attribute__((visibility("default")))
- #define JNIIMPORT __attribute__((visibility("default")))
+ #ifdef ARM
+ #define JNIEXPORT __attribute__((externally_visible,visibility("default")))
+ #define JNIIMPORT __attribute__((externally_visible,visibility("default")))
+ #else
+ #define JNIEXPORT __attribute__((visibility("default")))
+ #define JNIIMPORT __attribute__((visibility("default")))
+ #endif
#else
#define JNIEXPORT
#define JNIIMPORT
@@ -40,7 +45,7 @@
#define JNICALL
typedef int jint;
-#ifdef _LP64 /* 64-bit Solaris */
+#ifdef _LP64
typedef long jlong;
#else
typedef long long jlong;
--- a/src/java.base/unix/native/include/jvm_md.h Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/unix/native/include/jvm_md.h Thu Nov 16 10:45:42 2017 -0800
@@ -39,6 +39,10 @@
#define JNI_ONLOAD_SYMBOLS {"JNI_OnLoad"}
#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"}
+#define JVM_ONLOAD_SYMBOLS {"JVM_OnLoad"}
+#define AGENT_ONLOAD_SYMBOLS {"Agent_OnLoad"}
+#define AGENT_ONUNLOAD_SYMBOLS {"Agent_OnUnload"}
+#define AGENT_ONATTACH_SYMBOLS {"Agent_OnAttach"}
#define JNI_LIB_PREFIX "lib"
#ifdef __APPLE__
@@ -50,7 +54,15 @@
#endif
#define JNI_LIB_NAME(NAME) JNI_LIB_PREFIX NAME JNI_LIB_SUFFIX
+#if defined(AIX) || defined(SOLARIS)
#define JVM_MAXPATHLEN MAXPATHLEN
+#else
+// Hack: MAXPATHLEN is 4095 on some Linux and 4096 on others. This may
+// cause problems if JVM and the rest of JDK are built on different
+// Linux releases. Here we define JVM_MAXPATHLEN to be MAXPATHLEN + 1,
+// so buffers declared in VM are always >= 4096.
+#define JVM_MAXPATHLEN MAXPATHLEN + 1
+#endif
#define JVM_R_OK R_OK
#define JVM_W_OK W_OK
@@ -67,19 +79,22 @@
#include <errno.h>
#include <signal.h>
-/* O Flags */
+/* Signals */
-#define JVM_O_RDONLY O_RDONLY
-#define JVM_O_WRONLY O_WRONLY
-#define JVM_O_RDWR O_RDWR
-#define JVM_O_O_APPEND O_APPEND
-#define JVM_O_EXCL O_EXCL
-#define JVM_O_CREAT O_CREAT
-
-/* Signals */
+#include <sys/socket.h> // for socklen_t
#define JVM_SIGINT SIGINT
#define JVM_SIGTERM SIGTERM
+#define BREAK_SIGNAL SIGQUIT /* Thread dumping support. */
+#ifdef SOLARIS
+#define ASYNC_SIGNAL SIGJVM2 /* Event-based suspend/resume support */
+#endif // SOLARIS
+#define SHUTDOWN1_SIGNAL SIGHUP /* Shutdown Hooks support. */
+#define SHUTDOWN2_SIGNAL SIGINT
+#define SHUTDOWN3_SIGNAL SIGTERM
+
+/* With 1.4.1 libjsig added versioning: used in os_solaris.cpp and jsig.c */
+#define JSIG_VERSION_1_4_1 0x30140100
#endif /* !_JAVASOFT_JVM_MD_H_ */
--- a/src/java.base/unix/native/libjava/UnixFileSystem_md.c Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/unix/native/libjava/UnixFileSystem_md.c Thu Nov 16 10:45:42 2017 -0800
@@ -38,11 +38,13 @@
#include <stdlib.h>
#include <dlfcn.h>
#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
#include "jni.h"
#include "jni_util.h"
#include "jlong.h"
-#include "jvm.h"
#include "io_util.h"
#include "io_util_md.h"
#include "java_io_FileSystem.h"
@@ -97,9 +99,9 @@
jstring rv = NULL;
WITH_PLATFORM_STRING(env, pathname, path) {
- char canonicalPath[JVM_MAXPATHLEN];
+ char canonicalPath[PATH_MAX];
if (canonicalize((char *)path,
- canonicalPath, JVM_MAXPATHLEN) < 0) {
+ canonicalPath, PATH_MAX) < 0) {
JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
} else {
#ifdef MACOSX
--- a/src/java.base/windows/native/include/jni_md.h Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/windows/native/include/jni_md.h Thu Nov 16 10:45:42 2017 -0800
@@ -30,6 +30,7 @@
#define JNIIMPORT __declspec(dllimport)
#define JNICALL __stdcall
+// 'long' is always 32 bit on windows so this matches what jdk expects
typedef long jint;
typedef __int64 jlong;
typedef signed char jbyte;
--- a/src/java.base/windows/native/include/jvm_md.h Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.base/windows/native/include/jvm_md.h Thu Nov 16 10:45:42 2017 -0800
@@ -31,13 +31,20 @@
* JNI conversion, which should be sorted out later.
*/
+#include <windows.h>
#include <windef.h>
#include <winbase.h>
#include "jni.h"
+typedef int socklen_t;
+
#define JNI_ONLOAD_SYMBOLS {"_JNI_OnLoad@8", "JNI_OnLoad"}
#define JNI_ONUNLOAD_SYMBOLS {"_JNI_OnUnload@8", "JNI_OnUnload"}
+#define JVM_ONLOAD_SYMBOLS {"_JVM_OnLoad@12", "JVM_OnLoad"}
+#define AGENT_ONLOAD_SYMBOLS {"_Agent_OnLoad@12", "Agent_OnLoad"}
+#define AGENT_ONUNLOAD_SYMBOLS {"_Agent_OnUnload@4", "Agent_OnUnload"}
+#define AGENT_ONATTACH_SYMBOLS {"_Agent_OnAttach@12", "Agent_OnAttach"}
#define JNI_LIB_PREFIX ""
#define JNI_LIB_SUFFIX ".dll"
@@ -63,21 +70,16 @@
#define JVM_X_OK 1
#define JVM_F_OK 0
+#ifdef __cplusplus
+extern "C" {
+#endif
+
JNIEXPORT void * JNICALL
JVM_GetThreadInterruptEvent();
-/*
- * These routines are only reentrant on Windows
- */
-
-JNIEXPORT struct protoent * JNICALL
-JVM_GetProtoByName(char* name);
-
-JNIEXPORT struct hostent* JNICALL
-JVM_GetHostByAddr(const char* name, int len, int type);
-
-JNIEXPORT struct hostent* JNICALL
-JVM_GetHostByName(char* name);
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
/*
* File I/O
@@ -89,19 +91,12 @@
#include <errno.h>
#include <signal.h>
-/* O Flags */
-
-#define JVM_O_RDONLY O_RDONLY
-#define JVM_O_WRONLY O_WRONLY
-#define JVM_O_RDWR O_RDWR
-#define JVM_O_O_APPEND O_APPEND
-#define JVM_O_EXCL O_EXCL
-#define JVM_O_CREAT O_CREAT
-
/* Signals */
#define JVM_SIGINT SIGINT
#define JVM_SIGTERM SIGTERM
+#define SHUTDOWN1_SIGNAL SIGINT /* Shutdown Hooks support. */
+#define SHUTDOWN2_SIGNAL SIGTERM
#endif /* !_JAVASOFT_JVM_MD_H_ */
--- a/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.instrument/share/classes/sun/instrument/InstrumentationImpl.java Thu Nov 16 10:45:42 2017 -0800
@@ -103,6 +103,9 @@
}
} else {
mTransformerManager.addTransformer(transformer);
+ if (mTransformerManager.getTransformerCount() == 1) {
+ setHasTransformers(mNativeAgent, true);
+ }
}
}
@@ -114,8 +117,12 @@
TransformerManager mgr = findTransformerManager(transformer);
if (mgr != null) {
mgr.removeTransformer(transformer);
- if (mgr.isRetransformable() && mgr.getTransformerCount() == 0) {
- setHasRetransformableTransformers(mNativeAgent, false);
+ if (mgr.getTransformerCount() == 0) {
+ if (mgr.isRetransformable()) {
+ setHasRetransformableTransformers(mNativeAgent, false);
+ } else {
+ setHasTransformers(mNativeAgent, false);
+ }
}
return true;
}
@@ -362,6 +369,9 @@
isRetransformClassesSupported0(long nativeAgent);
private native void
+ setHasTransformers(long nativeAgent, boolean has);
+
+ private native void
setHasRetransformableTransformers(long nativeAgent, boolean has);
private native void
--- a/src/java.instrument/share/native/libinstrument/InstrumentationImplNativeMethods.c Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.instrument/share/native/libinstrument/InstrumentationImplNativeMethods.c Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -78,6 +78,17 @@
/*
* Class: sun_instrument_InstrumentationImpl
+ * Method: setHasTransformers
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_instrument_InstrumentationImpl_setHasTransformers
+ (JNIEnv * jnienv, jobject implThis, jlong agent, jboolean has) {
+ setHasTransformers(jnienv, (JPLISAgent*)(intptr_t)agent, has);
+}
+
+/*
+ * Class: sun_instrument_InstrumentationImpl
* Method: setHasRetransformableTransformers
* Signature: (Z)V
*/
--- a/src/java.instrument/share/native/libinstrument/InvocationAdapter.c Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.instrument/share/native/libinstrument/InvocationAdapter.c Thu Nov 16 10:45:42 2017 -0800
@@ -395,7 +395,7 @@
jplis_assert(success);
/*
- * Turn on the ClassFileLoadHook.
+ * Setup ClassFileLoadHook handler.
*/
if (success) {
success = setLivePhaseEventHandlers(agent);
--- a/src/java.instrument/share/native/libinstrument/JPLISAgent.c Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.instrument/share/native/libinstrument/JPLISAgent.c Thu Nov 16 10:45:42 2017 -0800
@@ -404,8 +404,8 @@
/*
- * Then turn off the VMInit handler and turn on the ClassFileLoadHook.
- * This way it is on before anyone registers a transformer.
+ * Register a handler for ClassFileLoadHook (without enabling this event).
+ * Turn off the VMInit handler.
*/
if ( result ) {
result = setLivePhaseEventHandlers(agent);
@@ -649,17 +649,6 @@
jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
}
- if ( jvmtierror == JVMTI_ERROR_NONE ) {
- /* turn on ClassFileLoadHook */
- jvmtierror = (*jvmtienv)->SetEventNotificationMode(
- jvmtienv,
- JVMTI_ENABLE,
- JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
- NULL /* all threads */);
- check_phase_ret_false(jvmtierror);
- jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
- }
-
return (jvmtierror == JVMTI_ERROR_NONE);
}
@@ -1097,6 +1086,21 @@
}
void
+setHasTransformers(JNIEnv * jnienv, JPLISAgent * agent, jboolean has) {
+ jvmtiEnv * jvmtienv = jvmti(agent);
+ jvmtiError jvmtierror;
+
+ jplis_assert(jvmtienv != NULL);
+ jvmtierror = (*jvmtienv)->SetEventNotificationMode(
+ jvmtienv,
+ has? JVMTI_ENABLE : JVMTI_DISABLE,
+ JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
+ NULL /* all threads */);
+ check_phase_ret(jvmtierror);
+ jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
+}
+
+void
setHasRetransformableTransformers(JNIEnv * jnienv, JPLISAgent * agent, jboolean has) {
jvmtiEnv * retransformerEnv = retransformableEnvironment(agent);
jvmtiError jvmtierror;
@@ -1107,6 +1111,7 @@
has? JVMTI_ENABLE : JVMTI_DISABLE,
JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
NULL /* all threads */);
+ check_phase_ret(jvmtierror);
jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
}
@@ -1185,6 +1190,10 @@
deallocate(retransformerEnv, (void*)classArray);
}
+ /* Return back if we executed the JVMTI API in a wrong phase
+ */
+ check_phase_ret(errorCode);
+
if (errorCode != JVMTI_ERROR_NONE) {
createAndThrowThrowableFromJVMTIErrorCode(jnienv, errorCode);
}
--- a/src/java.instrument/share/native/libinstrument/JPLISAgent.h Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.instrument/share/native/libinstrument/JPLISAgent.h Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -120,7 +120,11 @@
JNIEnv * jnienv,
jthread thread);
-/* ClassFileLoadHook event handler. Installed during VMInit, then left in place forever. */
+/*
+ * ClassFileLoadHook event handler.
+ * Enabled when the first transformer is added;
+ * Disabled when the last transformer is removed.
+ */
extern void JNICALL
eventHandlerClassFileLoadHook( jvmtiEnv * jvmtienv,
JNIEnv * jnienv,
@@ -241,6 +245,9 @@
isRetransformClassesSupported(JNIEnv * jnienv, JPLISAgent * agent);
extern void
+setHasTransformers(JNIEnv * jnienv, JPLISAgent * agent, jboolean has);
+
+extern void
setHasRetransformableTransformers(JNIEnv * jnienv, JPLISAgent * agent, jboolean has);
extern void
--- a/src/java.management/share/classes/java/lang/management/RuntimeMXBean.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.management/share/classes/java/lang/management/RuntimeMXBean.java Thu Nov 16 10:45:42 2017 -0800
@@ -25,6 +25,9 @@
package java.lang.management;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
/**
* The management interface for the runtime system of
* the Java virtual machine.
@@ -61,6 +64,22 @@
*/
public interface RuntimeMXBean extends PlatformManagedObject {
/**
+ * Returns the {@linkplain ProcessHandle#pid process ID} representing
+ * the running Java virtual machine.
+ *
+ * @implSpec The default implementation returns {@link ProcessHandle#pid process ID}
+ * of the {@linkplain ProcessHandle#current current process}.
+ *
+ * @return the process ID representing the running Java virtual machine.
+ *
+ * @since 10
+ */
+ public default long getPid() {
+ return AccessController.doPrivileged((PrivilegedAction<Long>)
+ () -> ProcessHandle.current().pid());
+ }
+
+ /**
* Returns the name representing the running Java virtual machine.
* The returned name string can be any arbitrary string and
* a Java virtual machine implementation can choose
--- a/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java Thu Nov 16 10:45:42 2017 -0800
@@ -176,6 +176,8 @@
* @param args names of the arguments in the method call.
*
* @return The String used to invoke the method in the syntax of the scripting language.
+ *
+ * @throws NullPointerException if obj or m or args or any of the elements of args is null.
*/
public String getMethodCallSyntax(String obj, String m, String... args);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java Thu Nov 16 10:45:42 2017 -0800
@@ -192,6 +192,8 @@
{"StubRoutines::_checkcast_arraycopy", "_aot_stub_routines_checkcast_arraycopy"},
+ {"StubRoutines::_generic_arraycopy", "_aot_stub_routines_generic_arraycopy"},
+
{"StubRoutines::_aescrypt_encryptBlock", "_aot_stub_routines_aescrypt_encryptBlock"},
{"StubRoutines::_aescrypt_decryptBlock", "_aot_stub_routines_aescrypt_decryptBlock"},
{"StubRoutines::_cipherBlockChaining_encryptAESCrypt", "_aot_stub_routines_cipherBlockChaining_encryptAESCrypt"},
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapPair.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapPair.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -34,8 +34,8 @@
import java.util.Observer;
public class ImmutableOopMapPair {
- private static CIntegerField pcField;
- private static CIntegerField offsetField;
+ private static CIntegerField pcOffsetField;
+ private static CIntegerField oopmapOffsetField;
private static long classSize;
static {
@@ -57,18 +57,18 @@
}
public int getPC() {
- return (int) pcField.getValue(address);
+ return (int) pcOffsetField.getValue(address);
}
public int getOffset() {
- return (int) offsetField.getValue(address);
+ return (int) oopmapOffsetField.getValue(address);
}
private static void initialize(TypeDataBase db) {
Type type = db.lookupType("ImmutableOopMapPair");
- pcField = type.getCIntegerField("_pc_offset");
- offsetField = type.getCIntegerField("_oopmap_offset");
+ pcOffsetField = type.getCIntegerField("_pc_offset");
+ oopmapOffsetField = type.getCIntegerField("_oopmap_offset");
classSize = type.getSize();
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/cms/CompactibleFreeListSpace.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/cms/CompactibleFreeListSpace.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -41,10 +41,11 @@
private static AddressField dictionaryField;
private static long smallLinearAllocBlockFieldOffset;
- private int heapWordSize; // 4 for 32bit, 8 for 64 bits
- private int IndexSetStart; // for small indexed list
- private int IndexSetSize;
- private int IndexSetStride;
+ private int heapWordSize; // 4 for 32bit, 8 for 64 bits
+ private int IndexSetStart; // for small indexed list
+ private int IndexSetSize;
+ private int IndexSetStride;
+ private static long MinChunkSizeInBytes;
static {
VM.registerVMInitializedObserver(new Observer() {
@@ -57,8 +58,6 @@
private static synchronized void initialize(TypeDataBase db) {
long sizeofFreeChunk = db.lookupType("FreeChunk").getSize();
VM vm = VM.getVM();
- MinChunkSizeInBytes = numQuanta(sizeofFreeChunk, vm.getMinObjAlignmentInBytes()) *
- vm.getMinObjAlignmentInBytes();
Type type = db.lookupType("CompactibleFreeListSpace");
collectorField = type.getAddressField("_collector");
@@ -66,6 +65,7 @@
dictionaryField = type.getAddressField("_dictionary");
indexedFreeListField = type.getAddressField("_indexedFreeList[0]");
smallLinearAllocBlockFieldOffset = type.getField("_smallLinearAllocBlock").getOffset();
+ MinChunkSizeInBytes = (type.getCIntegerField("_min_chunk_size_in_bytes")).getValue();
}
public CompactibleFreeListSpace(Address addr) {
@@ -74,7 +74,7 @@
heapWordSize = vm.getHeapWordSize();
IndexSetStart = vm.getMinObjAlignmentInBytes() / heapWordSize;
IndexSetStride = IndexSetStart;
- IndexSetSize = 257;
+ IndexSetSize = vm.getIndexSetSize();
}
// Accessing block offset table
@@ -201,14 +201,8 @@
// Unlike corresponding VM code, we operate on byte size rather than
// HeapWord size for convenience.
- private static long numQuanta(long x, long y) {
- return ((x+y-1)/y);
- }
-
public static long adjustObjectSizeInBytes(long sizeInBytes) {
return Oop.alignObjectSize(Math.max(sizeInBytes, MinChunkSizeInBytes));
}
- // FIXME: should I read this directly from VM?
- private static long MinChunkSizeInBytes;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/serial/SerialHeap.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.gc.serial;
+
+import sun.jvm.hotspot.debugger.Address;
+import sun.jvm.hotspot.gc.shared.GenCollectedHeap;
+import sun.jvm.hotspot.gc.shared.CollectedHeapName;
+
+public class SerialHeap extends GenCollectedHeap {
+
+ public SerialHeap(Address addr) {
+ super(addr);
+ }
+
+ public CollectedHeapName kind() {
+ return CollectedHeapName.SERIAL_HEAP;
+ }
+}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CollectedHeapName.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CollectedHeapName.java Thu Nov 16 10:45:42 2017 -0800
@@ -33,6 +33,7 @@
public static final CollectedHeapName GEN_COLLECTED_HEAP = new CollectedHeapName("GenCollectedHeap");
public static final CollectedHeapName CMS_HEAP = new CollectedHeapName("CMSHeap");
+ public static final CollectedHeapName SERIAL_HEAP = new CollectedHeapName("SerialHeap");
public static final CollectedHeapName G1_COLLECTED_HEAP = new CollectedHeapName("G1CollectedHeap");
public static final CollectedHeapName PARALLEL_SCAVENGE_HEAP = new CollectedHeapName("ParallelScavengeHeap");
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java Thu Nov 16 10:45:42 2017 -0800
@@ -28,6 +28,7 @@
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.gc.cms.CMSHeap;
+import sun.jvm.hotspot.gc.serial.SerialHeap;
import sun.jvm.hotspot.gc.shared.*;
import sun.jvm.hotspot.gc.g1.G1CollectedHeap;
import sun.jvm.hotspot.gc.parallel.*;
@@ -77,8 +78,8 @@
collectedHeapField = type.getAddressField("_collectedHeap");
heapConstructor = new VirtualConstructor(db);
- heapConstructor.addMapping("GenCollectedHeap", GenCollectedHeap.class);
heapConstructor.addMapping("CMSHeap", CMSHeap.class);
+ heapConstructor.addMapping("SerialHeap", SerialHeap.class);
heapConstructor.addMapping("ParallelScavengeHeap", ParallelScavengeHeap.class);
heapConstructor.addMapping("G1CollectedHeap", G1CollectedHeap.class);
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/TypeArrayKlass.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/TypeArrayKlass.java Thu Nov 16 10:45:42 2017 -0800
@@ -44,14 +44,14 @@
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type t = db.lookupType("TypeArrayKlass");
- maxLength = new CIntField(t.getCIntegerField("_max_length"), 0);
+ maxLength = new IntField(t.getJIntField("_max_length"), 0);
}
public TypeArrayKlass(Address addr) {
super(addr);
}
- private static CIntField maxLength;
+ private static IntField maxLength;
public long getMaxLength() { return maxLength.getValue(this); }
@@ -98,7 +98,7 @@
public void iterateFields(MetadataVisitor visitor) {
super.iterateFields(visitor);
- visitor.doCInt(maxLength, true);
+ visitor.doInt(maxLength, true);
}
public Klass arrayKlassImpl(boolean orNull, int n) {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Arguments.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Arguments.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,11 +42,11 @@
}
public static String getJVMFlags() {
- return buildString(jvmFlagsField, jvmFlagsCount);
+ return buildString(jvmFlagsArrayField, numJvmFlags);
}
public static String getJVMArgs() {
- return buildString(jvmArgsField, jvmArgsCount);
+ return buildString(jvmArgsArrayField, numJvmArgs);
}
public static String getJavaCommand() {
@@ -56,20 +56,20 @@
// Internals only below this point
// Fields
- private static AddressField jvmFlagsField;
- private static AddressField jvmArgsField;
+ private static AddressField jvmFlagsArrayField;
+ private static AddressField jvmArgsArrayField;
private static AddressField javaCommandField;
- private static long jvmFlagsCount;
- private static long jvmArgsCount;
+ private static long numJvmFlags;
+ private static long numJvmArgs;
private static synchronized void initialize(TypeDataBase db) {
Type argumentsType = db.lookupType("Arguments");
- jvmFlagsField = argumentsType.getAddressField("_jvm_flags_array");
- jvmArgsField = argumentsType.getAddressField("_jvm_args_array");
+ jvmFlagsArrayField = argumentsType.getAddressField("_jvm_flags_array");
+ jvmArgsArrayField = argumentsType.getAddressField("_jvm_args_array");
javaCommandField = argumentsType.getAddressField("_java_command");
- jvmArgsCount = argumentsType.getCIntegerField("_num_jvm_args").getValue();
- jvmFlagsCount = argumentsType.getCIntegerField("_num_jvm_flags").getValue();
+ numJvmArgs = argumentsType.getCIntegerField("_num_jvm_args").getValue();
+ numJvmFlags = argumentsType.getCIntegerField("_num_jvm_flags").getValue();
}
private static String buildString(AddressField arrayField, long count) {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompilerThread.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompilerThread.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -39,19 +39,19 @@
});
}
- private static AddressField _env_field;
+ private static AddressField envField;
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("CompilerThread");
- _env_field = type.getAddressField("_env");
+ envField = type.getAddressField("_env");
}
private ciEnv _env;
public synchronized ciEnv env() {
if (_env == null) {
- Address v = _env_field.getValue(this.getAddress());
+ Address v = envField.getValue(this.getAddress());
if (v != null) {
_env = new ciEnv(v);
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JNIid.java Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2002, 2012, 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 sun.jvm.hotspot.runtime;
-
-import java.util.*;
-
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.types.*;
-
-public class JNIid extends VMObject {
- private static MetadataField holder;
- private static AddressField next;
- private static CIntegerField offset;
- private static MetadataField resolvedMethod;
- private static MetadataField resolvedReceiver;
-
- private ObjectHeap heap;
-
- static {
- VM.registerVMInitializedObserver(new Observer() {
- public void update(Observable o, Object data) {
- initialize(VM.getVM().getTypeDataBase());
- }
- });
- }
-
- private static synchronized void initialize(TypeDataBase db) {
-
- // FIXME: JNIid has been removed as part of redesign of JNI method,
- // field ID generation. Please refer to src/share/vm/prims/jniId.hpp/.cpp
- // For now, commenting out the below code.
-
- /***********************************************************
- Type type = db.lookupType("JNIid");
-
- holder = type.getOopField("_holder");
- next = type.getAddressField("_next");
- offset = type.getCIntegerField("_offset");
- resolvedMethod = type.getOopField("_resolved_method");
- resolvedReceiver = type.getOopField("_resolved_receiver");
- ***********************************************************/
- }
-
- public JNIid(Address addr, ObjectHeap heap) {
- super(addr);
- this.heap = heap;
- }
-
- public JNIid next() {
- Address nextAddr = next.getValue(addr);
- if (nextAddr == null) {
- return null;
- }
- return new JNIid(nextAddr, heap);
- }
-
- public Klass holder() { return (Klass) holder.getValue(addr); }
- public int offset() { return (int) offset.getValue(addr); }
- public Method method() {
- return ((InstanceKlass) holder()).getMethods().at(offset());
- }
- public Method resolvedMethod() { return (Method)resolvedMethod.getValue(addr); }
- public Klass resolvedReceiver() { return (Klass) resolvedReceiver.getValue(addr); }
-}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/PerfMemory.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/PerfMemory.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,7 @@
private static AddressField topField;
private static CIntegerField capacityField;
private static AddressField prologueField;
- private static JIntField initializedField;
+ private static CIntegerField initializedField;
static {
VM.registerVMInitializedObserver(new Observer() {
@@ -52,7 +52,7 @@
topField = type.getAddressField("_top");
capacityField = type.getCIntegerField("_capacity");
prologueField = type.getAddressField("_prologue");
- initializedField = type.getJIntField("_initialized");
+ initializedField = type.getCIntegerField("_initialized");
}
// Accessors
@@ -73,7 +73,7 @@
}
public static boolean initialized() {
- return ((int) initializedField.getValue()) != 0;
+ return (initializedField.getValue()) != 0;
}
public static PerfDataPrologue prologue() {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -105,6 +105,7 @@
private int heapOopSize;
private int klassPtrSize;
private int oopSize;
+ private final int IndexSetSize;
/** This is only present in a non-core build */
private CodeCache codeCache;
/** This is only present in a C1 build */
@@ -376,6 +377,7 @@
bytesPerWord = db.lookupIntConstant("BytesPerWord").intValue();
heapWordSize = db.lookupIntConstant("HeapWordSize").intValue();
oopSize = db.lookupIntConstant("oopSize").intValue();
+ IndexSetSize = db.lookupIntConstant("CompactibleFreeListSpace::IndexSetSize").intValue();
intType = db.lookupType("int");
uintType = db.lookupType("uint");
@@ -594,6 +596,10 @@
return heapOopSize;
}
+ public int getIndexSetSize() {
+ return IndexSetSize;
+ }
+
public int getKlassPtrSize() {
return klassPtrSize;
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -43,7 +43,7 @@
private static AddressField osThreadField;
// Field from OSThread
- private static Field osThreadThreadIdField;
+ private static Field threadIdField;
// This is currently unneeded but is being kept in case we change
// the currentFrameGuess algorithm
@@ -64,7 +64,7 @@
osThreadField = type.getAddressField("_osthread");
type = db.lookupType("OSThread");
- osThreadThreadIdField = type.getField("_thread_id");
+ threadIdField = type.getField("_thread_id");
}
public Address getLastJavaFP(Address addr) {
@@ -130,7 +130,7 @@
Address osThreadAddr = osThreadField.getValue(addr);
// Get the address of the thread_id within the OSThread
Address threadIdAddr =
- osThreadAddr.addOffsetTo(osThreadThreadIdField.getOffset());
+ osThreadAddr.addOffsetTo(threadIdField.getOffset());
JVMDebugger debugger = VM.getVM().getDebugger();
return debugger.getThreadForIdentifierAddress(threadIdAddr);
}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
private static AddressField osThreadField;
// Field from OSThread
- private static Field osThreadThreadIdField;
+ private static Field threadIdField;
// This is currently unneeded but is being kept in case we change
// the currentFrameGuess algorithm
@@ -63,7 +63,7 @@
osThreadField = type.getAddressField("_osthread");
type = db.lookupType("OSThread");
- osThreadThreadIdField = type.getField("_thread_id");
+ threadIdField = type.getField("_thread_id");
}
public Address getLastJavaFP(Address addr) {
@@ -129,7 +129,7 @@
Address osThreadAddr = osThreadField.getValue(addr);
// Get the address of the thread_id within the OSThread
Address threadIdAddr =
- osThreadAddr.addOffsetTo(osThreadThreadIdField.getOffset());
+ osThreadAddr.addOffsetTo(threadIdField.getOffset());
JVMDebugger debugger = VM.getVM().getDebugger();
return debugger.getThreadForIdentifierAddress(threadIdAddr);
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.code/overview.html Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-<!--
-
-Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
-DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
-This code is free software; you can redistribute it and/or modify it
-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.
--->
-
-</head>
-<body>
-
-The <code>jdk.vm.ci.code</code> project provides an API to the runtime's native code cache.
-It allows installation and execution of native code.
-
-</body>
-</html>
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java Thu Nov 16 10:45:42 2017 -0800
@@ -470,7 +470,7 @@
/**
* Sets flags on {@code method} indicating that it should never be inlined or compiled by the VM.
*/
- native void setNotInlineableOrCompileable(HotSpotResolvedJavaMethodImpl method);
+ native void setNotInlinableOrCompilable(HotSpotResolvedJavaMethodImpl method);
/**
* Invalidates the profiling information for {@code method} and (re)initializes it such that
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotNmethod.java Thu Nov 16 10:45:42 2017 -0800
@@ -30,13 +30,10 @@
import jdk.vm.ci.meta.ResolvedJavaMethod;
/**
- * Implementation of {@link InstalledCode} for code installed as an nmethod. The nmethod stores a
- * weak reference to an instance of this class. This is necessary to keep the nmethod from being
- * unloaded while the associated {@link HotSpotNmethod} instance is alive.
- * <p>
- * Note that there is no (current) way for the reference from an nmethod to a {@link HotSpotNmethod}
- * instance to be anything but weak. This is due to the fact that HotSpot does not treat nmethods as
- * strong GC roots.
+ * Implementation of {@link InstalledCode} for code installed as an nmethod.
+ *
+ * When a {@link HotSpotNmethod} dies, it triggers unloading of the nmethod unless
+ * {@link #isDefault() == true}.
*/
public class HotSpotNmethod extends HotSpotInstalledCode {
@@ -54,6 +51,11 @@
this.isDefault = isDefault;
}
+ /**
+ * Determines if the nmethod associated with this object is the compiled entry point for
+ * {@link #getMethod()}. If {@code false}, then the nmethod is unloaded when the VM determines
+ * this object has died.
+ */
public boolean isDefault() {
return isDefault;
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java Thu Nov 16 10:45:42 2017 -0800
@@ -59,7 +59,7 @@
/**
* Sets flags on {@code method} indicating that it should never be inlined or compiled by the VM.
*/
- void setNotInlineableOrCompileable();
+ void setNotInlinableOrCompilable();
/**
* Returns true if this method is one of the special methods that is ignored by security stack
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java Thu Nov 16 10:45:42 2017 -0800
@@ -320,8 +320,8 @@
/**
* Sets flags on {@code method} indicating that it should never be inlined or compiled by the VM.
*/
- public void setNotInlineableOrCompileable() {
- compilerToVM().setNotInlineableOrCompileable(this);
+ public void setNotInlinableOrCompilable() {
+ compilerToVM().setNotInlinableOrCompilable(this);
}
/**
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Thu Nov 16 10:45:42 2017 -0800
@@ -538,7 +538,7 @@
return result;
}
- synchronized HotSpotResolvedJavaField createField(JavaType type, long offset, int rawFlags, int index) {
+ HotSpotResolvedJavaField createField(JavaType type, long offset, int rawFlags, int index) {
return new HotSpotResolvedJavaFieldImpl(this, type, offset, rawFlags, index);
}
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/overview.html Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-<!--
-
-Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
-DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
-This code is free software; you can redistribute it and/or modify it
-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.
--->
-
-</head>
-<body>
-
-The <code>jdk.vm.ci.meta</code> project provides an API to the runtime data structures
-for various Java elements. Unlike standard Java reflection, it can model elements that are not yet loaded.
-It can also expose profiling information collected by the runtime system.
-
-</body>
-</html>
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/BlackholeDirectiveTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/BlackholeDirectiveTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -34,6 +34,9 @@
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.nodes.ParameterNode;
import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.phases.OptimisticOptimizations;
+import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
/**
* Tests for {@link GraalDirectives#blackhole}.
@@ -129,6 +132,11 @@
}
@Override
+ protected HighTierContext getDefaultHighTierContext() {
+ return new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL.remove(Optimization.RemoveNeverExecutedCode));
+ }
+
+ @Override
protected boolean checkLowTierGraph(StructuredGraph graph) {
BlackholeSnippet snippet = graph.method().getAnnotation(BlackholeSnippet.class);
ParameterNode arg = graph.getParameter(0);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ControlFlowAnchorDirectiveTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ControlFlowAnchorDirectiveTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -46,6 +46,9 @@
import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode;
import jdk.vm.ci.meta.ResolvedJavaMethod;
+import org.graalvm.compiler.phases.OptimisticOptimizations;
+import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
public class ControlFlowAnchorDirectiveTest extends GraalCompilerTest {
@@ -239,6 +242,11 @@
}
@Override
+ protected HighTierContext getDefaultHighTierContext() {
+ return new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL.remove(Optimization.RemoveNeverExecutedCode));
+ }
+
+ @Override
protected boolean checkLowTierGraph(StructuredGraph graph) {
List<ControlFlowAnchorNode> anchors = graph.getNodes().filter(ControlFlowAnchorNode.class).snapshot();
for (int i = 0; i < anchors.size(); i++) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/OpaqueDirectiveTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/OpaqueDirectiveTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -37,6 +37,9 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.calc.AddNode;
import org.graalvm.compiler.nodes.calc.ConditionalNode;
+import org.graalvm.compiler.phases.OptimisticOptimizations;
+import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
/**
* Tests for {@link GraalDirectives#opaque}.
@@ -128,6 +131,11 @@
}
@Override
+ protected HighTierContext getDefaultHighTierContext() {
+ return new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL.remove(Optimization.RemoveNeverExecutedCode));
+ }
+
+ @Override
protected boolean checkLowTierGraph(StructuredGraph graph) {
OpaqueSnippet snippet = graph.method().getAnnotation(OpaqueSnippet.class);
for (ReturnNode returnNode : graph.getNodes(ReturnNode.TYPE)) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java Thu Nov 16 10:45:42 2017 -0800
@@ -36,6 +36,13 @@
public @interface Snippet {
/**
+ * A partial intrinsic exits by (effectively) calling the intrinsified method. Normally, this
+ * call must use exactly the same arguments as the call that is being intrinsified. For well
+ * known snippets that are used after frame state assignment, we want to relax this restriction.
+ */
+ boolean allowPartialIntrinsicArgumentMismatch() default false;
+
+ /**
* Denotes a snippet parameter representing 0 or more arguments that will be bound during
* snippet template instantiation. During snippet template creation, its value must be an array
* whose length specifies the number of arguments (the contents of the array are ignored) bound
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,10 +22,14 @@
*/
package org.graalvm.compiler.asm.amd64;
-import static org.graalvm.compiler.core.common.NumUtil.isByte;
-import static org.graalvm.compiler.core.common.NumUtil.isInt;
-import static org.graalvm.compiler.core.common.NumUtil.isShiftCount;
-import static org.graalvm.compiler.core.common.NumUtil.isUByte;
+import static jdk.vm.ci.amd64.AMD64.CPU;
+import static jdk.vm.ci.amd64.AMD64.XMM;
+import static jdk.vm.ci.amd64.AMD64.r12;
+import static jdk.vm.ci.amd64.AMD64.r13;
+import static jdk.vm.ci.amd64.AMD64.rbp;
+import static jdk.vm.ci.amd64.AMD64.rip;
+import static jdk.vm.ci.amd64.AMD64.rsp;
+import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseAddressNop;
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseNormalNop;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.ADD;
@@ -47,25 +51,24 @@
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SD;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SS;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD;
-import static jdk.vm.ci.amd64.AMD64.CPU;
-import static jdk.vm.ci.amd64.AMD64.XMM;
-import static jdk.vm.ci.amd64.AMD64.r12;
-import static jdk.vm.ci.amd64.AMD64.r13;
-import static jdk.vm.ci.amd64.AMD64.rbp;
-import static jdk.vm.ci.amd64.AMD64.rip;
-import static jdk.vm.ci.amd64.AMD64.rsp;
-import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
+import static org.graalvm.compiler.core.common.NumUtil.isByte;
+import static org.graalvm.compiler.core.common.NumUtil.isInt;
+import static org.graalvm.compiler.core.common.NumUtil.isShiftCount;
+import static org.graalvm.compiler.core.common.NumUtil.isUByte;
import org.graalvm.compiler.asm.Assembler;
import org.graalvm.compiler.asm.Label;
+import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
import org.graalvm.compiler.core.common.NumUtil;
-import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
+import org.graalvm.compiler.debug.GraalError;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64.CPUFeature;
+import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.Register.RegisterCategory;
import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.PlatformKind;
/**
* This class implements an assembler that can encode most X86 instructions.
@@ -225,7 +228,7 @@
* The x86 operand sizes.
*/
public enum OperandSize {
- BYTE(1) {
+ BYTE(1, AMD64Kind.BYTE) {
@Override
protected void emitImmediate(AMD64Assembler asm, int imm) {
assert imm == (byte) imm;
@@ -238,7 +241,7 @@
}
},
- WORD(2, 0x66) {
+ WORD(2, AMD64Kind.WORD, 0x66) {
@Override
protected void emitImmediate(AMD64Assembler asm, int imm) {
assert imm == (short) imm;
@@ -251,7 +254,7 @@
}
},
- DWORD(4) {
+ DWORD(4, AMD64Kind.DWORD) {
@Override
protected void emitImmediate(AMD64Assembler asm, int imm) {
asm.emitInt(imm);
@@ -263,7 +266,7 @@
}
},
- QWORD(8) {
+ QWORD(8, AMD64Kind.QWORD) {
@Override
protected void emitImmediate(AMD64Assembler asm, int imm) {
asm.emitInt(imm);
@@ -275,34 +278,35 @@
}
},
- SS(4, 0xF3, true),
-
- SD(8, 0xF2, true),
-
- PS(16, true),
-
- PD(16, 0x66, true);
+ SS(4, AMD64Kind.SINGLE, 0xF3, true),
+
+ SD(8, AMD64Kind.DOUBLE, 0xF2, true),
+
+ PS(16, AMD64Kind.V128_SINGLE, true),
+
+ PD(16, AMD64Kind.V128_DOUBLE, 0x66, true);
private final int sizePrefix;
-
private final int bytes;
private final boolean xmm;
-
- OperandSize(int bytes) {
- this(bytes, 0);
+ private final AMD64Kind kind;
+
+ OperandSize(int bytes, AMD64Kind kind) {
+ this(bytes, kind, 0);
}
- OperandSize(int bytes, int sizePrefix) {
- this(bytes, sizePrefix, false);
+ OperandSize(int bytes, AMD64Kind kind, int sizePrefix) {
+ this(bytes, kind, sizePrefix, false);
}
- OperandSize(int bytes, boolean xmm) {
- this(bytes, 0, xmm);
+ OperandSize(int bytes, AMD64Kind kind, boolean xmm) {
+ this(bytes, kind, 0, xmm);
}
- OperandSize(int bytes, int sizePrefix, boolean xmm) {
+ OperandSize(int bytes, AMD64Kind kind, int sizePrefix, boolean xmm) {
this.sizePrefix = sizePrefix;
this.bytes = bytes;
+ this.kind = kind;
this.xmm = xmm;
}
@@ -314,6 +318,19 @@
return xmm;
}
+ public AMD64Kind getKind() {
+ return kind;
+ }
+
+ public static OperandSize get(PlatformKind kind) {
+ for (OperandSize operandSize : OperandSize.values()) {
+ if (operandSize.kind.equals(kind)) {
+ return operandSize;
+ }
+ }
+ throw GraalError.shouldNotReachHere("Unexpected kind: " + kind.toString());
+ }
+
/**
* Emit an immediate of this size. Note that immediate {@link #QWORD} operands are encoded
* as sign-extended 32-bit values.
@@ -2230,6 +2247,14 @@
emitOperandHelper(dst, src, 0);
}
+ public final void movzbl(Register dst, Register src) {
+ AMD64RMOp.MOVZXB.emit(this, OperandSize.DWORD, dst, src);
+ }
+
+ public final void movzbq(Register dst, Register src) {
+ AMD64RMOp.MOVZXB.emit(this, OperandSize.QWORD, dst, src);
+ }
+
public final void movzwl(Register dst, AMD64Address src) {
prefix(src, dst);
emitByte(0x0F);
@@ -3198,6 +3223,13 @@
emitByte(0xC0 | encode);
}
+ public final void setb(ConditionFlag cc, Register dst) {
+ int encode = prefixAndEncode(dst.encoding, true);
+ emitByte(0x0F);
+ emitByte(0x90 | cc.getValue());
+ emitByte(0xC0 | encode);
+ }
+
public final void cmovq(ConditionFlag cc, Register dst, AMD64Address src) {
prefixq(src, dst);
emitByte(0x0F);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java Thu Nov 16 10:45:42 2017 -0800
@@ -31,8 +31,8 @@
import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmRegToRegMoveAll;
import org.graalvm.compiler.asm.Label;
+import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
import org.graalvm.compiler.core.common.NumUtil;
-import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64Kind;
@@ -281,6 +281,16 @@
}
+ public final void setl(ConditionFlag cc, Register dst) {
+ setb(cc, dst);
+ movzbl(dst, dst);
+ }
+
+ public final void setq(ConditionFlag cc, Register dst) {
+ setb(cc, dst);
+ movzbq(dst, dst);
+ }
+
public final void flog(Register dest, Register value, boolean base10) {
if (base10) {
fldlg2();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AddressLoweringTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.core.amd64.test;
+
+import static org.junit.Assume.assumeTrue;
+
+import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
+import org.graalvm.compiler.core.amd64.AMD64AddressLowering;
+import org.graalvm.compiler.core.amd64.AMD64AddressNode;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.nodes.ConstantNode;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.calc.AddNode;
+import org.graalvm.compiler.nodes.calc.LeftShiftNode;
+import org.graalvm.compiler.nodes.calc.NegateNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import jdk.vm.ci.amd64.AMD64;
+
+public class AMD64AddressLoweringTest extends GraalCompilerTest {
+
+ private StructuredGraph graph;
+ private AMD64AddressLowering lowering;
+
+ @Before
+ public void checkAMD64() {
+ assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64);
+ graph = new StructuredGraph.Builder(getInitialOptions(), getDebugContext()).build();
+ lowering = new AMD64AddressLowering();
+ }
+
+ @Test
+ public void convertBaseAndIndexToDisplacement() {
+ ValueNode base = graph.unique(const64(1000));
+ ValueNode index = graph.unique(const64(10));
+ AddressNode result = lowering.lower(base, index);
+ assertAddress(result, null, null, Scale.Times1, 1010);
+ }
+
+ @Test
+ public void convertBaseToDisplacement() {
+ ValueNode constantAddress = graph.addOrUniqueWithInputs(const64(1000));
+ AddressNode result = lowering.lower(constantAddress, null);
+ assertAddress(result, null, null, Scale.Times1, 1000);
+ }
+
+ @Test
+ public void convertBaseAndShiftedIndexToDisplacement() {
+ ValueNode base = graph.addOrUniqueWithInputs(const64(1000));
+ ValueNode index = graph.addOrUniqueWithInputs(new LeftShiftNode(const64(10), const32(1)));
+ AddressNode result = lowering.lower(base, index);
+ assertAddress(result, null, null, Scale.Times2, 1020);
+ }
+
+ @Test
+ public void convertBaseAndNegatedShiftedIndexToDisplacement() {
+ ValueNode base = graph.addOrUniqueWithInputs(const64(1000));
+ ValueNode index = graph.addOrUniqueWithInputs(new NegateNode(new LeftShiftNode(const64(10), const32(2))));
+ AddressNode result = lowering.lower(base, index);
+ assertAddress(result, null, null, Scale.Times4, 960);
+ }
+
+ @Test
+ public void convertNegatedBaseAndNegatedShiftedIndexToDisplacement() {
+ ValueNode base = graph.addOrUniqueWithInputs(new NegateNode(const64(1000)));
+ ValueNode index = graph.addOrUniqueWithInputs(new NegateNode(new LeftShiftNode(const64(10), const32(2))));
+ AddressNode result = lowering.lower(base, index);
+ assertAddress(result, null, null, Scale.Times4, -1040);
+ }
+
+ @Test
+ public void convertNegatedShiftedBaseAndNegatedIndexToDisplacement() {
+ ValueNode base = graph.addOrUniqueWithInputs(new NegateNode(new LeftShiftNode(const64(10), const32(2))));
+ ValueNode index = graph.addOrUniqueWithInputs(new NegateNode(const64(1000)));
+ AddressNode result = lowering.lower(base, index);
+ assertAddress(result, null, null, Scale.Times4, -1040);
+ }
+
+ @Test
+ public void convertTwoLevelsOfNegatedShiftedBaseAndNegatedIndexToDisplacement() {
+ ValueNode base = graph.addOrUniqueWithInputs(new NegateNode(new LeftShiftNode(new NegateNode(new LeftShiftNode(const64(500), const32(1))), const32(1))));
+ ValueNode index = graph.addOrUniqueWithInputs(new NegateNode(new AddNode(new NegateNode(const64(13)), const64(3))));
+ AddressNode result = lowering.lower(base, index);
+ assertAddress(result, null, null, Scale.Times4, 2010);
+ }
+
+ private static ConstantNode const64(long value) {
+ return ConstantNode.forIntegerBits(Long.SIZE, value);
+ }
+
+ private static ConstantNode const32(long value) {
+ return ConstantNode.forIntegerBits(Integer.SIZE, value);
+ }
+
+ private static void assertAddress(AddressNode actual, ValueNode expectedBase, ValueNode expectedIndex, Scale expectedScale, int expectedDisplacement) {
+ AMD64AddressNode address = (AMD64AddressNode) actual;
+ Assert.assertEquals(expectedBase, address.getBase());
+ Assert.assertEquals(expectedIndex, address.getIndex());
+ Assert.assertEquals(expectedScale, address.getScale());
+ Assert.assertEquals(expectedDisplacement, address.getDisplacement());
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java Thu Nov 16 10:45:42 2017 -0800
@@ -23,21 +23,22 @@
package org.graalvm.compiler.core.amd64;
-import jdk.vm.ci.meta.JavaConstant;
-
+import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
import org.graalvm.compiler.core.common.NumUtil;
-import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.AddNode;
import org.graalvm.compiler.nodes.calc.LeftShiftNode;
+import org.graalvm.compiler.nodes.calc.NegateNode;
import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
import org.graalvm.compiler.nodes.memory.address.AddressNode;
import org.graalvm.compiler.phases.common.AddressLoweringPhase.AddressLowering;
+import jdk.vm.ci.meta.JavaConstant;
+
public class AMD64AddressLowering extends AddressLowering {
-
@Override
public AddressNode lower(ValueNode address) {
return lower(address, null);
@@ -46,24 +47,37 @@
@Override
public AddressNode lower(ValueNode base, ValueNode offset) {
AMD64AddressNode ret = new AMD64AddressNode(base, offset);
+ StructuredGraph graph = base.graph();
+
boolean changed;
do {
- changed = improve(base.getDebug(), ret);
+ changed = improve(graph, base.getDebug(), ret, false, false);
} while (changed);
- return base.graph().unique(ret);
+
+ return graph.unique(ret);
}
/**
- * @param debug
+ * Tries to optimize addresses so that they match the AMD64-specific addressing mode better
+ * (base + index * scale + displacement).
+ *
+ * @param graph the current graph
+ * @param debug the current debug context
+ * @param ret the address that should be optimized
+ * @param isBaseNegated determines if the address base is negated. if so, all values that are
+ * extracted from the base will be negated as well
+ * @param isIndexNegated determines if the index is negated. if so, all values that are
+ * extracted from the index will be negated as well
+ * @return true if the address was modified
*/
- protected boolean improve(DebugContext debug, AMD64AddressNode ret) {
- ValueNode newBase = improveInput(ret, ret.getBase(), 0);
+ protected boolean improve(StructuredGraph graph, DebugContext debug, AMD64AddressNode ret, boolean isBaseNegated, boolean isIndexNegated) {
+ ValueNode newBase = improveInput(ret, ret.getBase(), 0, isBaseNegated);
if (newBase != ret.getBase()) {
ret.setBase(newBase);
return true;
}
- ValueNode newIdx = improveInput(ret, ret.getIndex(), ret.getScale().log2);
+ ValueNode newIdx = improveInput(ret, ret.getIndex(), ret.getScale().log2, isIndexNegated);
if (newIdx != ret.getIndex()) {
ret.setIndex(newIdx);
return true;
@@ -83,55 +97,122 @@
}
if (ret.getScale() == Scale.Times1) {
- if (ret.getBase() == null || ret.getIndex() == null) {
- if (ret.getBase() instanceof AddNode) {
- AddNode add = (AddNode) ret.getBase();
- ret.setBase(add.getX());
- ret.setIndex(add.getY());
- return true;
- } else if (ret.getIndex() instanceof AddNode) {
- AddNode add = (AddNode) ret.getIndex();
- ret.setBase(add.getX());
- ret.setIndex(add.getY());
- return true;
- }
+ if (ret.getIndex() == null && ret.getBase() instanceof AddNode) {
+ AddNode add = (AddNode) ret.getBase();
+ ret.setBase(add.getX());
+ ret.setIndex(considerNegation(graph, add.getY(), isBaseNegated));
+ return true;
+ } else if (ret.getBase() == null && ret.getIndex() instanceof AddNode) {
+ AddNode add = (AddNode) ret.getIndex();
+ ret.setBase(considerNegation(graph, add.getX(), isIndexNegated));
+ ret.setIndex(add.getY());
+ return true;
}
if (ret.getBase() instanceof LeftShiftNode && !(ret.getIndex() instanceof LeftShiftNode)) {
ValueNode tmp = ret.getBase();
- ret.setBase(ret.getIndex());
- ret.setIndex(tmp);
+ ret.setBase(considerNegation(graph, ret.getIndex(), isIndexNegated != isBaseNegated));
+ ret.setIndex(considerNegation(graph, tmp, isIndexNegated != isBaseNegated));
return true;
}
}
+ return improveNegation(graph, debug, ret, isBaseNegated, isIndexNegated);
+ }
+
+ private boolean improveNegation(StructuredGraph graph, DebugContext debug, AMD64AddressNode ret, boolean originalBaseNegated, boolean originalIndexNegated) {
+ boolean baseNegated = originalBaseNegated;
+ boolean indexNegated = originalIndexNegated;
+
+ ValueNode originalBase = ret.getBase();
+ ValueNode originalIndex = ret.getIndex();
+
+ if (ret.getBase() instanceof NegateNode) {
+ NegateNode negate = (NegateNode) ret.getBase();
+ ret.setBase(negate.getValue());
+ baseNegated = !baseNegated;
+ }
+
+ if (ret.getIndex() instanceof NegateNode) {
+ NegateNode negate = (NegateNode) ret.getIndex();
+ ret.setIndex(negate.getValue());
+ indexNegated = !indexNegated;
+ }
+
+ if (baseNegated != originalBaseNegated || indexNegated != originalIndexNegated) {
+ ValueNode base = ret.getBase();
+ ValueNode index = ret.getIndex();
+
+ boolean improved = improve(graph, debug, ret, baseNegated, indexNegated);
+ if (baseNegated != originalBaseNegated) {
+ if (base == ret.getBase()) {
+ ret.setBase(originalBase);
+ } else if (ret.getBase() != null) {
+ ret.setBase(graph.maybeAddOrUnique(NegateNode.create(ret.getBase())));
+ }
+ }
+
+ if (indexNegated != originalIndexNegated) {
+ if (index == ret.getIndex()) {
+ ret.setIndex(originalIndex);
+ } else if (ret.getIndex() != null) {
+ ret.setIndex(graph.maybeAddOrUnique(NegateNode.create(ret.getIndex())));
+ }
+ }
+ return improved;
+ } else {
+ assert ret.getBase() == originalBase && ret.getIndex() == originalIndex;
+ }
return false;
}
- private static ValueNode improveInput(AMD64AddressNode address, ValueNode node, int shift) {
+ private static ValueNode considerNegation(StructuredGraph graph, ValueNode value, boolean negate) {
+ if (negate && value != null) {
+ return graph.maybeAddOrUnique(NegateNode.create(value));
+ }
+ return value;
+ }
+
+ private ValueNode improveInput(AMD64AddressNode address, ValueNode node, int shift, boolean negateExtractedDisplacement) {
if (node == null) {
return null;
}
JavaConstant c = node.asJavaConstant();
if (c != null) {
- return improveConstDisp(address, node, c, null, shift);
+ return improveConstDisp(address, node, c, null, shift, negateExtractedDisplacement);
} else {
- if (node.stamp() instanceof IntegerStamp && ((IntegerStamp) node.stamp()).getBits() == 64) {
- if (node instanceof ZeroExtendNode) {
- if (((ZeroExtendNode) node).getInputBits() == 32) {
- /*
- * We can just swallow a zero-extend from 32 bit to 64 bit because the upper
- * half of the register will always be zero.
- */
- return ((ZeroExtendNode) node).getValue();
+ if (node.stamp() instanceof IntegerStamp) {
+ if (node instanceof ZeroExtendNode && (((ZeroExtendNode) node).getInputBits() == 32)) {
+ /*
+ * we can't just swallow all zero-extends as we might encounter something like
+ * the following: ZeroExtend(Add(negativeValue, positiveValue)).
+ *
+ * if we swallow the zero-extend in this case and subsequently optimize the add,
+ * we might end up with a negative value that has less than 64 bits in base or
+ * index. such a value would require sign extension instead of zero-extension
+ * but the backend can only do zero-extension. if we ever want to optimize that
+ * further, we would also need to be careful about over-/underflows.
+ *
+ * furthermore, we also can't swallow zero-extends with less than 32 bits as
+ * most of these values are immediately sign-extended to 32 bit by the backend
+ * (therefore, the subsequent implicit zero-extension to 64 bit won't do what we
+ * expect).
+ */
+ ValueNode value = ((ZeroExtendNode) node).getValue();
+ if (!mightBeOptimized(value)) {
+ // if the value is not optimized further by the address lowering, then we
+ // can safely rely on the backend doing the implicitly zero-extension.
+ return value;
}
- } else if (node instanceof AddNode) {
+ }
+
+ if (node instanceof AddNode) {
AddNode add = (AddNode) node;
if (add.getX().isConstant()) {
- return improveConstDisp(address, node, add.getX().asJavaConstant(), add.getY(), shift);
+ return improveConstDisp(address, node, add.getX().asJavaConstant(), add.getY(), shift, negateExtractedDisplacement);
} else if (add.getY().isConstant()) {
- return improveConstDisp(address, node, add.getY().asJavaConstant(), add.getX(), shift);
+ return improveConstDisp(address, node, add.getY().asJavaConstant(), add.getX(), shift, negateExtractedDisplacement);
}
}
}
@@ -140,15 +221,30 @@
return node;
}
- private static ValueNode improveConstDisp(AMD64AddressNode address, ValueNode original, JavaConstant c, ValueNode other, int shift) {
+ /**
+ * This method returns true for all nodes that might be optimized by the address lowering.
+ */
+ protected boolean mightBeOptimized(ValueNode value) {
+ return value instanceof AddNode || value instanceof LeftShiftNode || value instanceof NegateNode || value instanceof ZeroExtendNode;
+ }
+
+ private static ValueNode improveConstDisp(AMD64AddressNode address, ValueNode original, JavaConstant c, ValueNode other, int shift, boolean negateExtractedDisplacement) {
if (c.getJavaKind().isNumericInteger()) {
- long disp = address.getDisplacement();
- disp += c.asLong() << shift;
- if (NumUtil.isInt(disp)) {
- address.setDisplacement((int) disp);
+ long delta = c.asLong() << shift;
+ if (updateDisplacement(address, delta, negateExtractedDisplacement)) {
return other;
}
}
return original;
}
+
+ protected static boolean updateDisplacement(AMD64AddressNode address, long displacementDelta, boolean negateDelta) {
+ long sign = negateDelta ? -1 : 1;
+ long disp = address.getDisplacement() + displacementDelta * sign;
+ if (NumUtil.isInt(disp)) {
+ address.setDisplacement((int) disp);
+ return true;
+ }
+ return false;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java Thu Nov 16 10:45:42 2017 -0800
@@ -33,15 +33,17 @@
import static org.graalvm.compiler.lir.LIRValueUtil.asConstantValue;
import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
+import static org.graalvm.compiler.lir.LIRValueUtil.isIntConstant;
import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
-import org.graalvm.compiler.core.common.NumUtil;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
import org.graalvm.compiler.core.common.spi.LIRKindTool;
@@ -58,13 +60,17 @@
import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool;
import org.graalvm.compiler.lir.amd64.AMD64ArrayEqualsOp;
+import org.graalvm.compiler.lir.amd64.AMD64Binary;
import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer;
import org.graalvm.compiler.lir.amd64.AMD64ByteSwapOp;
import org.graalvm.compiler.lir.amd64.AMD64Call;
+import org.graalvm.compiler.lir.amd64.AMD64ControlFlow;
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.BranchOp;
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.CondMoveOp;
+import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.CondSetOp;
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatBranchOp;
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatCondMoveOp;
+import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatCondSetOp;
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.ReturnOp;
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.TableSwitchOp;
@@ -257,8 +263,7 @@
@Override
public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueLabel, LabelRef falseLabel, double trueLabelProbability) {
- boolean mirrored = emitCompare(cmpKind, left, right);
- Condition finalCondition = mirrored ? cond.mirror() : cond;
+ Condition finalCondition = emitCompare(cmpKind, left, right, cond);
if (cmpKind == AMD64Kind.SINGLE || cmpKind == AMD64Kind.DOUBLE) {
append(new FloatBranchOp(finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability));
} else {
@@ -290,14 +295,60 @@
@Override
public Variable emitConditionalMove(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
- boolean mirrored = emitCompare(cmpKind, left, right);
- Condition finalCondition = mirrored ? cond.mirror() : cond;
+ boolean isFloatComparison = cmpKind == AMD64Kind.SINGLE || cmpKind == AMD64Kind.DOUBLE;
- Variable result = newVariable(trueValue.getValueKind());
- if (cmpKind == AMD64Kind.SINGLE || cmpKind == AMD64Kind.DOUBLE) {
- append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
+ Condition finalCondition = cond;
+ Value finalTrueValue = trueValue;
+ Value finalFalseValue = falseValue;
+ if (isFloatComparison) {
+ // eliminate the parity check in case of a float comparison
+ Value finalLeft = left;
+ Value finalRight = right;
+ if (unorderedIsTrue != AMD64ControlFlow.trueOnUnordered(finalCondition)) {
+ if (unorderedIsTrue == AMD64ControlFlow.trueOnUnordered(finalCondition.mirror())) {
+ finalCondition = finalCondition.mirror();
+ finalLeft = right;
+ finalRight = left;
+ } else if (finalCondition != Condition.EQ && finalCondition != Condition.NE) {
+ // negating EQ and NE does not make any sense as we would need to negate
+ // unorderedIsTrue as well (otherwise, we would no longer fulfill the Java
+ // NaN semantics)
+ assert unorderedIsTrue == AMD64ControlFlow.trueOnUnordered(finalCondition.negate());
+ finalCondition = finalCondition.negate();
+ finalTrueValue = falseValue;
+ finalFalseValue = trueValue;
+ }
+ }
+ emitRawCompare(cmpKind, finalLeft, finalRight);
} else {
- append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue)));
+ finalCondition = emitCompare(cmpKind, left, right, cond);
+ }
+
+ boolean isParityCheckNecessary = isFloatComparison && unorderedIsTrue != AMD64ControlFlow.trueOnUnordered(finalCondition);
+ Variable result = newVariable(finalTrueValue.getValueKind());
+ if (!isParityCheckNecessary && isIntConstant(finalTrueValue, 1) && isIntConstant(finalFalseValue, 0)) {
+ if (isFloatComparison) {
+ append(new FloatCondSetOp(result, finalCondition));
+ } else {
+ append(new CondSetOp(result, finalCondition));
+ }
+ } else if (!isParityCheckNecessary && isIntConstant(finalTrueValue, 0) && isIntConstant(finalFalseValue, 1)) {
+ if (isFloatComparison) {
+ if (unorderedIsTrue == AMD64ControlFlow.trueOnUnordered(finalCondition.negate())) {
+ append(new FloatCondSetOp(result, finalCondition.negate()));
+ } else {
+ append(new FloatCondSetOp(result, finalCondition));
+ Variable negatedResult = newVariable(result.getValueKind());
+ append(new AMD64Binary.ConstOp(AMD64BinaryArithmetic.XOR, OperandSize.get(result.getPlatformKind()), negatedResult, result, 1));
+ result = negatedResult;
+ }
+ } else {
+ append(new CondSetOp(result, finalCondition.negate()));
+ }
+ } else if (isFloatComparison) {
+ append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(finalTrueValue), load(finalFalseValue)));
+ } else {
+ append(new CondMoveOp(result, finalCondition, load(finalTrueValue), loadNonConst(finalFalseValue)));
}
return result;
}
@@ -394,23 +445,21 @@
*
* @param a the left operand of the comparison
* @param b the right operand of the comparison
+ * @param cond the condition of the comparison
* @return true if the left and right operands were switched, false otherwise
*/
- private boolean emitCompare(PlatformKind cmpKind, Value a, Value b) {
- Variable left;
- Value right;
- boolean mirrored;
+ private Condition emitCompare(PlatformKind cmpKind, Value a, Value b, Condition cond) {
if (LIRValueUtil.isVariable(b)) {
- left = load(b);
- right = loadNonConst(a);
- mirrored = true;
+ emitRawCompare(cmpKind, b, a);
+ return cond.mirror();
} else {
- left = load(a);
- right = loadNonConst(b);
- mirrored = false;
+ emitRawCompare(cmpKind, a, b);
+ return cond;
}
- ((AMD64ArithmeticLIRGeneratorTool) arithmeticLIRGen).emitCompareOp((AMD64Kind) cmpKind, left, right);
- return mirrored;
+ }
+
+ private void emitRawCompare(PlatformKind cmpKind, Value left, Value right) {
+ ((AMD64ArithmeticLIRGeneratorTool) arithmeticLIRGen).emitCompareOp((AMD64Kind) cmpKind, load(left), loadNonConst(right));
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRKindTool.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRKindTool.java Thu Nov 16 10:45:42 2017 -0800
@@ -28,7 +28,7 @@
import jdk.vm.ci.amd64.AMD64Kind;
-public class AMD64LIRKindTool implements LIRKindTool {
+public abstract class AMD64LIRKindTool implements LIRKindTool {
@Override
public LIRKind getIntegerKind(int bits) {
@@ -67,12 +67,8 @@
}
@Override
- public LIRKind getNarrowOopKind() {
- return LIRKind.reference(AMD64Kind.DWORD);
- }
+ public abstract LIRKind getNarrowOopKind();
@Override
- public LIRKind getNarrowPointerKind() {
- return LIRKind.value(AMD64Kind.DWORD);
- }
+ public abstract LIRKind getNarrowPointerKind();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompressEncoding.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompressEncoding.java Thu Nov 16 10:45:42 2017 -0800
@@ -34,14 +34,6 @@
this.shift = shift;
}
- public int compress(long ptr) {
- if (ptr == 0L) {
- return 0;
- } else {
- return (int) ((ptr - base) >>> shift);
- }
- }
-
public boolean hasBase() {
return base != 0;
}
@@ -58,14 +50,6 @@
return shift;
}
- public long uncompress(int ptr) {
- if (ptr == 0) {
- return 0L;
- } else {
- return ((ptr & 0xFFFFFFFFL) << shift) + base;
- }
- }
-
@Override
public String toString() {
return "base: " + base + " shift: " + shift;
@@ -85,8 +69,7 @@
if (obj instanceof CompressEncoding) {
CompressEncoding other = (CompressEncoding) obj;
return base == other.base && shift == other.shift;
- } else {
- return false;
}
+ return false;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/FloatConvert.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/FloatConvert.java Thu Nov 16 10:45:42 2017 -0800
@@ -25,21 +25,23 @@
import org.graalvm.compiler.debug.GraalError;
public enum FloatConvert {
- F2I(FloatConvertCategory.FloatingPointToInteger),
- D2I(FloatConvertCategory.FloatingPointToInteger),
- F2L(FloatConvertCategory.FloatingPointToInteger),
- D2L(FloatConvertCategory.FloatingPointToInteger),
- I2F(FloatConvertCategory.IntegerToFloatingPoint),
- L2F(FloatConvertCategory.IntegerToFloatingPoint),
- D2F(FloatConvertCategory.FloatingPointToFloatingPoint),
- I2D(FloatConvertCategory.IntegerToFloatingPoint),
- L2D(FloatConvertCategory.IntegerToFloatingPoint),
- F2D(FloatConvertCategory.FloatingPointToFloatingPoint);
+ F2I(FloatConvertCategory.FloatingPointToInteger, 32),
+ D2I(FloatConvertCategory.FloatingPointToInteger, 64),
+ F2L(FloatConvertCategory.FloatingPointToInteger, 32),
+ D2L(FloatConvertCategory.FloatingPointToInteger, 64),
+ I2F(FloatConvertCategory.IntegerToFloatingPoint, 32),
+ L2F(FloatConvertCategory.IntegerToFloatingPoint, 64),
+ D2F(FloatConvertCategory.FloatingPointToFloatingPoint, 64),
+ I2D(FloatConvertCategory.IntegerToFloatingPoint, 32),
+ L2D(FloatConvertCategory.IntegerToFloatingPoint, 64),
+ F2D(FloatConvertCategory.FloatingPointToFloatingPoint, 32);
- private FloatConvertCategory category;
+ private final FloatConvertCategory category;
+ private final int inputBits;
- FloatConvert(FloatConvertCategory category) {
+ FloatConvert(FloatConvertCategory category, int inputBits) {
this.category = category;
+ this.inputBits = inputBits;
}
public FloatConvertCategory getCategory() {
@@ -72,4 +74,8 @@
throw GraalError.shouldNotReachHere();
}
}
+
+ public int getInputBits() {
+ return inputBits;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java Thu Nov 16 10:45:42 2017 -0800
@@ -41,7 +41,6 @@
this.parent = parent;
if (parent != null) {
this.depth = parent.getDepth() + 1;
- parent.getChildren().add(this);
} else {
this.depth = 1;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java Thu Nov 16 10:45:42 2017 -0800
@@ -96,6 +96,22 @@
}
}
+ public BinaryOp<?>[] getBinaryOps() {
+ return new BinaryOp<?>[]{add, sub, mul, mulHigh, umulHigh, div, rem, and, or, xor};
+ }
+
+ public UnaryOp<?>[] getUnaryOps() {
+ return new UnaryOp<?>[]{neg, not, abs, sqrt};
+ }
+
+ public ShiftOp<?>[] getShiftOps() {
+ return new ShiftOp<?>[]{shl, shr, ushr};
+ }
+
+ public IntegerConvertOp<?>[] getIntegerConvertOps() {
+ return new IntegerConvertOp<?>[]{zeroExtend, signExtend, narrow};
+ }
+
public static final ArithmeticOpTable EMPTY = new ArithmeticOpTable(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
public interface ArithmeticOpWrapper {
@@ -562,7 +578,10 @@
}
/**
- * Apply the operation to two {@linkplain Constant Constants}.
+ * Applies this operation to {@code a} and {@code b}.
+ *
+ * @return the result of applying this operation or {@code null} if applying it would raise
+ * an exception (e.g., {@link ArithmeticException} for dividing by 0)
*/
public abstract Constant foldConstant(Constant a, Constant b);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java Thu Nov 16 10:45:42 2017 -0800
@@ -291,7 +291,7 @@
@Override
public JavaConstant asConstant() {
- if (nonNaN && Double.compare(lowerBound, upperBound) == 0) {
+ if (isConstant()) {
switch (getBits()) {
case 32:
return JavaConstant.forFloat((float) lowerBound);
@@ -302,6 +302,68 @@
return null;
}
+ private boolean isConstant() {
+ /*
+ * There are many forms of NaNs and any operations on them can silently convert them into
+ * the canonical NaN.
+ */
+ return (Double.compare(lowerBound, upperBound) == 0 && nonNaN);
+ }
+
+ private static FloatStamp stampForConstant(Constant constant) {
+ FloatStamp result;
+ PrimitiveConstant value = (PrimitiveConstant) constant;
+ switch (value.getJavaKind()) {
+ case Float:
+ if (Float.isNaN(value.asFloat())) {
+ result = new FloatStamp(32, Double.NaN, Double.NaN, false);
+ } else {
+ result = new FloatStamp(32, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat()));
+ }
+ break;
+ case Double:
+ if (Double.isNaN(value.asDouble())) {
+ result = new FloatStamp(64, Double.NaN, Double.NaN, false);
+ } else {
+ result = new FloatStamp(64, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble()));
+ }
+ break;
+ default:
+ throw GraalError.shouldNotReachHere();
+ }
+ if (result.isConstant()) {
+ return result;
+ }
+ return null;
+ }
+
+ private static Stamp maybeFoldConstant(UnaryOp<?> op, FloatStamp stamp) {
+ if (stamp.isConstant()) {
+ JavaConstant constant = stamp.asConstant();
+ Constant folded = op.foldConstant(constant);
+ if (folded != null) {
+ return FloatStamp.stampForConstant(folded);
+ }
+ }
+ return null;
+ }
+
+ private static Stamp maybeFoldConstant(BinaryOp<?> op, FloatStamp stamp1, FloatStamp stamp2) {
+ if (stamp1.isConstant() && stamp2.isConstant()) {
+ JavaConstant constant1 = stamp1.asConstant();
+ JavaConstant constant2 = stamp2.asConstant();
+ Constant folded = op.foldConstant(constant1, constant2);
+ if (folded != null) {
+ FloatStamp stamp = stampForConstant(folded);
+ if (stamp != null && stamp.isConstant()) {
+ assert stamp.asConstant().equals(folded);
+ return stamp;
+ }
+ }
+ }
+ return null;
+ }
+
public static final ArithmeticOpTable OPS = new ArithmeticOpTable(
new UnaryOp.Neg() {
@@ -322,8 +384,13 @@
@Override
public Stamp foldStamp(Stamp s) {
FloatStamp stamp = (FloatStamp) s;
+ Stamp folded = maybeFoldConstant(this, stamp);
+ if (folded != null) {
+ return folded;
+ }
return new FloatStamp(stamp.getBits(), -stamp.upperBound(), -stamp.lowerBound(), stamp.isNonNaN());
}
+
},
new BinaryOp.Add(false, true) {
@@ -344,8 +411,13 @@
}
@Override
- public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
- // TODO
+ public Stamp foldStamp(Stamp s1, Stamp s2) {
+ FloatStamp stamp1 = (FloatStamp) s1;
+ FloatStamp stamp2 = (FloatStamp) s2;
+ Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+ if (folded != null) {
+ return folded;
+ }
return stamp1.unrestricted();
}
@@ -381,8 +453,13 @@
}
@Override
- public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
- // TODO
+ public Stamp foldStamp(Stamp s1, Stamp s2) {
+ FloatStamp stamp1 = (FloatStamp) s1;
+ FloatStamp stamp2 = (FloatStamp) s2;
+ Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+ if (folded != null) {
+ return folded;
+ }
return stamp1.unrestricted();
}
@@ -418,9 +495,14 @@
}
@Override
- public Stamp foldStamp(Stamp a, Stamp b) {
- // TODO
- return a.unrestricted();
+ public Stamp foldStamp(Stamp s1, Stamp s2) {
+ FloatStamp stamp1 = (FloatStamp) s1;
+ FloatStamp stamp2 = (FloatStamp) s2;
+ Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+ if (folded != null) {
+ return folded;
+ }
+ return stamp1.unrestricted();
}
@Override
@@ -450,17 +532,24 @@
assert a.getJavaKind() == b.getJavaKind();
switch (a.getJavaKind()) {
case Float:
- return JavaConstant.forFloat(a.asFloat() / b.asFloat());
+ float floatDivisor = b.asFloat();
+ return (floatDivisor == 0) ? null : JavaConstant.forFloat(a.asFloat() / floatDivisor);
case Double:
- return JavaConstant.forDouble(a.asDouble() / b.asDouble());
+ double doubleDivisor = b.asDouble();
+ return (doubleDivisor == 0) ? null : JavaConstant.forDouble(a.asDouble() / doubleDivisor);
default:
throw GraalError.shouldNotReachHere();
}
}
@Override
- public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
- // TODO
+ public Stamp foldStamp(Stamp s1, Stamp s2) {
+ FloatStamp stamp1 = (FloatStamp) s1;
+ FloatStamp stamp2 = (FloatStamp) s2;
+ Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+ if (folded != null) {
+ return folded;
+ }
return stamp1.unrestricted();
}
@@ -496,8 +585,13 @@
}
@Override
- public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
- // TODO
+ public Stamp foldStamp(Stamp s1, Stamp s2) {
+ FloatStamp stamp1 = (FloatStamp) s1;
+ FloatStamp stamp2 = (FloatStamp) s2;
+ Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+ if (folded != null) {
+ return folded;
+ }
return stamp1.unrestricted();
}
},
@@ -521,6 +615,17 @@
@Override
public Stamp foldStamp(Stamp s) {
+ FloatStamp stamp = (FloatStamp) s;
+ JavaConstant constant = stamp.asConstant();
+ if (constant != null) {
+ Constant folded = foldConstant(constant);
+ if (folded != null) {
+ FloatStamp result = stampForConstant(folded);
+ if (result != null && result.isConstant()) {
+ return result;
+ }
+ }
+ }
return s.unrestricted();
}
},
@@ -547,7 +652,13 @@
}
@Override
- public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+ public Stamp foldStamp(Stamp s1, Stamp s2) {
+ FloatStamp stamp1 = (FloatStamp) s1;
+ FloatStamp stamp2 = (FloatStamp) s2;
+ Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+ if (folded != null) {
+ return folded;
+ }
return stamp1.unrestricted();
}
@@ -576,7 +687,9 @@
case Float:
int fa = Float.floatToRawIntBits(a.asFloat());
int fb = Float.floatToRawIntBits(b.asFloat());
- return JavaConstant.forFloat(Float.intBitsToFloat(fa | fb));
+ float floatOr = Float.intBitsToFloat(fa | fb);
+ assert (fa | fb) == Float.floatToRawIntBits((floatOr));
+ return JavaConstant.forFloat(floatOr);
case Double:
long da = Double.doubleToRawLongBits(a.asDouble());
long db = Double.doubleToRawLongBits(b.asDouble());
@@ -587,7 +700,13 @@
}
@Override
- public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+ public Stamp foldStamp(Stamp s1, Stamp s2) {
+ FloatStamp stamp1 = (FloatStamp) s1;
+ FloatStamp stamp2 = (FloatStamp) s2;
+ Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+ if (folded != null) {
+ return folded;
+ }
return stamp1.unrestricted();
}
@@ -627,7 +746,13 @@
}
@Override
- public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+ public Stamp foldStamp(Stamp s1, Stamp s2) {
+ FloatStamp stamp1 = (FloatStamp) s1;
+ FloatStamp stamp2 = (FloatStamp) s2;
+ Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
+ if (folded != null) {
+ return folded;
+ }
return stamp1.unrestricted();
}
@@ -665,6 +790,10 @@
@Override
public Stamp foldStamp(Stamp s) {
FloatStamp stamp = (FloatStamp) s;
+ Stamp folded = maybeFoldConstant(this, stamp);
+ if (folded != null) {
+ return folded;
+ }
if (stamp.isNaN()) {
return stamp;
}
@@ -689,6 +818,11 @@
@Override
public Stamp foldStamp(Stamp s) {
+ FloatStamp stamp = (FloatStamp) s;
+ Stamp folded = maybeFoldConstant(this, stamp);
+ if (folded != null) {
+ return folded;
+ }
return s.unrestricted();
}
},
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java Thu Nov 16 10:45:42 2017 -0800
@@ -597,6 +597,10 @@
public Stamp foldStamp(Stamp s) {
IntegerStamp stamp = (IntegerStamp) s;
int bits = stamp.getBits();
+ if (stamp.lowerBound == stamp.upperBound) {
+ long value = CodeUtil.convert(-stamp.lowerBound(), stamp.getBits(), false);
+ return StampFactory.forInteger(stamp.getBits(), value, value);
+ }
if (stamp.lowerBound() != CodeUtil.minValue(bits)) {
// TODO(ls) check if the mask calculation is correct...
return StampFactory.forInteger(bits, -stamp.upperBound(), -stamp.lowerBound());
@@ -624,6 +628,11 @@
int bits = a.getBits();
assert bits == b.getBits();
+ if (a.lowerBound == a.upperBound && b.lowerBound == b.upperBound) {
+ long value = CodeUtil.convert(a.lowerBound() + b.lowerBound(), a.getBits(), false);
+ return StampFactory.forInteger(a.getBits(), value, value);
+ }
+
if (a.isUnrestricted()) {
return a;
} else if (b.isUnrestricted()) {
@@ -711,6 +720,12 @@
int bits = a.getBits();
assert bits == b.getBits();
+
+ if (a.lowerBound == a.upperBound && b.lowerBound == b.upperBound) {
+ long value = CodeUtil.convert(a.lowerBound() * b.lowerBound(), a.getBits(), false);
+ return StampFactory.forInteger(a.getBits(), value, value);
+ }
+
// if a==0 or b==0 result of a*b is always 0
if (a.upMask() == 0) {
return a;
@@ -791,7 +806,7 @@
long maxPosB = b.upperBound();
// multiplication has shift semantics
- long newUpMask = ~CodeUtil.mask(Long.numberOfTrailingZeros(a.upMask) + Long.numberOfTrailingZeros(b.upMask)) & CodeUtil.mask(bits);
+ long newUpMask = ~CodeUtil.mask(Math.min(64, Long.numberOfTrailingZeros(a.upMask) + Long.numberOfTrailingZeros(b.upMask))) & CodeUtil.mask(bits);
if (a.canBePositive()) {
if (b.canBePositive()) {
@@ -1023,6 +1038,9 @@
PrimitiveConstant a = (PrimitiveConstant) const1;
PrimitiveConstant b = (PrimitiveConstant) const2;
assert a.getJavaKind() == b.getJavaKind();
+ if (b.asLong() == 0) {
+ return null;
+ }
return JavaConstant.forIntegerKind(a.getJavaKind(), a.asLong() / b.asLong());
}
@@ -1031,9 +1049,12 @@
IntegerStamp a = (IntegerStamp) stamp1;
IntegerStamp b = (IntegerStamp) stamp2;
assert a.getBits() == b.getBits();
- if (b.isStrictlyPositive()) {
- long newLowerBound = a.lowerBound() / b.upperBound();
- long newUpperBound = a.upperBound() / b.lowerBound();
+ if (a.lowerBound == a.upperBound && b.lowerBound == b.upperBound && b.lowerBound != 0) {
+ long value = CodeUtil.convert(a.lowerBound() / b.lowerBound(), a.getBits(), false);
+ return StampFactory.forInteger(a.getBits(), value, value);
+ } else if (b.isStrictlyPositive()) {
+ long newLowerBound = a.lowerBound() < 0 ? a.lowerBound() / b.lowerBound() : a.lowerBound() / b.upperBound();
+ long newUpperBound = a.upperBound() < 0 ? a.upperBound() / b.upperBound() : a.upperBound() / b.lowerBound();
return StampFactory.forInteger(a.getBits(), newLowerBound, newUpperBound);
} else {
return a.unrestricted();
@@ -1054,6 +1075,9 @@
PrimitiveConstant a = (PrimitiveConstant) const1;
PrimitiveConstant b = (PrimitiveConstant) const2;
assert a.getJavaKind() == b.getJavaKind();
+ if (b.asLong() == 0) {
+ return null;
+ }
return JavaConstant.forIntegerKind(a.getJavaKind(), a.asLong() % b.asLong());
}
@@ -1062,6 +1086,12 @@
IntegerStamp a = (IntegerStamp) stamp1;
IntegerStamp b = (IntegerStamp) stamp2;
assert a.getBits() == b.getBits();
+
+ if (a.lowerBound == a.upperBound && b.lowerBound == b.upperBound && b.lowerBound != 0) {
+ long value = CodeUtil.convert(a.lowerBound() % b.lowerBound(), a.getBits(), false);
+ return StampFactory.forInteger(a.getBits(), value, value);
+ }
+
// zero is always possible
long newLowerBound = Math.min(a.lowerBound(), 0);
long newUpperBound = Math.max(a.upperBound(), 0);
@@ -1364,6 +1394,10 @@
public Stamp foldStamp(Stamp input) {
IntegerStamp stamp = (IntegerStamp) input;
int bits = stamp.getBits();
+ if (stamp.lowerBound == stamp.upperBound) {
+ long value = CodeUtil.convert(Math.abs(stamp.lowerBound()), stamp.getBits(), false);
+ return StampFactory.forInteger(stamp.getBits(), value, value);
+ }
if (stamp.lowerBound() == CodeUtil.minValue(bits)) {
return input.unrestricted();
} else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Thu Nov 16 10:45:42 2017 -0800
@@ -49,8 +49,8 @@
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
import org.graalvm.compiler.debug.DebugCloseable;
+import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugHandlersFactory;
-import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
@@ -73,6 +73,8 @@
import org.graalvm.compiler.phases.verify.VerifyBailoutUsage;
import org.graalvm.compiler.phases.verify.VerifyCallerSensitiveMethods;
import org.graalvm.compiler.phases.verify.VerifyDebugUsage;
+import org.graalvm.compiler.phases.verify.VerifyGetOptionsUsage;
+import org.graalvm.compiler.phases.verify.VerifyGraphAddUsage;
import org.graalvm.compiler.phases.verify.VerifyInstanceOfUsage;
import org.graalvm.compiler.phases.verify.VerifyUpdateUsages;
import org.graalvm.compiler.phases.verify.VerifyUsageWithEquals;
@@ -381,6 +383,8 @@
new VerifyUpdateUsages().apply(graph, context);
new VerifyBailoutUsage().apply(graph, context);
new VerifyInstanceOfUsage().apply(graph, context);
+ new VerifyGraphAddUsage().apply(graph, context);
+ new VerifyGetOptionsUsage().apply(graph, context);
if (graph.method().isBridge()) {
BridgeMethodUtils.getBridgedMethod(graph.method());
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest14.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 org.graalvm.compiler.core.test;
+
+import org.graalvm.compiler.graph.iterators.NodeIterable;
+import org.graalvm.compiler.nodes.ConstantNode;
+import org.graalvm.compiler.nodes.FixedGuardNode;
+import org.graalvm.compiler.nodes.GuardNode;
+import org.graalvm.compiler.nodes.LogicNode;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
+import org.graalvm.compiler.nodes.java.LoadIndexedNode;
+import org.graalvm.compiler.nodes.memory.FloatingReadNode;
+import org.graalvm.compiler.nodes.memory.ReadNode;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.graalvm.compiler.phases.common.FloatingReadPhase;
+import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
+import org.graalvm.compiler.phases.common.LoweringPhase;
+import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.junit.Assert;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.DeoptimizationReason;
+
+/**
+ * Check that multiple bounds checks are correctly grouped together.
+ */
+public class ConditionalEliminationTest14 extends ConditionalEliminationTestBase {
+
+ public static void test1Snippet(Object[] args) {
+ Object a5 = args[5];
+ Object a7 = args[7];
+ Object a6 = args[6];
+
+ /*
+ * The order of the conditions matters: The scheduler processes the floating reads for the
+ * array loads in the order of the conditions here, and we want the index 7 access to be
+ * processed before the index 6 access.
+ */
+ if (a5 != null && a7 != null && a6 != null) {
+ sink1 = 1;
+ }
+ sink0 = 0;
+ }
+
+ @Test
+ public void test1() {
+ StructuredGraph graph = parseEager("test1Snippet", AllowAssumptions.YES);
+ CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+ PhaseContext context = new PhaseContext(getProviders());
+
+ /* Convert the LoadIndexNode to ReadNode with floating guards. */
+ new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+ /* Convert the ReadNode to FloatingReadNode. */
+ new FloatingReadPhase().apply(graph);
+ /* Apply the phase that we want to test. */
+ new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context);
+
+ Assert.assertEquals("All guards must be floating", 0, graph.getNodes(FixedGuardNode.TYPE).count());
+ Assert.assertEquals("All array accesses must have been lowered", 0, graph.getNodes().filter(LoadIndexedNode.class).count());
+ Assert.assertEquals("All reads must be floating", 0, graph.getNodes().filter(ReadNode.class).count());
+ Assert.assertEquals("Must have floating reads (3 array accesses, 1 array length)", 4, graph.getNodes().filter(FloatingReadNode.class).count());
+
+ NodeIterable<GuardNode> boundsChecks = graph.getNodes(GuardNode.TYPE).filter(n -> ((GuardNode) n).getReason() == DeoptimizationReason.BoundsCheckException);
+ Assert.assertEquals("Must have only 1 bounds check remaining", 1, boundsChecks.count());
+ LogicNode condition = boundsChecks.first().getCondition();
+ Assert.assertTrue("Bounds check must check for array length 8", condition instanceof IntegerBelowNode && ((IntegerBelowNode) condition).getY().valueEquals(ConstantNode.forInt(8)));
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java Thu Nov 16 10:45:42 2017 -0800
@@ -27,12 +27,15 @@
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.phases.OptimisticOptimizations;
+import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.ConditionalEliminationPhase;
import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Assert;
@@ -45,6 +48,15 @@
protected static int sink1;
protected static int sink2;
+ /**
+ * These tests assume all code paths in called routines are reachable so disable removal of dead
+ * code based on method profiles.
+ */
+ @Override
+ protected HighTierContext getDefaultHighTierContext() {
+ return new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL.remove(Optimization.RemoveNeverExecutedCode));
+ }
+
protected void testConditionalElimination(String snippet, String referenceSnippet) {
testConditionalElimination(snippet, referenceSnippet, false, false);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.core.test;
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.graalvm.compiler.debug.DebugOptions;
+import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.util.EconomicMap;
+import org.junit.Test;
+
+/**
+ * Check that setting the dump path results in files ending up in the right directory with matching
+ * names.
+ */
+public class DumpPathTest extends GraalCompilerTest {
+
+ public static Object snippet() {
+ return new String("snippet");
+ }
+
+ @Test
+ public void testDump() throws IOException {
+ Path dumpDirectoryPath = Files.createTempDirectory("DumpPathTest");
+ String[] extensions = new String[]{".cfg", ".bgv", ".graph-strings"};
+ EconomicMap<OptionKey<?>, Object> overrides = OptionValues.newOptionMap();
+ overrides.put(DebugOptions.DumpPath, dumpDirectoryPath.toString());
+ overrides.put(DebugOptions.PrintGraphFile, true);
+ overrides.put(DebugOptions.PrintCanonicalGraphStrings, true);
+ overrides.put(DebugOptions.Dump, "*");
+
+ // Generate dump files.
+ test(new OptionValues(getInitialOptions(), overrides), "snippet");
+ // Check that Ideal files got created, in the right place.
+ checkForFiles(dumpDirectoryPath, extensions);
+
+ // Clean up the generated files.
+ scrubDirectory(dumpDirectoryPath);
+ }
+
+ /**
+ * Check that the given directory contains file or directory names with all the given
+ * extensions.
+ */
+ private static void checkForFiles(Path directoryPath, String[] extensions) throws IOException {
+ String[] paths = new String[extensions.length];
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath)) {
+ for (Path filePath : stream) {
+ String fileName = filePath.getFileName().toString();
+ for (int i = 0; i < extensions.length; i++) {
+ String extension = extensions[i];
+ if (fileName.endsWith(extensions[i])) {
+ assertTrue(paths[i] == null, "multiple files found for %s in %s", extension, directoryPath);
+ paths[i] = fileName.replace(extensions[i], "");
+ }
+ }
+ }
+ }
+ for (int i = 0; i < paths.length; i++) {
+ assertTrue(paths[i] != null, "missing file for extension %s in %s", extensions[i], directoryPath);
+ }
+ // Ensure that all file names are the same.
+ for (int i = 1; i < paths.length; i++) {
+ assertTrue(paths[0].equals(paths[i]), paths[0] + " != " + paths[i]);
+ }
+ }
+
+ /**
+ * Remove the temporary directory.
+ */
+ private static void scrubDirectory(Path directoryPath) {
+ try {
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath)) {
+ for (Path filePath : stream) {
+ if (Files.isRegularFile(filePath)) {
+ Files.delete(filePath);
+ } else if (Files.isDirectory(filePath)) {
+ scrubDirectory(filePath);
+ }
+ }
+ }
+ Files.delete(directoryPath);
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -72,7 +72,7 @@
Assert.assertTrue(constructors.length == 1);
final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(constructors[0]);
OptionValues options = getInitialOptions();
- StructuredGraph graph = new StructuredGraph.Builder(options, getDebugContext(options), allowAssumptions).method(javaMethod).build();
+ StructuredGraph graph = new StructuredGraph.Builder(options, getDebugContext(options, null, javaMethod), allowAssumptions).method(javaMethod).build();
GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(getDefaultGraphBuilderPlugins());
new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), getProviders().getConstantFieldProvider(), conf,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -389,7 +389,7 @@
* {@link DebugDumpHandler}s closed in {@link #afterTest()}.
*/
protected DebugContext getDebugContext() {
- return getDebugContext(getInitialOptions());
+ return getDebugContext(getInitialOptions(), null, null);
}
@Override
@@ -862,7 +862,7 @@
Result actual = executeActual(options, method, receiver, args);
profile = method.getProfilingInfo(); // profile can change after execution
for (DeoptimizationReason reason : shouldNotDeopt) {
- Assert.assertEquals((int) deoptCounts.get(reason), profile.getDeoptimizationCount(reason));
+ Assert.assertEquals("wrong number of deopt counts for " + reason, (int) deoptCounts.get(reason), profile.getDeoptimizationCount(reason));
}
return actual;
}
@@ -1216,15 +1216,15 @@
protected final Builder builder(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) {
OptionValues options = getInitialOptions();
- return new Builder(options, getDebugContext(options), allowAssumptions).method(method).compilationId(getCompilationId(method));
+ return new Builder(options, getDebugContext(options, null, method), allowAssumptions).method(method).compilationId(getCompilationId(method));
}
protected final Builder builder(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) {
- return new Builder(options, getDebugContext(options), allowAssumptions).method(method).compilationId(compilationId);
+ return new Builder(options, getDebugContext(options, compilationId.toString(CompilationIdentifier.Verbosity.ID), method), allowAssumptions).method(method).compilationId(compilationId);
}
protected final Builder builder(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, OptionValues options) {
- return new Builder(options, getDebugContext(options), allowAssumptions).method(method).compilationId(getCompilationId(method));
+ return new Builder(options, getDebugContext(options, null, method), allowAssumptions).method(method).compilationId(getCompilationId(method));
}
protected PhaseSuite<HighTierContext> getDebugGraphBuilderSuite() {
@@ -1234,6 +1234,7 @@
@SuppressWarnings("try")
protected StructuredGraph parse(StructuredGraph.Builder builder, PhaseSuite<HighTierContext> graphBuilderSuite) {
ResolvedJavaMethod javaMethod = builder.getMethod();
+ builder.speculationLog(getSpeculationLog());
if (builder.getCancellable() == null) {
builder.cancellable(getCancellable(javaMethod));
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalDebugHandlersFactoryTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalDebugHandlersFactoryTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -31,8 +31,12 @@
import java.nio.file.Paths;
import java.util.Comparator;
-import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
+import org.graalvm.compiler.debug.DebugOptions;
+import org.graalvm.compiler.debug.PathUtilities;
+import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.test.AddExports;
+import org.junit.Assume;
import org.junit.Test;
@AddExports("jdk.internal.vm.compiler/org.graalvm.compiler.printer")
@@ -40,23 +44,28 @@
@Test
public void createUniqueTest() throws Exception {
- Field maxFileNameLengthField = GraalDebugHandlersFactory.class.getDeclaredField("MAX_FILE_NAME_LENGTH");
- maxFileNameLengthField.setAccessible(true);
+ Field maxFileNameLengthField = PathUtilities.class.getDeclaredField("MAX_FILE_NAME_LENGTH");
+ try {
+ maxFileNameLengthField.setAccessible(true);
+ } catch (RuntimeException ex) {
+ Assume.assumeFalse("If InaccessibleObjectException is thrown, skip the test, we are on JDK9", ex.getClass().getSimpleName().equals("InaccessibleObjectException"));
+ }
int maxFileNameLength = maxFileNameLengthField.getInt(null);
- Method createUniqueMethod = GraalDebugHandlersFactory.class.getDeclaredMethod("createUnique", Path.class, String.class, String.class, String.class, boolean.class);
+ Method createUniqueMethod = PathUtilities.class.getDeclaredMethod("createUnique", OptionValues.class, OptionKey.class, String.class, String.class, String.class, boolean.class);
createUniqueMethod.setAccessible(true);
Path tmpDir = Files.createTempDirectory(Paths.get("."), "createUniqueTest");
+ OptionValues options = new OptionValues(OptionValues.asMap(DebugOptions.DumpPath, tmpDir.toString()));
try {
for (boolean createDirectory : new boolean[]{true, false}) {
for (String ext : new String[]{"", ".bgv", ".graph-strings"}) {
for (int i = 0; i < maxFileNameLength + 5; i++) {
String id = new String(new char[i]).replace('\0', 'i');
String label = "";
- createUniqueMethod.invoke(null, tmpDir, id, label, ext, createDirectory);
+ createUniqueMethod.invoke(null, options, null, id, label, ext, createDirectory);
id = "";
label = new String(new char[i]).replace('\0', 'l');
- createUniqueMethod.invoke(null, tmpDir, id, label, ext, createDirectory);
+ createUniqueMethod.invoke(null, options, null, id, label, ext, createDirectory);
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -144,6 +144,11 @@
public void test01() {
Super inheritsHC = new Super();
Person overridesHC = new Person(0);
+
+ // Ensure the profile for getSuperAge includes both receiver types
+ getSuperAge(inheritsHC);
+ getSuperAge(overridesHC);
+
test("getSuperAge", inheritsHC);
test("getSuperAge", overridesHC);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,6 +22,8 @@
*/
package org.graalvm.compiler.core.test;
+import java.util.HashMap;
+
import org.graalvm.compiler.core.phases.HighTier;
import org.graalvm.compiler.core.phases.MidTier;
import org.graalvm.compiler.nodes.InvokeNode;
@@ -139,6 +141,10 @@
public void test08() {
initialize(Appendable.class);
checkForGuardedIntrinsicPattern("hashCodeInterface");
+
+ // Ensure the profile for the dispatch in hashCodeSnippet01
+ // has a receiver type that does not select Object.hashCode intrinsic
+ hashCodeSnippet01(new HashMap<>());
checkForGuardedIntrinsicPattern("hashCodeSnippet01");
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -25,6 +25,7 @@
import static java.nio.file.StandardOpenOption.READ;
import static java.nio.file.StandardOpenOption.WRITE;
+import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
@@ -33,22 +34,20 @@
import java.nio.file.Files;
import java.nio.file.Path;
-import jdk.vm.ci.code.InstalledCode;
-import jdk.vm.ci.code.InvalidInstalledCodeException;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaType;
-
-import org.junit.Assert;
-import org.junit.Assume;
-import org.junit.Test;
-
-import sun.misc.Unsafe;
-
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.inlining.InliningPhase;
import org.graalvm.compiler.phases.common.inlining.policy.InlineEverythingPolicy;
import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.code.InvalidInstalledCodeException;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import sun.misc.Unsafe;
public class MarkUnsafeAccessTest extends GraalCompilerTest {
@@ -170,7 +169,9 @@
try {
mbb.position(BLOCK_SIZE);
getter.get(mbb);
- System.currentTimeMillis(); // materialize async exception
+
+ // Make a call that goes into native code to materialize async exception
+ new File("").exists();
} catch (InternalError e) {
return;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -26,12 +26,23 @@
import org.graalvm.compiler.nodes.ReturnNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.phases.OptimisticOptimizations;
+import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.phases.tiers.PhaseContext;
import org.junit.Test;
public class MergeCanonicalizerTest extends GraalCompilerTest {
+ /**
+ * These tests assume all code paths are reachable so disable profile based dead code removal.
+ */
+ @Override
+ protected HighTierContext getDefaultHighTierContext() {
+ return new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL.remove(Optimization.RemoveNeverExecutedCode));
+ }
+
public static int staticField;
private int field;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ProfilingInfoTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ProfilingInfoTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -24,15 +24,17 @@
import java.io.Serializable;
+import org.graalvm.compiler.test.SubprocessUtil;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+
import jdk.vm.ci.meta.JavaTypeProfile;
import jdk.vm.ci.meta.ProfilingInfo;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.TriState;
-import org.junit.Assert;
-import org.junit.Test;
-
/**
* Tests profiling information provided by the runtime.
* <p>
@@ -40,7 +42,7 @@
* information may be gathered for any given method. For example, HotSpot's advanced compilation
* policy can decide to only gather partial profiles in a first level compilation (see
* AdvancedThresholdPolicy::common(...) in advancedThresholdPolicy.cpp). Because of this,
- * occasionally tests for {@link ProfilingInfo#getNullSeen(int)} can fail since HotSpot only set's
+ * occasionally tests for {@link ProfilingInfo#getNullSeen(int)} can fail since HotSpot only sets
* the null_seen bit when doing full profiling.
*/
public class ProfilingInfoTest extends GraalCompilerTest {
@@ -182,6 +184,14 @@
Assert.assertNull(typeProfile);
}
+ public ProfilingInfoTest() {
+ // These tests are explicitly testing the profiling behavior of the
+ // interpreter. C1-based profiling differs slightly and when -Xcomp
+ // is present, profiles will be created by C1 compiled code, not the
+ // interpreter.
+ Assume.assumeTrue(!SubprocessUtil.getVMCommandLine().contains("-Xcomp"));
+ }
+
@Test
public void testExceptionSeen() {
// NullPointerException
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SubWordReturnTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.core.test;
+
+import java.util.ArrayList;
+import java.util.List;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+@RunWith(Parameterized.class)
+public class SubWordReturnTest extends GraalCompilerTest {
+
+ private final JavaKind kind;
+ private final int value;
+
+ private final String generatedClassName;
+ private final String generatedClassNameInternal;
+
+ private final String testMethodName;
+
+ /**
+ * The {@link AsmLoader} generates a class looking like this for the types byte, short, int and
+ * char.
+ */
+ static class ByteGetter {
+
+ // private static int intField = 1000000;
+
+ private static byte get() {
+ // GETSTATIC intField
+ // IRETURN
+ return 0;
+ }
+
+ public static int testByteSnippet() {
+ return get();
+ }
+ }
+
+ @Parameters(name = "{0}, {1}")
+ public static List<Object[]> data() {
+ ArrayList<Object[]> ret = new ArrayList<>();
+ for (int i : new int[]{1000000, 1000001, -1000000, -1}) {
+ ret.add(new Object[]{JavaKind.Boolean, i});
+ ret.add(new Object[]{JavaKind.Byte, i});
+ ret.add(new Object[]{JavaKind.Short, i});
+ ret.add(new Object[]{JavaKind.Char, i});
+ }
+ return ret;
+ }
+
+ public SubWordReturnTest(JavaKind kind, int value) {
+ this.kind = kind;
+ this.value = value;
+
+ this.generatedClassName = SubWordReturnTest.class.getName() + "$" + kind.toString() + "Getter";
+ this.generatedClassNameInternal = generatedClassName.replace('.', '/');
+ this.testMethodName = "test" + kind.name() + "Snippet";
+ }
+
+ @Test
+ public void test() throws ClassNotFoundException {
+ Class<?> testClass = new AsmLoader(SubWordReturnTest.class.getClassLoader()).findClass(generatedClassName);
+ ResolvedJavaMethod method = getResolvedJavaMethod(testClass, testMethodName);
+ test(method, null);
+ }
+
+ class AsmLoader extends ClassLoader implements Opcodes {
+
+ Class<?> loaded;
+
+ AsmLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ if (name.equals(generatedClassName)) {
+ if (loaded == null) {
+ byte[] gen = generateClass();
+ loaded = defineClass(name, gen, 0, gen.length);
+ }
+ return loaded;
+ } else {
+ return super.findClass(name);
+ }
+ }
+
+ private byte[] generateClass() {
+ ClassWriter cw = new ClassWriter(0);
+ cw.visit(52, ACC_SUPER | ACC_PUBLIC, generatedClassNameInternal, null, "java/lang/Object", null);
+
+ FieldVisitor intField = cw.visitField(ACC_PRIVATE | ACC_STATIC, "intField", "I", null, value);
+ intField.visitEnd();
+
+ MethodVisitor get = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, "get", "()" + kind.getTypeChar(), null, null);
+ get.visitCode();
+ get.visitFieldInsn(GETSTATIC, generatedClassNameInternal, "intField", "I");
+ get.visitInsn(IRETURN);
+ get.visitMaxs(1, 0);
+ get.visitEnd();
+
+ MethodVisitor snippet = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, testMethodName, "()I", null, null);
+ snippet.visitCode();
+ snippet.visitMethodInsn(INVOKESTATIC, generatedClassNameInternal, "get", "()" + kind.getTypeChar(), false);
+ snippet.visitInsn(IRETURN);
+ snippet.visitMaxs(1, 0);
+ snippet.visitEnd();
+
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -87,7 +87,7 @@
ResolvedJavaMethod method = getResolvedJavaMethod(LOADER.findClass(INNER_CLASS_NAME), name);
try {
OptionValues options = getInitialOptions();
- StructuredGraph graph = new StructuredGraph.Builder(options, getDebugContext(options)).method(method).build();
+ StructuredGraph graph = new StructuredGraph.Builder(options, getDebugContext(options, null, method)).method(method).build();
Plugins plugins = new Plugins(new InvocationPlugins());
GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true).withUnresolvedIsError(true);
OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -32,9 +32,20 @@
import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
import org.junit.Test;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
public class UnsafeVirtualizationTest extends GraalCompilerTest {
- public static class A {
+ public static class Base {
+ /*
+ * This padding ensure that the size of the Base class ends up as a multiple of 8, which
+ * makes the first field of the subclass 8-byte aligned.
+ */
+ double padding;
+ }
+
+ public static class A extends Base {
int f1;
int f2;
}
@@ -56,39 +67,96 @@
AF2Offset = o2;
}
- public static int unsafeSnippet0(int i1, int i2) {
+ public static int unsafeSnippet1(double i1) {
A a = new A();
- UNSAFE.putDouble(a, AF1Offset, i1 + i2);
+ UNSAFE.putDouble(a, AF1Offset, i1);
return UNSAFE.getInt(a, AF1Offset) + UNSAFE.getInt(a, AF2Offset);
}
- public static int unsafeSnippet1(int i1, int i2) {
+ public static long unsafeSnippet2a(int i1) {
+ A a = new A();
+ UNSAFE.putDouble(a, AF1Offset, i1);
+ a.f1 = i1;
+ return UNSAFE.getLong(a, AF1Offset);
+ }
+
+ public static long unsafeSnippet2b(int i1) {
+ A a = new A();
+ UNSAFE.putDouble(a, AF1Offset, i1);
+ a.f2 = i1;
+ return UNSAFE.getLong(a, AF1Offset);
+ }
+
+ public static long unsafeSnippet3a(int i1) {
A a = new A();
- UNSAFE.putDouble(a, AF1Offset, i1 + i2);
- a.f2 = i1;
- return (int) UNSAFE.getDouble(a, AF1Offset);
+ UNSAFE.putDouble(a, AF1Offset, i1);
+ UNSAFE.putInt(a, AF1Offset, i1);
+ return UNSAFE.getLong(a, AF1Offset);
+ }
+
+ public static long unsafeSnippet3b(int i1) {
+ A a = new A();
+ UNSAFE.putDouble(a, AF1Offset, i1);
+ UNSAFE.putInt(a, AF2Offset, i1);
+ return UNSAFE.getLong(a, AF1Offset);
+ }
+
+ public static int unsafeSnippet4(double i1) {
+ A a = new A();
+ UNSAFE.putDouble(a, AF1Offset, i1);
+ UNSAFE.putDouble(a, AF1Offset, i1);
+ return UNSAFE.getInt(a, AF1Offset) + UNSAFE.getInt(a, AF2Offset);
}
@Test
public void testUnsafePEA01() {
- testPartialEscapeReadElimination(parseEager("unsafeSnippet0", AllowAssumptions.NO), false);
- testPartialEscapeReadElimination(parseEager("unsafeSnippet0", AllowAssumptions.NO), true);
+ testPartialEscapeReadElimination("unsafeSnippet1", false, 1.0);
+ testPartialEscapeReadElimination("unsafeSnippet1", true, 1.0);
}
@Test
public void testUnsafePEA02() {
- testPartialEscapeReadElimination(parseEager("unsafeSnippet1", AllowAssumptions.NO), false);
- testPartialEscapeReadElimination(parseEager("unsafeSnippet1", AllowAssumptions.NO), true);
+ testPartialEscapeReadElimination("unsafeSnippet2a", false, 1);
+ testPartialEscapeReadElimination("unsafeSnippet2a", true, 1);
+
+ testPartialEscapeReadElimination("unsafeSnippet2b", false, 1);
+ testPartialEscapeReadElimination("unsafeSnippet2b", true, 1);
}
- public void testPartialEscapeReadElimination(StructuredGraph graph, boolean canonicalizeBefore) {
+ @Test
+ public void testUnsafePEA03() {
+ testPartialEscapeReadElimination("unsafeSnippet3a", false, 1);
+ testPartialEscapeReadElimination("unsafeSnippet3a", true, 1);
+
+ testPartialEscapeReadElimination("unsafeSnippet3b", false, 1);
+ testPartialEscapeReadElimination("unsafeSnippet3b", true, 1);
+ }
+
+ @Test
+ public void testUnsafePEA04() {
+ testPartialEscapeReadElimination("unsafeSnippet4", false, 1.0);
+ testPartialEscapeReadElimination("unsafeSnippet4", true, 1.0);
+ }
+
+ public void testPartialEscapeReadElimination(String snippet, boolean canonicalizeBefore, Object... args) {
+ assert AF1Offset % 8 == 0 : "First of the two int-fields must be 8-byte aligned";
+
+ ResolvedJavaMethod method = getResolvedJavaMethod(snippet);
+ StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
OptionValues options = graph.getOptions();
PhaseContext context = getDefaultHighTierContext();
CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
if (canonicalizeBefore) {
canonicalizer.apply(graph, context);
}
+ Result r = executeExpected(method, null, args);
new PartialEscapePhase(true, true, canonicalizer, null, options).apply(graph, context);
+ try {
+ InstalledCode code = getCode(method, graph);
+ Object result = code.executeVarargs(args);
+ assertEquals(r, new Result(result, null));
+ } catch (Throwable e) {
+ assertFalse(true, e.toString());
+ }
}
-
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java Thu Nov 16 10:45:42 2017 -0800
@@ -77,7 +77,7 @@
@Override
public String toString() {
- return "{" + x + "," + y + "}";
+ return "{" + x + "," + y + "," + z + "}";
}
@Override
@@ -158,11 +158,19 @@
context = getDefaultHighTierContext();
new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
new DeadCodeEliminationPhase().apply(graph);
- new CanonicalizerPhase().apply(graph, context);
+ canonicalizeGraph();
new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context);
+ postEACanonicalizeGraph();
returnNodes = graph.getNodes(ReturnNode.TYPE).snapshot();
} catch (Throwable e) {
throw debug.handle(e);
}
}
+
+ protected void postEACanonicalizeGraph() {
+ }
+
+ protected void canonicalizeGraph() {
+ new CanonicalizerPhase().apply(graph, context);
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAAssertionsTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAAssertionsTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -27,9 +27,20 @@
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.code.SourceStackTraceBailoutException;
import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.phases.OptimisticOptimizations;
+import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
public class PEAAssertionsTest extends GraalCompilerTest {
+ /**
+ * These tests assume all code paths are reachable so disable profile based dead code removal.
+ */
+ @Override
+ protected HighTierContext getDefaultHighTierContext() {
+ return new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL.remove(Optimization.RemoveNeverExecutedCode));
+ }
+
public static Object field;
public static void snippet1(int i) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/TrufflePEATest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/TrufflePEATest.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,6 +22,8 @@
*/
package org.graalvm.compiler.core.test.ea;
+import java.lang.reflect.Field;
+
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.nodes.StructuredGraph;
@@ -33,10 +35,9 @@
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
import org.junit.Test;
+
import sun.misc.Unsafe;
-import java.lang.reflect.Field;
-
public class TrufflePEATest extends GraalCompilerTest {
/**
@@ -56,6 +57,7 @@
static class DynamicObject {
int primitiveField0;
int primitiveField1;
+ int primitiveField2;
}
private static final long offsetLong1 = Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * 1;
@@ -66,7 +68,15 @@
static {
try {
Field primitiveField0 = DynamicObject.class.getDeclaredField("primitiveField0");
- primitiveField0Offset = UNSAFE.objectFieldOffset(primitiveField0);
+ long offset = UNSAFE.objectFieldOffset(primitiveField0);
+ if (offset % 8 == 0) {
+ primitiveField0Offset = offset;
+ } else {
+ Field primitiveField1 = DynamicObject.class.getDeclaredField("primitiveField1");
+ offset = UNSAFE.objectFieldOffset(primitiveField1);
+ assert offset % 8 == 0;
+ primitiveField0Offset = offset;
+ }
} catch (NoSuchFieldException | SecurityException e) {
throw new AssertionError(e);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,14 +22,26 @@
*/
package org.graalvm.compiler.core.test.ea;
-import jdk.vm.ci.meta.JavaConstant;
+import java.nio.ByteBuffer;
+import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.graph.Graph;
+import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.nodes.NamedLocationIdentity;
+import org.graalvm.compiler.nodes.PhiNode;
+import org.graalvm.compiler.nodes.ValuePhiNode;
+import org.graalvm.compiler.nodes.calc.UnpackEndianHalfNode;
+import org.graalvm.compiler.nodes.extended.RawLoadNode;
+import org.graalvm.compiler.nodes.extended.RawStoreNode;
+import org.graalvm.compiler.nodes.extended.UnsafeAccessNode;
+import org.graalvm.compiler.nodes.java.LoadFieldNode;
+import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.junit.Assert;
import org.junit.Test;
-import org.graalvm.compiler.nodes.PhiNode;
-import org.graalvm.compiler.nodes.ValuePhiNode;
-import org.graalvm.compiler.nodes.java.LoadFieldNode;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
public class UnsafeEATest extends EATestBase {
@@ -56,6 +68,64 @@
}
}
+ @Override
+ protected void testEscapeAnalysis(String snippet, JavaConstant expectedConstantResult, boolean iterativeEscapeAnalysis) {
+ // Exercise both a graph containing UnsafeAccessNodes and one which has been possibly been
+ // canonicalized into AccessFieldNodes.
+ testingUnsafe = true;
+ super.testEscapeAnalysis(snippet, expectedConstantResult, iterativeEscapeAnalysis);
+ testingUnsafe = false;
+ super.testEscapeAnalysis(snippet, expectedConstantResult, iterativeEscapeAnalysis);
+ if (expectedConstantResult != null) {
+ // Check that a compiled version of this method returns the same value if we expect a
+ // constant result.
+ ResolvedJavaMethod method = getResolvedJavaMethod(snippet);
+ JavaKind[] javaKinds = method.getSignature().toParameterKinds(false);
+ Object[] args = new Object[javaKinds.length];
+ int i = 0;
+ for (JavaKind k : javaKinds) {
+ args[i++] = JavaConstant.defaultForKind(k).asBoxedPrimitive();
+ }
+ Result result = executeExpected(method, null, args);
+ assertTrue(result.returnValue.equals(expectedConstantResult.asBoxedPrimitive()));
+ }
+ }
+
+ @Override
+ protected void canonicalizeGraph() {
+ if (testingUnsafe) {
+ // For testing purposes we'd like to ensure that our raw unsafe operations stay as
+ // unsafe nodes, so force them to appear to have LocationIdentity.any to disable
+ // transformation into field access nodes.
+ for (Node node : graph.getNodes().filter(x -> x instanceof UnsafeAccessNode).snapshot()) {
+ if (node instanceof RawStoreNode) {
+ RawStoreNode store = (RawStoreNode) node;
+ RawStoreNode newStore = graph.add(new RawStoreNode(store.object(), store.offset(), store.value(), store.accessKind(), NamedLocationIdentity.any(),
+ store.needsBarrier(), store.stateAfter(), true));
+ graph.replaceFixedWithFixed(store, newStore);
+ } else if (node instanceof RawLoadNode) {
+ RawLoadNode load = (RawLoadNode) node;
+ RawLoadNode newLoad = graph.add(new RawLoadNode(load.object(), load.offset(), load.accessKind(), NamedLocationIdentity.any(),
+ true));
+ graph.replaceFixedWithFixed(load, newLoad);
+ }
+ }
+ }
+ super.canonicalizeGraph();
+ }
+
+ @Override
+ protected void postEACanonicalizeGraph() {
+ // Simplify any UnpackEndianHalfNode so we end up with constants.
+ Graph.Mark mark = graph.getMark();
+ for (UnpackEndianHalfNode node : graph.getNodes().filter(UnpackEndianHalfNode.class)) {
+ node.lower(getTarget().arch.getByteOrder());
+ }
+ new CanonicalizerPhase().applyIncremental(graph, context, mark);
+ }
+
+ private boolean testingUnsafe;
+
@Test
public void testSimpleInt() {
testEscapeAnalysis("testSimpleIntSnippet", JavaConstant.forInt(101), false);
@@ -90,6 +160,82 @@
}
@Test
+ public void testSimpleDoubleOverwriteWithInt() {
+ testEscapeAnalysis("testSimpleDoubleOverwriteWithIntSnippet", JavaConstant.forInt(10), false);
+ }
+
+ public static int testSimpleDoubleOverwriteWithIntSnippet() {
+ TestClassInt x = new TestClassInt();
+ UNSAFE.putDouble(x, fieldOffset1, 10.1);
+ UNSAFE.putInt(x, fieldOffset1, 10);
+ return UNSAFE.getInt(x, fieldOffset1);
+ }
+
+ @Test
+ public void testSimpleDoubleOverwriteWithSecondInt() {
+ ByteBuffer bb = ByteBuffer.allocate(8).order(getTarget().arch.getByteOrder());
+ bb.putDouble(10.1);
+ int value = bb.getInt(4);
+
+ testEscapeAnalysis("testSimpleDoubleOverwriteWithSecondIntSnippet", JavaConstant.forInt(value), false);
+ }
+
+ public static int testSimpleDoubleOverwriteWithSecondIntSnippet() {
+ TestClassInt x = new TestClassInt();
+ UNSAFE.putDouble(x, fieldOffset1, 10.1);
+ UNSAFE.putInt(x, fieldOffset1, 10);
+ return UNSAFE.getInt(x, fieldOffset2);
+ }
+
+ @Test
+ public void testSimpleDoubleOverwriteWithFirstInt() {
+ ByteBuffer bb = ByteBuffer.allocate(8).order(getTarget().arch.getByteOrder());
+ bb.putDouble(10.1);
+ int value = bb.getInt(0);
+
+ testEscapeAnalysis("testSimpleDoubleOverwriteWithFirstIntSnippet", JavaConstant.forInt(value), false);
+ }
+
+ public static int testSimpleDoubleOverwriteWithFirstIntSnippet() {
+ TestClassInt x = new TestClassInt();
+ UNSAFE.putDouble(x, fieldOffset1, 10.1);
+ UNSAFE.putInt(x, fieldOffset2, 10);
+ return UNSAFE.getInt(x, fieldOffset1);
+ }
+
+ @Test
+ public void testSimpleLongOverwriteWithSecondInt() {
+ ByteBuffer bb = ByteBuffer.allocate(8).order(getTarget().arch.getByteOrder());
+ bb.putLong(0, 0x1122334455667788L);
+ int value = bb.getInt(4);
+
+ testEscapeAnalysis("testSimpleLongOverwriteWithSecondIntSnippet", JavaConstant.forInt(value), false);
+ }
+
+ public static int testSimpleLongOverwriteWithSecondIntSnippet() {
+ TestClassInt x = new TestClassInt();
+ UNSAFE.putLong(x, fieldOffset1, 0x1122334455667788L);
+ UNSAFE.putInt(x, fieldOffset1, 10);
+ return UNSAFE.getInt(x, fieldOffset2);
+ }
+
+ @Test
+ public void testSimpleLongOverwriteWithFirstInt() {
+ ByteBuffer bb = ByteBuffer.allocate(8).order(getTarget().arch.getByteOrder());
+ bb.putLong(0, 0x1122334455667788L);
+ int value = bb.getInt(0);
+
+ testEscapeAnalysis("testSimpleLongOverwriteWithFirstIntSnippet", JavaConstant.forInt(value), false);
+ }
+
+ public static int testSimpleLongOverwriteWithFirstIntSnippet() {
+ TestClassInt x = new TestClassInt();
+ UNSAFE.putLong(x, fieldOffset1, 0x1122334455667788L);
+ UNSAFE.putInt(x, fieldOffset2, 10);
+ return UNSAFE.getInt(x, fieldOffset1);
+ }
+
+ @Test
public void testMergedDouble() {
testEscapeAnalysis("testMergedDoubleSnippet", null, false);
Assert.assertEquals(1, returnNodes.size());
@@ -111,6 +257,32 @@
return UNSAFE.getDouble(x, fieldOffset1);
}
+ static class ExtendedTestClassInt extends TestClassInt {
+ public long l;
+ }
+
+ @Test
+ public void testMergedVirtualObjects() {
+ testEscapeAnalysis("testMergedVirtualObjectsSnippet", null, false);
+ }
+
+ public static TestClassInt testMergedVirtualObjectsSnippet(int value) {
+ TestClassInt x;
+ if (value == 1) {
+ x = new TestClassInt();
+ UNSAFE.putDouble(x, fieldOffset1, 10);
+ } else {
+ x = new TestClassInt();
+ UNSAFE.putInt(x, fieldOffset1, 0);
+ }
+ UNSAFE.putInt(x, fieldOffset1, 0);
+ if (value == 2) {
+ UNSAFE.putInt(x, fieldOffset2, 0);
+ }
+ GraalDirectives.deoptimizeAndInvalidate();
+ return x;
+ }
+
@Test
public void testMaterializedDouble() {
test("testMaterializedDoubleSnippet");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -146,7 +146,7 @@
private StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer) {
OptionValues options = getInitialOptions();
- StructuredGraph newGraph = new StructuredGraph.Builder(options, getDebugContext(options), AllowAssumptions.NO).method(method).build();
+ StructuredGraph newGraph = new StructuredGraph.Builder(options, getDebugContext(options, null, method), AllowAssumptions.NO).method(method).build();
context.getGraphBuilderSuite().apply(newGraph, context);
new DeadCodeEliminationPhase(Optional).apply(newGraph);
canonicalizer.apply(newGraph, context);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Thu Nov 16 10:45:42 2017 -0800
@@ -47,7 +47,7 @@
public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose);
@Option(help = "The maximum number of compilation failures or bailouts to handle with the action specified " +
"by CompilationFailureAction or CompilationBailoutAction before changing to a less verbose action.", type = OptionType.User)
- public static final OptionKey<Integer> MaxCompilationProblemsPerAction = new OptionKey<>(5);
+ public static final OptionKey<Integer> MaxCompilationProblemsPerAction = new OptionKey<>(2);
@Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.User)
public static final OptionKey<Boolean> ExitVMOnException = new OptionKey<>(false);
// @formatter:on
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -132,8 +132,17 @@
slotKinds[pos] = toSlotKind(value);
pos++;
} else {
- assert currentField.values().get(i - 1).getStackKind() == JavaKind.Double || currentField.values().get(i - 1).getStackKind() == JavaKind.Long : vobjNode + " " + i + " " +
- currentField.values().get(i - 1);
+ assert value.getStackKind() == JavaKind.Illegal;
+ ValueNode previousValue = currentField.values().get(i - 1);
+ assert (previousValue != null && previousValue.getStackKind().needsTwoSlots()) : vobjNode + " " + i +
+ " " + previousValue + " " + currentField.values().snapshot();
+ if (previousValue == null || !previousValue.getStackKind().needsTwoSlots()) {
+ // Don't allow the IllegalConstant to leak into the debug info
+ JavaKind entryKind = vobjNode.entryKind(i);
+ values[pos] = JavaConstant.defaultForKind(entryKind.getStackKind());
+ slotKinds[pos] = entryKind.getStackKind();
+ pos++;
+ }
}
}
if (pos != entryCount) {
@@ -164,19 +173,19 @@
if (!type.isArray()) {
ResolvedJavaField[] fields = type.getInstanceFields(true);
int fieldIndex = 0;
- for (int i = 0; i < values.length; i++) {
- ResolvedJavaField field = fields[fieldIndex++];
- JavaKind valKind = slotKinds[i].getStackKind();
+ for (int valueIndex = 0; valueIndex < values.length; valueIndex++, fieldIndex++) {
+ ResolvedJavaField field = fields[fieldIndex];
+ JavaKind valKind = slotKinds[valueIndex].getStackKind();
JavaKind fieldKind = storageKind(field.getType());
- if (fieldKind == JavaKind.Object) {
- assert valKind.isObject() : field + ": " + valKind + " != " + fieldKind;
+ if ((valKind == JavaKind.Double || valKind == JavaKind.Long) && fieldKind == JavaKind.Int) {
+ assert fieldIndex + 1 < fields.length : String.format("Not enough fields for fieldIndex = %d valueIndex = %d %s %s", fieldIndex, valueIndex, Arrays.toString(fields),
+ Arrays.toString(values));
+ assert storageKind(fields[fieldIndex + 1].getType()) == JavaKind.Int : String.format("fieldIndex = %d valueIndex = %d %s %s %s", fieldIndex, valueIndex,
+ storageKind(fields[fieldIndex + 1].getType()), Arrays.toString(fields),
+ Arrays.toString(values));
+ fieldIndex++;
} else {
- if ((valKind == JavaKind.Double || valKind == JavaKind.Long) && fieldKind == JavaKind.Int) {
- assert storageKind(fields[fieldIndex].getType()) == JavaKind.Int;
- fieldIndex++;
- } else {
- assert valKind == fieldKind.getStackKind() : field + ": " + valKind + " != " + fieldKind;
- }
+ assert valKind == fieldKind.getStackKind() : field + ": " + valKind + " != " + fieldKind;
}
}
assert fields.length == fieldIndex : type + ": fields=" + Arrays.toString(fields) + ", field values=" + Arrays.toString(values);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java Thu Nov 16 10:45:42 2017 -0800
@@ -59,6 +59,7 @@
import org.graalvm.compiler.lir.SwitchStrategy;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.debug.LIRGenerationDebugContext;
+import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
import org.graalvm.compiler.lir.gen.LIRGenerator;
import org.graalvm.compiler.lir.gen.LIRGenerator.Options;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
@@ -577,9 +578,9 @@
@Override
public void emitInvoke(Invoke x) {
LoweredCallTargetNode callTarget = (LoweredCallTargetNode) x.callTarget();
- CallingConvention invokeCc = gen.getResult().getFrameMapBuilder().getRegisterConfig().getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(gen.getMetaAccess()),
- callTarget.signature(), gen);
- gen.getResult().getFrameMapBuilder().callsMethod(invokeCc);
+ FrameMapBuilder frameMapBuilder = gen.getResult().getFrameMapBuilder();
+ CallingConvention invokeCc = frameMapBuilder.getRegisterConfig().getCallingConvention(callTarget.callType(), x.asNode().stamp().javaType(gen.getMetaAccess()), callTarget.signature(), gen);
+ frameMapBuilder.callsMethod(invokeCc);
Value[] parameters = visitInvokeArguments(invokeCc, callTarget.arguments());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java Thu Nov 16 10:45:42 2017 -0800
@@ -195,9 +195,12 @@
public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult,
SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault, Object[] context) {
Object[] debugContext = context != null ? context : new Object[]{getProviders().getCodeCache(), method, compilationResult};
- CodeInstallationTask[] tasks = new CodeInstallationTask[codeInstallationTaskFactories.size()];
- for (int i = 0; i < codeInstallationTaskFactories.size(); i++) {
- tasks[i] = codeInstallationTaskFactories.get(i).create();
+ CodeInstallationTask[] tasks;
+ synchronized (this) {
+ tasks = new CodeInstallationTask[codeInstallationTaskFactories.size()];
+ for (int i = 0; i < codeInstallationTaskFactories.size(); i++) {
+ tasks[i] = codeInstallationTaskFactories.get(i).create();
+ }
}
try (DebugContext.Scope s2 = debug.scope("CodeInstall", debugContext);
DebugContext.Activation a = debug.activate()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java Thu Nov 16 10:45:42 2017 -0800
@@ -29,9 +29,11 @@
import static org.graalvm.compiler.debug.DebugOptions.Dump;
import static org.graalvm.compiler.debug.DebugOptions.DumpOnError;
import static org.graalvm.compiler.debug.DebugOptions.DumpOnPhaseChange;
+import static org.graalvm.compiler.debug.DebugOptions.DumpPath;
import static org.graalvm.compiler.debug.DebugOptions.ListMetrics;
import static org.graalvm.compiler.debug.DebugOptions.Log;
import static org.graalvm.compiler.debug.DebugOptions.MemUseTrackers;
+import static org.graalvm.compiler.debug.DebugOptions.ShowDumpFiles;
import static org.graalvm.compiler.debug.DebugOptions.Time;
import static org.graalvm.compiler.debug.DebugOptions.Timers;
import static org.graalvm.compiler.debug.DebugOptions.TrackMemUse;
@@ -56,6 +58,7 @@
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.graphio.GraphOutput;
import org.graalvm.util.EconomicMap;
import org.graalvm.util.EconomicSet;
import org.graalvm.util.Pair;
@@ -98,6 +101,8 @@
CloseableCounter currentMemUseTracker;
Scope lastClosedScope;
Throwable lastExceptionThrown;
+ private IgvDumpChannel sharedChannel;
+ private GraphOutput<?, ?> parentOutput;
/**
* Stores the {@link MetricKey} values.
@@ -111,6 +116,19 @@
return immutable.scopesEnabled;
}
+ public <G, N, M> GraphOutput<G, M> buildOutput(GraphOutput.Builder<G, N, M> builder) throws IOException {
+ if (parentOutput != null) {
+ return builder.build(parentOutput);
+ } else {
+ if (sharedChannel == null) {
+ sharedChannel = new IgvDumpChannel(() -> getDumpPath(".bgv", false), immutable.options);
+ }
+ final GraphOutput<G, M> output = builder.build(sharedChannel);
+ parentOutput = output;
+ return output;
+ }
+ }
+
/**
* The immutable configuration that can be shared between {@link DebugContext} objects.
*/
@@ -323,6 +341,14 @@
String compilableName = compilable instanceof JavaMethod ? ((JavaMethod) compilable).format("%H.%n(%p)%R") : String.valueOf(compilable);
return identifier + ":" + compilableName;
}
+
+ final String getLabel() {
+ if (compilable instanceof JavaMethod) {
+ JavaMethod method = (JavaMethod) compilable;
+ return method.format("%h.%n(%p)%r");
+ }
+ return String.valueOf(compilable);
+ }
}
private final Description description;
@@ -394,6 +420,20 @@
}
}
+ public Path getDumpPath(String extension, boolean directory) {
+ try {
+ String id = description == null ? null : description.identifier;
+ String label = description == null ? null : description.getLabel();
+ Path result = PathUtilities.createUnique(immutable.options, DumpPath, id, label, extension, directory);
+ if (ShowDumpFiles.getValue(immutable.options)) {
+ TTY.println("Dumping debug output to %s", result.toAbsolutePath().toString());
+ }
+ return result;
+ } catch (IOException ex) {
+ throw rethrowSilently(RuntimeException.class, ex);
+ }
+ }
+
/**
* A special dump level that indicates the dumping machinery is enabled but no dumps will be
* produced except through other options.
@@ -2043,4 +2083,9 @@
}
out.println();
}
+
+ @SuppressWarnings({"unused", "unchecked"})
+ private static <E extends Exception> E rethrowSilently(Class<E> type, Throwable ex) throws E {
+ throw (E) ex;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHandlersFactory.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHandlersFactory.java Thu Nov 16 10:45:42 2017 -0800
@@ -35,6 +35,9 @@
/**
* Creates {@link DebugHandler}s based on {@code options}.
+ *
+ * @param options options to control type and name of the channel
+ * @return list of debug handers that have been created
*/
List<DebugHandler> createHandlers(OptionValues options);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java Thu Nov 16 10:45:42 2017 -0800
@@ -128,8 +128,6 @@
public static final OptionKey<Boolean> PrintGraphProbabilities = new OptionKey<>(false);
@Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintGraph = new OptionKey<>(true);
- @Option(help = "Dump graphs in binary format instead of XML format.", type = OptionType.Debug)
- public static final OptionKey<Boolean> PrintBinaryGraphs = new OptionKey<>(true);
@Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug)
public static final OptionKey<Boolean> PrintGraphFile = new OptionKey<>(false);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/IgvDumpChannel.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.debug;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedByInterruptException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.function.Supplier;
+import static org.graalvm.compiler.debug.DebugOptions.PrintBinaryGraphPort;
+import static org.graalvm.compiler.debug.DebugOptions.PrintGraphHost;
+import org.graalvm.compiler.options.OptionValues;
+
+final class IgvDumpChannel implements WritableByteChannel {
+ private final Supplier<Path> pathProvider;
+ private final OptionValues options;
+ private WritableByteChannel sharedChannel;
+ private boolean closed;
+
+ IgvDumpChannel(Supplier<Path> pathProvider, OptionValues options) {
+ this.pathProvider = pathProvider;
+ this.options = options;
+ }
+
+ @Override
+ public int write(ByteBuffer src) throws IOException {
+ return channel().write(src);
+ }
+
+ @Override
+ public boolean isOpen() {
+ return !closed;
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+
+ void realClose() throws IOException {
+ closed = true;
+ if (sharedChannel != null) {
+ sharedChannel.close();
+ sharedChannel = null;
+ }
+ }
+
+ WritableByteChannel channel() throws IOException {
+ if (closed) {
+ throw new IOException();
+ }
+ if (sharedChannel == null) {
+ if (DebugOptions.PrintGraphFile.getValue(options)) {
+ sharedChannel = createFileChannel(pathProvider);
+ } else {
+ sharedChannel = createNetworkChannel(pathProvider, options);
+ }
+ }
+ return sharedChannel;
+ }
+
+ private static WritableByteChannel createNetworkChannel(Supplier<Path> pathProvider, OptionValues options) throws IOException {
+ String host = PrintGraphHost.getValue(options);
+ int port = PrintBinaryGraphPort.getValue(options);
+ try {
+ WritableByteChannel channel = SocketChannel.open(new InetSocketAddress(host, port));
+ TTY.println("Connected to the IGV on %s:%d", host, port);
+ return channel;
+ } catch (ClosedByInterruptException | InterruptedIOException e) {
+ /*
+ * Interrupts should not count as errors because they may be caused by a cancelled Graal
+ * compilation. ClosedByInterruptException occurs if the SocketChannel could not be
+ * opened. InterruptedIOException occurs if new Socket(..) was interrupted.
+ */
+ return null;
+ } catch (IOException e) {
+ if (!DebugOptions.PrintGraphFile.hasBeenSet(options)) {
+ return createFileChannel(pathProvider);
+ } else {
+ throw new IOException(String.format("Could not connect to the IGV on %s:%d", host, port), e);
+ }
+ }
+ }
+
+ private static WritableByteChannel createFileChannel(Supplier<Path> pathProvider) throws IOException {
+ Path path = pathProvider.get();
+ try {
+ return FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
+ } catch (IOException e) {
+ throw new IOException(String.format("Failed to open %s to dump IGV graphs", path), e);
+ }
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,12 +22,13 @@
*/
package org.graalvm.compiler.debug;
+import java.io.File;
import java.io.IOException;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.HashMap;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.graalvm.compiler.options.OptionKey;
@@ -39,54 +40,6 @@
public class PathUtilities {
private static final AtomicLong globalTimeStamp = new AtomicLong();
- /**
- * This generates a per thread persistent id to aid mapping related dump files with each other.
- */
- private static final ThreadLocal<PerThreadSequence> threadDumpId = new ThreadLocal<>();
- private static final AtomicInteger dumpId = new AtomicInteger();
-
- static class PerThreadSequence {
- final int threadID;
- HashMap<String, Integer> sequences = new HashMap<>(2);
-
- PerThreadSequence(int threadID) {
- this.threadID = threadID;
- }
-
- String generateID(String extension) {
- Integer box = sequences.get(extension);
- if (box == null) {
- sequences.put(extension, 1);
- return Integer.toString(threadID);
- } else {
- sequences.put(extension, box + 1);
- return Integer.toString(threadID) + '-' + box;
- }
- }
- }
-
- private static String getThreadDumpId(String extension) {
- PerThreadSequence id = threadDumpId.get();
- if (id == null) {
- id = new PerThreadSequence(dumpId.incrementAndGet());
- threadDumpId.set(id);
- }
- return id.generateID(extension);
- }
-
- /**
- * Prepends a period (i.e., {@code '.'}) to an non-null, non-empty string representation a file
- * extension if the string does not already start with a period.
- *
- * @return {@code ext} unmodified if it is null, empty or already starts with a period other
- * {@code "." + ext}
- */
- public static String formatExtension(String ext) {
- if (ext == null || ext.length() == 0) {
- return "";
- }
- return "." + ext;
- }
/**
* Gets a time stamp for the current process. This method will always return the same value for
@@ -100,43 +53,6 @@
}
/**
- * Generates a {@link Path} using the format "%s-%d_%d%s" with the {@code baseNameOption}, a
- * {@link #getGlobalTimeStamp() global timestamp} , {@link #getThreadDumpId a per thread unique
- * id} and an optional {@code extension}.
- *
- * @return the output file path or null if the flag is null
- */
- public static Path getPath(OptionValues options, OptionKey<String> baseNameOption, String extension) throws IOException {
- return getPath(options, baseNameOption, extension, true);
- }
-
- /**
- * Generate a {@link Path} using the format "%s-%d_%s" with the {@code baseNameOption}, a
- * {@link #getGlobalTimeStamp() global timestamp} and an optional {@code extension} .
- *
- * @return the output file path or null if the flag is null
- */
- public static Path getPathGlobal(OptionValues options, OptionKey<String> baseNameOption, String extension) throws IOException {
- return getPath(options, baseNameOption, extension, false);
- }
-
- private static Path getPath(OptionValues options, OptionKey<String> baseNameOption, String extension, boolean includeThreadId) throws IOException {
- if (baseNameOption.getValue(options) == null) {
- return null;
- }
- String ext = formatExtension(extension);
- final String name = includeThreadId
- ? String.format("%s-%d_%s%s", baseNameOption.getValue(options), getGlobalTimeStamp(), getThreadDumpId(ext), ext)
- : String.format("%s-%d%s", baseNameOption.getValue(options), getGlobalTimeStamp(), ext);
- Path result = Paths.get(name);
- if (result.isAbsolute()) {
- return result;
- }
- Path dumpDir = DebugOptions.getDumpDirectory(options);
- return dumpDir.resolve(name).normalize();
- }
-
- /**
* Gets a value based on {@code name} that can be passed to {@link Paths#get(String, String...)}
* without causing an {@link InvalidPathException}.
*
@@ -145,21 +61,80 @@
*/
public static String sanitizeFileName(String name) {
try {
- Paths.get(name);
- return name;
+ Path path = Paths.get(name);
+ if (path.getNameCount() == 0) {
+ return name;
+ }
} catch (InvalidPathException e) {
// fall through
}
StringBuilder buf = new StringBuilder(name.length());
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
- try {
- Paths.get(String.valueOf(c));
- } catch (InvalidPathException e) {
- buf.append('_');
+ if (c != File.separatorChar && c != ' ' && !Character.isISOControl(c)) {
+ try {
+ Paths.get(String.valueOf(c));
+ buf.append(c);
+ continue;
+ } catch (InvalidPathException e) {
+ }
}
- buf.append(c);
+ buf.append('_');
}
return buf.toString();
}
+
+ /**
+ * A maximum file name length supported by most file systems. There is no platform independent
+ * way to get this in Java.
+ */
+ private static final int MAX_FILE_NAME_LENGTH = 255;
+
+ private static final String ELLIPSIS = "...";
+
+ static Path createUnique(OptionValues options, OptionKey<String> baseNameOption, String id, String label, String ext, boolean createDirectory) throws IOException {
+ String uniqueTag = "";
+ int dumpCounter = 1;
+ String prefix;
+ if (id == null) {
+ prefix = baseNameOption.getValue(options);
+ int slash = prefix.lastIndexOf(File.separatorChar);
+ prefix = prefix.substring(slash + 1);
+ } else {
+ prefix = id;
+ }
+ for (;;) {
+ int fileNameLengthWithoutLabel = uniqueTag.length() + ext.length() + prefix.length() + "[]".length();
+ int labelLengthLimit = MAX_FILE_NAME_LENGTH - fileNameLengthWithoutLabel;
+ String fileName;
+ if (labelLengthLimit < ELLIPSIS.length()) {
+ // This means `id` is very long
+ String suffix = uniqueTag + ext;
+ int idLengthLimit = Math.min(MAX_FILE_NAME_LENGTH - suffix.length(), prefix.length());
+ fileName = sanitizeFileName(prefix.substring(0, idLengthLimit) + suffix);
+ } else {
+ if (label == null) {
+ fileName = sanitizeFileName(prefix + uniqueTag + ext);
+ } else {
+ String adjustedLabel = label;
+ if (label.length() > labelLengthLimit) {
+ adjustedLabel = label.substring(0, labelLengthLimit - ELLIPSIS.length()) + ELLIPSIS;
+ }
+ fileName = sanitizeFileName(prefix + '[' + adjustedLabel + ']' + uniqueTag + ext);
+ }
+ }
+ Path dumpDir = DebugOptions.getDumpDirectory(options);
+ Path result = Paths.get(dumpDir.toString(), fileName);
+ try {
+ if (createDirectory) {
+ return Files.createDirectory(result);
+ } else {
+ return Files.createFile(result);
+ }
+ } catch (FileAlreadyExistsException e) {
+ uniqueTag = "_" + dumpCounter++;
+ }
+ }
+ }
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/graphio/GraphSnippetTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.graph.test.graphio;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import static org.junit.Assert.assertTrue;
+import org.junit.Assume;
+import org.junit.Test;
+
+public class GraphSnippetTest {
+ @Test
+ public void dumpTheFile() throws Exception {
+ Class<?> snippets = null;
+ try {
+ snippets = Class.forName("org.graalvm.graphio.GraphSnippets");
+ } catch (ClassNotFoundException notFound) {
+ Assume.assumeNoException("The snippets class has to be around", notFound);
+ }
+ Method dump = null;
+ try {
+ dump = snippets.getDeclaredMethod("dump", File.class);
+ dump.setAccessible(true);
+ } catch (RuntimeException ex) {
+ Assume.assumeTrue("Only run the test, if the method is accessible", dump != null && dump.isAccessible());
+ }
+ File diamond = File.createTempFile("diamond", ".bgv");
+ dump.invoke(null, diamond);
+ assertTrue("File .bgv created: " + diamond, diamond.length() > 50);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/graphio/NodeEncodingTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.graph.test.graphio;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.channels.Channels;
+import java.nio.channels.WritableByteChannel;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.graalvm.graphio.GraphOutput;
+import org.graalvm.graphio.GraphStructure;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.junit.Before;
+import org.junit.Test;
+
+public final class NodeEncodingTest {
+
+ private ByteArrayOutputStream out;
+
+ @Before
+ public void initOutput() {
+ out = new ByteArrayOutputStream();
+ }
+
+ @Test
+ public void version40TheNodeIsntDumpedWithItsID() throws Exception {
+ runTheNodeIsntDumpedWithItsID(true);
+ }
+
+ @Test
+ public void defaultVersionTheNodeIsntDumpedWithItsID() throws Exception {
+ runTheNodeIsntDumpedWithItsID(false);
+ }
+
+ private void runTheNodeIsntDumpedWithItsID(boolean explicitVersion) throws Exception {
+ WritableByteChannel w = Channels.newChannel(out);
+ MockGraph graph = new MockGraph();
+ MockNodeClass clazz = new MockNodeClass("clazz");
+ MockNode node = new MockNode(clazz, 33); // random value otherwise not found in the stream
+ try (GraphOutput<MockGraph, ?> dump = explicitVersion ? GraphOutput.newBuilder(new MockStructure()).protocolVersion(4, 0).build(w) : GraphOutput.newBuilder(new MockStructure()).build(w)) {
+ dump.beginGroup(graph, "test1", "t1", null, 0, Collections.singletonMap("node", node));
+ dump.endGroup();
+ }
+
+ assertEquals("Node is always requested", 1, node.nodeRequested);
+ assertEquals("Nobody asks for id of a node in version 4.0", 0, node.idTested);
+ assertByte(false, out.toByteArray(), 33);
+ assertEquals("Node class of the node has been requested", 1, node.nodeClassRequested);
+ assertEquals("Node class template name stored", 1, clazz.nameTemplateQueried);
+ assertFalse("No to string ops", node.toStringRequested);
+ }
+
+ @Test
+ public void dumpingNodeInVersion10() throws Exception {
+ runTheNodeIsTreatedAsString(true);
+ }
+
+ private void runTheNodeIsTreatedAsString(boolean explicitVersion) throws Exception {
+ WritableByteChannel w = Channels.newChannel(out);
+ MockGraph graph = new MockGraph();
+ MockNodeClass clazz = new MockNodeClass("clazz");
+ MockNode node = new MockNode(clazz, 33); // random value otherwise not found in the stream
+ try (GraphOutput<MockGraph, ?> dump = explicitVersion ? GraphOutput.newBuilder(new MockStructure()).protocolVersion(1, 0).build(w) : GraphOutput.newBuilder(new MockStructure()).build(w)) {
+ dump.beginGroup(graph, "test1", "t1", null, 0, Collections.singletonMap("node", node));
+ dump.endGroup();
+ }
+
+ assertEquals("Node is always requested", 1, node.nodeRequested);
+ assertEquals("Nobody asks for id of a node in version 1.0", 0, node.idTested);
+ assertByte(false, out.toByteArray(), 33);
+ assertEquals("Node class was needed to find out it is not a NodeClass instance", 1, node.nodeClassRequested);
+ assertEquals("Node class template name wasn't needed however", 0, clazz.nameTemplateQueried);
+ assertTrue("Node sent as a string version 1.0", node.toStringRequested);
+ }
+
+ @Test
+ public void dumpingNodeInVersion15() throws Exception {
+ runTheNodeIsTreatedPoolEntry(true);
+ }
+
+ private void runTheNodeIsTreatedPoolEntry(boolean explicitVersion) throws Exception {
+ WritableByteChannel w = Channels.newChannel(out);
+ MockGraph graph = new MockGraph();
+ MockNodeClass clazz = new MockNodeClass("clazz");
+ MockNode node = new MockNode(clazz, 33); // random value otherwise not found in the stream
+ try (GraphOutput<MockGraph, ?> dump = explicitVersion ? GraphOutput.newBuilder(new MockStructure()).protocolVersion(5, 0).build(w) : GraphOutput.newBuilder(new MockStructure()).build(w)) {
+ dump.beginGroup(graph, "test1", "t1", null, 0, Collections.singletonMap("node", node));
+ dump.endGroup();
+ }
+
+ assertEquals("Node is always requested", 1, node.nodeRequested);
+ assertEquals("Id of our node is requested in version 5.0", 1, node.idTested);
+ assertByte(true, out.toByteArray(), 33);
+ assertTrue("Node class was needed at least once", 1 <= node.nodeClassRequested);
+ assertEquals("Node class template name sent to server", 1, clazz.nameTemplateQueried);
+ assertFalse("Node.toString() isn't needed", node.toStringRequested);
+ }
+
+ @Test
+ public void dumpingNodeTwiceInVersion4() throws Exception {
+ WritableByteChannel w = Channels.newChannel(out);
+ MockGraph graph = new MockGraph();
+ MockNodeClass clazz = new MockNodeClass("clazz");
+ MockNode node = new MockNode(clazz, 33); // random value otherwise not found in the stream
+ try (GraphOutput<MockGraph, ?> dump = GraphOutput.newBuilder(new MockStructure()).protocolVersion(4, 0).build(w)) {
+ Map<String, Object> props = new LinkedHashMap<>();
+ props.put("node1", node);
+ props.put("node2", node);
+ props.put("node3", node);
+ dump.beginGroup(graph, "test1", "t1", null, 0, props);
+ dump.endGroup();
+ }
+
+ assertEquals("Node requested three times", 3, node.nodeRequested);
+ assertEquals("Nobody asks for id of a node in version 4.0", 0, node.idTested);
+ // check there is no encoded string for object #3
+ assertByte(false, out.toByteArray(), 1, 0, 3);
+ assertEquals("Node class of the node has been requested three times", 3, node.nodeClassRequested);
+ assertEquals("Node class template name stored", 1, clazz.nameTemplateQueried);
+ assertFalse("No to string ops", node.toStringRequested);
+ }
+
+ private static void assertByte(boolean shouldBeFound, byte[] arr, int... value) {
+ boolean found = false;
+ int at = 0;
+ for (int i = 0; i < arr.length; i++) {
+ if (arr[i] == value[at]) {
+ if (++at == value.length) {
+ found = true;
+ break;
+ }
+ } else {
+ at = 0;
+ }
+ }
+ if (shouldBeFound == found) {
+ return;
+ }
+ if (shouldBeFound) {
+ fail("Value " + value + " not found in\n" + Arrays.toString(arr));
+ } else {
+ fail("Value " + value + " surprisingly found in\n" + Arrays.toString(arr));
+ }
+ }
+
+ private static final class MockStructure implements GraphStructure<MockGraph, MockNode, MockNodeClass, MockNodeClass> {
+
+ @Override
+ public MockGraph graph(MockGraph currentGraph, Object obj) {
+ return obj instanceof MockGraph ? (MockGraph) obj : null;
+ }
+
+ @Override
+ public Iterable<? extends MockNode> nodes(MockGraph graph) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public int nodesCount(MockGraph graph) {
+ return 0;
+ }
+
+ @Override
+ public int nodeId(MockNode node) {
+ node.idTested++;
+ return node.id;
+ }
+
+ @Override
+ public boolean nodeHasPredecessor(MockNode node) {
+ return false;
+ }
+
+ @Override
+ public void nodeProperties(MockGraph graph, MockNode node, Map<String, ? super Object> properties) {
+ }
+
+ @Override
+ public MockNode node(Object obj) {
+ if (obj instanceof MockNode) {
+ ((MockNode) obj).nodeRequested++;
+ return (MockNode) obj;
+ }
+ return null;
+ }
+
+ @Override
+ public MockNodeClass nodeClass(Object obj) {
+ if (obj instanceof MockNode) {
+ ((MockNode) obj).nodeClassRequested++;
+ }
+ return obj instanceof MockNodeClass ? (MockNodeClass) obj : null;
+ }
+
+ @Override
+ public MockNodeClass classForNode(MockNode n) {
+ n.nodeClassRequested++;
+ return n.clazz;
+ }
+
+ @Override
+ public String nameTemplate(MockNodeClass nodeClass) {
+ nodeClass.nameTemplateQueried++;
+ return "";
+ }
+
+ @Override
+ public Object nodeClassType(MockNodeClass nodeClass) {
+ return nodeClass.getClass();
+ }
+
+ @Override
+ public MockNodeClass portInputs(MockNodeClass nodeClass) {
+ return nodeClass;
+ }
+
+ @Override
+ public MockNodeClass portOutputs(MockNodeClass nodeClass) {
+ return nodeClass;
+ }
+
+ @Override
+ public int portSize(MockNodeClass port) {
+ return 0;
+ }
+
+ @Override
+ public boolean edgeDirect(MockNodeClass port, int index) {
+ return false;
+ }
+
+ @Override
+ public String edgeName(MockNodeClass port, int index) {
+ return null;
+ }
+
+ @Override
+ public Object edgeType(MockNodeClass port, int index) {
+ return null;
+ }
+
+ @Override
+ public Collection<? extends MockNode> edgeNodes(MockGraph graph, MockNode node, MockNodeClass port, int index) {
+ return null;
+ }
+ }
+
+ private static final class MockGraph {
+
+ }
+
+ private static final class MockNode {
+ final MockNodeClass clazz;
+ final int id;
+ int idTested;
+ int nodeClassRequested;
+ int nodeRequested;
+ boolean toStringRequested;
+
+ MockNode(MockNodeClass clazz, int id) {
+ this.clazz = clazz;
+ this.id = id;
+ }
+
+ @Override
+ public String toString() {
+ this.toStringRequested = true;
+ return "MockNode{" + "id=" + id + ", class=" + clazz + '}';
+ }
+ }
+
+ private static final class MockNodeClass {
+ final String name;
+ int nameTemplateQueried;
+
+ MockNodeClass(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return "MockNodeClass{" + "name=" + name + '}';
+ }
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java Thu Nov 16 10:45:42 2017 -0800
@@ -514,30 +514,61 @@
/**
* A node was added to a graph.
*/
- NODE_ADDED;
+ NODE_ADDED,
+
+ /**
+ * A node was removed from the graph.
+ */
+ NODE_REMOVED;
}
/**
* Client interested in one or more node related events.
*/
- public interface NodeEventListener {
+ public abstract static class NodeEventListener {
/**
- * Default handler for events.
+ * A method called when a change event occurs.
+ *
+ * This method dispatches the event to user-defined triggers. The methods that change the
+ * graph (typically in Graph and Node) must call this method to dispatch the event.
*
* @param e an event
* @param node the node related to {@code e}
*/
- default void event(NodeEvent e, Node node) {
+ final void event(NodeEvent e, Node node) {
+ switch (e) {
+ case INPUT_CHANGED:
+ inputChanged(node);
+ break;
+ case ZERO_USAGES:
+ usagesDroppedToZero(node);
+ break;
+ case NODE_ADDED:
+ nodeAdded(node);
+ break;
+ case NODE_REMOVED:
+ nodeRemoved(node);
+ break;
+ }
+ changed(e, node);
}
/**
- * Notifies this listener of a change in a node's inputs.
+ * Notifies this listener about any change event in the graph.
+ *
+ * @param e an event
+ * @param node the node related to {@code e}
+ */
+ public void changed(NodeEvent e, Node node) {
+ }
+
+ /**
+ * Notifies this listener about a change in a node's inputs.
*
* @param node a node who has had one of its inputs changed
*/
- default void inputChanged(Node node) {
- event(NodeEvent.INPUT_CHANGED, node);
+ public void inputChanged(Node node) {
}
/**
@@ -545,8 +576,7 @@
*
* @param node a node whose {@link Node#usages()} just became empty
*/
- default void usagesDroppedToZero(Node node) {
- event(NodeEvent.ZERO_USAGES, node);
+ public void usagesDroppedToZero(Node node) {
}
/**
@@ -554,8 +584,15 @@
*
* @param node a node that was just added to the graph
*/
- default void nodeAdded(Node node) {
- event(NodeEvent.NODE_ADDED, node);
+ public void nodeAdded(Node node) {
+ }
+
+ /**
+ * Notifies this listener of a removed node.
+ *
+ * @param node
+ */
+ public void nodeRemoved(Node node) {
}
}
@@ -583,7 +620,7 @@
}
}
- private static class ChainedNodeEventListener implements NodeEventListener {
+ private static class ChainedNodeEventListener extends NodeEventListener {
NodeEventListener head;
NodeEventListener next;
@@ -595,20 +632,32 @@
@Override
public void nodeAdded(Node node) {
- head.nodeAdded(node);
- next.nodeAdded(node);
+ head.event(NodeEvent.NODE_ADDED, node);
+ next.event(NodeEvent.NODE_ADDED, node);
}
@Override
public void inputChanged(Node node) {
- head.inputChanged(node);
- next.inputChanged(node);
+ head.event(NodeEvent.INPUT_CHANGED, node);
+ next.event(NodeEvent.INPUT_CHANGED, node);
}
@Override
public void usagesDroppedToZero(Node node) {
- head.usagesDroppedToZero(node);
- next.usagesDroppedToZero(node);
+ head.event(NodeEvent.ZERO_USAGES, node);
+ next.event(NodeEvent.ZERO_USAGES, node);
+ }
+
+ @Override
+ public void nodeRemoved(Node node) {
+ head.event(NodeEvent.NODE_REMOVED, node);
+ next.event(NodeEvent.NODE_REMOVED, node);
+ }
+
+ @Override
+ public void changed(NodeEvent e, Node node) {
+ head.event(e, node);
+ next.event(e, node);
}
}
@@ -1023,7 +1072,7 @@
updateNodeCaches(node);
if (nodeEventListener != null) {
- nodeEventListener.nodeAdded(node);
+ nodeEventListener.event(NodeEvent.NODE_ADDED, node);
}
afterRegister(node);
}
@@ -1085,6 +1134,10 @@
nodes[node.id] = null;
nodesDeletedSinceLastCompression++;
+ if (nodeEventListener != null) {
+ nodeEventListener.event(NodeEvent.NODE_ADDED, node);
+ }
+
// nodes aren't removed from the type cache here - they will be removed during iteration
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java Thu Nov 16 10:45:42 2017 -0800
@@ -752,7 +752,7 @@
assert !graph.isFrozen();
NodeEventListener listener = graph.nodeEventListener;
if (listener != null) {
- listener.inputChanged(node);
+ listener.event(Graph.NodeEvent.INPUT_CHANGED, node);
}
}
}
@@ -762,7 +762,7 @@
assert !graph.isFrozen();
NodeEventListener listener = graph.nodeEventListener;
if (listener != null && node.isAlive()) {
- listener.usagesDroppedToZero(node);
+ listener.event(Graph.NodeEvent.ZERO_USAGES, node);
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java Thu Nov 16 10:45:42 2017 -0800
@@ -183,8 +183,7 @@
sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess());
}
- Value[] parameters = visitInvokeArguments(gen.getResult().getFrameMapBuilder().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen),
- node.arguments());
+ Value[] parameters = visitInvokeArguments(gen.getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen), node.arguments());
append(new AArch64BreakpointOp(parameters));
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java Thu Nov 16 10:45:42 2017 -0800
@@ -32,7 +32,6 @@
import org.graalvm.compiler.core.amd64.AMD64AddressNode;
import org.graalvm.compiler.core.common.CompressEncoding;
import org.graalvm.compiler.core.common.LIRKind;
-import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.debug.CounterKey;
@@ -44,6 +43,7 @@
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.CompressionNode;
import org.graalvm.compiler.nodes.CompressionNode.CompressionOp;
+import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
@@ -93,76 +93,76 @@
}
@Override
- protected boolean improve(DebugContext debug, AMD64AddressNode addr) {
-
- boolean result = false;
-
- while (super.improve(debug, addr)) {
- result = true;
+ protected boolean improve(StructuredGraph graph, DebugContext debug, AMD64AddressNode addr, boolean isBaseNegated, boolean isIndexNegated) {
+ if (super.improve(graph, debug, addr, isBaseNegated, isIndexNegated)) {
+ return true;
}
if (addr.getScale() == Scale.Times1) {
if (addr.getIndex() instanceof CompressionNode) {
- if (improveUncompression(addr, (CompressionNode) addr.getIndex(), addr.getBase())) {
+ if (improveUncompression(addr, (CompressionNode) addr.getIndex(), addr.getBase(), isBaseNegated, isIndexNegated)) {
counterFoldedUncompressDuringAddressLowering.increment(debug);
return true;
}
}
if (addr.getBase() instanceof CompressionNode) {
- if (improveUncompression(addr, (CompressionNode) addr.getBase(), addr.getIndex())) {
+ if (improveUncompression(addr, (CompressionNode) addr.getBase(), addr.getIndex(), isBaseNegated, isIndexNegated)) {
counterFoldedUncompressDuringAddressLowering.increment(debug);
return true;
}
}
}
- return result;
+ return false;
+ }
+
+ @Override
+ protected boolean mightBeOptimized(ValueNode value) {
+ return super.mightBeOptimized(value) || value instanceof CompressionNode;
}
- private boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other) {
- if (compression.getOp() == CompressionOp.Uncompress) {
- CompressEncoding encoding = compression.getEncoding();
- Scale scale = Scale.fromShift(encoding.getShift());
- if (scale == null) {
+ private boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other, boolean isBaseNegated, boolean isIndexNegated) {
+ if (isBaseNegated || isIndexNegated || compression.getOp() != CompressionOp.Uncompress) {
+ return false;
+ }
+
+ CompressEncoding encoding = compression.getEncoding();
+ Scale scale = Scale.fromShift(encoding.getShift());
+ if (scale == null) {
+ return false;
+ }
+
+ if (heapBaseRegister != null && encoding.getBase() == heapBase) {
+ if ((!generatePIC || compression.stamp() instanceof ObjectStamp) && other == null) {
+ // With PIC it is only legal to do for oops since the base value may be
+ // different at runtime.
+ ValueNode base = compression.graph().unique(new HeapBaseNode(heapBaseRegister));
+ addr.setBase(base);
+ } else {
return false;
}
-
- if (heapBaseRegister != null && encoding.getBase() == heapBase) {
- if ((!generatePIC || compression.stamp() instanceof ObjectStamp) && other == null) {
- // With PIC it is only legal to do for oops since the base value may be
- // different at runtime.
- ValueNode base = compression.graph().unique(new HeapBaseNode(heapBaseRegister));
+ } else if (encoding.getBase() != 0 || (generatePIC && compression.stamp() instanceof KlassPointerStamp)) {
+ if (generatePIC) {
+ if (other == null) {
+ ValueNode base = compression.graph().unique(new GraalHotSpotVMConfigNode(config, config.MARKID_NARROW_KLASS_BASE_ADDRESS, JavaKind.Long));
addr.setBase(base);
} else {
return false;
}
- } else if (encoding.getBase() != 0 || (generatePIC && compression.stamp() instanceof KlassPointerStamp)) {
- if (generatePIC) {
- if (other == null) {
- ValueNode base = compression.graph().unique(new GraalHotSpotVMConfigNode(config, config.MARKID_NARROW_KLASS_BASE_ADDRESS, JavaKind.Long));
- addr.setBase(base);
- } else {
- return false;
- }
+ } else {
+ if (updateDisplacement(addr, encoding.getBase(), isBaseNegated)) {
+ addr.setBase(other);
} else {
- long disp = addr.getDisplacement() + encoding.getBase();
- if (NumUtil.isInt(disp)) {
- addr.setDisplacement((int) disp);
- addr.setBase(other);
- } else {
- return false;
- }
+ return false;
}
- } else {
- addr.setBase(other);
}
+ } else {
+ addr.setBase(other);
+ }
- addr.setScale(scale);
- addr.setIndex(compression.getValue());
- return true;
- } else {
- return false;
- }
+ addr.setScale(scale);
+ addr.setIndex(compression.getValue());
+ return true;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Nov 16 10:45:42 2017 -0800
@@ -39,7 +39,6 @@
import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator;
import org.graalvm.compiler.core.amd64.AMD64LIRGenerator;
-import org.graalvm.compiler.core.amd64.AMD64LIRKindTool;
import org.graalvm.compiler.core.amd64.AMD64MoveFactoryBase.BackupSlotProvider;
import org.graalvm.compiler.core.common.CompressEncoding;
import org.graalvm.compiler.core.common.LIRKind;
@@ -116,7 +115,7 @@
}
private AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, BackupSlotProvider backupSlotProvider) {
- this(new AMD64LIRKindTool(), new AMD64HotSpotArithmeticLIRGenerator(), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes);
+ this(new AMD64HotSpotLIRKindTool(), new AMD64HotSpotArithmeticLIRGenerator(), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes);
}
protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config,
@@ -363,7 +362,7 @@
Stub stub = getStub();
if (destroysRegisters) {
if (stub != null && stub.preservesRegisters()) {
- Register[] savedRegisters = getResult().getFrameMapBuilder().getRegisterConfig().getAllocatableRegisters().toArray();
+ Register[] savedRegisters = getRegisterConfig().getAllocatableRegisters().toArray();
save = emitSaveAllRegisters(savedRegisters, true);
}
}
@@ -567,28 +566,29 @@
@Override
public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
LIRKind inputKind = pointer.getValueKind(LIRKind.class);
- assert inputKind.getPlatformKind() == AMD64Kind.QWORD;
+ LIRKindTool lirKindTool = getLIRKindTool();
+ assert inputKind.getPlatformKind() == lirKindTool.getObjectKind().getPlatformKind();
if (inputKind.isReference(0)) {
// oop
- Variable result = newVariable(LIRKind.reference(AMD64Kind.DWORD));
- append(new AMD64HotSpotMove.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull));
+ Variable result = newVariable(lirKindTool.getNarrowOopKind());
+ append(new AMD64Move.CompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull, getLIRKindTool()));
return result;
} else {
// metaspace pointer
- Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
+ Variable result = newVariable(lirKindTool.getNarrowPointerKind());
AllocatableValue base = Value.ILLEGAL;
OptionValues options = getResult().getLIR().getOptions();
if (encoding.hasBase() || GeneratePIC.getValue(options)) {
if (GeneratePIC.getValue(options)) {
- Variable baseAddress = newVariable(LIRKind.value(AMD64Kind.QWORD));
+ Variable baseAddress = newVariable(lirKindTool.getWordKind());
AMD64HotSpotMove.BaseMove move = new AMD64HotSpotMove.BaseMove(baseAddress, config);
append(move);
base = baseAddress;
} else {
- base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.getBase()));
+ base = emitLoadConstant(lirKindTool.getWordKind(), JavaConstant.forLong(encoding.getBase()));
}
}
- append(new AMD64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull));
+ append(new AMD64Move.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull, getLIRKindTool()));
return result;
}
}
@@ -596,35 +596,37 @@
@Override
public Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull) {
LIRKind inputKind = pointer.getValueKind(LIRKind.class);
- assert inputKind.getPlatformKind() == AMD64Kind.DWORD;
+ LIRKindTool lirKindTool = getLIRKindTool();
+ assert inputKind.getPlatformKind() == lirKindTool.getNarrowOopKind().getPlatformKind();
if (inputKind.isReference(0)) {
// oop
- Variable result = newVariable(LIRKind.reference(AMD64Kind.QWORD));
- append(new AMD64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull));
+ Variable result = newVariable(lirKindTool.getObjectKind());
+ append(new AMD64Move.UncompressPointer(result, asAllocatable(pointer), getProviders().getRegisters().getHeapBaseRegister().asValue(), encoding, nonNull, lirKindTool));
return result;
} else {
// metaspace pointer
- Variable result = newVariable(LIRKind.value(AMD64Kind.QWORD));
+ LIRKind uncompressedKind = lirKindTool.getWordKind();
+ Variable result = newVariable(uncompressedKind);
AllocatableValue base = Value.ILLEGAL;
OptionValues options = getResult().getLIR().getOptions();
if (encoding.hasBase() || GeneratePIC.getValue(options)) {
if (GeneratePIC.getValue(options)) {
- Variable baseAddress = newVariable(LIRKind.value(AMD64Kind.QWORD));
+ Variable baseAddress = newVariable(uncompressedKind);
AMD64HotSpotMove.BaseMove move = new AMD64HotSpotMove.BaseMove(baseAddress, config);
append(move);
base = baseAddress;
} else {
- base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.getBase()));
+ base = emitLoadConstant(uncompressedKind, JavaConstant.forLong(encoding.getBase()));
}
}
- append(new AMD64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull));
+ append(new AMD64Move.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull, lirKindTool));
return result;
}
}
@Override
public void emitNullCheck(Value address, LIRFrameState state) {
- if (address.getValueKind().getPlatformKind() == AMD64Kind.DWORD) {
+ if (address.getValueKind().getPlatformKind() == getLIRKindTool().getNarrowOopKind().getPlatformKind()) {
CompressEncoding encoding = config.getOopEncoding();
Value uncompressed;
if (encoding.getShift() <= 3) {
@@ -635,9 +637,9 @@
uncompressed = emitUncompress(address, encoding, false);
}
append(new AMD64Move.NullCheckOp(asAddressValue(uncompressed), state));
- } else {
- super.emitNullCheck(address, state);
+ return;
}
+ super.emitNullCheck(address, state);
}
@Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRKindTool.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.hotspot.amd64;
+
+import jdk.vm.ci.amd64.AMD64Kind;
+import org.graalvm.compiler.core.amd64.AMD64LIRKindTool;
+import org.graalvm.compiler.core.common.LIRKind;
+
+public class AMD64HotSpotLIRKindTool extends AMD64LIRKindTool {
+ @Override
+ public LIRKind getNarrowOopKind() {
+ return LIRKind.reference(AMD64Kind.DWORD);
+ }
+
+ @Override
+ public LIRKind getNarrowPointerKind() {
+ return LIRKind.value(AMD64Kind.DWORD);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java Thu Nov 16 10:45:42 2017 -0800
@@ -24,16 +24,13 @@
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
-import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
import static jdk.vm.ci.code.ValueUtil.asRegister;
import static jdk.vm.ci.code.ValueUtil.isRegister;
import static jdk.vm.ci.code.ValueUtil.isStackSlot;
-import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.amd64.AMD64Address;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
import org.graalvm.compiler.core.common.CompressEncoding;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.debug.GraalError;
@@ -41,10 +38,8 @@
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.StandardOp.LoadConstantOp;
import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
-import org.graalvm.compiler.lir.amd64.AMD64Move;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
-import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
@@ -180,91 +175,6 @@
}
}
- public static final class CompressPointer extends AMD64LIRInstruction {
- public static final LIRInstructionClass<CompressPointer> TYPE = LIRInstructionClass.create(CompressPointer.class);
-
- private final CompressEncoding encoding;
- private final boolean nonNull;
-
- @Def({REG, HINT}) protected AllocatableValue result;
- @Use({REG}) protected AllocatableValue input;
- @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister;
-
- public CompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) {
- super(TYPE);
- this.result = result;
- this.input = input;
- this.baseRegister = baseRegister;
- this.encoding = encoding;
- this.nonNull = nonNull;
- }
-
- @Override
- public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
- AMD64Move.move(AMD64Kind.QWORD, crb, masm, result, input);
-
- Register resReg = asRegister(result);
- if (encoding.hasBase() || GeneratePIC.getValue(crb.getOptions())) {
- Register baseReg = asRegister(baseRegister);
- if (!nonNull) {
- masm.testq(resReg, resReg);
- masm.cmovq(ConditionFlag.Equal, resReg, baseReg);
- }
- masm.subq(resReg, baseReg);
- }
-
- if (encoding.hasShift()) {
- masm.shrq(resReg, encoding.getShift());
- }
- }
- }
-
- public static final class UncompressPointer extends AMD64LIRInstruction {
- public static final LIRInstructionClass<UncompressPointer> TYPE = LIRInstructionClass.create(UncompressPointer.class);
-
- private final CompressEncoding encoding;
- private final boolean nonNull;
-
- @Def({REG, HINT}) protected AllocatableValue result;
- @Use({REG}) protected AllocatableValue input;
- @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister;
-
- public UncompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) {
- super(TYPE);
- this.result = result;
- this.input = input;
- this.baseRegister = baseRegister;
- this.encoding = encoding;
- this.nonNull = nonNull;
- }
-
- @Override
- public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
- AMD64Move.move(AMD64Kind.DWORD, crb, masm, result, input);
-
- Register resReg = asRegister(result);
- if (encoding.getShift() != 0) {
- masm.shlq(resReg, encoding.getShift());
- }
-
- if (encoding.hasBase() || GeneratePIC.getValue(crb.getOptions())) {
- if (nonNull) {
- masm.addq(resReg, asRegister(baseRegister));
- } else {
- if (!encoding.hasShift()) {
- // if encoding.shift != 0, the flags are already set by the shlq
- masm.testq(resReg, resReg);
- }
-
- Label done = new Label();
- masm.jccb(ConditionFlag.Equal, done);
- masm.addq(resReg, asRegister(baseRegister));
- masm.bind(done);
- }
- }
- }
- }
-
public static void decodeKlassPointer(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) {
CompressEncoding encoding = config.getKlassEncoding();
masm.movl(register, address);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Thu Nov 16 10:45:42 2017 -0800
@@ -189,8 +189,7 @@
sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess());
}
- Value[] parameters = visitInvokeArguments(gen.getResult().getFrameMapBuilder().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen),
- node.arguments());
+ Value[] parameters = visitInvokeArguments(gen.getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen), node.arguments());
append(new AMD64BreakpointOp(parameters));
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java Thu Nov 16 10:45:42 2017 -0800
@@ -113,8 +113,7 @@
} else {
register = asRegister(result);
}
- int bytes = result.getPlatformKind().getSizeInBytes();
- loadFromConstantTable(crb, masm, bytes, asRegister(constantTableBase), constant, register, SPARCDelayedControlTransfer.DUMMY);
+ int bytes = loadFromConstantTable(crb, masm, asRegister(constantTableBase), constant, register, SPARCDelayedControlTransfer.DUMMY);
if (isStack) {
masm.st(register, (SPARCAddress) crb.asAddress(result), bytes);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java Thu Nov 16 10:45:42 2017 -0800
@@ -162,8 +162,7 @@
sig[i] = node.arguments().get(i).stamp().javaType(gen.getMetaAccess());
}
- Value[] parameters = visitInvokeArguments(gen.getResult().getFrameMapBuilder().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen),
- node.arguments());
+ Value[] parameters = visitInvokeArguments(gen.getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCall, null, sig, gen), node.arguments());
append(new SPARCBreakpointOp(parameters));
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java Thu Nov 16 10:45:42 2017 -0800
@@ -77,8 +77,7 @@
boolean canUseShortBranch = masm.hasFeature(CPUFeature.CBCOND) && SPARCControlFlow.isShortBranch(masm, cbCondPosition, hint, target);
Register scratchRegister = asRegister(scratch);
- final int byteCount = constant.isCompressed() ? 4 : 8;
- loadFromConstantTable(crb, masm, byteCount, asRegister(constantTableBase), constant, scratchRegister, SPARCDelayedControlTransfer.DUMMY);
+ loadFromConstantTable(crb, masm, asRegister(constantTableBase), constant, scratchRegister, SPARCDelayedControlTransfer.DUMMY);
if (canUseShortBranch) {
CBCOND.emit(masm, conditionFlag, conditionCode == CC.Xcc, keyRegister, scratchRegister, target);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -160,7 +160,7 @@
}
/**
- * Tests {@link ArrayCopySnippets#checkcastArraycopyWork}.
+ * Tests {@link ArrayCopySnippets#arraycopyCheckcastSnippet}.
*/
@Test
public void testArrayStoreException() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -122,7 +122,7 @@
* Tests compilation requested by Truffle.
*/
@Test
- public void testTruffleCompilation() throws IOException, InterruptedException {
+ public void testTruffleCompilation1() throws IOException, InterruptedException {
testHelper(Collections.emptyList(),
Arrays.asList(
"-Dgraal.CompilationFailureAction=ExitVM",
@@ -130,6 +130,22 @@
"org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test");
}
+ /**
+ * Tests that TruffleCompilationExceptionsAreFatal works as expected.
+ */
+ @Test
+ public void testTruffleCompilation2() throws IOException, InterruptedException {
+ Probe[] probes = {
+ new Probe("Exiting VM due to TruffleCompilationExceptionsAreFatal=true", 1),
+ };
+ testHelper(Arrays.asList(probes),
+ Arrays.asList(
+ "-Dgraal.CompilationFailureAction=Silent",
+ "-Dgraal.TruffleCompilationExceptionsAreFatal=true",
+ "-Dgraal.CrashAt=root test1"),
+ "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test");
+ }
+
private static final boolean VERBOSE = Boolean.getBoolean(CompilationWrapperTest.class.getSimpleName() + ".verbose");
private static void testHelper(List<Probe> initialProbes, List<String> extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException {
@@ -149,14 +165,17 @@
}
List<Probe> probes = new ArrayList<>(initialProbes);
- Probe diagnosticProbe = new Probe("Graal diagnostic output saved in ", 1);
- probes.add(diagnosticProbe);
- probes.add(new Probe("Forced crash after compiling", Integer.MAX_VALUE) {
- @Override
- String test() {
- return actualOccurrences > 0 ? null : "expected at least 1 occurrence";
- }
- });
+ Probe diagnosticProbe = null;
+ if (!extraVmArgs.contains("-Dgraal.TruffleCompilationExceptionsAreFatal=true")) {
+ diagnosticProbe = new Probe("Graal diagnostic output saved in ", 1);
+ probes.add(diagnosticProbe);
+ probes.add(new Probe("Forced crash after compiling", Integer.MAX_VALUE) {
+ @Override
+ String test() {
+ return actualOccurrences > 0 ? null : "expected at least 1 occurrence";
+ }
+ });
+ }
for (String line : proc.output) {
for (Probe probe : probes) {
@@ -171,38 +190,42 @@
Assert.fail(String.format("Did not find expected occurences of '%s' in output of command: %s%n%s", probe.substring, error, proc));
}
}
+ if (diagnosticProbe != null) {
+ String line = diagnosticProbe.lastMatchingLine;
+ int substringStart = line.indexOf(diagnosticProbe.substring);
+ int substringLength = diagnosticProbe.substring.length();
+ String diagnosticOutputZip = line.substring(substringStart + substringLength).trim();
- String diagnosticOutputZip = diagnosticProbe.lastMatchingLine.substring(diagnosticProbe.substring.length()).trim();
-
- List<String> dumpPathEntries = Arrays.asList(dumpPath.list());
+ List<String> dumpPathEntries = Arrays.asList(dumpPath.list());
- File zip = new File(diagnosticOutputZip).getAbsoluteFile();
- Assert.assertTrue(zip.toString(), zip.exists());
- Assert.assertTrue(zip + " not in " + dumpPathEntries, dumpPathEntries.contains(zip.getName()));
- try {
- int bgv = 0;
- int cfg = 0;
- ZipFile dd = new ZipFile(diagnosticOutputZip);
- List<String> entries = new ArrayList<>();
- for (Enumeration<? extends ZipEntry> e = dd.entries(); e.hasMoreElements();) {
- ZipEntry ze = e.nextElement();
- String name = ze.getName();
- entries.add(name);
- if (name.endsWith(".bgv")) {
- bgv++;
- } else if (name.endsWith(".cfg")) {
- cfg++;
+ File zip = new File(diagnosticOutputZip).getAbsoluteFile();
+ Assert.assertTrue(zip.toString(), zip.exists());
+ Assert.assertTrue(zip + " not in " + dumpPathEntries, dumpPathEntries.contains(zip.getName()));
+ try {
+ int bgv = 0;
+ int cfg = 0;
+ ZipFile dd = new ZipFile(diagnosticOutputZip);
+ List<String> entries = new ArrayList<>();
+ for (Enumeration<? extends ZipEntry> e = dd.entries(); e.hasMoreElements();) {
+ ZipEntry ze = e.nextElement();
+ String name = ze.getName();
+ entries.add(name);
+ if (name.endsWith(".bgv")) {
+ bgv++;
+ } else if (name.endsWith(".cfg")) {
+ cfg++;
+ }
}
- }
- if (bgv == 0) {
- Assert.fail(String.format("Expected at least one .bgv file in %s: %s%n%s", diagnosticOutputZip, entries, proc));
+ if (bgv == 0) {
+ Assert.fail(String.format("Expected at least one .bgv file in %s: %s%n%s", diagnosticOutputZip, entries, proc));
+ }
+ if (cfg == 0) {
+ Assert.fail(String.format("Expected at least one .cfg file in %s: %s", diagnosticOutputZip, entries));
+ }
+ } finally {
+ zip.delete();
+ dumpPath.delete();
}
- if (cfg == 0) {
- Assert.fail(String.format("Expected at least one .cfg file in %s: %s", diagnosticOutputZip, entries));
- }
- } finally {
- zip.delete();
- dumpPath.delete();
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,23 +22,44 @@
*/
package org.graalvm.compiler.hotspot.test;
-import org.junit.Test;
-
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.extended.ForeignCallNode;
import org.graalvm.compiler.options.OptionValues;
+import org.junit.Assume;
+import org.junit.Test;
import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.meta.ProfilingInfo;
import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.TriState;
public class ExplicitExceptionTest extends GraalCompilerTest {
private int expectedForeignCallCount;
+ /**
+ * Determines if profiling info for {@code method} indicates an exception was thrown somewhere
+ * in the method. In the case of the {@code -Xcomp} VM option, interpreter execution can be
+ * skipped altogether and other execution engines (e.g., C1) may not record seen exceptions in a
+ * method profile.
+ */
+ private static boolean exceptionWasSeen(ResolvedJavaMethod method) {
+ ProfilingInfo profilingInfo = method.getProfilingInfo();
+ if (profilingInfo != null) {
+ for (int i = 0; i < profilingInfo.getCodeSize(); i++) {
+ if (profilingInfo.getExceptionSeen(i) == TriState.TRUE) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
@Override
protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) {
InstalledCode installedCode = super.getCode(method, graph, forceCompile, installAsDefault, options);
+ Assume.assumeTrue(exceptionWasSeen(method));
assertDeepEquals(expectedForeignCallCount, lastCompiledGraph.getNodes().filter(ForeignCallNode.class).count());
return installedCode;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -24,11 +24,13 @@
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
+import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import org.graalvm.compiler.api.directives.GraalDirectives;
import org.graalvm.compiler.core.phases.HighTier;
@@ -44,6 +46,7 @@
import jdk.vm.ci.meta.ResolvedJavaMethod;
import org.junit.Assume;
+import org.junit.BeforeClass;
/**
* Test on-stack-replacement with locks.
@@ -51,13 +54,28 @@
public class GraalOSRLockTest extends GraalOSRTestBase {
private static boolean TestInSeparateThread = false;
+ private static final String COMPILE_ONLY_FLAG = "-Xcomp";
- public GraalOSRLockTest() {
+ @BeforeClass
+ public static void checkVMArguments() {
try {
Class.forName("java.lang.management.ManagementFactory");
} catch (ClassNotFoundException ex) {
Assume.assumeNoException("cannot check for monitors without java.management JDK9 module", ex);
}
+ /*
+ * Note: The -Xcomp execution mode of the VM will stop most of the OSR test cases from
+ * working as every method is compiled at level3 (followed by level4 on the second
+ * invocation). The tests in this class are written in a way that they expect a method to be
+ * executed at the invocation BCI with the interpreter and then perform an OSR to an
+ * installed nmethod at a given BCI.
+ *
+ */
+ RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
+ List<String> arguments = runtimeMxBean.getInputArguments();
+ for (String arg : arguments) {
+ Assume.assumeFalse(arg.equals(COMPILE_ONLY_FLAG));
+ }
}
// testing only
@@ -438,7 +456,7 @@
}
GraalDirectives.controlFlowAnchor();
if (!GraalDirectives.inCompiledCode()) {
- throw new Error("Must part of compiled code");
+ throw new Error("Must be part of compiled code");
}
return ret;
}
@@ -449,11 +467,11 @@
ReturnValue ret = ReturnValue.FAILURE;
synchronized (lock) {
synchronized (lock1) {
- for (int i = 1; i < limit; i++) {
+ for (int i = 1; i < 10 * limit; i++) {
GraalDirectives.blackhole(i);
- if (i % 1001 == 0) {
+ if (i % 33 == 0) {
ret = ReturnValue.SUCCESS;
- if (GraalDirectives.inCompiledCode() && i + 33 > (limit)) {
+ if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) {
GraalDirectives.blackhole(ret);
System.gc();
}
@@ -462,7 +480,7 @@
}
GraalDirectives.controlFlowAnchor();
if (!GraalDirectives.inCompiledCode()) {
- throw new Error("Must part of compiled code");
+ throw new Error("Must be part of compiled code already hereeeeee");
} else {
// lock 1 must be free
if (isMonitorLockHeld(lock1)) {
@@ -519,7 +537,7 @@
}
GraalDirectives.controlFlowAnchor();
if (!GraalDirectives.inCompiledCode()) {
- throw new Error("Must part of compiled code");
+ throw new Error("Must be part of compiled code");
}
return ret;
}
@@ -543,7 +561,7 @@
}
GraalDirectives.controlFlowAnchor();
if (!GraalDirectives.inCompiledCode()) {
- throw new Error("Must part of compiled code");
+ throw new Error("Must be part of compiled code");
}
return ret;
}
@@ -568,7 +586,7 @@
}
GraalDirectives.controlFlowAnchor();
if (!GraalDirectives.inCompiledCode()) {
- throw new Error("Must part of compiled code");
+ throw new Error("Must be part of compiled code");
}
return ret;
}
@@ -646,7 +664,7 @@
synchronized (monitor) {
GraalDirectives.controlFlowAnchor();
if (!GraalDirectives.inCompiledCode()) {
- throw new Error("Must part of compiled code");
+ throw new Error("Must be part of compiled code");
}
}
return ret;
@@ -670,7 +688,7 @@
}
GraalDirectives.controlFlowAnchor();
if (!GraalDirectives.inCompiledCode()) {
- throw new Error("Must part of compiled code");
+ throw new Error("Must be part of compiled code");
}
return ret;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java Thu Nov 16 10:45:42 2017 -0800
@@ -35,7 +35,9 @@
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.hotspot.CompilationTask;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotGraalCompiler;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
import org.graalvm.compiler.java.BciBlockMapping;
import org.graalvm.compiler.java.BciBlockMapping.BciBlock;
import org.graalvm.compiler.nodes.StructuredGraph;
@@ -76,6 +78,13 @@
HotSpotCompilationRequest request = new HotSpotCompilationRequest((HotSpotResolvedJavaMethod) method, bci, jvmciEnv);
HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler();
CompilationTask task = new CompilationTask(runtime, compiler, request, true, true, debug.getOptions());
+ if (method instanceof HotSpotResolvedJavaMethod) {
+ HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime();
+ GraalHotSpotVMConfig config = graalRuntime.getVMConfig();
+ if (((HotSpotResolvedJavaMethod) method).hasCodeAtLevel(bci, config.compilationLevelFullOptimization)) {
+ return;
+ }
+ }
HotSpotCompilationRequestResult result = task.runCompilation(debug);
if (result.getFailure() != null) {
throw new GraalError(result.getFailureMessage());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -37,7 +37,6 @@
import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier;
import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase;
-import org.graalvm.compiler.hotspot.replacements.arraycopy.UnsafeArrayCopyNode;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractMergeNode;
import org.graalvm.compiler.nodes.FieldLocationIdentity;
@@ -629,12 +628,6 @@
System.arraycopy(a, 0, b, 0, a.length);
}
- @Test
- public void test61() {
- GraphPredicate checkForUnsafeArrayCopy = graph -> graph.getNodes().filter(UnsafeArrayCopyNode.class).count() > 0 ? 1 : 0;
- testPredicate("test13Snippet", checkForUnsafeArrayCopy, new int[]{});
- }
-
private interface GraphPredicate {
int apply(StructuredGraph graph);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2017, 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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -280,14 +280,19 @@
}
if (offset == -1) {
try {
- offset = getFieldOffset(name, Integer.class, "OopHandle");
+ offset = getFieldOffset(name, Integer.class, "jobject");
isHandle = true;
} catch (JVMCIError e) {
-
+ try {
+ // JDK-8186777
+ offset = getFieldOffset(name, Integer.class, "OopHandle");
+ isHandle = true;
+ } catch (JVMCIError e2) {
+ }
}
}
if (offset == -1) {
- throw new JVMCIError("cannot get offset of field " + name + " with type oop or OopHandle");
+ throw new JVMCIError("cannot get offset of field " + name + " with type oop, jobject or OopHandle");
}
classMirrorOffset = offset;
classMirrorIsHandle = isHandle;
@@ -648,6 +653,8 @@
public final long heapEndAddress = getFieldValue("CompilerToVM::Data::_heap_end_addr", Long.class, "HeapWord**");
public final long heapTopAddress = getFieldValue("CompilerToVM::Data::_heap_top_addr", Long.class, isJDK8 ? "HeapWord**" : "HeapWord* volatile*");
+ public final boolean cmsIncrementalMode = getFlag("CMSIncrementalMode", Boolean.class, false);
+
public final long inlineCacheMissStub = getFieldValue("CompilerToVM::Data::SharedRuntime_ic_miss_stub", Long.class, "address");
public final long handleWrongMethodStub = getFieldValue("CompilerToVM::Data::SharedRuntime_handle_wrong_method_stub", Long.class, "address");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java Thu Nov 16 10:45:42 2017 -0800
@@ -266,6 +266,8 @@
unsafeArraycopyStub(HotSpotBackend.UNSAFE_ARRAYCOPY, srcAddr, dstAddr, size);
}
+ public static final ForeignCallDescriptor GENERIC_ARRAYCOPY = new ForeignCallDescriptor("generic_arraycopy", int.class, Word.class, int.class, Word.class, int.class, int.class);
+
@NodeIntrinsic(ForeignCallNode.class)
private static native void unsafeArraycopyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word size);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java Thu Nov 16 10:45:42 2017 -0800
@@ -284,7 +284,7 @@
public Object mbean() {
if (graalRuntime instanceof HotSpotGraalRuntime) {
- return ((HotSpotGraalRuntime)graalRuntime).mbean();
+ return ((HotSpotGraalRuntime) graalRuntime).getMBean();
}
return null;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java Thu Nov 16 10:45:42 2017 -0800
@@ -26,6 +26,8 @@
import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX;
import java.io.PrintStream;
+import java.util.Map;
+import java.util.Collections;
import org.graalvm.compiler.debug.MethodFilter;
import org.graalvm.compiler.options.Option;
@@ -190,4 +192,11 @@
}
return level;
}
+
+ public Map<String, Object> mbeans() {
+ HotSpotGraalCompiler compiler = createCompiler(HotSpotJVMCIRuntime.runtime());
+ String name = "org.graalvm.compiler.hotspot:type=Options";
+ Object bean = ((HotSpotGraalRuntime) compiler.getGraalRuntime()).getMBean();
+ return Collections.singletonMap(name, bean);
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java Thu Nov 16 10:45:42 2017 -0800
@@ -283,10 +283,8 @@
@Override
public javax.management.MBeanInfo getMBeanInfo() {
List<javax.management.MBeanAttributeInfo> attrs = new ArrayList<>();
- if (registered != null) {
- for (OptionDescriptor descr : allOptionDescriptors()) {
- attrs.add(new javax.management.MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false));
- }
+ for (OptionDescriptor descr : allOptionDescriptors()) {
+ attrs.add(new javax.management.MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false));
}
javax.management.MBeanOperationInfo[] ops = {
new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Thu Nov 16 10:45:42 2017 -0800
@@ -317,7 +317,7 @@
return compilationProblemsPerAction;
}
- final Object mbean() {
+ Object getMBean() {
return mBean;
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Thu Nov 16 10:45:42 2017 -0800
@@ -28,8 +28,8 @@
import static org.graalvm.compiler.core.common.GraalOptions.OmitHotExceptionStacktrace;
import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_KLASS_LOCATION;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_HANDLE_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_HANDLE_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.COMPRESSED_HUB_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.DISPLACED_MARK_WORD_LOCATION;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_LOCATION;
@@ -41,6 +41,7 @@
import java.lang.ref.Reference;
import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.core.common.CompressEncoding;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
@@ -90,10 +91,8 @@
import org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets;
import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets;
import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopyNode;
-import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopySlowPathNode;
+import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopyWithSlowPathNode;
import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopySnippets;
-import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopyUnrollNode;
-import org.graalvm.compiler.hotspot.replacements.arraycopy.UnsafeArrayCopySnippets;
import org.graalvm.compiler.hotspot.replacements.profiling.ProfileSnippets;
import org.graalvm.compiler.hotspot.word.KlassPointer;
import org.graalvm.compiler.nodes.AbstractBeginNode;
@@ -193,7 +192,7 @@
public DefaultHotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers,
HotSpotConstantReflectionProvider constantReflection, TargetDescription target) {
- super(metaAccess, foreignCalls, target);
+ super(metaAccess, foreignCalls, target, runtime.getVMConfig().useCompressedOops);
this.runtime = runtime;
this.registers = registers;
this.constantReflection = constantReflection;
@@ -216,7 +215,6 @@
hashCodeSnippets = new HashCodeSnippets.Templates(options, factories, providers, target);
resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, factories, providers, target);
profileSnippets = new ProfileSnippets.Templates(options, factories, providers, target);
- providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(options, factories, providers, target));
}
public MonitorSnippets.Templates getMonitorSnippets() {
@@ -315,10 +313,8 @@
}
} else if (n instanceof ArrayCopyNode) {
arraycopySnippets.lower((ArrayCopyNode) n, tool);
- } else if (n instanceof ArrayCopySlowPathNode) {
- arraycopySnippets.lower((ArrayCopySlowPathNode) n, tool);
- } else if (n instanceof ArrayCopyUnrollNode) {
- arraycopySnippets.lower((ArrayCopyUnrollNode) n, tool);
+ } else if (n instanceof ArrayCopyWithSlowPathNode) {
+ arraycopySnippets.lower((ArrayCopyWithSlowPathNode) n, tool);
} else if (n instanceof G1PreWriteBarrier) {
writeBarrierSnippets.lower((G1PreWriteBarrier) n, registers, tool);
} else if (n instanceof G1PostWriteBarrier) {
@@ -495,20 +491,18 @@
}
}
- @Override
- protected Stamp loadStamp(Stamp stamp, JavaKind kind, boolean compressible) {
- if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) {
- return HotSpotNarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getVMConfig().getOopEncoding());
- }
- return super.loadStamp(stamp, kind, compressible);
+ private CompressEncoding getOopEncoding() {
+ return runtime.getVMConfig().getOopEncoding();
}
@Override
- protected ValueNode implicitLoadConvert(JavaKind kind, ValueNode value, boolean compressible) {
- if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) {
- return new HotSpotCompressionNode(CompressionOp.Uncompress, value, runtime.getVMConfig().getOopEncoding());
- }
- return super.implicitLoadConvert(kind, value, compressible);
+ protected Stamp loadCompressedStamp(ObjectStamp stamp) {
+ return HotSpotNarrowOopStamp.compressed(stamp, getOopEncoding());
+ }
+
+ @Override
+ protected ValueNode newCompressionNode(CompressionOp op, ValueNode value) {
+ return new HotSpotCompressionNode(op, value, getOopEncoding());
}
@Override
@@ -519,14 +513,6 @@
}
@Override
- protected ValueNode implicitStoreConvert(JavaKind kind, ValueNode value, boolean compressible) {
- if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) {
- return new HotSpotCompressionNode(CompressionOp.Compress, value, runtime.getVMConfig().getOopEncoding());
- }
- return super.implicitStoreConvert(kind, value, compressible);
- }
-
- @Override
protected ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor) {
/*
* Anchor the read of the element klass to the cfg, because it is only valid when arrayClass
@@ -800,4 +786,9 @@
public int arrayLengthOffset() {
return runtime.getVMConfig().arrayOopDescLengthOffset();
}
+
+ @Override
+ protected final JavaKind getStorageKind(ResolvedJavaField field) {
+ return field.getJavaKind();
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java Thu Nov 16 10:45:42 2017 -0800
@@ -39,6 +39,7 @@
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.bytecode.BytecodeProvider;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
+import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode;
@@ -68,6 +69,7 @@
import org.graalvm.compiler.nodes.PiNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.AddNode;
+import org.graalvm.compiler.nodes.calc.IntegerConvertNode;
import org.graalvm.compiler.nodes.calc.LeftShiftNode;
import org.graalvm.compiler.nodes.graphbuilderconf.ForeignCallPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
@@ -316,8 +318,8 @@
private static boolean readMetaspaceConstantPoolElement(GraphBuilderContext b, ValueNode constantPoolOop, ValueNode index, JavaKind elementKind, WordTypes wordTypes, GraalHotSpotVMConfig config) {
ValueNode constants = getMetaspaceConstantPool(b, constantPoolOop, wordTypes, config);
int shift = CodeUtil.log2(wordTypes.getWordKind().getByteCount());
- ValueNode scaledIndex = b.add(new LeftShiftNode(index, b.add(ConstantNode.forInt(shift))));
- ValueNode offset = b.add(new AddNode(scaledIndex, b.add(ConstantNode.forInt(config.constantPoolSize))));
+ ValueNode scaledIndex = b.add(new LeftShiftNode(IntegerConvertNode.convert(index, StampFactory.forKind(JavaKind.Long)), b.add(ConstantNode.forInt(shift))));
+ ValueNode offset = b.add(new AddNode(scaledIndex, b.add(ConstantNode.forLong(config.constantPoolSize))));
AddressNode elementAddress = b.add(new OffsetAddressNode(constants, offset));
boolean notCompressible = false;
ValueNode elementValue = WordOperationPlugin.readOp(b, elementKind, elementAddress, NamedLocationIdentity.getArrayLocation(elementKind), BarrierType.NONE, notCompressible);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java Thu Nov 16 10:45:42 2017 -0800
@@ -34,6 +34,7 @@
import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT;
import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT_BLOCK;
import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER;
+import static org.graalvm.compiler.hotspot.HotSpotBackend.GENERIC_ARRAYCOPY;
import static org.graalvm.compiler.hotspot.HotSpotBackend.IC_MISS_HANDLER;
import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL;
import static org.graalvm.compiler.hotspot.HotSpotBackend.INVOCATION_EVENT;
@@ -85,7 +86,6 @@
import static org.graalvm.compiler.hotspot.stubs.NewInstanceStub.NEW_INSTANCE_C;
import static org.graalvm.compiler.hotspot.stubs.StubUtil.VM_MESSAGE_C;
import static org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub.EXCEPTION_HANDLER_FOR_RETURN_ADDRESS;
-import static org.graalvm.compiler.nodes.NamedLocationIdentity.any;
import static org.graalvm.compiler.nodes.java.ForeignCallDescriptors.REGISTER_FINALIZER;
import static org.graalvm.compiler.replacements.Log.LOG_OBJECT;
import static org.graalvm.compiler.replacements.Log.LOG_PRIMITIVE;
@@ -97,6 +97,7 @@
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
+import static org.graalvm.word.LocationIdentity.any;
import java.util.EnumMap;
@@ -213,7 +214,7 @@
// c_rarg4 - oop ckval (super_klass)
// return: 0 = success, n = number of copied elements xor'd with -1.
ForeignCallDescriptor desc = new ForeignCallDescriptor(name, int.class, Word.class, Word.class, Word.class, Word.class, Word.class);
- LocationIdentity killed = NamedLocationIdentity.getArrayLocation(JavaKind.Object);
+ LocationIdentity killed = NamedLocationIdentity.any();
registerForeignCall(desc, routine, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, killed);
checkcastArraycopyDescriptors[uninit ? 1 : 0] = desc;
}
@@ -333,6 +334,7 @@
registerCheckcastArraycopyDescriptor(true, c.checkcastArraycopyUninit);
registerCheckcastArraycopyDescriptor(false, c.checkcastArraycopy);
+ registerForeignCall(GENERIC_ARRAYCOPY, c.genericArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.any());
registerForeignCall(UNSAFE_ARRAYCOPY, c.unsafeArraycopy, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, NamedLocationIdentity.any());
if (c.useMultiplyToLenIntrinsic()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -28,6 +28,7 @@
import org.graalvm.word.LocationIdentity;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.InputType;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode;
import org.graalvm.compiler.nodes.ValueNode;
@@ -35,7 +36,7 @@
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.compiler.nodes.spi.LoweringTool;
-@NodeInfo(cycles = CYCLES_4, size = SIZE_16)
+@NodeInfo(cycles = CYCLES_4, size = SIZE_16, allowedUsageTypes = {InputType.Memory})
public class ResolveDynamicConstantNode extends DeoptimizingFixedWithNextNode implements Lowerable, MemoryCheckpoint.Single {
public static final NodeClass<ResolveDynamicConstantNode> TYPE = NodeClass.create(ResolveDynamicConstantNode.class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileBranchNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileBranchNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -71,6 +71,15 @@
return branchCondition != null;
}
+ @Override
+ protected boolean canBeMergedWith(ProfileNode p) {
+ if (p instanceof ProfileBranchNode) {
+ ProfileBranchNode that = (ProfileBranchNode) p;
+ return this.method.equals(that.method) && this.bci == that.bci;
+ }
+ return false;
+ }
+
/**
* Gathers all the {@link ProfileBranchNode}s that are inputs to the
* {@linkplain StructuredGraph#getNodes() live nodes} in a given graph.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileInvokeNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileInvokeNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -37,6 +37,15 @@
super(TYPE, method, freqLog, probabilityLog);
}
+ @Override
+ protected boolean canBeMergedWith(ProfileNode p) {
+ if (p instanceof ProfileInvokeNode) {
+ ProfileInvokeNode that = (ProfileInvokeNode) p;
+ return this.method.equals(that.method);
+ }
+ return false;
+ }
+
/**
* Gathers all the {@link ProfileInvokeNode}s that are inputs to the
* {@linkplain StructuredGraph#getNodes() live nodes} in a given graph.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,11 +24,17 @@
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;
+import static org.graalvm.compiler.nodes.util.GraphUtil.removeFixedWithUnusedInputs;
import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.iterators.NodeIterable;
+import org.graalvm.compiler.graph.spi.Simplifiable;
+import org.graalvm.compiler.graph.spi.SimplifierTool;
import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.AbstractMergeNode;
+import org.graalvm.compiler.nodes.ControlSplitNode;
import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
@@ -41,7 +47,7 @@
import jdk.vm.ci.meta.ResolvedJavaMethod;
@NodeInfo(cycles = CYCLES_IGNORED, cyclesRationale = "profiling should be ignored", size = SIZE_IGNORED, sizeRationale = "profiling should be ignored")
-public class ProfileNode extends DeoptimizingFixedWithNextNode implements Lowerable {
+public abstract class ProfileNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable {
public static class Options {
@Option(help = "Control probabilistic profiling on AMD64", type = OptionType.Expert)//
public static final OptionKey<Boolean> ProbabilisticProfiling = new OptionKey<>(true);
@@ -54,19 +60,21 @@
// Only used if ProbabilisticProfiling == true and may be ignored by lowerer.
@OptionalInput protected ValueNode random;
- // logarithm base 2 of the profile probability
+ // Logarithm base 2 of the profile probability.
protected int probabilityLog;
+ // Step value to add to the profile counter.
+ protected int step;
+
protected ProfileNode(NodeClass<? extends DeoptimizingFixedWithNextNode> c, ResolvedJavaMethod method, int probabilityLog) {
super(c, StampFactory.forVoid());
this.method = method;
this.probabilityLog = probabilityLog;
+ this.step = 1;
}
public ProfileNode(ResolvedJavaMethod method, int probabilityLog) {
- super(TYPE, StampFactory.forVoid());
- this.method = method;
- this.probabilityLog = probabilityLog;
+ this(TYPE, method, probabilityLog);
}
@Override
@@ -92,6 +100,14 @@
this.random = r;
}
+ public int getStep() {
+ return step;
+ }
+
+ public void setStep(int s) {
+ step = s;
+ }
+
/**
* Get the logarithm base 2 of the profile probability.
*/
@@ -106,4 +122,25 @@
public static NodeIterable<ProfileNode> getProfileNodes(StructuredGraph graph) {
return graph.getNodes().filter(ProfileNode.class);
}
+
+ protected abstract boolean canBeMergedWith(ProfileNode p);
+
+ @Override
+ public void simplify(SimplifierTool tool) {
+ for (Node p = predecessor(); p != null; p = p.predecessor()) {
+ // Terminate search when we hit a control split or merge.
+ if (p instanceof ControlSplitNode || p instanceof AbstractMergeNode) {
+ break;
+ }
+ if (p instanceof ProfileNode) {
+ ProfileNode that = (ProfileNode) p;
+ if (this.canBeMergedWith(that)) {
+ that.setStep(this.getStep() + that.getStep());
+ removeFixedWithUnusedInputs(this);
+ tool.addToWorkList(that);
+ break;
+ }
+ }
+ }
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
import jdk.vm.ci.meta.ResolvedJavaMethod;
@NodeInfo
-public class ProfileWithNotificationNode extends ProfileNode {
+public abstract class ProfileWithNotificationNode extends ProfileNode {
public static final NodeClass<ProfileWithNotificationNode> TYPE = NodeClass.create(ProfileWithNotificationNode.class);
protected int freqLog;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,10 +22,16 @@
*/
package org.graalvm.compiler.hotspot.phases;
+import static jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;
+import jdk.vm.ci.meta.DeoptimizationAction;
+import jdk.vm.ci.meta.DeoptimizationReason;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.core.common.cfg.Loop;
+import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugContext;
@@ -37,13 +43,15 @@
import org.graalvm.compiler.nodeinfo.InputType;
import org.graalvm.compiler.nodeinfo.Verbosity;
import org.graalvm.compiler.nodes.AbstractBeginNode;
-import org.graalvm.compiler.nodes.AbstractLocalNode;
import org.graalvm.compiler.nodes.EntryMarkerNode;
import org.graalvm.compiler.nodes.EntryProxyNode;
+import org.graalvm.compiler.nodes.FixedGuardNode;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.FrameState;
+import org.graalvm.compiler.nodes.LogicNode;
import org.graalvm.compiler.nodes.LoopBeginNode;
import org.graalvm.compiler.nodes.ParameterNode;
+import org.graalvm.compiler.nodes.PiNode;
import org.graalvm.compiler.nodes.StartNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
@@ -53,6 +61,7 @@
import org.graalvm.compiler.nodes.extended.OSRMonitorEnterNode;
import org.graalvm.compiler.nodes.extended.OSRStartNode;
import org.graalvm.compiler.nodes.java.AccessMonitorNode;
+import org.graalvm.compiler.nodes.java.InstanceOfNode;
import org.graalvm.compiler.nodes.java.MonitorEnterNode;
import org.graalvm.compiler.nodes.java.MonitorExitNode;
import org.graalvm.compiler.nodes.java.MonitorIdNode;
@@ -172,15 +181,32 @@
if (value instanceof EntryProxyNode) {
EntryProxyNode proxy = (EntryProxyNode) value;
/*
- * we need to drop the stamp since the types we see during OSR may be too precise
- * (if a branch was not parsed for example).
+ * We need to drop the stamp since the types we see during OSR may be too precise
+ * (if a branch was not parsed for example). In cases when this is possible, we
+ * insert a guard and narrow the OSRLocal stamp at its usages.
*/
- Stamp s = proxy.stamp().unrestricted();
- AbstractLocalNode osrLocal = null;
+ Stamp narrowedStamp = proxy.value().stamp();
+ Stamp unrestrictedStamp = proxy.stamp().unrestricted();
+ ValueNode osrLocal;
if (i >= localsSize) {
- osrLocal = graph.addOrUnique(new OSRLockNode(i - localsSize, s));
+ osrLocal = graph.addOrUnique(new OSRLockNode(i - localsSize, unrestrictedStamp));
} else {
- osrLocal = graph.addOrUnique(new OSRLocalNode(i, s));
+ osrLocal = graph.addOrUnique(new OSRLocalNode(i, unrestrictedStamp));
+ }
+ // Speculate on the OSRLocal stamps that could be more precise.
+ OSRLocalSpeculationReason reason = new OSRLocalSpeculationReason(osrState.bci, narrowedStamp, i);
+ if (graph.getSpeculationLog().maySpeculate(reason) && osrLocal instanceof OSRLocalNode && value.getStackKind().equals(JavaKind.Object) && !narrowedStamp.isUnrestricted()) {
+ // Add guard.
+ LogicNode check = graph.addOrUniqueWithInputs(InstanceOfNode.createHelper((ObjectStamp) narrowedStamp, osrLocal, null, null));
+ JavaConstant constant = graph.getSpeculationLog().speculate(reason);
+ FixedGuardNode guard = graph.add(new FixedGuardNode(check, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, constant, false));
+ graph.addAfterFixed(osrStart, guard);
+
+ // Replace with a more specific type at usages.
+ // We know that we are at the root,
+ // so we need to replace the proxy in the state.
+ proxy.replaceAtMatchingUsages(osrLocal, n -> n == osrState);
+ osrLocal = graph.addOrUnique(new PiNode(osrLocal, narrowedStamp, guard));
}
proxy.replaceAndDelete(osrLocal);
} else {
@@ -268,4 +294,30 @@
public float codeSizeIncrease() {
return 5.0f;
}
+
+ private static class OSRLocalSpeculationReason implements SpeculationReason {
+ private int bci;
+ private Stamp speculatedStamp;
+ private int localIndex;
+
+ OSRLocalSpeculationReason(int bci, Stamp speculatedStamp, int localIndex) {
+ this.bci = bci;
+ this.speculatedStamp = speculatedStamp;
+ this.localIndex = localIndex;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof OSRLocalSpeculationReason) {
+ OSRLocalSpeculationReason that = (OSRLocalSpeculationReason) obj;
+ return this.bci == that.bci && this.speculatedStamp.equals(that.speculatedStamp) && this.localIndex == that.localIndex;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return (bci << 16) ^ speculatedStamp.hashCode() ^ localIndex;
+ }
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Thu Nov 16 10:45:42 2017 -0800
@@ -670,6 +670,11 @@
}
@Fold
+ public static boolean useCMSIncrementalMode(@InjectedParameter GraalHotSpotVMConfig config) {
+ return config.cmsIncrementalMode;
+ }
+
+ @Fold
public static boolean useCompressedOops(@InjectedParameter GraalHotSpotVMConfig config) {
return config.useCompressedOops;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -71,7 +71,7 @@
return null;
} else {
MetaAccessProvider metaAccess = tool.getMetaAccess();
- if (metaAccess != null && hub.isConstant() && !GraalOptions.ImmutableCode.getValue(graph().getOptions())) {
+ if (metaAccess != null && hub.isConstant() && !GraalOptions.ImmutableCode.getValue(tool.getOptions())) {
ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(hub.asConstant());
if (exactType != null) {
return ConstantNode.forConstant(tool.getConstantReflection().asJavaClass(exactType), metaAccess);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -67,7 +67,7 @@
if (object.isConstant()) {
assert object.stamp() instanceof AbstractObjectStamp;
JavaConstant c = (JavaConstant) object.asConstant();
- if (ImmutableCode.getValue(getOptions())) {
+ if (ImmutableCode.getValue(tool.getOptions())) {
return this;
}
JavaConstant identityHashCode = null;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySlowPathNode.java Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2015, 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 org.graalvm.compiler.hotspot.replacements.arraycopy;
-
-import jdk.vm.ci.code.BytecodeFrame;
-import jdk.vm.ci.meta.JavaKind;
-
-import static org.graalvm.word.LocationIdentity.any;
-
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.hotspot.word.KlassPointer;
-import org.graalvm.compiler.nodeinfo.InputType;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.NamedLocationIdentity;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.type.StampTool;
-import org.graalvm.compiler.replacements.SnippetTemplate;
-import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode;
-import org.graalvm.word.LocationIdentity;
-
-@NodeInfo(allowedUsageTypes = InputType.Memory)
-public final class ArrayCopySlowPathNode extends BasicArrayCopyNode {
-
- public static final NodeClass<ArrayCopySlowPathNode> TYPE = NodeClass.create(ArrayCopySlowPathNode.class);
-
- private final SnippetTemplate.SnippetInfo snippet;
-
- /**
- * Extra context for the slow path snippet.
- */
- private final Object argument;
-
- /**
- * AOT compilation requires klass constants to be exposed after the first lowering to be handled
- * automatically. Lowering for {@link ArrayCopySlowPathNode}, with snippet ==
- * {@link ArrayCopySnippets#arraycopyPredictedObjectWork}, requires a klass of Object[]. For
- * other snippets {@link #predictedKlass} is a null constant.
- */
- @Input protected ValueNode predictedKlass;
-
- public ArrayCopySlowPathNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode predictedKlass, JavaKind elementKind,
- SnippetTemplate.SnippetInfo snippet, Object argument) {
- super(TYPE, src, srcPos, dest, destPos, length, elementKind, BytecodeFrame.INVALID_FRAMESTATE_BCI);
- assert StampTool.isPointerNonNull(src) && StampTool.isPointerNonNull(dest) : "must have been null checked";
- this.snippet = snippet;
- this.argument = argument;
- this.predictedKlass = predictedKlass;
- }
-
- @NodeIntrinsic
- public static native void arraycopy(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, KlassPointer predictedKlass,
- @ConstantNodeParameter JavaKind elementKind, @ConstantNodeParameter SnippetTemplate.SnippetInfo snippet, @ConstantNodeParameter Object argument);
-
- public SnippetTemplate.SnippetInfo getSnippet() {
- return snippet;
- }
-
- public Object getArgument() {
- return argument;
- }
-
- @Override
- public LocationIdentity getLocationIdentity() {
- if (elementKind != null) {
- return NamedLocationIdentity.getArrayLocation(elementKind);
- }
- return any();
- }
-
- public void setBci(int bci) {
- this.bci = bci;
- }
-
- public ValueNode getPredictedKlass() {
- return predictedKlass;
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java Thu Nov 16 10:45:42 2017 -0800
@@ -28,11 +28,12 @@
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayBaseOffset;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayClassElementOffset;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayIndexScale;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperElementTypePrimitiveInPlace;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHub;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.superCheckOffsetOffset;
-import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY;
+import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY;
+import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_PROBABILITY;
+import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY;
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY;
import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
@@ -47,10 +48,8 @@
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
-import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
import org.graalvm.compiler.hotspot.word.KlassPointer;
import org.graalvm.compiler.nodes.CallTargetNode;
-import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.DeoptimizeNode;
import org.graalvm.compiler.nodes.Invoke;
import org.graalvm.compiler.nodes.InvokeNode;
@@ -65,8 +64,10 @@
import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.replacements.ReplacementsUtil;
import org.graalvm.compiler.replacements.SnippetCounter;
import org.graalvm.compiler.replacements.SnippetCounter.Group;
+import org.graalvm.compiler.replacements.SnippetIntegerHistogram;
import org.graalvm.compiler.replacements.SnippetTemplate;
import org.graalvm.compiler.replacements.SnippetTemplate.Arguments;
import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
@@ -79,16 +80,208 @@
import org.graalvm.word.WordFactory;
import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
import jdk.vm.ci.meta.DeoptimizationAction;
import jdk.vm.ci.meta.DeoptimizationReason;
-import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
public class ArrayCopySnippets implements Snippets {
+ private enum ArrayCopyTypeCheck {
+ UNDEFINED_ARRAY_TYPE_CHECK,
+ // we know that both objects are arrays and have the same type
+ NO_ARRAY_TYPE_CHECK,
+ // can be used when we know that one of the objects is a primitive array
+ HUB_BASED_ARRAY_TYPE_CHECK,
+ // must be used when we don't have sufficient information to use one of the others
+ LAYOUT_HELPER_BASED_ARRAY_TYPE_CHECK
+ }
+
+ @Snippet
+ public static void arraycopyZeroLengthSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck,
+ @ConstantParameter Counters counters) {
+ Object nonNullSrc = GraalDirectives.guardingNonNull(src);
+ Object nonNullDest = GraalDirectives.guardingNonNull(dest);
+ checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck);
+ checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
+ counters.zeroLengthStaticCounter.inc();
+ }
+
+ @Snippet
+ public static void arraycopyExactSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck,
+ @ConstantParameter JavaKind elementKind, @ConstantParameter SnippetCounter elementKindCounter, @ConstantParameter SnippetCounter elementKindCopiedCounter,
+ @ConstantParameter Counters counters) {
+ Object nonNullSrc = GraalDirectives.guardingNonNull(src);
+ Object nonNullDest = GraalDirectives.guardingNonNull(dest);
+ checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck);
+ checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
+ incrementLengthCounter(length, counters);
+
+ elementKindCounter.inc();
+ elementKindCopiedCounter.add(length);
+ ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind);
+ }
+
+ @Snippet
+ public static void arraycopyUnrolledSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck,
+ @ConstantParameter JavaKind elementKind, @ConstantParameter int unrolledLength, @ConstantParameter Counters counters) {
+ Object nonNullSrc = GraalDirectives.guardingNonNull(src);
+ Object nonNullDest = GraalDirectives.guardingNonNull(dest);
+ checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck);
+ checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
+ incrementLengthCounter(length, counters);
+
+ unrolledArraycopyWork(nonNullSrc, srcPos, nonNullDest, destPos, unrolledLength, elementKind);
+ }
+
+ @Snippet
+ public static void arraycopyCheckcastSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck,
+ @ConstantParameter Counters counters, @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind) {
+ Object nonNullSrc = GraalDirectives.guardingNonNull(src);
+ Object nonNullDest = GraalDirectives.guardingNonNull(dest);
+ checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck);
+ checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
+ incrementLengthCounter(length, counters);
+
+ ArrayCopyWithSlowPathNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind);
+ }
+
+ @Snippet
+ public static void arraycopyGenericSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter ArrayCopyTypeCheck arrayTypeCheck, @ConstantParameter Counters counters,
+ @ConstantParameter SnippetInfo workSnippet, @ConstantParameter JavaKind elementKind) {
+ Object nonNullSrc = GraalDirectives.guardingNonNull(src);
+ Object nonNullDest = GraalDirectives.guardingNonNull(dest);
+ checkArrayTypes(nonNullSrc, nonNullDest, arrayTypeCheck);
+ checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
+ incrementLengthCounter(length, counters);
+
+ ArrayCopyWithSlowPathNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, workSnippet, elementKind);
+ }
+
+ @Snippet
+ public static void arraycopyNativeSnippet(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) {
+ // all checks are done in the native method, so no need to emit additional checks here
+ incrementLengthCounter(length, counters);
+ counters.systemArraycopyCounter.inc();
+ counters.systemArraycopyCopiedCounter.add(length);
+
+ System.arraycopy(src, srcPos, dest, destPos, length);
+ }
+
+ @Fold
+ static LocationIdentity getArrayLocation(JavaKind kind) {
+ return NamedLocationIdentity.getArrayLocation(kind);
+ }
+
+ private static void unrolledArraycopyWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, JavaKind elementKind) {
+ int scale = arrayIndexScale(elementKind);
+ int arrayBaseOffset = arrayBaseOffset(elementKind);
+ LocationIdentity arrayLocation = getArrayLocation(elementKind);
+
+ long sourceOffset = arrayBaseOffset + (long) srcPos * scale;
+ long destOffset = arrayBaseOffset + (long) destPos * scale;
+ long position = 0;
+ long delta = scale;
+ if (probability(NOT_FREQUENT_PROBABILITY, nonNullSrc == nonNullDest && srcPos < destPos)) {
+ // bad aliased case so we need to copy the array from back to front
+ position = (long) (length - 1) * scale;
+ delta = -delta;
+ }
+
+ // the length was already checked before - we can emit unconditional instructions
+ ExplodeLoopNode.explodeLoop();
+ for (int iteration = 0; iteration < length; iteration++) {
+ Object value = RawLoadNode.load(nonNullSrc, sourceOffset + position, elementKind, arrayLocation);
+ RawStoreNode.storeObject(nonNullDest, destOffset + position, value, elementKind, arrayLocation, false);
+ position += delta;
+ }
+ }
+
+ @Snippet(allowPartialIntrinsicArgumentMismatch = true)
+ public static void checkcastArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) {
+ if (probability(FREQUENT_PROBABILITY, length > 0)) {
+ Object nonNullSrc = PiNode.asNonNullObject(src);
+ Object nonNullDest = PiNode.asNonNullObject(dest);
+ KlassPointer srcKlass = loadHub(nonNullSrc);
+ KlassPointer destKlass = loadHub(nonNullDest);
+ if (probability(LIKELY_PROBABILITY, srcKlass == destKlass)) {
+ // no storecheck required.
+ counters.objectCheckcastSameTypeCounter.inc();
+ counters.objectCheckcastSameTypeCopiedCounter.add(length);
+ ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length);
+ } else {
+ KlassPointer destElemKlass = destKlass.readKlassPointer(arrayClassElementOffset(INJECTED_VMCONFIG), OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION);
+ Word superCheckOffset = WordFactory.signed(destElemKlass.readInt(superCheckOffsetOffset(INJECTED_VMCONFIG), KLASS_SUPER_CHECK_OFFSET_LOCATION));
+
+ counters.objectCheckcastDifferentTypeCounter.inc();
+ counters.objectCheckcastDifferentTypeCopiedCounter.add(length);
+
+ int copiedElements = CheckcastArrayCopyCallNode.checkcastArraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, superCheckOffset, destElemKlass, false);
+ if (probability(SLOW_PATH_PROBABILITY, copiedElements != 0)) {
+ /*
+ * the stub doesn't throw the ArrayStoreException, but returns the number of
+ * copied elements (xor'd with -1).
+ */
+ copiedElements ^= -1;
+ System.arraycopy(nonNullSrc, srcPos + copiedElements, nonNullDest, destPos + copiedElements, length - copiedElements);
+ }
+ }
+ }
+ }
+
+ @Snippet(allowPartialIntrinsicArgumentMismatch = true)
+ public static void genericArraycopyWithSlowPathWork(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) {
+ if (probability(FREQUENT_PROBABILITY, length > 0)) {
+ counters.genericArraycopyDifferentTypeCounter.inc();
+ counters.genericArraycopyDifferentTypeCopiedCounter.add(length);
+ int copiedElements = GenericArrayCopyCallNode.genericArraycopy(src, srcPos, dest, destPos, length);
+ if (probability(SLOW_PATH_PROBABILITY, copiedElements != 0)) {
+ /*
+ * the stub doesn't throw the ArrayStoreException, but returns the number of copied
+ * elements (xor'd with -1).
+ */
+ copiedElements ^= -1;
+ System.arraycopy(src, srcPos + copiedElements, dest, destPos + copiedElements, length - copiedElements);
+ }
+ }
+ }
+
+ private static void incrementLengthCounter(int length, Counters counters) {
+ counters.lengthHistogram.inc(length);
+ }
+
+ private static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length, Counters counters) {
+ if (probability(SLOW_PATH_PROBABILITY, srcPos < 0) ||
+ probability(SLOW_PATH_PROBABILITY, destPos < 0) ||
+ probability(SLOW_PATH_PROBABILITY, length < 0) ||
+ probability(SLOW_PATH_PROBABILITY, srcPos > ArrayLengthNode.arrayLength(src) - length) ||
+ probability(SLOW_PATH_PROBABILITY, destPos > ArrayLengthNode.arrayLength(dest) - length)) {
+ counters.checkAIOOBECounter.inc();
+ DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+ }
+ counters.checkSuccessCounter.inc();
+ }
+
+ private static void checkArrayTypes(Object nonNullSrc, Object nonNullDest, ArrayCopyTypeCheck arrayTypeCheck) {
+ if (arrayTypeCheck == ArrayCopyTypeCheck.NO_ARRAY_TYPE_CHECK) {
+ // nothing to do
+ } else if (arrayTypeCheck == ArrayCopyTypeCheck.HUB_BASED_ARRAY_TYPE_CHECK) {
+ KlassPointer srcHub = loadHub(nonNullSrc);
+ KlassPointer destHub = loadHub(nonNullDest);
+ if (probability(SLOW_PATH_PROBABILITY, srcHub != destHub)) {
+ DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
+ }
+ } else if (arrayTypeCheck == ArrayCopyTypeCheck.LAYOUT_HELPER_BASED_ARRAY_TYPE_CHECK) {
+ KlassPointer srcHub = loadHub(nonNullSrc);
+ KlassPointer destHub = loadHub(nonNullDest);
+ checkArrayType(srcHub);
+ checkArrayType(destHub);
+ } else {
+ ReplacementsUtil.staticAssert(false, "unknown array type check");
+ }
+ }
+
private static int checkArrayType(KlassPointer nonNullHub) {
int layoutHelper = readLayoutHelper(nonNullHub);
if (probability(SLOW_PATH_PROBABILITY, layoutHelper >= 0)) {
@@ -97,528 +290,228 @@
return layoutHelper;
}
- private static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length, Counters counters) {
- if (probability(SLOW_PATH_PROBABILITY, srcPos < 0)) {
- counters.checkAIOOBECounter.inc();
- DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
- }
- if (probability(SLOW_PATH_PROBABILITY, destPos < 0)) {
- counters.checkAIOOBECounter.inc();
- DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
- }
- if (probability(SLOW_PATH_PROBABILITY, length < 0)) {
- counters.checkAIOOBECounter.inc();
- DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
- }
- if (probability(SLOW_PATH_PROBABILITY, srcPos > ArrayLengthNode.arrayLength(src) - length)) {
- counters.checkAIOOBECounter.inc();
- DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
- }
- if (probability(SLOW_PATH_PROBABILITY, destPos > ArrayLengthNode.arrayLength(dest) - length)) {
- counters.checkAIOOBECounter.inc();
- DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
- }
- counters.checkSuccessCounter.inc();
- }
-
- @Snippet
- public static void arraycopyZeroLengthIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) {
- Object nonNullSrc = GraalDirectives.guardingNonNull(src);
- Object nonNullDest = GraalDirectives.guardingNonNull(dest);
- KlassPointer srcHub = loadHub(nonNullSrc);
- KlassPointer destHub = loadHub(nonNullDest);
- checkArrayType(srcHub);
- checkArrayType(destHub);
- checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
- counters.zeroLengthStaticCounter.inc();
- }
-
- @Snippet
- public static void arraycopyExactIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, @ConstantParameter SnippetCounter counter,
- @ConstantParameter SnippetCounter copiedCounter, @ConstantParameter Counters counters) {
- Object nonNullSrc = GraalDirectives.guardingNonNull(src);
- Object nonNullDest = GraalDirectives.guardingNonNull(dest);
- checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
- counter.inc();
- copiedCounter.add(length);
- ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind);
- if (length == 0) {
- counters.zeroLengthDynamicCounter.inc();
- } else {
- counters.nonZeroLengthDynamicCounter.inc();
- counters.nonZeroLengthDynamicCopiedCounter.add(length);
- }
- }
-
- /**
- * This intrinsic is useful for the case where we know something statically about one of the
- * inputs but not the other.
- */
- @Snippet
- public static void arraycopyPredictedExactIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind,
- @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter, @ConstantParameter Counters counters) {
- Object nonNullSrc = GraalDirectives.guardingNonNull(src);
- Object nonNullDest = GraalDirectives.guardingNonNull(dest);
- KlassPointer srcHub = loadHub(nonNullSrc);
- KlassPointer destHub = loadHub(nonNullDest);
- if (probability(SLOW_PATH_PROBABILITY, srcHub != destHub)) {
- DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
- }
- checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
- counter.inc();
- copiedCounter.add(length);
- ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind);
- if (length == 0) {
- counters.zeroLengthDynamicCounter.inc();
- } else {
- counters.nonZeroLengthDynamicCounter.inc();
- counters.nonZeroLengthDynamicCopiedCounter.add(length);
- }
- }
-
- @Snippet
- public static void arraycopyPredictedObjectWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, KlassPointer objectArrayKlass,
- @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter, @ConstantParameter Counters counters) {
- if (length > 0) {
- KlassPointer srcHub = loadHub(PiNode.asNonNullObject(nonNullSrc));
- KlassPointer destHub = loadHub(PiNode.asNonNullObject(nonNullDest));
- if (probability(FAST_PATH_PROBABILITY, srcHub == destHub || destHub == objectArrayKlass)) {
- counter.inc();
- copiedCounter.add(length);
- counters.predictedObjectArrayCopyFastPathCounter.inc();
- counters.predictedObjectArrayCopyFastPathCopiedCounter.add(length);
- ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length);
- } else {
- counters.predictedObjectArrayCopySlowPathCounter.inc();
- counters.predictedObjectArrayCopySlowPathCopiedCounter.add(length);
- System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length);
- }
- }
- }
-
- /**
- * This is the basic template for the full arraycopy checks, including a check that the
- * underlying type is really an array type.
- */
- @Snippet
- public static void arraycopySlowPathIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, KlassPointer predictedKlass, @ConstantParameter JavaKind elementKind,
- @ConstantParameter SnippetInfo slowPath, @ConstantParameter Object slowPathArgument, @ConstantParameter Counters counters) {
- Object nonNullSrc = GraalDirectives.guardingNonNull(src);
- Object nonNullDest = GraalDirectives.guardingNonNull(dest);
- KlassPointer srcHub = loadHub(nonNullSrc);
- KlassPointer destHub = loadHub(nonNullDest);
- checkArrayType(srcHub);
- checkArrayType(destHub);
- checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
- if (length == 0) {
- counters.zeroLengthDynamicCounter.inc();
- } else {
- counters.nonZeroLengthDynamicCounter.inc();
- counters.nonZeroLengthDynamicCopiedCounter.add(length);
- }
- ArrayCopySlowPathNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, predictedKlass, elementKind, slowPath, slowPathArgument);
- }
-
- /**
- * Snippet for unrolled arraycopy.
- */
- @Snippet
- public static void arraycopyUnrolledIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter int unrolledLength, @ConstantParameter JavaKind elementKind,
- @ConstantParameter Counters counters) {
- Object nonNullSrc = GraalDirectives.guardingNonNull(src);
- Object nonNullDest = GraalDirectives.guardingNonNull(dest);
- checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
- if (length == 0) {
- counters.zeroLengthDynamicCounter.inc();
- } else {
- counters.nonZeroLengthDynamicCounter.inc();
- counters.nonZeroLengthDynamicCopiedCounter.add(length);
- }
- ArrayCopyUnrollNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, unrolledLength, elementKind);
- }
-
- @Snippet
- public static void checkcastArraycopyWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantParameter Counters counters) {
- if (length > 0) {
- KlassPointer destKlass = loadHub(nonNullDest);
- KlassPointer srcKlass = loadHub(nonNullSrc);
- if (probability(SLOW_PATH_PROBABILITY, srcKlass == destKlass)) {
- // no storecheck required.
- counters.objectCheckcastSameTypeCounter.inc();
- counters.objectCheckcastSameTypeCopiedCounter.add(length);
- ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length);
- } else {
- KlassPointer destElemKlass = destKlass.readKlassPointer(arrayClassElementOffset(INJECTED_VMCONFIG), OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION);
- Word superCheckOffset = WordFactory.signed(destElemKlass.readInt(superCheckOffsetOffset(INJECTED_VMCONFIG), KLASS_SUPER_CHECK_OFFSET_LOCATION));
- counters.objectCheckcastCounter.inc();
- counters.objectCheckcastCopiedCounter.add(length);
- int copiedElements = CheckcastArrayCopyCallNode.checkcastArraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, superCheckOffset, destElemKlass, false);
- if (copiedElements != 0) {
- /*
- * the checkcast stub doesn't throw the ArrayStoreException, but returns the
- * number of copied elements (xor'd with -1).
- */
- copiedElements ^= -1;
- System.arraycopy(nonNullSrc, srcPos + copiedElements, nonNullDest, destPos + copiedElements, length - copiedElements);
- }
- }
- }
- }
-
- @Snippet
- public static void arraycopyGeneric(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) {
- Object nonNullSrc = GraalDirectives.guardingNonNull(src);
- Object nonNullDest = GraalDirectives.guardingNonNull(dest);
- KlassPointer srcHub = loadHub(nonNullSrc);
- KlassPointer destHub = loadHub(nonNullDest);
- if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, nonNullSrc != nonNullDest)) {
- int layoutHelper = checkArrayType(srcHub);
- final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace(INJECTED_VMCONFIG)) == 0);
- checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters);
- if (probability(FAST_PATH_PROBABILITY, isObjectArray)) {
- counters.genericObjectExactCallCounter.inc();
- counters.genericObjectExactCallCopiedCounter.add(length);
- ArrayCopyCallNode.disjointArraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, JavaKind.Object);
- } else {
- counters.genericPrimitiveCallCounter.inc();
- counters.genericPrimitiveCallCopiedCounter.add(length);
- UnsafeArrayCopyNode.arraycopyPrimitive(nonNullSrc, srcPos, nonNullDest, destPos, length, layoutHelper);
- }
- } else {
- counters.systemArraycopyCounter.inc();
- counters.systemArraycopyCopiedCounter.add(length);
- System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length);
- }
- }
-
- @Fold
- static LocationIdentity getArrayLocation(JavaKind kind) {
- return NamedLocationIdentity.getArrayLocation(kind);
- }
-
- @Snippet
- public static void arraycopyUnrolledWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, @ConstantParameter int length, @ConstantParameter JavaKind elementKind) {
- final int scale = arrayIndexScale(elementKind);
- int arrayBaseOffset = arrayBaseOffset(elementKind);
- LocationIdentity arrayLocation = getArrayLocation(elementKind);
- if (nonNullSrc == nonNullDest && srcPos < destPos) { // bad aliased case
- long start = (long) (length - 1) * scale;
- long i = start;
- ExplodeLoopNode.explodeLoop();
- for (int iteration = 0; iteration < length; iteration++) {
- if (i >= 0) {
- Object a = RawLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation);
- RawStoreNode.storeObject(nonNullDest, arrayBaseOffset + i + (long) destPos * scale, a, elementKind, arrayLocation, false);
- i -= scale;
- }
- }
- } else {
- long end = (long) length * scale;
- long i = 0;
- ExplodeLoopNode.explodeLoop();
- for (int iteration = 0; iteration < length; iteration++) {
- if (i < end) {
- Object a = RawLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation);
- RawStoreNode.storeObject(nonNullDest, arrayBaseOffset + i + (long) destPos * scale, a, elementKind, arrayLocation, false);
- i += scale;
- }
- }
- }
- }
-
static class Counters {
final SnippetCounter checkSuccessCounter;
final SnippetCounter checkAIOOBECounter;
- final SnippetCounter objectCheckcastCounter;
- final SnippetCounter objectCheckcastSameTypeCounter;
- final SnippetCounter predictedObjectArrayCopySlowPathCounter;
- final SnippetCounter predictedObjectArrayCopyFastPathCounter;
+ final SnippetCounter zeroLengthStaticCounter;
+ final SnippetIntegerHistogram lengthHistogram;
- final SnippetCounter genericPrimitiveCallCounter;
- final SnippetCounter genericObjectExactCallCounter;
final SnippetCounter systemArraycopyCounter;
-
- final SnippetCounter zeroLengthStaticCounter;
- final SnippetCounter zeroLengthDynamicCounter;
- final SnippetCounter nonZeroLengthDynamicCounter;
-
- final SnippetCounter nonZeroLengthDynamicCopiedCounter;
- final SnippetCounter genericPrimitiveCallCopiedCounter;
- final SnippetCounter genericObjectExactCallCopiedCounter;
final SnippetCounter systemArraycopyCopiedCounter;
- final SnippetCounter objectCheckcastCopiedCounter;
+ final SnippetCounter genericArraycopyDifferentTypeCopiedCounter;
+ final SnippetCounter genericArraycopyDifferentTypeCounter;
+
final SnippetCounter objectCheckcastSameTypeCopiedCounter;
- final SnippetCounter predictedObjectArrayCopySlowPathCopiedCounter;
- final SnippetCounter predictedObjectArrayCopyFastPathCopiedCounter;
+ final SnippetCounter objectCheckcastSameTypeCounter;
+ final SnippetCounter objectCheckcastDifferentTypeCopiedCounter;
+ final SnippetCounter objectCheckcastDifferentTypeCounter;
final EnumMap<JavaKind, SnippetCounter> arraycopyCallCounters = new EnumMap<>(JavaKind.class);
- final EnumMap<JavaKind, SnippetCounter> arraycopyCounters = new EnumMap<>(JavaKind.class);
-
final EnumMap<JavaKind, SnippetCounter> arraycopyCallCopiedCounters = new EnumMap<>(JavaKind.class);
- final EnumMap<JavaKind, SnippetCounter> arraycopyCopiedCounters = new EnumMap<>(JavaKind.class);
Counters(SnippetCounter.Group.Factory factory) {
final Group checkCounters = factory.createSnippetCounterGroup("System.arraycopy checkInputs");
- final Group counters = factory.createSnippetCounterGroup("System.arraycopy");
- final Group copiedCounters = factory.createSnippetCounterGroup("System.arraycopy copied elements");
- final Group lengthCounters = factory.createSnippetCounterGroup("System.arraycopy 0-length checks");
+ final Group callCounters = factory.createSnippetCounterGroup("System.arraycopy calls");
+ final Group copiedElementsCounters = factory.createSnippetCounterGroup("System.arraycopy copied elements");
+ final Group lengthCounters = factory.createSnippetCounterGroup("System.arraycopy with 0-length");
checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess");
checkAIOOBECounter = new SnippetCounter(checkCounters, "checkAIOOBE", "checkAIOOBE");
- objectCheckcastCounter = new SnippetCounter(counters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays");
- objectCheckcastSameTypeCounter = new SnippetCounter(counters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays");
- predictedObjectArrayCopySlowPathCounter = new SnippetCounter(counters, "Object[]{slow-path}", "used System.arraycopy slow path for predicted Object[] arrays");
- predictedObjectArrayCopyFastPathCounter = new SnippetCounter(counters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays");
- genericPrimitiveCallCounter = new SnippetCounter(counters, "genericPrimitive", "generic arraycopy snippet for primitive arrays");
- genericObjectExactCallCounter = new SnippetCounter(counters, "genericObjectExact", "generic arraycopy snippet for special object arrays");
- systemArraycopyCounter = new SnippetCounter(counters, "genericObject", "call to System.arraycopy");
+ zeroLengthStaticCounter = new SnippetCounter(lengthCounters, "0-length copy static", "calls where the length is statically 0");
+ lengthHistogram = new SnippetIntegerHistogram(lengthCounters, 2, "length", "length");
- zeroLengthStaticCounter = new SnippetCounter(lengthCounters, "0-lengthcopy static", "arraycopy where the length is statically 0");
- zeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "0-lengthcopy dynamically", "arraycopy where the length is dynamically 0");
- nonZeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero");
+ systemArraycopyCounter = new SnippetCounter(callCounters, "native System.arraycopy", "JNI-based System.arraycopy call");
+ systemArraycopyCopiedCounter = new SnippetCounter(copiedElementsCounters, "native System.arraycopy", "JNI-based System.arraycopy call");
+
+ genericArraycopyDifferentTypeCounter = new SnippetCounter(callCounters, "generic[] stub", "generic arraycopy stub");
+ genericArraycopyDifferentTypeCopiedCounter = new SnippetCounter(copiedElementsCounters, "generic[] stub", "generic arraycopy stub");
- nonZeroLengthDynamicCopiedCounter = new SnippetCounter(copiedCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero");
- genericPrimitiveCallCopiedCounter = new SnippetCounter(copiedCounters, "genericPrimitive", "generic arraycopy snippet for primitive arrays");
- genericObjectExactCallCopiedCounter = new SnippetCounter(copiedCounters, "genericObjectExact", "generic arraycopy snippet for special object arrays");
- systemArraycopyCopiedCounter = new SnippetCounter(copiedCounters, "genericObject", "call to System.arraycopy");
+ objectCheckcastSameTypeCounter = new SnippetCounter(callCounters, "checkcast object[] (same-type)", "checkcast object[] stub but src.klass == dest.klass Object[] arrays");
+ objectCheckcastSameTypeCopiedCounter = new SnippetCounter(copiedElementsCounters, "checkcast object[] (same-type)", "checkcast object[] stub but src.klass == dest.klass Object[] arrays");
+ objectCheckcastDifferentTypeCounter = new SnippetCounter(callCounters, "checkcast object[] (store-check)", "checkcast object[] stub with store check");
+ objectCheckcastDifferentTypeCopiedCounter = new SnippetCounter(copiedElementsCounters, "checkcast object[] (store-check)", "checkcast object[] stub with store check");
- objectCheckcastCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays");
- objectCheckcastSameTypeCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays");
- predictedObjectArrayCopySlowPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{slow-path}",
- "used System.arraycopy slow path for predicted Object[] arrays");
- predictedObjectArrayCopyFastPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays");
- createArraycopyCounter(JavaKind.Byte, counters, copiedCounters);
- createArraycopyCounter(JavaKind.Boolean, counters, copiedCounters);
- createArraycopyCounter(JavaKind.Char, counters, copiedCounters);
- createArraycopyCounter(JavaKind.Short, counters, copiedCounters);
- createArraycopyCounter(JavaKind.Int, counters, copiedCounters);
- createArraycopyCounter(JavaKind.Long, counters, copiedCounters);
- createArraycopyCounter(JavaKind.Float, counters, copiedCounters);
- createArraycopyCounter(JavaKind.Double, counters, copiedCounters);
- createArraycopyCounter(JavaKind.Object, counters, copiedCounters);
+ createArraycopyCounter(JavaKind.Byte, callCounters, copiedElementsCounters);
+ createArraycopyCounter(JavaKind.Boolean, callCounters, copiedElementsCounters);
+ createArraycopyCounter(JavaKind.Char, callCounters, copiedElementsCounters);
+ createArraycopyCounter(JavaKind.Short, callCounters, copiedElementsCounters);
+ createArraycopyCounter(JavaKind.Int, callCounters, copiedElementsCounters);
+ createArraycopyCounter(JavaKind.Long, callCounters, copiedElementsCounters);
+ createArraycopyCounter(JavaKind.Float, callCounters, copiedElementsCounters);
+ createArraycopyCounter(JavaKind.Double, callCounters, copiedElementsCounters);
+ createArraycopyCounter(JavaKind.Object, callCounters, copiedElementsCounters);
}
void createArraycopyCounter(JavaKind kind, Group counters, Group copiedCounters) {
- arraycopyCallCounters.put(kind, new SnippetCounter(counters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays"));
- arraycopyCounters.put(kind, new SnippetCounter(counters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays"));
-
- arraycopyCallCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays"));
- arraycopyCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays"));
+ arraycopyCallCounters.put(kind, new SnippetCounter(counters, kind + "[] stub", "arraycopy call for " + kind + "[] arrays"));
+ arraycopyCallCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[] stub", "arraycopy call for " + kind + "[] arrays"));
}
}
public static class Templates extends SnippetTemplate.AbstractTemplates {
+ private final SnippetInfo arraycopyGenericSnippet = snippet("arraycopyGenericSnippet");
+ private final SnippetInfo arraycopyUnrolledSnippet = snippet("arraycopyUnrolledSnippet");
+ private final SnippetInfo arraycopyExactSnippet = snippet("arraycopyExactSnippet");
+ private final SnippetInfo arraycopyZeroLengthSnippet = snippet("arraycopyZeroLengthSnippet");
+ private final SnippetInfo arraycopyCheckcastSnippet = snippet("arraycopyCheckcastSnippet");
+ private final SnippetInfo arraycopyNativeSnippet = snippet("arraycopyNativeSnippet");
+
+ private final SnippetInfo checkcastArraycopyWithSlowPathWork = snippet("checkcastArraycopyWithSlowPathWork");
+ private final SnippetInfo genericArraycopyWithSlowPathWork = snippet("genericArraycopyWithSlowPathWork");
+
+ private ResolvedJavaMethod originalArraycopy;
+ private final Counters counters;
public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target) {
super(options, factories, providers, providers.getSnippetReflection(), target);
this.counters = new Counters(factory);
}
- private ResolvedJavaMethod originalArraycopy() throws GraalError {
- if (originalArraycopy == null) {
- Method method;
- try {
- method = System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class);
- } catch (NoSuchMethodException | SecurityException e) {
- throw new GraalError(e);
- }
- originalArraycopy = providers.getMetaAccess().lookupJavaMethod(method);
- }
- return originalArraycopy;
- }
-
- private ResolvedJavaMethod originalArraycopy;
-
- private final SnippetInfo checkcastArraycopyWorkSnippet = snippet("checkcastArraycopyWork");
- private final SnippetInfo arraycopyGenericSnippet = snippet("arraycopyGeneric");
-
- private final SnippetInfo arraycopySlowPathIntrinsicSnippet = snippet("arraycopySlowPathIntrinsic");
- private final SnippetInfo arraycopyUnrolledIntrinsicSnippet = snippet("arraycopyUnrolledIntrinsic");
- private final SnippetInfo arraycopyExactIntrinsicSnippet = snippet("arraycopyExactIntrinsic");
- private final SnippetInfo arraycopyZeroLengthIntrinsicSnippet = snippet("arraycopyZeroLengthIntrinsic");
- private final SnippetInfo arraycopyPredictedExactIntrinsicSnippet = snippet("arraycopyPredictedExactIntrinsic");
- private final SnippetInfo arraycopyPredictedObjectWorkSnippet = snippet("arraycopyPredictedObjectWork");
-
- private final SnippetInfo arraycopyUnrolledWorkSnippet = snippet("arraycopyUnrolledWork");
-
- private final Counters counters;
-
protected SnippetInfo snippet(String methodName) {
SnippetInfo info = snippet(ArrayCopySnippets.class, methodName, LocationIdentity.any());
info.setOriginalMethod(originalArraycopy());
return info;
}
- public static JavaKind selectComponentKind(BasicArrayCopyNode arraycopy) {
- return selectComponentKind(arraycopy, true);
- }
+ public void lower(ArrayCopyNode arraycopy, LoweringTool tool) {
+ JavaKind elementKind = selectComponentKind(arraycopy);
+ SnippetInfo snippetInfo;
+ ArrayCopyTypeCheck arrayTypeCheck;
- public static JavaKind selectComponentKind(BasicArrayCopyNode arraycopy, boolean exact) {
ResolvedJavaType srcType = StampTool.typeOrNull(arraycopy.getSource().stamp());
ResolvedJavaType destType = StampTool.typeOrNull(arraycopy.getDestination().stamp());
+ if (!canBeArray(srcType) || !canBeArray(destType)) {
+ // at least one of the objects is definitely not an array - use the native call
+ // right away as the copying will fail anyways
+ snippetInfo = arraycopyNativeSnippet;
+ arrayTypeCheck = ArrayCopyTypeCheck.UNDEFINED_ARRAY_TYPE_CHECK;
+ } else {
+ ResolvedJavaType srcComponentType = srcType == null ? null : srcType.getComponentType();
+ ResolvedJavaType destComponentType = destType == null ? null : destType.getComponentType();
- if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) {
- if (!exact) {
- JavaKind component = getComponentKind(srcType);
- if (component != null) {
- return component;
+ if (arraycopy.isExact()) {
+ // there is a sufficient type match - we don't need any additional type checks
+ snippetInfo = arraycopyExactSnippet;
+ arrayTypeCheck = ArrayCopyTypeCheck.NO_ARRAY_TYPE_CHECK;
+ } else if (srcComponentType == null && destComponentType == null) {
+ // we don't know anything about the types - use the generic copying
+ snippetInfo = arraycopyGenericSnippet;
+ arrayTypeCheck = ArrayCopyTypeCheck.LAYOUT_HELPER_BASED_ARRAY_TYPE_CHECK;
+ } else if (srcComponentType != null && destComponentType != null) {
+ if (!srcComponentType.isPrimitive() && !destComponentType.isPrimitive()) {
+ // it depends on the array content if the copy succeeds - we need
+ // a type check for every store
+ snippetInfo = arraycopyCheckcastSnippet;
+ arrayTypeCheck = ArrayCopyTypeCheck.NO_ARRAY_TYPE_CHECK;
+ } else {
+ // one object is an object array, the other one is a primitive array.
+ // this copy will always fail - use the native call right away
+ assert !srcComponentType.equals(destComponentType) : "must be handled by arraycopy.isExact()";
+ snippetInfo = arraycopyNativeSnippet;
+ arrayTypeCheck = ArrayCopyTypeCheck.UNDEFINED_ARRAY_TYPE_CHECK;
}
- return getComponentKind(destType);
- }
- return null;
- }
- if (exact) {
- if (!destType.getComponentType().isAssignableFrom(srcType.getComponentType())) {
- return null;
- }
- if (!arraycopy.isExact()) {
- return null;
+ } else {
+ ResolvedJavaType nonNullComponentType = srcComponentType != null ? srcComponentType : destComponentType;
+ if (nonNullComponentType.isPrimitive()) {
+ // one involved object is a primitive array - we can safely assume that we
+ // are copying primitive arrays
+ snippetInfo = arraycopyExactSnippet;
+ arrayTypeCheck = ArrayCopyTypeCheck.HUB_BASED_ARRAY_TYPE_CHECK;
+ elementKind = nonNullComponentType.getJavaKind();
+ } else {
+ // one involved object is an object array - we can safely assume that we are
+ // copying object arrays that might require a store check
+ snippetInfo = arraycopyCheckcastSnippet;
+ arrayTypeCheck = ArrayCopyTypeCheck.LAYOUT_HELPER_BASED_ARRAY_TYPE_CHECK;
+ }
}
}
- return srcType.getComponentType().getJavaKind();
- }
- private static JavaKind getComponentKind(ResolvedJavaType type) {
- if (type != null && type.isArray()) {
- return type.getComponentType().getJavaKind();
- }
- return null;
- }
-
- private static boolean shouldUnroll(ValueNode length) {
- return length.isConstant() && length.asJavaConstant().asInt() <= 8 && length.asJavaConstant().asInt() != 0;
- }
-
- public void lower(ArrayCopyNode arraycopy, LoweringTool tool) {
- JavaKind componentKind = selectComponentKind(arraycopy);
- SnippetInfo snippetInfo = null;
- SnippetInfo slowPathSnippetInfo = null;
- Object slowPathArgument = null;
-
+ // a few special cases that are easier to handle when all other variables already have a
+ // value
if (arraycopy.getLength().isConstant() && arraycopy.getLength().asJavaConstant().asLong() == 0) {
- snippetInfo = arraycopyZeroLengthIntrinsicSnippet;
- } else if (arraycopy.isExact()) {
- snippetInfo = arraycopyExactIntrinsicSnippet;
- if (shouldUnroll(arraycopy.getLength())) {
- snippetInfo = arraycopyUnrolledIntrinsicSnippet;
- }
- } else {
- if (componentKind == JavaKind.Object) {
- ResolvedJavaType srcType = StampTool.typeOrNull(arraycopy.getSource().stamp());
- ResolvedJavaType destType = StampTool.typeOrNull(arraycopy.getDestination().stamp());
- ResolvedJavaType srcComponentType = srcType == null ? null : srcType.getComponentType();
- ResolvedJavaType destComponentType = destType == null ? null : destType.getComponentType();
- if (srcComponentType != null && destComponentType != null && !srcComponentType.isPrimitive() && !destComponentType.isPrimitive()) {
- snippetInfo = arraycopySlowPathIntrinsicSnippet;
- slowPathSnippetInfo = checkcastArraycopyWorkSnippet;
- slowPathArgument = LocationIdentity.any();
- /*
- * Because this snippet has to use Sysytem.arraycopy as a slow path, we must
- * pretend to kill any() so clear the componentKind.
- */
- componentKind = null;
- }
- }
- if (componentKind == null && snippetInfo == null) {
- JavaKind predictedKind = selectComponentKind(arraycopy, false);
- if (predictedKind != null) {
- /*
- * At least one array is of a known type requiring no store checks, so
- * assume the other is of the same type. Generally this is working around
- * deficiencies in our propagation of type information.
- */
- componentKind = predictedKind;
- if (predictedKind == JavaKind.Object) {
- snippetInfo = arraycopySlowPathIntrinsicSnippet;
- slowPathSnippetInfo = arraycopyPredictedObjectWorkSnippet;
- slowPathArgument = predictedKind;
- componentKind = null;
- } else {
- snippetInfo = arraycopyPredictedExactIntrinsicSnippet;
- }
- }
- }
- if (snippetInfo == null) {
- snippetInfo = arraycopyGenericSnippet;
- }
+ snippetInfo = arraycopyZeroLengthSnippet;
+ } else if (snippetInfo == arraycopyExactSnippet && shouldUnroll(arraycopy.getLength())) {
+ snippetInfo = arraycopyUnrolledSnippet;
}
+
+ // create the snippet
Arguments args = new Arguments(snippetInfo, arraycopy.graph().getGuardsStage(), tool.getLoweringStage());
args.add("src", arraycopy.getSource());
args.add("srcPos", arraycopy.getSourcePosition());
args.add("dest", arraycopy.getDestination());
args.add("destPos", arraycopy.getDestinationPosition());
args.add("length", arraycopy.getLength());
- if (snippetInfo == arraycopyUnrolledIntrinsicSnippet) {
+ if (snippetInfo != arraycopyNativeSnippet) {
+ assert arrayTypeCheck != ArrayCopyTypeCheck.UNDEFINED_ARRAY_TYPE_CHECK;
+ args.addConst("arrayTypeCheck", arrayTypeCheck);
+ }
+ if (snippetInfo == arraycopyUnrolledSnippet) {
+ args.addConst("elementKind", elementKind != null ? elementKind : JavaKind.Illegal);
args.addConst("unrolledLength", arraycopy.getLength().asJavaConstant().asInt());
- args.addConst("elementKind", componentKind != null ? componentKind : JavaKind.Illegal);
- } else if (snippetInfo == arraycopySlowPathIntrinsicSnippet) {
- ValueNode predictedKlass = null;
- if (slowPathArgument == arraycopyPredictedObjectWorkSnippet) {
- HotSpotResolvedObjectType arrayClass = (HotSpotResolvedObjectType) tool.getMetaAccess().lookupJavaType(Object[].class);
- predictedKlass = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), arrayClass.klass(), tool.getMetaAccess(), arraycopy.graph());
- } else {
- predictedKlass = ConstantNode.forConstant(KlassPointerStamp.klassAlwaysNull(), JavaConstant.NULL_POINTER, tool.getMetaAccess(), arraycopy.graph());
- }
- args.add("predictedKlass", predictedKlass);
- args.addConst("elementKind", componentKind != null ? componentKind : JavaKind.Illegal);
- args.addConst("slowPath", slowPathSnippetInfo);
- assert slowPathArgument != null;
- args.addConst("slowPathArgument", slowPathArgument);
- } else if (snippetInfo == arraycopyExactIntrinsicSnippet || snippetInfo == arraycopyPredictedExactIntrinsicSnippet) {
- assert componentKind != null;
- args.addConst("elementKind", componentKind);
- args.addConst("counter", counters.arraycopyCallCounters.get(componentKind));
- args.addConst("copiedCounter", counters.arraycopyCallCopiedCounters.get(componentKind));
+ }
+ if (snippetInfo == arraycopyExactSnippet) {
+ assert elementKind != null;
+ args.addConst("elementKind", elementKind);
+ args.addConst("elementKindCounter", counters.arraycopyCallCounters.get(elementKind));
+ args.addConst("elementKindCopiedCounter", counters.arraycopyCallCopiedCounters.get(elementKind));
+ }
+ args.addConst("counters", counters);
+ if (snippetInfo == arraycopyCheckcastSnippet) {
+ args.addConst("workSnippet", checkcastArraycopyWithSlowPathWork);
+ args.addConst("elementKind", JavaKind.Illegal);
+ }
+ if (snippetInfo == arraycopyGenericSnippet) {
+ args.addConst("workSnippet", genericArraycopyWithSlowPathWork);
+ args.addConst("elementKind", JavaKind.Illegal);
}
+
+ instantiate(args, arraycopy);
+ }
+
+ public void lower(ArrayCopyWithSlowPathNode arraycopy, LoweringTool tool) {
+ StructuredGraph graph = arraycopy.graph();
+ if (!graph.getGuardsStage().areFrameStatesAtDeopts()) {
+ // if an arraycopy contains a slow path, we can't lower it right away
+ return;
+ }
+
+ SnippetInfo snippetInfo = arraycopy.getSnippet();
+ Arguments args = new Arguments(snippetInfo, graph.getGuardsStage(), tool.getLoweringStage());
+ args.add("src", arraycopy.getSource());
+ args.add("srcPos", arraycopy.getSourcePosition());
+ args.add("dest", arraycopy.getDestination());
+ args.add("destPos", arraycopy.getDestinationPosition());
+ args.add("length", arraycopy.getLength());
args.addConst("counters", counters);
instantiate(args, arraycopy);
}
- public void lower(ArrayCopySlowPathNode arraycopy, LoweringTool tool) {
- StructuredGraph graph = arraycopy.graph();
- if (!graph.getGuardsStage().areFrameStatesAtDeopts()) {
- // Can't be lowered yet
- return;
- }
- SnippetInfo snippetInfo = arraycopy.getSnippet();
- Arguments args = new Arguments(snippetInfo, graph.getGuardsStage(), tool.getLoweringStage());
- args.add("nonNullSrc", arraycopy.getSource());
- args.add("srcPos", arraycopy.getSourcePosition());
- args.add("nonNullDest", arraycopy.getDestination());
- args.add("destPos", arraycopy.getDestinationPosition());
- if (snippetInfo == arraycopyUnrolledWorkSnippet) {
- args.addConst("length", ((Integer) arraycopy.getArgument()).intValue());
- args.addConst("elementKind", arraycopy.getElementKind());
- } else {
- args.add("length", arraycopy.getLength());
- }
- if (snippetInfo == arraycopyPredictedObjectWorkSnippet) {
- args.add("objectArrayKlass", arraycopy.getPredictedKlass());
- args.addConst("counter", counters.arraycopyCallCounters.get(JavaKind.Object));
- args.addConst("copiedCounter", counters.arraycopyCallCopiedCounters.get(JavaKind.Object));
- args.addConst("counters", counters);
- }
- instantiate(args, arraycopy);
+ private static boolean canBeArray(ResolvedJavaType type) {
+ return type == null || type.isJavaLangObject() || type.isArray();
}
- public void lower(ArrayCopyUnrollNode arraycopy, LoweringTool tool) {
- StructuredGraph graph = arraycopy.graph();
- if (!graph.getGuardsStage().areFrameStatesAtDeopts()) {
- // Can't be lowered yet
- return;
+ public static JavaKind selectComponentKind(BasicArrayCopyNode arraycopy) {
+ ResolvedJavaType srcType = StampTool.typeOrNull(arraycopy.getSource().stamp());
+ ResolvedJavaType destType = StampTool.typeOrNull(arraycopy.getDestination().stamp());
+
+ if (srcType == null || !srcType.isArray() || destType == null || !destType.isArray()) {
+ return null;
}
- SnippetInfo snippetInfo = arraycopyUnrolledWorkSnippet;
- Arguments args = new Arguments(snippetInfo, graph.getGuardsStage(), tool.getLoweringStage());
- args.add("nonNullSrc", arraycopy.getSource());
- args.add("srcPos", arraycopy.getSourcePosition());
- args.add("nonNullDest", arraycopy.getDestination());
- args.add("destPos", arraycopy.getDestinationPosition());
- args.addConst("length", arraycopy.getUnrollLength());
- args.addConst("elementKind", arraycopy.getElementKind());
- template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args);
+ if (!destType.getComponentType().isAssignableFrom(srcType.getComponentType())) {
+ return null;
+ }
+ if (!arraycopy.isExact()) {
+ return null;
+ }
+ return srcType.getComponentType().getJavaKind();
+ }
+
+ private static boolean shouldUnroll(ValueNode length) {
+ return length.isConstant() && length.asJavaConstant().asInt() <= 8 && length.asJavaConstant().asInt() != 0;
}
/**
@@ -650,8 +543,8 @@
newInvoke.setStateAfter(arraycopy.stateAfter());
}
graph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke);
- } else if (originalNode instanceof ArrayCopySlowPathNode) {
- ArrayCopySlowPathNode slowPath = (ArrayCopySlowPathNode) replacements.get(originalNode);
+ } else if (originalNode instanceof ArrayCopyWithSlowPathNode) {
+ ArrayCopyWithSlowPathNode slowPath = (ArrayCopyWithSlowPathNode) replacements.get(originalNode);
assert arraycopy.stateAfter() != null : arraycopy;
assert slowPath.stateAfter() == arraycopy.stateAfter();
slowPath.setBci(arraycopy.getBci());
@@ -659,5 +552,18 @@
}
GraphUtil.killCFG(arraycopy);
}
+
+ private ResolvedJavaMethod originalArraycopy() throws GraalError {
+ if (originalArraycopy == null) {
+ Method method;
+ try {
+ method = System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class);
+ } catch (NoSuchMethodException | SecurityException e) {
+ throw new GraalError(e);
+ }
+ originalArraycopy = providers.getMetaAccess().lookupJavaMethod(method);
+ }
+ return originalArraycopy;
+ }
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyUnrollNode.java Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2015, 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 org.graalvm.compiler.hotspot.replacements.arraycopy;
-
-import jdk.vm.ci.meta.JavaKind;
-
-import static org.graalvm.word.LocationIdentity.any;
-
-import org.graalvm.compiler.core.common.type.StampFactory;
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.nodeinfo.InputType;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.NamedLocationIdentity;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.ArrayRangeWriteNode;
-import org.graalvm.compiler.nodes.memory.MemoryAccess;
-import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
-import org.graalvm.compiler.nodes.memory.MemoryNode;
-import org.graalvm.compiler.nodes.spi.Lowerable;
-import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
-
-@NodeInfo(allowedUsageTypes = InputType.Memory)
-public class ArrayCopyUnrollNode extends ArrayRangeWriteNode implements MemoryCheckpoint.Single, Lowerable, MemoryAccess {
-
- public static final NodeClass<ArrayCopyUnrollNode> TYPE = NodeClass.create(ArrayCopyUnrollNode.class);
-
- @Input protected ValueNode src;
- @Input protected ValueNode srcPos;
- @Input protected ValueNode dest;
- @Input protected ValueNode destPos;
- @Input protected ValueNode length;
-
- private JavaKind elementKind;
-
- private int unrolledLength;
-
- @OptionalInput(InputType.Memory) private MemoryNode lastLocationAccess;
-
- public ArrayCopyUnrollNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, int unrolledLength, JavaKind elementKind) {
- super(TYPE, StampFactory.forKind(JavaKind.Void));
- this.src = src;
- this.srcPos = srcPos;
- this.dest = dest;
- this.destPos = destPos;
- this.length = length;
- this.unrolledLength = unrolledLength;
- assert elementKind != null && elementKind != JavaKind.Illegal;
- this.elementKind = elementKind;
- }
-
- public ValueNode getSource() {
- return src;
- }
-
- public ValueNode getSourcePosition() {
- return srcPos;
- }
-
- public ValueNode getDestination() {
- return dest;
- }
-
- public ValueNode getDestinationPosition() {
- return destPos;
- }
-
- @Override
- public ValueNode getLength() {
- return length;
- }
-
- @Override
- public ValueNode getArray() {
- return dest;
- }
-
- @Override
- public ValueNode getIndex() {
- return destPos;
- }
-
- @Override
- public boolean isObjectArray() {
- return elementKind == JavaKind.Object;
- }
-
- @Override
- public boolean isInitialization() {
- return false;
- }
-
- @NodeIntrinsic
- public static native void arraycopy(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantNodeParameter int unrolledLength,
- @ConstantNodeParameter JavaKind elementKind);
-
- public int getUnrollLength() {
- return unrolledLength;
- }
-
- public JavaKind getElementKind() {
- return elementKind;
- }
-
- @Override
- public LocationIdentity getLocationIdentity() {
- if (elementKind != null) {
- return NamedLocationIdentity.getArrayLocation(elementKind);
- }
- return any();
- }
-
- @Override
- public void lower(LoweringTool tool) {
- tool.getLowerer().lower(this, tool);
- }
-
- @Override
- public MemoryNode getLastLocationAccess() {
- return lastLocationAccess;
- }
-
- @Override
- public void setLastLocationAccess(MemoryNode lla) {
- updateUsagesInterface(lastLocationAccess, lla);
- lastLocationAccess = lla;
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyWithSlowPathNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 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 org.graalvm.compiler.hotspot.replacements.arraycopy;
+
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.type.StampTool;
+import org.graalvm.compiler.replacements.SnippetTemplate;
+import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode;
+
+import jdk.vm.ci.code.BytecodeFrame;
+import jdk.vm.ci.meta.JavaKind;
+
+@NodeInfo(allowedUsageTypes = InputType.Memory)
+public final class ArrayCopyWithSlowPathNode extends BasicArrayCopyNode {
+
+ public static final NodeClass<ArrayCopyWithSlowPathNode> TYPE = NodeClass.create(ArrayCopyWithSlowPathNode.class);
+
+ private final SnippetTemplate.SnippetInfo snippet;
+
+ public ArrayCopyWithSlowPathNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, SnippetTemplate.SnippetInfo snippet, JavaKind elementKind) {
+ super(TYPE, src, srcPos, dest, destPos, length, elementKind, BytecodeFrame.INVALID_FRAMESTATE_BCI);
+ assert StampTool.isPointerNonNull(src) && StampTool.isPointerNonNull(dest) : "must have been null checked";
+ this.snippet = snippet;
+ }
+
+ @NodeIntrinsic
+ public static native void arraycopy(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantNodeParameter SnippetTemplate.SnippetInfo snippet,
+ @ConstantNodeParameter JavaKind elementKind);
+
+ public SnippetTemplate.SnippetInfo getSnippet() {
+ return snippet;
+ }
+
+ public void setBci(int bci) {
+ this.bci = bci;
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -23,12 +23,13 @@
//JaCoCo Exclude
package org.graalvm.compiler.hotspot.replacements.arraycopy;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
+import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN;
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.core.common.type.PrimitiveStamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
@@ -114,8 +115,9 @@
graph().addBeforeFixed(this, basePtr);
int shift = CodeUtil.log2(getArrayIndexScale(JavaKind.Object));
- ValueNode scaledIndex = graph().unique(new LeftShiftNode(pos, ConstantNode.forInt(shift, graph())));
- ValueNode offset = graph().unique(new AddNode(scaledIndex, ConstantNode.forInt(getArrayBaseOffset(JavaKind.Object), graph())));
+ ValueNode extendedPos = IntegerConvertNode.convert(pos, StampFactory.forKind(runtime.getTarget().wordJavaKind), graph());
+ ValueNode scaledIndex = graph().unique(new LeftShiftNode(extendedPos, ConstantNode.forInt(shift, graph())));
+ ValueNode offset = graph().unique(new AddNode(scaledIndex, ConstantNode.forIntegerBits(PrimitiveStamp.getBits(scaledIndex.stamp()), getArrayBaseOffset(JavaKind.Object), graph())));
return graph().unique(new OffsetAddressNode(basePtr, offset));
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/GenericArrayCopyCallNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+//JaCoCo Exclude
+package org.graalvm.compiler.hotspot.replacements.arraycopy;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN;
+
+import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.hotspot.HotSpotBackend;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+import org.graalvm.compiler.hotspot.nodes.GetObjectAddressNode;
+import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.calc.IntegerConvertNode;
+import org.graalvm.compiler.nodes.extended.ForeignCallNode;
+import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint;
+import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
+import org.graalvm.compiler.nodes.spi.Lowerable;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.word.LocationIdentity;
+
+import jdk.vm.ci.meta.JavaKind;
+
+@NodeInfo(allowedUsageTypes = {InputType.Memory, InputType.Value}, cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN)
+public final class GenericArrayCopyCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
+
+ public static final NodeClass<GenericArrayCopyCallNode> TYPE = NodeClass.create(GenericArrayCopyCallNode.class);
+ @Input ValueNode src;
+ @Input ValueNode srcPos;
+ @Input ValueNode dest;
+ @Input ValueNode destPos;
+ @Input ValueNode length;
+
+ protected final HotSpotGraalRuntimeProvider runtime;
+
+ protected GenericArrayCopyCallNode(@InjectedNodeParameter HotSpotGraalRuntimeProvider runtime, ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length) {
+ super(TYPE, StampFactory.forKind(JavaKind.Int));
+ this.src = src;
+ this.srcPos = srcPos;
+ this.dest = dest;
+ this.destPos = destPos;
+ this.length = length;
+ this.runtime = runtime;
+ }
+
+ public ValueNode getSource() {
+ return src;
+ }
+
+ public ValueNode getSourcePosition() {
+ return srcPos;
+ }
+
+ public ValueNode getDestination() {
+ return dest;
+ }
+
+ public ValueNode getDestinationPosition() {
+ return destPos;
+ }
+
+ public ValueNode getLength() {
+ return length;
+ }
+
+ @Override
+ public void lower(LoweringTool tool) {
+ if (graph().getGuardsStage().areFrameStatesAtDeopts()) {
+ StructuredGraph graph = graph();
+ ValueNode srcAddr = objectAddress(getSource());
+ ValueNode destAddr = objectAddress(getDestination());
+ ForeignCallNode call = graph.add(new ForeignCallNode(runtime.getHostBackend().getForeignCalls(), HotSpotBackend.GENERIC_ARRAYCOPY, srcAddr, srcPos, destAddr, destPos, length));
+ call.setStateAfter(stateAfter());
+ graph.replaceFixedWithFixed(this, call);
+ }
+ }
+
+ private ValueNode objectAddress(ValueNode obj) {
+ GetObjectAddressNode result = graph().add(new GetObjectAddressNode(obj));
+ graph().addBeforeFixed(this, result);
+ return result;
+ }
+
+ private ValueNode wordValue(ValueNode value) {
+ if (value.stamp().getStackKind() != runtime.getTarget().wordJavaKind) {
+ return IntegerConvertNode.convert(value, StampFactory.forKind(runtime.getTarget().wordJavaKind), graph());
+ }
+ return value;
+ }
+
+ @Override
+ public LocationIdentity getLocationIdentity() {
+ return LocationIdentity.any();
+ }
+
+ @NodeIntrinsic
+ public static native int genericArraycopy(Object src, int srcPos, Object dest, int destPos, int length);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2013, 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 org.graalvm.compiler.hotspot.replacements.arraycopy;
-
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_256;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
-import static org.graalvm.word.LocationIdentity.any;
-
-import org.graalvm.compiler.core.common.type.StampFactory;
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.nodeinfo.InputType;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.NamedLocationIdentity;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.ArrayRangeWriteNode;
-import org.graalvm.compiler.nodes.memory.MemoryAccess;
-import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
-import org.graalvm.compiler.nodes.memory.MemoryNode;
-import org.graalvm.compiler.nodes.spi.Lowerable;
-import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.compiler.replacements.SnippetTemplate.Arguments;
-import org.graalvm.word.LocationIdentity;
-
-import jdk.vm.ci.meta.JavaKind;
-
-@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_256, size = SIZE_64)
-public final class UnsafeArrayCopyNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single, MemoryAccess {
-
- public static final NodeClass<UnsafeArrayCopyNode> TYPE = NodeClass.create(UnsafeArrayCopyNode.class);
- @Input ValueNode src;
- @Input ValueNode srcPos;
- @Input ValueNode dest;
- @Input ValueNode destPos;
- @Input ValueNode length;
- @OptionalInput ValueNode layoutHelper;
-
- @OptionalInput(InputType.Memory) MemoryNode lastLocationAccess;
-
- protected JavaKind elementKind;
-
- public UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper, JavaKind elementKind) {
- super(TYPE, StampFactory.forVoid());
- assert layoutHelper == null || elementKind == null;
- this.src = src;
- this.srcPos = srcPos;
- this.dest = dest;
- this.destPos = destPos;
- this.length = length;
- this.layoutHelper = layoutHelper;
- this.elementKind = elementKind;
- }
-
- public UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, JavaKind elementKind) {
- this(src, srcPos, dest, destPos, length, null, elementKind);
- }
-
- public UnsafeArrayCopyNode(ValueNode src, ValueNode srcPos, ValueNode dest, ValueNode destPos, ValueNode length, ValueNode layoutHelper) {
- this(src, srcPos, dest, destPos, length, layoutHelper, null);
- }
-
- @Override
- public ValueNode getArray() {
- return dest;
- }
-
- @Override
- public ValueNode getIndex() {
- return destPos;
- }
-
- @Override
- public ValueNode getLength() {
- return length;
- }
-
- @Override
- public boolean isObjectArray() {
- return elementKind == JavaKind.Object;
- }
-
- @Override
- public boolean isInitialization() {
- return false;
- }
-
- public JavaKind getElementKind() {
- return elementKind;
- }
-
- @Override
- public void lower(LoweringTool tool) {
- if (graph().getGuardsStage().areFrameStatesAtDeopts()) {
- UnsafeArrayCopySnippets.Templates templates = tool.getReplacements().getSnippetTemplateCache(UnsafeArrayCopySnippets.Templates.class);
- templates.lower(this, tool);
- }
- }
-
- public void addSnippetArguments(Arguments args) {
- args.add("src", src);
- args.add("srcPos", srcPos);
- args.add("dest", dest);
- args.add("destPos", destPos);
- args.add("length", length);
- if (layoutHelper != null) {
- args.add("layoutHelper", layoutHelper);
- }
- }
-
- @Override
- public LocationIdentity getLocationIdentity() {
- if (elementKind != null) {
- return NamedLocationIdentity.getArrayLocation(elementKind);
- }
- return any();
- }
-
- @Override
- public MemoryNode getLastLocationAccess() {
- return lastLocationAccess;
- }
-
- @Override
- public void setLastLocationAccess(MemoryNode lla) {
- updateUsagesInterface(lastLocationAccess, lla);
- lastLocationAccess = lla;
- }
-
- @NodeIntrinsic
- public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length, @ConstantNodeParameter JavaKind elementKind);
-
- @NodeIntrinsic
- public static native void arraycopyPrimitive(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,324 +0,0 @@
-/*
- * Copyright (c) 2013, 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 org.graalvm.compiler.hotspot.replacements.arraycopy;
-
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale;
-import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayBaseOffset;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayIndexScale;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperHeaderSizeMask;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperHeaderSizeShift;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeMask;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeShift;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.runtime;
-import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize;
-import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY;
-import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability;
-import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
-import static org.graalvm.word.LocationIdentity.any;
-
-import org.graalvm.compiler.api.replacements.Fold;
-import org.graalvm.compiler.api.replacements.Snippet;
-import org.graalvm.compiler.core.common.NumUtil;
-import org.graalvm.compiler.debug.DebugHandlersFactory;
-import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
-import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
-import org.graalvm.compiler.nodes.NamedLocationIdentity;
-import org.graalvm.compiler.nodes.extended.RawLoadNode;
-import org.graalvm.compiler.nodes.extended.RawStoreNode;
-import org.graalvm.compiler.nodes.extended.UnsafeCopyNode;
-import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.replacements.SnippetTemplate;
-import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
-import org.graalvm.compiler.replacements.SnippetTemplate.Arguments;
-import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
-import org.graalvm.compiler.replacements.Snippets;
-import org.graalvm.compiler.word.ObjectAccess;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordFactory;
-
-import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.meta.JavaKind;
-
-/**
- * As opposed to {@link ArrayCopySnippets}, these Snippets do <b>not</b> perform store checks.
- */
-public class UnsafeArrayCopySnippets implements Snippets {
-
- private static final boolean supportsUnalignedMemoryAccess = runtime().getHostJVMCIBackend().getTarget().arch.supportsUnalignedMemoryAccess();
-
- private static final JavaKind VECTOR_KIND = JavaKind.Long;
- private static final long VECTOR_SIZE = getArrayIndexScale(VECTOR_KIND);
-
- private static void vectorizedCopy(Object src, int srcPos, Object dest, int destPos, int length, JavaKind baseKind, LocationIdentity locationIdentity) {
- int arrayBaseOffset = arrayBaseOffset(baseKind);
- int elementSize = arrayIndexScale(baseKind);
- long byteLength = (long) length * elementSize;
- long srcOffset = (long) srcPos * elementSize;
- long destOffset = (long) destPos * elementSize;
-
- long preLoopBytes;
- long mainLoopBytes;
- long postLoopBytes;
-
- // We can easily vectorize the loop if both offsets have the same alignment.
- if (byteLength >= VECTOR_SIZE && (srcOffset % VECTOR_SIZE) == (destOffset % VECTOR_SIZE)) {
- preLoopBytes = NumUtil.roundUp(arrayBaseOffset + srcOffset, VECTOR_SIZE) - (arrayBaseOffset + srcOffset);
- postLoopBytes = (byteLength - preLoopBytes) % VECTOR_SIZE;
- mainLoopBytes = byteLength - preLoopBytes - postLoopBytes;
- } else {
- // Does the architecture support unaligned memory accesses?
- if (supportsUnalignedMemoryAccess) {
- preLoopBytes = byteLength % VECTOR_SIZE;
- mainLoopBytes = byteLength - preLoopBytes;
- postLoopBytes = 0;
- } else {
- // No. Let's do element-wise copying.
- preLoopBytes = byteLength;
- mainLoopBytes = 0;
- postLoopBytes = 0;
- }
- }
-
- if (probability(NOT_FREQUENT_PROBABILITY, src == dest) && probability(NOT_FREQUENT_PROBABILITY, srcPos < destPos)) {
- // bad aliased case
- srcOffset += byteLength;
- destOffset += byteLength;
-
- // Post-loop
- for (long i = 0; i < postLoopBytes; i += elementSize) {
- srcOffset -= elementSize;
- destOffset -= elementSize;
- UnsafeCopyNode.copy(src, arrayBaseOffset + srcOffset, dest, arrayBaseOffset + destOffset, baseKind, locationIdentity);
- }
- // Main-loop
- for (long i = 0; i < mainLoopBytes; i += VECTOR_SIZE) {
- srcOffset -= VECTOR_SIZE;
- destOffset -= VECTOR_SIZE;
- UnsafeCopyNode.copy(src, arrayBaseOffset + srcOffset, dest, arrayBaseOffset + destOffset, VECTOR_KIND, locationIdentity);
- }
- // Pre-loop
- for (long i = 0; i < preLoopBytes; i += elementSize) {
- srcOffset -= elementSize;
- destOffset -= elementSize;
- UnsafeCopyNode.copy(src, arrayBaseOffset + srcOffset, dest, arrayBaseOffset + destOffset, baseKind, locationIdentity);
- }
- } else {
- // Pre-loop
- for (long i = 0; i < preLoopBytes; i += elementSize) {
- UnsafeCopyNode.copy(src, arrayBaseOffset + srcOffset, dest, arrayBaseOffset + destOffset, baseKind, locationIdentity);
- srcOffset += elementSize;
- destOffset += elementSize;
- }
- // Main-loop
- for (long i = 0; i < mainLoopBytes; i += VECTOR_SIZE) {
- UnsafeCopyNode.copy(src, arrayBaseOffset + srcOffset, dest, arrayBaseOffset + destOffset, VECTOR_KIND, locationIdentity);
- srcOffset += VECTOR_SIZE;
- destOffset += VECTOR_SIZE;
- }
- // Post-loop
- for (long i = 0; i < postLoopBytes; i += elementSize) {
- UnsafeCopyNode.copy(src, arrayBaseOffset + srcOffset, dest, arrayBaseOffset + destOffset, baseKind, locationIdentity);
- srcOffset += elementSize;
- destOffset += elementSize;
- }
- }
- }
-
- @Fold
- static LocationIdentity getArrayLocation(JavaKind kind) {
- return NamedLocationIdentity.getArrayLocation(kind);
- }
-
- @Snippet
- public static void arraycopyByte(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
- JavaKind kind = JavaKind.Byte;
- vectorizedCopy(src, srcPos, dest, destPos, length, kind, getArrayLocation(kind));
- }
-
- @Snippet
- public static void arraycopyBoolean(boolean[] src, int srcPos, boolean[] dest, int destPos, int length) {
- JavaKind kind = JavaKind.Boolean;
- vectorizedCopy(src, srcPos, dest, destPos, length, kind, getArrayLocation(kind));
- }
-
- @Snippet
- public static void arraycopyChar(char[] src, int srcPos, char[] dest, int destPos, int length) {
- JavaKind kind = JavaKind.Char;
- vectorizedCopy(src, srcPos, dest, destPos, length, kind, getArrayLocation(kind));
- }
-
- @Snippet
- public static void arraycopyShort(short[] src, int srcPos, short[] dest, int destPos, int length) {
- JavaKind kind = JavaKind.Short;
- vectorizedCopy(src, srcPos, dest, destPos, length, kind, getArrayLocation(kind));
- }
-
- @Snippet
- public static void arraycopyInt(int[] src, int srcPos, int[] dest, int destPos, int length) {
- JavaKind kind = JavaKind.Int;
- vectorizedCopy(src, srcPos, dest, destPos, length, kind, getArrayLocation(kind));
- }
-
- @Snippet
- public static void arraycopyFloat(float[] src, int srcPos, float[] dest, int destPos, int length) {
- JavaKind kind = JavaKind.Float;
- vectorizedCopy(src, srcPos, dest, destPos, length, kind, getArrayLocation(kind));
- }
-
- @Snippet
- public static void arraycopyLong(long[] src, int srcPos, long[] dest, int destPos, int length) {
- JavaKind kind = JavaKind.Long;
- vectorizedCopy(src, srcPos, dest, destPos, length, kind, getArrayLocation(kind));
- }
-
- @Snippet
- public static void arraycopyDouble(double[] src, int srcPos, double[] dest, int destPos, int length) {
- JavaKind kind = JavaKind.Double;
- /*
- * TODO atomicity problem on 32-bit architectures: The JVM spec requires double values to be
- * copied atomically, but not long values. For example, on Intel 32-bit this code is not
- * atomic as long as the vector kind remains Kind.Long.
- */
- vectorizedCopy(src, srcPos, dest, destPos, length, kind, getArrayLocation(kind));
- }
-
- /**
- * For this kind, Object, we want to avoid write barriers between writes, but instead have them
- * at the end of the snippet. This is done by using {@link RawStoreNode}, and rely on
- * {@link WriteBarrierAdditionPhase} to put write barriers after the {@link UnsafeArrayCopyNode}
- * with kind Object.
- */
- @Snippet
- public static void arraycopyObject(Object[] src, int srcPos, Object[] dest, int destPos, int length) {
- JavaKind kind = JavaKind.Object;
- final int scale = arrayIndexScale(kind);
- int arrayBaseOffset = arrayBaseOffset(kind);
- LocationIdentity arrayLocation = getArrayLocation(kind);
- if (src == dest && srcPos < destPos) { // bad aliased case
- long start = (long) (length - 1) * scale;
- for (long i = start; i >= 0; i -= scale) {
- Object a = RawLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation);
- RawStoreNode.storeObject(dest, arrayBaseOffset + i + (long) destPos * scale, a, kind, getArrayLocation(kind), false);
- }
- } else {
- long end = (long) length * scale;
- for (long i = 0; i < end; i += scale) {
- Object a = RawLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation);
- RawStoreNode.storeObject(dest, arrayBaseOffset + i + (long) destPos * scale, a, kind, getArrayLocation(kind), false);
- }
- }
- }
-
- @Snippet
- public static void arraycopyPrimitive(Object src, int srcPos, Object dest, int destPos, int length, int layoutHelper) {
- int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG);
- int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG);
-
- UnsignedWord vectorSize = WordFactory.unsigned(VECTOR_SIZE);
- UnsignedWord srcOffset = WordFactory.unsigned(srcPos).shiftLeft(log2ElementSize).add(headerSize);
- UnsignedWord destOffset = WordFactory.unsigned(destPos).shiftLeft(log2ElementSize).add(headerSize);
- UnsignedWord destStart = destOffset;
- UnsignedWord destEnd = destOffset.add(WordFactory.unsigned(length).shiftLeft(log2ElementSize));
-
- UnsignedWord destVectorEnd = null;
- UnsignedWord nonVectorBytes = null;
- UnsignedWord sizeInBytes = WordFactory.unsigned(length).shiftLeft(log2ElementSize);
- if (supportsUnalignedMemoryAccess) {
- nonVectorBytes = sizeInBytes.unsignedRemainder(vectorSize);
- destVectorEnd = destEnd;
- } else {
- boolean inPhase = srcOffset.and((int) VECTOR_SIZE - 1).equal(destOffset.and((int) VECTOR_SIZE - 1));
- boolean hasAtLeastOneVector = sizeInBytes.aboveOrEqual(vectorSize);
- // We must have at least one full vector, otherwise we must copy each byte separately
- if (hasAtLeastOneVector && inPhase) { // If in phase, we can vectorize
- nonVectorBytes = vectorSize.subtract(destStart.unsignedRemainder(vectorSize));
- } else { // fallback is byte-wise
- nonVectorBytes = sizeInBytes;
- }
- destVectorEnd = destEnd.subtract(destEnd.unsignedRemainder(vectorSize));
- }
-
- UnsignedWord destNonVectorEnd = destStart.add(nonVectorBytes);
- while (destOffset.belowThan(destNonVectorEnd)) {
- ObjectAccess.writeByte(dest, destOffset, ObjectAccess.readByte(src, srcOffset, any()), any());
- destOffset = destOffset.add(1);
- srcOffset = srcOffset.add(1);
- }
- // Unsigned destVectorEnd = destEnd.subtract(destEnd.unsignedRemainder(8));
- while (destOffset.belowThan(destVectorEnd)) {
- ObjectAccess.writeWord(dest, destOffset, ObjectAccess.readWord(src, srcOffset, any()), any());
- destOffset = destOffset.add(wordSize());
- srcOffset = srcOffset.add(wordSize());
- }
- // Do the last bytes each when it is required to have absolute alignment.
- while (!supportsUnalignedMemoryAccess && destOffset.belowThan(destEnd)) {
- ObjectAccess.writeByte(dest, destOffset, ObjectAccess.readByte(src, srcOffset, any()), any());
- destOffset = destOffset.add(1);
- srcOffset = srcOffset.add(1);
- }
- }
-
- public static class Templates extends AbstractTemplates {
-
- private final SnippetInfo[] arraycopySnippets;
- private final SnippetInfo genericPrimitiveSnippet;
-
- public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, TargetDescription target) {
- super(options, factories, providers, providers.getSnippetReflection(), target);
-
- arraycopySnippets = new SnippetInfo[JavaKind.values().length];
- arraycopySnippets[JavaKind.Boolean.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyBoolean");
- arraycopySnippets[JavaKind.Byte.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyByte");
- arraycopySnippets[JavaKind.Short.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyShort");
- arraycopySnippets[JavaKind.Char.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyChar");
- arraycopySnippets[JavaKind.Int.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyInt");
- arraycopySnippets[JavaKind.Long.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyLong");
- arraycopySnippets[JavaKind.Float.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyFloat");
- arraycopySnippets[JavaKind.Double.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyDouble");
- arraycopySnippets[JavaKind.Object.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyObject");
-
- genericPrimitiveSnippet = snippet(UnsafeArrayCopySnippets.class, "arraycopyPrimitive");
- }
-
- public void lower(UnsafeArrayCopyNode node, LoweringTool tool) {
- JavaKind elementKind = node.getElementKind();
- SnippetInfo snippet;
- if (elementKind == null) {
- // primitive array of unknown kind
- snippet = genericPrimitiveSnippet;
- } else {
- snippet = arraycopySnippets[elementKind.ordinal()];
- assert snippet != null : "arraycopy snippet for " + elementKind.name() + " not found";
- }
-
- Arguments args = new Arguments(snippet, node.graph().getGuardsStage(), tool.getLoweringStage());
- node.addSnippetArguments(args);
-
- SnippetTemplate template = template(node.getDebug(), args);
- template.instantiate(providers.getMetaAccess(), node, DEFAULT_REPLACER, args);
- }
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -54,6 +54,7 @@
import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
import org.graalvm.compiler.replacements.Snippets;
+import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.code.TargetDescription;
public class ProbabilisticProfileSnippets implements Snippets {
@@ -64,22 +65,22 @@
}
@Snippet
- public static int notificationMask(int freqLog, int probLog) {
- int probabilityMask = (1 << probLog) - 1;
+ public static int notificationMask(int freqLog, int probLog, int stepLog) {
int frequencyMask = (1 << freqLog) - 1;
- return frequencyMask & ~probabilityMask;
+ int stepMask = (1 << (stepLog + probLog)) - 1;
+ return frequencyMask & ~stepMask;
}
@NodeIntrinsic(ForeignCallNode.class)
public static native void methodInvocationEvent(@ConstantNodeParameter ForeignCallDescriptor descriptor, MethodCountersPointer counters);
@Snippet
- public static void profileMethodEntryWithProbability(MethodCountersPointer counters, int random, @ConstantParameter int freqLog, @ConstantParameter int probLog) {
+ public static void profileMethodEntryWithProbability(MethodCountersPointer counters, int random, int step, int stepLog, @ConstantParameter int freqLog, @ConstantParameter int probLog) {
if (probability(1.0 / (1 << probLog), shouldProfile(probLog, random))) {
- int counterValue = counters.readInt(config(INJECTED_VMCONFIG).invocationCounterOffset) + (config(INJECTED_VMCONFIG).invocationCounterIncrement << probLog);
+ int counterValue = counters.readInt(config(INJECTED_VMCONFIG).invocationCounterOffset) + ((config(INJECTED_VMCONFIG).invocationCounterIncrement * step) << probLog);
counters.writeInt(config(INJECTED_VMCONFIG).invocationCounterOffset, counterValue);
if (freqLog >= 0) {
- int mask = notificationMask(freqLog, probLog);
+ int mask = notificationMask(freqLog, probLog, stepLog);
if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
methodInvocationEvent(HotSpotBackend.INVOCATION_EVENT, counters);
}
@@ -91,11 +92,12 @@
public static native void methodBackedgeEvent(@ConstantNodeParameter ForeignCallDescriptor descriptor, MethodCountersPointer counters, int bci, int targetBci);
@Snippet
- public static void profileBackedgeWithProbability(MethodCountersPointer counters, int random, @ConstantParameter int freqLog, @ConstantParameter int probLog, int bci, int targetBci) {
+ public static void profileBackedgeWithProbability(MethodCountersPointer counters, int random, int step, int stepLog, @ConstantParameter int freqLog, @ConstantParameter int probLog, int bci,
+ int targetBci) {
if (probability(1.0 / (1 << probLog), shouldProfile(probLog, random))) {
- int counterValue = counters.readInt(config(INJECTED_VMCONFIG).backedgeCounterOffset) + (config(INJECTED_VMCONFIG).invocationCounterIncrement << probLog);
+ int counterValue = counters.readInt(config(INJECTED_VMCONFIG).backedgeCounterOffset) + ((config(INJECTED_VMCONFIG).invocationCounterIncrement * step) << probLog);
counters.writeInt(config(INJECTED_VMCONFIG).backedgeCounterOffset, counterValue);
- int mask = notificationMask(freqLog, probLog);
+ int mask = notificationMask(freqLog, probLog, stepLog);
if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
methodBackedgeEvent(HotSpotBackend.BACKEDGE_EVENT, counters, bci, targetBci);
}
@@ -103,10 +105,11 @@
}
@Snippet
- public static void profileConditionalBackedgeWithProbability(MethodCountersPointer counters, int random, @ConstantParameter int freqLog, @ConstantParameter int probLog, boolean branchCondition,
+ public static void profileConditionalBackedgeWithProbability(MethodCountersPointer counters, int random, int step, int stepLog, @ConstantParameter int freqLog,
+ @ConstantParameter int probLog, boolean branchCondition,
int bci, int targetBci) {
if (branchCondition) {
- profileBackedgeWithProbability(counters, random, freqLog, probLog, bci, targetBci);
+ profileBackedgeWithProbability(counters, random, step, stepLog, freqLog, probLog, bci, targetBci);
}
}
@@ -124,6 +127,8 @@
StructuredGraph graph = profileNode.graph();
LoadMethodCountersNode counters = graph.unique(new LoadMethodCountersNode(profileNode.getProfiledMethod()));
+ ConstantNode step = ConstantNode.forInt(profileNode.getStep(), graph);
+ ConstantNode stepLog = ConstantNode.forInt(CodeUtil.log2(profileNode.getStep()), graph);
if (profileNode instanceof ProfileBranchNode) {
// Backedge event
@@ -132,8 +137,11 @@
Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage());
ConstantNode bci = ConstantNode.forInt(profileBranchNode.bci(), graph);
ConstantNode targetBci = ConstantNode.forInt(profileBranchNode.targetBci(), graph);
+
args.add("counters", counters);
args.add("random", profileBranchNode.getRandom());
+ args.add("step", step);
+ args.add("stepLog", stepLog);
args.addConst("freqLog", profileBranchNode.getNotificationFreqLog());
args.addConst("probLog", profileBranchNode.getProbabilityLog());
if (profileBranchNode.hasCondition()) {
@@ -148,8 +156,11 @@
ProfileInvokeNode profileInvokeNode = (ProfileInvokeNode) profileNode;
// Method invocation event
Arguments args = new Arguments(profileMethodEntryWithProbability, graph.getGuardsStage(), tool.getLoweringStage());
+
args.add("counters", counters);
args.add("random", profileInvokeNode.getRandom());
+ args.add("step", step);
+ args.add("stepLog", stepLog);
args.addConst("freqLog", profileInvokeNode.getNotificationFreqLog());
args.addConst("probLog", profileInvokeNode.getProbabilityLog());
SnippetTemplate template = template(graph.getDebug(), args);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -54,6 +54,7 @@
import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
import org.graalvm.compiler.replacements.Snippets;
+import jdk.vm.ci.code.CodeUtil;
import jdk.vm.ci.code.TargetDescription;
public class ProfileSnippets implements Snippets {
@@ -61,12 +62,19 @@
public static native void methodInvocationEvent(@ConstantNodeParameter ForeignCallDescriptor descriptor, MethodCountersPointer counters);
@Snippet
- public static void profileMethodEntry(MethodCountersPointer counters, @ConstantParameter int freqLog) {
- int counterValue = counters.readInt(config(INJECTED_VMCONFIG).invocationCounterOffset) + config(INJECTED_VMCONFIG).invocationCounterIncrement;
+ protected static int notificationMask(int freqLog, int stepLog) {
+ int stepMask = (1 << stepLog) - 1;
+ int frequencyMask = (1 << freqLog) - 1;
+ return frequencyMask & ~stepMask;
+ }
+
+ @Snippet
+ public static void profileMethodEntry(MethodCountersPointer counters, int step, int stepLog, @ConstantParameter int freqLog) {
+ int counterValue = counters.readInt(config(INJECTED_VMCONFIG).invocationCounterOffset) + config(INJECTED_VMCONFIG).invocationCounterIncrement * step;
counters.writeInt(config(INJECTED_VMCONFIG).invocationCounterOffset, counterValue);
if (freqLog >= 0) {
- final int frequencyMask = (1 << freqLog) - 1;
- if (probability(SLOW_PATH_PROBABILITY, (counterValue & (frequencyMask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
+ final int mask = notificationMask(freqLog, stepLog);
+ if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
methodInvocationEvent(HotSpotBackend.INVOCATION_EVENT, counters);
}
}
@@ -76,19 +84,19 @@
public static native void methodBackedgeEvent(@ConstantNodeParameter ForeignCallDescriptor descriptor, MethodCountersPointer counters, int bci, int targetBci);
@Snippet
- public static void profileBackedge(MethodCountersPointer counters, @ConstantParameter int freqLog, int bci, int targetBci) {
- int counterValue = counters.readInt(config(INJECTED_VMCONFIG).backedgeCounterOffset) + config(INJECTED_VMCONFIG).invocationCounterIncrement;
+ public static void profileBackedge(MethodCountersPointer counters, int step, int stepLog, @ConstantParameter int freqLog, int bci, int targetBci) {
+ int counterValue = counters.readInt(config(INJECTED_VMCONFIG).backedgeCounterOffset) + config(INJECTED_VMCONFIG).invocationCounterIncrement * step;
counters.writeInt(config(INJECTED_VMCONFIG).backedgeCounterOffset, counterValue);
- final int frequencyMask = (1 << freqLog) - 1;
- if (probability(SLOW_PATH_PROBABILITY, (counterValue & (frequencyMask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
+ final int mask = notificationMask(freqLog, stepLog);
+ if (probability(SLOW_PATH_PROBABILITY, (counterValue & (mask << config(INJECTED_VMCONFIG).invocationCounterShift)) == 0)) {
methodBackedgeEvent(HotSpotBackend.BACKEDGE_EVENT, counters, bci, targetBci);
}
}
@Snippet
- public static void profileConditionalBackedge(MethodCountersPointer counters, @ConstantParameter int freqLog, boolean branchCondition, int bci, int targetBci) {
+ public static void profileConditionalBackedge(MethodCountersPointer counters, int step, int stepLog, @ConstantParameter int freqLog, boolean branchCondition, int bci, int targetBci) {
if (branchCondition) {
- profileBackedge(counters, freqLog, bci, targetBci);
+ profileBackedge(counters, step, stepLog, freqLog, bci, targetBci);
}
}
@@ -104,6 +112,8 @@
public void lower(ProfileNode profileNode, LoweringTool tool) {
StructuredGraph graph = profileNode.graph();
LoadMethodCountersNode counters = graph.unique(new LoadMethodCountersNode(profileNode.getProfiledMethod()));
+ ConstantNode step = ConstantNode.forInt(profileNode.getStep(), graph);
+ ConstantNode stepLog = ConstantNode.forInt(CodeUtil.log2(profileNode.getStep()), graph);
if (profileNode instanceof ProfileBranchNode) {
// Backedge event
@@ -113,6 +123,8 @@
ConstantNode bci = ConstantNode.forInt(profileBranchNode.bci(), graph);
ConstantNode targetBci = ConstantNode.forInt(profileBranchNode.targetBci(), graph);
args.add("counters", counters);
+ args.add("step", step);
+ args.add("stepLog", stepLog);
args.addConst("freqLog", profileBranchNode.getNotificationFreqLog());
if (profileBranchNode.hasCondition()) {
args.add("branchCondition", profileBranchNode.branchCondition());
@@ -127,6 +139,8 @@
// Method invocation event
Arguments args = new Arguments(profileMethodEntry, graph.getGuardsStage(), tool.getLoweringStage());
args.add("counters", counters);
+ args.add("step", step);
+ args.add("stepLog", stepLog);
args.addConst("freqLog", profileInvokeNode.getNotificationFreqLog());
SnippetTemplate template = template(graph.getDebug(), args);
template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java Thu Nov 16 10:45:42 2017 -0800
@@ -33,6 +33,7 @@
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeShift;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useCMSIncrementalMode;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize;
import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH;
import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.formatArray;
@@ -122,7 +123,7 @@
// check that array length is small enough for fast path.
Word thread = registerAsWord(threadRegister);
boolean inlineContiguousAllocationSupported = GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported();
- if (inlineContiguousAllocationSupported && length >= 0 && length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) {
+ if (inlineContiguousAllocationSupported && !useCMSIncrementalMode(INJECTED_VMCONFIG) && length >= 0 && length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) {
Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging(options));
if (memory.notEqual(0)) {
if (logging(options)) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java Thu Nov 16 10:45:42 2017 -0800
@@ -53,6 +53,7 @@
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabRefillWasteLimitOffset;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabSlowAllocationsOffset;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.tlabStats;
+import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useCMSIncrementalMode;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useG1GC;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.useTLAB;
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize;
@@ -147,7 +148,7 @@
*/
Word thread = registerAsWord(threadRegister);
boolean inlineContiguousAllocationSupported = GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported();
- if (!forceSlowPath(options) && inlineContiguousAllocationSupported) {
+ if (!forceSlowPath(options) && inlineContiguousAllocationSupported && !useCMSIncrementalMode(INJECTED_VMCONFIG)) {
if (isInstanceKlassFullyInitialized(hub)) {
int sizeInBytes = readLayoutHelper(hub);
Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging(options));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Thu Nov 16 10:45:42 2017 -0800
@@ -342,7 +342,7 @@
import org.graalvm.compiler.nodes.calc.AndNode;
import org.graalvm.compiler.nodes.calc.CompareNode;
import org.graalvm.compiler.nodes.calc.ConditionalNode;
-import org.graalvm.compiler.nodes.calc.DivNode;
+import org.graalvm.compiler.nodes.calc.FloatDivNode;
import org.graalvm.compiler.nodes.calc.FloatConvertNode;
import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
@@ -374,7 +374,6 @@
import org.graalvm.compiler.nodes.extended.StateSplitProxyNode;
import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
@@ -383,6 +382,7 @@
import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvokeDynamicPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin;
import org.graalvm.compiler.nodes.java.ArrayLengthNode;
@@ -435,6 +435,7 @@
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.Signature;
import jdk.vm.ci.meta.TriState;
+import org.graalvm.compiler.core.common.type.IntegerStamp;
/**
* The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
@@ -1036,7 +1037,7 @@
deopt.updateNodeSourcePosition(() -> createBytecodePosition());
}
- private AbstractBeginNode handleException(ValueNode exceptionObject, int bci) {
+ private AbstractBeginNode handleException(ValueNode exceptionObject, int bci, boolean deoptimizeOnly) {
assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci";
debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci)));
@@ -1058,8 +1059,12 @@
this.controlFlowSplit = true;
FixedWithNextNode finishedDispatch = finishInstruction(dispatchBegin, dispatchState);
- createHandleExceptionTarget(finishedDispatch, bci, dispatchState);
-
+ if (deoptimizeOnly) {
+ DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter));
+ dispatchBegin.setNext(BeginNode.begin(deoptimizeNode));
+ } else {
+ createHandleExceptionTarget(finishedDispatch, bci, dispatchState);
+ }
return dispatchBegin;
}
@@ -1111,7 +1116,7 @@
}
protected ValueNode genFloatDiv(ValueNode x, ValueNode y) {
- return DivNode.create(x, y);
+ return FloatDivNode.create(x, y);
}
protected ValueNode genFloatRem(ValueNode x, ValueNode y) {
@@ -1215,7 +1220,7 @@
ValueNode exception = frameState.pop(JavaKind.Object);
FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true));
ValueNode nonNullException = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp().join(objectNonNull()), nullCheck));
- lastInstr.setNext(handleException(nonNullException, bci()));
+ lastInstr.setNext(handleException(nonNullException, bci(), false));
}
protected LogicNode createInstanceOf(TypeReference type, ValueNode object) {
@@ -1275,12 +1280,12 @@
}
BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class));
AbstractBeginNode falseSucc = graph.add(new BeginNode());
- ValueNode nonNullReceiver = graph.addOrUnique(PiNode.create(receiver, objectNonNull(), falseSucc));
+ ValueNode nonNullReceiver = graph.addOrUniqueWithInputs(PiNode.create(receiver, objectNonNull(), falseSucc));
append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(receiver)), exception, falseSucc, SLOW_PATH_PROBABILITY));
lastInstr = falseSucc;
exception.setStateAfter(createFrameState(bci(), exception));
- exception.setNext(handleException(exception, bci()));
+ exception.setNext(handleException(exception, bci(), false));
EXPLICIT_EXCEPTIONS.increment(debug);
return nonNullReceiver;
}
@@ -1292,7 +1297,7 @@
lastInstr = trueSucc;
exception.setStateAfter(createFrameState(bci(), exception));
- exception.setNext(handleException(exception, bci()));
+ exception.setNext(handleException(exception, bci(), false));
}
protected ValueNode genArrayLength(ValueNode x) {
@@ -1532,8 +1537,8 @@
@Override
public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) {
BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
- boolean withExceptionEdge = intrinsicCallSiteParser == null ? !omitInvokeExceptionEdge(null) : !intrinsicCallSiteParser.omitInvokeExceptionEdge(null);
- createNonInlinedInvoke(withExceptionEdge, bci(), callTarget, resultType);
+ ExceptionEdgeAction exceptionEdgeAction = intrinsicCallSiteParser == null ? getActionForInvokeExceptionEdge(null) : intrinsicCallSiteParser.getActionForInvokeExceptionEdge(null);
+ createNonInlinedInvoke(exceptionEdgeAction, bci(), callTarget, resultType);
}
protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) {
@@ -1603,7 +1608,7 @@
int invokeBci = bci();
JavaTypeProfile profile = getProfileForInvoke(invokeKind);
- boolean withExceptionEdge = !omitInvokeExceptionEdge(inlineInfo);
+ ExceptionEdgeAction edgeAction = getActionForInvokeExceptionEdge(inlineInfo);
boolean partialIntrinsicExit = false;
if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) {
partialIntrinsicExit = true;
@@ -1614,7 +1619,7 @@
// must use the same context as the call to the intrinsic.
invokeBci = intrinsicCallSiteParser.bci();
profile = intrinsicCallSiteParser.getProfileForInvoke(invokeKind);
- withExceptionEdge = !intrinsicCallSiteParser.omitInvokeExceptionEdge(inlineInfo);
+ edgeAction = intrinsicCallSiteParser.getActionForInvokeExceptionEdge(inlineInfo);
} else {
// We are parsing the intrinsic for the root compilation or for inlining,
// This call is a partial intrinsic exit, and we do not have profile information
@@ -1624,7 +1629,7 @@
assert intrinsicContext.isPostParseInlined();
invokeBci = BytecodeFrame.UNKNOWN_BCI;
profile = null;
- withExceptionEdge = graph.method().getAnnotation(Snippet.class) == null;
+ edgeAction = graph.method().getAnnotation(Snippet.class) == null ? ExceptionEdgeAction.INCLUDE_AND_HANDLE : ExceptionEdgeAction.OMIT;
}
if (originalMethod.isStatic()) {
@@ -1637,10 +1642,10 @@
Signature sig = originalMethod.getSignature();
returnType = sig.getReturnType(method.getDeclaringClass());
resultType = sig.getReturnKind();
- assert checkPartialIntrinsicExit(intrinsicCallSiteParser == null ? null : intrinsicCallSiteParser.currentInvoke.args, args);
+ assert intrinsicContext.allowPartialIntrinsicArgumentMismatch() || checkPartialIntrinsicExit(intrinsicCallSiteParser == null ? null : intrinsicCallSiteParser.currentInvoke.args, args);
targetMethod = originalMethod;
}
- Invoke invoke = createNonInlinedInvoke(withExceptionEdge, invokeBci, args, targetMethod, invokeKind, resultType, returnType, profile);
+ Invoke invoke = createNonInlinedInvoke(edgeAction, invokeBci, args, targetMethod, invokeKind, resultType, returnType, profile);
if (partialIntrinsicExit) {
// This invoke must never be later inlined as it might select the intrinsic graph.
// Until there is a mechanism to guarantee that any late inlining will not select
@@ -1698,14 +1703,14 @@
} else {
for (int i = 0; i < recursiveArgs.length; i++) {
ValueNode arg = GraphUtil.unproxify(recursiveArgs[i]);
- assert arg instanceof ParameterNode && ((ParameterNode) arg).index() == i : String.format("argument %d of call denoting partial intrinsic exit should be a %s with index %d, not %s", i,
- ParameterNode.class.getSimpleName(), i, arg);
+ assert arg instanceof ParameterNode && ((ParameterNode) arg).index() == i : String.format("argument %d of call denoting partial intrinsic exit should be a %s with index %d, not %s",
+ i, ParameterNode.class.getSimpleName(), i, arg);
}
}
return true;
}
- protected Invoke createNonInlinedInvoke(boolean withExceptionEdge, int invokeBci, ValueNode[] invokeArgs, ResolvedJavaMethod targetMethod,
+ protected Invoke createNonInlinedInvoke(ExceptionEdgeAction exceptionEdge, int invokeBci, ValueNode[] invokeArgs, ResolvedJavaMethod targetMethod,
InvokeKind invokeKind, JavaKind resultType, JavaType returnType, JavaTypeProfile profile) {
StampPair returnStamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, returnType, false);
@@ -1714,7 +1719,7 @@
}
MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, targetMethod, invokeArgs, returnStamp, profile));
- Invoke invoke = createNonInlinedInvoke(withExceptionEdge, invokeBci, callTarget, resultType);
+ Invoke invoke = createNonInlinedInvoke(exceptionEdge, invokeBci, callTarget, resultType);
for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) {
plugin.notifyNotInlined(this, targetMethod, invoke);
@@ -1723,11 +1728,11 @@
return invoke;
}
- protected Invoke createNonInlinedInvoke(boolean withExceptionEdge, int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
- if (!withExceptionEdge) {
+ protected Invoke createNonInlinedInvoke(ExceptionEdgeAction exceptionEdge, int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
+ if (exceptionEdge == ExceptionEdgeAction.OMIT) {
return createInvoke(invokeBci, callTarget, resultType);
} else {
- Invoke invoke = createInvokeWithException(invokeBci, callTarget, resultType);
+ Invoke invoke = createInvokeWithException(invokeBci, callTarget, resultType, exceptionEdge);
AbstractBeginNode beginNode = graph.add(KillingBeginNode.create(LocationIdentity.any()));
invoke.setNext(beginNode);
lastInstr = beginNode;
@@ -1736,20 +1741,29 @@
}
/**
- * If the method returns true, the invocation of the given {@link MethodCallTargetNode call
- * target} does not need an exception edge.
+ * Describes what should be done with the exception edge of an invocation. The edge can be
+ * omitted or included. An included edge can handle the exception or transfer execution to the
+ * interpreter for handling (deoptimize).
*/
- protected boolean omitInvokeExceptionEdge(InlineInfo lastInlineInfo) {
+ protected enum ExceptionEdgeAction {
+ OMIT,
+ INCLUDE_AND_HANDLE,
+ INCLUDE_AND_DEOPTIMIZE
+ }
+
+ protected ExceptionEdgeAction getActionForInvokeExceptionEdge(InlineInfo lastInlineInfo) {
if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION) {
- return false;
+ return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
} else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_NO_EXCEPTION) {
- return true;
+ return ExceptionEdgeAction.OMIT;
+ } else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_DEOPTIMIZE_ON_EXCEPTION) {
+ return ExceptionEdgeAction.INCLUDE_AND_DEOPTIMIZE;
} else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.CheckAll) {
- return false;
+ return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
} else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.ExplicitOnly) {
- return false;
+ return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
} else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) {
- return true;
+ return ExceptionEdgeAction.OMIT;
} else {
assert graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile;
// be conservative if information was not recorded (could result in endless
@@ -1759,12 +1773,12 @@
if (profilingInfo != null) {
TriState exceptionSeen = profilingInfo.getExceptionSeen(bci());
if (exceptionSeen == TriState.FALSE) {
- return true;
+ return ExceptionEdgeAction.OMIT;
}
}
}
}
- return false;
+ return ExceptionEdgeAction.INCLUDE_AND_HANDLE;
}
}
@@ -1887,7 +1901,7 @@
if (newProfile != profile) {
if (newProfile.getTypes().length == 0) {
// All profiled types select the intrinsic so
- // emit a fixed guard instead of a if-then-else.
+ // emit a fixed guard instead of an if-then-else.
lastInstr = append(new FixedGuardNode(compare, TypeCheckedInliningViolated, InvalidateReprofile, false));
return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, null, null);
}
@@ -1966,7 +1980,7 @@
}
lastInstr = intrinsicGuard.nonIntrinsicBranch;
- createNonInlinedInvoke(omitInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile);
+ createNonInlinedInvoke(getActionForInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile);
EndNode nonIntrinsicEnd = append(new EndNode());
AbstractMergeNode mergeNode = graph.add(new MergeNode());
@@ -2303,7 +2317,7 @@
if (calleeBeforeUnwindNode != null) {
ValueNode calleeUnwindValue = parser.getUnwindValue();
assert calleeUnwindValue != null;
- calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci()));
+ calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci(), false));
}
}
}
@@ -2319,7 +2333,7 @@
return invoke;
}
- protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallTargetNode callTarget, JavaKind resultType) {
+ protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallTargetNode callTarget, JavaKind resultType, ExceptionEdgeAction exceptionEdgeAction) {
if (currentBlock != null && stream.nextBCI() > currentBlock.endBci) {
/*
* Clear non-live locals early so that the exception handler entry gets the cleared
@@ -2328,7 +2342,7 @@
frameState.clearNonLiveLocals(currentBlock, liveness, false);
}
- AbstractBeginNode exceptionEdge = handleException(null, bci());
+ AbstractBeginNode exceptionEdge = handleException(null, bci(), exceptionEdgeAction == ExceptionEdgeAction.INCLUDE_AND_DEOPTIMIZE);
InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, invokeBci));
frameState.pushReturn(resultType, invoke);
invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke));
@@ -2359,20 +2373,43 @@
}
}
+ ValueNode realReturnVal = processReturnValue(returnVal, returnKind);
+
frameState.setRethrowException(false);
frameState.clearStack();
- beforeReturn(returnVal, returnKind);
+ beforeReturn(realReturnVal, returnKind);
if (parent == null) {
- append(new ReturnNode(returnVal));
+ append(new ReturnNode(realReturnVal));
} else {
if (returnDataList == null) {
returnDataList = new ArrayList<>();
}
- returnDataList.add(new ReturnToCallerData(returnVal, lastInstr));
+ returnDataList.add(new ReturnToCallerData(realReturnVal, lastInstr));
lastInstr = null;
}
}
+ private ValueNode processReturnValue(ValueNode value, JavaKind kind) {
+ JavaKind returnKind = method.getSignature().getReturnKind();
+ if (kind != returnKind) {
+ // sub-word integer
+ assert returnKind.isNumericInteger() && returnKind.getStackKind() == JavaKind.Int;
+ IntegerStamp stamp = (IntegerStamp) value.stamp();
+
+ // the bytecode verifier doesn't check that the value is in the correct range
+ if (stamp.lowerBound() < returnKind.getMinValue() || returnKind.getMaxValue() < stamp.upperBound()) {
+ ValueNode narrow = append(genNarrow(value, returnKind.getBitCount()));
+ if (returnKind.isUnsigned()) {
+ return append(genZeroExtend(narrow, 32));
+ } else {
+ return append(genSignExtend(narrow, 32));
+ }
+ }
+ }
+
+ return value;
+ }
+
private void beforeReturn(ValueNode x, JavaKind kind) {
if (graph.method() != null && graph.method().isJavaLangObjectInit()) {
/*
@@ -2794,6 +2831,8 @@
}
private void createExceptionDispatch(ExceptionDispatchBlock block) {
+ lastInstr = finishInstruction(lastInstr, frameState);
+
assert frameState.stackSize() == 1 : frameState;
if (block.handler.isCatchAll()) {
assert block.getSuccessorCount() == 1;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java Thu Nov 16 10:45:42 2017 -0800
@@ -207,7 +207,7 @@
receiver = new ParameterNode(javaIndex, receiverStamp);
}
- locals[javaIndex] = graph.addOrUnique(receiver);
+ locals[javaIndex] = graph.addOrUniqueWithInputs(receiver);
javaIndex = 1;
index = 1;
}
@@ -241,7 +241,7 @@
param = new ParameterNode(index, stamp);
}
- locals[javaIndex] = graph.addOrUnique(param);
+ locals[javaIndex] = graph.addOrUniqueWithInputs(param);
javaIndex++;
if (kind.needsTwoSlots()) {
locals[javaIndex] = TWO_SLOT_MARKER;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/ConditionalElimination02.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/ConditionalElimination02.java Thu Nov 16 10:45:42 2017 -0800
@@ -29,6 +29,9 @@
import org.junit.Test;
import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.phases.OptimisticOptimizations;
+import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
public class ConditionalElimination02 extends JTTTest {
@@ -59,6 +62,14 @@
return -1;
}
+ /**
+ * These tests assume all code paths are reachable so disable profile based dead code removal.
+ */
+ @Override
+ protected HighTierContext getDefaultHighTierContext() {
+ return new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL.remove(Optimization.RemoveNeverExecutedCode));
+ }
+
@Test
public void run0() throws Throwable {
runTest(EnumSet.of(DeoptimizationReason.NullCheckException), "test", new A(5), false, false);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/Fold_Double04.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, 2017, 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 org.graalvm.compiler.jtt.optimize;
+
+import org.junit.Test;
+
+import org.graalvm.compiler.jtt.JTTTest;
+
+/*
+ * Tests constant folding of double operations.
+ */
+public class Fold_Double04 extends JTTTest {
+
+ // Contrived check whether both arguments are the same kind of zero
+ public static boolean test(double x, double y) {
+ if (x == 0) {
+ if (1 / x == Double.NEGATIVE_INFINITY) {
+ return 1 / y == Double.NEGATIVE_INFINITY;
+ } else {
+ return 1 / y == Double.POSITIVE_INFINITY;
+ }
+ }
+ return false;
+ }
+
+ @Test
+ public void run0() throws Throwable {
+ runTest("test", -0d, -0d);
+ }
+
+ @Test
+ public void run1() throws Throwable {
+ runTest("test", -0d, 0d);
+ }
+
+ @Test
+ public void run2() throws Throwable {
+ runTest("test", 0d, -0d);
+ }
+
+ @Test
+ public void run3() throws Throwable {
+ runTest("test", 0d, 0d);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/Fold_Float03.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, 2017, 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 org.graalvm.compiler.jtt.optimize;
+
+import org.junit.Test;
+
+import org.graalvm.compiler.jtt.JTTTest;
+
+/*
+ * Tests constant folding of float operations.
+ */
+public class Fold_Float03 extends JTTTest {
+
+ // Contrived check whether both arguments are the same kind of zero
+ public static boolean test(float x, float y) {
+ if (x == 0) {
+ if (1 / x == Float.NEGATIVE_INFINITY) {
+ return 1 / y == Float.NEGATIVE_INFINITY;
+ } else {
+ return 1 / y == Float.POSITIVE_INFINITY;
+ }
+ }
+ return false;
+ }
+
+ @Test
+ public void run0() throws Throwable {
+ runTest("test", -0f, -0f);
+ }
+
+ @Test
+ public void run1() throws Throwable {
+ runTest("test", -0f, 0f);
+ }
+
+ @Test
+ public void run2() throws Throwable {
+ runTest("test", 0f, -0f);
+ }
+
+ @Test
+ public void run3() throws Throwable {
+ runTest("test", 0f, 0f);
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java Thu Nov 16 10:45:42 2017 -0800
@@ -37,6 +37,7 @@
import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
@@ -132,12 +133,19 @@
masm.leaq(array2, new AMD64Address(asRegister(array2Value), arrayBaseOffset));
// Get array length in bytes.
- masm.imull(length, asRegister(lengthValue), arrayIndexScale);
+ masm.movl(length, asRegister(lengthValue));
+
+ if (arrayIndexScale > 1) {
+ masm.shll(length, NumUtil.log2Ceil(arrayIndexScale)); // scale length
+ }
+
masm.movl(result, length); // copy
if (supportsAVX2(crb.target)) {
emitAVXCompare(crb, masm, result, array1, array2, length, trueLabel, falseLabel);
} else if (supportsSSE41(crb.target)) {
+ // this code is used for AVX as well because our backend correctly ensures that
+ // VEX-prefixed instructions are emitted if AVX is supported
emitSSE41Compare(crb, masm, result, array1, array2, length, trueLabel, falseLabel);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,21 +22,21 @@
*/
package org.graalvm.compiler.lir.amd64;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static jdk.vm.ci.code.ValueUtil.isRegister;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.CONST;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
-import static jdk.vm.ci.code.ValueUtil.isRegister;
import org.graalvm.compiler.asm.Label;
-import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.code.CompilationResult.JumpTable;
+import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.lir.LIRInstructionClass;
@@ -312,6 +312,42 @@
}
}
+ @Opcode("SETcc")
+ public static final class CondSetOp extends AMD64LIRInstruction {
+ public static final LIRInstructionClass<CondSetOp> TYPE = LIRInstructionClass.create(CondSetOp.class);
+ @Def({REG, HINT}) protected Value result;
+ private final ConditionFlag condition;
+
+ public CondSetOp(Variable result, Condition condition) {
+ super(TYPE);
+ this.result = result;
+ this.condition = intCond(condition);
+ }
+
+ @Override
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+ setcc(masm, result, condition);
+ }
+ }
+
+ @Opcode("SETcc")
+ public static final class FloatCondSetOp extends AMD64LIRInstruction {
+ public static final LIRInstructionClass<FloatCondSetOp> TYPE = LIRInstructionClass.create(FloatCondSetOp.class);
+ @Def({REG, HINT}) protected Value result;
+ private final ConditionFlag condition;
+
+ public FloatCondSetOp(Variable result, Condition condition) {
+ super(TYPE);
+ this.result = result;
+ this.condition = floatCond(condition);
+ }
+
+ @Override
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+ setcc(masm, result, condition);
+ }
+ }
+
@Opcode("CMOVE")
public static final class CondMoveOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<CondMoveOp> TYPE = LIRInstructionClass.create(CondMoveOp.class);
@@ -418,6 +454,21 @@
}
}
+ private static void setcc(AMD64MacroAssembler masm, Value result, ConditionFlag cond) {
+ switch ((AMD64Kind) result.getPlatformKind()) {
+ case BYTE:
+ case WORD:
+ case DWORD:
+ masm.setl(cond, asRegister(result));
+ break;
+ case QWORD:
+ masm.setq(cond, asRegister(result));
+ break;
+ default:
+ throw GraalError.shouldNotReachHere();
+ }
+ }
+
private static ConditionFlag intCond(Condition cond) {
switch (cond) {
case EQ:
@@ -464,6 +515,10 @@
}
}
+ public static boolean trueOnUnordered(Condition condition) {
+ return trueOnUnordered(floatCond(condition));
+ }
+
private static boolean trueOnUnordered(ConditionFlag condition) {
switch (condition) {
case AboveEqual:
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,8 +22,11 @@
*/
package org.graalvm.compiler.lir.amd64;
+import static org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag.Equal;
+import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.UNINITIALIZED;
@@ -35,12 +38,16 @@
import static jdk.vm.ci.code.ValueUtil.isRegister;
import static jdk.vm.ci.code.ValueUtil.isStackSlot;
+import org.graalvm.compiler.asm.Label;
+import org.graalvm.compiler.core.common.CompressEncoding;
+import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.core.common.spi.LIRKindTool;
import org.graalvm.compiler.core.common.type.DataPointerConstant;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.lir.LIRFrameState;
@@ -740,4 +747,110 @@
throw GraalError.shouldNotReachHere("Unknown result Kind: " + result.getPlatformKind());
}
}
+
+ public abstract static class Pointer extends AMD64LIRInstruction {
+ protected final LIRKindTool lirKindTool;
+ protected final CompressEncoding encoding;
+ protected final boolean nonNull;
+
+ @Def({REG, HINT}) private AllocatableValue result;
+ @Use({REG}) private AllocatableValue input;
+ @Alive({REG, ILLEGAL}) private AllocatableValue baseRegister;
+
+ protected Pointer(LIRInstructionClass<? extends Pointer> type, AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull,
+ LIRKindTool lirKindTool) {
+ super(type);
+ this.result = result;
+ this.input = input;
+ this.baseRegister = baseRegister;
+ this.encoding = encoding;
+ this.nonNull = nonNull;
+ this.lirKindTool = lirKindTool;
+ }
+
+ protected boolean hasBase(CompilationResultBuilder crb) {
+ return GeneratePIC.getValue(crb.getOptions()) || encoding.hasBase();
+ }
+
+ protected final Register getResultRegister() {
+ return asRegister(result);
+ }
+
+ protected final Register getBaseRegister() {
+ return asRegister(baseRegister);
+ }
+
+ protected final int getShift() {
+ return encoding.getShift();
+ }
+
+ protected final void move(LIRKind kind, CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+ AMD64Move.move((AMD64Kind) kind.getPlatformKind(), crb, masm, result, input);
+ }
+ }
+
+ public static final class CompressPointer extends Pointer {
+ public static final LIRInstructionClass<CompressPointer> TYPE = LIRInstructionClass.create(CompressPointer.class);
+
+ public CompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) {
+ super(TYPE, result, input, baseRegister, encoding, nonNull, lirKindTool);
+ }
+
+ @Override
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+ move(lirKindTool.getObjectKind(), crb, masm);
+
+ Register resReg = getResultRegister();
+ if (hasBase(crb)) {
+ Register baseReg = getBaseRegister();
+ if (!nonNull) {
+ masm.testq(resReg, resReg);
+ masm.cmovq(Equal, resReg, baseReg);
+ }
+ masm.subq(resReg, baseReg);
+ }
+
+ int shift = getShift();
+ if (shift != 0) {
+ masm.shrq(resReg, shift);
+ }
+ }
+ }
+
+ public static final class UncompressPointer extends Pointer {
+ public static final LIRInstructionClass<UncompressPointer> TYPE = LIRInstructionClass.create(UncompressPointer.class);
+
+ public UncompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) {
+ super(TYPE, result, input, baseRegister, encoding, nonNull, lirKindTool);
+ }
+
+ @Override
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+ move(lirKindTool.getNarrowOopKind(), crb, masm);
+
+ Register resReg = getResultRegister();
+ int shift = getShift();
+ if (shift != 0) {
+ masm.shlq(resReg, shift);
+ }
+
+ if (hasBase(crb)) {
+ Register baseReg = getBaseRegister();
+ if (nonNull) {
+ masm.addq(resReg, baseReg);
+ return;
+ }
+
+ if (shift == 0) {
+ // if encoding.shift != 0, the flags are already set by the shlq
+ masm.testq(resReg, resReg);
+ }
+
+ Label done = new Label();
+ masm.jccb(Equal, done);
+ masm.addq(resReg, baseReg);
+ masm.bind(done);
+ }
+ }
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCLoadConstantTableBaseOp.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCLoadConstantTableBaseOp.java Thu Nov 16 10:45:42 2017 -0800
@@ -55,8 +55,8 @@
* this case absolute addressing (without using the base pointer is used). See also:
* CodeInstaller::pd_patch_DataSectionReference
*
- * @see SPARCMove#loadFromConstantTable(CompilationResultBuilder, SPARCMacroAssembler, int,
- * Register, jdk.vm.ci.meta.Constant, Register, SPARCDelayedControlTransfer)
+ * @see SPARCMove#loadFromConstantTable(CompilationResultBuilder, SPARCMacroAssembler, Register,
+ * jdk.vm.ci.meta.Constant, Register, SPARCDelayedControlTransfer)
*/
public class SPARCLoadConstantTableBaseOp extends SPARCLIRInstruction {
public static final LIRInstructionClass<SPARCLoadConstantTableBaseOp> TYPE = LIRInstructionClass.create(SPARCLoadConstantTableBaseOp.class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCMove.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCMove.java Thu Nov 16 10:45:42 2017 -0800
@@ -53,6 +53,7 @@
import org.graalvm.compiler.asm.sparc.SPARCAssembler;
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
+import org.graalvm.compiler.code.DataSection.Data;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.type.DataPointerConstant;
import org.graalvm.compiler.debug.GraalError;
@@ -116,11 +117,11 @@
public static final LIRInstructionClass<LoadConstantFromTable> TYPE = LIRInstructionClass.create(LoadConstantFromTable.class);
public static final SizeEstimate SIZE = SizeEstimate.create(1, 8);
- private Constant constant;
+ private JavaConstant constant;
@Def({REG, STACK}) AllocatableValue result;
@Use({REG}) private AllocatableValue constantTableBase;
- public LoadConstantFromTable(Constant constant, AllocatableValue constantTableBase, AllocatableValue result) {
+ public LoadConstantFromTable(JavaConstant constant, AllocatableValue constantTableBase, AllocatableValue result) {
super(TYPE, SIZE);
this.constant = constant;
this.result = result;
@@ -134,11 +135,11 @@
Register baseRegister = asRegister(constantTableBase);
if (isRegister(result)) {
Register resultRegister = asRegister(result);
- loadFromConstantTable(crb, masm, byteCount, baseRegister, constant, resultRegister, getDelayedControlTransfer());
+ loadFromConstantTable(crb, masm, baseRegister, constant, resultRegister, getDelayedControlTransfer());
} else if (isStackSlot(result)) {
try (ScratchRegister scratch = masm.getScratchRegister()) {
Register scratchRegister = scratch.getRegister();
- loadFromConstantTable(crb, masm, byteCount, baseRegister, constant, scratchRegister, getDelayedControlTransfer());
+ loadFromConstantTable(crb, masm, baseRegister, constant, scratchRegister, getDelayedControlTransfer());
StackSlot slot = asStackSlot(result);
reg2stack(crb, masm, slot, scratchRegister.asValue(), getDelayedControlTransfer());
}
@@ -642,7 +643,6 @@
boolean hasVIS1 = cpuFeatures.contains(CPUFeature.VIS1);
boolean hasVIS3 = cpuFeatures.contains(CPUFeature.VIS3);
Register resultRegister = asRegister(result);
- int byteCount = result.getPlatformKind().getSizeInBytes();
switch (input.getJavaKind().getStackKind()) {
case Int:
if (input.isDefaultForKind()) {
@@ -655,7 +655,7 @@
if (constantTableBase.equals(g0)) {
throw GraalError.shouldNotReachHere();
} else {
- loadFromConstantTable(crb, masm, byteCount, constantTableBase, input, resultRegister, delaySlotLir);
+ loadFromConstantTable(crb, masm, constantTableBase, input, resultRegister, delaySlotLir);
}
}
break;
@@ -667,7 +667,7 @@
delaySlotLir.emitControlTransfer(crb, masm);
masm.or(g0, (int) input.asLong(), resultRegister);
} else {
- loadFromConstantTable(crb, masm, byteCount, constantTableBase, input, resultRegister, delaySlotLir);
+ loadFromConstantTable(crb, masm, constantTableBase, input, resultRegister, delaySlotLir);
}
break;
case Float: {
@@ -683,7 +683,7 @@
masm.movwtos(scratch, resultRegister);
} else {
// First load the address into the scratch register
- loadFromConstantTable(crb, masm, byteCount, constantTableBase, input, resultRegister, delaySlotLir);
+ loadFromConstantTable(crb, masm, constantTableBase, input, resultRegister, delaySlotLir);
}
}
break;
@@ -700,7 +700,7 @@
delaySlotLir.emitControlTransfer(crb, masm);
masm.movxtod(scratch, resultRegister);
} else {
- loadFromConstantTable(crb, masm, byteCount, constantTableBase, input, resultRegister, delaySlotLir);
+ loadFromConstantTable(crb, masm, constantTableBase, input, resultRegister, delaySlotLir);
}
}
break;
@@ -710,7 +710,7 @@
delaySlotLir.emitControlTransfer(crb, masm);
masm.clr(resultRegister);
} else {
- loadFromConstantTable(crb, masm, byteCount, constantTableBase, input, resultRegister, delaySlotLir);
+ loadFromConstantTable(crb, masm, constantTableBase, input, resultRegister, delaySlotLir);
}
break;
default:
@@ -768,25 +768,30 @@
* patterns used for small constant sections (<8k) and large constant sections (>=8k). The
* generated patterns by this method must be understood by
* CodeInstaller::pd_patch_DataSectionReference (jvmciCodeInstaller_sparc.cpp).
+ *
+ * @return the number of bytes loaded from the constant table
*/
- public static void loadFromConstantTable(CompilationResultBuilder crb, SPARCMacroAssembler masm, int byteCount, Register constantTableBase, Constant input, Register dest,
+ public static int loadFromConstantTable(CompilationResultBuilder crb, SPARCMacroAssembler masm, Register constantTableBase, Constant input, Register dest,
SPARCDelayedControlTransfer delaySlotInstruction) {
SPARCAddress address;
ScratchRegister scratch = null;
try {
+ Data data = crb.createDataItem(input);
+ int size = data.getSize();
if (masm.isImmediateConstantLoad()) {
address = new SPARCAddress(constantTableBase, 0);
// Make delayed only, when using immediate constant load.
delaySlotInstruction.emitControlTransfer(crb, masm);
- crb.recordDataReferenceInCode(input, byteCount);
+ crb.recordDataReferenceInCode(data, size);
} else {
scratch = masm.getScratchRegister();
Register sr = scratch.getRegister();
- crb.recordDataReferenceInCode(input, byteCount);
+ crb.recordDataReferenceInCode(data, size);
masm.sethix(0, sr, true);
address = new SPARCAddress(sr, 0);
}
- masm.ld(address, dest, byteCount, false);
+ masm.ld(address, dest, size, false);
+ return size;
} finally {
if (scratch != null) {
scratch.close();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRValueUtil.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRValueUtil.java Thu Nov 16 10:45:42 2017 -0800
@@ -69,6 +69,16 @@
return asConstantValue(value).getJavaConstant();
}
+ public static boolean isIntConstant(Value value, long expected) {
+ if (isJavaConstant(value)) {
+ JavaConstant javaConstant = asJavaConstant(value);
+ if (javaConstant != null && javaConstant.getJavaKind().isNumericInteger()) {
+ return javaConstant.asLong() == expected;
+ }
+ }
+ return false;
+ }
+
public static boolean isStackSlotValue(Value value) {
assert value != null;
return value instanceof StackSlot || value instanceof VirtualStackSlot;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java Thu Nov 16 10:45:42 2017 -0800
@@ -30,6 +30,7 @@
import java.util.Collections;
import java.util.EnumSet;
+import jdk.vm.ci.code.RegisterConfig;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.debug.CounterKey;
@@ -138,8 +139,8 @@
private void doOptimize(LIR lir) {
DebugContext debug = lir.getDebug();
try (Indent indent = debug.logAndIndent("eliminate redundant moves")) {
-
- callerSaveRegs = frameMap.getRegisterConfig().getCallerSaveRegisters();
+ RegisterConfig registerConfig = frameMap.getRegisterConfig();
+ callerSaveRegs = registerConfig.getCallerSaveRegisters();
initBlockData(lir);
@@ -147,7 +148,7 @@
// Unallocatable registers should never be optimized.
eligibleRegs = new int[numRegs];
Arrays.fill(eligibleRegs, -1);
- for (Register reg : frameMap.getRegisterConfig().getAllocatableRegisters()) {
+ for (Register reg : registerConfig.getAllocatableRegisters()) {
if (reg.number < numRegs) {
eligibleRegs[reg.number] = reg.number;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/SaveCalleeSaveRegisters.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/SaveCalleeSaveRegisters.java Thu Nov 16 10:45:42 2017 -0800
@@ -31,7 +31,6 @@
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.StandardOp;
import org.graalvm.compiler.lir.Variable;
-import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase;
@@ -48,8 +47,7 @@
@Override
protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreAllocationOptimizationContext context) {
- FrameMapBuilder frameMapBuilder = lirGenRes.getFrameMapBuilder();
- RegisterArray calleeSaveRegisters = frameMapBuilder.getCodeCache().getRegisterConfig().getCalleeSaveRegisters();
+ RegisterArray calleeSaveRegisters = lirGenRes.getRegisterConfig().getCalleeSaveRegisters();
if (calleeSaveRegisters == null || calleeSaveRegisters.size() == 0) {
return;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java Thu Nov 16 10:45:42 2017 -0800
@@ -80,10 +80,10 @@
*/
public class CompilationResultBuilder {
- // @formatter:off
- @Option(help = "Include the LIR as comments with the final assembly.", type = OptionType.Debug)
- public static final OptionKey<Boolean> PrintLIRWithAssembly = new OptionKey<>(false);
- // @formatter:on
+ public static class Options {
+ @Option(help = "Include the LIR as comments with the final assembly.", type = OptionType.Debug) //
+ public static final OptionKey<Boolean> PrintLIRWithAssembly = new OptionKey<>(false);
+ }
private static class ExceptionInfo {
@@ -295,13 +295,24 @@
public AbstractAddress recordDataReferenceInCode(Constant constant, int alignment) {
assert constant != null;
debug.log("Constant reference in code: pos = %d, data = %s", asm.position(), constant);
+ Data data = createDataItem(constant);
+ data.updateAlignment(alignment);
+ return recordDataSectionReference(data);
+ }
+
+ public AbstractAddress recordDataReferenceInCode(Data data, int alignment) {
+ assert data != null;
+ data.updateAlignment(alignment);
+ return recordDataSectionReference(data);
+ }
+
+ public Data createDataItem(Constant constant) {
Data data = dataCache.get(constant);
if (data == null) {
data = dataBuilder.createDataItem(constant);
dataCache.put(constant, data);
}
- data.updateAlignment(alignment);
- return recordDataSectionReference(data);
+ return data;
}
public AbstractAddress recordDataReferenceInCode(byte[] data, int alignment) {
@@ -472,7 +483,7 @@
if (block == null) {
return;
}
- boolean emitComment = debug.isDumpEnabled(DebugContext.BASIC_LEVEL) || PrintLIRWithAssembly.getValue(getOptions());
+ boolean emitComment = debug.isDumpEnabled(DebugContext.BASIC_LEVEL) || Options.PrintLIRWithAssembly.getValue(getOptions());
if (emitComment) {
blockComment(String.format("block B%d %s", block.getId(), block.getLoop()));
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/ArithmeticLIRGenerator.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/ArithmeticLIRGenerator.java Thu Nov 16 10:45:42 2017 -0800
@@ -50,8 +50,19 @@
protected abstract Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags);
+ protected abstract Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags);
+
@Override
public final Variable emitAdd(Value aVal, Value bVal, boolean setFlags) {
+ return emitAddOrSub(aVal, bVal, setFlags, true);
+ }
+
+ @Override
+ public final Variable emitSub(Value aVal, Value bVal, boolean setFlags) {
+ return emitAddOrSub(aVal, bVal, setFlags, false);
+ }
+
+ private Variable emitAddOrSub(Value aVal, Value bVal, boolean setFlags, boolean isAdd) {
LIRKind resultKind;
Value a = aVal;
Value b = bVal;
@@ -90,47 +101,7 @@
resultKind = LIRKind.combine(a, b);
}
- return emitAdd(resultKind, a, b, setFlags);
+ return isAdd ? emitAdd(resultKind, a, b, setFlags) : emitSub(resultKind, a, b, setFlags);
}
- protected abstract Variable emitSub(LIRKind resultKind, Value a, Value b, boolean setFlags);
-
- @Override
- public final Variable emitSub(Value aVal, Value bVal, boolean setFlags) {
- LIRKind resultKind;
- Value a = aVal;
- Value b = bVal;
-
- if (isNumericInteger(a.getPlatformKind())) {
- LIRKind aKind = a.getValueKind(LIRKind.class);
- LIRKind bKind = b.getValueKind(LIRKind.class);
- assert a.getPlatformKind() == b.getPlatformKind();
-
- if (aKind.isUnknownReference()) {
- resultKind = aKind;
- } else if (bKind.isUnknownReference()) {
- resultKind = bKind;
- }
-
- if (aKind.isValue() && bKind.isValue()) {
- resultKind = aKind;
- } else if (bKind.isValue()) {
- if (aKind.isDerivedReference()) {
- resultKind = aKind;
- } else {
- AllocatableValue allocatable = getLIRGen().asAllocatable(a);
- resultKind = aKind.makeDerivedReference(allocatable);
- a = allocatable;
- }
- } else if (aKind.isDerivedReference() && bKind.isDerivedReference() && aKind.getDerivedReferenceBase().equals(bKind.getDerivedReferenceBase())) {
- resultKind = LIRKind.value(a.getPlatformKind());
- } else {
- resultKind = aKind.makeUnknownReference();
- }
- } else {
- resultKind = LIRKind.combine(a, b);
- }
-
- return emitSub(resultKind, a, b, setFlags);
- }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.lir.gen;
+import jdk.vm.ci.code.RegisterConfig;
import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.CompilationIdentifier.Verbosity;
import org.graalvm.compiler.debug.DebugContext;
@@ -123,6 +124,10 @@
return frameMap;
}
+ public final RegisterConfig getRegisterConfig() {
+ return frameMapBuilder.getRegisterConfig();
+ }
+
public LIR getLIR() {
return lir;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java Thu Nov 16 10:45:42 2017 -0800
@@ -34,6 +34,7 @@
import java.util.ArrayList;
import java.util.List;
+import jdk.vm.ci.code.RegisterConfig;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.calc.Condition;
@@ -201,8 +202,13 @@
}
@Override
+ public RegisterConfig getRegisterConfig() {
+ return res.getRegisterConfig();
+ }
+
+ @Override
public RegisterAttributes attributes(Register register) {
- return res.getFrameMapBuilder().getRegisterConfig().getAttributesMap()[register.number];
+ return getRegisterConfig().getAttributesMap()[register.number];
}
@Override
@@ -228,7 +234,7 @@
if (moveFactory.canInlineConstant(constant)) {
return new ConstantValue(toRegisterKind(kind), constant);
} else {
- return emitLoadConstant(kind, constant);
+ return emitLoadConstant(toRegisterKind(kind), constant);
}
}
@@ -289,7 +295,7 @@
*/
@Override
public AllocatableValue resultOperandFor(JavaKind javaKind, ValueKind<?> valueKind) {
- Register reg = res.getFrameMapBuilder().getRegisterConfig().getReturnRegister(javaKind);
+ Register reg = getRegisterConfig().getReturnRegister(javaKind);
assert target().arch.canStoreValue(reg.getRegisterCategory(), valueKind.getPlatformKind()) : reg.getRegisterCategory() + " " + valueKind.getPlatformKind();
return reg.asValue(valueKind);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.lir.gen;
+import jdk.vm.ci.code.RegisterConfig;
import org.graalvm.compiler.core.common.CompressEncoding;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.calc.Condition;
@@ -109,6 +110,8 @@
LIRGenerationResult getResult();
+ RegisterConfig getRegisterConfig();
+
boolean hasBlockEnd(AbstractBlockBase<?> block);
MoveFactory getMoveFactory();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -214,7 +214,7 @@
}
};
ResolvedJavaMethod method = getResolvedJavaMethod(name);
- OptionValues options = new OptionValues(getInitialOptions(), DefaultLoopPolicies.UnrollMaxIterations, 2);
+ OptionValues options = new OptionValues(getInitialOptions(), DefaultLoopPolicies.Options.UnrollMaxIterations, 2);
StructuredGraph graph = parse(builder(method, StructuredGraph.AllowAssumptions.YES, id, options), getEagerGraphBuilderSuite());
try (DebugContext.Scope buildScope = graph.getDebug().scope(name, method, graph)) {
MidTierContext context = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, null);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java Thu Nov 16 10:45:42 2017 -0800
@@ -83,7 +83,11 @@
range = add(graph, range, oneDirection);
}
// round-away-from-zero divison: (range + stride -/+ 1) / stride
- ValueNode denominator = add(graph, sub(graph, range, oneDirection), iv.strideNode());
+ ValueNode denominator = range;
+ if (!oneDirection.stamp().equals(iv.strideNode().stamp())) {
+ ValueNode subedRanged = sub(graph, range, oneDirection);
+ denominator = add(graph, subedRanged, iv.strideNode());
+ }
ValueNode div = divBefore(graph, loop.entryPoint(), denominator, iv.strideNode());
if (assumePositive) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DefaultLoopPolicies.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DefaultLoopPolicies.java Thu Nov 16 10:45:42 2017 -0800
@@ -55,16 +55,19 @@
import jdk.vm.ci.meta.MetaAccessProvider;
public class DefaultLoopPolicies implements LoopPolicies {
- @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> LoopUnswitchMaxIncrease = new OptionKey<>(500);
- @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> LoopUnswitchTrivial = new OptionKey<>(10);
- @Option(help = "", type = OptionType.Expert) public static final OptionKey<Double> LoopUnswitchFrequencyBoost = new OptionKey<>(10.0);
+
+ public static class Options {
+ @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> LoopUnswitchMaxIncrease = new OptionKey<>(500);
+ @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> LoopUnswitchTrivial = new OptionKey<>(10);
+ @Option(help = "", type = OptionType.Expert) public static final OptionKey<Double> LoopUnswitchFrequencyBoost = new OptionKey<>(10.0);
- @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> FullUnrollMaxNodes = new OptionKey<>(300);
- @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> FullUnrollMaxIterations = new OptionKey<>(600);
- @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> ExactFullUnrollMaxNodes = new OptionKey<>(1200);
- @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> ExactPartialUnrollMaxNodes = new OptionKey<>(200);
+ @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> FullUnrollMaxNodes = new OptionKey<>(300);
+ @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> FullUnrollMaxIterations = new OptionKey<>(600);
+ @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> ExactFullUnrollMaxNodes = new OptionKey<>(1200);
+ @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> ExactPartialUnrollMaxNodes = new OptionKey<>(200);
- @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> UnrollMaxIterations = new OptionKey<>(16);
+ @Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> UnrollMaxIterations = new OptionKey<>(16);
+ }
@Override
public boolean shouldPeel(LoopEx loop, ControlFlowGraph cfg, MetaAccessProvider metaAccess) {
@@ -87,10 +90,10 @@
OptionValues options = loop.entryPoint().getOptions();
CountedLoopInfo counted = loop.counted();
long maxTrips = counted.constantMaxTripCount();
- int maxNodes = (counted.isExactTripCount() && counted.isConstantExactTripCount()) ? ExactFullUnrollMaxNodes.getValue(options) : FullUnrollMaxNodes.getValue(options);
+ int maxNodes = (counted.isExactTripCount() && counted.isConstantExactTripCount()) ? Options.ExactFullUnrollMaxNodes.getValue(options) : Options.FullUnrollMaxNodes.getValue(options);
maxNodes = Math.min(maxNodes, Math.max(0, MaximumDesiredSize.getValue(options) - loop.loopBegin().graph().getNodeCount()));
int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count());
- if (maxTrips <= FullUnrollMaxIterations.getValue(options) && size * (maxTrips - 1) <= maxNodes) {
+ if (maxTrips <= Options.FullUnrollMaxIterations.getValue(options) && size * (maxTrips - 1) <= maxNodes) {
// check whether we're allowed to unroll this loop
return loop.canDuplicateLoop();
} else {
@@ -106,7 +109,7 @@
return false;
}
OptionValues options = loop.entryPoint().getOptions();
- int maxNodes = ExactPartialUnrollMaxNodes.getValue(options);
+ int maxNodes = Options.ExactPartialUnrollMaxNodes.getValue(options);
maxNodes = Math.min(maxNodes, Math.max(0, MaximumDesiredSize.getValue(options) - loop.loopBegin().graph().getNodeCount()));
int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count());
int unrollFactor = loopBegin.getUnrollFactor();
@@ -118,7 +121,7 @@
}
loopBegin.setLoopOrigFrequency(loopFrequency);
}
- int maxUnroll = UnrollMaxIterations.getValue(options);
+ int maxUnroll = Options.UnrollMaxIterations.getValue(options);
// Now correct size for the next unroll. UnrollMaxIterations == 1 means perform the
// pre/main/post transformation but don't actually unroll the main loop.
size += size;
@@ -190,9 +193,9 @@
CountingClosure stateNodesCount = new CountingClosure();
double loopFrequency = loop.loopBegin().loopFrequency();
OptionValues options = loop.loopBegin().getOptions();
- int maxDiff = LoopUnswitchTrivial.getValue(options) + (int) (LoopUnswitchFrequencyBoost.getValue(options) * (loopFrequency - 1.0 + phis));
+ int maxDiff = Options.LoopUnswitchTrivial.getValue(options) + (int) (Options.LoopUnswitchFrequencyBoost.getValue(options) * (loopFrequency - 1.0 + phis));
- maxDiff = Math.min(maxDiff, LoopUnswitchMaxIncrease.getValue(options));
+ maxDiff = Math.min(maxDiff, Options.LoopUnswitchMaxIncrease.getValue(options));
int remainingGraphSpace = MaximumDesiredSize.getValue(options) - graph.getNodeCount();
maxDiff = Math.min(maxDiff, remainingGraphSpace);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo/src/org/graalvm/compiler/nodeinfo/NodeCycles.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodeinfo/src/org/graalvm/compiler/nodeinfo/NodeCycles.java Thu Nov 16 10:45:42 2017 -0800
@@ -68,6 +68,10 @@
this.value = value;
}
+ public boolean isValueKnown() {
+ return this != NodeCycles.CYCLES_UNKNOWN && this != NodeCycles.CYCLES_UNSET;
+ }
+
public static final int IGNORE_CYCLES_CONTRACT_FACTOR = 0xFFFF;
public static NodeCycles compute(NodeCycles base, int opCount) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -552,4 +552,21 @@
return result.longValue();
}
}
+
+ @Test
+ public void testDiv() {
+ testDiv(32, Integer.MIN_VALUE, Integer.MAX_VALUE);
+ testDiv(64, Long.MIN_VALUE, Long.MAX_VALUE);
+ }
+
+ private static void testDiv(int bits, long min, long max) {
+ BinaryOp<?> div = IntegerStamp.OPS.getDiv();
+ assertEquals(IntegerStamp.create(bits, -50, 50), div.foldStamp(IntegerStamp.create(bits, -100, 100), IntegerStamp.create(bits, 2, 5)));
+ assertEquals(IntegerStamp.create(bits, 20, 500), div.foldStamp(IntegerStamp.create(bits, 100, 1000), IntegerStamp.create(bits, 2, 5)));
+ assertEquals(IntegerStamp.create(bits, -500, -20), div.foldStamp(IntegerStamp.create(bits, -1000, -100), IntegerStamp.create(bits, 2, 5)));
+ assertEquals(IntegerStamp.create(bits, min, max), div.foldStamp(IntegerStamp.create(bits, min, max), IntegerStamp.create(bits, 1, max)));
+ assertEquals(IntegerStamp.create(bits, -100, 100), div.foldStamp(IntegerStamp.create(bits, -100, 100), IntegerStamp.create(bits, 1, max)));
+ assertEquals(IntegerStamp.create(bits, 0, 1000), div.foldStamp(IntegerStamp.create(bits, 100, 1000), IntegerStamp.create(bits, 1, max)));
+ assertEquals(IntegerStamp.create(bits, -1000, 0), div.foldStamp(IntegerStamp.create(bits, -1000, -100), IntegerStamp.create(bits, 1, max)));
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/PrimitiveStampBoundaryTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 org.graalvm.compiler.nodes.test;
+
+import java.util.EnumSet;
+import java.util.HashSet;
+
+import org.graalvm.compiler.core.common.calc.FloatConvert;
+import org.graalvm.compiler.core.common.calc.FloatConvertCategory;
+import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
+import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
+import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp;
+import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp;
+import org.graalvm.compiler.core.common.type.FloatStamp;
+import org.graalvm.compiler.core.common.type.IntegerStamp;
+import org.graalvm.compiler.core.common.type.PrimitiveStamp;
+import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.test.GraalTest;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+
+/**
+ * Exercise the various stamp folding operations by generating ranges from a set of boundary values
+ * and then ensuring that the values that produced those ranges are in the resulting stamp.
+ */
+public class PrimitiveStampBoundaryTest extends GraalTest {
+
+ static long[] longBoundaryValues = {Long.MIN_VALUE, Long.MIN_VALUE + 1, Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -1, 0, 1, Integer.MAX_VALUE - 1, Integer.MAX_VALUE, Long.MAX_VALUE - 1,
+ Long.MAX_VALUE};
+
+ static int[] shiftBoundaryValues = {-128, -1, 0, 1, 4, 8, 16, 31, 63, 128};
+
+ static HashSet<IntegerStamp> shiftStamps;
+ static HashSet<PrimitiveStamp> integerTestStamps;
+ static HashSet<PrimitiveStamp> floatTestStamps;
+
+ static {
+ shiftStamps = new HashSet<>();
+ for (long v1 : shiftBoundaryValues) {
+ for (long v2 : shiftBoundaryValues) {
+ shiftStamps.add(IntegerStamp.create(32, Math.min(v1, v2), Math.max(v1, v2)));
+ }
+ }
+
+ integerTestStamps = new HashSet<>();
+ for (long v1 : longBoundaryValues) {
+ for (long v2 : longBoundaryValues) {
+ if (v2 == (int) v2 && v1 == (int) v1) {
+ integerTestStamps.add(IntegerStamp.create(32, Math.min(v1, v2), Math.max(v1, v2)));
+ }
+ integerTestStamps.add(IntegerStamp.create(64, Math.min(v1, v2), Math.max(v1, v2)));
+ }
+ }
+ }
+
+ static double[] doubleBoundaryValues = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, Float.NEGATIVE_INFINITY, Float.MIN_VALUE,
+ Long.MIN_VALUE, Long.MIN_VALUE + 1, Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -1, 0, 1,
+ Integer.MAX_VALUE - 1, Integer.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE,
+ Float.MAX_VALUE, Float.POSITIVE_INFINITY, Double.MAX_VALUE, Double.POSITIVE_INFINITY};
+
+ static double[] doubleSpecialValues = {Double.NaN, -0.0, -0.0F, Float.NaN};
+
+ static {
+ floatTestStamps = new HashSet<>();
+
+ for (double d1 : doubleBoundaryValues) {
+ for (double d2 : doubleBoundaryValues) {
+ float f1 = (float) d2;
+ float f2 = (float) d1;
+ if (d2 == f1 && d1 == f2) {
+ generateFloatingStamps(new FloatStamp(32, Math.min(f2, f1), Math.max(f2, f1), true));
+ generateFloatingStamps(new FloatStamp(32, Math.min(f2, f1), Math.max(f2, f1), false));
+ }
+ generateFloatingStamps(new FloatStamp(64, Math.min(d1, d2), Math.max(d1, d2), true));
+ generateFloatingStamps(new FloatStamp(64, Math.min(d1, d2), Math.max(d1, d2), false));
+ }
+ }
+ }
+
+ private static void generateFloatingStamps(FloatStamp floatStamp) {
+ floatTestStamps.add(floatStamp);
+ for (double d : doubleSpecialValues) {
+ FloatStamp newStamp = (FloatStamp) floatStamp.meet(floatStampForConstant(d, floatStamp.getBits()));
+ if (!newStamp.isUnrestricted()) {
+ floatTestStamps.add(newStamp);
+ }
+ }
+ }
+
+ @Test
+ public void testConvertBoundaryValues() {
+ testConvertBoundaryValues(IntegerStamp.OPS.getSignExtend(), 32, 64, integerTestStamps);
+ testConvertBoundaryValues(IntegerStamp.OPS.getZeroExtend(), 32, 64, integerTestStamps);
+ testConvertBoundaryValues(IntegerStamp.OPS.getNarrow(), 64, 32, integerTestStamps);
+ }
+
+ private static void testConvertBoundaryValues(IntegerConvertOp<?> op, int inputBits, int resultBits, HashSet<PrimitiveStamp> stamps) {
+ for (PrimitiveStamp stamp : stamps) {
+ if (inputBits == stamp.getBits()) {
+ Stamp lower = boundaryStamp(stamp, false);
+ Stamp upper = boundaryStamp(stamp, true);
+ checkConvertOperation(op, inputBits, resultBits, op.foldStamp(inputBits, resultBits, stamp), lower);
+ checkConvertOperation(op, inputBits, resultBits, op.foldStamp(inputBits, resultBits, stamp), upper);
+ }
+ }
+ }
+
+ private static void checkConvertOperation(IntegerConvertOp<?> op, int inputBits, int resultBits, Stamp result, Stamp v1stamp) {
+ Stamp folded = op.foldStamp(inputBits, resultBits, v1stamp);
+ assertTrue(folded.asConstant() != null, "should constant fold %s %s %s", op, v1stamp, folded);
+ assertTrue(result.meet(folded).equals(result), "result out of range %s %s %s %s %s", op, v1stamp, folded, result, result.meet(folded));
+ }
+
+ @Test
+ public void testFloatConvertBoundaryValues() {
+ for (FloatConvert op : EnumSet.allOf(FloatConvert.class)) {
+ ArithmeticOpTable.FloatConvertOp floatConvert = IntegerStamp.OPS.getFloatConvert(op);
+ if (floatConvert == null) {
+ continue;
+ }
+ assert op.getCategory() == FloatConvertCategory.IntegerToFloatingPoint : op;
+ testConvertBoundaryValues(floatConvert, op.getInputBits(), integerTestStamps);
+ }
+ for (FloatConvert op : EnumSet.allOf(FloatConvert.class)) {
+ ArithmeticOpTable.FloatConvertOp floatConvert = FloatStamp.OPS.getFloatConvert(op);
+ if (floatConvert == null) {
+ continue;
+ }
+ assert op.getCategory() == FloatConvertCategory.FloatingPointToInteger || op.getCategory() == FloatConvertCategory.FloatingPointToFloatingPoint : op;
+ testConvertBoundaryValues(floatConvert, op.getInputBits(), floatTestStamps);
+ }
+ }
+
+ private static void testConvertBoundaryValues(ArithmeticOpTable.FloatConvertOp op, int bits, HashSet<PrimitiveStamp> stamps) {
+ for (PrimitiveStamp stamp : stamps) {
+ if (bits == stamp.getBits()) {
+ Stamp lower = boundaryStamp(stamp, false);
+ Stamp upper = boundaryStamp(stamp, true);
+ checkConvertOperation(op, op.foldStamp(stamp), lower);
+ checkConvertOperation(op, op.foldStamp(stamp), upper);
+ }
+ }
+ }
+
+ private static void checkConvertOperation(ArithmeticOpTable.FloatConvertOp op, Stamp result, Stamp v1stamp) {
+ Stamp folded = op.foldStamp(v1stamp);
+ assertTrue(folded.asConstant() != null, "should constant fold %s %s %s", op, v1stamp, folded);
+ assertTrue(result.meet(folded).equals(result), "result out of range %s %s %s %s %s", op, v1stamp, folded, result, result.meet(folded));
+ }
+
+ @Test
+ public void testShiftBoundaryValues() {
+ for (ShiftOp<?> op : IntegerStamp.OPS.getShiftOps()) {
+ testShiftBoundaryValues(op, integerTestStamps, shiftStamps);
+ }
+ }
+
+ private static void testShiftBoundaryValues(ShiftOp<?> shiftOp, HashSet<PrimitiveStamp> stamps, HashSet<IntegerStamp> shifts) {
+ for (PrimitiveStamp testStamp : stamps) {
+ if (testStamp instanceof IntegerStamp) {
+ IntegerStamp stamp = (IntegerStamp) testStamp;
+ for (IntegerStamp shiftStamp : shifts) {
+ IntegerStamp foldedStamp = (IntegerStamp) shiftOp.foldStamp(stamp, shiftStamp);
+ checkShiftOperation(stamp.getBits(), shiftOp, foldedStamp, stamp.lowerBound(), shiftStamp.lowerBound());
+ checkShiftOperation(stamp.getBits(), shiftOp, foldedStamp, stamp.lowerBound(), shiftStamp.upperBound());
+ checkShiftOperation(stamp.getBits(), shiftOp, foldedStamp, stamp.upperBound(), shiftStamp.lowerBound());
+ checkShiftOperation(stamp.getBits(), shiftOp, foldedStamp, stamp.upperBound(), shiftStamp.upperBound());
+ }
+ }
+ }
+ }
+
+ private static void checkShiftOperation(int bits, ShiftOp<?> op, IntegerStamp result, long v1, long v2) {
+ IntegerStamp v1stamp = IntegerStamp.create(bits, v1, v1);
+ IntegerStamp v2stamp = IntegerStamp.create(32, v2, v2);
+ IntegerStamp folded = (IntegerStamp) op.foldStamp(v1stamp, v2stamp);
+ Constant constant = op.foldConstant(JavaConstant.forPrimitiveInt(bits, v1), (int) v2);
+ assertTrue(constant != null);
+ assertTrue(folded.asConstant() != null, "should constant fold %s %s %s %s", op, v1stamp, v2stamp, folded);
+ assertTrue(result.meet(folded).equals(result), "result out of range %s %s %s %s %s %s", op, v1stamp, v2stamp, folded, result, result.meet(folded));
+ }
+
+ private static void checkBinaryOperation(ArithmeticOpTable.BinaryOp<?> op, Stamp result, Stamp v1stamp, Stamp v2stamp) {
+ Stamp folded = op.foldStamp(v1stamp, v2stamp);
+ Constant constant = op.foldConstant(v1stamp.asConstant(), v2stamp.asConstant());
+ if (constant != null) {
+ Constant constant2 = folded.asConstant();
+ if (constant2 == null && v1stamp instanceof FloatStamp) {
+ JavaConstant c = (JavaConstant) constant;
+ assertTrue((c.getJavaKind() == JavaKind.Double && Double.isNaN(c.asDouble())) ||
+ (c.getJavaKind() == JavaKind.Float && Float.isNaN(c.asFloat())));
+ } else {
+ assertTrue(constant2 != null, "should constant fold %s %s %s %s", op, v1stamp, v2stamp, folded);
+ if (!constant.equals(constant2)) {
+ op.foldConstant(v1stamp.asConstant(), v2stamp.asConstant());
+ op.foldStamp(v1stamp, v2stamp);
+ }
+ assertTrue(constant.equals(constant2), "should produce same constant %s %s %s %s %s", op, v1stamp, v2stamp, constant, constant2);
+ }
+ assertTrue(result.meet(folded).equals(result), "result out of range %s %s %s %s %s %s", op, v1stamp, v2stamp, folded, result, result.meet(folded));
+ }
+ }
+
+ @Test
+ public void testBinaryBoundaryValues() {
+ for (BinaryOp<?> op : IntegerStamp.OPS.getBinaryOps()) {
+ if (op != null) {
+ testBinaryBoundaryValues(op, integerTestStamps);
+ }
+ }
+ for (BinaryOp<?> op : FloatStamp.OPS.getBinaryOps()) {
+ if (op != null) {
+ testBinaryBoundaryValues(op, floatTestStamps);
+ }
+ }
+ }
+
+ private static Stamp boundaryStamp(Stamp v1, boolean upper) {
+ if (v1 instanceof IntegerStamp) {
+ IntegerStamp istamp = (IntegerStamp) v1;
+ long bound = upper ? istamp.upperBound() : istamp.lowerBound();
+ return IntegerStamp.create(istamp.getBits(), bound, bound);
+ } else if (v1 instanceof FloatStamp) {
+ FloatStamp floatStamp = (FloatStamp) v1;
+ double bound = upper ? floatStamp.upperBound() : floatStamp.lowerBound();
+ int bits = floatStamp.getBits();
+ return floatStampForConstant(bound, bits);
+ } else {
+ throw new InternalError("unexpected stamp type " + v1);
+ }
+ }
+
+ private static FloatStamp floatStampForConstant(double bound, int bits) {
+ if (bits == 32) {
+ float fbound = (float) bound;
+ return new FloatStamp(bits, fbound, fbound, !Float.isNaN(fbound));
+ } else {
+ return new FloatStamp(bits, bound, bound, !Double.isNaN(bound));
+ }
+ }
+
+ private static void testBinaryBoundaryValues(ArithmeticOpTable.BinaryOp<?> op, HashSet<PrimitiveStamp> stamps) {
+ for (PrimitiveStamp v1 : stamps) {
+ for (PrimitiveStamp v2 : stamps) {
+ if (v1.getBits() == v2.getBits() && v1.getClass() == v2.getClass()) {
+ Stamp result = op.foldStamp(v1, v2);
+ Stamp v1lower = boundaryStamp(v1, false);
+ Stamp v1upper = boundaryStamp(v1, true);
+ Stamp v2lower = boundaryStamp(v2, false);
+ Stamp v2upper = boundaryStamp(v2, true);
+ checkBinaryOperation(op, result, v1lower, v2lower);
+ checkBinaryOperation(op, result, v1lower, v2upper);
+ checkBinaryOperation(op, result, v1upper, v2lower);
+ checkBinaryOperation(op, result, v1upper, v2upper);
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testUnaryBoundaryValues() {
+ for (ArithmeticOpTable.UnaryOp<?> op : IntegerStamp.OPS.getUnaryOps()) {
+ if (op != null) {
+ testUnaryBoundaryValues(op, integerTestStamps);
+ }
+ }
+ for (ArithmeticOpTable.UnaryOp<?> op : FloatStamp.OPS.getUnaryOps()) {
+ if (op != null) {
+ testUnaryBoundaryValues(op, floatTestStamps);
+ }
+ }
+ }
+
+ private static void testUnaryBoundaryValues(ArithmeticOpTable.UnaryOp<?> op, HashSet<PrimitiveStamp> stamps) {
+ for (PrimitiveStamp v1 : stamps) {
+ Stamp result = op.foldStamp(v1);
+ checkUnaryOperation(op, result, boundaryStamp(v1, false));
+ checkUnaryOperation(op, result, boundaryStamp(v1, true));
+ }
+ }
+
+ private static void checkUnaryOperation(ArithmeticOpTable.UnaryOp<?> op, Stamp result, Stamp v1stamp) {
+ Stamp folded = op.foldStamp(v1stamp);
+ Constant v1constant = v1stamp.asConstant();
+ if (v1constant != null) {
+ Constant constant = op.foldConstant(v1constant);
+ if (constant != null) {
+ Constant constant2 = folded.asConstant();
+ if (constant2 == null && v1stamp instanceof FloatStamp) {
+ JavaConstant c = (JavaConstant) constant;
+ assertTrue((c.getJavaKind() == JavaKind.Double && Double.isNaN(c.asDouble())) ||
+ (c.getJavaKind() == JavaKind.Float && Float.isNaN(c.asFloat())));
+ } else {
+ assertTrue(constant2 != null, "should constant fold %s %s %s", op, v1stamp, folded);
+ assertTrue(constant.equals(constant2), "should produce same constant %s %s %s %s", op, v1stamp, constant, constant2);
+ }
+ }
+ } else {
+ assert v1stamp instanceof FloatStamp;
+ }
+ assertTrue(result.meet(folded).equals(result), "result out of range %s %s %s %s %s", op, v1stamp, folded, result, result.meet(folded));
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CompressionNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/CompressionNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -122,9 +122,9 @@
// We always want uncompressed constants
return this;
}
- int stableDimension = ((ConstantNode) forValue).getStableDimension();
- boolean isDefaultStable = ((ConstantNode) forValue).isDefaultStable();
- return ConstantNode.forConstant(stamp(), convert(forValue.asConstant(), tool.getConstantReflection()), stableDimension, isDefaultStable, tool.getMetaAccess());
+
+ ConstantNode constant = (ConstantNode) forValue;
+ return ConstantNode.forConstant(stamp(), convert(constant.getValue(), tool.getConstantReflection()), constant.getStableDimension(), constant.isDefaultStable(), tool.getMetaAccess());
} else if (forValue instanceof CompressionNode) {
CompressionNode other = (CompressionNode) forValue;
if (op != other.op && encoding.equals(other.encoding)) {
@@ -136,22 +136,22 @@
@Override
public void generate(NodeLIRBuilderTool gen) {
- LIRGeneratorTool hsGen = gen.getLIRGeneratorTool();
boolean nonNull;
- if (getValue().stamp() instanceof AbstractObjectStamp) {
- nonNull = StampTool.isPointerNonNull(getValue().stamp());
+ if (value.stamp() instanceof AbstractObjectStamp) {
+ nonNull = StampTool.isPointerNonNull(value.stamp());
} else {
// metaspace pointers are never null
nonNull = true;
}
+ LIRGeneratorTool tool = gen.getLIRGeneratorTool();
Value result;
switch (op) {
case Compress:
- result = hsGen.emitCompress(gen.operand(getValue()), encoding, nonNull);
+ result = tool.emitCompress(gen.operand(value), encoding, nonNull);
break;
case Uncompress:
- result = hsGen.emitUncompress(gen.operand(getValue()), encoding, nonNull);
+ result = tool.emitUncompress(gen.operand(value), encoding, nonNull);
break;
default:
throw GraalError.shouldNotReachHere();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -54,7 +54,7 @@
/**
* The {@code ConstantNode} represents a {@link Constant constant}.
*/
-@NodeInfo(nameTemplate = "C({p#rawvalue})", cycles = CYCLES_0, size = SIZE_1)
+@NodeInfo(nameTemplate = "C({p#rawvalue}) {p#stampKind}", cycles = CYCLES_0, size = SIZE_1)
public final class ConstantNode extends FloatingNode implements LIRLowerable {
public static final NodeClass<ConstantNode> TYPE = NodeClass.create(ConstantNode.class);
@@ -518,13 +518,14 @@
public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
Map<Object, Object> properties = super.getDebugProperties(map);
properties.put("rawvalue", value.toValueString());
+ properties.put("stampKind", stamp.unrestricted().toString());
return properties;
}
@Override
public String toString(Verbosity verbosity) {
if (verbosity == Verbosity.Name) {
- return super.toString(Verbosity.Name) + "(" + value.toValueString() + ")";
+ return super.toString(Verbosity.Name) + "(" + value.toValueString() + ", " + stamp().unrestricted().toString() + ")";
} else {
return super.toString(verbosity);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.nodes;
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
import java.util.ArrayList;
@@ -74,7 +74,7 @@
* The {@code IfNode} represents a branch that can go one of two directions depending on the outcome
* of a comparison.
*/
-@NodeInfo(cycles = CYCLES_2, size = SIZE_2, sizeRationale = "2 jmps")
+@NodeInfo(cycles = CYCLES_1, size = SIZE_2, sizeRationale = "2 jmps")
public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable {
public static final NodeClass<IfNode> TYPE = NodeClass.create(IfNode.class);
@@ -375,7 +375,7 @@
}
// Falsify the reference check.
- setCondition(graph().addOrUnique(LogicConstantNode.contradiction()));
+ setCondition(graph().addOrUniqueWithInputs(LogicConstantNode.contradiction()));
return true;
}
@@ -726,10 +726,11 @@
protected void removeThroughFalseBranch(SimplifierTool tool, AbstractMergeNode merge) {
AbstractBeginNode trueBegin = trueSuccessor();
+ LogicNode conditionNode = condition();
graph().removeSplitPropagate(this, trueBegin);
tool.addToWorkList(trueBegin);
- if (condition() != null) {
- GraphUtil.tryKillUnused(condition());
+ if (conditionNode != null) {
+ GraphUtil.tryKillUnused(conditionNode);
}
if (merge.isAlive() && merge.forwardEndCount() > 1) {
for (FixedNode end : merge.forwardEnds()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PhiNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PhiNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -132,12 +132,24 @@
}
str.append(valueAt(i) == null ? "-" : valueAt(i).toString(Verbosity.Id));
}
+ String description = valueDescription();
+ if (description.length() > 0) {
+ str.append(", ").append(description);
+ }
return super.toString(Verbosity.Name) + "(" + str + ")";
} else {
return super.toString(verbosity);
}
}
+ /**
+ * String describing the kind of value this Phi merges. Used by {@link #toString(Verbosity)} and
+ * dumping.
+ */
+ protected String valueDescription() {
+ return "";
+ }
+
public void addInput(ValueNode x) {
assert !(x instanceof ValuePhiNode) || ((ValuePhiNode) x).merge() instanceof LoopBeginNode || ((ValuePhiNode) x).merge() != this.merge();
assert !(this instanceof ValuePhiNode) || x.stamp().isCompatible(stamp());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -59,14 +59,14 @@
*
* In contrast to a {@link GuardedValueNode}, a {@link PiNode} is useless as soon as the type of its
* input is as narrow or narrower than the {@link PiNode}'s type. The {@link PiNode}, and therefore
- * also the scheduling restriction enforced by the anchor, will go away.
+ * also the scheduling restriction enforced by the guard, will go away.
*/
@NodeInfo(cycles = CYCLES_0, size = SIZE_0)
public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, Canonicalizable, ValueProxy {
public static final NodeClass<PiNode> TYPE = NodeClass.create(PiNode.class);
@Input ValueNode object;
- protected final Stamp piStamp;
+ protected Stamp piStamp;
public ValueNode object() {
return object;
@@ -84,12 +84,12 @@
this(object, stamp, null);
}
- public PiNode(ValueNode object, Stamp stamp, ValueNode anchor) {
- this(TYPE, object, stamp, (GuardingNode) anchor);
+ public PiNode(ValueNode object, Stamp stamp, ValueNode guard) {
+ this(TYPE, object, stamp, (GuardingNode) guard);
}
- public PiNode(ValueNode object, ValueNode anchor) {
- this(object, AbstractPointerStamp.pointerNonNull(object.stamp()), anchor);
+ public PiNode(ValueNode object, ValueNode guard) {
+ this(object, AbstractPointerStamp.pointerNonNull(object.stamp()), guard);
}
public PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
@@ -104,29 +104,29 @@
return new PiNode(object, stamp);
}
- public static ValueNode create(ValueNode object, Stamp stamp, ValueNode anchor) {
- ValueNode value = canonical(object, stamp, (GuardingNode) anchor);
+ public static ValueNode create(ValueNode object, Stamp stamp, ValueNode guard) {
+ ValueNode value = canonical(object, stamp, (GuardingNode) guard);
if (value != null) {
return value;
}
- return new PiNode(object, stamp, anchor);
+ return new PiNode(object, stamp, guard);
}
- public static ValueNode create(ValueNode object, ValueNode anchor) {
+ public static ValueNode create(ValueNode object, ValueNode guard) {
Stamp stamp = AbstractPointerStamp.pointerNonNull(object.stamp());
- ValueNode value = canonical(object, stamp, (GuardingNode) anchor);
+ ValueNode value = canonical(object, stamp, (GuardingNode) guard);
if (value != null) {
return value;
}
- return new PiNode(object, stamp, anchor);
+ return new PiNode(object, stamp, guard);
}
@SuppressWarnings("unused")
- public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode object, ValueNode anchor) {
+ public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode object, ValueNode guard) {
Stamp stamp = AbstractPointerStamp.pointerNonNull(object.stamp());
- ValueNode value = canonical(object, stamp, (GuardingNode) anchor);
+ ValueNode value = canonical(object, stamp, (GuardingNode) guard);
if (value == null) {
- value = new PiNode(object, stamp, anchor);
+ value = new PiNode(object, stamp, guard);
}
b.push(JavaKind.Object, b.append(value));
return true;
@@ -147,6 +147,11 @@
return piStamp;
}
+ public void strengthenPiStamp(Stamp newPiStamp) {
+ assert this.piStamp.join(newPiStamp).equals(newPiStamp) : "stamp can only improve";
+ this.piStamp = newPiStamp;
+ }
+
@Override
public void generate(NodeLIRBuilderTool generator) {
if (generator.hasOperand(object)) {
@@ -256,17 +261,17 @@
/**
* Changes the stamp of an object and ensures the newly stamped value is non-null and does not
- * float above a given anchor.
+ * float above a given guard.
*/
@NodeIntrinsic
- public static native Object piCastNonNull(Object object, GuardingNode anchor);
+ public static native Object piCastNonNull(Object object, GuardingNode guard);
/**
* Changes the stamp of an object and ensures the newly stamped value is non-null and does not
- * float above a given anchor.
+ * float above a given guard.
*/
@NodeIntrinsic
- public static native Class<?> piCastNonNullClass(Class<?> type, GuardingNode anchor);
+ public static native Class<?> piCastNonNullClass(Class<?> type, GuardingNode guard);
/**
* Changes the stamp of an object to represent a given type and to indicate that the object is
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValuePhiNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValuePhiNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,6 +22,8 @@
*/
package org.graalvm.compiler.nodes;
+import java.util.Map;
+
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
@@ -35,7 +37,7 @@
/**
* Value {@link PhiNode}s merge data flow values at control flow merges.
*/
-@NodeInfo(nameTemplate = "Phi({i#values})")
+@NodeInfo(nameTemplate = "Phi({i#values}, {p#valueDescription})")
public class ValuePhiNode extends PhiNode implements ArrayLengthProvider {
public static final NodeClass<ValuePhiNode> TYPE = NodeClass.create(ValuePhiNode.class);
@@ -113,4 +115,16 @@
}
return super.verify();
}
+
+ @Override
+ protected String valueDescription() {
+ return stamp().unrestricted().toString();
+ }
+
+ @Override
+ public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
+ Map<Object, Object> properties = super.getDebugProperties(map);
+ properties.put("valueDescription", valueDescription());
+ return properties;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -91,7 +91,9 @@
public static <OP> ConstantNode tryConstantFold(BinaryOp<OP> op, ValueNode forX, ValueNode forY, Stamp stamp) {
if (forX.isConstant() && forY.isConstant()) {
Constant ret = op.foldConstant(forX.asConstant(), forY.asConstant());
- return ConstantNode.forPrimitive(stamp, ret);
+ if (ret != null) {
+ return ConstantNode.forPrimitive(stamp, ret);
+ }
}
return null;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,7 +22,7 @@
*/
package org.graalvm.compiler.nodes.calc;
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
import static org.graalvm.compiler.nodes.calc.CompareNode.createCompareNode;
@@ -47,10 +47,10 @@
import jdk.vm.ci.meta.JavaConstant;
/**
- * The {@code ConditionalNode} class represents a comparison that yields one of two values. Note
- * that these nodes are not built directly from the bytecode but are introduced by canonicalization.
+ * The {@code ConditionalNode} class represents a comparison that yields one of two (eagerly
+ * evaluated) values.
*/
-@NodeInfo(cycles = CYCLES_0, size = SIZE_2)
+@NodeInfo(cycles = CYCLES_1, size = SIZE_2)
public final class ConditionalNode extends FloatingNode implements Canonicalizable, LIRLowerable {
public static final NodeClass<ConditionalNode> TYPE = NodeClass.create(ConditionalNode.class);
@@ -116,7 +116,6 @@
valueStamp = valueStamp.join(bounds);
}
}
-
}
return updateStamp(valueStamp);
}
@@ -145,49 +144,10 @@
}
public static ValueNode canonicalizeConditional(LogicNode condition, ValueNode trueValue, ValueNode falseValue, Stamp stamp) {
- // this optimizes the case where a value from the range 0 - 1 is mapped to the range 0 - 1
- if (trueValue.isConstant() && falseValue.isConstant() && trueValue.stamp() instanceof IntegerStamp && falseValue.stamp() instanceof IntegerStamp) {
- long constTrueValue = trueValue.asJavaConstant().asLong();
- long constFalseValue = falseValue.asJavaConstant().asLong();
- if (condition instanceof IntegerEqualsNode) {
- IntegerEqualsNode equals = (IntegerEqualsNode) condition;
- if (equals.getY().isConstant() && equals.getX().stamp() instanceof IntegerStamp) {
- IntegerStamp equalsXStamp = (IntegerStamp) equals.getX().stamp();
- if (equalsXStamp.upMask() == 1) {
- long equalsY = equals.getY().asJavaConstant().asLong();
- if (equalsY == 0) {
- if (constTrueValue == 0 && constFalseValue == 1) {
- // return x when: x == 0 ? 0 : 1;
- return IntegerConvertNode.convertUnsigned(equals.getX(), stamp);
- } else if (constTrueValue == 1 && constFalseValue == 0) {
- // negate a boolean value via xor
- return IntegerConvertNode.convertUnsigned(XorNode.create(equals.getX(), ConstantNode.forIntegerStamp(equals.getX().stamp(), 1)), stamp);
- }
- } else if (equalsY == 1) {
- if (constTrueValue == 1 && constFalseValue == 0) {
- // return x when: x == 1 ? 1 : 0;
- return IntegerConvertNode.convertUnsigned(equals.getX(), stamp);
- } else if (constTrueValue == 0 && constFalseValue == 1) {
- // negate a boolean value via xor
- return IntegerConvertNode.convertUnsigned(XorNode.create(equals.getX(), ConstantNode.forIntegerStamp(equals.getX().stamp(), 1)), stamp);
- }
- }
- }
- }
- } else if (condition instanceof IntegerTestNode) {
- // replace IntegerTestNode with AndNode for the following patterns:
- // (value & 1) == 0 ? 0 : 1
- // (value & 1) == 1 ? 1 : 0
- IntegerTestNode integerTestNode = (IntegerTestNode) condition;
- if (integerTestNode.getY().isConstant()) {
- assert integerTestNode.getX().stamp() instanceof IntegerStamp;
- long testY = integerTestNode.getY().asJavaConstant().asLong();
- if (testY == 1 && constTrueValue == 0 && constFalseValue == 1) {
- return IntegerConvertNode.convertUnsigned(AndNode.create(integerTestNode.getX(), integerTestNode.getY()), stamp);
- }
- }
- }
+ if (trueValue == falseValue) {
+ return trueValue;
}
+
if (condition instanceof CompareNode && ((CompareNode) condition).isIdentityComparison()) {
// optimize the pattern (x == y) ? x : y
CompareNode compare = (CompareNode) condition;
@@ -195,25 +155,87 @@
return falseValue;
}
}
- if (trueValue == falseValue) {
- return trueValue;
- }
+
+ if (trueValue.stamp() instanceof IntegerStamp) {
+ // check if the conditional is redundant
+ if (condition instanceof IntegerLessThanNode) {
+ IntegerLessThanNode lessThan = (IntegerLessThanNode) condition;
+ IntegerStamp falseValueStamp = (IntegerStamp) falseValue.stamp();
+ IntegerStamp trueValueStamp = (IntegerStamp) trueValue.stamp();
+ if (lessThan.getX() == trueValue && lessThan.getY() == falseValue) {
+ // return "x" for "x < y ? x : y" in case that we know "x <= y"
+ if (trueValueStamp.upperBound() <= falseValueStamp.lowerBound()) {
+ return trueValue;
+ }
+ } else if (lessThan.getX() == falseValue && lessThan.getY() == trueValue) {
+ // return "x" for "x < y ? y : x" in case that we know "x <= y"
+ if (falseValueStamp.upperBound() <= trueValueStamp.lowerBound()) {
+ return falseValue;
+ }
+ }
+ }
- if (condition instanceof IntegerLessThanNode && trueValue.stamp() instanceof IntegerStamp) {
- /*
- * Convert a conditional add ((x < 0) ? (x + y) : x) into (x + (y & (x >> (bits - 1))))
- * to avoid the test.
- */
- IntegerLessThanNode lt = (IntegerLessThanNode) condition;
- if (lt.getY().isConstant() && lt.getY().asConstant().isDefaultForKind()) {
- if (falseValue == lt.getX()) {
- if (trueValue instanceof AddNode) {
- AddNode add = (AddNode) trueValue;
- if (add.getX() == falseValue) {
- int bits = ((IntegerStamp) trueValue.stamp()).getBits();
- ValueNode shift = new RightShiftNode(lt.getX(), ConstantNode.forIntegerBits(32, bits - 1));
- ValueNode and = new AndNode(shift, add.getY());
- return new AddNode(add.getX(), and);
+ // this optimizes the case where a value from the range 0 - 1 is mapped to the
+ // range 0 - 1
+ if (trueValue.isConstant() && falseValue.isConstant()) {
+ long constTrueValue = trueValue.asJavaConstant().asLong();
+ long constFalseValue = falseValue.asJavaConstant().asLong();
+ if (condition instanceof IntegerEqualsNode) {
+ IntegerEqualsNode equals = (IntegerEqualsNode) condition;
+ if (equals.getY().isConstant() && equals.getX().stamp() instanceof IntegerStamp) {
+ IntegerStamp equalsXStamp = (IntegerStamp) equals.getX().stamp();
+ if (equalsXStamp.upMask() == 1) {
+ long equalsY = equals.getY().asJavaConstant().asLong();
+ if (equalsY == 0) {
+ if (constTrueValue == 0 && constFalseValue == 1) {
+ // return x when: x == 0 ? 0 : 1;
+ return IntegerConvertNode.convertUnsigned(equals.getX(), stamp);
+ } else if (constTrueValue == 1 && constFalseValue == 0) {
+ // negate a boolean value via xor
+ return IntegerConvertNode.convertUnsigned(XorNode.create(equals.getX(), ConstantNode.forIntegerStamp(equals.getX().stamp(), 1)), stamp);
+ }
+ } else if (equalsY == 1) {
+ if (constTrueValue == 1 && constFalseValue == 0) {
+ // return x when: x == 1 ? 1 : 0;
+ return IntegerConvertNode.convertUnsigned(equals.getX(), stamp);
+ } else if (constTrueValue == 0 && constFalseValue == 1) {
+ // negate a boolean value via xor
+ return IntegerConvertNode.convertUnsigned(XorNode.create(equals.getX(), ConstantNode.forIntegerStamp(equals.getX().stamp(), 1)), stamp);
+ }
+ }
+ }
+ }
+ } else if (condition instanceof IntegerTestNode) {
+ // replace IntegerTestNode with AndNode for the following patterns:
+ // (value & 1) == 0 ? 0 : 1
+ // (value & 1) == 1 ? 1 : 0
+ IntegerTestNode integerTestNode = (IntegerTestNode) condition;
+ if (integerTestNode.getY().isConstant()) {
+ assert integerTestNode.getX().stamp() instanceof IntegerStamp;
+ long testY = integerTestNode.getY().asJavaConstant().asLong();
+ if (testY == 1 && constTrueValue == 0 && constFalseValue == 1) {
+ return IntegerConvertNode.convertUnsigned(AndNode.create(integerTestNode.getX(), integerTestNode.getY()), stamp);
+ }
+ }
+ }
+ }
+
+ if (condition instanceof IntegerLessThanNode) {
+ /*
+ * Convert a conditional add ((x < 0) ? (x + y) : x) into (x + (y & (x >> (bits -
+ * 1)))) to avoid the test.
+ */
+ IntegerLessThanNode lt = (IntegerLessThanNode) condition;
+ if (lt.getY().isConstant() && lt.getY().asConstant().isDefaultForKind()) {
+ if (falseValue == lt.getX()) {
+ if (trueValue instanceof AddNode) {
+ AddNode add = (AddNode) trueValue;
+ if (add.getX() == falseValue) {
+ int bits = ((IntegerStamp) trueValue.stamp()).getBits();
+ ValueNode shift = new RightShiftNode(lt.getX(), ConstantNode.forIntegerBits(32, bits - 1));
+ ValueNode and = new AndNode(shift, add.getY());
+ return new AddNode(add.getX(), and);
+ }
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/DivNode.java Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 org.graalvm.compiler.nodes.calc;
-
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_32;
-
-import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
-import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
-import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Div;
-import org.graalvm.compiler.core.common.type.Stamp;
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.graph.spi.CanonicalizerTool;
-import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.ConstantNode;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-
-import jdk.vm.ci.code.CodeUtil;
-import jdk.vm.ci.meta.Constant;
-import jdk.vm.ci.meta.PrimitiveConstant;
-
-@NodeInfo(shortName = "/", cycles = CYCLES_32)
-public class DivNode extends BinaryArithmeticNode<Div> {
-
- public static final NodeClass<DivNode> TYPE = NodeClass.create(DivNode.class);
-
- public DivNode(ValueNode x, ValueNode y) {
- super(TYPE, ArithmeticOpTable::getDiv, x, y);
- }
-
- protected DivNode(NodeClass<? extends DivNode> c, ValueNode x, ValueNode y) {
- super(c, ArithmeticOpTable::getDiv, x, y);
- }
-
- public static ValueNode create(ValueNode x, ValueNode y) {
- BinaryOp<Div> op = ArithmeticOpTable.forStamp(x.stamp()).getDiv();
- Stamp stamp = op.foldStamp(x.stamp(), y.stamp());
- ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp);
- if (tryConstantFold != null) {
- return tryConstantFold;
- }
- return canonical(null, op, x, y);
- }
-
- @Override
- public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
- ValueNode ret = super.canonical(tool, forX, forY);
- if (ret != this) {
- return ret;
- }
-
- return canonical(this, getOp(forX, forY), forX, forY);
- }
-
- private static ValueNode canonical(DivNode self, BinaryOp<Div> op, ValueNode forX, ValueNode forY) {
- if (forY.isConstant()) {
- Constant c = forY.asConstant();
- if (op.isNeutral(c)) {
- return forX;
- }
- if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) {
- long i = ((PrimitiveConstant) c).asLong();
- boolean signFlip = false;
- if (i < 0) {
- i = -i;
- signFlip = true;
- }
- ValueNode divResult = null;
- if (CodeUtil.isPowerOf2(i)) {
- divResult = new RightShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(i)));
- }
- if (divResult != null) {
- if (signFlip) {
- return NegateNode.create(divResult);
- } else {
- return divResult;
- }
- }
- }
- }
- return self != null ? self : new DivNode(forX, forY);
- }
-
- @Override
- public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
- nodeValueMap.setResult(this, gen.emitDiv(nodeValueMap.operand(getX()), nodeValueMap.operand(getY()), null));
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/FloatDivNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 org.graalvm.compiler.nodes.calc;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_32;
+
+import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
+import org.graalvm.compiler.core.common.type.FloatStamp;
+import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
+import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Div;
+import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ConstantNode;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+
+import jdk.vm.ci.meta.Constant;
+
+@NodeInfo(shortName = "/", cycles = CYCLES_32)
+public class FloatDivNode extends BinaryArithmeticNode<Div> {
+
+ public static final NodeClass<FloatDivNode> TYPE = NodeClass.create(FloatDivNode.class);
+
+ public FloatDivNode(ValueNode x, ValueNode y) {
+ this(TYPE, x, y);
+ }
+
+ protected FloatDivNode(NodeClass<? extends FloatDivNode> c, ValueNode x, ValueNode y) {
+ super(c, ArithmeticOpTable::getDiv, x, y);
+ assert stamp instanceof FloatStamp;
+ }
+
+ public static ValueNode create(ValueNode x, ValueNode y) {
+ BinaryOp<Div> op = ArithmeticOpTable.forStamp(x.stamp()).getDiv();
+ Stamp stamp = op.foldStamp(x.stamp(), y.stamp());
+ ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp);
+ if (tryConstantFold != null) {
+ return tryConstantFold;
+ }
+ return canonical(null, op, x, y);
+ }
+
+ @Override
+ public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+ ValueNode ret = super.canonical(tool, forX, forY);
+ if (ret != this) {
+ return ret;
+ }
+
+ return canonical(this, getOp(forX, forY), forX, forY);
+ }
+
+ private static ValueNode canonical(FloatDivNode self, BinaryOp<Div> op, ValueNode forX, ValueNode forY) {
+ if (forY.isConstant()) {
+ Constant c = forY.asConstant();
+ if (op.isNeutral(c)) {
+ return forX;
+ }
+ }
+ return self != null ? self : new FloatDivNode(forX, forY);
+ }
+
+ @Override
+ public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
+ nodeValueMap.setResult(this, gen.emitDiv(nodeValueMap.operand(getX()), nodeValueMap.operand(getY()), null));
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerConvertNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerConvertNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -129,7 +129,7 @@
ValueNode convert = convert(input, stamp, false);
if (!convert.isAlive()) {
assert !convert.isDeleted();
- convert = graph.addOrUnique(convert);
+ convert = graph.addOrUniqueWithInputs(convert);
}
return convert;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -52,7 +52,7 @@
@NodeInfo(shortName = "<")
public final class IntegerLessThanNode extends IntegerLowerThanNode {
public static final NodeClass<IntegerLessThanNode> TYPE = NodeClass.create(IntegerLessThanNode.class);
- public static final LessThanOp OP = new LessThanOp();
+ private static final LessThanOp OP = new LessThanOp();
public IntegerLessThanNode(ValueNode x, ValueNode y) {
super(TYPE, x, y, OP);
@@ -203,49 +203,52 @@
}
}
- int bits = ((IntegerStamp) forX.stamp()).getBits();
- assert ((IntegerStamp) forY.stamp()).getBits() == bits;
- long min = OP.minValue(bits);
- long xResidue = 0;
- ValueNode left = null;
- JavaConstant leftCst = null;
- if (forX instanceof AddNode) {
- AddNode xAdd = (AddNode) forX;
- if (xAdd.getY().isJavaConstant()) {
- long xCst = xAdd.getY().asJavaConstant().asLong();
- xResidue = xCst - min;
- left = xAdd.getX();
+ if (forX.stamp() instanceof IntegerStamp) {
+ assert forY.stamp() instanceof IntegerStamp;
+ int bits = ((IntegerStamp) forX.stamp()).getBits();
+ assert ((IntegerStamp) forY.stamp()).getBits() == bits;
+ long min = OP.minValue(bits);
+ long xResidue = 0;
+ ValueNode left = null;
+ JavaConstant leftCst = null;
+ if (forX instanceof AddNode) {
+ AddNode xAdd = (AddNode) forX;
+ if (xAdd.getY().isJavaConstant()) {
+ long xCst = xAdd.getY().asJavaConstant().asLong();
+ xResidue = xCst - min;
+ left = xAdd.getX();
+ }
+ } else if (forX.isJavaConstant()) {
+ leftCst = forX.asJavaConstant();
}
- } else if (forX.isJavaConstant()) {
- leftCst = forX.asJavaConstant();
- }
- if (left != null || leftCst != null) {
- long yResidue = 0;
- ValueNode right = null;
- JavaConstant rightCst = null;
- if (forY instanceof AddNode) {
- AddNode yAdd = (AddNode) forY;
- if (yAdd.getY().isJavaConstant()) {
- long yCst = yAdd.getY().asJavaConstant().asLong();
- yResidue = yCst - min;
- right = yAdd.getX();
+ if (left != null || leftCst != null) {
+ long yResidue = 0;
+ ValueNode right = null;
+ JavaConstant rightCst = null;
+ if (forY instanceof AddNode) {
+ AddNode yAdd = (AddNode) forY;
+ if (yAdd.getY().isJavaConstant()) {
+ long yCst = yAdd.getY().asJavaConstant().asLong();
+ yResidue = yCst - min;
+ right = yAdd.getX();
+ }
+ } else if (forY.isJavaConstant()) {
+ rightCst = forY.asJavaConstant();
}
- } else if (forY.isJavaConstant()) {
- rightCst = forY.asJavaConstant();
- }
- if (right != null || rightCst != null) {
- if ((xResidue == 0 && left != null) || (yResidue == 0 && right != null)) {
- if (left == null) {
- left = ConstantNode.forIntegerBits(bits, leftCst.asLong() - min);
- } else if (xResidue != 0) {
- left = AddNode.create(left, ConstantNode.forIntegerBits(bits, xResidue));
+ if (right != null || rightCst != null) {
+ if ((xResidue == 0 && left != null) || (yResidue == 0 && right != null)) {
+ if (left == null) {
+ left = ConstantNode.forIntegerBits(bits, leftCst.asLong() - min);
+ } else if (xResidue != 0) {
+ left = AddNode.create(left, ConstantNode.forIntegerBits(bits, xResidue));
+ }
+ if (right == null) {
+ right = ConstantNode.forIntegerBits(bits, rightCst.asLong() - min);
+ } else if (yResidue != 0) {
+ right = AddNode.create(right, ConstantNode.forIntegerBits(bits, yResidue));
+ }
+ return new IntegerBelowNode(left, right);
}
- if (right == null) {
- right = ConstantNode.forIntegerBits(bits, rightCst.asLong() - min);
- } else if (yResidue != 0) {
- right = AddNode.create(right, ConstantNode.forIntegerBits(bits, yResidue));
- }
- return new IntegerBelowNode(left, right);
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -121,7 +121,8 @@
@Override
public Stamp getSucceedingStampForValue(boolean negated) {
- AbstractPointerStamp pointerStamp = (AbstractPointerStamp) getValue().stamp();
+ // Ignore any more precise input stamp since canonicalization will skip through PiNodes
+ AbstractPointerStamp pointerStamp = (AbstractPointerStamp) getValue().stamp().unrestricted();
return negated ? pointerStamp.asNonNull() : pointerStamp.asAlwaysNull();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -63,29 +63,9 @@
return ConstantNode.forIntegerStamp(stamp(), forX.asJavaConstant().asLong() / y);
} else if (forY.isConstant()) {
long c = forY.asJavaConstant().asLong();
- if (c == 1) {
- return forX;
- }
- if (c == -1) {
- return NegateNode.create(forX);
- }
- long abs = Math.abs(c);
- if (CodeUtil.isPowerOf2(abs) && forX.stamp() instanceof IntegerStamp) {
- ValueNode dividend = forX;
- IntegerStamp stampX = (IntegerStamp) forX.stamp();
- int log2 = CodeUtil.log2(abs);
- // no rounding if dividend is positive or if its low bits are always 0
- if (stampX.canBeNegative() || (stampX.upMask() & (abs - 1)) != 0) {
- int bits = PrimitiveStamp.getBits(stamp());
- RightShiftNode sign = new RightShiftNode(forX, ConstantNode.forInt(bits - 1));
- UnsignedRightShiftNode round = new UnsignedRightShiftNode(sign, ConstantNode.forInt(bits - log2));
- dividend = BinaryArithmeticNode.add(dividend, round);
- }
- RightShiftNode shift = new RightShiftNode(dividend, ConstantNode.forInt(log2));
- if (c < 0) {
- return NegateNode.create(shift);
- }
- return shift;
+ ValueNode v = canonical(forX, c);
+ if (v != null) {
+ return v;
}
}
@@ -113,6 +93,34 @@
return this;
}
+ public static ValueNode canonical(ValueNode forX, long c) {
+ if (c == 1) {
+ return forX;
+ }
+ if (c == -1) {
+ return NegateNode.create(forX);
+ }
+ long abs = Math.abs(c);
+ if (CodeUtil.isPowerOf2(abs) && forX.stamp() instanceof IntegerStamp) {
+ ValueNode dividend = forX;
+ IntegerStamp stampX = (IntegerStamp) forX.stamp();
+ int log2 = CodeUtil.log2(abs);
+ // no rounding if dividend is positive or if its low bits are always 0
+ if (stampX.canBeNegative() || (stampX.upMask() & (abs - 1)) != 0) {
+ int bits = PrimitiveStamp.getBits(forX.stamp());
+ RightShiftNode sign = new RightShiftNode(forX, ConstantNode.forInt(bits - 1));
+ UnsignedRightShiftNode round = new UnsignedRightShiftNode(sign, ConstantNode.forInt(bits - log2));
+ dividend = BinaryArithmeticNode.add(dividend, round);
+ }
+ RightShiftNode shift = new RightShiftNode(dividend, ConstantNode.forInt(log2));
+ if (c < 0) {
+ return NegateNode.create(shift);
+ }
+ return shift;
+ }
+ return null;
+ }
+
@Override
public void generate(NodeLIRBuilderTool gen) {
gen.setResult(this, gen.getLIRGeneratorTool().getArithmetic().emitDiv(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -72,13 +72,14 @@
return ConstantNode.forIntegerStamp(stamp(), 0);
} else if (CodeUtil.isPowerOf2(constY)) {
if (xStamp.isPositive()) {
+ // x & (y - 1)
return new AndNode(forX, ConstantNode.forIntegerStamp(stamp(), constY - 1));
} else if (xStamp.isNegative()) {
+ // -((-x) & (y - 1))
return new NegateNode(new AndNode(new NegateNode(forX), ConstantNode.forIntegerStamp(stamp(), constY - 1)));
} else {
- return new ConditionalNode(IntegerLessThanNode.create(forX, ConstantNode.forIntegerStamp(forX.stamp(), 0)),
- new NegateNode(new AndNode(new NegateNode(forX), ConstantNode.forIntegerStamp(stamp(), constY - 1))),
- new AndNode(forX, ConstantNode.forIntegerStamp(stamp(), constY - 1)));
+ // x - ((x / y) << log2(y))
+ return SubNode.create(forX, LeftShiftNode.create(SignedDivNode.canonical(forX, constY), ConstantNode.forInt(CodeUtil.log2(constY))));
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnaryNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnaryNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -45,6 +45,11 @@
return value;
}
+ public void setValue(ValueNode value) {
+ updateUsages(this.value, value);
+ this.value = value;
+ }
+
/**
* Creates a new UnaryNode instance.
*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnpackEndianHalfNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.nodes.calc;
+
+import java.nio.ByteOrder;
+
+import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.nodeinfo.NodeCycles;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ConstantNode;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.spi.Lowerable;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+
+import jdk.vm.ci.meta.JavaKind;
+
+/**
+ * Produces the platform dependent first or second half of a long or double value as an int.
+ */
+@NodeInfo(cycles = NodeCycles.CYCLES_2)
+public final class UnpackEndianHalfNode extends UnaryNode implements Lowerable {
+ public static final NodeClass<UnpackEndianHalfNode> TYPE = NodeClass.create(UnpackEndianHalfNode.class);
+
+ private final boolean firstHalf;
+
+ protected UnpackEndianHalfNode(ValueNode value, boolean firstHalf) {
+ super(TYPE, StampFactory.forKind(JavaKind.Int), value);
+ assert value.getStackKind() == JavaKind.Double || value.getStackKind() == JavaKind.Long : "unexpected kind " + value.getStackKind();
+ this.firstHalf = firstHalf;
+ }
+
+ public static ValueNode create(ValueNode value, boolean firstHalf) {
+ if (value.isConstant() && value.asConstant().isDefaultForKind()) {
+ return ConstantNode.defaultForKind(JavaKind.Int);
+ }
+ return new UnpackEndianHalfNode(value, firstHalf);
+ }
+
+ public boolean isFirstHalf() {
+ return firstHalf;
+ }
+
+ @Override
+ public Node canonical(CanonicalizerTool tool, ValueNode forValue) {
+ if (forValue.isConstant() && forValue.asConstant().isDefaultForKind()) {
+ return ConstantNode.defaultForKind(stamp.getStackKind());
+ }
+ return this;
+ }
+
+ @Override
+ public void lower(LoweringTool tool) {
+ tool.getLowerer().lower(this, tool);
+ }
+
+ public void lower(ByteOrder byteOrder) {
+ ValueNode result = value;
+ if (value.getStackKind() == JavaKind.Double) {
+ result = graph().unique(new ReinterpretNode(JavaKind.Long, value));
+ }
+ if ((byteOrder == ByteOrder.BIG_ENDIAN) == firstHalf) {
+ result = graph().unique(new UnsignedRightShiftNode(result, ConstantNode.forInt(32, graph())));
+ }
+ result = IntegerConvertNode.convert(result, StampFactory.forKind(JavaKind.Int), graph());
+ replaceAtUsagesAndDelete(result);
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java Thu Nov 16 10:45:42 2017 -0800
@@ -592,7 +592,11 @@
for (Block block : reversePostOrder) {
AbstractBeginNode beginNode = block.getBeginNode();
if (beginNode instanceof LoopBeginNode) {
- Loop<Block> loop = new HIRLoop(block.getLoop(), loops.size(), block);
+ Loop<Block> parent = block.getLoop();
+ Loop<Block> loop = new HIRLoop(parent, loops.size(), block);
+ if (parent != null) {
+ parent.getChildren().add(loop);
+ }
loops.add(loop);
block.setLoop(loop);
loop.getBlocks().add(block);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -82,6 +82,9 @@
@Override
public void simplify(SimplifierTool tool) {
+ if (!hasUsages()) {
+ return;
+ }
if (probability.isConstant()) {
double probabilityValue = probability.asJavaConstant().asDouble();
if (probabilityValue < 0.0) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -79,7 +79,7 @@
super(TYPE, stamp, object, offset, accessKind, locationIdentity, false);
}
- public RawLoadNode(NodeClass<? extends RawLoadNode> c, ValueNode object, ValueNode offset, JavaKind accessKind, LocationIdentity locationIdentity) {
+ protected RawLoadNode(NodeClass<? extends RawLoadNode> c, ValueNode object, ValueNode offset, JavaKind accessKind, LocationIdentity locationIdentity) {
super(c, StampFactory.forKind(accessKind.getStackKind()), object, offset, accessKind, locationIdentity, false);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -29,7 +29,6 @@
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.StateSplit;
import org.graalvm.compiler.nodes.ValueNode;
@@ -39,12 +38,10 @@
import org.graalvm.compiler.nodes.spi.LoweringTool;
import org.graalvm.compiler.nodes.spi.Virtualizable;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
-import org.graalvm.compiler.nodes.type.StampTool;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import org.graalvm.word.LocationIdentity;
import jdk.vm.ci.meta.Assumptions;
-import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaField;
@@ -123,41 +120,8 @@
if (indexValue.isConstant()) {
long off = indexValue.asJavaConstant().asLong();
int entryIndex = virtual.entryIndexForOffset(off, accessKind());
- if (entryIndex != -1) {
- JavaKind entryKind = virtual.entryKind(entryIndex);
- boolean canVirtualize = entryKind == accessKind() || (entryKind == accessKind().getStackKind() && !StampTool.typeOrNull(object()).isArray());
- if (!canVirtualize) {
- /*
- * Special case: If the entryKind is long, allow arbitrary kinds as long as
- * a value of the same kind is already there. This can only happen if some
- * other node initialized the entry with a value of a different kind. One
- * example where this happens is the Truffle NewFrameNode.
- */
- ValueNode entry = tool.getEntry(virtual, entryIndex);
- if (entryKind == JavaKind.Long && entry.getStackKind() == value.getStackKind()) {
- canVirtualize = true;
- }
- }
- if (canVirtualize) {
- tool.setVirtualEntry(virtual, entryIndex, value(), true);
- tool.delete();
- } else {
- /*
- * Special case: Allow storing a single long or double value into two
- * consecutive int slots.
- */
- if ((accessKind() == JavaKind.Long || accessKind() == JavaKind.Double) && entryKind == JavaKind.Int) {
- int nextIndex = virtual.entryIndexForOffset(off + 4, entryKind);
- if (nextIndex != -1) {
- JavaKind nextKind = virtual.entryKind(nextIndex);
- if (nextKind == JavaKind.Int) {
- tool.setVirtualEntry(virtual, entryIndex, value(), true);
- tool.setVirtualEntry(virtual, nextIndex, ConstantNode.forConstant(JavaConstant.forIllegal(), tool.getMetaAccessProvider(), graph()), true);
- tool.delete();
- }
- }
- }
- }
+ if (entryIndex != -1 && tool.setVirtualEntry(virtual, entryIndex, value(), accessKind(), off)) {
+ tool.delete();
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java Thu Nov 16 10:45:42 2017 -0800
@@ -280,7 +280,7 @@
ObjectStamp receiverStamp = (ObjectStamp) value.stamp();
Stamp stamp = receiverStamp.join(objectNonNull());
FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, NullCheckException, action, true));
- ValueNode nonNullReceiver = getGraph().addOrUnique(PiNode.create(value, stamp, fixedGuard));
+ ValueNode nonNullReceiver = getGraph().addOrUniqueWithInputs(PiNode.create(value, stamp, fixedGuard));
// TODO: Propogating the non-null into the frame state would
// remove subsequent null-checks on the same value. However,
// it currently causes an assertion failure when merging states.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InlineInvokePlugin.java Thu Nov 16 10:45:42 2017 -0800
@@ -53,6 +53,12 @@
*/
public static final InlineInfo DO_NOT_INLINE_NO_EXCEPTION = new InlineInfo(null, null);
+ /**
+ * Denotes a call site must not be inlined and the execution should be transferred to
+ * interpreter in case of an exception.
+ */
+ public static final InlineInfo DO_NOT_INLINE_DEOPTIMIZE_ON_EXCEPTION = new InlineInfo(null, null);
+
private final ResolvedJavaMethod methodToInline;
private final BytecodeProvider intrinsicBytecodeProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java Thu Nov 16 10:45:42 2017 -0800
@@ -66,6 +66,34 @@
*/
final BytecodeProvider bytecodeProvider;
+ final CompilationContext compilationContext;
+
+ final boolean allowPartialIntrinsicArgumentMismatch;
+
+ public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod intrinsic, BytecodeProvider bytecodeProvider, CompilationContext compilationContext) {
+ this(method, intrinsic, bytecodeProvider, compilationContext, false);
+ }
+
+ public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod intrinsic, BytecodeProvider bytecodeProvider, CompilationContext compilationContext,
+ boolean allowPartialIntrinsicArgumentMismatch) {
+ this.method = method;
+ this.intrinsic = intrinsic;
+ this.bytecodeProvider = bytecodeProvider;
+ assert bytecodeProvider != null;
+ this.compilationContext = compilationContext;
+ this.allowPartialIntrinsicArgumentMismatch = allowPartialIntrinsicArgumentMismatch;
+ assert !isCompilationRoot() || method.hasBytecodes() : "Cannot root compile intrinsic for native or abstract method " + method.format("%H.%n(%p)");
+ }
+
+ /**
+ * A partial intrinsic exits by (effectively) calling the intrinsified method. Normally, this
+ * call must use exactly the same arguments as the call that is being intrinsified. This allows
+ * to override this behavior.
+ */
+ public boolean allowPartialIntrinsicArgumentMismatch() {
+ return allowPartialIntrinsicArgumentMismatch;
+ }
+
/**
* Gets the method being intrinsified.
*/
@@ -96,17 +124,6 @@
return method.equals(targetMethod) || intrinsic.equals(targetMethod);
}
- final CompilationContext compilationContext;
-
- public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod intrinsic, BytecodeProvider bytecodeProvider, CompilationContext compilationContext) {
- this.method = method;
- this.intrinsic = intrinsic;
- this.bytecodeProvider = bytecodeProvider;
- assert bytecodeProvider != null;
- this.compilationContext = compilationContext;
- assert !isCompilationRoot() || method.hasBytecodes() : "Cannot root compile intrinsic for native or abstract method " + method.format("%H.%n(%p)");
- }
-
public boolean isPostParseInlined() {
return compilationContext.equals(INLINE_AFTER_PARSING);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -49,6 +49,8 @@
import jdk.vm.ci.meta.JavaTypeProfile;
import jdk.vm.ci.meta.TriState;
+import java.util.Objects;
+
/**
* The {@code InstanceOfNode} represents an instanceof test.
*/
@@ -56,7 +58,7 @@
public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtualizable {
public static final NodeClass<InstanceOfNode> TYPE = NodeClass.create(InstanceOfNode.class);
- protected final ObjectStamp checkedStamp;
+ private ObjectStamp checkedStamp;
private JavaTypeProfile profile;
@OptionalInput(Anchor) protected AnchoringNode anchor;
@@ -126,7 +128,9 @@
// The check will always succeed, the union of the two stamps is equal to the
// checked stamp.
return LogicConstantNode.tautology();
- } else if (checkedStamp.type().equals(meetStamp.type()) && checkedStamp.isExactType() == meetStamp.isExactType() && checkedStamp.alwaysNull() == meetStamp.alwaysNull()) {
+ } else if (checkedStamp.alwaysNull()) {
+ return IsNullNode.create(object);
+ } else if (Objects.equals(checkedStamp.type(), meetStamp.type()) && checkedStamp.isExactType() == meetStamp.isExactType() && checkedStamp.alwaysNull() == meetStamp.alwaysNull()) {
assert checkedStamp.nonNull() != inputStamp.nonNull();
// The only difference makes the null-ness of the value => simplify the check.
if (checkedStamp.nonNull()) {
@@ -135,8 +139,8 @@
return IsNullNode.create(object);
}
}
+ assert checkedStamp.type() != null;
}
-
return null;
}
@@ -204,4 +208,13 @@
public AnchoringNode getAnchor() {
return anchor;
}
+
+ public ObjectStamp getCheckedStamp() {
+ return checkedStamp;
+ }
+
+ public void strengthenCheckedStamp(ObjectStamp newCheckedStamp) {
+ assert this.checkedStamp.join(newCheckedStamp).equals(newCheckedStamp) : "stamp can only improve";
+ this.checkedStamp = newCheckedStamp;
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadFieldNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadFieldNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -25,7 +25,6 @@
import static org.graalvm.compiler.graph.iterators.NodePredicates.isNotA;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
-import jdk.vm.ci.meta.ConstantReflectionProvider;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
@@ -47,15 +46,16 @@
import org.graalvm.compiler.nodes.util.ConstantFoldUtil;
import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
+import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.meta.Assumptions;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.DeoptimizationAction;
import jdk.vm.ci.meta.DeoptimizationReason;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaField;
-import org.graalvm.compiler.options.OptionValues;
/**
* The {@code LoadFieldNode} represents a read of a static or instance field.
@@ -150,7 +150,7 @@
}
public ConstantNode asConstant(CanonicalizerTool tool, JavaConstant constant) {
- return ConstantFoldUtil.tryConstantFold(tool.getConstantFieldProvider(), tool.getConstantReflection(), tool.getMetaAccess(), field(), constant, getOptions());
+ return ConstantFoldUtil.tryConstantFold(tool.getConstantFieldProvider(), tool.getConstantReflection(), tool.getMetaAccess(), field(), constant, tool.getOptions());
}
private static PhiNode asPhi(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreFieldNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreFieldNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -29,7 +29,6 @@
import org.graalvm.compiler.nodeinfo.InputType;
import org.graalvm.compiler.nodeinfo.NodeCycles;
import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.StateSplit;
import org.graalvm.compiler.nodes.ValueNode;
@@ -38,7 +37,6 @@
import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.ResolvedJavaField;
/**
@@ -90,15 +88,8 @@
VirtualInstanceNode virtual = (VirtualInstanceNode) alias;
int fieldIndex = virtual.fieldIndex(field());
if (fieldIndex != -1) {
- ValueNode existing = tool.getEntry((VirtualObjectNode) alias, fieldIndex);
- if (existing.stamp().isCompatible(value().stamp())) {
- tool.setVirtualEntry(virtual, fieldIndex, value(), false);
- tool.delete();
- } else {
- // stamp of the value is not compatible with the value in the virtualizer
- // can only happen with unsafe two slot writes on one slot fields
- assert existing instanceof ConstantNode && ((ConstantNode) existing).asConstant().equals(JavaConstant.forIllegal()) : value.stamp() + " vs " + existing.stamp();
- }
+ tool.setVirtualEntry(virtual, fieldIndex, value());
+ tool.delete();
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreIndexedNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreIndexedNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -89,7 +89,7 @@
ResolvedJavaType componentType = virtual.type().getComponentType();
if (componentType.isPrimitive() || StampTool.isPointerAlwaysNull(value) || componentType.getSuperclass() == null ||
(StampTool.typeReferenceOrNull(value) != null && componentType.isAssignableFrom(StampTool.typeOrNull(value)))) {
- tool.setVirtualEntry(virtual, idx, value(), false);
+ tool.setVirtualEntry(virtual, idx, value());
tool.delete();
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryPhiNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryPhiNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -62,4 +62,9 @@
public NodeInputList<ValueNode> values() {
return values;
}
+
+ @Override
+ protected String valueDescription() {
+ return locationIdentity.toString();
+ }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/address/OffsetAddressNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/address/OffsetAddressNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.nodes.memory.address;
+import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.Node;
@@ -52,6 +53,9 @@
super(TYPE);
this.base = base;
this.offset = offset;
+
+ assert base != null && (base.stamp() instanceof AbstractPointerStamp || IntegerStamp.getBits(base.stamp()) == 64) &&
+ offset != null && IntegerStamp.getBits(offset.stamp()) == 64 : "both values must have 64 bits";
}
@Override
@@ -62,6 +66,7 @@
public void setBase(ValueNode base) {
updateUsages(this.base, base);
this.base = base;
+ assert base != null && (base.stamp() instanceof AbstractPointerStamp || IntegerStamp.getBits(base.stamp()) == 64);
}
public ValueNode getOffset() {
@@ -71,6 +76,7 @@
public void setOffset(ValueNode offset) {
updateUsages(this.offset, offset);
this.offset = offset;
+ assert offset != null && IntegerStamp.getBits(offset.stamp()) == 64;
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/VirtualizerTool.java Thu Nov 16 10:45:42 2017 -0800
@@ -25,6 +25,7 @@
import java.util.List;
import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.java.MonitorIdNode;
@@ -91,9 +92,17 @@
*
* @param index the index to be set.
* @param value the new value for the given index.
- * @param unsafe if true, then mismatching value {@link JavaKind}s will be accepted.
+ * @param accessKind the kind of the store which might be different than
+ * {@link VirtualObjectNode#entryKind(int)}.
+ * @return true if the operation was permitted
*/
- void setVirtualEntry(VirtualObjectNode virtualObject, int index, ValueNode value, boolean unsafe);
+ boolean setVirtualEntry(VirtualObjectNode virtualObject, int index, ValueNode value, JavaKind accessKind, long offset);
+
+ default void setVirtualEntry(VirtualObjectNode virtualObject, int index, ValueNode value) {
+ if (!setVirtualEntry(virtualObject, index, value, null, 0)) {
+ throw new GraalError("unexpected failure when updating virtual entry");
+ }
+ }
ValueNode getEntry(VirtualObjectNode virtualObject, int index);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Thu Nov 16 10:45:42 2017 -0800
@@ -242,7 +242,7 @@
EconomicSet<Node> collectedUnusedNodes = unusedNodes = EconomicSet.create(Equivalence.IDENTITY);
nodeEventScope = node.graph().trackNodeEvents(new Graph.NodeEventListener() {
@Override
- public void event(Graph.NodeEvent e, Node n) {
+ public void changed(Graph.NodeEvent e, Node n) {
if (e == Graph.NodeEvent.ZERO_USAGES && isFloatingNode(n) && !(n instanceof GuardNode)) {
collectedUnusedNodes.add(n);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/JavaConstantFormattable.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.nodes.util;
+
+/**
+ * Performs special formatting of values involving {@link jdk.vm.ci.meta.JavaConstant JavaConstants}
+ * when they are being dumped.
+ */
+public interface JavaConstantFormattable {
+ String format(JavaConstantFormatter formatter);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/JavaConstantFormatter.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.nodes.util;
+
+import jdk.vm.ci.meta.JavaConstant;
+
+public interface JavaConstantFormatter {
+ String format(JavaConstant constant);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualArrayNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -37,7 +37,7 @@
import jdk.vm.ci.meta.ResolvedJavaType;
import sun.misc.Unsafe;
-@NodeInfo(nameTemplate = "VirtualArray {p#componentType/s}[{p#length}]")
+@NodeInfo(nameTemplate = "VirtualArray({p#objectId}) {p#componentType/s}[{p#length}]")
public class VirtualArrayNode extends VirtualObjectNode implements ArrayLengthProvider {
public static final NodeClass<VirtualArrayNode> TYPE = NodeClass.create(VirtualArrayNode.class);
@@ -76,7 +76,7 @@
@Override
public String toString(Verbosity verbosity) {
if (verbosity == Verbosity.Name) {
- return super.toString(Verbosity.Name) + " " + componentType.getName() + "[" + length + "]";
+ return super.toString(Verbosity.Name) + "(" + getObjectId() + ") " + componentType.getName() + "[" + length + "]";
} else {
return super.toString(verbosity);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/VirtualInstanceNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -32,7 +32,7 @@
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaType;
-@NodeInfo(nameTemplate = "VirtualInstance {p#type/s}")
+@NodeInfo(nameTemplate = "VirtualInstance({p#objectId}) {p#type/s}")
public class VirtualInstanceNode extends VirtualObjectNode {
public static final NodeClass<VirtualInstanceNode> TYPE = NodeClass.create(VirtualInstanceNode.class);
@@ -78,7 +78,7 @@
@Override
public String toString(Verbosity verbosity) {
if (verbosity == Verbosity.Name) {
- return super.toString(Verbosity.Name) + " " + type.toJavaName(false);
+ return super.toString(Verbosity.Name) + "(" + getObjectId() + ") " + type.toJavaName(false);
} else {
return super.toString(verbosity);
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java Thu Nov 16 10:45:42 2017 -0800
@@ -394,6 +394,9 @@
options = new OptionsInfo(topDeclaringType);
map.put(topDeclaringType, options);
}
+ if (!element.getEnclosingElement().getSimpleName().toString().endsWith("Options")) {
+ processingEnv.getMessager().printMessage(Kind.ERROR, "Option declaring classes must have a name that ends with 'Options'", element.getEnclosingElement());
+ }
processElement(element, options);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Thu Nov 16 10:45:42 2017 -0800
@@ -248,7 +248,7 @@
/**
* Tests which may be eliminated because post dominating tests to prove a broader condition.
*/
- private Deque<PendingTest> pendingTests;
+ private Deque<DeoptimizingGuard> pendingTests;
public Instance(StructuredGraph graph, BlockMap<List<Node>> blockToNodes, PhaseContext context) {
this.graph = graph;
@@ -555,7 +555,8 @@
}
}
if (guard instanceof DeoptimizingGuard) {
- pendingTests.push(new PendingTest(condition, (DeoptimizingGuard) guard));
+ assert ((DeoptimizingGuard) guard).getCondition() == condition;
+ pendingTests.push((DeoptimizingGuard) guard);
}
registerCondition(condition, negated, guard);
}
@@ -628,15 +629,16 @@
}
protected boolean foldPendingTest(DeoptimizingGuard thisGuard, ValueNode original, Stamp newStamp, GuardRewirer rewireGuardFunction) {
- for (PendingTest pending : pendingTests) {
+ for (DeoptimizingGuard pendingGuard : pendingTests) {
+ LogicNode pendingCondition = pendingGuard.getCondition();
TriState result = TriState.UNKNOWN;
- if (pending.condition instanceof UnaryOpLogicNode) {
- UnaryOpLogicNode unaryLogicNode = (UnaryOpLogicNode) pending.condition;
+ if (pendingCondition instanceof UnaryOpLogicNode) {
+ UnaryOpLogicNode unaryLogicNode = (UnaryOpLogicNode) pendingCondition;
if (unaryLogicNode.getValue() == original) {
result = unaryLogicNode.tryFold(newStamp);
}
- } else if (pending.condition instanceof BinaryOpLogicNode) {
- BinaryOpLogicNode binaryOpLogicNode = (BinaryOpLogicNode) pending.condition;
+ } else if (pendingCondition instanceof BinaryOpLogicNode) {
+ BinaryOpLogicNode binaryOpLogicNode = (BinaryOpLogicNode) pendingCondition;
ValueNode x = binaryOpLogicNode.getX();
ValueNode y = binaryOpLogicNode.getY();
if (x == original) {
@@ -659,7 +661,7 @@
*/
InputFilter v = new InputFilter(original);
thisGuard.getCondition().applyInputs(v);
- if (v.ok && foldGuard(thisGuard, pending.guard, newStamp, rewireGuardFunction)) {
+ if (v.ok && foldGuard(thisGuard, pendingGuard, newStamp, rewireGuardFunction)) {
return true;
}
}
@@ -1026,16 +1028,6 @@
boolean rewire(GuardingNode guard, boolean result, Stamp guardedValueStamp, ValueNode newInput);
}
- protected static class PendingTest {
- private final LogicNode condition;
- private final DeoptimizingGuard guard;
-
- public PendingTest(LogicNode condition, DeoptimizingGuard guard) {
- this.condition = condition;
- this.guard = guard;
- }
- }
-
protected static final class InfoElement {
private final Stamp stamp;
private final GuardingNode guard;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java Thu Nov 16 10:45:42 2017 -0800
@@ -221,7 +221,12 @@
EconomicMap<ValueNode, Stamp> endMap = endMaps.get(node);
MapCursor<ValueNode, Stamp> entries = endMap.getEntries();
while (entries.advance()) {
- if (registerNewValueStamp(entries.getKey(), entries.getValue())) {
+ ValueNode value = entries.getKey();
+ if (value.isDeleted()) {
+ // nodes from this map can be deleted when a loop dies
+ continue;
+ }
+ if (registerNewValueStamp(value, entries.getValue())) {
counterBetterMergedStamps.increment(debug);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java Thu Nov 16 10:45:42 2017 -0800
@@ -48,7 +48,7 @@
import org.graalvm.compiler.nodes.VirtualState;
import org.graalvm.compiler.nodes.calc.BinaryNode;
import org.graalvm.compiler.nodes.calc.ConvertNode;
-import org.graalvm.compiler.nodes.calc.DivNode;
+import org.graalvm.compiler.nodes.calc.FloatDivNode;
import org.graalvm.compiler.nodes.calc.IntegerDivRemNode;
import org.graalvm.compiler.nodes.calc.MulNode;
import org.graalvm.compiler.nodes.calc.NotNode;
@@ -162,7 +162,7 @@
return 2;
} else if (node instanceof LogicNode || node instanceof ConvertNode || node instanceof BinaryNode || node instanceof NotNode) {
return 1;
- } else if (node instanceof IntegerDivRemNode || node instanceof DivNode || node instanceof RemNode) {
+ } else if (node instanceof IntegerDivRemNode || node instanceof FloatDivNode || node instanceof RemNode) {
return 10;
} else if (node instanceof MulNode) {
return 3;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java Thu Nov 16 10:45:42 2017 -0800
@@ -43,7 +43,6 @@
import org.graalvm.compiler.phases.graph.FixedNodeProbabilityCache;
import org.graalvm.compiler.phases.tiers.HighTierContext;
-import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.ResolvedJavaMethod;
/**
@@ -159,11 +158,11 @@
if (param.usages().isNotEmpty()) {
ValueNode arg = args.get(param.index());
if (arg.isConstant()) {
- Constant constant = arg.asConstant();
+ ConstantNode constant = (ConstantNode) arg;
parameterUsages = trackParameterUsages(param, parameterUsages);
// collect param usages before replacing the param
param.replaceAtUsagesAndDelete(graph.unique(
- ConstantNode.forConstant(arg.stamp(), constant, ((ConstantNode) arg).getStableDimension(), ((ConstantNode) arg).isDefaultStable(), context.getMetaAccess())));
+ ConstantNode.forConstant(arg.stamp(), constant.getValue(), constant.getStableDimension(), constant.isDefaultStable(), context.getMetaAccess())));
// param-node gone, leaving a gap in the sequence given by param.index()
} else {
Stamp impro = improvedStamp(arg, param);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java Thu Nov 16 10:45:42 2017 -0800
@@ -37,7 +37,7 @@
* A simple {@link NodeEventListener} implementation that accumulates event nodes in a
* {@link HashSet}.
*/
-public class HashSetNodeEventListener implements NodeEventListener {
+public class HashSetNodeEventListener extends NodeEventListener {
private final EconomicSet<Node> nodes;
private final Set<NodeEvent> filter;
@@ -68,7 +68,7 @@
}
@Override
- public void event(NodeEvent e, Node node) {
+ public void changed(NodeEvent e, Node node) {
if (filter.contains(e)) {
nodes.add(node);
if (node instanceof IndirectCanonicalization) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java Thu Nov 16 10:45:42 2017 -0800
@@ -258,7 +258,7 @@
return false;
}
- private final class GraphChangeListener implements NodeEventListener {
+ private final class GraphChangeListener extends NodeEventListener {
boolean changed;
private StructuredGraph graph;
private Mark mark;
@@ -269,7 +269,7 @@
}
@Override
- public void event(NodeEvent e, Node node) {
+ public void changed(NodeEvent e, Node node) {
if (!graph.isNew(mark, node) && node.isAlive()) {
if (e == NodeEvent.INPUT_CHANGED || e == NodeEvent.ZERO_USAGES) {
changed = true;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java Thu Nov 16 10:45:42 2017 -0800
@@ -109,7 +109,7 @@
if (immutableGraph && Assertions.assertionsEnabled()) {
return graph.trackNodeEvents(new NodeEventListener() {
@Override
- public void event(NodeEvent e, Node node) {
+ public void changed(NodeEvent e, Node node) {
assert false : "graph changed: " + e + " on node " + node;
}
});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGetOptionsUsage.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.phases.verify;
+
+import java.lang.reflect.MalformedParametersException;
+import java.lang.reflect.Method;
+
+import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.phases.VerifyPhase;
+import org.graalvm.compiler.phases.tiers.PhaseContext;
+
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * {@link Node#getOptions()} is unsafe for use during canonicalization so try to verify that it
+ * isn't used when a {@link CanonicalizerTool} is available in the arguments. This is slightly more
+ * general but since there are several canonical methods with varying signatures this covers more
+ * cases.
+ */
+public class VerifyGetOptionsUsage extends VerifyPhase<PhaseContext> {
+ static Method lookupMethod(Class<?> klass, String name) {
+ for (Method m : klass.getDeclaredMethods()) {
+ if (m.getName().equals(name)) {
+ return m;
+ }
+ }
+ throw new InternalError();
+ }
+
+ @Override
+ protected boolean verify(StructuredGraph graph, PhaseContext context) {
+ MetaAccessProvider metaAccess = context.getMetaAccess();
+ ResolvedJavaType canonicalizerToolClass = metaAccess.lookupJavaType(CanonicalizerTool.class);
+ boolean hasTool = false;
+ try {
+ for (ResolvedJavaMethod.Parameter parameter : graph.method().getParameters()) {
+ if (parameter.getType().getName().equals(canonicalizerToolClass.getName())) {
+ hasTool = true;
+ break;
+ }
+ }
+ } catch (MalformedParametersException e) {
+ // Lambdas sometimes have malformed parameters so ignore this.
+ }
+ if (hasTool) {
+ ResolvedJavaMethod getOptionsMethod = metaAccess.lookupJavaMethod(lookupMethod(Node.class, "getOptions"));
+ for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) {
+ ResolvedJavaMethod callee = t.targetMethod();
+ if (callee.equals(getOptionsMethod)) {
+ if (hasTool) {
+ throw new VerificationError("Must use CanonicalizerTool.getOptions() instead of Node.getOptions() in method '%s' of class '%s'.",
+ graph.method().getName(), graph.method().getDeclaringClass().getName());
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.phases.verify;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.graph.Graph;
+import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.nodes.ConstantNode;
+import org.graalvm.compiler.nodes.Invoke;
+import org.graalvm.compiler.nodes.ParameterNode;
+import org.graalvm.compiler.nodes.PiNode;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.ValuePhiNode;
+import org.graalvm.compiler.nodes.ValueProxyNode;
+import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.java.NewInstanceNode;
+import org.graalvm.compiler.nodes.spi.LoweringProvider;
+import org.graalvm.compiler.phases.VerifyPhase;
+import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.graalvm.util.EconomicSet;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+public class VerifyGraphAddUsage extends VerifyPhase<PhaseContext> {
+ private static final Method ADD_OR_UNIQUE;
+ private static final Method CONSTRUCTOR_NEW_INSTANCE;
+ private static final EconomicSet<Class<?>> ALLOWED_CLASSES = EconomicSet.create();
+
+ static {
+ try {
+ ADD_OR_UNIQUE = Graph.class.getDeclaredMethod("addOrUnique", Node.class);
+ CONSTRUCTOR_NEW_INSTANCE = Constructor.class.getDeclaredMethod("newInstance", Object[].class);
+ } catch (NoSuchMethodException e) {
+ throw new GraalError(e);
+ }
+
+ ALLOWED_CLASSES.add(Graph.class);
+ ALLOWED_CLASSES.add(LoweringProvider.class);
+ }
+
+ @Override
+ protected boolean verify(StructuredGraph graph, PhaseContext context) {
+ boolean allowed = false;
+ for (Class<?> cls : ALLOWED_CLASSES) {
+ ResolvedJavaType declaringClass = graph.method().getDeclaringClass();
+ if (context.getMetaAccess().lookupJavaType(cls).isAssignableFrom(declaringClass)) {
+ allowed = true;
+ }
+ }
+ if (!allowed) {
+ ResolvedJavaMethod addOrUniqueMethod = context.getMetaAccess().lookupJavaMethod(ADD_OR_UNIQUE);
+ for (MethodCallTargetNode t : graph.getNodes(MethodCallTargetNode.TYPE)) {
+ ResolvedJavaMethod callee = t.targetMethod();
+ if (callee.equals(addOrUniqueMethod)) {
+ ValueNode nodeArgument = t.arguments().get(1);
+ EconomicSet<Node> seen = EconomicSet.create();
+ checkNonFactory(graph, seen, context, nodeArgument);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private void checkNonFactory(StructuredGraph graph, EconomicSet<Node> seen, PhaseContext context, ValueNode node) {
+ if (seen.contains(node)) {
+ return;
+ }
+ seen.add(node);
+
+ // Check where the value came from recursively, or if it is allowed.
+ if (node instanceof ValuePhiNode) {
+ for (ValueNode input : ((ValuePhiNode) node).values()) {
+ checkNonFactory(graph, seen, context, input);
+ }
+ } else if (node instanceof PiNode) {
+ checkNonFactory(graph, seen, context, ((PiNode) node).object());
+ } else if (node instanceof ParameterNode) {
+ return;
+ } else if (node instanceof ConstantNode) {
+ return;
+ } else if (node instanceof ValueProxyNode) {
+ checkNonFactory(graph, seen, context, ((ValueProxyNode) node).value());
+ } else if (node instanceof Invoke && ((Invoke) node).callTarget().targetMethod().equals(context.getMetaAccess().lookupJavaMethod(CONSTRUCTOR_NEW_INSTANCE))) {
+ return;
+ } else if (!(node instanceof NewInstanceNode)) {
+ // In all other cases, the argument must be a new instance.
+ throw new VerificationError("Must add node '%s' with inputs in method '%s' of class '%s'.",
+ node, graph.method().getName(), graph.method().getDeclaringClass().getName());
+ }
+ }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BasicIdealGraphPrinter.java Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,366 +0,0 @@
-/*
- * Copyright (c) 2011, 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 org.graalvm.compiler.printer;
-
-import java.io.BufferedOutputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * Elementary, generic generator of Ideal Graph Visualizer input for use in printers for specific
- * data structures.
- */
-class BasicIdealGraphPrinter {
-
- /**
- * Edge between two nodes.
- */
- protected static class Edge {
-
- final String from;
- final int fromIndex;
- final String to;
- final int toIndex;
- final String label;
-
- public Edge(String from, int fromIndex, String to, int toIndex, String label) {
- assert (from != null && to != null);
- this.from = from;
- this.fromIndex = fromIndex;
- this.to = to;
- this.toIndex = toIndex;
- this.label = label;
- }
-
- @Override
- public int hashCode() {
- int h = from.hashCode() ^ to.hashCode();
- h = 3 * h + fromIndex;
- h = 5 * h + toIndex;
- if (label != null) {
- h ^= label.hashCode();
- }
- return h;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
- if (obj instanceof Edge) {
- Edge other = (Edge) obj;
- return from.equals(other.from) && fromIndex == other.fromIndex && to.equals(other.to) && toIndex == other.toIndex &&
- (label == other.label || (label != null && label.equals(other.label)));
- }
- return false;
- }
- }
-
- private final PrintStream stream;
-
- /**
- * Creates a new {@link IdealGraphPrinter} that writes to the specified output stream.
- */
- protected BasicIdealGraphPrinter(OutputStream stream) {
- try {
- OutputStream buffered;
- if (stream instanceof BufferedOutputStream) {
- buffered = stream;
- } else {
- buffered = new BufferedOutputStream(stream, 256 * 1024);
- }
- this.stream = new PrintStream(buffered, false, Charset.defaultCharset().name());
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Flushes any buffered output.
- */
- protected void flush() {
- stream.flush();
- }
-
- /**
- * Starts a new graph document.
- */
- protected void begin() {
- stream.println("<graphDocument>");
- }
-
- protected void beginGroup() {
- stream.println("<group>");
- }
-
- protected void beginMethod(String name, String shortName, int bci) {
- stream.printf(" <method name='%s' shortName='%s' bci='%d'>%n", escape(name), escape(shortName), bci);
- }
-
- protected void beginBytecodes() {
- stream.println(" <bytecodes>\n<![CDATA[");
- }
-
- protected void printBytecode(int bci, String mnemonic, int[] extra) {
- stream.print(bci);
- stream.print(' ');
- stream.print(mnemonic);
- if (extra != null) {
- for (int b : extra) {
- stream.print(' ');
- stream.print(b);
- }
- }
- stream.println();
- }
-
- protected void endBytecodes() {
- stream.println(" ]]></bytecodes>");
- }
-
- protected void printBytecodes(String disassembly) {
- beginBytecodes();
- stream.println(disassembly);
- endBytecodes();
- }
-
- protected void endMethod() {
- stream.println(" </method>");
- }
-
- protected void beginGraph(String title) {
- stream.printf(" <graph name='%s'>%n", escape(title));
- }
-
- protected void beginProperties() {
- stream.print("<properties>");
- }
-
- protected void printProperty(String name, String value) {
- stream.printf("<p name='%s'>%s</p>", escape(name), escape(value));
- }
-
- protected void endProperties() {
- stream.print("</properties>");
- }
-
- protected void printProperties(Map<String, String> properties) {
- beginProperties();
- for (Entry<String, String> entry : properties.entrySet()) {
- printProperty(entry.getKey(), entry.getValue());
- }
- endProperties();
- }
-
- protected void beginNodes() {
- stream.println(" <nodes>");
- }
-
- protected void beginNode(String id) {
- stream.printf(" <node id='%s'>", escape(id));
- }
-
- protected void endNode() {
- stream.println(" </node>");
- }
-
- protected void printNode(String id, Map<String, String> properties) {
- beginNode(id);
- if (properties != null) {
- printProperties(properties);
- }
- endNode();
- }
-
- protected void endNodes() {
- stream.println(" </nodes>");
- }
-
- protected void beginEdges() {
- stream.println(" <edges>");
- }
-
- protected void printEdge(Edge edge) {
- stream.printf(" <edge from='%s' fromIndex='%d' to='%s' toIndex='%d' label='%s' />%n", escape(edge.from), edge.fromIndex, escape(edge.to), edge.toIndex, escape(edge.label));
- }
-
- protected void endEdges() {
- stream.println(" </edges>");
- }
-
- protected void beginControlFlow() {
- stream.println(" <controlFlow>");
- }
-
- protected void beginBlock(String name) {
- stream.printf(" <block name='%s'>%n", escape(name));
- }
-
- protected void beginSuccessors() {
- stream.println(" <successors>");
- }
-
- protected void printSuccessor(String name) {
- stream.printf(" <successor name='%s'/>%n", escape(name));
- }
-
- protected void endSuccessors() {
- stream.println(" </successors>");
- }
-
- protected void beginBlockNodes() {
- stream.println(" <nodes>");
- }
-
- protected void printBlockNode(String nodeId) {
- stream.printf(" <node id='%s'/>%n", escape(nodeId));
- }
-
- protected void endBlockNodes() {
- stream.println(" </nodes>");
- }
-
- protected void endBlock() {
- stream.println(" </block>");
- }
-
- protected void endControlFlow() {
- stream.println(" </controlFlow>");
- }
-
- protected void endGraph() {
- stream.println(" </graph>");
- }
-
- /**
- * Ends the current group.
- */
- public void endGroup() {
- stream.println("</group>");
- }
-
- /**
- * Finishes the graph document and flushes the output stream.
- */
- protected void end() {
- stream.println("</graphDocument>");
- flush();
- }
-
- public void close() {
- end();
- stream.close();
- }
-
- public boolean isValid() {
- return !stream.checkError();
- }
-
- private static String escape(String s) {
- StringBuilder str = null;
- for (int i = 0; i < s.length(); i++) {
- char c = s.charAt(i);
- switch (c) {
- case '&':
- case '<':
- case '>':
- case '"':
- case '\'':
- if (str == null) {
- str = new StringBuilder();
- str.append(s, 0, i);
- }
- switch (c) {
- case '&':
- str.append("&");
- break;
- case '<':
- str.append("<");
- break;
- case '>':
- str.append(">");
- break;
- case '"':
- str.append(""");
- break;
- case '\'':
- str.append("'");
- break;
- default:
- assert false;
- }
- break;
- case '\u0000':
- case '\u0001':
- case '\u0002':
- case '\u0003':
- case '\u0004':
- case '\u0005':
- case '\u0006':
- case '\u0007':
- case '\u0008':
- case '\u000b':
- case '\u000c':
- case '\u000e':
- case '\u000f':
- case '\u0010':
- case '\u0011':
- case '\u0012':
- case '\u0013':
- case '\u0014':
- case '\u0015':
- case '\u0016':
- case '\u0017':
- case '\u0018':
- case '\u0019':
- case '\u001a':
- case '\u001b':
- case '\u001c':
- case '\u001d':
- case '\u001e':
- case '\u001f':
- if (str == null) {
- str = new StringBuilder();
- str.append(s, 0, i);
- }
- str.append("'0x").append(Integer.toHexString(c));
- break;
- default:
- if (str != null) {
- str.append(c);
- }
- break;
- }
- }
- if (str == null) {
- return s;
- } else {
- return str.toString();
- }
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java Thu Nov 16 10:45:42 2017 -0800
@@ -26,18 +26,17 @@
import static org.graalvm.compiler.graph.Edges.Type.Successors;
import java.io.IOException;
-import java.nio.channels.WritableByteChannel;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import jdk.vm.ci.meta.ResolvedJavaField;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.core.common.cfg.BlockMap;
+import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugOptions;
import org.graalvm.compiler.graph.CachedGraph;
import org.graalvm.compiler.graph.Edges;
@@ -46,6 +45,7 @@
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeMap;
+import org.graalvm.compiler.graph.NodeSourcePosition;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractEndNode;
import org.graalvm.compiler.nodes.AbstractMergeNode;
@@ -55,15 +55,11 @@
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.PhiNode;
import org.graalvm.compiler.nodes.ProxyNode;
+import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.VirtualState;
import org.graalvm.compiler.nodes.cfg.Block;
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaType;
-import jdk.vm.ci.meta.Signature;
-import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.graph.NodeSourcePosition;
-import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.util.JavaConstantFormattable;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.graphio.GraphBlocks;
import org.graalvm.graphio.GraphElements;
@@ -71,6 +67,11 @@
import org.graalvm.graphio.GraphStructure;
import org.graalvm.graphio.GraphTypes;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
+
public class BinaryGraphPrinter implements
GraphStructure<BinaryGraphPrinter.GraphInfo, Node, NodeClass<?>, Edges>,
GraphBlocks<BinaryGraphPrinter.GraphInfo, Block, Node>,
@@ -79,8 +80,8 @@
private final SnippetReflectionProvider snippetReflection;
private final GraphOutput<BinaryGraphPrinter.GraphInfo, ResolvedJavaMethod> output;
- public BinaryGraphPrinter(WritableByteChannel channel, SnippetReflectionProvider snippetReflection) throws IOException {
- this.output = GraphOutput.newBuilder(this).blocks(this).elements(this).types(this).build(channel);
+ public BinaryGraphPrinter(DebugContext ctx, SnippetReflectionProvider snippetReflection) throws IOException {
+ this.output = ctx.buildOutput(GraphOutput.newBuilder(this).protocolVersion(5, 0).blocks(this).elements(this).types(this));
this.snippetReflection = snippetReflection;
}
@@ -116,17 +117,24 @@
}
@Override
+ public Node node(Object obj) {
+ return obj instanceof Node ? (Node) obj : null;
+ }
+
+ @Override
public NodeClass<?> nodeClass(Object obj) {
if (obj instanceof NodeClass<?>) {
return (NodeClass<?>) obj;
}
- if (obj instanceof Node) {
- return ((Node) obj).getNodeClass();
- }
return null;
}
@Override
+ public NodeClass<?> classForNode(Node node) {
+ return node.getNodeClass();
+ }
+
+ @Override
public Object nodeClassType(NodeClass<?> node) {
return node.getJavaClass();
}
@@ -257,6 +265,13 @@
}
props.put("category", "floating");
}
+ if (getSnippetReflectionProvider() != null) {
+ for (Map.Entry<String, Object> prop : props.entrySet()) {
+ if (prop.getValue() instanceof JavaConstantFormattable) {
+ props.put(prop.getKey(), ((JavaConstantFormattable) prop.getValue()).format(this));
+ }
+ }
+ }
}
private Object getBlockForNode(Node node, NodeMap<Block> nodeToBlocks) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java Thu Nov 16 10:45:42 2017 -0800
@@ -23,13 +23,13 @@
package org.graalvm.compiler.printer;
import static org.graalvm.compiler.debug.DebugOptions.PrintCFG;
-import static org.graalvm.compiler.printer.GraalDebugHandlersFactory.createDumpPath;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -153,8 +153,8 @@
if (cfgPrinter == null) {
try {
- Graph graph = debug.contextLookupTopdown(Graph.class);
- cfgFile = createDumpPath(options, graph, "cfg", false).toFile();
+ Path dumpFile = debug.getDumpPath(".cfg", false);
+ cfgFile = dumpFile.toFile();
OutputStream out = new BufferedOutputStream(new FileOutputStream(cfgFile));
cfgPrinter = new CFGPrinter(out);
} catch (IOException e) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CanonicalStringGraphPrinter.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CanonicalStringGraphPrinter.java Thu Nov 16 10:45:42 2017 -0800
@@ -26,7 +26,6 @@
import static org.graalvm.compiler.debug.DebugOptions.CanonicalGraphStringsExcludeVirtuals;
import static org.graalvm.compiler.debug.DebugOptions.CanonicalGraphStringsRemoveIdentities;
import static org.graalvm.compiler.debug.DebugOptions.PrintCanonicalGraphStringFlavor;
-import static org.graalvm.compiler.printer.GraalDebugHandlersFactory.sanitizedFileName;
import java.io.BufferedWriter;
import java.io.FileWriter;
@@ -44,6 +43,7 @@
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.PathUtilities;
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeMap;
@@ -260,11 +260,11 @@
private StructuredGraph currentGraph;
private Path currentDirectory;
- private Path getDirectory(StructuredGraph graph) throws IOException {
+ private Path getDirectory(DebugContext debug, StructuredGraph graph) {
if (graph == currentGraph) {
return currentDirectory;
}
- currentDirectory = GraalDebugHandlersFactory.createDumpPath(graph.getOptions(), graph, "graph-strings", true);
+ currentDirectory = debug.getDumpPath(".graph-strings", true);
currentGraph = graph;
return currentDirectory;
}
@@ -274,9 +274,9 @@
if (graph instanceof StructuredGraph) {
OptionValues options = graph.getOptions();
StructuredGraph structuredGraph = (StructuredGraph) graph;
- Path outDirectory = getDirectory(structuredGraph);
+ Path outDirectory = getDirectory(debug, structuredGraph);
String title = String.format("%03d-%s.txt", id, String.format(format, simplifyClassArgs(args)));
- Path filePath = outDirectory.resolve(sanitizedFileName(title));
+ Path filePath = outDirectory.resolve(PathUtilities.sanitizeFileName(title));
try (PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(filePath.toFile())))) {
switch (PrintCanonicalGraphStringFlavor.getValue(options)) {
case 1:
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugHandlersFactory.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugHandlersFactory.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,44 +22,18 @@
*/
package org.graalvm.compiler.printer;
-import static org.graalvm.compiler.debug.DebugOptions.PrintBinaryGraphPort;
-import static org.graalvm.compiler.debug.DebugOptions.PrintBinaryGraphs;
-import static org.graalvm.compiler.debug.DebugOptions.PrintGraphHost;
-import static org.graalvm.compiler.debug.DebugOptions.PrintXmlGraphPort;
-import static org.graalvm.compiler.debug.DebugOptions.ShowDumpFiles;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.nio.channels.ClosedByInterruptException;
-import java.nio.channels.FileChannel;
-import java.nio.channels.SocketChannel;
-import java.nio.file.FileAlreadyExistsException;
-import java.nio.file.Files;
-import java.nio.file.InvalidPathException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
-import org.graalvm.compiler.core.common.CompilationIdentifier;
-import org.graalvm.compiler.debug.Assertions;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugDumpHandler;
import org.graalvm.compiler.debug.DebugHandler;
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.DebugOptions;
import org.graalvm.compiler.debug.TTY;
-import org.graalvm.compiler.debug.PathUtilities;
-import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodeinfo.Verbosity;
-import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
@@ -80,17 +54,13 @@
@Override
public List<DebugHandler> createHandlers(OptionValues options) {
List<DebugHandler> handlers = new ArrayList<>();
- if (DebugOptions.PrintGraphFile.getValue(options)) {
- handlers.add(new GraphPrinterDumpHandler((graph) -> createFilePrinter(graph, options, snippetReflection)));
- } else {
- handlers.add(new GraphPrinterDumpHandler((graph) -> createNetworkPrinter(graph, options, snippetReflection)));
- }
+ handlers.add(new GraphPrinterDumpHandler((debug, graph) -> new BinaryGraphPrinter(debug, snippetReflection)));
if (DebugOptions.PrintCanonicalGraphStrings.getValue(options)) {
- handlers.add(new GraphPrinterDumpHandler((graph) -> createStringPrinter(snippetReflection)));
+ handlers.add(new GraphPrinterDumpHandler((debug, graph) -> createStringPrinter(snippetReflection)));
}
handlers.add(new NodeDumper());
if (DebugOptions.PrintCFG.getValue(options) || DebugOptions.PrintBackendCFG.getValue(options)) {
- if (DebugOptions.PrintBinaryGraphs.getValue(options) && DebugOptions.PrintCFG.getValue(options)) {
+ if (DebugOptions.PrintCFG.getValue(options)) {
TTY.out.println("Complete C1Visualizer dumping slows down PrintBinaryGraphs: use -Dgraal.PrintCFG=false to disable it");
}
handlers.add(new CFGPrinterObserver());
@@ -119,162 +89,4 @@
return new CanonicalStringGraphPrinter(snippetReflection);
}
- public static String sanitizedFileName(String n) {
- /*
- * First ensure that the name does not contain the directory separator (which would be
- * considered a valid path).
- */
- String name = n.replace(File.separatorChar, '_');
-
- try {
- Paths.get(name);
- return name;
- } catch (InvalidPathException e) {
- // fall through
- }
- StringBuilder buf = new StringBuilder(name.length());
- for (int i = 0; i < name.length(); i++) {
- char c = name.charAt(i);
- try {
- Paths.get(String.valueOf(c));
- } catch (InvalidPathException e) {
- buf.append('_');
- }
- buf.append(c);
- }
- return buf.toString();
- }
-
- private static GraphPrinter createNetworkPrinter(Graph graph, OptionValues options, SnippetReflectionProvider snippetReflection) throws IOException {
- String host = PrintGraphHost.getValue(options);
- int port = PrintBinaryGraphs.getValue(options) ? PrintBinaryGraphPort.getValue(options) : PrintXmlGraphPort.getValue(options);
- try {
- GraphPrinter printer;
- if (DebugOptions.PrintBinaryGraphs.getValue(options)) {
- printer = new BinaryGraphPrinter(SocketChannel.open(new InetSocketAddress(host, port)), snippetReflection);
- } else {
- printer = new IdealGraphPrinter(new Socket(host, port).getOutputStream(), true, snippetReflection);
- }
- TTY.println("Connected to the IGV on %s:%d", host, port);
- return printer;
- } catch (ClosedByInterruptException | InterruptedIOException e) {
- /*
- * Interrupts should not count as errors because they may be caused by a cancelled Graal
- * compilation. ClosedByInterruptException occurs if the SocketChannel could not be
- * opened. InterruptedIOException occurs if new Socket(..) was interrupted.
- */
- return null;
- } catch (IOException e) {
- if (!DebugOptions.PrintGraphFile.hasBeenSet(options)) {
- return createFilePrinter(graph, options, snippetReflection);
- } else {
- throw new IOException(String.format("Could not connect to the IGV on %s:%d", host, port), e);
- }
- }
- }
-
- private static final AtomicInteger unknownCompilationId = new AtomicInteger();
-
- /**
- * Creates a new file or directory for dumping based on a given graph and a file extension.
- *
- * @param graph a base path name is derived from {@code graph}
- * @param extension a suffix which if non-null and non-empty added to the end of the returned
- * path separated by a {@code "."}
- * @param createDirectory specifies if this is a request to create a directory instead of a file
- * @return the created directory or file
- * @throws IOException if there was an error creating the directory or file
- */
- static Path createDumpPath(OptionValues options, Graph graph, String extension, boolean createDirectory) throws IOException {
- CompilationIdentifier compilationId = CompilationIdentifier.INVALID_COMPILATION_ID;
- String id = null;
- String label = null;
- if (graph instanceof StructuredGraph) {
- StructuredGraph sgraph = (StructuredGraph) graph;
- label = getGraphName(sgraph);
- compilationId = sgraph.compilationId();
- if (compilationId == CompilationIdentifier.INVALID_COMPILATION_ID) {
- id = graph.getClass().getSimpleName() + "-" + sgraph.graphId();
- } else {
- id = compilationId.toString(CompilationIdentifier.Verbosity.ID);
- }
- } else {
- label = graph == null ? null : graph.name != null ? graph.name : graph.toString();
- id = "UnknownCompilation-" + unknownCompilationId.incrementAndGet();
- }
- String ext = PathUtilities.formatExtension(extension);
- Path result = createUnique(DebugOptions.getDumpDirectory(options), id, label, ext, createDirectory);
- if (ShowDumpFiles.getValue(options) || Assertions.assertionsEnabled()) {
- TTY.println("Dumping debug output to %s", result.toAbsolutePath().toString());
- }
- return result;
- }
-
- /**
- * A maximum file name length supported by most file systems. There is no platform independent
- * way to get this in Java.
- */
- private static final int MAX_FILE_NAME_LENGTH = 255;
-
- private static final String ELLIPSIS = "...";
-
- private static Path createUnique(Path dumpDir, String id, String label, String ext, boolean createDirectory) throws IOException {
- String timestamp = "";
- for (;;) {
- int fileNameLengthWithoutLabel = timestamp.length() + ext.length() + id.length() + "[]".length();
- int labelLengthLimit = MAX_FILE_NAME_LENGTH - fileNameLengthWithoutLabel;
- String fileName;
- if (labelLengthLimit < ELLIPSIS.length()) {
- // This means `id` is very long
- String suffix = timestamp + ext;
- int idLengthLimit = Math.min(MAX_FILE_NAME_LENGTH - suffix.length(), id.length());
- fileName = sanitizedFileName(id.substring(0, idLengthLimit) + suffix);
- } else {
- if (label == null) {
- fileName = sanitizedFileName(id + timestamp + ext);
- } else {
- String adjustedLabel = label;
- if (label.length() > labelLengthLimit) {
- adjustedLabel = label.substring(0, labelLengthLimit - ELLIPSIS.length()) + ELLIPSIS;
- }
- fileName = sanitizedFileName(id + '[' + adjustedLabel + ']' + timestamp + ext);
- }
- }
- Path result = dumpDir.resolve(fileName);
- try {
- if (createDirectory) {
- return Files.createDirectory(result);
- } else {
- return Files.createFile(result);
- }
- } catch (FileAlreadyExistsException e) {
- timestamp = "_" + Long.toString(System.currentTimeMillis());
- }
- }
- }
-
- private static String getGraphName(StructuredGraph graph) {
- if (graph.name != null) {
- return graph.name;
- } else if (graph.method() != null) {
- return graph.method().format("%h.%n(%p)").replace(" ", "");
- } else {
- return graph.toString();
- }
- }
-
- private static GraphPrinter createFilePrinter(Graph graph, OptionValues options, SnippetReflectionProvider snippetReflection) throws IOException {
- Path path = createDumpPath(options, graph, PrintBinaryGraphs.getValue(options) ? "bgv" : "gv.xml", false);
- try {
- GraphPrinter printer;
- if (DebugOptions.PrintBinaryGraphs.getValue(options)) {
- printer = new BinaryGraphPrinter(FileChannel.open(path, StandardOpenOption.WRITE), snippetReflection);
- } else {
- printer = new IdealGraphPrinter(Files.newOutputStream(path), true, snippetReflection);
- }
- return printer;
- } catch (IOException e) {
- throw new IOException(String.format("Failed to open %s to dump IGV graphs", path), e);
- }
- }
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java Thu Nov 16 10:45:42 2017 -0800
@@ -35,6 +35,7 @@
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.util.JavaConstantFormatter;
import org.graalvm.compiler.phases.schedule.SchedulePhase;
import org.graalvm.compiler.serviceprovider.JDK9Method;
@@ -46,7 +47,7 @@
import jdk.vm.ci.runtime.JVMCI;
import jdk.vm.ci.services.Services;
-interface GraphPrinter extends Closeable {
+interface GraphPrinter extends Closeable, JavaConstantFormatter {
/**
* Starts a new group of graphs with the given name, short name and method byte code index (BCI)
@@ -116,30 +117,44 @@
return true;
}
}
+ if (c.getClassLoader() == GraphPrinter.class.getClassLoader()) {
+ return true;
+ }
return false;
}
/**
+ * Use the real {@link Object#toString()} method for {@link JavaConstant JavaConstants} that are
+ * wrapping trusted types, other just return the results of {@link JavaConstant#toString()}.
+ */
+ @Override
+ default String format(JavaConstant constant) {
+ SnippetReflectionProvider snippetReflection = getSnippetReflectionProvider();
+ if (snippetReflection != null) {
+ if (constant.getJavaKind() == JavaKind.Object) {
+ Object obj = snippetReflection.asObject(Object.class, constant);
+ if (obj != null) {
+ return GraphPrinter.constantToString(obj);
+ }
+ }
+ }
+ return constant.toString();
+ }
+
+ /**
* Sets or updates the {@code "rawvalue"} and {@code "toString"} properties in {@code props} for
* {@code cn} if it's a boxed Object value and {@code snippetReflection} can access the raw
* value.
*/
default void updateStringPropertiesForConstant(Map<Object, Object> props, ConstantNode cn) {
- SnippetReflectionProvider snippetReflection = getSnippetReflectionProvider();
- if (snippetReflection != null && cn.getValue() instanceof JavaConstant) {
- JavaConstant constant = (JavaConstant) cn.getValue();
- if (constant.getJavaKind() == JavaKind.Object) {
- Object obj = snippetReflection.asObject(Object.class, constant);
- if (obj != null) {
- String toString = GraphPrinter.constantToString(obj);
- String rawvalue = GraphPrinter.truncate(toString);
- // Overwrite the value inserted by
- // ConstantNode.getDebugProperties()
- props.put("rawvalue", rawvalue);
- if (!rawvalue.equals(toString)) {
- props.put("toString", toString);
- }
- }
+ if (cn.isJavaConstant() && cn.getStackKind().isObject()) {
+ String toString = format(cn.asJavaConstant());
+ String rawvalue = GraphPrinter.truncate(toString);
+ // Overwrite the value inserted by
+ // ConstantNode.getDebugProperties()
+ props.put("rawvalue", rawvalue);
+ if (!rawvalue.equals(toString)) {
+ props.put("toString", toString);
}
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java Thu Nov 16 10:45:42 2017 -0800
@@ -52,8 +52,8 @@
//JaCoCo Exclude
/**
- * Observes compilation events and uses {@link IdealGraphPrinter} to generate a graph representation
- * that can be inspected with the Graph Visualizer.
+ * Observes compilation events and uses {@link BinaryGraphPrinter} to generate a graph
+ * representation that can be inspected with the Graph Visualizer.
*/
public class GraphPrinterDumpHandler implements DebugDumpHandler {
@@ -69,7 +69,7 @@
@FunctionalInterface
public interface GraphPrinterSupplier {
- GraphPrinter get(Graph graph) throws IOException;
+ GraphPrinter get(DebugContext ctx, Graph graph) throws IOException;
}
/**
@@ -93,7 +93,7 @@
}
}
- private void ensureInitialized(Graph graph) {
+ private void ensureInitialized(DebugContext ctx, Graph graph) {
if (printer == null) {
if (failuresCount >= FAILURE_LIMIT) {
return;
@@ -102,7 +102,7 @@
inlineContextMap = new WeakHashMap<>();
DebugContext debug = graph.getDebug();
try {
- printer = printerSupplier.get(graph);
+ printer = printerSupplier.get(ctx, graph);
} catch (IOException e) {
handleException(debug, e);
}
@@ -123,7 +123,7 @@
OptionValues options = debug.getOptions();
if (object instanceof Graph && DebugOptions.PrintGraph.getValue(options)) {
final Graph graph = (Graph) object;
- ensureInitialized(graph);
+ ensureInitialized(debug, graph);
if (printer == null) {
return;
}
@@ -168,11 +168,13 @@
// Save inline context for next dump.
previousInlineContext = inlineContext;
+ // Capture before creating the sandbox
+ String currentScopeName = debug.getCurrentScopeName();
try (DebugContext.Scope s = debug.sandbox("PrintingGraph", null)) {
// Finally, output the graph.
Map<Object, Object> properties = new HashMap<>();
properties.put("graph", graph.toString());
- properties.put("scope", debug.getCurrentScopeName());
+ properties.put("scope", currentScopeName);
if (graph instanceof StructuredGraph) {
properties.put("compilationIdentifier", ((StructuredGraph) graph).compilationId());
try {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/IdealGraphPrinter.java Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,356 +0,0 @@
-/*
- * Copyright (c) 2011, 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 org.graalvm.compiler.printer;
-
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
-import org.graalvm.compiler.bytecode.BytecodeDisassembler;
-import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.debug.DebugOptions;
-import org.graalvm.compiler.graph.Graph;
-import org.graalvm.compiler.graph.Node;
-import org.graalvm.compiler.graph.NodeMap;
-import org.graalvm.compiler.graph.Position;
-import org.graalvm.compiler.nodeinfo.Verbosity;
-import org.graalvm.compiler.nodes.AbstractMergeNode;
-import org.graalvm.compiler.nodes.BeginNode;
-import org.graalvm.compiler.nodes.ConstantNode;
-import org.graalvm.compiler.nodes.EndNode;
-import org.graalvm.compiler.nodes.ParameterNode;
-import org.graalvm.compiler.nodes.PhiNode;
-import org.graalvm.compiler.nodes.StateSplit;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
-import org.graalvm.compiler.nodes.cfg.Block;
-import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.phases.schedule.SchedulePhase;
-import org.graalvm.util.EconomicSet;
-import org.graalvm.util.Equivalence;
-
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
-/**
- * Generates a representation of {@link Graph Graphs} that can be visualized and inspected with the
- * <a href="http://kenai.com/projects/igv">Ideal Graph Visualizer</a>.
- */
-public class IdealGraphPrinter extends BasicIdealGraphPrinter implements GraphPrinter {
-
- private final boolean tryToSchedule;
- private final SnippetReflectionProvider snippetReflection;
-
- /**
- * Creates a new {@link IdealGraphPrinter} that writes to the specified output stream.
- *
- * @param tryToSchedule If false, no scheduling is done, which avoids exceptions for
- * non-schedulable graphs.
- */
- public IdealGraphPrinter(OutputStream stream, boolean tryToSchedule, SnippetReflectionProvider snippetReflection) {
- super(stream);
- this.snippetReflection = snippetReflection;
- this.begin();
- this.tryToSchedule = tryToSchedule;
- }
-
- @Override
- public SnippetReflectionProvider getSnippetReflectionProvider() {
- return snippetReflection;
- }
-
- /**
- * Starts a new group of graphs with the given name, short name and method byte code index (BCI)
- * as properties.
- */
- @Override
- public void beginGroup(DebugContext debug, String name, String shortName, ResolvedJavaMethod method, int bci, Map<Object, Object> properties) {
- beginGroup();
- beginProperties();
- printProperty("name", name);
- if (properties != null) {
- for (Entry<Object, Object> entry : properties.entrySet()) {
- printProperty(entry.getKey().toString(), entry.getValue().toString());
- }
- }
- endProperties();
- beginMethod(name, shortName, bci);
- if (method != null && method.getCode() != null) {
- printBytecodes(new BytecodeDisassembler(false).disassemble(method));
- }
- endMethod();
- }
-
- /**
- * Prints an entire {@link Graph} with the specified title, optionally using short names for
- * nodes.
- */
- @Override
- public void print(DebugContext debug, Graph graph, Map<Object, Object> properties, int id, String format, Object... args) {
- String title = id + ": " + String.format(format, simplifyClassArgs(args));
- beginGraph(title);
- EconomicSet<Node> noBlockNodes = EconomicSet.create(Equivalence.IDENTITY);
- ScheduleResult schedule = null;
- if (graph instanceof StructuredGraph) {
- StructuredGraph structuredGraph = (StructuredGraph) graph;
- schedule = structuredGraph.getLastSchedule();
- if (schedule == null && tryToSchedule) {
- OptionValues options = graph.getOptions();
- if (DebugOptions.PrintGraphWithSchedule.getValue(options)) {
- try {
- SchedulePhase schedulePhase = new SchedulePhase(options);
- schedulePhase.apply(structuredGraph);
- schedule = structuredGraph.getLastSchedule();
- } catch (Throwable t) {
- }
- }
- }
- }
- ControlFlowGraph cfg = schedule == null ? null : schedule.getCFG();
-
- if (properties != null) {
- beginProperties();
- for (Entry<Object, Object> entry : properties.entrySet()) {
- printProperty(entry.getKey().toString(), entry.getValue().toString());
- }
- endProperties();
- }
-
- beginNodes();
- List<Edge> edges = printNodes(graph, cfg == null ? null : cfg.getNodeToBlock(), noBlockNodes);
- endNodes();
-
- beginEdges();
- for (Edge edge : edges) {
- printEdge(edge);
- }
- endEdges();
-
- if (cfg != null && cfg.getBlocks() != null) {
- beginControlFlow();
- for (Block block : cfg.getBlocks()) {
- printBlock(graph, block, cfg.getNodeToBlock());
- }
- printNoBlock(noBlockNodes);
- endControlFlow();
- }
-
- endGraph();
- flush();
- }
-
- private List<Edge> printNodes(Graph graph, NodeMap<Block> nodeToBlock, EconomicSet<Node> noBlockNodes) {
- ArrayList<Edge> edges = new ArrayList<>();
-
- NodeMap<Set<Entry<String, Integer>>> colors = graph.createNodeMap();
- NodeMap<Set<Entry<String, String>>> colorsToString = graph.createNodeMap();
- NodeMap<Set<String>> bits = graph.createNodeMap();
-
- for (Node node : graph.getNodes()) {
-
- beginNode(node.toString(Verbosity.Id));
- beginProperties();
- printProperty("idx", node.toString(Verbosity.Id));
-
- Map<Object, Object> props = node.getDebugProperties();
- if (!props.containsKey("name") || props.get("name").toString().trim().length() == 0) {
- String name = node.toString(Verbosity.Name);
- printProperty("name", name);
- }
- printProperty("class", node.getClass().getSimpleName());
-
- Block block = nodeToBlock == null || nodeToBlock.isNew(node) ? null : nodeToBlock.get(node);
- if (block != null) {
- printProperty("block", Integer.toString(block.getId()));
- // if (!(node instanceof PhiNode || node instanceof FrameState || node instanceof
- // ParameterNode) && !block.nodes().contains(node)) {
- // printProperty("notInOwnBlock", "true");
- // }
- } else {
- printProperty("block", "noBlock");
- noBlockNodes.add(node);
- }
-
- Set<Entry<String, Integer>> nodeColors = colors.get(node);
- if (nodeColors != null) {
- for (Entry<String, Integer> color : nodeColors) {
- String name = color.getKey();
- Integer value = color.getValue();
- printProperty(name, Integer.toString(value));
- }
- }
- Set<Entry<String, String>> nodeColorStrings = colorsToString.get(node);
- if (nodeColorStrings != null) {
- for (Entry<String, String> color : nodeColorStrings) {
- String name = color.getKey();
- String value = color.getValue();
- printProperty(name, value);
- }
- }
- Set<String> nodeBits = bits.get(node);
- if (nodeBits != null) {
- for (String bit : nodeBits) {
- printProperty(bit, "true");
- }
- }
- if (node instanceof BeginNode) {
- printProperty("shortName", "B");
- } else if (node.getClass() == EndNode.class) {
- printProperty("shortName", "E");
- } else if (node instanceof ConstantNode) {
- ConstantNode cn = (ConstantNode) node;
- updateStringPropertiesForConstant(props, cn);
- }
- if (node.predecessor() != null) {
- printProperty("hasPredecessor", "true");
- }
-
- try {
- printProperty("NodeCost-Size", node.estimatedNodeSize().toString());
- printProperty("NodeCost-Cycles", node.estimatedNodeCycles().toString());
- } catch (Throwable t) {
- props.put("node-cost-exception", t.getMessage());
- }
-
- for (Entry<Object, Object> entry : props.entrySet()) {
- String key = entry.getKey().toString();
- Object value = entry.getValue();
- String valueString;
- if (value == null) {
- valueString = "null";
- } else {
- Class<?> type = value.getClass();
- if (type.isArray()) {
- if (!type.getComponentType().isPrimitive()) {
- valueString = Arrays.toString((Object[]) value);
- } else if (type.getComponentType() == Integer.TYPE) {
- valueString = Arrays.toString((int[]) value);
- } else if (type.getComponentType() == Double.TYPE) {
- valueString = Arrays.toString((double[]) value);
- } else {
- valueString = toString();
- }
- } else {
- valueString = value.toString();
- }
- }
- printProperty(key, valueString);
- }
-
- endProperties();
- endNode();
-
- // successors
- int fromIndex = 0;
- for (Position position : node.successorPositions()) {
- Node successor = position.get(node);
- if (successor != null) {
- edges.add(new Edge(node.toString(Verbosity.Id), fromIndex, successor.toString(Verbosity.Id), 0, position.getName()));
- }
- fromIndex++;
- }
-
- // inputs
- int toIndex = 1;
- for (Position position : node.inputPositions()) {
- Node input = position.get(node);
- if (input != null) {
- edges.add(new Edge(input.toString(Verbosity.Id), input.successors().count(), node.toString(Verbosity.Id), toIndex, position.getName()));
- }
- toIndex++;
- }
- }
-
- return edges;
- }
-
- private void printBlock(Graph graph, Block block, NodeMap<Block> nodeToBlock) {
- beginBlock(Integer.toString(block.getId()));
- beginSuccessors();
- for (Block sux : block.getSuccessors()) {
- if (sux != null) {
- printSuccessor(Integer.toString(sux.getId()));
- }
- }
- endSuccessors();
- beginBlockNodes();
-
- EconomicSet<Node> nodes = EconomicSet.create(Equivalence.IDENTITY);
-
- if (nodeToBlock != null) {
- for (Node n : graph.getNodes()) {
- Block blk = nodeToBlock.isNew(n) ? null : nodeToBlock.get(n);
- if (blk == block) {
- nodes.add(n);
- }
- }
- }
-
- if (nodes.size() > 0) {
- // if this is the first block: add all locals to this block
- if (block.getBeginNode() == ((StructuredGraph) graph).start()) {
- for (Node node : graph.getNodes()) {
- if (node instanceof ParameterNode) {
- nodes.add(node);
- }
- }
- }
-
- EconomicSet<Node> snapshot = EconomicSet.create(Equivalence.IDENTITY, nodes);
- // add all framestates and phis to their blocks
- for (Node node : snapshot) {
- if (node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) {
- nodes.add(((StateSplit) node).stateAfter());
- }
- if (node instanceof AbstractMergeNode) {
- for (PhiNode phi : ((AbstractMergeNode) node).phis()) {
- nodes.add(phi);
- }
- }
- }
-
- for (Node node : nodes) {
- printBlockNode(node.toString(Verbosity.Id));
- }
- }
- endBlockNodes();
- endBlock();
- }
-
- private void printNoBlock(EconomicSet<Node> noBlockNodes) {
- if (!noBlockNodes.isEmpty()) {
- beginBlock("noBlock");
- beginBlockNodes();
- for (Node node : noBlockNodes) {
- printBlockNode(node.toString(Verbosity.Id));
- }
- endBlockNodes();
- endBlock();
- }
- }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringIndexOfNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringIndexOfNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,13 +22,13 @@
*/
package org.graalvm.compiler.replacements.amd64;
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_256;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeInputList;
import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodeinfo.NodeCycles;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.FixedWithNextNode;
import org.graalvm.compiler.nodes.NamedLocationIdentity;
@@ -44,7 +44,7 @@
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.Value;
-@NodeInfo(size = SIZE_64, cycles = CYCLES_256)
+@NodeInfo(size = SIZE_64, cycles = NodeCycles.CYCLES_UNKNOWN)
public class AMD64StringIndexOfNode extends FixedWithNextNode implements LIRLowerable, MemoryAccess {
public static final NodeClass<AMD64StringIndexOfNode> TYPE = NodeClass.create(AMD64StringIndexOfNode.class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantBindingParameterPlugin.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantBindingParameterPlugin.java Thu Nov 16 10:45:42 2017 -0800
@@ -63,7 +63,7 @@
* This is a node from another graph, so copy over extra state into a new
* ConstantNode.
*/
- constantNode = ConstantNode.forConstant(stamp.getTrustedStamp(), otherCon.asConstant(), otherCon.getStableDimension(), otherCon.isDefaultStable(), metaAccess);
+ constantNode = ConstantNode.forConstant(stamp.getTrustedStamp(), otherCon.getValue(), otherCon.getStableDimension(), otherCon.isDefaultStable(), metaAccess);
} else {
constantNode = otherCon;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java Thu Nov 16 10:45:42 2017 -0800
@@ -33,6 +33,7 @@
import static org.graalvm.compiler.nodes.java.ArrayLengthNode.readArrayLength;
import static org.graalvm.compiler.nodes.util.GraphUtil.skipPiWhileNonNull;
+import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
@@ -43,6 +44,7 @@
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.core.common.type.IntegerStamp;
+import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
@@ -50,6 +52,7 @@
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodes.CompressionNode.CompressionOp;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.FieldLocationIdentity;
import org.graalvm.compiler.nodes.FixedNode;
@@ -69,6 +72,7 @@
import org.graalvm.compiler.nodes.calc.RightShiftNode;
import org.graalvm.compiler.nodes.calc.SignExtendNode;
import org.graalvm.compiler.nodes.calc.SubNode;
+import org.graalvm.compiler.nodes.calc.UnpackEndianHalfNode;
import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
import org.graalvm.compiler.nodes.debug.VerifyHeapNode;
import org.graalvm.compiler.nodes.extended.BoxNode;
@@ -150,14 +154,16 @@
protected final MetaAccessProvider metaAccess;
protected final ForeignCallsProvider foreignCalls;
protected final TargetDescription target;
+ private final boolean useCompressedOops;
private BoxingSnippets.Templates boxingSnippets;
private ConstantStringIndexOfSnippets.Templates indexOfSnippets;
- public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, TargetDescription target) {
+ public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, TargetDescription target, boolean useCompressedOops) {
this.metaAccess = metaAccess;
this.foreignCalls = foreignCalls;
this.target = target;
+ this.useCompressedOops = useCompressedOops;
}
public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection) {
@@ -218,11 +224,18 @@
lowerBinaryMath((BinaryMathIntrinsicNode) n, tool);
} else if (n instanceof StringIndexOfNode) {
lowerIndexOf((StringIndexOfNode) n);
+ } else if (n instanceof UnpackEndianHalfNode) {
+ lowerSecondHalf((UnpackEndianHalfNode) n);
} else {
throw GraalError.shouldNotReachHere("Node implementing Lowerable not handled: " + n);
}
}
+ private void lowerSecondHalf(UnpackEndianHalfNode n) {
+ ByteOrder byteOrder = target.arch.getByteOrder();
+ n.lower(byteOrder);
+ }
+
private void lowerIndexOf(StringIndexOfNode n) {
if (n.getArgument(3).isConstant()) {
SnippetLowering lowering = new SnippetLowering() {
@@ -326,19 +339,21 @@
}
}
+ protected abstract JavaKind getStorageKind(ResolvedJavaField field);
+
protected void lowerLoadFieldNode(LoadFieldNode loadField, LoweringTool tool) {
assert loadField.getStackKind() != JavaKind.Illegal;
StructuredGraph graph = loadField.graph();
ResolvedJavaField field = loadField.field();
ValueNode object = loadField.isStatic() ? staticFieldBase(graph, field) : loadField.object();
object = createNullCheckedValue(object, loadField, tool);
- Stamp loadStamp = loadStamp(loadField.stamp(), field.getJavaKind());
+ Stamp loadStamp = loadStamp(loadField.stamp(), getStorageKind(field));
AddressNode address = createFieldAddress(graph, object, field);
assert address != null : "Field that is loaded must not be eliminated: " + field.getDeclaringClass().toJavaName(true) + "." + field.getName();
ReadNode memoryRead = graph.add(new ReadNode(address, fieldLocationIdentity(field), loadStamp, fieldLoadBarrierType(field)));
- ValueNode readValue = implicitLoadConvert(graph, field.getJavaKind(), memoryRead);
+ ValueNode readValue = implicitLoadConvert(graph, getStorageKind(field), memoryRead);
loadField.replaceAtUsages(readValue);
graph.replaceFixed(loadField, memoryRead);
@@ -355,7 +370,7 @@
ResolvedJavaField field = storeField.field();
ValueNode object = storeField.isStatic() ? staticFieldBase(graph, field) : storeField.object();
object = createNullCheckedValue(object, storeField, tool);
- ValueNode value = implicitStoreConvert(graph, storeField.field().getJavaKind(), storeField.value());
+ ValueNode value = implicitStoreConvert(graph, getStorageKind(storeField.field()), storeField.value());
AddressNode address = createFieldAddress(graph, object, field);
assert address != null;
@@ -651,9 +666,7 @@
protected void lowerJavaWriteNode(JavaWriteNode write) {
StructuredGraph graph = write.graph();
- JavaKind valueKind = write.getWriteKind();
- ValueNode value = implicitStoreConvert(graph, valueKind, write.value(), write.isCompressible());
-
+ ValueNode value = implicitStoreConvert(graph, write.getWriteKind(), write.value(), write.isCompressible());
WriteNode memoryWrite = graph.add(new WriteNode(write.getAddress(), write.getLocationIdentity(), value, write.getBarrierType()));
memoryWrite.setStateAfter(write.stateAfter());
graph.replaceFixedWithFixed(write, memoryWrite);
@@ -918,10 +931,20 @@
return loadStamp(stamp, kind, true);
}
+ private boolean useCompressedOops(JavaKind kind, boolean compressible) {
+ return kind == JavaKind.Object && compressible && useCompressedOops;
+ }
+
+ protected abstract Stamp loadCompressedStamp(ObjectStamp stamp);
+
/**
* @param compressible whether the stamp should be compressible
*/
protected Stamp loadStamp(Stamp stamp, JavaKind kind, boolean compressible) {
+ if (useCompressedOops(kind, compressible)) {
+ return loadCompressedStamp((ObjectStamp) stamp);
+ }
+
switch (kind) {
case Boolean:
case Byte:
@@ -949,10 +972,16 @@
return ret;
}
+ protected abstract ValueNode newCompressionNode(CompressionOp op, ValueNode value);
+
/**
- * @param compressible whether the covert should be compressible
+ * @param compressible whether the convert should be compressible
*/
protected ValueNode implicitLoadConvert(JavaKind kind, ValueNode value, boolean compressible) {
+ if (useCompressedOops(kind, compressible)) {
+ return newCompressionNode(CompressionOp.Uncompress, value);
+ }
+
switch (kind) {
case Byte:
case Short:
@@ -984,6 +1013,10 @@
* @param compressible whether the covert should be compressible
*/
protected ValueNode implicitStoreConvert(JavaKind kind, ValueNode value, boolean compressible) {
+ if (useCompressedOops(kind, compressible)) {
+ return newCompressionNode(CompressionOp.Compress, value);
+ }
+
switch (kind) {
case Boolean:
case Byte:
@@ -1011,9 +1044,8 @@
LogicNode boundsCheck = IntegerBelowNode.create(n.index(), arrayLength);
if (boundsCheck.isTautology()) {
return null;
- } else {
- return tool.createGuard(n, graph.addOrUniqueWithInputs(boundsCheck), BoundsCheckException, InvalidateReprofile);
}
+ return tool.createGuard(n, graph.addOrUniqueWithInputs(boundsCheck), BoundsCheckException, InvalidateReprofile);
}
protected GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) {
@@ -1027,9 +1059,8 @@
GuardingNode nullCheck = createNullCheck(object, before, tool);
if (nullCheck == null) {
return object;
- } else {
- return before.graph().maybeAddOrUnique(PiNode.create(object, (object.stamp()).join(StampFactory.objectNonNull()), (ValueNode) nullCheck));
}
+ return before.graph().maybeAddOrUnique(PiNode.create(object, (object.stamp()).join(StampFactory.objectNonNull()), (ValueNode) nullCheck));
}
@Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java Thu Nov 16 10:45:42 2017 -0800
@@ -75,7 +75,6 @@
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.Signature;
/**
@@ -252,6 +251,10 @@
return new MethodCallTargetNode(invokeKind, targetMethod, args, returnStamp, null);
}
+ protected final JavaKind asKind(JavaType type) {
+ return wordTypes != null ? wordTypes.asKind(type) : type.getJavaKind();
+ }
+
/**
* Determines if a given set of arguments is compatible with the signature of a given method.
*
@@ -267,14 +270,12 @@
}
int argIndex = 0;
if (!isStatic) {
- ResolvedJavaType expectedType = method.getDeclaringClass();
- JavaKind expected = wordTypes == null ? expectedType.getJavaKind() : wordTypes.asKind(expectedType);
+ JavaKind expected = asKind(method.getDeclaringClass());
JavaKind actual = args[argIndex++].stamp().getStackKind();
assert expected == actual : graph + ": wrong kind of value for receiver argument of call to " + method + " [" + actual + " != " + expected + "]";
}
for (int i = 0; i != signature.getParameterCount(false); i++) {
- JavaType expectedType = signature.getParameterType(i, method.getDeclaringClass());
- JavaKind expected = wordTypes == null ? expectedType.getJavaKind().getStackKind() : wordTypes.asKind(expectedType).getStackKind();
+ JavaKind expected = asKind(signature.getParameterType(i, method.getDeclaringClass())).getStackKind();
JavaKind actual = args[argIndex++].stamp().getStackKind();
if (expected != actual) {
throw new AssertionError(graph + ": wrong kind of value for argument " + i + " of call to " + method + " [" + actual + " != " + expected + "]");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java Thu Nov 16 10:45:42 2017 -0800
@@ -433,13 +433,14 @@
}
IntrinsicContext initialIntrinsicContext = null;
- if (method.getAnnotation(Snippet.class) == null) {
+ Snippet snippetAnnotation = method.getAnnotation(Snippet.class);
+ if (snippetAnnotation == null) {
// Post-parse inlined intrinsic
initialIntrinsicContext = new IntrinsicContext(substitutedMethod, method, bytecodeProvider, INLINE_AFTER_PARSING);
} else {
// Snippet
ResolvedJavaMethod original = substitutedMethod != null ? substitutedMethod : method;
- initialIntrinsicContext = new IntrinsicContext(original, method, bytecodeProvider, INLINE_AFTER_PARSING);
+ initialIntrinsicContext = new IntrinsicContext(original, method, bytecodeProvider, INLINE_AFTER_PARSING, snippetAnnotation.allowPartialIntrinsicArgumentMismatch());
}
createGraphBuilder(metaAccess, replacements.providers.getStampProvider(), replacements.providers.getConstantReflection(), replacements.providers.getConstantFieldProvider(), config,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetCounter.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetCounter.java Thu Nov 16 10:45:42 2017 -0800
@@ -93,12 +93,7 @@
*/
@Override
public int compareTo(SnippetCounter o) {
- if (value > o.value) {
- return -1;
- } else if (o.value < value) {
- return 1;
- }
- return 0;
+ return Long.signum(o.value - value);
}
private final Group group;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetIntegerHistogram.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.replacements;
+
+/**
+ * A histogram that can (only) be {@linkplain #inc(long) incremented} from within a snippet for
+ * gathering snippet specific metrics.
+ */
+public final class SnippetIntegerHistogram {
+ private final SnippetCounter.Group group;
+ private final String name;
+
+ private final SnippetCounter counter0;
+ private final SnippetCounter counter1;
+ private final SnippetCounter counter2;
+ private final SnippetCounter counter3;
+ private final SnippetCounter counter4;
+ private final SnippetCounter counter5;
+ private final SnippetCounter counter6;
+ private final SnippetCounter counter7;
+ private final SnippetCounter counter8;
+ private final SnippetCounter counter9;
+ private final SnippetCounter counter10;
+
+ private final int counter0UpperBound;
+ private final int counter1UpperBound;
+ private final int counter2UpperBound;
+ private final int counter3UpperBound;
+ private final int counter4UpperBound;
+ private final int counter5UpperBound;
+ private final int counter6UpperBound;
+ private final int counter7UpperBound;
+ private final int counter8UpperBound;
+ private final int counter9UpperBound;
+
+ public SnippetIntegerHistogram(SnippetCounter.Group group, int log2StepLength, String name, String description) {
+ assert log2StepLength > 0;
+
+ this.group = group;
+ this.name = name;
+
+ int lowerBound = 0;
+ counter0UpperBound = 0;
+ counter0 = createCounter(group, name, description, lowerBound, counter0UpperBound);
+
+ lowerBound = counter0UpperBound + 1;
+ counter1UpperBound = Math.max(1, lowerBound - 1) << log2StepLength;
+ counter1 = createCounter(group, name, description, lowerBound, counter1UpperBound);
+
+ lowerBound = counter1UpperBound + 1;
+ counter2UpperBound = Math.max(1, lowerBound - 1) << log2StepLength;
+ counter2 = createCounter(group, name, description, lowerBound, counter2UpperBound);
+
+ lowerBound = counter2UpperBound + 1;
+ counter3UpperBound = Math.max(1, lowerBound - 1) << log2StepLength;
+ counter3 = createCounter(group, name, description, lowerBound, counter3UpperBound);
+
+ lowerBound = counter3UpperBound + 1;
+ counter4UpperBound = Math.max(1, lowerBound - 1) << log2StepLength;
+ counter4 = createCounter(group, name, description, lowerBound, counter4UpperBound);
+
+ lowerBound = counter4UpperBound + 1;
+ counter5UpperBound = Math.max(1, lowerBound - 1) << log2StepLength;
+ counter5 = createCounter(group, name, description, lowerBound, counter5UpperBound);
+
+ lowerBound = counter5UpperBound + 1;
+ counter6UpperBound = Math.max(1, lowerBound - 1) << log2StepLength;
+ counter6 = createCounter(group, name, description, lowerBound, counter6UpperBound);
+
+ lowerBound = counter6UpperBound + 1;
+ counter7UpperBound = Math.max(1, lowerBound - 1) << log2StepLength;
+ counter7 = createCounter(group, name, description, lowerBound, counter7UpperBound);
+
+ lowerBound = counter7UpperBound + 1;
+ counter8UpperBound = Math.max(1, lowerBound - 1) << log2StepLength;
+ counter8 = createCounter(group, name, description, lowerBound, counter8UpperBound);
+
+ lowerBound = counter8UpperBound + 1;
+ counter9UpperBound = Math.max(1, lowerBound - 1) << log2StepLength;
+ counter9 = createCounter(group, name, description, lowerBound, counter9UpperBound);
+
+ lowerBound = counter9UpperBound + 1;
+ counter10 = createCounter(group, name, description, lowerBound, Long.MAX_VALUE);
+ }
+
+ private static SnippetCounter createCounter(SnippetCounter.Group group, String name, String description, long lowerBound, long upperBound) {
+ if (group != null) {
+ SnippetCounter snippetCounter = new SnippetCounter(group, name + "[" + lowerBound + ", " + upperBound + "]", description);
+ return snippetCounter;
+ }
+ return null;
+ }
+
+ /**
+ * Increments the value of the matching histogram element. This method can only be used in a
+ * snippet on a compile-time constant {@link SnippetIntegerHistogram} object.
+ */
+ public void inc(long value) {
+ if (group != null) {
+ if (value <= counter0UpperBound) {
+ counter0.inc();
+ } else if (value <= counter1UpperBound) {
+ counter1.inc();
+ } else if (value <= counter2UpperBound) {
+ counter2.inc();
+ } else if (value <= counter3UpperBound) {
+ counter3.inc();
+ } else if (value <= counter4UpperBound) {
+ counter4.inc();
+ } else if (value <= counter5UpperBound) {
+ counter5.inc();
+ } else if (value <= counter6UpperBound) {
+ counter6.inc();
+ } else if (value <= counter7UpperBound) {
+ counter7.inc();
+ } else if (value <= counter8UpperBound) {
+ counter8.inc();
+ } else if (value <= counter9UpperBound) {
+ counter9.inc();
+ } else {
+ counter10.inc();
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (group != null) {
+ return "SnippetHistogram-" + group.name + ":" + name;
+ }
+ return super.toString();
+ }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -23,15 +23,15 @@
package org.graalvm.compiler.replacements.nodes;
import static org.graalvm.compiler.nodeinfo.InputType.Memory;
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1024;
-import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1024;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.Canonicalizable;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.nodeinfo.NodeCycles;
import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodeinfo.NodeSize;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.FixedWithNextNode;
import org.graalvm.compiler.nodes.NamedLocationIdentity;
@@ -57,7 +57,7 @@
/**
* Compares two arrays with the same length.
*/
-@NodeInfo(cycles = CYCLES_1024, size = SIZE_1024)
+@NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = NodeSize.SIZE_128)
public final class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess {
public static final NodeClass<ArrayEqualsNode> TYPE = NodeClass.create(ArrayEqualsNode.class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -24,7 +24,6 @@
import static org.graalvm.compiler.nodeinfo.InputType.Memory;
import static org.graalvm.compiler.nodeinfo.InputType.State;
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_256;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
import static org.graalvm.word.LocationIdentity.any;
@@ -32,6 +31,7 @@
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeInputList;
+import org.graalvm.compiler.nodeinfo.NodeCycles;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.DeoptimizingNode;
@@ -56,7 +56,7 @@
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaType;
-@NodeInfo(cycles = CYCLES_256, size = SIZE_64)
+@NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = SIZE_64)
public class BasicArrayCopyNode extends AbstractMemoryCheckpoint implements Virtualizable, MemoryCheckpoint.Single, MemoryAccess, Lowerable, DeoptimizingNode.DeoptDuring {
public static final NodeClass<BasicArrayCopyNode> TYPE = NodeClass.create(BasicArrayCopyNode.class);
@@ -215,7 +215,7 @@
return;
}
for (int i = 0; i < len; i++) {
- tool.setVirtualEntry(destVirtual, destPosInt + i, tool.getEntry(srcVirtual, srcPosInt + i), false);
+ tool.setVirtualEntry(destVirtual, destPosInt + i, tool.getEntry(srcVirtual, srcPosInt + i));
}
tool.delete();
DebugContext debug = getDebug();
@@ -235,7 +235,7 @@
for (int i = 0; i < len; i++) {
LoadIndexedNode load = new LoadIndexedNode(graph().getAssumptions(), srcAlias, ConstantNode.forInt(i + srcPosInt, graph()), destComponentType.getJavaKind());
tool.addNode(load);
- tool.setVirtualEntry(destVirtual, destPosInt + i, load, false);
+ tool.setVirtualEntry(destVirtual, destPosInt + i, load);
}
tool.delete();
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -22,7 +22,6 @@
*/
package org.graalvm.compiler.replacements.nodes;
-import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8;
import java.util.Collections;
@@ -32,6 +31,7 @@
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.StampPair;
import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.nodeinfo.NodeCycles;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
import org.graalvm.compiler.nodes.ValueNode;
@@ -49,7 +49,7 @@
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
-@NodeInfo(cycles = CYCLES_8, size = SIZE_8)
+@NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = SIZE_8)
public abstract class BasicObjectCloneNode extends MacroStateSplitNode implements VirtualizableAllocation, ArrayLengthProvider {
public static final NodeClass<BasicObjectCloneNode> TYPE = NodeClass.create(BasicObjectCloneNode.class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BinaryMathIntrinsicNode.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BinaryMathIntrinsicNode.java Thu Nov 16 10:45:42 2017 -0800
@@ -37,7 +37,7 @@
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.BinaryNode;
-import org.graalvm.compiler.nodes.calc.DivNode;
+import org.graalvm.compiler.nodes.calc.FloatDivNode;
import org.graalvm.compiler.nodes.calc.MulNode;
import org.graalvm.compiler.nodes.calc.SqrtNode;
import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable;
@@ -141,7 +141,7 @@
// x**-1 = 1/x
if (yValue == -1.0D) {
- return new DivNode(ConstantNode.forDouble(1), x);
+ return new FloatDivNode(ConstantNode.forDouble(1), x);
}
// x**2 = x*x
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -36,6 +36,7 @@
import java.util.Collections;
import java.util.List;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.DebugDumpHandler;
@@ -392,6 +393,20 @@
* {@link DebugDumpHandler}s closed in {@link #afterTest()}.
*/
protected DebugContext getDebugContext(OptionValues options) {
+ return getDebugContext(options, null, null);
+ }
+
+ /**
+ * Gets a {@link DebugContext} object corresponding to {@code options}, creating a new one if
+ * none currently exists.Debug contexts created by this method will have their
+ * {@link DebugDumpHandler}s closed in {@link #afterTest()}.
+ *
+ * @param options currently active options
+ * @param id identification of the compilation or {@code null}
+ * @param method method to use for a proper description of the context or {@code null}
+ * @return configured context for compilation
+ */
+ protected DebugContext getDebugContext(OptionValues options, String id, ResolvedJavaMethod method) {
List<DebugContext> cached = cachedDebugs.get();
if (cached == null) {
cached = new ArrayList<>();
@@ -402,7 +417,13 @@
return debug;
}
}
- DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, getDebugHandlersFactories());
+ final DebugContext.Description descr;
+ if (method == null) {
+ descr = NO_DESCRIPTION;
+ } else {
+ descr = new DebugContext.Description(method, id == null ? method.getName() : id);
+ }
+ DebugContext debug = DebugContext.create(options, descr, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, getDebugHandlersFactories());
cached.add(debug);
return debug;
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectList.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectList.java Thu Nov 16 10:45:42 2017 -0800
@@ -171,9 +171,14 @@
}
public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes, boolean cfgKills) {
+ boolean message = false;
for (int i = 0; i < size(); i++) {
Effect effect = effects[i];
if (effect.isCfgKill() == cfgKills) {
+ if (!message) {
+ message = true;
+ debug.log(cfgKills ? " ==== cfg kill effects" : " ==== effects");
+ }
try {
effect.apply(graph, obsoleteNodes);
} catch (Throwable t) {
@@ -202,7 +207,7 @@
// Inner classes could capture the EffectList itself.
continue;
}
- str.append(first ? "" : ", ").append(format(object));
+ str.append(first ? "" : ", ").append(field.getName()).append("=").append(format(object));
first = false;
} catch (SecurityException | IllegalAccessException e) {
throw new RuntimeException(e);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java Thu Nov 16 10:45:42 2017 -0800
@@ -184,7 +184,6 @@
};
ReentrantBlockIterator.apply(closure, cfg.getStartBlock());
for (GraphEffectList effects : effectList) {
- debug.log(" ==== effects");
effects.apply(graph, obsoleteNodes, false);
}
/*
@@ -193,7 +192,6 @@
* indexes.
*/
for (GraphEffectList effects : effectList) {
- debug.log(" ==== cfg kill effects");
effects.apply(graph, obsoleteNodes, true);
}
debug.dump(DebugContext.DETAILED_LEVEL, graph, "After applying effects");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java Thu Nov 16 10:45:42 2017 -0800
@@ -99,8 +99,8 @@
closure.applyEffects();
}
- if (debug.isDumpEnabled(DebugContext.INFO_LEVEL)) {
- debug.dump(DebugContext.DETAILED_LEVEL, graph, "%s iteration", getName());
+ if (debug.isDumpEnabled(DebugContext.VERBOSE_LEVEL)) {
+ debug.dump(DebugContext.VERBOSE_LEVEL, graph, "%s iteration", getName());
}
new DeadCodeEliminationPhase(Required).apply(graph);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ObjectState.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ObjectState.java Thu Nov 16 10:45:42 2017 -0800
@@ -68,6 +68,7 @@
}
public ObjectState(ValueNode[] entries, LockState locks, boolean ensureVirtualized) {
+ assert checkIllegalValues(entries);
this.entries = entries;
this.locks = locks;
this.ensureVirtualized = ensureVirtualized;
@@ -92,6 +93,30 @@
return new ObjectState(this);
}
+ /**
+ * Ensure that if an {@link JavaConstant#forIllegal() illegal value} is seen that the previous
+ * value is a double word value.
+ */
+ public static boolean checkIllegalValues(ValueNode[] values) {
+ if (values != null) {
+ for (int v = 1; v < values.length; v++) {
+ checkIllegalValue(values, v);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Ensure that if an {@link JavaConstant#forIllegal() illegal value} is seen that the previous
+ * value is a double word value.
+ */
+ public static boolean checkIllegalValue(ValueNode[] values, int v) {
+ if (v > 0 && values[v].isConstant() && values[v].asConstant().equals(JavaConstant.forIllegal())) {
+ assert values[v - 1].getStackKind().needsTwoSlots();
+ }
+ return true;
+ }
+
public EscapeObjectState createEscapeObjectState(DebugContext debug, VirtualObjectNode virtual) {
GET_ESCAPED_OBJECT_STATE.increment(debug);
if (cachedState == null) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java Thu Nov 16 10:45:42 2017 -0800
@@ -854,6 +854,7 @@
ValueNode nextValue = objectState.getEntry(valueIndex + 1);
if (value.isConstant() && value.asConstant().equals(JavaConstant.INT_0) && nextValue.isConstant() && nextValue.asConstant().equals(JavaConstant.INT_0)) {
// rewrite to a zero constant of the larger kind
+ debug.log("Rewriting entry %s to constant of larger size", valueIndex);
states[i].setEntry(object, valueIndex, ConstantNode.defaultForKind(twoSlotKinds[valueIndex], graph()));
states[i].setEntry(object, valueIndex + 1, ConstantNode.forConstant(JavaConstant.forIllegal(), tool.getMetaAccessProvider(), graph()));
} else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualizerToolImpl.java Thu Nov 16 10:45:42 2017 -0800
@@ -30,18 +30,22 @@
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.FixedNode;
import org.graalvm.compiler.nodes.FixedWithNextNode;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.FloatingNode;
+import org.graalvm.compiler.nodes.calc.UnpackEndianHalfNode;
import org.graalvm.compiler.nodes.java.MonitorIdNode;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.VirtualizerTool;
+import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode;
import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.meta.Assumptions;
import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
@@ -58,6 +62,7 @@
private final OptionValues options;
private final DebugContext debug;
private final LoweringProvider loweringProvider;
+ private ConstantNode illegalConstant;
VirtualizerToolImpl(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, PartialEscapeClosure<?> closure,
Assumptions assumptions, OptionValues options, DebugContext debug, LoweringProvider loweringProvider) {
@@ -125,17 +130,81 @@
}
@Override
- public void setVirtualEntry(VirtualObjectNode virtual, int index, ValueNode value, boolean unsafe) {
+ public boolean setVirtualEntry(VirtualObjectNode virtual, int index, ValueNode value, JavaKind theAccessKind, long offset) {
ObjectState obj = state.getObjectState(virtual);
assert obj.isVirtual() : "not virtual: " + obj;
ValueNode newValue;
+ JavaKind entryKind = virtual.entryKind(index);
+ JavaKind accessKind = theAccessKind != null ? theAccessKind : entryKind;
if (value == null) {
newValue = null;
} else {
newValue = closure.getAliasAndResolve(state, value);
- assert unsafe || obj.getEntry(index) == null || obj.getEntry(index).getStackKind() == newValue.getStackKind() || (isObjectEntry(obj.getEntry(index)) && isObjectEntry(newValue));
+ }
+ getDebug().log(DebugContext.DETAILED_LEVEL, "Setting entry %d in virtual object %s %s results in %s", index, virtual.getObjectId(), virtual, state.getObjectState(virtual.getObjectId()));
+ ValueNode oldValue = getEntry(virtual, index);
+ boolean canVirtualize = entryKind == accessKind || (entryKind == accessKind.getStackKind() && virtual instanceof VirtualInstanceNode);
+ if (!canVirtualize) {
+ if (entryKind == JavaKind.Long && oldValue.getStackKind() == newValue.getStackKind() && oldValue.getStackKind().isPrimitive()) {
+ /*
+ * Special case: If the entryKind is long, allow arbitrary kinds as long as a value
+ * of the same kind is already there. This can only happen if some other node
+ * initialized the entry with a value of a different kind. One example where this
+ * happens is the Truffle NewFrameNode.
+ */
+ getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s with primitive of kind %s in long entry ", current, oldValue.getStackKind());
+ canVirtualize = true;
+ } else if (entryKind == JavaKind.Int && (accessKind == JavaKind.Long || accessKind == JavaKind.Double) && offset % 8 == 0) {
+ /*
+ * Special case: Allow storing a single long or double value into two consecutive
+ * int slots.
+ */
+ int nextIndex = virtual.entryIndexForOffset(offset + 4, JavaKind.Int);
+ if (nextIndex != -1) {
+ canVirtualize = true;
+ assert nextIndex == index + 1 : "expected to be sequential";
+ getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s for double word stored in two ints", current);
+ }
+ }
}
- state.setEntry(virtual.getObjectId(), index, newValue);
+
+ if (canVirtualize) {
+ getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s for entryKind %s and access kind %s", current, entryKind, accessKind);
+ state.setEntry(virtual.getObjectId(), index, newValue);
+ if (entryKind == JavaKind.Int) {
+ if (accessKind.needsTwoSlots()) {
+ // Storing double word value two int slots
+ assert virtual.entryKind(index + 1) == JavaKind.Int;
+ state.setEntry(virtual.getObjectId(), index + 1, getIllegalConstant());
+ } else if (oldValue.getStackKind() == JavaKind.Double || oldValue.getStackKind() == JavaKind.Long) {
+ // Splitting double word constant by storing over it with an int
+ getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing second half of double word value %s", current, oldValue);
+ ValueNode secondHalf = UnpackEndianHalfNode.create(oldValue, false);
+ addNode(secondHalf);
+ state.setEntry(virtual.getObjectId(), index + 1, secondHalf);
+ }
+ }
+ if (oldValue.isConstant() && oldValue.asConstant().equals(JavaConstant.forIllegal())) {
+ // Storing into second half of double, so replace previous value
+ ValueNode previous = getEntry(virtual, index - 1);
+ getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing first half of double word value %s", current, previous);
+ ValueNode firstHalf = UnpackEndianHalfNode.create(previous, true);
+ addNode(firstHalf);
+ state.setEntry(virtual.getObjectId(), index - 1, firstHalf);
+ }
+ return true;
+ }
+ // Should only occur if there are mismatches between the entry and access kind
+ assert entryKind != accessKind;
+ return false;
+ }
+
+ private ValueNode getIllegalConstant() {
+ if (illegalConstant == null) {
+ illegalConstant = ConstantNode.forConstant(JavaConstant.forIllegal(), getMetaAccessProvider());
+ addNode(illegalConstant);
+ }
+ return illegalConstant;
}
@Override
@@ -149,10 +218,6 @@
return state.getObjectState(virtualObject).getEnsureVirtualized();
}
- private static boolean isObjectEntry(ValueNode value) {
- return value.getStackKind() == JavaKind.Object || value instanceof VirtualObjectNode;
- }
-
@Override
public void replaceWithVirtual(VirtualObjectNode virtual) {
closure.addVirtualAlias(virtual, current);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphOutput.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphOutput.java Thu Nov 16 10:45:42 2017 -0800
@@ -113,12 +113,30 @@
private GraphElements<M, ?, ?, ?> elements = null;
private GraphTypes types = DefaultGraphTypes.DEFAULT;
private GraphBlocks<G, ?, N> blocks = DefaultGraphBlocks.empty();
+ private int major = 4;
+ private int minor = 0;
Builder(GraphStructure<G, N, ?, ?> structure) {
this.structure = structure;
}
/**
+ * Chooses which version of the protocol to use. The default version is <code>4.0</code>
+ * (when the {@link GraphOutput} & co. classes were introduced). The default can be changed
+ * to other known versions manually by calling this method.
+ *
+ * @param majorVersion by default 4, newer version may be known
+ * @param minorVersion usually 0
+ * @return this builder
+ * @since 0.28
+ */
+ public Builder<G, N, M> protocolVersion(int majorVersion, int minorVersion) {
+ this.major = majorVersion;
+ this.minor = minorVersion;
+ return this;
+ }
+
+ /**
* Associates different implementation of types.
*
* @param graphTypes implementation of types and enum recognition
@@ -161,7 +179,28 @@
* @throws IOException if something goes wrong when writing to the channel
*/
public GraphOutput<G, M> build(WritableByteChannel channel) throws IOException {
- ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?> p = new ProtocolImpl<>(structure, types, blocks, elements, channel);
+ ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?> p = new ProtocolImpl<>(major, minor, structure, types, blocks, elements, channel);
+ return new GraphOutput<>(p);
+ }
+
+ /**
+ * Support for nesting heterogenous graphs. The newly created output uses all the interfaces
+ * currently associated with this builder, but shares with {@code parent} the output
+ * {@code channel}, internal constant pool and {@link #protocolVersion(int, int) protocol
+ * version}.
+ * <p>
+ * Both GraphOutput (the {@code parent} and the returned one) has to be used in
+ * synchronization - e.g. only one
+ * {@link #beginGroup(java.lang.Object, java.lang.String, java.lang.String, java.lang.Object, int, java.util.Map)
+ * begin}, {@link #endGroup() end} of group or
+ * {@link #print(java.lang.Object, java.util.Map, int, java.lang.String, java.lang.Object...)
+ * printing} can be on at a given moment.
+ *
+ * @param parent the output to inherit {@code channel} and protocol version from
+ * @return new output sharing {@code channel} and other internals with {@code parent}
+ */
+ public GraphOutput<G, M> build(GraphOutput<?, ?> parent) {
+ ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?> p = new ProtocolImpl<>(parent.printer, structure, types, blocks, elements);
return new GraphOutput<>(p);
}
}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java Thu Nov 16 10:45:42 2017 -0800
@@ -52,6 +52,7 @@
private static final int POOL_FIELD = 0x07;
private static final int POOL_SIGNATURE = 0x08;
private static final int POOL_NODE_SOURCE_POSITION = 0x09;
+ private static final int POOL_NODE = 0x0a;
private static final int PROPERTY_POOL = 0x00;
private static final int PROPERTY_INT = 0x01;
@@ -71,19 +72,12 @@
private final ConstantPool constantPool;
private final ByteBuffer buffer;
private final WritableByteChannel channel;
- private final int versionMajor;
- private final int versionMinor;
-
- protected GraphProtocol(WritableByteChannel channel) throws IOException {
- this(channel, 4, 0);
- }
+ final int versionMajor;
+ final int versionMinor;
- private GraphProtocol(WritableByteChannel channel, int major, int minor) throws IOException {
- if (major > 4) {
- throw new IllegalArgumentException();
- }
- if (major == 4 && minor > 0) {
- throw new IllegalArgumentException();
+ GraphProtocol(WritableByteChannel channel, int major, int minor) throws IOException {
+ if (major > 5 || (major == 5 && minor > 0)) {
+ throw new IllegalArgumentException("Unrecognized version " + major + "." + minor);
}
this.versionMajor = major;
this.versionMinor = minor;
@@ -93,6 +87,14 @@
writeVersion();
}
+ GraphProtocol(GraphProtocol<?, ?, ?, ?, ?, ?, ?, ?, ?> parent) {
+ this.versionMajor = parent.versionMajor;
+ this.versionMinor = parent.versionMinor;
+ this.constantPool = parent.constantPool;
+ this.buffer = parent.buffer;
+ this.channel = parent.channel;
+ }
+
@SuppressWarnings("all")
public final void print(Graph graph, Map<? extends Object, ? extends Object> properties, int id, String format, Object... args) throws IOException {
writeByte(BEGIN_GRAPH);
@@ -137,9 +139,33 @@
protected abstract ResolvedJavaMethod findMethod(Object obj);
+ /**
+ * Attempts to recognize the provided object as a node. Used to encode it with
+ * {@link #POOL_NODE} pool type.
+ *
+ * @param obj any object
+ * @return <code>null</code> if it is not a node object, non-null otherwise
+ */
+ protected abstract Node findNode(Object obj);
+
+ /**
+ * Determines whether the provided object is node class or not.
+ *
+ * @param obj object to check
+ * @return {@code null} if {@code obj} does not represent a NodeClass otherwise the NodeClass
+ * represented by {@code obj}
+ */
protected abstract NodeClass findNodeClass(Object obj);
/**
+ * Returns the NodeClass for a given Node {@code obj}.
+ *
+ * @param obj instance of node
+ * @return non-{@code null} instance of the node's class object
+ */
+ protected abstract NodeClass findClassForNode(Node obj);
+
+ /**
* Find a Java class. The returned object must be acceptable by
* {@link #findJavaTypeName(java.lang.Object)} and return valid name for the class.
*
@@ -239,7 +265,7 @@
private void flush() throws IOException {
buffer.flip();
/*
- * Try not to let interrupted threads aborting the write. There's still a race here but an
+ * Try not to let interrupted threads abort the write. There's still a race here but an
* interrupt that's been pending for a long time shouldn't stop this writing.
*/
boolean interrupted = Thread.interrupted();
@@ -338,7 +364,8 @@
}
}
- private void writePoolObject(Object object) throws IOException {
+ private void writePoolObject(Object obj) throws IOException {
+ Object object = obj;
if (object == null) {
writeByte(POOL_NULL);
return;
@@ -347,23 +374,31 @@
if (id == null) {
addPoolEntry(object);
} else {
- if (object instanceof Enum<?> || findEnumOrdinal(object) >= 0) {
- writeByte(POOL_ENUM);
- } else if (object instanceof Class<?> || findJavaTypeName(object) != null) {
- writeByte(POOL_CLASS);
- } else if (findJavaField(object) != null) {
+ if (findJavaField(object) != null) {
writeByte(POOL_FIELD);
} else if (findSignature(object) != null) {
writeByte(POOL_SIGNATURE);
} else if (versionMajor >= 4 && findNodeSourcePosition(object) != null) {
writeByte(POOL_NODE_SOURCE_POSITION);
} else {
+ final Node node = findNode(object);
+ if (versionMajor == 4 && node != null) {
+ object = classForNode(node);
+ }
if (findNodeClass(object) != null) {
writeByte(POOL_NODE_CLASS);
+ } else if (versionMajor >= 5 && node != null) {
+ writeByte(POOL_NODE);
} else if (findMethod(object) != null) {
writeByte(POOL_METHOD);
} else {
- writeByte(POOL_STRING);
+ if (object instanceof Enum<?> || findEnumOrdinal(object) >= 0) {
+ writeByte(POOL_ENUM);
+ } else if (object instanceof Class<?> || findJavaTypeName(object) != null) {
+ writeByte(POOL_CLASS);
+ } else {
+ writeByte(POOL_STRING);
+ }
}
}
writeShort(id.charValue());
@@ -383,10 +418,7 @@
writeInt(size);
int cnt = 0;
for (Node node : findNodes(info)) {
- NodeClass nodeClass = findNodeClass(node);
- if (nodeClass == null) {
- throw new IOException("No class for " + node);
- }
+ NodeClass nodeClass = classForNode(node);
findNodeProperties(node, props, info);
writeInt(findNodeId(node));
@@ -405,7 +437,7 @@
}
private void writeEdges(Graph graph, Node node, boolean dumpInputs) throws IOException {
- NodeClass clazz = findNodeClass(node);
+ NodeClass clazz = classForNode(node);
Edges edges = findClassEdges(clazz, dumpInputs);
int size = findSize(edges);
for (int i = 0; i < size; i++) {
@@ -434,6 +466,14 @@
}
}
+ private NodeClass classForNode(Node node) throws IOException {
+ NodeClass clazz = findClassForNode(node);
+ if (clazz == null) {
+ throw new IOException("No class for " + node);
+ }
+ return clazz;
+ }
+
private void writeNodeRef(Node node) throws IOException {
writeInt(findNodeId(node));
}
@@ -480,7 +520,8 @@
}
@SuppressWarnings("all")
- private void addPoolEntry(Object object) throws IOException {
+ private void addPoolEntry(Object obj) throws IOException {
+ Object object = obj;
ResolvedJavaField field;
String typeName;
Signature signature;
@@ -489,24 +530,7 @@
char index = constantPool.add(object);
writeByte(POOL_NEW);
writeShort(index);
- if ((typeName = findJavaTypeName(object)) != null) {
- writeByte(POOL_CLASS);
- writeString(typeName);
- String[] enumValueNames = findEnumTypeValues(object);
- if (enumValueNames != null) {
- writeByte(ENUM_KLASS);
- writeInt(enumValueNames.length);
- for (String o : enumValueNames) {
- writePoolObject(o);
- }
- } else {
- writeByte(KLASS);
- }
- } else if ((enumOrdinal = findEnumOrdinal(object)) >= 0) {
- writeByte(POOL_ENUM);
- writePoolObject(findEnumClass(object));
- writeInt(enumOrdinal);
- } else if ((field = findJavaField(object)) != null) {
+ if ((field = findJavaField(object)) != null) {
writeByte(POOL_FIELD);
writePoolObject(findFieldDeclaringClass(field));
writePoolObject(findFieldName(field));
@@ -535,6 +559,18 @@
}
writePoolObject(findNodeSourcePositionCaller(pos));
} else {
+ Node node = findNode(object);
+ if (node != null) {
+ if (versionMajor >= 5) {
+ writeByte(POOL_NODE);
+ writeInt(findNodeId(node));
+ writePoolObject(classForNode(node));
+ return;
+ }
+ if (versionMajor == 4) {
+ object = classForNode(node);
+ }
+ }
NodeClass nodeClass = findNodeClass(object);
if (nodeClass != null) {
writeByte(POOL_NODE_CLASS);
@@ -553,8 +589,27 @@
}
ResolvedJavaMethod method = findMethod(object);
if (method == null) {
- writeByte(POOL_STRING);
- writeString(object.toString());
+ if ((typeName = findJavaTypeName(object)) != null) {
+ writeByte(POOL_CLASS);
+ writeString(typeName);
+ String[] enumValueNames = findEnumTypeValues(object);
+ if (enumValueNames != null) {
+ writeByte(ENUM_KLASS);
+ writeInt(enumValueNames.length);
+ for (String o : enumValueNames) {
+ writePoolObject(o);
+ }
+ } else {
+ writeByte(KLASS);
+ }
+ } else if ((enumOrdinal = findEnumOrdinal(object)) >= 0) {
+ writeByte(POOL_ENUM);
+ writePoolObject(findEnumClass(object));
+ writeInt(enumOrdinal);
+ } else {
+ writeByte(POOL_STRING);
+ writeString(object.toString());
+ }
return;
}
writeByte(POOL_METHOD);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphSnippets.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.graphio;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.WritableByteChannel;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+final class GraphSnippets {
+ static GraphStructure<AcmeGraph, AcmeNode, AcmeNodeType, AcmePorts> acmeGraphStructure() {
+ // @formatter:off
+ // BEGIN: org.graalvm.graphio.GraphSnippets#acmeGraphStructure
+ class AcmeGraphStructure implements
+ GraphStructure<AcmeGraph, AcmeNode, AcmeNodeType, AcmePorts> {
+
+ @Override
+ public AcmeGraph graph(AcmeGraph currentGraph, Object obj) {
+ return obj instanceof AcmeGraph ? (AcmeGraph) obj : null;
+ }
+
+ @Override
+ public Iterable<? extends AcmeNode> nodes(AcmeGraph graph) {
+ return graph.allNodes();
+ }
+
+ @Override
+ public int nodesCount(AcmeGraph graph) {
+ return graph.allNodes().size();
+ }
+
+ @Override
+ public int nodeId(AcmeNode node) {
+ return node.id;
+ }
+
+ @Override
+ public boolean nodeHasPredecessor(AcmeNode node) {
+ return node.id > 0;
+ }
+
+ @Override
+ public void nodeProperties(
+ AcmeGraph graph, AcmeNode node, Map<String, ? super Object> properties
+ ) {
+ properties.put("id", node.id);
+ }
+
+ @Override
+ public AcmeNodeType nodeClass(Object obj) {
+ return obj instanceof AcmeNodeType ? (AcmeNodeType) obj : null;
+ }
+
+ @Override
+ public AcmeNode node(Object obj) {
+ return obj instanceof AcmeNode ? (AcmeNode) obj : null;
+ }
+
+ @Override
+ public AcmeNodeType classForNode(AcmeNode node) {
+ // we have only one type of nodes
+ return AcmeNodeType.STANDARD;
+ }
+
+
+ @Override
+ public String nameTemplate(AcmeNodeType nodeClass) {
+ return "Acme ({p#id})";
+ }
+
+ @Override
+ public Object nodeClassType(AcmeNodeType nodeClass) {
+ return nodeClass.getClass();
+ }
+
+ @Override
+ public AcmePorts portInputs(AcmeNodeType nodeClass) {
+ return AcmePorts.INPUT;
+ }
+
+ @Override
+ public AcmePorts portOutputs(AcmeNodeType nodeClass) {
+ return AcmePorts.OUTPUT;
+ }
+
+ @Override
+ public int portSize(AcmePorts port) {
+ return port == AcmePorts.OUTPUT ? 1 : 0;
+ }
+
+ @Override
+ public boolean edgeDirect(AcmePorts port, int index) {
+ return false;
+ }
+
+ @Override
+ public String edgeName(AcmePorts port, int index) {
+ return port.name();
+ }
+
+ @Override
+ public Object edgeType(AcmePorts port, int index) {
+ return port;
+ }
+
+ @Override
+ public Collection<? extends AcmeNode> edgeNodes(
+ AcmeGraph graph, AcmeNode node, AcmePorts port, int index
+ ) {
+ if (port == AcmePorts.OUTPUT) {
+ return node.outgoing.targets;
+ }
+ return null;
+ }
+ }
+
+ // END: org.graalvm.graphio.GraphSnippets#acmeGraphStructure
+
+ return new AcmeGraphStructure();
+ }
+
+ // BEGIN: org.graalvm.graphio.GraphSnippets#buildOutput
+ static GraphOutput<AcmeGraph, ?> buildOutput(WritableByteChannel channel)
+ throws IOException {
+ return GraphOutput.newBuilder(acmeGraphStructure()).
+ // use the latest version; currently 5.0
+ protocolVersion(5, 0).
+ build(channel);
+ }
+ // END: org.graalvm.graphio.GraphSnippets#buildOutput
+
+ // BEGIN: org.graalvm.graphio.GraphSnippets#buildAll
+ static GraphOutput<AcmeGraph, ?> buildAll(WritableByteChannel channel)
+ throws IOException {
+ GraphBlocks<AcmeGraph, AcmeBlocks, AcmeNode> graphBlocks = acmeBlocks();
+ GraphElements<AcmeMethod, AcmeField,
+ AcmeSignature, AcmeCodePosition> graphElements = acmeElements();
+ GraphTypes graphTypes = acmeTypes();
+
+ return GraphOutput.newBuilder(acmeGraphStructure()).
+ protocolVersion(5, 0).
+ blocks(graphBlocks).
+ elements(graphElements).
+ types(graphTypes).
+ build(channel);
+ }
+ // END: org.graalvm.graphio.GraphSnippets#buildAll
+
+ private static GraphTypes acmeTypes() {
+ GraphTypes graphTypes = null;
+ // in real world don't return null
+ return graphTypes;
+ }
+
+ private static GraphElements<AcmeMethod, AcmeField, AcmeSignature, AcmeCodePosition> acmeElements() {
+ GraphElements<AcmeMethod, AcmeField, AcmeSignature, AcmeCodePosition> graphElements = null;
+ // in real world don't return null
+ return graphElements;
+ }
+
+ private static GraphBlocks<AcmeGraph, AcmeBlocks, AcmeNode> acmeBlocks() {
+ GraphBlocks<AcmeGraph, AcmeBlocks, AcmeNode> graphBlocks = null;
+ // in real world don't return null
+ return graphBlocks;
+ }
+
+ private static class AcmeGraph {
+ final AcmeNode root;
+
+ AcmeGraph(AcmeNode root) {
+ this.root = root;
+ }
+
+ Set<AcmeNode> allNodes() {
+ return allNodes(root, new LinkedHashSet<>());
+ }
+
+ private static Set<AcmeNode> allNodes(AcmeNode node, Set<AcmeNode> collectTo) {
+ if (collectTo.add(node)) {
+ for (AcmeNode target : node.outgoing.targets) {
+ allNodes(target, collectTo);
+ }
+ }
+ return collectTo;
+ }
+ }
+
+ private static class AcmeNode {
+ final int id;
+ final AcmeEdges outgoing;
+
+ AcmeNode(int id) {
+ this.id = id;
+ this.outgoing = new AcmeEdges();
+ }
+
+ void linkTo(AcmeNode target) {
+ outgoing.targets.add(target);
+ }
+ }
+
+ private enum AcmeNodeType {
+ STANDARD
+ }
+
+ private enum AcmePorts {
+ INPUT,
+ OUTPUT;
+ }
+
+ private static class AcmeEdges {
+ final Set<AcmeNode> targets;
+
+ AcmeEdges() {
+ this.targets = new LinkedHashSet<>();
+ }
+ }
+
+ private static class AcmeBlocks {
+ }
+
+ private static class AcmeMethod {
+ }
+
+ private static class AcmeField {
+ }
+
+ private static class AcmeSignature {
+ }
+
+ private static class AcmeCodePosition {
+ }
+
+ // BEGIN: org.graalvm.graphio.GraphSnippets#dump
+ static void dump(File toFile) throws IOException {
+ try (
+ FileChannel ch = new FileOutputStream(toFile).getChannel();
+ GraphOutput<AcmeGraph, ?> output = buildOutput(ch);
+ ) {
+ AcmeNode root = new AcmeNode(0);
+ AcmeNode n1 = new AcmeNode(1);
+ AcmeNode n2 = new AcmeNode(2);
+ AcmeNode n3 = new AcmeNode(3);
+
+ root.linkTo(n1);
+ root.linkTo(n2);
+ n1.linkTo(n3);
+ n2.linkTo(n3);
+
+ AcmeGraph diamondGraph = new AcmeGraph(root);
+
+ output.beginGroup(diamondGraph, "Diamond", "dia", null, 0, null);
+ output.print(diamondGraph, null, 0, "Diamond graph #%d", 1);
+ output.endGroup();
+ }
+ }
+ // END: org.graalvm.graphio.GraphSnippets#dump
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphStructure.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphStructure.java Thu Nov 16 10:45:42 2017 -0800
@@ -38,9 +38,9 @@
*/
public interface GraphStructure<G, N, C, P> {
/**
- * Casts the provided object to graph, if possible. If the given object <code>obj</code> can be
- * seen as a graph or sub-graph of a graph, then return the properly typed instance. Otherwise
- * return <code>null</code>
+ * Casts {@code obj} to graph, if possible. If the given object <code>obj</code> can be seen as
+ * a graph or sub-graph of a graph, then return the properly typed instance. Otherwise return
+ * <code>null</code>
*
* @param currentGraph the currently processed graph
* @param obj an object to check and view as a graph
@@ -69,8 +69,8 @@
int nodesCount(G graph);
/**
- * Id of a node. Each node in the graph is uniquely identified by a integer value. If two nodes
- * have the same id, then they shall be <code>==</code> to each other.
+ * Id of {@code node}. Each node in the graph is uniquely identified by an integer value. If two
+ * nodes have the same id, then they shall be <code>==</code> to each other.
*
* @param node the node to query for an id
* @return the id of the node
@@ -96,16 +96,35 @@
void nodeProperties(G graph, N node, Map<String, ? super Object> properties);
/**
- * Finds the node class for the provided object, if possible. If the given object
- * <code>obj</code> can be seen as an instance of node class or it is a node in this graph,
- * return the properly typed instance of the node class. Otherwise return <code>null</code>
+ * Finds a node for {@code obj}, if possible. If the given object <code>obj</code> can be seen
+ * as an instance of node return the properly typed instance of the node class. Otherwise return
+ * <code>null</code>.
+ *
+ * @param obj an object to find node for
+ * @return appropriate graph object or <code>null</code> if the object doesn't represent a node
+ */
+ N node(Object obj);
+
+ /**
+ * Finds a node class for {@code obj}, if possible. If the given object <code>obj</code> can be
+ * seen as an instance of node class return the properly typed instance of the node class.
+ * Otherwise return <code>null</code>.
*
* @param obj an object to find node class for
- * @return appropriate graph object or <code>null</code> if the object doesn't represent a graph
+ * @return appropriate graph object or <code>null</code> if the object doesn't represent a node
+ * class
*/
C nodeClass(Object obj);
/**
+ * Finds a node class for {@code node}.
+ *
+ * @param node an instance of node in this graph
+ * @return the node's node class, never <code>null</code>
+ */
+ C classForNode(N node);
+
+ /**
* The template used to build the name of nodes of this class. The template may use references
* to inputs ({i#inputName}) and its properties ({p#propertyName}).
*
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/ProtocolImpl.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/ProtocolImpl.java Thu Nov 16 10:45:42 2017 -0800
@@ -34,9 +34,18 @@
private final GraphBlocks<Graph, Block, Node> blocks;
private final GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements;
- ProtocolImpl(GraphStructure<Graph, Node, NodeClass, Port> structure, GraphTypes enums, GraphBlocks<Graph, Block, Node> blocks,
+ ProtocolImpl(int major, int minor, GraphStructure<Graph, Node, NodeClass, Port> structure, GraphTypes enums, GraphBlocks<Graph, Block, Node> blocks,
GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements, WritableByteChannel channel) throws IOException {
- super(channel);
+ super(channel, major, minor);
+ this.structure = structure;
+ this.types = enums;
+ this.blocks = blocks;
+ this.elements = elements;
+ }
+
+ ProtocolImpl(GraphProtocol<?, ?, ?, ?, ?, ?, ?, ?, ?> parent, GraphStructure<Graph, Node, NodeClass, Port> structure, GraphTypes enums, GraphBlocks<Graph, Block, Node> blocks,
+ GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements) {
+ super(parent);
this.structure = structure;
this.types = enums;
this.blocks = blocks;
@@ -49,11 +58,21 @@
}
@Override
+ protected Node findNode(Object obj) {
+ return structure.node(obj);
+ }
+
+ @Override
protected NodeClass findNodeClass(Object obj) {
return structure.nodeClass(obj);
}
@Override
+ protected NodeClass findClassForNode(Node obj) {
+ return structure.classForNode(obj);
+ }
+
+ @Override
protected String findNameTemplate(NodeClass clazz) {
return structure.nameTemplate(clazz);
}
Binary file src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/doc-files/diamond.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/package-info.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,86 @@
+
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/**
+ * Send your graphs to <b>IGV</b> via a socket or a file. This package allows one to easily encode
+ * any graph-like data structure and send it for visualization to
+ * <em>OracleLab's Ideal Graph Visualizer</em> tool. Assuming you already have your own data
+ * structure that contains <b>nodes</b> and <b>edges</b> among them, creating a
+ * {@link org.graalvm.graphio.GraphOutput} specialized for your data is a matter of implementing a
+ * single interface:
+ *
+ * {@link org.graalvm.graphio.GraphSnippets#acmeGraphStructure}
+ *
+ * The {@link org.graalvm.graphio.GraphStructure} interface defines the set of operations that are
+ * needed by the <em>graph protocol</em> to encode a graph into the <b>IGV</b> expected format. The
+ * graph structure is implemented as a so called
+ * <a href="http://wiki.apidesign.org/wiki/Singletonizer">singletonizer</a> API pattern: there is no
+ * need to change your data structures or implement some special interfaces - everything needed is
+ * provided by implementing the {@link org.graalvm.graphio.GraphStructure} operations.
+ * <p>
+ * The next step is to turn this graph structure into an instance of
+ * {@link org.graalvm.graphio.GraphOutput}. To do so use the associated
+ * {@link org.graalvm.graphio.GraphOutput.Builder builder} just like shown in the following method:
+ *
+ * {@link org.graalvm.graphio.GraphSnippets#buildOutput}
+ *
+ * Now you are ready to dump your graph into <b>IGV</b>. Where to obtain the right channel? One
+ * option is to create a {@link java.nio.channels.FileChannel} and dump the data into a file
+ * (preferrably with <code>.bgv</code> extension). The other is to open a socket to port
+ * <code>4445</code> (the default port <b>IGV</b> listens to) and dump the data there. Here is an
+ * example:
+ *
+ * {@link org.graalvm.graphio.GraphSnippets#dump}
+ *
+ * Call the {@code dump} method with pointer to file {@code diamond.bgv} and then you can open the
+ * file in <b>IGV</b>. The result will look like this:
+ * <p>
+ * <img src="doc-files/diamond.png">
+ * <p>
+ * You can verify the behavior directly in the <b>IGV</b> by downloading
+ * <a href="doc-files/diamond.bgv">diamond.bgv</a> file generated from the above diamond structure
+ * graph.
+ * <p>
+ * The primary <b>IGV</b> focus is on graphs used by Graal compiler. As such they aren't plain
+ * graphs, but contain various compiler oriented attributes:
+ * <ul>
+ * <li>{@linkplain org.graalvm.graphio.GraphBlocks code blocks} information</li>
+ * <li>{@linkplain org.graalvm.graphio.GraphElements method and fields} information</li>
+ * <li>Advanced support for {@linkplain org.graalvm.graphio.GraphTypes recognizing types}</li>
+ * </ul>
+ * all these additional interfaces ({@link org.graalvm.graphio.GraphBlocks},
+ * {@link org.graalvm.graphio.GraphElements} and {@link org.graalvm.graphio.GraphTypes}) are
+ * optional - they don't have to be provided. As such they can be specified via
+ * {@link org.graalvm.graphio.GraphOutput.Builder} instance methods, which may, but need not be
+ * called at all. Here is an example:
+ *
+ * {@link org.graalvm.graphio.GraphSnippets#buildAll}
+ *
+ * All these interfaces follow the
+ * <a href="http://wiki.apidesign.org/wiki/Singletonizer">singletonizer</a> API pattern again - e.g.
+ * no need to change your existing data structures, just implement the operations provided by the
+ * interfaces you pass into the builder. By combining these interfaces together you can get as rich,
+ * colorful, source linked graphs as Graal compiler produces to describe its optimizations.
+ */
+package org.graalvm.graphio;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!--
+ This configuration file was written by the eclipse-cs plugin configuration editor
+-->
+<!--
+ Checkstyle-Configuration: Checks
+ Description: none
+-->
+<module name="Checker">
+ <property name="severity" value="error"/>
+ <module name="TreeWalker">
+ <module name="AvoidStarImport">
+ <property name="allowClassImports" value="false"/>
+ <property name="allowStaticMemberImports" value="false"/>
+ </module>
+ <property name="tabWidth" value="4"/>
+ <module name="FileContentsHolder"/>
+ <module name="JavadocStyle">
+ <property name="checkHtml" value="false"/>
+ </module>
+ <module name="LocalFinalVariableName"/>
+ <module name="LocalVariableName"/>
+ <module name="MemberName">
+ <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
+ </module>
+ <module name="MethodName"/>
+ <module name="PackageName"/>
+ <module name="ParameterName"/>
+ <module name="TypeName">
+ <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
+ </module>
+ <module name="RedundantImport"/>
+ <module name="LineLength">
+ <property name="max" value="250"/>
+ </module>
+ <module name="MethodParamPad"/>
+ <module name="NoWhitespaceAfter">
+ <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
+ </module>
+ <module name="NoWhitespaceBefore">
+ <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
+ </module>
+ <module name="ParenPad"/>
+ <module name="TypecastParenPad">
+ <property name="tokens" value="RPAREN,TYPECAST"/>
+ </module>
+ <module name="WhitespaceAfter"/>
+ <module name="WhitespaceAround">
+ <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
+ </module>
+ <module name="RedundantModifier"/>
+ <module name="AvoidNestedBlocks">
+ <property name="allowInSwitchCase" value="true"/>
+ </module>
+ <module name="EmptyBlock">
+ <property name="option" value="text"/>
+ <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
+ </module>
+ <module name="LeftCurly"/>
+ <module name="NeedBraces"/>
+ <module name="RightCurly"/>
+ <module name="EmptyStatement"/>
+ <module name="HiddenField">
+ <property name="severity" value="ignore"/>
+ <property name="ignoreConstructorParameter" value="true"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="FinalClass"/>
+ <module name="HideUtilityClassConstructor">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="ArrayTypeStyle"/>
+ <module name="UpperEll"/>
+ <module name="FallThrough"/>
+ <module name="FinalLocalVariable">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="MultipleVariableDeclarations"/>
+ <module name="StringLiteralEquality">
+ <property name="severity" value="error"/>
+ </module>
+ <module name="SuperFinalize"/>
+ <module name="UnnecessaryParentheses">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="Indentation">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="StaticVariableName">
+ <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
+ </module>
+ <module name="EmptyForInitializerPad"/>
+ <module name="EmptyForIteratorPad"/>
+ <module name="ModifierOrder"/>
+ <module name="DefaultComesLast"/>
+ <module name="InnerAssignment">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="ModifiedControlVariable"/>
+ <module name="MutableException">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="ParameterAssignment">
+ <property name="severity" value="ignore"/>
+ <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
+ <property name="format" value="\s$"/>
+ <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
+ <property name="ignoreComments" value="true"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
+ <property name="format" value=" ,"/>
+ <property name="message" value="illegal space before a comma"/>
+ <property name="ignoreComments" value="true"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="[^\x00-\x7F]"/>
+ <property name="message" value="Only use ASCII characters."/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
+ <property name="message" value="Don't use old synchronized collection classes"/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="instanceof MoveOp"/>
+ <property name="message" value="Do not use `op instanceof MoveOp`. Use `MoveOp.isMoveOp(op)` instead!"/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="instanceof ValueMoveOp"/>
+ <property name="message" value="Do not use `op instanceof ValueMoveOp`. Use `ValueMoveOp.isValueMoveOp(op)` instead!"/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="instanceof LoadConstantOp"/>
+ <property name="message" value="Do not use `op instanceof LoadConstantOp`. Use `LoadConstantOp.isLoadConstantOp(op)` instead!"/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="\(MoveOp\)"/>
+ <property name="message" value="Do not cast directly to `MoveOp`. Use `MoveOp.asMoveOp(op)` instead!"/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="\(ValueMoveOp\)"/>
+ <property name="message" value="Do not cast directly to `ValueMoveOp`. Use `ValueMoveOp.asValueMoveOp(op)` instead!"/>
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="\(LoadConstantOp\)"/>
+ <property name="message" value="Do not cast directly to `LoadConstantOp`. Use `LoadConstantOp.asLoadConstantOp(op)` instead!"/>
+ </module>
+ </module>
+ <module name="RegexpHeader">
+ <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation. Oracle designates this\n \* particular file as subject to the "Classpath" exception as provided\n \* by Oracle in the LICENSE file that accompanied this code.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
+ <property name="fileExtensions" value="java"/>
+ </module>
+ <module name="FileTabCharacter">
+ <property name="severity" value="error"/>
+ <property name="fileExtensions" value="java"/>
+ </module>
+ <module name="NewlineAtEndOfFile">
+ <property name="lineSeparator" value="lf"/>
+ </module>
+ <module name="Translation"/>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
+ <property name="checkFormat" value="ConstantNameCheck"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
+ <property name="checkFormat" value="MethodName"/>
+ <property name="checkC" value="false"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
+ <property name="checkFormat" value="ParameterAssignment"/>
+ <property name="checkC" value="false"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
+ <property name="checkFormat" value="FinalLocalVariable"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop"/>
+ <property name="onCommentFormat" value="Checkstyle: resume"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
+ <property name="checkFormat" value="InnerAssignment"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
+ <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
+ <property name="checkFormat" value="MemberName"/>
+ <property name="checkC" value="false"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
+ </module>
+ <module name="RegexpMultiline">
+ <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
+ <property name="format" value="\r\n"/>
+ <property name="message" value="illegal Windows line ending"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop header check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume header check"/>
+ <property name="checkFormat" value=".*Header"/>
+ <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
+ <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
+ <property name="checkFormat" value="LineLength"/>
+ </module>
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="CheckStyle: start generated"/>
+ <property name="onCommentFormat" value="CheckStyle: stop generated"/>
+ <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
+ </module>
+</module>
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java Thu Nov 16 10:45:42 2017 -0800
@@ -139,7 +139,7 @@
head.addContent(windowTitle);
Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, configuration.charset);
head.addContent(meta);
- head.addContent(getStyleSheetProperties(configuration));
+ addStyleSheetProperties(configuration, head);
head.addContent(getFramesJavaScript());
Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
head, body);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java Thu Nov 16 10:45:42 2017 -0800
@@ -133,6 +133,11 @@
public String stylesheetfile = "";
/**
+ * Argument for command line option "--add-stylesheet".
+ */
+ public List<String> additionalStylesheets = new ArrayList<>();
+
+ /**
* Argument for command line option "-Xdocrootparent".
*/
public String docrootparent = "";
@@ -304,6 +309,22 @@
return false;
}
}
+ // check if stylesheetfile exists
+ if (!stylesheetfile.isEmpty()) {
+ DocFile stylesheet = DocFile.createFileForInput(this, stylesheetfile);
+ if (!stylesheet.exists()) {
+ reporter.print(ERROR, getText("doclet.File_not_found", stylesheetfile));
+ return false;
+ }
+ }
+ // check if additional stylesheets exists
+ for (String ssheet : additionalStylesheets) {
+ DocFile ssfile = DocFile.createFileForInput(this, ssheet);
+ if (!ssfile.exists()) {
+ reporter.print(ERROR, getText("doclet.File_not_found", ssheet));
+ return false;
+ }
+ }
// In a more object-oriented world, this would be done by methods on the Option objects.
// Note that -windowtitle silently removes any and all HTML elements, and so does not need
@@ -554,6 +575,13 @@
public Set<Doclet.Option> getSupportedOptions() {
Resources resources = getResources();
Doclet.Option[] options = {
+ new Option(resources, "--add-stylesheet", 1) {
+ @Override
+ public boolean process(String opt, List<String> args) {
+ additionalStylesheets.add(args.get(0));
+ return true;
+ }
+ },
new Option(resources, "-bottom", 1) {
@Override
public boolean process(String opt, List<String> args) {
@@ -722,7 +750,7 @@
return true;
}
},
- new Option(resources, "-stylesheetfile", 1) {
+ new Option(resources, "--main-stylesheet -stylesheetfile", 1) {
@Override
public boolean process(String opt, List<String> args) {
stylesheetfile = args.get(0);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java Thu Nov 16 10:45:42 2017 -0800
@@ -125,6 +125,9 @@
boolean nodeprecated = configuration.nodeprecated;
performCopy(configuration.helpfile);
performCopy(configuration.stylesheetfile);
+ for (String stylesheet : configuration.additionalStylesheets) {
+ performCopy(stylesheet);
+ }
// do early to reduce memory footprint
if (configuration.classuse) {
ClassUseWriter.generate(configuration, classtree);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java Thu Nov 16 10:45:42 2017 -0800
@@ -2162,6 +2162,7 @@
pathToRoot.resolve(stylesheet).getPath(),
"Style");
head.addContent(link);
+ addStylesheets(configuration, head);
if (configuration.createindex) {
HtmlTree jq_link = HtmlTree.LINK("stylesheet", "text/css",
pathToRoot.resolve(DocPaths.JQUERY_FILES.resolve(DocPaths.JQUERY_STYLESHEET_FILE)).getPath(),
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java Thu Nov 16 10:45:42 2017 -0800
@@ -94,7 +94,7 @@
head.addContent(metaRefresh);
}
- head.addContent(getStyleSheetProperties(configuration));
+ addStyleSheetProperties(configuration, head);
ContentBuilder bodyContent = new ContentBuilder();
bodyContent.addContent(HtmlTree.NOSCRIPT(
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SourceToHTMLConverter.java Thu Nov 16 10:45:42 2017 -0800
@@ -26,6 +26,7 @@
package jdk.javadoc.internal.doclets.formats.html;
import java.io.*;
+import java.util.List;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
@@ -210,7 +211,7 @@
Content head = new HtmlTree(HtmlTag.HEAD);
head.addContent(HtmlTree.TITLE(new StringContent(
configuration.getText("doclet.Window_Source_title"))));
- head.addContent(getStyleSheetProperties());
+ addStyleSheetProperties(head);
Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
head, body);
Content htmlDocument = new HtmlDocument(htmlDocType, htmlTree);
@@ -227,9 +228,9 @@
/**
* Returns a link to the stylesheet file.
*
- * @return an HtmlTree for the lINK tag which provides the stylesheet location
+ * @param head an HtmlTree to which the stylesheet links will be added
*/
- public HtmlTree getStyleSheetProperties() {
+ public void addStyleSheetProperties(Content head) {
String filename = configuration.stylesheetfile;
DocPath stylesheet;
if (filename.length() > 0) {
@@ -240,7 +241,21 @@
}
DocPath p = relativePath.resolve(stylesheet);
HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", p.getPath(), "Style");
- return link;
+ head.addContent(link);
+ addStylesheets(head);
+ }
+
+ protected void addStylesheets(Content tree) {
+ List<String> stylesheets = configuration.additionalStylesheets;
+ if (!stylesheets.isEmpty()) {
+ stylesheets.forEach((ssheet) -> {
+ DocFile file = DocFile.createFileForInput(configuration, ssheet);
+ DocPath ssheetPath = DocPath.create(file.getName());
+ HtmlTree slink = HtmlTree.LINK("stylesheet", "text/css", relativePath.resolve(ssheetPath).getPath(),
+ "Style");
+ tree.addContent(slink);
+ });
+ }
}
/**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocWriter.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocWriter.java Thu Nov 16 10:45:42 2017 -0800
@@ -311,9 +311,9 @@
* Returns a link to the stylesheet file.
*
* @param configuration the configuration for this doclet
- * @return an HtmlTree for the lINK tag which provides the stylesheet location
+ * @param head HtmlTree to which the stylesheet links will be added
*/
- public HtmlTree getStyleSheetProperties(HtmlConfiguration configuration) {
+ public void addStyleSheetProperties(HtmlConfiguration configuration, Content head) {
String stylesheetfile = configuration.stylesheetfile;
DocPath stylesheet;
if (stylesheetfile.isEmpty()) {
@@ -325,7 +325,21 @@
HtmlTree link = HtmlTree.LINK("stylesheet", "text/css",
pathToRoot.resolve(stylesheet).getPath(),
"Style");
- return link;
+ head.addContent(link);
+ addStylesheets(configuration, head);
+ }
+
+ protected void addStylesheets(HtmlConfiguration configuration, Content tree) {
+ List<String> stylesheets = configuration.additionalStylesheets;
+ if (!stylesheets.isEmpty()) {
+ stylesheets.forEach((ssheet) -> {
+ DocFile file = DocFile.createFileForInput(configuration, ssheet);
+ DocPath ssheetPath = DocPath.create(file.getName());
+ HtmlTree slink = HtmlTree.LINK("stylesheet", "text/css", pathToRoot.resolve(ssheetPath).getPath(),
+ "Style");
+ tree.addContent(slink);
+ });
+ }
}
protected Comment getGeneratedBy(boolean timestamp) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties Thu Nov 16 10:45:42 2017 -0800
@@ -175,6 +175,10 @@
doclet.Same_element_name_used=Element name or pattern used twice: {0}
# option specifiers
+doclet.usage.add-stylesheet.parameters=\
+ <file>
+doclet.usage.add-stylesheet.description=\
+ Additional stylesheet file for the generated documentation
doclet.usage.d.parameters=\
<directory>
doclet.usage.d.description=\
@@ -329,9 +333,9 @@
doclet.usage.keywords.description=\
Include HTML meta tags with package, class and member info
-doclet.usage.stylesheetfile.parameters=\
- <path>
-doclet.usage.stylesheetfile.description=\
+doclet.usage.main-stylesheet.parameters=\
+ <file>
+doclet.usage.main-stylesheet.description=\
File to change style of the generated documentation
doclet.usage.docencoding.parameters=\
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java Thu Nov 16 10:45:42 2017 -0800
@@ -242,8 +242,14 @@
lines.map(line -> line.split(" "))
.forEach(parts -> {
switch (parts[0]) {
- case "[BMH_RESOLVE]":
- speciesTypes.add(expandSignature(parts[1]));
+ case "[SPECIES_RESOLVE]":
+ // Allow for new types of species data classes being resolved here
+ if (parts.length == 3 && parts[1].startsWith("java.lang.invoke.BoundMethodHandle$Species_")) {
+ String species = parts[1].substring("java.lang.invoke.BoundMethodHandle$Species_".length());
+ if (!"L".equals(species)) {
+ speciesTypes.add(expandSignature(species));
+ }
+ }
break;
case "[LF_RESOLVE]":
String methodType = parts[3];
@@ -449,7 +455,7 @@
"/java.base/" + INVOKERS_HOLDER + ".class";
// Convert LL -> LL, L3 -> LLL
- private static String expandSignature(String signature) {
+ public static String expandSignature(String signature) {
StringBuilder sb = new StringBuilder();
char last = 'X';
int count = 0;
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Thu Nov 16 10:45:42 2017 -0800
@@ -76,14 +76,16 @@
@Override
public String getMethodCallSyntax(final String obj, final String method, final String... args) {
- final StringBuilder sb = new StringBuilder().append(obj).append('.').append(method).append('(');
+ final StringBuilder sb = new StringBuilder().
+ append(Objects.requireNonNull(obj)).append('.').
+ append(Objects.requireNonNull(method)).append('(');
final int len = args.length;
if (len > 0) {
- sb.append(args[0]);
+ sb.append(Objects.requireNonNull(args[0]));
}
for (int i = 1; i < len; i++) {
- sb.append(',').append(args[i]);
+ sb.append(',').append(Objects.requireNonNull(args[i]));
}
sb.append(')');
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeMath.java Wed Nov 15 09:31:17 2017 -0800
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeMath.java Thu Nov 16 10:45:42 2017 -0800
@@ -105,8 +105,8 @@
* @return abs of argument
*/
@SpecializedFunction
- public static int abs(final Object self, final int x) {
- return Math.abs(x);
+ public static double abs(final Object self, final int x) {
+ return x == Integer.MIN_VALUE? Math.abs((double)x) : Math.abs(x);
}
/**
--- a/test/hotspot/gtest/classfile/test_AltHashing.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/gtest/classfile/test_AltHashing.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -51,7 +51,7 @@
class AltHashingTest : public ::testing::Test {
public:
- static juint murmur3_32(const int* data, int len) {
+ static juint murmur3_32(const jint* data, int len) {
return AltHashing::murmur3_32(data, len);
}
};
--- a/test/hotspot/gtest/logging/logTestFixture.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/gtest/logging/logTestFixture.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,11 +22,11 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logTestFixture.hpp"
#include "logTestUtils.inline.hpp"
#include "logging/logConfiguration.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "unittest.hpp"
#include "utilities/ostream.hpp"
--- a/test/hotspot/gtest/logging/test_log.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/gtest/logging/test_log.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,11 +22,11 @@
*
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "logTestFixture.hpp"
#include "logTestUtils.inline.hpp"
#include "logging/log.hpp"
-#include "prims/jvm.h"
#include "unittest.hpp"
class LogTest : public LogTestFixture {
--- a/test/hotspot/gtest/logging/test_logConfiguration.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/gtest/logging/test_logConfiguration.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,6 +22,7 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logTestFixture.hpp"
#include "logTestUtils.inline.hpp"
#include "logging/logConfiguration.hpp"
@@ -31,7 +32,6 @@
#include "logging/logTag.hpp"
#include "logging/logTagSet.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "unittest.hpp"
#include "utilities/ostream.hpp"
--- a/test/hotspot/gtest/logging/test_logDecorators.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/gtest/logging/test_logDecorators.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,8 +22,8 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logging/logDecorators.hpp"
-#include "prims/jvm.h"
#include "unittest.hpp"
static LogDecorators::Decorator decorator_array[] = {
--- a/test/hotspot/gtest/logging/test_logFileOutput.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/gtest/logging/test_logFileOutput.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,10 +22,10 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logTestUtils.inline.hpp"
#include "logging/logFileOutput.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "runtime/os.hpp"
#include "unittest.hpp"
#include "utilities/globalDefinitions.hpp"
--- a/test/hotspot/gtest/logging/test_logMessageTest.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/gtest/logging/test_logMessageTest.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,11 +22,11 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logTestFixture.hpp"
#include "logTestUtils.inline.hpp"
#include "logging/log.hpp"
#include "logging/logMessage.hpp"
-#include "prims/jvm.h"
#include "unittest.hpp"
#include "utilities/globalDefinitions.hpp"
--- a/test/hotspot/gtest/logging/test_logTagLevelExpression.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/gtest/logging/test_logTagLevelExpression.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,10 +22,10 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logging/logLevel.hpp"
#include "logging/logTagLevelExpression.hpp"
#include "logging/logTagSet.hpp"
-#include "prims/jvm.h"
#include "unittest.hpp"
#include "utilities/globalDefinitions.hpp"
--- a/test/hotspot/gtest/logging/test_logTagSetDescriptions.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/gtest/logging/test_logTagSetDescriptions.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,12 +22,12 @@
*
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "logTestUtils.inline.hpp"
#include "logging/logConfiguration.hpp"
#include "logging/logTagSet.hpp"
#include "logging/logTagSetDescriptions.hpp"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "unittest.hpp"
#include "utilities/ostream.hpp"
--- a/test/hotspot/gtest/runtime/test_arguments.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/gtest/runtime/test_arguments.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,9 +22,9 @@
*/
#include "precompiled.hpp"
-#include "prims/jvm.h"
+#include "jvm.h"
+#include "unittest.hpp"
#include "runtime/arguments.hpp"
-#include "unittest.hpp"
#include "utilities/align.hpp"
#include "utilities/globalDefinitions.hpp"
--- a/test/hotspot/gtest/utilities/test_json.cpp Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/gtest/utilities/test_json.cpp Thu Nov 16 10:45:42 2017 -0800
@@ -22,8 +22,8 @@
*/
#include "precompiled.hpp"
+#include "jvm.h"
#include "memory/resourceArea.hpp"
-#include "prims/jvm.h"
#include "utilities/json.hpp"
#include "unittest.hpp"
--- a/test/hotspot/jtreg/ProblemList.txt Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/ProblemList.txt Thu Nov 16 10:45:42 2017 -0800
@@ -54,6 +54,9 @@
# aot test intermittently failing in jprt 8175791
compiler/aot/DeoptimizationTest.java 8175791 windows-all
+applications/ctw/modules/java_desktop.java 8189604 windows-all
+applications/ctw/modules/jdk_jconsole.java 8189604 windows-all
+
#############################################################################
# :hotspot_gc
--- a/test/hotspot/jtreg/TEST.groups Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/TEST.groups Thu Nov 16 10:45:42 2017 -0800
@@ -107,15 +107,11 @@
-compiler/loopopts/Test7052494.java \
-compiler/runtime/Test6826736.java
-hotspot_tier1_compiler_closed = \
- sanity/ExecuteInternalVMTests.java
-
hotspot_not_fast_compiler = \
:hotspot_compiler \
-:hotspot_tier1_compiler_1 \
-:hotspot_tier1_compiler_2 \
-:hotspot_tier1_compiler_3 \
- -:hotspot_tier1_compiler_closed
hotspot_tier1_gc_1 = \
gc/g1/
@@ -130,9 +126,6 @@
-gc/cms/TestMBeanCMS.java \
-gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java
-hotspot_tier1_gc_closed = \
- sanity/ExecuteInternalVMTests.java
-
hotspot_tier1_gc_gcold = \
gc/stress/gcold/TestGCOldWithG1.java
gc/stress/gcold/TestGCOldWithCMS.java
@@ -204,10 +197,8 @@
:hotspot_tier1_compiler_1 \
:hotspot_tier1_compiler_2 \
:hotspot_tier1_compiler_3 \
- :hotspot_tier1_compiler_closed \
:hotspot_tier1_gc_1 \
:hotspot_tier1_gc_2 \
- :hotspot_tier1_gc_closed \
:hotspot_tier1_gc_gcold \
:hotspot_tier1_runtime \
:hotspot_tier1_serviceability
--- a/test/hotspot/jtreg/applications/ctw/Modules.java Wed Nov 15 09:31:17 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2017, 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.
- */
-
-/*
- * @test
- * @summary run CTW for all classes from boot "modules" jimage -- lib/modules.
- *
- * @library /test/lib / /testlibrary/ctw/src
- * @modules java.base/jdk.internal.jimage
- * java.base/jdk.internal.misc
- * java.base/jdk.internal.reflect
- *
- * @build sun.hotspot.WhiteBox
- * @run driver ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/timeout=0 sun.hotspot.tools.ctw.CtwRunner modules
- */
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/generate.bash Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# Copyright (c) 2017, 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.
+#
+
+# generates CTW tests for modules passed as argument
+
+for module in $@
+do
+ file=${module//./_}.java
+ echo creating $file for $module...
+ cat > $file <<EOF
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from $module module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules $module
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox\$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:$module
+ */
+EOF
+
+done
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_activation.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.activation module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.activation
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.activation
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_base.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.base module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.base
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.base
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_compiler.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.compiler module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.compiler
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.compiler
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_corba.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.corba module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.corba
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.corba
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_datatransfer.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.datatransfer module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.datatransfer
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.datatransfer
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_desktop.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.desktop module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.desktop
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.desktop
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_instrument.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.instrument module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.instrument
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.instrument
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_logging.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.logging module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.logging
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.logging
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_management.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.management module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.management
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.management
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_management_rmi.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.management.rmi module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.management.rmi
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.management.rmi
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_naming.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.naming module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.naming
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.naming
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_prefs.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.prefs module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.prefs
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.prefs
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_rmi.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.rmi module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.rmi
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.rmi
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_scripting.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.scripting module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.scripting
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.scripting
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_security_jgss.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.security.jgss module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.security.jgss
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.security.jgss
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_security_sasl.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.security.sasl module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.security.sasl
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.security.sasl
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_smartcardio.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.smartcardio module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.smartcardio
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.smartcardio
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_sql.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.sql module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.sql
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.sql
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_sql_rowset.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.sql.rowset module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.sql.rowset
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.sql.rowset
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_transaction.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.transaction module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.transaction
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.transaction
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_xml.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.xml module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.xml
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.xml
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_xml_bind.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.xml.bind module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.xml.bind
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.xml.bind
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_xml_crypto.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.xml.crypto module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.xml.crypto
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.xml.crypto
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_xml_ws.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.xml.ws module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.xml.ws
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.xml.ws
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_xml_ws_annotation.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from java.xml.ws.annotation module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules java.xml.ws.annotation
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.xml.ws.annotation
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/javafx_base.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from javafx.base module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules javafx.base
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:javafx.base
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/javafx_controls.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from javafx.controls module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules javafx.controls
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:javafx.controls
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/javafx_fxml.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from javafx.fxml module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules javafx.fxml
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:javafx.fxml
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/javafx_graphics.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from javafx.graphics module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules javafx.graphics
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:javafx.graphics
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/javafx_media.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from javafx.media module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules javafx.media
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:javafx.media
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/javafx_swing.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from javafx.swing module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules javafx.swing
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:javafx.swing
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/javafx_web.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from javafx.web module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules javafx.web
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:javafx.web
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_accessibility.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.accessibility module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.accessibility
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.accessibility
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_aot.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.aot module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.aot
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.aot
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_attach.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.attach module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.attach
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.attach
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_charsets.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.charsets module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.charsets
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.charsets
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_compiler.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.compiler module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.compiler
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.compiler
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_crypto_cryptoki.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.crypto.cryptoki module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.crypto.cryptoki
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.crypto.cryptoki
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_crypto_ec.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.crypto.ec module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.crypto.ec
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.crypto.ec
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_crypto_mscapi.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.crypto.mscapi module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.crypto.mscapi
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.crypto.mscapi
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_crypto_ucrypto.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.crypto.ucrypto module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.crypto.ucrypto
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.crypto.ucrypto
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_dynalink.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.dynalink module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.dynalink
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.dynalink
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_editpad.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.editpad module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.editpad
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.editpad
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_hotspot_agent.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.hotspot.agent module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.hotspot.agent
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.hotspot.agent
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_httpserver.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.httpserver module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.httpserver
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.httpserver
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_incubator_httpclient.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.incubator.httpclient module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.incubator.httpclient
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.incubator.httpclient
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_internal_ed.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.internal.ed module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.internal.ed
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.internal.ed
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_internal_jvmstat.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.internal.jvmstat module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.internal.jvmstat
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.internal.jvmstat
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_internal_le.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.internal.le module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.internal.le
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.internal.le
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_internal_opt.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.internal.opt module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.internal.opt
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.internal.opt
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_internal_vm_ci.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.internal.vm.ci module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.internal.vm.ci
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.internal.vm.ci
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_internal_vm_compiler.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.internal.vm.compiler module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.internal.vm.compiler
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.internal.vm.compiler
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_internal_vm_compiler_management.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.internal.vm.compiler.management module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.internal.vm.compiler.management
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.internal.vm.compiler.management
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_jartool.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.jartool module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.jartool
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.jartool
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_javadoc.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.javadoc module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.javadoc
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.javadoc
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_jcmd.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.jcmd module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.jcmd
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.jcmd
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_jconsole.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.jconsole module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.jconsole
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.jconsole
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_jdeps.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.jdeps module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.jdeps
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.jdeps
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_jdi.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.jdi module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.jdi
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.jdi
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_jlink.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.jlink module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.jlink
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.jlink
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_jshell.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.jshell module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.jshell
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.jshell
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_jsobject.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.jsobject module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.jsobject
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.jsobject
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_jstatd.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.jstatd module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.jstatd
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.jstatd
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_localedata.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.localedata module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.localedata
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.localedata
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_management.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.management module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.management
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.management
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_management_agent.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.management.agent module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.management.agent
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.management.agent
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_naming_dns.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.naming.dns module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.naming.dns
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.naming.dns
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_naming_rmi.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.naming.rmi module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.naming.rmi
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.naming.rmi
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_net.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.net module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.net
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.net
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_packager.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.packager module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.packager
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.packager
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_packager_services.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.packager.services module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.packager.services
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.packager.services
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_rmic.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.rmic module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.rmic
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.rmic
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_scripting_nashorn.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.scripting.nashorn module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.scripting.nashorn
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.scripting.nashorn
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_scripting_nashorn_shell.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.scripting.nashorn.shell module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.scripting.nashorn.shell
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.scripting.nashorn.shell
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_sctp.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.sctp module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.sctp
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.sctp
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_security_auth.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.security.auth module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.security.auth
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.security.auth
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_security_jgss.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.security.jgss module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.security.jgss
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.security.jgss
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_unsupported.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.unsupported module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.unsupported
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.unsupported
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_xml_bind.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.xml.bind module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.xml.bind
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.xml.bind
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_xml_dom.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.xml.dom module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.xml.dom
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.xml.dom
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_xml_ws.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.xml.ws module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.xml.ws
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.xml.ws
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/jdk_zipfs.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for all classes from jdk.zipfs module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ * java.base/jdk.internal.misc
+ * java.base/jdk.internal.reflect
+ * @modules jdk.zipfs
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.zipfs
+ */
--- a/test/hotspot/jtreg/compiler/codecache/jmx/InitialAndMaxUsageTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/compiler/codecache/jmx/InitialAndMaxUsageTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -75,18 +75,12 @@
}
}
- private void fillWithSize(long size, List<Long> blobs, MemoryPoolMXBean bean) {
- long blob;
- /* Don't fill too much to have space for adapters. So, stop after crossing 95% and
- don't allocate in case we'll cross 97% on next allocation. We can hit situation
- like 94% -> (1 allocation) -> 100% otherwise. So, check if
- <Usage + allocatedSize> is less than 97%, then allocate in case it is, then, stop
- further allocations with given size in case <Usage> more than 95% */
- while (((double) bean.getUsage().getUsed() + size <= (CACHE_USAGE_COEF + 0.02d) * maxSize)
- && (blob = CodeCacheUtils.WB.allocateCodeBlob(size, btype.id)) != 0L
- && ((double) bean.getUsage().getUsed() <= CACHE_USAGE_COEF * maxSize)) {
- blobs.add(blob);
- }
+ private boolean canAllocate(double size, long maxSize, MemoryPoolMXBean bean) {
+ // Don't fill too much to have space for adapters. So, stop after crossing 95% and
+ // don't allocate in case we'll cross 97% on next allocation.
+ double used = bean.getUsage().getUsed();
+ return (used <= CACHE_USAGE_COEF * maxSize) &&
+ (used + size <= (CACHE_USAGE_COEF + 0.02d) * maxSize);
}
protected void runTest() {
@@ -106,8 +100,12 @@
lots of small allocations takes too much time, so, just a small
optimization */
try {
- for (int coef = 1000000; coef > 0; coef /= 10) {
- fillWithSize(coef * minAllocationUnit, blobs, bean);
+ for (long size = 100_000 * minAllocationUnit; size > 0; size /= 10) {
+ long blob = 0;
+ while (canAllocate(size, maxSize, bean) &&
+ (blob = CodeCacheUtils.WB.allocateCodeBlob(size, btype.id)) != 0) {
+ blobs.add(blob);
+ }
}
Asserts.assertGT((double) bean.getUsage().getUsed(),
CACHE_USAGE_COEF * maxSize, String.format("Unable to fill "
--- a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java Thu Nov 16 10:45:42 2017 -0800
@@ -224,8 +224,8 @@
return CTVM.getLocalVariableTableStart((HotSpotResolvedJavaMethodImpl)method);
}
- public static void setNotInlineableOrCompileable(HotSpotResolvedJavaMethod method) {
- CTVM.setNotInlineableOrCompileable((HotSpotResolvedJavaMethodImpl)method);
+ public static void setNotInlinableOrCompilable(HotSpotResolvedJavaMethod method) {
+ CTVM.setNotInlinableOrCompilable((HotSpotResolvedJavaMethodImpl)method);
}
public static void reprofile(HotSpotResolvedJavaMethod method) {
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -71,10 +71,10 @@
boolean hasNeverInlineDirective = CompilerToVMHelper.hasNeverInlineDirective(method);
Asserts.assertFalse(hasNeverInlineDirective, "Unexpected initial " +
"value of property 'hasNeverInlineDirective'");
- CompilerToVMHelper.setNotInlineableOrCompileable(method);
+ CompilerToVMHelper.setNotInlinableOrCompilable(method);
hasNeverInlineDirective = CompilerToVMHelper.hasNeverInlineDirective(method);
Asserts.assertTrue(hasNeverInlineDirective, aMethod
- + " : hasNeverInlineDirective is false even after setNotInlineableOrCompileable'");
+ + " : hasNeverInlineDirective is false even after setNotInlinableOrCompilable'");
}
private static List<Executable> createTestCases() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/linkage/OSRWithBadOperandStack.jasm Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017, 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.
+ *
+ */
+
+public class compiler/linkage/OSRWithBadOperandStack version 52:0 {
+ public static Method m1:"()I" stack 1 locals 0 {
+ iconst_0;
+ ireturn;
+ }
+
+ public static Method m2:"(Ljava/lang/Object;)V" stack 1 locals 1 {
+ return;
+ }
+
+ public static Method test:"()V" stack 2 locals 1 {
+ iconst_0;
+ istore_0;
+ Loop: stack_frame_type append;
+ locals_map int;
+ iload_0;
+ // This should fail with "java.lang.VerifyError: Bad type on operand stack Exception"
+ // because m1 returns an integer and m2 takes an Object.
+ invokestatic Method compiler/linkage/OSRWithBadOperandStack."m1":"()I";
+ invokestatic Method compiler/linkage/OSRWithBadOperandStack."m2":"(Ljava/lang/Object;)V";
+ iinc 0, 1;
+ ldc 100000;
+ if_icmple Loop;
+ return;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/linkage/TestLinkageErrorInGenerateOopMap.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @bug 8190797
+ * @summary Test OSR compilation with bad operand stack.
+ * @library /test/lib /
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * @compile OSRWithBadOperandStack.jasm
+ * @run driver compiler.linkage.TestLinkageErrorInGenerateOopMap
+ */
+
+package compiler.linkage;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestLinkageErrorInGenerateOopMap {
+
+ public static void main(String args[]) throws Exception {
+ if (args.length == 0) {
+ // Spawn new VM instance to execute test
+ String[] flags = {"-noverify", "-XX:-TieredCompilation",
+ "-XX:CompileCommand=dontinline,compiler/linkage/OSRWithBadOperandStack.m*",
+ "compiler.linkage.TestLinkageErrorInGenerateOopMap", "run"};
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(flags);
+ OutputAnalyzer out = new OutputAnalyzer(pb.start());
+ if (out.getExitValue() != 0) {
+ // OSR compilation should exit with an error during OopMap verification
+ // because a LinkageError cannot be thrown from a compiler thread.
+ out.shouldContain("fatal error: Illegal class file encountered");
+ }
+ } else {
+ // Execute test
+ OSRWithBadOperandStack.test();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+
+/* @test
+ * @bug 8167409
+ * @run main/othervm/native -Xcomp compiler.runtime.criticalnatives.argumentcorruption.CheckLongArgs
+ */
+package compiler.runtime.criticalnatives.argumentcorruption;
+public class CheckLongArgs {
+ static {
+ System.loadLibrary("CNCheckLongArgs");
+ }
+ static native void m1(long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, byte[] result);
+ static native void m2(long a1, int[] a2, long a3, int[] a4, long a5, int[] a6, long a7, int[] a8, long a9, byte[] result);
+ public static void main(String args[]) throws Exception {
+ test();
+ }
+ private static void test() throws Exception {
+ int[] l1 = { 1111, 2222, 3333 };
+ int[] l2 = { 4444, 5555, 6666 };
+ int[] l3 = { 7777, 8888, 9999 };
+ int[] l4 = { 1010, 2020, 3030 };
+ byte[] result = { -1 };
+ m1(1111111122222222L, 3333333344444444L, 5555555566666666L, 7777777788888888L, 9999999900000000L, 1212121234343434L,
+ 5656565678787878L, 9090909012121212L, result);
+ check(result[0]);
+ result[0] = -1;
+ m2(1111111122222222L, l1, 3333333344444444L, l2, 5555555566666666L, l3, 7777777788888888L, l4, 9999999900000000L, result);
+ check(result[0]);
+ }
+ private static void check(byte result) throws Exception {
+ if (result != 2) {
+ if (result == 1) {
+ throw new Exception("critical native arguments mismatch");
+ }
+ throw new Exception("critical native lookup failed");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/libCNCheckLongArgs.c Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,30 @@
+#include "jni.h"
+JNIEXPORT void JNICALL JavaCritical_compiler_runtime_criticalnatives_argumentcorruption_CheckLongArgs_m1
+ (jlong a1, jlong a2, jlong a3, jlong a4, jlong a5, jlong a6, jlong a7, jlong a8,jint result_length,jbyte* result) {
+
+ if (a1 != 1111111122222222LL || a2 != 3333333344444444LL || a3 != 5555555566666666LL || a4 != 7777777788888888LL ||
+ a5 != 9999999900000000LL || a6 != 1212121234343434LL || a7 != 5656565678787878LL || a8 != 9090909012121212LL ||
+ result_length != 1 || result[0] != -1) {
+ result[0] = 1;
+ } else {
+ result[0] = 2;
+ }
+}
+
+JNIEXPORT void JNICALL JavaCritical_compiler_runtime_criticalnatives_argumentcorruption_CheckLongArgs_m2
+ (jlong a1, jint a2_length, jint* a2, jlong a3, jint a4_length, jint* a4, jlong a5, jint a6_length, jint* a6, jlong a7,
+ jint a8_length, jint* a8, jlong a9, jint result_length, jbyte* result) {
+ if (a1 != 1111111122222222LL || a2_length != 3 || a2[0] != 1111 || a3 != 3333333344444444LL || a4_length != 3 || a4[0] != 4444 ||
+ a5 != 5555555566666666LL || a6_length != 3 || a6[0] != 7777 || a7 != 7777777788888888LL || a8_length != 3 || a8[0] != 1010 || a9 != 9999999900000000LL ||
+ result_length != 1 || result[0] != -1) {
+ result[0] = 1;
+ } else {
+ result[0] = 2;
+ }
+}
+
+JNIEXPORT void JNICALL Java_compiler_runtime_criticalnatives_argumentcorruption_CheckLongArgs_m1
+ (JNIEnv * env, jclass jclazz, jlong a3, jlong a4, jlong a5, jlong a6, jlong a7, jlong a8, jlong a9, jlong a10, jbyteArray result) {}
+
+JNIEXPORT void JNICALL Java_compiler_runtime_criticalnatives_argumentcorruption_CheckLongArgs_m2
+ (JNIEnv * env, jclass jclazz, jlong a3, jintArray a4, jlong a5, jintArray a6, jlong a7, jintArray a8, jlong a9, jintArray a10, jlong a11, jbyteArray result) {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+
+/* @test
+ * @bug 8167408
+ * @run main/othervm/native -Xcomp compiler.runtime.criticalnatives.lookup.LookUp
+ */
+package compiler.runtime.criticalnatives.lookup;
+public class LookUp {
+ static {
+ System.loadLibrary("CNLookUp");
+ }
+ static native void m1(byte a1, long a2, char a3, int a4, float a5, double a6, byte[] result);
+ static native void m2(int a1, int[] a2, long a3, long[] a4, float a5,float[] a6, double a7, double[] a8, byte result[]);
+ public static void main(String args[]) throws Exception {
+ test();
+ }
+ private static void test() throws Exception {
+ int[] l1 = { 1111, 2222, 3333 };
+ long[] l2 = { 4444L, 5555L, 6666L };
+ float[] l3 = { 7777.0F, 8888.0F, 9999.0F };
+ double[] l4 = { 4545.0D, 5656.0D, 6767.0D };
+ byte[] result = { -1 };
+ m1((byte)0xA, 4444444455555555L, 'A', 12345678, 343434.0F, 6666666677777777.0D, result);
+ check(result[0]);
+ result[0] = -1;
+ m2(12345678, l1, 4444444455555555L, l2, 343434.0F, l3, 6666666677777777.0D, l4, result);
+ check(result[0]);
+ }
+ private static void check(byte result) throws Exception {
+ if (result != 2) {
+ if (result == 1) {
+ throw new Exception("critical native arguments mismatch");
+ }
+ throw new Exception("critical native lookup failed");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/libCNLookUp.c Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,35 @@
+#include "jni.h"
+JNIEXPORT void JNICALL JavaCritical_compiler_runtime_criticalnatives_lookup_LookUp_m1
+ (jbyte a1, jlong a2, jchar a3, jint a4, jfloat a5, jdouble a6, jint result_length, jbyte* result) {
+ jint l1 = (jint) a5;
+ jlong l2 = (jlong) a6;
+
+ if (a1 != 0xA || a2 != 4444444455555555LL || a3 != 0x41 || a4 != 12345678 || l1 != 343434 || l2 != 6666666677777777LL ||
+ result_length != 1 || result[0] != -1) {
+ result[0] = 1;
+ } else {
+ result[0] = 2;
+ }
+}
+
+JNIEXPORT void JNICALL JavaCritical_compiler_runtime_criticalnatives_lookup_LookUp_m2
+ (jint a1, jint a2_length, jint* a2, jlong a3, jint a4_length, jlong* a4, jfloat a5, jint a6_length, jfloat* a6, jdouble a7,
+ jint a8_length, jdouble* a8, jint result_length, jbyte* result) {
+ jint l1 = (jint) a5;
+ jlong l2 = (jlong) a7;
+
+ if (a1 != 12345678 || a2_length != 3 || a2[0] != 1111 || a3 != 4444444455555555LL || a4_length != 3 || a4[0] != 4444 ||
+ l1 != 343434 || a6_length != 3 || 7777 != (jint)a6[0] || l2 != 6666666677777777LL || a8_length != 3 || 4545 != (jlong)a8[0] ||
+ result_length != 1 || result[0] != -1) {
+ result[0] = 1;
+ } else {
+ result[0] = 2;
+ }
+}
+
+JNIEXPORT void JNICALL Java_compiler_runtime_criticalnatives_lookup_LookUp_m1
+ (JNIEnv * env, jclass jclazz, jbyte a3, jlong a4, jchar a5, jint a6, jfloat a7, jdouble a8, jbyteArray result) {}
+
+JNIEXPORT void JNICALL Java_compiler_runtime_criticalnatives_lookup_LookUp_m2
+ (JNIEnv * env, jclass jclazz, jint a3, jintArray a4, jlong a5, jlongArray a6, jfloat a7, jfloatArray a8, jdouble a9, jdoubleArray a10, jbyteArray result) {}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/unsafe/TestSplitIf.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8186125
+ * @summary cast before unsafe access moved in dominating null check null path causes crash
+ * @modules java.base/jdk.internal.misc:+open
+ *
+ * @run main/othervm -XX:-BackgroundCompilation TestSplitIf
+ *
+ */
+
+import jdk.internal.misc.Unsafe;
+import java.lang.reflect.Field;
+
+public class TestSplitIf {
+
+ static final jdk.internal.misc.Unsafe UNSAFE = Unsafe.getUnsafe();
+ static final long F_OFFSET;
+
+ static class A {
+ int f;
+ A(int f) {
+ this.f = f;
+ }
+ }
+
+ static {
+ try {
+ Field fField = A.class.getDeclaredField("f");
+ F_OFFSET = UNSAFE.objectFieldOffset(fField);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ static int test(A a1, A a2, boolean flag1) {
+ boolean flag2;
+ int f = 0;
+ A a = null;
+ if (flag1) {
+ flag2 = true;
+ a = a1;
+ } else {
+ flag2 = false;
+ a = a2;
+ }
+ if (flag2) {
+ f = UNSAFE.getInt(a, F_OFFSET);
+ } else {
+ f = UNSAFE.getInt(a, F_OFFSET);
+ }
+ return f;
+ }
+
+ static public void main(String[] args) {
+ A a = new A(0x42);
+ for (int i = 0; i < 20000; i++) {
+ test(a, a, (i % 2) == 0);
+ }
+ }
+
+}
--- a/test/hotspot/jtreg/gc/g1/TestGreyReclaimedHumongousObjects.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/gc/g1/TestGreyReclaimedHumongousObjects.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -23,7 +23,7 @@
/*
* @test TestGreyReclaimedHumongousObjects.java
- * @bug 8069367
+ * @bug 8069367 8185278
* @requires vm.gc.G1
* @summary Test handling of marked but unscanned reclaimed humongous objects.
* @key gc
--- a/test/hotspot/jtreg/gc/logging/TestPrintReferences.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/gc/logging/TestPrintReferences.java Thu Nov 16 10:45:42 2017 -0800
@@ -137,15 +137,21 @@
// Actual value: SoftReference(5.55) = phase1(1.85) + phase2(1.85) + phase3(1.85)
// Log value: SoftReference(5.6) = phase1(1.9) + phase2(1.9) + phase3(1.9)
// When checked: 5.6 < 5.7 (sum of phase1~3)
- public static boolean approximatelyEqual(BigDecimal phaseTime, BigDecimal sumOfSubPhasesTime, BigDecimal tolerance) {
- BigDecimal abs = phaseTime.subtract(sumOfSubPhasesTime).abs();
-
- int result = abs.compareTo(tolerance);
+ // Because of this we need method to verify that our measurements and calculations are valid.
+ public static boolean greaterThanOrApproximatelyEqual(BigDecimal phaseTime, BigDecimal sumOfSubPhasesTime, BigDecimal tolerance) {
+ if (phaseTime.compareTo(sumOfSubPhasesTime) >= 0) {
+ // phaseTime is greater than or equal.
+ return true;
+ }
- // result == -1, abs is less than tolerance.
- // result == 0, abs is equal to tolerance.
- // result == 1, abs is greater than tolerance.
- return (result != 1);
+ BigDecimal diff = sumOfSubPhasesTime.subtract(phaseTime);
+ if (diff.compareTo(tolerance) <= 0) {
+ // Difference is within tolerance, so approximately equal.
+ return true;
+ }
+
+ // sumOfSubPhasesTime is greater than phaseTime and not within tolerance.
+ return false;
}
public static BigDecimal checkPhaseTime(String refType) {
@@ -160,7 +166,7 @@
// If there are 3 sub-phases, we should allow 0.1 tolerance.
final BigDecimal toleranceFor3SubPhases = BigDecimal.valueOf(0.1);
- if (!approximatelyEqual(phaseTime, sumOfSubPhasesTime, toleranceFor3SubPhases)) {
+ if (!greaterThanOrApproximatelyEqual(phaseTime, sumOfSubPhasesTime, toleranceFor3SubPhases)) {
throw new RuntimeException(refType +" time(" + phaseTime +
"ms) is less than the sum(" + sumOfSubPhasesTime + "ms) of each phases");
}
@@ -181,7 +187,7 @@
// If there are 4 sub-phases, we should allow 0.2 tolerance.
final BigDecimal toleranceFor4SubPhases = BigDecimal.valueOf(0.2);
- if (!approximatelyEqual(refProcTime, sumOfSubPhasesTime, toleranceFor4SubPhases)) {
+ if (!greaterThanOrApproximatelyEqual(refProcTime, sumOfSubPhasesTime, toleranceFor4SubPhases)) {
throw new RuntimeException("Reference Processing time(" + refProcTime + "ms) is less than the sum("
+ sumOfSubPhasesTime + "ms) of each phases");
}
--- a/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGC.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGC.java Thu Nov 16 10:45:42 2017 -0800
@@ -103,6 +103,8 @@
}
public class TestSystemGC {
+ private static long endTime;
+
private static final int numGroups = 7;
private static final int numGCsPerGroup = 4;
@@ -133,8 +135,11 @@
for (int i = 0; i < numGroups; i++) {
for (int j = 0; j < numGCsPerGroup; j++) {
- System.gc();
- ThreadUtils.sleep(getDelayMS(i));
+ System.gc();
+ if (System.currentTimeMillis() >= endTime) {
+ return;
+ }
+ ThreadUtils.sleep(getDelayMS(i));
}
}
}
@@ -159,7 +164,7 @@
}
private static void runAllPhases() {
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < 4 && System.currentTimeMillis() < endTime; i++) {
SystemGCTask gcTask =
(i % 2 == 1) ? createSystemGCTask(numGroups / 3) : null;
ShortLivedAllocationTask shortTask =
@@ -181,12 +186,15 @@
}
}
- public static void main(String[] args) {
+ public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ throw new IllegalArgumentException("Must specify timeout in seconds as first argument");
+ }
+ int timeout = Integer.parseInt(args[0]) * 1000;
+ System.out.println("Running with timeout of " + timeout + "ms");
+ endTime = System.currentTimeMillis() + timeout;
// First allocate the long lived objects and then run all phases.
populateLongLived();
runAllPhases();
- if (args.length > 0 && args[0].equals("long")) {
- runAllPhases();
- }
}
}
--- a/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithCMS.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithCMS.java Thu Nov 16 10:45:42 2017 -0800
@@ -24,14 +24,15 @@
/*
* @test TestSystemGCWithCMS
+ * @bug 8190703
* @key gc
* @key stress
* @requires vm.gc.ConcMarkSweep
* @summary Stress the CMS GC full GC by allocating objects of different lifetimes concurrently with System.gc().
- * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UseConcMarkSweepGC TestSystemGCWithCMS
+ * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UseConcMarkSweepGC TestSystemGCWithCMS 270
*/
public class TestSystemGCWithCMS {
- public static void main(String[] args) {
+ public static void main(String[] args) throws Exception {
TestSystemGC.main(args);
}
}
--- a/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithG1.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithG1.java Thu Nov 16 10:45:42 2017 -0800
@@ -24,14 +24,15 @@
/*
* @test TestSystemGCWithG1
+ * @bug 8190703
* @key gc
* @key stress
* @requires vm.gc.G1
* @summary Stress the G1 GC full GC by allocating objects of different lifetimes concurrently with System.gc().
- * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UseG1GC TestSystemGCWithG1
+ * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UseG1GC TestSystemGCWithG1 270
*/
public class TestSystemGCWithG1 {
- public static void main(String[] args) {
+ public static void main(String[] args) throws Exception {
TestSystemGC.main(args);
}
}
--- a/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithParallel.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithParallel.java Thu Nov 16 10:45:42 2017 -0800
@@ -24,14 +24,15 @@
/*
* @test TestSystemGCWithParallel
+ * @bug 8190703
* @key gc
* @key stress
* @requires vm.gc.Parallel
* @summary Stress the Parallel GC full GC by allocating objects of different lifetimes concurrently with System.gc().
- * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UseParallelGC TestSystemGCWithParallel
+ * @run main/othervm/timeout=300 -Xlog:gc=info -Xmx512m -XX:+UseParallelGC TestSystemGCWithParallel 270
*/
public class TestSystemGCWithParallel {
- public static void main(String[] args) {
+ public static void main(String[] args) throws Exception {
TestSystemGC.main(args);
}
}
--- a/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithSerial.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithSerial.java Thu Nov 16 10:45:42 2017 -0800
@@ -24,14 +24,15 @@
/*
* @test TestSystemGCWithSerial
+ * @bug 8190703
* @key gc
* @key stress
* @requires vm.gc.Serial
* @summary Stress the Serial GC full GC by allocating objects of different lifetimes concurrently with System.gc().
- * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UseSerialGC TestSystemGCWithSerial
+ * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UseSerialGC TestSystemGCWithSerial 270
*/
public class TestSystemGCWithSerial {
- public static void main(String[] args) {
+ public static void main(String[] args) throws Exception {
TestSystemGC.main(args);
}
}
--- a/test/hotspot/jtreg/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java Thu Nov 16 10:45:42 2017 -0800
@@ -216,6 +216,9 @@
case "CMSPrecleanDenominator":
option.addPrepend("-XX:CMSPrecleanNumerator=" + ((new Integer(option.getMin())) - 1));
break;
+ case "G1RefProcDrainInterval":
+ option.addPrepend("-XX:+ExplicitGCInvokesConcurrent");
+ break;
case "InitialTenuringThreshold":
option.addPrepend("-XX:MaxTenuringThreshold=" + option.getMax());
break;
--- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java Thu Nov 16 10:45:42 2017 -0800
@@ -91,5 +91,6 @@
public static void main(String[] args) throws Throwable {
testDeprecated(DEPRECATED_OPTIONS); // Make sure that each deprecated option is mentioned in the output.
testDeprecatedDiagnostic("UnsyncloadClass", "false");
+ testDeprecatedDiagnostic("IgnoreUnverifiableClassesDuringDump", "false");
}
}
--- a/test/hotspot/jtreg/runtime/CommandLine/VMOptionWarning.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/runtime/CommandLine/VMOptionWarning.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,9 +36,9 @@
public class VMOptionWarning {
public static void main(String[] args) throws Exception {
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+PredictedLoadedClassCount", "-version");
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+AlwaysSafeConstructors", "-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldContain("Error: VM option 'PredictedLoadedClassCount' is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions.");
+ output.shouldContain("Error: VM option 'AlwaysSafeConstructors' is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions.");
if (Platform.isDebugBuild()) {
System.out.println("Skip the rest of the tests on debug builds since diagnostic, develop, and notproduct options are available on debug builds.");
--- a/test/hotspot/jtreg/runtime/ErrorHandling/TestOnError.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/TestOnError.java Thu Nov 16 10:45:42 2017 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -44,7 +44,6 @@
String msg = "Test Succeeded";
- // Execute the VM so that a
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:-TransmitErrorReport",
"-XX:-CreateCoredumpOnCrash",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/LoadClass/TestResize.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @bug 8184765
+ * @summary make sure the SystemDictionary gets resized when load factor is too high
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * @compile TriggerResize.java
+ * @run driver TestResize
+ */
+
+import java.lang.ProcessBuilder;
+import java.lang.Process;
+import jdk.test.lib.process.ProcessTools;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.Scanner;
+
+public class TestResize {
+
+ static double MAX_LOAD_FACTOR = 5.0; // see _resize_load_trigger in dictionary.cpp
+
+ static int getInt(String string) {
+ int start = 0;
+ for (int i = 0; i < string.length(); i++) {
+ if (!Character.isDigit(string.charAt(i))) {
+ start++;
+ } else {
+ break;
+ }
+ }
+ int end = start;
+ for (int i = end; i < string.length(); i++) {
+ if (Character.isDigit(string.charAt(i))) {
+ end++;
+ } else {
+ break;
+ }
+ }
+ return Integer.parseInt(string.substring(start, end));
+ }
+
+ static void analyzeOutputOn(ProcessBuilder pb) throws Exception {
+ pb.redirectErrorStream(true);
+ Process process = pb.start();
+ BufferedReader rd = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ String line = rd.readLine();
+ while (line != null) {
+ if (line.startsWith("Java dictionary (")) {
+ // ex. "Java dictionary (table_size=107, classes=6)"
+ // ex. "Java dictionary (table_size=20201, classes=50002)"
+ Scanner scanner = new Scanner(line);
+ scanner.next();
+ scanner.next();
+ int table_size = getInt(scanner.next());
+ int classes = getInt(scanner.next());
+ scanner.close();
+
+ double loadFactor = (double)classes / (double)table_size;
+ if (loadFactor > MAX_LOAD_FACTOR) {
+ throw new RuntimeException("Load factor too high, expected MAX "+MAX_LOAD_FACTOR+", got "+loadFactor);
+ } else {
+ System.out.println("PASS table_size:"+table_size+", classes:"+classes+" OK");
+ }
+ }
+ line = rd.readLine();
+ }
+ int retval = process.waitFor();
+ if (retval != 0) {
+ throw new RuntimeException("Error: test returned non-zero value");
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+PrintSystemDictionaryAtExit",
+ "TriggerResize",
+ "50000");
+ analyzeOutputOn(pb);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/LoadClass/TriggerResize.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+import java.lang.ClassLoader;
+
+public class TriggerResize extends ClassLoader
+{
+ static private int[] DATA = // bytes for "class TestCase00000 {}"
+ {
+ -54, -2, -70, -66, 0, 0, 0, 52, 0, 13, // 0
+ 10, 0, 3, 0, 10, 7, 0, 11, 7, 0, // 10
+ 12, 1, 0, 6, 60, 105, 110, 105, 116, 62, // 20
+ 1, 0, 3, 40, 41, 86, 1, 0, 4, 67, // 30
+ 111, 100, 101, 1, 0, 15, 76, 105, 110, 101, // 40
+ 78, 117, 109, 98, 101, 114, 84, 97, 98, 108, // 50
+ 101, 1, 0, 10, 83, 111, 117, 114, 99, 101, // 60
+ 70, 105, 108, 101, 1, 0, 18, 84, 101, 115, // 70
+ 116, 67, 97, 115, 101, 48, 48, 48, 48, 48, // 80
+ 46, 106, 97, 118, 97, 12, 0, 4, 0, 5, // 90
+ 1, 0, 13, 84, 101, 115, 116, 67, 97, 115, // 100
+ 101, 48, 48, 48, 48, 48, 1, 0, 16, 106, // 110
+ 97, 118, 97, 47, 108, 97, 110, 103, 47, 79, // 120
+ 98, 106, 101, 99, 116, 0, 32, 0, 2, 0, // 130
+ 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, // 140
+ 4, 0, 5, 0, 1, 0, 6, 0, 0, 0, // 150
+ 29, 0, 1, 0, 1, 0, 0, 0, 5, 42, // 160
+ -73, 0, 1, -79, 0, 0, 0, 1, 0, 7, // 170
+ 0, 0, 0, 6, 0, 1, 0, 0, 0, 1, // 180
+ 0, 1, 0, 8, 0, 0, 0, 2, 0, 9 // 190
+ };
+
+ static private int INDEX1 = 85;
+ static private int INDEX2 = 111;
+ static private int BASE = 48;
+
+ public TriggerResize()
+ {
+ super();
+ }
+
+ public void load(int index)
+ {
+ byte[] bytes = new byte[TriggerResize.DATA.length];
+ for (int i=0; i<bytes.length; i++)
+ {
+ bytes[i] = (byte)TriggerResize.DATA[i];
+ }
+
+ // replace id "00000" in TestCase00000 to generate new class on the fly
+ {
+ int byte1 = index % 10;
+ int byte2 = index / 10 % 10;
+ int byte3 = index / 100 % 10;
+ int byte4 = index / 1000 % 10;
+ int byte5 = index / 10000 % 10;
+
+ bytes[INDEX1+0] = bytes[INDEX2+0] = (byte)(BASE+byte5);
+ bytes[INDEX1+1] = bytes[INDEX2+1] = (byte)(BASE+byte4);
+ bytes[INDEX1+2] = bytes[INDEX2+2] = (byte)(BASE+byte3);
+ bytes[INDEX1+3] = bytes[INDEX2+3] = (byte)(BASE+byte2);
+ bytes[INDEX1+4] = bytes[INDEX2+4] = (byte)(BASE+byte1);
+ }
+
+ Class generatedClass = defineClass(bytes, 0, bytes.length);
+ resolveClass(generatedClass);
+ }
+
+ public static void main(String args[]) throws Exception
+ {
+ int count = 0;
+ if (args.length >= 1) {
+ Integer i = new Integer(args[0]);
+ count = i.intValue();
+ }
+
+ TriggerResize test = new TriggerResize();
+ for (int i = 0; i <= count; i++)
+ {
+ test.load(i);
+ }
+
+ // trigger safepoint to resize the SystemDictionary if needed
+ System.gc();
+ }
+}
--- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java Thu Nov 16 10:45:42 2017 -0800
@@ -23,7 +23,6 @@
package sun.hotspot.tools.ctw;
-
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
@@ -67,8 +66,7 @@
for (String c : Utils.classNameToFileName(classname).split("/")) {
path = path.resolve(c);
}
- if (!path.toFile()
- .exists()) {
+ if (!Files.exists(path)) {
return null;
}
try {
--- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java Thu Nov 16 10:45:42 2017 -0800
@@ -24,7 +24,6 @@
package sun.hotspot.tools.ctw;
import java.io.IOException;
-import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
--- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJimageEntry.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJimageEntry.java Thu Nov 16 10:45:42 2017 -0800
@@ -23,14 +23,13 @@
package sun.hotspot.tools.ctw;
+import jdk.internal.jimage.ImageLocation;
import jdk.internal.jimage.ImageReader;
-import jdk.internal.jimage.ImageLocation;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
-import java.util.concurrent.Executor;
import java.util.stream.Stream;
/**
--- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java Thu Nov 16 10:45:42 2017 -0800
@@ -23,9 +23,10 @@
package sun.hotspot.tools.ctw;
+import java.io.IOException;
+import java.io.PrintStream;
import java.lang.management.ManagementFactory;
-import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -39,20 +40,23 @@
static PrintStream OUT = System.out;
static final PrintStream ERR = System.err;
/**
- * Entry point. Compiles classes in {@code paths}
+ * Entry point. Compiles classes in {@code targets}
*
- * @param paths paths to jar/zip, dir contains classes, or to .lst file
- * contains list of classes to compile
+ * @param targets each element can be either
+ * 'modules:<comma separated list of modules to compile>'
+ * or path to jimage file
+ * or path to jar/zip, dir contains classes
+ * or path to .lst file contains list of classes to compile
*/
- public static void main(String[] paths) {
- if (paths.length == 0) {
- throw new IllegalArgumentException("Expect a path to a compile target.");
+ public static void main(String[] targets) {
+ if (targets.length == 0) {
+ throw new IllegalArgumentException("Expect a compile target.");
}
String logfile = Utils.LOG_FILE;
PrintStream os = null;
if (logfile != null) {
try {
- os = new PrintStream(Files.newOutputStream(Paths.get(logfile)));
+ os = new PrintStream(Files.newOutputStream(Paths.get(logfile)), true);
} catch (IOException io) {
}
}
@@ -74,7 +78,7 @@
ExecutorService executor = createExecutor();
long start = System.currentTimeMillis();
try {
- Arrays.stream(paths)
+ Arrays.stream(targets)
.map(PathHandler::create)
.flatMap(List::stream)
.forEach(p -> {
@@ -87,10 +91,10 @@
} finally {
await(executor);
}
- CompileTheWorld.OUT.printf("Done (%d classes, %d methods, %d ms)%n",
+ CompileTheWorld.OUT.println(String.format("Done (%d classes, %d methods, %d ms)",
PathHandler.getProcessedClassCount(),
Compiler.getMethodCount(),
- System.currentTimeMillis() - start);
+ System.currentTimeMillis() - start));
passed = true;
} catch (Throwable t){
t.printStackTrace(ERR);
--- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java Thu Nov 16 10:45:42 2017 -0800
@@ -100,8 +100,8 @@
}
}
} catch (Throwable t) {
- CompileTheWorld.OUT.printf("[%d]\t%s\tWARNING preloading failed : %s%n",
- id, className, t);
+ CompileTheWorld.OUT.println(String.format("[%d]\t%s\tWARNING preloading failed : %s",
+ id, className, t));
t.printStackTrace(CompileTheWorld.ERR);
}
}
@@ -113,8 +113,8 @@
try {
WHITE_BOX.enqueueInitializerForCompilation(aClass, i);
} catch (Throwable t) {
- CompileTheWorld.OUT.printf("[%d]\t%s::<clinit>\tERROR at level %d : %s%n",
- id, aClass.getName(), i, t);
+ CompileTheWorld.OUT.println(String.format("[%d]\t%s::<clinit>\tERROR at level %d : %s",
+ id, aClass.getName(), i, t));
t.printStackTrace(CompileTheWorld.ERR);
}
}
--- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java Thu Nov 16 10:45:42 2017 -0800
@@ -35,8 +35,6 @@
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.regex.Pattern;
@@ -62,19 +60,27 @@
}
private final List<Throwable> errors;
+ private final String target;
private final Path targetPath;
private final String targetName;
private CtwRunner(String target) {
- if (target.equals("modules")) {
+ if (target.startsWith("modules")) {
targetPath = Paths
.get(Utils.TEST_JDK)
.resolve("lib")
- .resolve(target);
+ .resolve("modules");
+ if (target.equals("modules")){
+ target = targetPath.toString();
+ }
+ targetName = target.replace(':', '_')
+ .replace('.', '_')
+ .replace(',', '_');
} else {
targetPath = Paths.get(target).toAbsolutePath();
+ targetName = targetPath.getFileName().toString();
}
- targetName = targetPath.getFileName().toString();
+ this.target = target;
errors = new ArrayList<>();
}
@@ -104,7 +110,7 @@
long classStart = 0L;
long classCount = classCount();
Asserts.assertGreaterThan(classCount, 0L,
- targetPath + " does not have any classes");
+ target + "(at " + targetPath + ") does not have any classes");
boolean done = false;
while (!done) {
String[] cmd = cmd(classStart);
@@ -138,7 +144,7 @@
+ "] != classCount[" + classCount + "]"));
} else {
System.out.println("Executed CTW for all " + classCount
- + " classes in " + targetPath);
+ + " classes in " + target + "(at " + targetPath + ")");
}
done = true;
} else {
@@ -162,7 +168,7 @@
}
private long classCount() {
- List<PathHandler> phs = PathHandler.create(targetPath.toString());
+ List<PathHandler> phs = PathHandler.create(target);
long result = phs.stream()
.mapToLong(PathHandler::classCount)
.sum();
@@ -215,7 +221,7 @@
"-XX:CompileCommand=exclude,java/lang/invoke/MethodHandle.*",
// CTW entry point
CompileTheWorld.class.getName(),
- targetPath.toString(),
+ target,
};
}
--- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java Thu Nov 16 10:45:42 2017 -0800
@@ -24,9 +24,12 @@
package sun.hotspot.tools.ctw;
import java.io.Closeable;
+import java.net.URI;
+import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -35,6 +38,7 @@
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
@@ -121,6 +125,15 @@
path = matcher.group(1);
path = path.isEmpty() ? "." : path;
return ClassPathJarInDirEntry.create(Paths.get(path));
+ } else if (path.startsWith("modules:")) {
+ Path modules = FileSystems.getFileSystem(URI.create("jrt:/"))
+ .getPath("modules");
+ return Arrays.stream(path.substring("modules:".length())
+ .split(","))
+ .map(modules::resolve)
+ .map(ClassPathDirEntry::new)
+ .map(PathHandler::new)
+ .collect(Collectors.toList());
} else {
path = path.isEmpty() ? "." : path;
Path p = Paths.get(path);
@@ -180,7 +193,9 @@
*/
public final void process(Executor executor) {
CompileTheWorld.OUT.println(entry.description());
- entry.classes().forEach(s -> processClass(s, executor));
+ entry.classes()
+ .distinct()
+ .forEach(s -> processClass(s, executor));
}
/**
@@ -209,12 +224,12 @@
Class<?> aClass;
Thread.currentThread().setContextClassLoader(entry.loader());
try {
- CompileTheWorld.OUT.printf("[%d]\t%s%n", id, name);
+ CompileTheWorld.OUT.println(String.format("[%d]\t%s", id, name));
aClass = entry.loader().loadClass(name);
Compiler.compileClass(aClass, id, executor);
} catch (Throwable e) {
- CompileTheWorld.OUT.printf("[%d]\t%s\tWARNING skipped: %s%n",
- id, name, e);
+ CompileTheWorld.OUT.println(String.format("[%d]\t%s\tWARNING skipped: %s",
+ id, name, e));
e.printStackTrace(CompileTheWorld.ERR);
}
}
--- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java Thu Nov 16 10:45:42 2017 -0800
@@ -193,10 +193,11 @@
* @param filename tested filename
*/
public static boolean isClassFile(String filename) {
- // If the filename has a period after removing '.class', it's not valid class file
return endsWithIgnoreCase(filename, CLASSFILE_EXT)
- && (filename.indexOf('.')
- == (filename.length() - CLASSFILE_EXT.length()));
+ // skip all module-info.class files
+ && !(filename.substring(filename.lastIndexOf('/') + 1,
+ filename.lastIndexOf('.'))
+ .equals("module-info"));
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/ClassSpecializerTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/* @test
+ * @summary Smoke-test class specializer, used to create BoundMethodHandle classes
+ * @compile/module=java.base java/lang/invoke/ClassSpecializerHelper.java
+ * @run testng/othervm/timeout=250 -ea -esa ClassSpecializerTest
+ */
+
+// Useful diagnostics to try:
+// -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true
+// -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true
+
+
+import org.testng.annotations.*;
+import java.lang.invoke.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static java.lang.invoke.ClassSpecializerHelper.*;
+
+
+public class ClassSpecializerTest {
+ @Test
+ public void testFindSpecies() throws Throwable {
+ System.out.println("testFindSpecies");
+ System.out.println("test = " + SPEC_TEST);
+ ArrayList<Object> args = new ArrayList<>();
+ for (int key = 0; key <= Kind.MAX_KEY; key++) {
+ Kind k = SpecTest.kind(key);
+ System.out.println("k = " + k);
+ MethodHandle mh = k.factory();
+ System.out.println("k.f = " + mh);
+ args.clear();
+ for (Class<?> pt : mh.type().parameterList()) {
+ args.add(coughUpA(pt));
+ }
+ args.set(0, key * 1000 + 42);
+ Frob f = (Frob) mh.invokeWithArguments(args.toArray());
+ assert(f.kind() == k);
+ System.out.println("k.f(...) = " + f.toString());
+ List<Object> l = f.asList();
+ System.out.println("f.l = " + l);
+ args.subList(0,1).clear(); // drop label
+ assert(args.equals(l));
+ }
+ }
+ private static Object coughUpA(Class<?> pt) throws Throwable {
+ if (pt == String.class) return "foo";
+ if (pt.isArray()) return java.lang.reflect.Array.newInstance(pt.getComponentType(), 2);
+ if (pt == Integer.class) return 42;
+ if (pt == Double.class) return 3.14;
+ if (pt.isAssignableFrom(List.class))
+ return Arrays.asList("hello", "world", "from", pt.getSimpleName());
+ return MethodHandles.zero(pt).invoke();
+ }
+ public static void main(String... av) throws Throwable {
+ System.out.println("TEST: ClassSpecializerTest");
+ new ClassSpecializerTest().testFindSpecies();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/java.base/java/lang/invoke/ClassSpecializerHelper.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2017, 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 java.lang.invoke;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+
+/**
+ * Helper class, injected into java.lang.invoke,
+ * that bridges to the private ClassSpecializer mechanism.
+ */
+
+public interface ClassSpecializerHelper {
+ interface Frob {
+ Kind kind();
+ int label();
+ List<Object> asList();
+ }
+ abstract class FrobImpl implements Frob {
+ private final int label;
+ public FrobImpl(int label) {
+ this.label = label;
+ }
+ public int label() { return label; }
+ @Override public abstract Kind kind();
+
+ public String toString() {
+ final StringBuilder buf = new StringBuilder();
+ buf.append("Frob[label=").append(label);
+ final Kind k = kind();
+ if (k != null) {
+ for (MethodHandle mh : k.getters()) {
+ Object x = "?";
+ try {
+ x = mh.invoke(this);
+ } catch (Throwable ex) {
+ x = "<<"+ex.getMessage()+">>";
+ }
+ buf.append(", ").append(x);
+ }
+ }
+ buf.append("]");
+ return buf.toString();
+ }
+
+ public List<Object> asList() {
+ final List<MethodHandle> getters = kind().getters();
+ ArrayList<Object> res = new ArrayList<>(getters.size());
+ for (MethodHandle getter : getters) {
+ try {
+ res.add(getter.invoke(this));
+ } catch (Throwable ex) {
+ throw new AssertionError(ex);
+ }
+ }
+ return res;
+ }
+ }
+
+ public static class Kind extends ClassSpecializer<Frob, Byte, Kind>.SpeciesData {
+ public Kind(SpecTest outer, Byte key) {
+ outer.super(key);
+ }
+
+ public MethodHandle factory() {
+ return super.factory();
+ }
+
+ public List<MethodHandle> getters() {
+ return super.getters();
+ }
+
+ private static final List<Class<?>> FIELD_TYPES
+ = Arrays.asList(String.class, float.class, Double.class, boolean.class, Object[].class, Object.class);
+
+ public static int MAX_KEY = FIELD_TYPES.size();
+
+ @Override
+ protected List<Class<?>> deriveFieldTypes(Byte key) {
+ return FIELD_TYPES.subList(0, key);
+ }
+
+ @Override
+ protected Class<? extends Frob> deriveSuperClass() {
+ return FrobImpl.class;
+ }
+
+ @Override
+ protected MethodHandle deriveTransformHelper(MemberName transform, int whichtm) {
+ throw new AssertionError();
+ }
+
+ @Override
+ protected <X> List<X> deriveTransformHelperArguments(MemberName transform, int whichtm, List<X> args, List<X> fields) {
+ throw new AssertionError();
+ }
+ }
+
+ class SpecTest extends ClassSpecializer<Frob, Byte, Kind> {
+ private static final MemberName SPECIES_DATA_ACCESSOR;
+ static {
+ try {
+ SPECIES_DATA_ACCESSOR = MethodHandles.publicLookup()
+ .resolveOrFail(REF_invokeVirtual, FrobImpl.class, "kind", MethodType.methodType(Kind.class));
+ } catch (ReflectiveOperationException ex) {
+ throw new AssertionError("Bootstrap link error", ex);
+ }
+ }
+
+ public SpecTest() {
+ super(Frob.class, Byte.class, Kind.class,
+ MethodType.methodType(void.class, int.class),
+ SPECIES_DATA_ACCESSOR,
+ "KIND",
+ Arrays.asList());
+ }
+
+ @Override
+ protected Kind newSpeciesData(Byte key) {
+ return new Kind(this, key);
+ }
+
+ public static Kind kind(int key) {
+ return (Kind) SPEC_TEST.findSpecies((byte)key);
+ }
+ }
+
+ static final SpecTest SPEC_TEST = new SpecTest();
+
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/management/RuntimeMXBean/ProcessIdTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @bug 8044122
+ * @summary check the correctness of process ID returned by RuntimeMXBean.getPid()
+ * @run main ProcessIdTest
+ */
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.lang.ProcessHandle;
+
+public class ProcessIdTest {
+ public static void main(String args[]) {
+ RuntimeMXBean mbean = ManagementFactory.getRuntimeMXBean();
+ long mbeanPid = mbean.getPid();
+ long pid = ProcessHandle.current().pid();
+ long pid1 = Long.parseLong(mbean.getName().split("@")[0]);
+ if(mbeanPid != pid || mbeanPid != pid1) {
+ throw new RuntimeException("Incorrect process ID returned");
+ }
+
+ System.out.println("Test Passed");
+ }
+
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/util/stream/CustomFJPoolTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @summary Tests stream execution in a custom ForkJoinPool
+ * @bug 8190974
+ * @run testng/othervm CustomFJPoolTest
+ * @run testng/othervm -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 CustomFJPoolTest
+ */
+
+import org.testng.annotations.Test;
+
+import java.util.Comparator;
+import java.util.Spliterator;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+@Test
+public class CustomFJPoolTest {
+
+ // A Spliterator that counts the number of spliterators created
+ // including itself, thus the count starts at 1
+ static class SplitCountingSpliterator<T> implements Spliterator<T> {
+ final Spliterator<T> s;
+ final AtomicInteger nsplits;
+
+ // Top-level constructor
+ public SplitCountingSpliterator(Spliterator<T> s) {
+ this.s = s;
+ nsplits = new AtomicInteger(1);
+ }
+
+ // Splitting constructor
+ SplitCountingSpliterator(Spliterator<T> s, AtomicInteger nsplits) {
+ this.s = s;
+ this.nsplits = nsplits;
+ }
+
+ int splits() {
+ return nsplits.get();
+ }
+
+ @Override
+
+ public boolean tryAdvance(Consumer<? super T> action) {
+ return s.tryAdvance(action);
+ }
+
+ @Override
+ public void forEachRemaining(Consumer<? super T> action) {
+ s.forEachRemaining(action);
+ }
+
+ @Override
+ public Spliterator<T> trySplit() {
+ var split = s.trySplit();
+ if (split != null) {
+ nsplits.incrementAndGet();
+ return new SplitCountingSpliterator<>(split, nsplits);
+ }
+ else {
+ return null;
+ }
+ }
+
+ @Override
+ public long estimateSize() {
+ return s.estimateSize();
+ }
+
+ @Override
+ public long getExactSizeIfKnown() {
+ return s.getExactSizeIfKnown();
+ }
+
+ @Override
+ public int characteristics() {
+ return s.characteristics();
+ }
+
+ @Override
+ public boolean hasCharacteristics(int characteristics) {
+ return s.hasCharacteristics(characteristics);
+ }
+
+ @Override
+ public Comparator<? super T> getComparator() {
+ return s.getComparator();
+ }
+ }
+
+ public void testCustomPools() throws Exception {
+ int splitsForP1 = countSplits(new ForkJoinPool(1));
+ int splitsForP2 = countSplits(new ForkJoinPool(2));
+ assertEquals(splitsForP2, splitsForP1 * 2);
+
+ int commonParallelism = ForkJoinPool.getCommonPoolParallelism();
+ if (commonParallelism > 1 && commonParallelism < 128) {
+ int splitsForPHalfC = countSplits(new ForkJoinPool(commonParallelism / 2));
+ int splitsForPC = countSplits(ForkJoinPool.commonPool());
+
+ assertTrue(splitsForPHalfC < splitsForPC);
+ assertEquals(splitsForPC / splitsForPHalfC,
+ nearestPowerOfTwo(commonParallelism) / nearestPowerOfTwo(commonParallelism / 2));
+ }
+ }
+
+ static int countSplits(ForkJoinPool fjp) throws Exception {
+ // The number of splits will be equivalent to the number of leaf nodes
+ // and will be a power of 2
+ var fInteger = fjp.submit(() -> {
+ var s = IntStream.range(0, 1024).boxed().parallel().spliterator();
+ var cs = new SplitCountingSpliterator<>(s);
+ StreamSupport.stream(cs, true).forEach(e -> {});
+ return cs.splits();
+ });
+ return fInteger.get();
+ }
+
+ static int nearestPowerOfTwo(int i) {
+ return (i & (i - 1)) == 0
+ ? i
+ : 1 << (32 - Integer.numberOfLeadingZeros(i));
+ }
+}
--- a/test/jdk/tools/jlink/plugins/GenerateJLIClassesPluginTest.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/jdk/tools/jlink/plugins/GenerateJLIClassesPluginTest.java Thu Nov 16 10:45:42 2017 -0800
@@ -21,6 +21,8 @@
* questions.
*/
+import java.nio.charset.Charset;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
@@ -74,11 +76,30 @@
classFilesForSpecies(GenerateJLIClassesPlugin.defaultSpecies()),
List.of());
+ // Check that --generate-jli-classes=@file works as intended
+ Path baseFile = Files.createTempFile("base", "trace");
+ String species = "LLLLLLLLLLLLLLLLLLL";
+ String fileString = "[SPECIES_RESOLVE] java.lang.invoke.BoundMethodHandle$Species_" + species + " (salvaged)\n";
+ Files.write(baseFile, fileString.getBytes(Charset.defaultCharset()));
+ result = JImageGenerator.getJLinkTask()
+ .modulePath(helper.defaultModulePath())
+ .output(helper.createNewImageDir("generate-jli-file"))
+ .option("--generate-jli-classes=@" + baseFile.toString())
+ .addMods("java.base")
+ .call();
+
+ image = result.assertSuccess();
+
+ JImageValidator.validate(
+ image.resolve("lib").resolve("modules"),
+ classFilesForSpecies(List.of(species)), // species should be in the image
+ classFilesForSpecies(List.of(species.substring(1)))); // but not it's immediate parent
}
private static List<String> classFilesForSpecies(Collection<String> species) {
return species.stream()
- .map(s -> "/java.base/java/lang/invoke/BoundMethodHandle$Species_" + s + ".class")
+ .map(s -> "/java.base/java/lang/invoke/BoundMethodHandle$Species_"
+ + GenerateJLIClassesPlugin.expandSignature(s) + ".class")
.collect(Collectors.toList());
}
}
--- a/test/jtreg-ext/requires/VMProps.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/jtreg-ext/requires/VMProps.java Thu Nov 16 10:45:42 2017 -0800
@@ -347,7 +347,6 @@
isSupported = checkDockerSupport();
} catch (Exception e) {
isSupported = false;
- System.err.println("dockerSupport() threw exception: " + e);
}
return (isSupported) ? "true" : "false";
--- a/test/langtools/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/langtools/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java Thu Nov 16 10:45:42 2017 -0800
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4934778 4777599 6553182 8146427 8146475 8175055
+ * @bug 4934778 4777599 6553182 8146427 8146475 8175055 8185371
* @summary Make sure that -help, -helpfile and -nohelp options work correctly.
* @author jamieh
* @library ../lib
@@ -161,6 +161,7 @@
"-sourcetab ",
"-keywords ",
"-stylesheetfile ",
+ "--add-stylesheet ",
"-docencoding ",
"-html4 ",
"-html5 ",
--- a/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java Thu Nov 16 10:45:42 2017 -0800
@@ -23,8 +23,9 @@
/*
* @test
- * @bug 4749567 8071982 8175200 8186332
- * @summary Test the output for -header, -footer, -nooverview, -nodeprecatedlist, -nonavbar, -notree, -stylesheetfile options.
+ * @bug 4749567 8071982 8175200 8186332 8185371
+ * @summary Test the output for -header, -footer, -nooverview, -nodeprecatedlist, -nonavbar, -notree,
+ * -stylesheetfile, --main-stylesheet, --add-stylesheet options.
* @author Bhavesh Patel
* @library ../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -118,6 +119,64 @@
}
@Test
+ void testStylesheetFileAltOption() {
+ javadoc("-d", "out-stylesheet-file",
+ "--main-stylesheet", new File(testSrc, "custom-stylesheet.css").getAbsolutePath(),
+ "-sourcepath", testSrc,
+ "pkg");
+ checkExit(Exit.OK);
+
+ checkOutput("custom-stylesheet.css", true, "Custom javadoc style sheet");
+ checkOutput("pkg/Foo.html", true, "<link rel=\"stylesheet\" type=\"text/css\" "
+ + "href=\"../custom-stylesheet.css\" title=\"Style\">");
+ }
+
+ @Test
+ void testAdditionalStylesheetFile() {
+ javadoc("-d", "out-additional-css",
+ "--add-stylesheet", new File(testSrc, "additional-stylesheet-1.css").getAbsolutePath(),
+ "--add-stylesheet", new File(testSrc, "additional-stylesheet-2.css").getAbsolutePath(),
+ "--add-stylesheet", new File(testSrc, "additional-stylesheet-3.css").getAbsolutePath(),
+ "-sourcepath", testSrc,
+ "pkg");
+ checkExit(Exit.OK);
+
+ checkOutput("additional-stylesheet-1.css", true, "Additional javadoc style sheet 1");
+ checkOutput("additional-stylesheet-2.css", true, "Additional javadoc style sheet 2");
+ checkOutput("additional-stylesheet-3.css", true, "Additional javadoc style sheet 3");
+ checkOutput("pkg/Foo.html", true,
+ "<link rel=\"stylesheet\" type=\"text/css\" href=\"../additional-stylesheet-1.css\" title=\"Style\">\n"
+ + "<link rel=\"stylesheet\" type=\"text/css\" href=\"../additional-stylesheet-2.css\" title=\"Style\">\n"
+ + "<link rel=\"stylesheet\" type=\"text/css\" href=\"../additional-stylesheet-3.css\" title=\"Style\">");
+ }
+
+ @Test
+ void testInvalidStylesheetFile() {
+ javadoc("-d", "out-invalid-css",
+ "--main-stylesheet", new File(testSrc, "custom-stylesheet-1.css").getAbsolutePath(),
+ "-sourcepath", testSrc,
+ "pkg");
+ checkExit(Exit.ERROR);
+
+ checkOutput(Output.OUT, true,
+ "javadoc: error - File not found:",
+ "custom-stylesheet-1.css");
+ }
+
+ @Test
+ void testInvalidAdditionalStylesheetFiles() {
+ javadoc("-d", "out-invalid-additional-css",
+ "--add-stylesheet", new File(testSrc, "additional-stylesheet-4.css").getAbsolutePath(),
+ "-sourcepath", testSrc,
+ "pkg");
+ checkExit(Exit.ERROR);
+
+ checkOutput(Output.OUT, true,
+ "javadoc: error - File not found:",
+ "additional-stylesheet-4.css");
+ }
+
+ @Test
void testLinkSource() {
javadoc("-d", "out-9",
"-linksource",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/additional-stylesheet-1.css Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,5 @@
+/* Additional javadoc style sheet 1 */
+
+body {
+ background-color:#f8f8ff;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/additional-stylesheet-2.css Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,5 @@
+/* Additional javadoc style sheet 2 */
+
+.subNav {
+ background-color:#fafad2;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/additional-stylesheet-3.css Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,5 @@
+/* Additional javadoc style sheet 3 */
+
+a:link, a:visited {
+ color:#8b0000;
+}
--- a/test/lib/sun/hotspot/WhiteBox.java Wed Nov 15 09:31:17 2017 -0800
+++ b/test/lib/sun/hotspot/WhiteBox.java Thu Nov 16 10:45:42 2017 -0800
@@ -525,6 +525,7 @@
public native boolean areSharedStringsIgnored();
public native boolean isCDSIncludedInVmBuild();
public native Object getResolvedReferences(Class<?> c);
+ public native boolean areOpenArchiveHeapObjectsMapped();
// Compiler Directive
public native int addCompilerDirective(String compDirect);
--- a/test/make/TestCopyFiles.gmk Wed Nov 15 09:31:17 2017 -0800
+++ b/test/make/TestCopyFiles.gmk Thu Nov 16 10:45:42 2017 -0800
@@ -44,6 +44,7 @@
DEST_DIR := $(OUTPUT_DIR)/dest
$(OUTPUT_DIR)/_src_created: $(DEPS)
+ $(RM) -r $(DEST_DIR)
$(RM) -r $(SRC_DIR)
$(MKDIR) -p $(SRC_DIR)
$(MKDIR) -p $(SRC_DIR)/foo
@@ -51,7 +52,7 @@
$(TOUCH) $(SRC_DIR)/foo/foofile
$(TOUCH) "$(SRC_DIR)/foo/foo file"
# Spaces in directories only works with gnu make 4.0 or later
- ifeq (4.0, $(firstword $(sort 4.0 $(MAKE_VERSION))))
+ ifeq (4.0dfd, $(firstword $(sort 4.0 $(MAKE_VERSION))))
$(MKDIR) -p "$(SRC_DIR)/foo bar"
$(TOUCH) "$(SRC_DIR)/foo bar/foobarfile"
$(TOUCH) "$(SRC_DIR)/foo bar/foo bar file"
@@ -65,15 +66,32 @@
FILES := $(call CacheFind, $(SRC_DIR)), \
))
+# Optionally define a rule that deletes all the target files after the makefile
+# has been parsed. GNU make has specific problems with this in combination with
+# spaces in directory names.
+ifeq ($(DELETE_FIRST), true)
+ delete-targets:
+ $(RM) -r $(DEST_DIR)
+ $(ECHO) '$(DEST_DIR)/foo' '$(wildcard $(DEST_DIR)/foo)'
+
+ $(COPY_1): delete-targets
+endif
+
do-copy1: $(COPY_1)
run-test1: $(OUTPUT_DIR)/_src_created
+ $(ECHO) "Copy 1 first time"
+$(MAKE) -f $(THIS_FILE) do-copy1
$(DIFF) -r $(SRC_DIR) $(DEST_DIR)
+ # Rerun the copy a second time, with the targets present at make parse
+ # time, but then deleted by a prerequisite rule.
+ $(ECHO) "Copy 1 second time"
+ +$(MAKE) -f $(THIS_FILE) do-copy1 DELETE_FIRST=true
+ $(DIFF) -r $(SRC_DIR) $(DEST_DIR)
TEST_TARGETS += run-test1
-.PHONY: do-copy1 run-test1
+.PHONY: do-copy1 run-test1 delete-targets
################################################################################
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nashorn/script/basic/JDK-8191306.js Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/**
+ * JDK-8191306 Math.abs corner case with optimistic typing
+ *
+ * @test
+ * @run
+ */
+
+print(Math.abs(-2147483648))
+print(Math.abs(java.lang.Integer.MIN_VALUE))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nashorn/script/basic/JDK-8191306.js.EXPECTED Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,2 @@
+2147483648
+2147483648
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nashorn/src/jdk/nashorn/api/scripting/test/JDK_8068741_Test.java Thu Nov 16 10:45:42 2017 -0800
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+package jdk.nashorn.api.scripting.test;
+
+import javax.script.ScriptEngineFactory;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @run testng jdk.nashorn.api.scripting.test.JDK_8068741_Test
+ * @bug 8068741
+ * @summary javax.script.ScriptEngineFactory.getMethodCallSyntax() spec allows null passed as an object
+ */
+public class JDK_8068741_Test {
+ @Test
+ public void testGetMethodCallSyntax() {
+ ScriptEngineFactory fac = new NashornScriptEngineFactory();
+ checkThrowsNPE(() -> fac.getMethodCallSyntax(null, "foo"));
+ checkThrowsNPE(() -> fac.getMethodCallSyntax("obj", null));
+ checkThrowsNPE(() -> fac.getMethodCallSyntax("obj", "foo", (String[])null));
+ checkThrowsNPE(() -> fac.getMethodCallSyntax("obj", "foo", null, "xyz"));
+ checkThrowsNPE(() -> fac.getMethodCallSyntax("obj", "foo", "xyz", null));
+ }
+
+ private void checkThrowsNPE(Runnable r) {
+ boolean gotNPE = false;
+ try {
+ r.run();
+ } catch (NullPointerException npe) {
+ gotNPE = true;
+ System.err.println("Got NPE as expected: " + npe);
+ }
+ Assert.assertTrue(gotNPE);
+ }
+}